Как достать второе окно

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

fallologia
Сообщения: 20
Зарегистрирован: 22 июл 2005, 12:51

Пытаюсь программно работать с контролами окошек. С первым всё получилось, а второе, которое выскакивает как попап, всё никак не могу достать. В чем ошибки?

Код: Выделить всё

if(m_bLingvo6) 
     {
    STARTUPINFO si={0};
    si.cb = sizeof( si );
    si.wShowWindow = SW_NORMAL;
    PROCESS_INFORMATION pi = {0};
    CreateProcess (NULL, "R\\abbyy67\\dslcomp.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );    
    WaitForInputIdle( pi.hProcess, INFINITE );//SingleObject
    HWND wnd = FindWindow ("#32770", "DSL Compiler");
    SendDlgItemMessage (wnd, 1056, BM_SETCHECK, BST_UNCHECKED, 0);
    SendDlgItemMessage (wnd, 1057, BM_SETCHECK, BST_CHECKED, 0);
    SendDlgItemMessage (wnd, 1004, BM_SETCHECK, BST_UNCHECKED, 0);
    SendDlgItemMessage (wnd, 1006, WM_SETTEXT, 0, (LPARAM)"RusSyn.dsl");
    SendDlgItemMessage (wnd, 1040, BM_CLICK, 0, 0);

    HWND wnd2 = FindWindowEx(wnd, FindWindow ("#32770", "Dictionary Header Editor"), NULL, "Dictionary Header Editor");
    //SendDlgItemMessage (wnd2, 1048, IDC_COMBO, CB_ADDSTRING, (LPARAM)"Русский");
    SendDlgItemMessage (wnd2, 1047, WM_SETTEXT, 0, (LPARAM)"RusSyn");
    SendDlgItemMessage (wnd2, 1059, WM_SETTEXT, 0, (LPARAM)"Системный(*.lsd)");
    SendDlgItemMessage (wnd2, 1, BM_CLICK, 0, 0);

    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );   
     }
Кроме того, проблема и с комбо-боксом. Какой-то он твердолобый и не хочет меняться программно чего-то... :roll: Да и вообще, как в такой ситуации будет правильно работать с изменением параметров комбобокса?..
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Один из способов, которым можно управлять интерфейсом другой программы такой: эмуляция клика мыши в указанных координатах окна. Если размеры диалога и его элементов неизменны, то координаты их относительно клиентской области окна будут тоже неизменны. Вот и отправляй в окно диалога сообщения типа WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, WM_RBUTTONDOWN...
fallologia
Сообщения: 20
Зарегистрирован: 22 июл 2005, 12:51

WinMain писал(а):Вот и отправляй в окно диалога сообщения типа WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, WM_RBUTTONDOWN...
Да, но не могу понять необходимости применения метода координат в моем случае. Ведь с первым окошком я благополучно справляюсь и без этого. Единственное, не могу увязать почему-то хэндл дочернего окошка с управлением контролами... В чем же тут может быть причина?.. На определении хэндла как

Код: Выделить всё

HWND wnd2 = FindWindowEx&#40] при установке проверки способом [code]if (!wnd2)
    {
        AfxMessageBox(("Нет"),MB_OK|MB_ICONQUESTION);
        return 0;
    }
вылазит это предупреждение "Нет", а при проверке варианта

Код: Выделить всё

HWND wnd2 = FindWindowEx(wnd, FindWindow ("#32770", "Dictionary Header Editor"), NULL  , NULL); 
способом

Код: Выделить всё

if (wnd2)
    {
        AfxMessageBox(("Да"),MB_OK|MB_ICONQUESTION);
        return 0;
    }
появляется это сообщение "Да",. То есть хэндл дочернего окошка определяется. Но почемпу же он не срабатывает?.. Вот в чем вопрос. :?: :!:
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Непойму что-то, дык ты получил всетаки хендл окна? И он такой как надо ? (Посмотри в Spy++ например его хендл).
И почему не сделать просто -

Код: Выделить всё

HWND wnd2 = FindWindowEx(wnd, NULL, "#32770", "Dictionary Header Editor"); 
Если этот диалог ("Dictionary Header Editor") просто дочерний для диалога "DSL Compiler" то не должно быть никаких проблем. А что за проблемы с комбобоксом ? Поподробнее опиши
fallologia
Сообщения: 20
Зарегистрирован: 22 июл 2005, 12:51

Hawk писал(а):Непойму что-то, дык ты получил всетаки хендл окна?
В том-то всё и дело, что для второго окна, пожалуй, что и нет.

Код: Выделить всё

