Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Flash Приложения: AIR, Zinc и тд. (http://www.flasher.ru/forum/forumdisplay.php?f=94)
-   -   Zinc FAQ (http://www.flasher.ru/forum/showthread.php?t=104606)

screamge 10.11.2007 03:37

Zinc FAQ
 
Оглавление


Интеграция с ОС
Контроль над мышью
Получить список логических дисков
Программно изменить раскладку клавиатуры
Работа с реестром
Запуск скринсейвера
Использование функций VBS и WSH


Работа с файлами
Экспорт в Word
Экспорт в Excel


Общие вопросы
Запрет на запуск второго экземпляра приложения 1
Ошибка при запуске приложения "Access violation..."
Можно ли использовать {mdm}Script во внешних .swf, подгружаемых в основное приложение?


Прочее
Универсальная схема цинк-приложения.
А нельзя ли сделать что-нибудь наподобие динамической библиотеки различных функци vbs?
Связка CS3 & Zinc

alexcon314 27.11.2007 23:28

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();
}

для более детального управления можно ипользовать свою DLL.
модераторам: в это тему можно складывать удачные примеры использования цинка.

alexcon314 27.11.2007 23:32

Использование функций 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);

Пример 2
Замена символов в строке. (см. мануал по 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);

Пример 3

Импорт текста из документа 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);

Аналогично, используя свойства и методы объекта Excel.Sheet, можно импортировать данные из документов Excel.

Пример 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);

Пример 5

Построчное чтение текстового файла. Аргументы вызова - полное имя файла и номер строки, которую нужно прочитать.

Код:

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);

Файл, из которого производится чтение, может быть .txt, ini, cfg, .xml и т.д. И бинарный тоже, но с понятными оговорками.
В случае, если передан номер строки, больший их общего количества в файле, возвращается номер последней строки и она сама.

alexcon314 27.11.2007 23:33

А нельзя ли сделать что-нибудь наподобие динамической библиотеки различных функци 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);

На указанном url лежит файл fcom.wsc (windows scripting component):
оригинальный xml здесь

http://flasher.ru/forum/newreply.php...reply&p=677298

Код HTML:

<?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>

.swc-файл может располагаться и локально, конечно.
Происходит динамическая подгрузка этого компонента и вызывается его метод 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);

Скрипт запускает word, и с интервалом 0.3 с.(из-за особенностей vbs десятичный разделитель должен быть запятая ",") печатает в нем строки "Hello! It's me.", если использовать аргумент "notepad" - то запустится блокнот, если строку "12*3~" и аргумент "calc" то .. смотрите сами.

alexcon314 27.11.2007 23:34

Получить список логических дисков

Код:

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;
        }
}

Здесь вызывается API-функция GetLogicalDrives(), которая возвращает число, двоичное представление которого служит маской для букв дисков
по принципу
0000000000001101
...................DCBA
1 - соответствует наличию диска с буквой, 0 - отсутствует диск с такой буквой.
В примере видно, что есть диски A, C и D.

alexcon314 27.11.2007 23:35

Программно изменить раскладку клавиатуры
Код:

// подключаем системную 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();
}

Здесь вызывается API-функция ActivateKeyboardLayout(), которая, собственно и меняет раскладку.
Параметры берутся из справки 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;
        }
};

В поле test можно проверять язык ввода.
form - Название формы приложения (form title). Окно самому себе шлет message - запрос на изменение раскладки WM_INPUTLANGCHANGEREQUEST( численное значение 0x0050) c параметром-значением раскладки.

alexcon314 27.11.2007 23:37

Работа с реестром

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);

Для получения справки по утилите запустите cmd и набейте reg delete /? или reg query /?
Да, еще. Методы .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);
};

Как упоминалось в примерах по VBScript, этот инструмент можно так же использовать для работы с реестром, т.к.
возможности 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-скрипт.
Код:

// "голый" WSH-скрипт для работы с реестром может выглядеть так
Set Sh = CreateObject("WScript.Shell")
key =  "HKEY_CURRENT_USER\"
Sh.RegWrite key & "WSHTest\", "testkeydefault"

См. выше примеры.

alexcon314 27.11.2007 23:38

