Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Открытие окна и нажатие в нём кнопки


Автор: KaraKum 8.1.2008, 09:39
Доброе время суток.
Нужно, отправляя окну "MainWnd" сообщение, открыть новое окно "Optimum". Затем дочернему окну "OKButton" окна "Optimum" отправить сообщения о нажатии кнопки, тем самым закрывая окно "Optimum". Вот код:
Код

HWND hMainWnd = ::FindWindow(NULL, "MainWnd");
                                //отправка сообщения открытия окна "Optimum"
    ::SendMessage(hMainWnd, 0xC1F4, 0x0000000E, 0x01E11910); 

    HWND hOptimumWnd = ::FindWindow(NULL, "Optimum");
        //нажатие кнопки "ОК"
    HWND hOKWnd = ::FindWindowEx(hOptimumWnd, NULL, NULL, "ОК");
    ::SendMessage(hOKWnd, 0x0201, 0x00000001, 0x000c0021);
    ::SendMessage(hOKWnd, 0x0202, 0x00000000, 0x000c0021);

Всё работает, но только по-отдельности. То есть, если окно "Optimum" ещё не открыто, то оно только открывается первой частью кода, а кнопка "ОК" не нажимается, а если окно "Optimum" уже открыто, то открывается ещё одно окно "Optimum", а в уже открытом нажимается кнопка "ОК".
Пробовал между двумя частями кода вставлять такой код:
Код

while(::FindWindow(NULL, "Optimum") == 0)
{
     Sleep(1000);
}

но прога виснет - наверное так и не получается найти такое окно.
Подскажите, пожалуйста, что не так?

Автор: JackYF 8.1.2008, 12:08
KaraKum, ты разделом ошибся, общие вопросы ни при чём. Тебе в "Системное программирование и WinAPI".

Автор: KaraKum 8.1.2008, 12:56
Цитата(JackYF @ 8.1.2008,  12:08)
KaraKum, ты разделом ошибся, общие вопросы ни при чём. Тебе в "Системное программирование и WinAPI".

Заголовок форума: "Форум: C/C++: Системное программирование и WinAPI".
Так куда же?

Автор: JackYF 8.1.2008, 12:59
Цитата(KaraKum @  8.1.2008,  11:56 Найти цитируемый пост)
Так куда же? 

уже перенесли smile

Автор: KaraKum 8.1.2008, 13:51
Цитата(JackYF @ 8.1.2008,  12:59)
Цитата(KaraKum @  8.1.2008,  11:56 Найти цитируемый пост)
Так куда же? 

уже перенесли smile

А  smile .
Ну так жду ответа...

Автор: EnergoHokum 8.1.2008, 17:54
Во всех функциях, где может произойти ошибка (у тебя -- FindWindow  и SendMessage), нужно делать проверку на эту ошибку. Если ошибка случилась, то вызови GetLastError, она отдаст код ошибки, а там уже можно посмотреть, на чём у тебя программа споткнулась. Подробнее -- завтра, я счас не на винде.

Автор: KaraKum 9.1.2008, 21:41
Такая ошибка:
"ERROR_INVALID_WINDOW_HANDLE
1400 Invalid window handle. "
Это, вероятно, всвязи с тем, что сообщения отправляются окну по нулевому указателю (этот указатель я записываю в файл).
У меня этот код активируется при нажатии на кнопку в программе, так вот проблема в том, что если окно "Optimum" программы "MainWnd" ещё не открыто, то оно открывается, а по следующим строкам кода указатель на это окно не находится (в файл записывается нулевой указатель), а если окно уже открыто (часть кода, отправляющую сообщение открытия окна, при этом, нужно убирать), то выполняется нажатие кнопки "ОК" в окне "Optimum", что и требуется.
Но нужно, чтобы всё выполнялось за один раз.
Скажите, плиз, что не так?

Автор: ama_kid 10.1.2008, 12:10
KaraKum, а ты между строками ::SendMessage(hMainWnd, 0xC1F4, 0x0000000E, 0x01E11910);  и HWND hOptimumWnd = ::FindWindow(NULL, "Optimum"); не пробовал задержку вставить? У меня стойкое ощущение, что окно Optimum просто не успевает открыться к тому моменту, когда ты запрашиваешь его хендл...

Автор: KaraKum 10.1.2008, 17:10
Цитата(KaraKum @ 8.1.2008,  09:39)
Код

while(::FindWindow(NULL, "Optimum") == 0)
{
     Sleep(1000);
}

