|
|
|||||
Ветеран форума
Регистрация: Jul 2006
Адрес: Грузия, Тбилиси
Сообщений: 2,675
|
Zinc FAQ
Оглавление
Интеграция с ОС Контроль над мышью Получить список логических дисков Программно изменить раскладку клавиатуры Работа с реестром Запуск скринсейвера Использование функций VBS и WSH Работа с файлами Экспорт в Word Экспорт в Excel Общие вопросы Запрет на запуск второго экземпляра приложения 1 Ошибка при запуске приложения "Access violation..." Можно ли использовать {mdm}Script во внешних .swf, подгружаемых в основное приложение? Прочее Универсальная схема цинк-приложения. А нельзя ли сделать что-нибудь наподобие динамической библиотеки различных функци vbs? Связка CS3 & Zinc Последний раз редактировалось alexcon314; 20.06.2008 в 14:36. |
|
|||||
listener
|
Zinc: рецепты применения.
Контроль над мышью
для реализации на цинке под 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, время: 01:04. |
|
« Предыдущая тема | Следующая тема » |
|
|