Экспорт в 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");


alexcon314 27.11.2007 23:39

Экспорт в 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");
}

ds - двухмерный массив с данными.

alexcon314 27.11.2007 23:40

Запуск скринсейвера

небольшая фича, которая позволяет запустить программно скринсэйвер, установленный в системе по умолчанию

Код:

// 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);
        };

title у формы устанавливается программно, чтобы получить хэндл окна приложения через getWindowsList, но можно устанвить титле и вручную. Важно только чтоб фактический титле совпал со строкой сравнения в цикле while.
Далее окно само себе шлет системное сообщение на запуск скринсейвера.

alexcon314 27.11.2007 23:40

Запрет на запуск второго экземпляра приложения 1

Код:

//заставляем окно приложения реагировать
// на системные сообщения

mdm.Application.doEvents();
mdm.Application.enableExitHandler();
mdm.Application.onAppExit = exit;
mdm.Forms.MainForm.title = "form";
hwnd = mdm.System.Registry.load("AppHwnd");
if (hwnd && hwnd != "none") {
        // шлем WM_SYSCOMMAND с wParam = SC_RESTORE и lParam = 1
        mdm.System.sendMessage(hwnd, 0x0112, 0xF120, 1);
        // ставим фокус
        mdm.System.setWindowFocus(hwnd);
        flag = false;
        exit();
} else {
        var wList = mdm.System.getWindowList();
        var i = 0;
        while (wList[i][0] != "form") {
                i++;
        }
        mdm.System.Registry.save("AppHwnd", wList[i][1]);
        flag = true;
}
function exit() {
        if (flag) {
                mdm.System.Registry.save("AppHwnd", "none");
        }
        mdm.Application.exit();
}

При запуске пример пишет в реестр хэндл своего окна. Второй экземляр при запуске читает из реестра этот хэндл и шлет мессаги на ресторе и сетфокус первому экземпляру, а сам отваливает. Первый экземпляр при закрытии вытирает из реестра хэндл.
Конечно, сохранять хэндл необязательно в реестр, просто это в данной ситуации удобно.
В случае нештатного завершения работы приложения эта схема не работает.
ПОЭТОМУ ДРУГОЙ ПРИМЕР.

Запрет на запуск второго экземпляра приложения 2

Код:

mdm.Application.doEvents();
formTitle = mdm.Forms.MainForm.title = "form";
appTitle = mdm.Application.title = "app";
var wList = mdm.System.getWindowList();
var appList:Array = new Array();
var i = 0;
while (wList[i][1]) {
        if (wList[i][0] == formTitle || wList[i][0] == appTitle) {
                appList.push(wList[i][1]);
        }
        i++;
}
hwnd = appList[1];
if (hwnd) {
        mdm.System.sendMessage(hwnd, 0x0112, 0xF120, 1);
        mdm.System.setWindowFocus(hwnd);
        mdm.Application.exit();
}

Здесь все основано на том факте, что в списке окон wList окно второго экземпляра приложения находится выше чем окно ранее запущенного экземпляра. и при добавлении в массив appList хэндл уже запущенного окна (если таковое присутствует) оказывается под номером 1, а хэндл второго под номером 0, если запускать их подряд. В случае запуска не подряд можно применить сортировку массива appList. Действительно, должен признать, что в этом случае нужно проверять наличие в списке wList и титла на кнопке приложения в таскбаре: когда оно свернуто принудительно только так его можно найти. Поэтому присутствует строчка mdm.Application.title="...", где устанавливается титл на этой кнопке.
FormTitle и ApplicationTitle можно указать статически в самом компиляторе. Но в этом случае к ним не получишь доступ так просто. И придется писать в условии сравнения титлов сам титл. Не поручусь, что это всегда работает, особенно когда титл русский или необычные символы там есть. Поэтому, лучше назначать их динамически в коде.

alexcon314 28.11.2007 18:16

Zinc: Access violation at ...
 
Ошибка при запуске приложения

Иногда при разработке приложения на Zinc возникает такая ситуация, что приложение при запуске выдает ошибку
вида

Код:

"Access violation at address 7C93426D in module 'ntdll.dll. Read of address 003a0043."
и, соответственно, стартовать не хочет. возможны варианты, когда в сообщении об ошибке ntdll.dll не упоминается.
Данная проблема может возникнуть при попытке переноса приложение на другой компьютер простым копированием исполняемого файла, а так же при запуске с CD. И даже при переносе исполняемого файла в другую папку на той же машине, что я наблюдал сам.
На mdm-форуме эта прблема обсуждалась довольно долго.

http://www.mdmforum.com/forum/index.php?showtopic=13421

Кратко изложу суть обсуждения.
По непонятым причинам один и тот же .ехе файл нормально запускается на одной машине и отказывается
стартовать на другой. Речь шла именно о запуске с CD.
Эксперименты разработчиков показали, что возникновение ошибки происходит непредсказуемо.
Например, производились проверки на разных OC (семейства Windows), на разных аппаратных конфигурациях.
Никакой закономерности отследить не удалось и баг был помещен в WishList.
Тем не менее, было найдено несколько приемов устранения этой специфической ошибки.

1. Запуск в режиме совместимости с Win98.
2. Внесение изменений в реестр, таких, что программа принудительно стартует в режиме совместимости с Win98.
3. Сокращение имени исполняемого файла до 3-х - 4-х символов (или даже до 1-ого).

В моей практике эта неприятная ситуация возникала несколько раз.
Всякий раз сокращение имени файла мне помогало. Видимо, о чем свидетельствуют и сведения из указаного топика
на mdm-форуме, этот прием наиболее эффективен.
В целом у участников обсуждения сложилось мнение, что проблема возникает из-за внутренних политик безопасности
Windows XP. В чем конкретно состоит причина выяснить не удалось. Будем надеяться, что производители Zinc
смогут разрешить этот вопрос.

[добавлено]

М-да... сокращение имени файла не панацея, как оказалось.
После некоторого количества собственных экспериментов складывается такая картина.

1. "непредсказуемость" возникновения бага обусловлена на самом деле текущим сосотоянием профиля пользователя, который пытается приложение запустить. пересоздание профиля устраняет баг. где сидит затык в профиле до конца не выяснил, но установлено, что сидит он в той его части, которая хранится на компе, не выгружается на сервак (в случае использования сетвого входа). поэтому, на одних компах баг проявляется, на других может и не проявляться.
даже если установить точную причину затыка, вряд ли это будет иметь практическое значение, т.к. править профиль перед запуском все равно никто не будет.

2. баг с "хорошей" вероятностью возникает, если в Zinc IDE вручную указывать заголовок формы и приложения (поля Form Caption и Application title). Application title скорее приводит к ошибке. при этом "плохо" себя ведут символы вроде точки, пробела, русских букв, но не всегда, почему - смотри п.1. если задавать эти параметры программно, оставляя соответствующие поля в IDE пустыми, даже с использованием этих символов, баг не возникает.

3. баг не проявляется независимо от других факторов, если запускать приложение в режиме совместимости с Win98, Win2000.
это может оказаться полезным при создании собственного инсталлятора приложения (см. NSIS, Inno Setup из бесплатных). В алгоритме установки можно указать команду записи в реестр ХР соответствующего ключа типа
Код:

ключ:        HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
значение:  "D:\\Start.exe"="WIN98"

что и заставит приложение стартовать в режиме совместимости с указанной версией Windows.

4. судя по трэйсам, стоп с ошибкой происходит на стадии обращения к системной библиотеке ntdll.dll, которая подключается при запуске, как раз перед первой прорисовкой окна приложения.

Официальное описание проблемы

http://www.multidmedia.com/support/t...n=detail&id=19

alexcon314 27.12.2007 15:15

Подгрузка внешних .swf
 
Можно ли использовать {mdm}Script во внешних .swf, подгружаемых в основное приложение?

Да, можно.
mdm-классы инициализируются в основном приложении, точнее в мувике основного приложения при компиляции в цинке. К ним можно обращаться из подгружаемых мувиков точно так же как к обычным AS-классам.

Пример.
Код:

// основной клип main.swf, компилируемый в цинке
this.createEmptyMovieClip('cont',0);
var mc:MovieClipLoader= new MovieClipLoader();
mc.loadClip('loaded.swf',cont);