но прога виснет - наверное так и не получается найти такое окно.
Подскажите, пожалуйста, что не так?

Сначала пробовал простую задержку ставить - ничего. А потом и эту поставил - прога так и не заканчивает своё выполнение, видимо этот цикл всегда выполняется.
Так и не работает...

Автор: ama_kid 10.1.2008, 20:10
KaraKum, 
накидал тестовый проект (Win32), который делает нужную тебе вещь (по крайней мере - как я понял) - посмотри, сравни со своим, может и найдешь ошибку, так гадать можно долго...
Описание: есть дополнительное окошко About - если его выбирать из меню - оно появляется как положено и убирается по кнопке Ok, если нажать кнопку на окне - тогда это окошко появится и через секунду программно нажмется кнопка Ok, вызвав закрытие окна. Если нажать кнопку, когда окно About открыто - то через секунду закроется текущее окно без создания нового

Автор: KaraKum 11.1.2008, 05:44
Открыть файл не получилось - версия визуалки не совпадает, но, как я видел, принцип почти тот же:
Код

if (hAboutBox==NULL) 
{
    SendMessage(hWnd_Global,WM_COMMAND,IDM_ABOUT,0);
    Sleep(500);
    hAboutBox = FindWindow(NULL,"About");
}

И я переделал на:
Код

::SendMessage(hMainWnd, 0xc1c4, 0x0000000E, 0x01ed2f98); //открытите окна "Optimum"
HWND hOptimumWnd = NULL;
while(hOptimumWnd == 0)
{
                Sleep(1000);
    hOptimumWnd = ::FindWindow(NULL, "Optimum");
}
HWND hDialogWnd = ::FindWindowEx(hOptimumWnd, NULL, NULL, "OK");

Так и не работает.
Попробовал сымитировать клики мыши через SendInput(): такой код:
Код