HWND wnd2 = FindWindowEx&#40]не срабатывает. По крайней мере, ни один из контролов при этом корректировке не поддается:    [code]SendDlgItemMessage (wnd2, 1047, WM_SETTEXT, 0, (LPARAM)"RusSyn");
SendDlgItemMessage (wnd2, 1059, WM_SETTEXT, 0, (LPARAM)"НеСистемный(*.lsd)");
SendDlgItemMessage (wnd2, 1, BM_CLICK, 0, 0);
Spy++ говорит, что хэндл этого окна 003506D8 и что его Parent и Owner - первое окно (с которым проблем не возникает у меня). Я уже писал о проверке хэндла2 функциями

Код: Выделить всё

if (wnd2)
    {
        AfxMessageBox(("Есть"),MB_OK|MB_ICONQUESTION);
        return 0;
    }
и

Код: Выделить всё

if (!wnd2)
    {
        AfxMessageBox(("Нетутить"),MB_OK|MB_ICONQUESTION);
        return 0;
    }
Так вот, "Есть" срабатывает только на

Код: Выделить всё

HWND wnd2 = FindWindowEx(NULL, FindWindow ("#32770", "Dictionary Header Editor"), NULL, NULL);
и

Код: Выделить всё

HWND wnd2 = FindWindowEx(wnd, FindWindow ("#32770", "Dictionary Header Editor"), NULL, NULL);
Но и тогда, с убиранием этих своеобразных брейков, никакой из контролов не меняется. Чехарда какая-то...
Hawk писал(а):Если этот диалог ("Dictionary Header Editor") просто дочерний для диалога "DSL Compiler" то не должно быть никаких проблем.
Да и мне хотелось бы в это верить. Да выходит всё непонятно. Собственно говоря, программа, хэндлами которой пытаюсь управлять, находится здесь:
ftp://nich4.science.tsu.ru/Tools/Office/Lingvo6/
Нужно взять оттуда два файла:
DSLCOMP.EXE размером в 216.1K
ftp://nich4.science.tsu.ru/Tools/Office ... SLCOMP.EXE и
fobj600.dll размером в 1.1M
ftp://nich4.science.tsu.ru/Tools/Office ... OBJ600.DLL .
Hawk писал(а):А что за проблемы с комбобоксом ? Поподробнее опиши
В общих чертах, даже при таком неопределенном и неработающем хэндле компилятор ругается, мол, что вот, например, при

Код: Выделить всё

SendDlgItemMessage &#40] [quote][color=darkred] error C2065: 'IDC_COMBO' : undeclared identifier[/color] [/quote]. Однако ещё не время отлаживать управление этим комбо-боксом, пока не заработает хэндл на вышеприведенных более простых контролах. Хотя, конечно, предварительно понять свои уже существующие ошибки тут было бы неплохо.
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

У меня пишеть, что отсутствует файл анотации и отсутствует RusSyn.dsl.
А то,ч то незадефайнен 'IDC_COMBO' - ето правильно говорит, этот ID как я понимаю у тебя 1048 надо так -

Код: Выделить всё

SendDlgItemMessage (wnd2, 1048, CB_ADDSTRING, 0, (LPARAM)"Русский"); 
fallologia
Сообщения: 20
Зарегистрирован: 22 июл 2005, 12:51

Hawk писал(а):У меня пишеть, что отсутствует файл анотации и отсутствует RusSyn.dsl
Прошу прощения. Прошу не обессудить и закачать ещё дополнительно "Словарь биологических терминов" на 248 Кб специально под эту версию компилятора и с перебойной компиляцией в том числе и под ХР с http://www.lingvoda.ru/dictionaries/ind ... =left_menu. Не знаю, будет ли работать прямая ссылка, но вот и она: адрес закачки самого словаря: http://fr5.abbyy.com/LingvoDict/Biology.zip Словарь состоит в том числе из исходников (для программы компилляции нужны biology.dsl и biology.ann. В коде вместо RusSyn поставь biology. :) И... всё же как достать это оконце "Dictionary Header Editor" и перевернуть для примера все его контролы-настройки словаря на противоположные?..
Hawk писал(а): А то,ч то незадефайнен 'IDC_COMBO' - ето правильно говорит, этот ID как я понимаю у тебя 1048 надо так -
SendDlgItemMessage (wnd2, 1048, CB_ADDSTRING, 0, (LPARAM)"Русский")]
А так действительно лучше. Мелочь вот, вроде, в расположении параметров, а я и не дошел своим умом. Вот, что значит профессиональный взгляд на вещи. Что ж, теперь компилятор, по крайней мере, уже не ругается. Однако проверить, сработает ли эта функция , можно будет лишь только тогда, когда можно будет подобраться к этому второму оконцу. Почему у меня возникли сомнения о комбе-боксе?.. Среди многих программ, позволяющих определять и корректировать свойства окон приложений на лету есть, zDump с codeproject-com http://www.codeproject.com/tools/windowspy.asp Так вот, обычно она с легкостью меняет все комбо-боксы на caption, что выставишь в её окошке, а тут ни в какую... Может быть из-за того, что другие combs, в отличие от этого, являются ещё и класса edit?..
Да, а теперь самое для меня забавное. Оказывается функция
HWND wnd2 = FindWindowEx(wnd, FindWindow ("#32770", "Dictionary Header Editor"), NULL, NULL);
определяет хендл вовсе не дочернего окошка "Dictionary Header Editor", а, среди нескольких прочих, первого контрола первого окошка, который и является первой детишкой этого оконца. И caption у этого контрола... "Исходный файл:".
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