Код:

// подгружаемый клип loaded.swf. это обычный .swf, скомпилированный
// во Flash IDE, без какого-либо участия цинка.
mdm.prompt("Swf is loaded and says 'Hello!'");

после запуска main.exe подгруженный клип выведет сообщение. Точно так же можно обращаться и к другим mdm-классам из подгружаемых клипов. Например, использовать методы работы с файловой системой, базами данных и т.д..
Тем не менее, при использовании ActiveX, mdm.FileExplorer и т.п., окна этих элементов все равно будут привязываться к окну основного приложения.
...
в загружемом клипе не будет выполняться mdm-скрипт, если он загружен c урл, начинающегося как "http://".
т.е. такая схема сработает только при локалной загрузке. оно и хорошо.
...

alexcon314 06.05.2008 00:09

Универсальная схема цинк-приложения.
 
вырисовывается интересная схема построения цинк-приложения:

1. Основной swf, который ЕДИНОЖДЫ компилируется в цинк-IDE - это очень простой универсальный загрузчик, конфигурируемый файлом настроек (что и от куда грузить).

2. Весь основной код, включая mdm-скрипты, хранится во внешних swf-модулях, которые в свою очередь так же могут выступать в роли загрузчиков других модулей.

3. Все вышесказанное в полной мере относится к дочерним формам, которых по-сути нужна всего одна, даже если вам нужно их несколько разновидностей. просто в качестве основного swf для дочерней формы указывается все тот же простой загрузчик. (Конечно, если вы планируете ОДНОВРЕМЕННО показывать несколько дочерних форм, их количество придется увеличить)
Одна тонкость.
Чтобы дочерняя форма нормально инициализировалась при старте приложения и не мелькала при этом на экране - в IDE при компиляции задать ей отрицательную x- или y-координату и свойство visible=true.
Дело в том, что обращаться к функциям дочерней формы из основной формы можно только после первого появления дочерней формы на экране. до этого момента ее "как бы" нет.
При задании отрицательных координат при visible=true формально при старте форма будет "показана" (но не буквально), что и устраняет указанное препятствие. Далее, можно оперировать с ее координатами или с ее свойством visible из основной формы, показывая ее когда необходимо, предварительно подгрузив в нее нужный swf.

4. Приложение легко переносится, масштабируется, достраивается, дебажится.


Схема опробована на верси цинка 2.5. Обсуждение можно посмотреть здесь. По поводу версии 3 тоже.

http://www.flasher.ru/forum/showthread.php?t=111623

alexcon314 20.06.2008 14:25

Zinc и flash cs3 с update 9.0.3 (AIR)
 
Настройка CS3 под работу с Zinc. Удачный опыт связки.

Для AS 3.0:

http://flasher.ru/forum/showthread.php?t=113163

Файл mdm.swc, о котром идет речь поставляется с дистрибутивом Zinc и находится в папке (по умолчанию)

"c:\Program Files\MDM\MDM Zinc 3.0\swc\cs3\" для версии 3.0

Настройка CS4 под работу с Zinc. Удачный опыт связки.

http://www.flasher.ru/forum/showthread.php?t=121906

AS 2.0:

Настройка CS3/4 на работу с Zinc 2.5.0.34. (Собственно, никакой настройки не требуется, главное, чтобы проект был AS 2.0 и версия плеера 8).

cassius 01.08.2008 07:02

Цитата:

Сообщение от alexcon314 (Сообщение 699006)
Ошибка при запуске приложения

Скорее всего, дело не в цинке. Такая же проблема (без отображения сообщения) появляется и с использованинем стандартного прожектора на 8-м флеше. Решается запуском в режиме совместимости с предыдущими версиями windows.

Azo 13.01.2011 14:15

Экспорт в Excel из .mdb базы

Основываясь на примере alexcon314 делал себе программу которая выгружает не из фоеша а из базы... Это полезно тем что мы можем не заморачиваясь с кодировкай Юникода выгружат в Excel русские слова...

Код:


var telephoneDBUrl:String="\\\\10.23.123.11\Folder\base.mdb"// Адрес нашей базы , расположенной на нашем сервере 10.23.123.11
var SQLString:String="Select * from table1"// SQL запрос

