Ниже представлен небольшой код, который находит все запущенные терминалы Quik и запускает экспорт всех таблиц путем нажатия пункта меню 'Экспорт Данных -> Начать экспорт таблиц по DDE'.
Код не требует никаких дополнительных библиотек, вам просто достаточно добавить этот код в свой проект.
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; namespace QuikIntegration.dde { public class QuikUtil { private static string _exportMenuKey = "Экспорт данных"; private static string _stopExportMenuItem = "Остановить экспорт таблиц по &DDE"; private static string _startExportByDDEMenuItem = "Начать экспорт таблиц по &DDE"; // ReSharper disable InconsistentNaming [DllImport("user32.dll")] static extern IntPtr GetMenu(IntPtr hWnd); [DllImport("user32.dll")] static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos); [DllImport("user32.dll")] static extern int GetMenuItemCount(IntPtr hMenu); [DllImport("user32.dll")] static extern int GetMenuString(IntPtr hMenu, uint uIDItem, StringBuilder lpString, int nMaxCount, uint uFlag); [DllImport("user32.dll")] static extern uint GetMenuItemID(IntPtr hMenu, int nPos); [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); private const UInt32 MF_BYPOSITION = 0x00000400; public static bool StartDDE() { IntPtr[] quikWindows = FindQuikWindow(); if (quikWindows.Length == 0) { return false; } foreach (var quikWindow in quikWindows) { IntPtr mainMenu = GetMenu(quikWindow); int exportMenuIndex = (int)FindMenuItemByPart(mainMenu, _exportMenuKey); IntPtr exportMenu = GetSubMenu(mainMenu, exportMenuIndex); uint exportIndex = 6; // FindMenuItemByPart(exportMenu, _startExportByDDEMenuItem); uint menuItem = GetMenuItemID(exportMenu, (int)exportIndex); PostMessage(quikWindow, 0x111, (IntPtr)menuItem, (IntPtr)0); } return true; } public static bool StopDDE() { IntPtr[] quikWindows = FindQuikWindow(); if (quikWindows.Length == 0) { return false; } foreach (var quikWindow in quikWindows) { IntPtr mainMenu = GetMenu(quikWindow); int exportMenuIndex = (int)FindMenuItemByPart(mainMenu, _exportMenuKey); IntPtr exportMenu = GetSubMenu(mainMenu, exportMenuIndex); uint exportIndex = 7; // FindMenuItemByPart(exportMenu, _stopExportMenuItem); uint menuItem = GetMenuItemID(exportMenu, (int)exportIndex); PostMessage(quikWindow, 0x111, (IntPtr)menuItem, (IntPtr)0); } return true; } private static IntPtr[] FindQuikWindow() { Process[] processes = Process.GetProcessesByName("info"); IntPtr[] result = new IntPtr[processes.Length]; for (int i = 0; i < processes.Length; i++) { result[i] = processes[i].MainWindowHandle; } return result; } private static uint FindMenuItemByPart(IntPtr menu, string name) { int menuItemsCount = GetMenuItemCount(menu); for (uint menuIndex = 0; menuIndex < menuItemsCount; menuIndex++) { StringBuilder result = new StringBuilder(); GetMenuString(menu, menuIndex, result, 1024, MF_BYPOSITION); string buffer = result.ToString(); if (buffer.Contains(name)) { return menuIndex; } } return 0; } } // ReSharper restore InconsistentNaming }
Для того, чтобы запустить экспорт всех таблиц нужно выполнить комманду:
QuikUtil.StartDDE();остановить
QuikUtil.StopDDE();
привет...
ОтветитьУдалитьмож подскажешь..
обнаружил что если в квике открыто окошко системных сообщений
обычный заголовок "QUIK: окно сообщений"
то, т.к. в этом окне нет никаких меню ДДЕ экспорта...
то и запустить дде-экспорт не удастся...
как бы докопаться до оригинального окна info процесса?
как закрыть это "оконо сообщений"?
можно ль послать команду на закрытие этого окна ?
и потом уж рыть в нужном процессе на счет дде-экспорта
P.S. приделал поиск нужного окна по UID
проще отключить в настройках показ окна сообщений
ОтветитьУдалитьВ этой строке
ОтветитьУдалитьGetMenuString(menu, menuIndex, result, 1023, MF_BYPOSITION);
получаю:
System.ExecutionEngineException
В среде выполнения обнаружена критическая ошибка. Ошибка произошла по адресу 0x707dceca в потоке 0xe18. Код ошибки 0xc0000005. Она может быть вызвана ошибкой в CLR или в небезопасных либо не поддающихся проверке фрагментах пользовательского кода. Обычно источниками таких ошибок бывают ошибки упаковки, допускаемые пользователями при COM-взаимодействии, либо PInvoke, повредивший стек.
Давно не заходил сюда, времени совсем нету.
ОтветитьУдалитьОшибка которую вы описываете у меня тоже последнее время начала возникать, причем возникает не постоянно, а периодически, у меня стоит Windows 7.
Проблему решил криво, но у меня теперь все работает. Сейчас все работает. В теле поста поправленный код.
Спасибо за код клика по пунктам меню очень помог)
ОтветитьУдалитьХотелось бы продолжения про DDE сервер
ОтветитьУдалитьребят, очень нужен программист, который бы собственно и настроил экспорт из квика на вебсайт. нужна утилита, которая организует синхронизацию между терминалом и сайтом.
ОтветитьУдалитьне пойму как тут написать в личку на блоге, отпишитесь мне в скайп, плз, vasart_ceo или на мыло vasart1@mail.ru
И все же представленный код вызывает исключение. Лекарство простое - надо явно задать длину строки StringBuilder. Строка 94:
ОтветитьУдалитьStringBuilder result = new StringBuilder(1024);
Можно сделать дину поменьше (побольше), но тогда в следующей строке указывать точно такую же длину.
Кстати прототип в строке 25 лучше вот так описать:
static extern int GetMenuString(IntPtr hMenu, uint uIDItem, [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder lpString, int nMaxCount, uint uFlag);
А вообще спасибо автору за этот пост! Очень хороший код, который практически не пришлось править для своих целей )))) Но можно этот класс нагрузить еще немного и расширить его функционал для автоматического запуска QUIK, автоматического соединения с сервером и всяческими событиями по поводу внезапной кончины QUIK. Я в эту сторону обязательно пойду и, если это интересно, могу выложить дальнейшее развитие класса. Пишите на hamper [at] bk.ru
Спасибо!
Всем привет!
ОтветитьУдалитьУ меня в 51-й строке
PostMessage(quikWindow, 0x111, (IntPtr)menuItem, (IntPtr)0);
Валится на ошибке:
Переполнение в результате выполнения арифметической операции.
Подскажите плиз, с чем это может быть связано )))
А кто нить пробовал сделать, чтобы при разрыве связи он сам восстанавливал DDE экспорт ?))
ОтветитьУдалитьПривет,
ОтветитьУдалитьСтранная ошибка, у меня такой никогда не возникало. А какая версия терминала установлена?
А вот обработку разрыва связи нужно делать не в этом маленьком коде. Вам необходимо повесить слушателя на событие разрыва связи в trans2quik.dll и в случае если произошел разрыв нужно перезапустить dde.
Спасибо, уже решилась ..)
УдалитьКак выяснилось дело не в самом Postmessage а в параметрах которые туда поступают. Точно уже не помню, какие точно, помню только лишь что я раскомментил строки
FindMenuItemByPart(exportMenu, _stopExportMenuItem);
Может действительно в разных версиях квика разные номера меню ))
А Вы не реализовывали решение, чтобы он сам восстанавливал DDE экспорт при его разрыве ?)
Здравствуйте!
ОтветитьУдалитьПодскажите пожалуйста, а как сделать автозапуск экспорта только лишь таблицы текущих параметров?
Добрый день,
ОтветитьУдалитьК сожалению данный код настолько туп, что умеет делать только одну операцию - это имитировать нажатие кнопки меню квика "Экспорт всех таблиц". Чтобы сделать экспорт только таблицы текущий параметров предлагаю вам настроить на экспорт только данную таблицу (хотя конечно я абсолютно не знаю как вы используете остальные таблицы и возможно данный вариант вам не подходит).