![]() |
|
||||||||||
|
|||||
|
Ветеран форума
Регистрация: Jul 2006
Адрес: Грузия, Тбилиси
Сообщений: 2,675
|
Оглавление
Интеграция с ОС Контроль над мышью Получить список логических дисков Программно изменить раскладку клавиатуры Работа с реестром Запуск скринсейвера Использование функций VBS и WSH Работа с файлами Экспорт в Word Экспорт в Excel Общие вопросы Запрет на запуск второго экземпляра приложения 1 Ошибка при запуске приложения "Access violation..." Можно ли использовать {mdm}Script во внешних .swf, подгружаемых в основное приложение? Прочее Универсальная схема цинк-приложения. А нельзя ли сделать что-нибудь наподобие динамической библиотеки различных функци vbs? Связка CS3 & Zinc Последний раз редактировалось alexcon314; 20.06.2008 в 14:36. |
|
|||||
|
listener
|
Контроль над мышью
для реализации на цинке под WinXP пример выглядит примерно так // задействуем обработчик события onAppExit чтобы при выходе "восстановить" скорость мыши.
mdm.Application.enableExitHandler();
// ставим "наугад" 10, т.к. считать и запомнить бывшее значение скорости в данном примере нельзя.
// но это можно сделать при помощи своей DLL и только так.
mdm.Application.onAppExit = function() {
SetSpeed(10);
myDLL.close();
mdm.Application.exit();
};
// здесь иллюстрируем позиционирование курсора
// x1 - х-координата формы +30
x1 = mdm.Forms.thisForm.x + 30;
// y1 - y-координата формы +30
y1 = mdm.Forms.thisForm.y + 30;
for (i = 0; i <= 15; i++) {
// в цикле "перемещаем" курсор
mdm.Input.Mouse.setPosition(x1 + i * i, y1 + i * i);
// делаем паузу между перемещениями курсора 200 мс
mdm.Application.delay(200);
}
// подключаем системную DLL c:\windows\system32\user32.dll, полный
// путь для файлов DLL в этой папке указывать необязательно
myDLL = new mdm.DLL("user32.dll");
// на сцене имеем мувик mc - простой прямоугольник, например.
// задаем обработчики onRollOver и onRollOut для этого клипа.
mc.onRollOver = function() {
SetSpeed(1);
};
mc.onRollOut = function() {
SetSpeed(10);
};
// функция, изменяющая скорость мыши, v - скорость от 1 до ... не проверял, 1 -самая маленькая.
function SetSpeed(v) {
// формируем список параметров вызова API-функции из user32.dll
// оригинальный вид ее таков
//BOOL SystemParametersInfo(
// UINT uiAction, // system parameter to query or set
// UINT uiParam, // depends on action to be taken
// PVOID pvParam, // depends on action to be taken
// UINT fWinIni // user profile update flag
//);буковка А в конце названия функции ниже в примере
//означает ANSI-версию функции (W - UNICODE версию соответственно)
// здесь я вызываю ее так
//SystemParametersInfoA (SPI_SETMOUSESPEED, 0, (PVOID)1, SPIF_SENDCHANGE);
// например 113 - численное значение API-константы SPI_SETMOUSESPEED
// и т.д.
myDLL.addParameter("integer", 113);
myDLL.addParameter("integer", 0);
myDLL.addParameter("integer", v);
myDLL.addParameter("integer", 2);
// собственно, вызов функции.
myDLL.call("boolean", "SystemParametersInfoA");
// очищаем список параметров для последующих вызовов.
myDLL.clear();
}
модераторам: в это тему можно складывать удачные примеры использования цинка. |
|
|||||
|
listener
|
Использование функций VBS и WSH
Для использования многих системных функций, не имеющих реализации в цинке или реализованных с какими-то косяками, можно задействовать встроенный mdm-класс mdm.System.VBScript (как вариант mdm.System.JScript). В документации сказано, что метод mdm.System.VBScript.execute() ничего не возвращает. Однако это не так. Внимание - каждую строку тела формируемого скрипта не забываем заканчивать символом переноса строки. var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'MyFunc=\"Возвращаемое значение\"\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "", "", "", "", ""); mdm.Dialogs.prompt(Return); Польза в том, что можно использовать vb-скрипты с обратной связью, получая от них данные. Например, задействовать встроенные в vbs функции обработки строк при помощи регулярных выражений, шелльные команды, системные и сетевые функции и т.п. Возможностей тут немало, стоит посмотреть документацию по VBS и WHS. Скачать доки по скриптам http://download.microsoft.com/downlo...scrdoc56en.exe Пример 1 Получить имя компа, юзера, домена. Эти сведения будут отражать имя пользователя ЗАПУСТИВШЕГО ПРОГРАММУ. Т.е. при использовании команды "запуск от имени...", например, будут возвращены имя и домен пользователя, от чьего имени был произведен запуск. В скриптах используются COM-объекты, такие как Shell, WScript, FileSystemObject и т.д. var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'Set WshNetwork = CreateObject(\"WScript.Network\")\r'; vbCode += 'MyFunc = WshNetwork.ComputerName & vbNewLine & WshNetwork.UserName & vbNewLine & WshNetwork.UserDomain\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "", "", "", "", ""); mdm.Dialogs.prompt(Return); Замена символов в строке. (см. мануал по vb-функции Replace) var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'MyFunc = Replace(a, b, c)\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "XXpXXPXXp", "p", "_", "", ""); mdm.Dialogs.prompt(Return); Импорт текста из документа Word. В примере файл "Test line.doc" содержит несколько строк текста. var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'Set objDoc = GetObject(a)\r'; vbCode += 'objDoc.Select\r'; vbCode += 'MyFunc = objDoc.Application.Selection\r'; vbCode += 'objDoc.Application.Quit\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "C:\\Test line.doc", "", "", "", ""); mdm.Dialogs.prompt(Return); Пример 4 Регулярные выражения. В примере в передаваемой строке ищется адрес e-mail и производится его разбор. var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'Dim oRe, oMatch, oMatches\r'; vbCode += 'Set oRe = New RegExp\r'; vbCode += 'oRe.Pattern = \"(\\w+)@(\\w+)\\.(\\w+)\"\r'; vbCode += 'Set oMatches = oRe.Execute(a)\r'; vbCode += 'Set oMatch = oMatches(0)\r'; vbCode += 'retStr = \"Email address is: \" & oMatch\r'; vbCode += 'retStr = retStr & vbNewline\r'; vbCode += 'retStr = retStr & \"Email alias is: \" & oMatch.SubMatches(0)\r'; vbCode += 'retStr = retStr & vbNewline\r'; vbCode += 'retStr = retStr & \"Organization is: \" & oMatch. SubMatches(1)\r'; vbCode += 'retStr = retStr & vbNewline\r'; vbCode += 'retStr = retStr & \"Domain is: \" & oMatch. SubMatches(2)\r'; vbCode += 'MyFunc = retStr\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "Please send mail to dragon@xyzzy.com. Thanks!", "", "", "", ""); mdm.Dialogs.prompt(Return); Построчное чтение текстового файла. Аргументы вызова - полное имя файла и номер строки, которую нужно прочитать. var vbCode = 'Function GetLineTextFile(a,b,c,d,e)\r'; vbCode += 'Const ForReading = 1, ForWriting = 2\r'; vbCode += 'Dim fso, MyFile, res\r'; vbCode += 'Set fso = CreateObject(\"Scripting.FileSystemObject\")\r'; vbCode += 'Set MyFile = fso.OpenTextFile(a, ForReading)\r'; vbCode += 'For i=1 To b\r'; vbCode += 'res = MyFile.ReadLine\r'; vbCode += 'On Error Resume Next\r'; vbCode += 'If res = GetLineTextFile Then\r'; vbCode += 'res = "End line number " & CStr(i-1) & ": " & GetLineTextFile\r'; vbCode += 'GetLineTextFile = res\r'; vbCode += 'Exit Function\r'; vbCode += 'End If\r'; vbCode += 'GetLineTextFile = res\r'; vbCode += 'Next\r'; vbCode += 'MyFile.Close\r'; vbCode += 'End Function\r'; res = mdm.System.VBScript.execute(vbCode, "GetLineTextFile", "c:\\testfile.txt", 1009); mdm.Dialogs.prompt(res); В случае, если передан номер строки, больший их общего количества в файле, возвращается номер последней строки и она сама. Последний раз редактировалось alexcon314; 28.11.2007 в 22:10. |
|
|||||
|
listener
|
А нельзя ли сделать что-нибудь наподобие динамической библиотеки различных функци vbs?
var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'Set objCom = GetObject(a)\r'; vbCode += 'MyFunc = objCom.mkdir(b)\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "script:http://mdm-zinc.narod.ru/Com/fcom.wsc", "C:\\NewFolder", "", ""); mdm.Dialogs.prompt(Return); оригинальный xml здесь http://flasher.ru/forum/newreply.php...reply&p=677298 <?xml version="1.0"?> <component> <?component error="true" debug="true"?> <registration description="fcom" progid="fcom.WSC" version="1.00" classid="{fd17cd28-824d-4ddb-9980-5825cae259be}" > </registration> <public> <method name="mkdir"> <PARAMETER name="path"/> </method> </public> <script language="VBScript"> <![CDATA[ function mkdir(path) Dim fso, f Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.CreateFolder(path) mkdir = f.path end function ]]> </script> </component> Происходит динамическая подгрузка этого компонента и вызывается его метод mkdir(path), который создает папку 'path'. Проверку на "already exists" в этом примере я не делал, поэтому имя папки (в примере - NewFolder) должно быть уникальным, иначе - ошибка. Т.е. происходит что-то наподобие вызова библиотечной функции. Еще один занятный пример. Пример 7 var vbCode = 'Function MyFunc(a,b,c,d,e)\r'; vbCode += 'Set objCom = GetObject(a)\r'; vbCode += 'MyFunc = objCom.typechar(b,CDbl(c),d)\r'; vbCode += 'End Function\r'; var Return = mdm.System.VBScript.execute(vbCode, "MyFunc", "script:http://mdm-zinc.narod.ru/Com/fcom.wsc", "Hello!~It's me.", "0,3", "winword"); mdm.Dialogs.prompt(Return); Последний раз редактировалось screamge; 30.11.2007 в 22:32. |
|
|||||
|
listener
|
Получить список логических дисков
this.createTextField("driveList", 1, 20, 20, 200, 300);
driveList.text="Список логических дисков:"+ newline;
// подключаем системную DLL kernek32.dll
var kernel32 = new mdm.DLL(mdm.System.Paths.windows + "\\system32\\kernel32.dll");
//и вызываем API-функцию GetLogicalDrives из этой библиотеки.
// в оригинале она выглядит так DWORD GetLogicalDrives(VOID)
var numDrives:Number = 1 * kernel32.call("integer", "GetLogicalDrives");
// отключаем DLL
kernel32.close();
// анализируем результат
var driveLettersMask:Array = numDrives.toString(2).split("");
startChar = 65 + (driveLettersMask.length - 1);
// добавляем в список логические диски системы
for (i = driveLettersMask.length - 1; i >= 0; i--) {
if (driveLettersMask[i] == "1") {
var driveLetter:String = String.fromCharCode(startChar - i);
driveList.text += "Диск " + driveLetter + ":" + newline;
}
}
по принципу 0000000000001101 ...................DCBA 1 - соответствует наличию диска с буквой, 0 - отсутствует диск с такой буквой. В примере видно, что есть диски A, C и D. Последний раз редактировалось alexcon314; 28.11.2007 в 22:12. |
|
|||||
|
listener
|
Программно изменить раскладку клавиатуры
// подключаем системную DLL user32.dll
var user32 = new mdm.DLL(mdm.System.Paths.windows + "\\system32\\user32.dll");
// создаем текстовые поля для отображения результатов
createTextField("out1", 1, 20, 20, 200, 20);
out1.type = "dynamic";
out1.border = true;
createTextField("out2", 2, 20, 50, 200, 200);
out2.type = "input";
out2.multiline = true;
out2.border = true;
//go-это стандаотная кнопка
go.onRelease = Go;
function Go() {
// формируем список параметров вызова функции ActivateKeyboardLayout
// в оригинале она выглядит так
// HKL ActivateKeyboardLayout(
HKL hkl, // handle to keyboard layout
UINT Flags // keyboard layout flags
);
var parameter1 = user32.addParameter("integer", "1");
var parameter2 = user32.addParameter("integer", "8");
var res = user32.call("boolean", "ActivateKeyboardLayout");
out1.text = res;
user32.clear();
}
Параметры берутся из справки WIN API Еще о переключении раскладки. Вот так можно обойтись без подключения системных DLL. createTextField("test", 1, 20, 20, 200, 200);
test.type = "input";
test.border = true;
test.multiline = true;
test.wordWrap = true;
go.label = "EN";
// ищем хэндл окна
var wList = mdm.System.getWindowList();
var i = 0;
while (wList[i][0] != "form") {
i++;
}
var hwnd = wList[i][1];
// начальное значение раскладки, это численное представление того, что раскладка EN
var kblName = 0x04190419;
// go-это стандартная кнопка
go.onRelease = function() {
// ставим принудительно EN
mdm.System.postMessage(hwnd, 0x0050, 1, kblName);
switch (kblName) {
// меняем значение раскладки
// при каждом нажатии кнопки
case 0x04190419 :
kblName = 0x04090409;
go.label = "RU";
break;
case 0x04090409 :
kblName = 0x04190419;
go.label = "EN";
break;
}
};
form - Название формы приложения (form title). Окно самому себе шлет message - запрос на изменение раскладки WM_INPUTLANGCHANGEREQUEST( численное значение 0x0050) c параметром-значением раскладки. |
|
|||||
|
listener
|
Работа с реестром
C именованием методов цинка наблюдается путаница. Внесем некоторую ясность. Папки в левой панели редактора реестра regedit - разделы (или ветки 'branches'). Методы mdm.System.Registry.createKey, .getKeyNames и .deleteKey воздействуют именно на разделы. Далее, в правой панели regedit'a отображаются ключи: название, тип, значение, которые в данном разделе присутствуют. на пример var login:String = mdm.System.Registry.loadString("3", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName");
То же относится и к .saveString(), который принимает аргументами ветку, имя ключа, значение. С удалением раздела (ветки) нет проблем. Но вот с удалением ключа или его значения - непонтно. Метод deleteValue() не работает. Да и принимает он, судя по мануалу просто ветку, имя ключа туда не вставляется. Видимо, это косяк. Здесь http://www.mdmforum.com/forum/index....hl=deletevalue изложена пара достойных идей как этот косяк спрямить. В частности, осбого внимания заслуживает использование утилиты редактирования реестра из командной строки REG DELETE. var cmdExe = "REG DELETE раздел /v ключ"; var results = mdm.System.execStdOut(cmdExe); mdm.Dialogs.prompt(results); Да, еще. Методы .load() и .save() облегченный вариант всех прочих. В том смысле , что они воздействуют на определенную ветку в реестре, и ее не надо им указывать, ветка эта формируется при первом вызове .save(), точное ее местоположение огрворено в мануале: HKEY_CURRENT_USER\Software\<название формы приложения>\ . пример go.onRelease = function() {
mdm.System.Registry.save("myKey", "This is my Content");// записали в ключ 'myKey' значение 'This is my Content'
var Result = mdm.System.Registry.load("MyKey");// считали только что записанное значение
mdm.Dialogs.prompt(Result);
};
возможности vb-скрипта это позволяют. А вот так можно получить имя текущего пользователя и домена на WinXP var login:String = mdm.System.Registry.loadString("3", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName");
var domain:String = mdm.System.Registry.loadString("3", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName");
// for winXP registry
Для корректной работы лучше использовать WSH-скрипт. См. выше примеры. Последний раз редактировалось alexcon314; 28.11.2007 в 22:21. |
|
|||||
|
listener
|
Экспорт в Word
пример работы с VBScript. В системе должен быть установлен Word, чтобы все работало. //каждую строку тела формируемого скрипта не забываем заканчивать
//символом переноса строки.
// имитация динамического массива данных;
//например, массив - результат выборки из БД MySql
var dataArray:Array = new Array();
for (var i = 0; i <= 100; i++) {
dataArray.push({field1:i + " a", field2:i + " b", field3:i + " c", field4:i + " d", field5:i + " e", field6:i + " f", field7:i + " g", field8:i + " h"});
}
//формируем заголовочную строку vb-скрипта:
//создаем документ, таблицу, элеметарное форматирование, используя
// VBA-объект Word.Application
var vbcode:String = "";
vbcode += "Set objWord = CreateObject(\"Word.Application\")\r";
vbcode += "objWord.Visible = True\r";
vbcode += "Set objDoc = objWord.Documents.Add()\r";
vbcode += "objWord.Activate()\r";
vbcode += "objDoc.Select\r";
vbcode += "objDoc.Application.Selection.PageSetup.Orientation = 1\r";
vbcode += "objDoc.Application.Selection.PageSetup.LeftMargin = 30\r";
vbcode += "Set objRange= objDoc.Range()\r";
vbcode += "objDoc.Tables.Add objRange,1,8\r";
vbcode += "Set objTable = objDoc.Tables (1)\r";
vbcode += "objTable.Range.Style = \"Сетка таблицы\"\r";
for (var i = 1; i <= 8; i++) {
vbcode += "objTable.Columns(" + i + ").Width =80\r";
}
vbcode += "objTable.Rows.Height = 16\r";
vbcode += "objTable.Rows.Add ()\r";
for (var i = 1; i <= 8; i++) {
vbcode += "objTable.Cell(1, " + i + ").Range.Text = \"Колонка " + i + "\"\r";
}
vbcode += "objDoc.Tables (1).Rows(1).HeadingFormat = True\r";
//сохраняем на диск
mdm.FileSystem.saveFile(mdm.System.Paths.appData + "toWord.vbs", vbcode);
vbcode = "";
//формируем тело скрипта, заполняющего таблицу с помощью команд VBA
for (var i = 0; i <= 100; i++) {
vbcode += "objTable.Rows.Add ()\r";
for (var j = 1; j <= 8; j++) {
vbcode += "objTable.Cell(" + (i + 2) + ", " + j + ").Range.Text = \"" + dataArray[i]["field" + j] + "\"\r";
}
//сохраняем на диск построчно
mdm.FileSystem.appendFile(mdm.System.Paths.appData + "toWord.vbs", vbcode);
vbcode = "";
}
//запускаем скрипт на выполнение
mdm.System.exec(mdm.System.Paths.appData + "toWord.vbs");
|
|
|||||
|
listener
|
Экспорт в Excel
Простенький пример выгрузки данных из цинк в MS Excel суть та же что и с Word, только в скрипте используется другой VBA-объект - Excel.Application //каждую строку тела формируемого скрипта не забываем заканчивать
//символом переноса строки.
function Export() {
var vbs:String = "";
vbs += "Set objExcel = CreateObject(\"Excel.Application\")\r";
vbs += "objExcel.Visible = True\r";
vbs += "Set objDoc = objExcel.Workbooks.Add()\r";
vbs += "objDoc.Sheets(1).Activate\r";
mdm.FileSystem.saveFile(mdm.System.Paths.appData + "toExcel.vbs", vbs);
vbs = "";
var i = 0;
while (ds[i][0]) {
vbs = "";
vbs += "objDoc.Sheets(1).Range(\"A" + (i + 1) + "\").Value=\"" + ds[i][0] + "\"\r";
vbs += "objDoc.Sheets(1).Range(\"B" + (i + 1) + "\").Value=\"" + ds[i][1] + "\"\r";
vbs += "objDoc.Sheets(1).Range(\"C" + (i + 1) + "\").Value=\"" + ds[i][2] + "\"\r";
vbs += "objDoc.Sheets(1).Range(\"D" + (i + 1) + "\").Value=\"" + ds[i][3] + "\"\r";
vbs += "objDoc.Sheets(1).Range(\"F" + (i + 1) + "\").Value=\"" + ds[i][4] + "\"\r";
mdm.FileSystem.appendFile(mdm.System.Paths.appData + "toExcel.vbs", vbs);
i++;
}
mdm.System.exec(mdm.System.Paths.appData + "toExcel.vbs");
}
Последний раз редактировалось alexcon314; 27.11.2007 в 23:51. |
|
|||||
|
listener
|
Запуск скринсейвера
небольшая фича, которая позволяет запустить программно скринсэйвер, установленный в системе по умолчанию // go-стандартная кнопка
go.label = "screensaver";
mdm.Application.doEvents();
formTitle = mdm.Forms.MainForm.title = "form";
appTitle = mdm.Application.title = "app";
// получаем хэндл окна
var wList = mdm.System.getWindowList();
var i = 0;
while (wList[i][1]) {
if (wList[i][0] == formTitle || wList[i][0] == appTitle) {
hwnd = wList[i][1];
}
i++;
}
go.onRelease = function() {
// шлем WM_SYSCOMMAND с wParam = SC_SCREENSAVE и lParam = 0
mdm.System.postMessage(hwnd, 0x0112, 0xF140, 0);
};
Далее окно само себе шлет системное сообщение на запуск скринсейвера. |
![]() |
![]() |
Часовой пояс GMT +4, время: 06:35. |
|
|
« Предыдущая тема | Следующая тема » |
|
|