// Создаем строковую переменную vbs и вписываем туда команды

var vbs="";
vbs+="Option Explicit\r"
vbs+="Dim ZAGOLOVOK\r"
vbs+="ZAGOLOVOK=\"GENSER | Kotlas\"\r"
vbs+="Dim SQLZAPROS\r"
vbs+="SQLZAPROS = \""+SQLString+"\"\r"
vbs+="Dim MDBADRESS\r"
vbs+="MDBADRESS=\""+telephoneDBUrl+"\"\r"


vbs+="Dim mcn\r"
vbs+="Set mcn = CreateObject(\"ADODB.Connection\")\r"
vbs+="mcn.CursorLocation = 3 'adUseClient\r"
vbs+="mcn.CommandTimeout = 300\r"
vbs+="mcn.ConnectionString = \"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"&MDBADRESS&\";Persist Security Info=False\"\r"
vbs+="mcn.Open\r"
vbs+="Dim rs\r"
vbs+="Set rs = mcn.Execute(SQLZAPROS)\r"
vbs+="Dim ddd\r"
vbs+="Dim i\r"
vbs+="i=0\r"
vbs+="DIM objExcel\r"
vbs+="DIM objDoc\r"
vbs+="DIM oSheet\r"
vbs+="        Set objExcel = CreateObject(\"Excel.Application\")\r"
vbs+="                objExcel.Visible = True\r"
vbs+="        Set objDoc = objExcel.Workbooks.Add()\r"
vbs+="        Set oSheet = objExcel.ActiveSheet\r"
vbs+="        \r"
vbs+="                objExcel.Caption = ZAGOLOVOK\r"
vbs+="Do While Not rs.EOF\r"
vbs+="                objDoc.Sheets(1).Range(\"A\" & (i + 1)).Value= rs.fields(\"Dates\")\r"
vbs+="                objDoc.Sheets(1).Range(\"B\" & (i + 1)).Value= rs.fields(\"Type\")\r"
vbs+="                objDoc.Sheets(1).Range(\"C\" & (i + 1)).Value= rs.fields(\"Manager\")\r"
vbs+="                objDoc.Sheets(1).Range(\"D\" & (i + 1)).Value= rs.fields(\"Istok\")\r"
vbs+="                objDoc.Sheets(1).Range(\"E\" & (i + 1)).Value= rs.fields(\"Marka\")\r"
vbs+="                objDoc.Sheets(1).Range(\"F\" & (i + 1)).Value= rs.fields(\"Model\")\r"
vbs+="                objDoc.Sheets(1).Range(\"G\" & (i + 1)).Value= rs.fields(\"Adder\")\r"
vbs+="i=i+1\r"
vbs+="rs.MoveNext\r"
vbs+="Loop\r"
vbs+="        objDoc.Sheets(1).Columns(1).ColumnWidth = 20\r"// ширины колонок
vbs+="        objDoc.Sheets(1).Columns(2).ColumnWidth = 20\r"
vbs+="        objDoc.Sheets(1).Columns(3).ColumnWidth = 20\r"
vbs+="        objDoc.Sheets(1).Columns(4).ColumnWidth = 20\r"
vbs+="        objDoc.Sheets(1).Columns(5).ColumnWidth = 20\r"
vbs+="        objDoc.Sheets(1).Columns(6).ColumnWidth = 20\r"
vbs+="        objDoc.Sheets(1).Columns(7).ColumnWidth = 20\r"

vbs+=" With oSheet.Range(\"A1\", \"A1111\")\r"
vbs+="        .Font.Bold = True\r"  //жирность
vbs+="        .NumberFormat = \"dd/mm/yyyy\"\r" // формат даты
vbs+="      End With\r"

vbs+="mcn.Close\r"
vbs+="Set mcn = Nothing\r"

mdm.FileSystem.saveFileUnicode(mdm.System.Paths.appData + "toExcel.vbs", vbs);// сохраняем файл
mdm.System.exec(mdm.System.Paths.appData + "toExcel.vbs");// запускаем файл



Часовой пояс GMT +4, время: 02:26.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.