INPUT clicks[2];
clicks[0].type = INPUT_MOUSE;
clicks[0].mi.dx = 5695;
clicks[0].mi.dy = 21930;
clicks[0].mi.mouseData = NULL;
clicks[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
clicks[0].mi.time = NULL;
clicks[0].mi.dwExtraInfo = NULL;

после компиляции появились ошибки и одна из них:
235: error C2065: 'INPUT' : undeclared identifier
но при наведении указателя мыши на "INPUT" высвечивается умная надпись: "typedef tagINPUT INPUT".
Что не так?

Автор: ama_kid 11.1.2008, 08:04
KaraKum, выложи свой проект (максимально обрезанный, но чтобы ошибка наблюдалась), посмотрим...
Цитата(KaraKum @  11.1.2008,  05:44 Найти цитируемый пост)
версия визуалки не совпадает
какая у тебя?

Автор: KaraKum 11.1.2008, 11:29
Цитата(ama_kid @ 11.1.2008,  08:04)
KaraKum, выложи свой проект (максимально обрезанный, но чтобы ошибка наблюдалась), посмотрим...
Цитата(KaraKum @  11.1.2008,  05:44 Найти цитируемый пост)
версия визуалки не совпадает
какая у тебя?

Your project file version is '7.10'. Visual Studio .NET can only load version '7.0' project files.
Version 7.0.9466/Version 7.0.3705

Тот же код, что и у меня, только для калькулятора:
Код

//открытие помощи в калькуляторе и сохранения указателя в файле
HWND hCalcWnd = ::FindWindow("SciCalc", NULL);
::SendMessage(hCalcWnd, 0x004d, 0x00000000, 0x00000000); //отправка сообщения о нажатии F1
HWND hHelpWnd = NULL;
while(hHelpWnd == 0)
{
     Sleep(200);
     hHelpWnd = ::FindWindow("HH Parent", NULL);
}
ofstream labFile("labFile.txt");
labFile << hHelpWnd << endl;
labFile.close;

Всё работает, в файл записывается правильный указатель. Но если использовать такой же код в моём случае, то окно открывается, но указатель не находится, но если окно уже открыто (при этом нужно удалить часть кода, ответственную за открытие окна), то выполняется всё, что нужно: и указатель записывается в файл и кнопки нужные нажимаются (как дочерние окна).
Скорее всего проблема тут не в коде, а в программе. Не пойму с чем это связано, но, например, для отправки сообщения об открытии окна "Optimum" каждый раз приходится искать сообщение в Spy++ - оно почти всегда разное и ещё программа on-line.
Думаю, что так ничего и не выйдет, поэтому хочу нажать нужные кнопки, исользуя функцию SendInput(), но не могу определить переменную типа INPUT, ошибка при компиляции:
235: error C2065: 'INPUT' : undeclared identifier.
В чём здесь ошибка?

Автор: ama_kid 11.1.2008, 12:10
Цитата(KaraKum @  11.1.2008,  11:29 Найти цитируемый пост)
А почему, всё-таки, не получается определить переменную типа INPUT? 
Код
#if (_WIN32_WINNT > 0x0400)
...
typedef struct tagINPUT {
    DWORD   type;

    union
    {
        MOUSEINPUT      mi;
        KEYBDINPUT      ki;
        HARDWAREINPUT   hi;
    };
} INPUT, *PINPUT, FAR* LPINPUT;
...
#endif // (_WIN32_WINNT > 0x0400)
проверь значение макроса _WIN32_WINNT

Цитата(KaraKum @  11.1.2008,  11:29 Найти цитируемый пост)
Visual Studio .NET can only load version '7.0' project files.
Я обычно в таких случаях просто вручную меняю версию проекта в vcproj-файле... Или создаю новый проект с таким же именем и просто заменяю *.cpp и *.h - файлы...

Автор: KaraKum 11.1.2008, 12:17
Цитата(ama_kid @ 11.1.2008,  12:10)
Цитата(KaraKum @  11.1.2008,  11:29 Найти цитируемый пост)
А почему, всё-таки, не получается определить переменную типа INPUT? 
Код
#if (_WIN32_WINNT > 0x0400)
...
typedef struct tagINPUT {
    DWORD   type;

    union
    {
        MOUSEINPUT      mi;
        KEYBDINPUT      ki;
        HARDWAREINPUT   hi;
    };
} INPUT, *PINPUT, FAR* LPINPUT;
...
#endif // (_WIN32_WINNT > 0x0400)
проверь значение макроса _WIN32_WINNT

У меня в файле winable.h:
Код

#if (_WIN32_WINNT < 0x0403) // these structures and this function prototype are in NT 4.03 and above winuser.h
...
typedef struct tagINPUT {
    DWORD   type;

    union
    {
        MOUSEINPUT      mi;
        KEYBDINPUT      ki;
        HARDWAREINPUT   hi;
    };
} INPUT, *PINPUT, FAR* LPINPUT;
...
#endif // (_WIN32_WINNT < 0x0403)

что-то не так?

Автор: ama_kid 11.1.2008, 12:33
Цитата(KaraKum @  11.1.2008,  12:17 Найти цитируемый пост)
что-то не так?
Цитата
winuser.h

Короче, попробуй в файле stdafx.h закомментировать строку 
Код
#define WIN32_LEAN_AND_MEAN
и добавить 
Код
#define _WIN32_WINNT 0x0500
 - должно заработать


Автор: KaraKum 11.1.2008, 12:57
У меня там была только строка
Код

#include "stdafx.h"

Я добавил строку
Код

#define _WIN32_WINNT 0x0500

но ничего не изменилось - та же ошибка...

Автор: ama_kid 11.1.2008, 13:06
Цитата(KaraKum @ 11.1.2008,  12:57)
У меня там была только строка
Код

#include "stdafx.h"

Я добавил строку
Код

#define _WIN32_WINNT 0x0500

но ничего не изменилось - та же ошибка...

кажись я намекал, что смотреть надо не в stdafx.cpp, а в stdafx.h...  smile 

Автор: KaraKum 11.1.2008, 13:18
Цитата(ama_kid @ 11.1.2008,  13:06)
кажись я намекал, что смотреть надо не в stdafx.cpp, а в stdafx.h...  smile

точно  smile .
Добавил строку в stdafx.h - тоже не работает...

Автор: ama_kid 11.1.2008, 14:08
Цитата(KaraKum @  11.1.2008,  13:18 Найти цитируемый пост)
Добавил строку в stdafx.h - тоже не работает... 
добавить, ессно, надо перед строкой
Код
#include <windows.h>


Автор: KaraKum 11.1.2008, 16:27
Цитата(ama_kid @ 11.1.2008,  14:08)
Цитата(KaraKum @  11.1.2008,  13:18 Найти цитируемый пост)
Добавил строку в stdafx.h - тоже не работает... 
добавить, ессно, надо перед строкой
Код
#include <windows.h>

У меня такой строки в файле stdafx.h нет, но я просто добавил в самое начала файала и всё заработало.
Спасибо за помощь!  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)