И правильно, что функция находит следующее. Советую поподробнее почитать MSDN и что означает каждый параметр.
Что у тебя неправильно -

Код: Выделить всё

    SendDlgItemMessage (wnd, 1040, BM_CLICK, 0, 0); 
SendMessage не возвращает управление программе его вызвавшей пока сообщение не будет полностью обработано. Т.е. пока оконная процедура этого DSL Compiller-а не завершит свое выполнение. А она в свою очередь делает DoModal (или DialogBox для API) для нового диалога который ты хочешь найти. А эти функции тоже не возвращают управление пока не закроется полностью диалог. Получается, что твоя программа перейдет на следующую после вызова SendDlgItemMessage (wnd, 1040, BM_CLICK, 0, 0); строчку только когда диалог уже будет закрыт. Чтобы это обойти можно воспользоваться PostMessasge, т.е. надо эту строчку заменить на -

Код: Выделить всё

    PostMessage (GetDlgItem(wnd, 1040), BM_CLICK, 0, 0); 
Дальше, нет никакой необходимости вызывать FindWindowEx, окно которое нам надо найти обычное Top Level окно и прекрасно находится с помощью FindWindow (_T("#32770"), _T("Dictionary Header Editor")). Единственная проблема тут может .snm связанна с тем, что диалог появляется не сразу после нажатия на кнопку а после какого-то времени компиляции этого словара и сразу после вызова его может ещё и не быть, по этому лучше сделать небольшое ожидание типа такого -

Код: Выделить всё

    HWND wnd2 = NULL;
	do{
		Sleep(500); // Ждем 0,5 секунды 
		wnd2 = FindWindow (_T("#32770"), _T("Dictionary Header Editor")); 
	}while (!wnd2);
Правда этот цикл потенциально может сталь бесконечным, для надежности можно ввести какой-нить счетчик, но это уже сами попробуйте.

И наконец комбобокс.

Сообщение CB_ADDSTRING добавляет ещё одну строчку в выпадающий список комбобокса. Какой смысле использовать это сообщение если тебе надо выбрать какую-то уже имеющуюся строчку ??? Выбор строчки делается сообщением -

Код: Выделить всё

    SendDlgItemMessage (wnd2, 1048, CB_SETCURSEL, 1, 0); 
fallologia
Сообщения: 20
Зарегистрирован: 22 июл 2005, 12:51

Дорогой Hawk! Спасибо за точный и простой ответ и верное решение. Всё работает. Но остаются у меня несколько теоретических недоразумений:

1. Время компиляции словаря под Виндоуз 98 занимает 17 секунд. И все это время программа терпеливо ждёт появления второго окошка. Почему? Ведь в функции

Код: Выделить всё

    HWND wnd2 = NULL; 
   do{ 
      Sleep(500); // Ждем 0,5 секунды 
      wnd2 = FindWindow (_T("#32770"), _T("Dictionary Header Editor")); 
   }while (!wnd2);
стоит всего полсекунды ожидания?..

2. Поскольку и у тебя уже есть 6 версия компилятора, не мог бы как-то обосновать его странное поведение при компилировании в среде ХР (под 98 работает без сучка-задоринки)?.. Так вот, в текстовом файле biology.dsl 7513 строк. Если статьи (от начала строки до следующей строки, которая тоже начинается без отступа) начать сокращать, то вначале сокращение файла компилятор воспринимает спокойно, затем с какой-то строчки начинает критично относиться к наличию в конце файла пустой строчки, если нет пустой строки, то выдает ошибку, и, наконец, с еще одной определенной строчки (для biology.dsl минимальное количество необходимо присутствующих под ХР строчек - всегда 2225, причем 2225-я пустая) не переносит сокращения вообще. Для каждого исходника необходимое для безошибочной компиляции количество строк разное. В то же время, под 98 компилятор без труда скомпилирует и одну статью, то есть 2 строчки. Почему так?.. Возможно, с той же причиной связано и то, что какое-то более сложное форматирование исходного для компиляции текста, легко переносимое под 98, dslcomp.exe совершенно не переносит под ХР. Есть ли возможность программно внешне как-то устранить эту странность или же она под ХР неустранима?..
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

По поводу первого вопроса - кроме полусекундного ожидания там ещё и есть цикл который проверяет есть ли окно и если нету его то снова ждед полсекунды и проверяет (do while знаем ?).

По поводу второго - незнаю, это надо разработчикам пистаь. Думаю просто у них есть какая-то ошибка, которую старые винды пропускали а ХР уже не хочет
Ответить