Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не задается текст с помощью WM_SETTEXT 
V
    Опции темы
Temdegon
Дата 2.1.2009, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.10.2008
Где: Minsk

Репутация: нет
Всего: 9



Есть "подопытная" программа - PokerStove.
http://www.pokerstove.com/
user posted image
Нужно из другой программы задать текст в окошках "Player1", "Player2" и нажать кнопку "Evalute".

Код

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "stdio.h"


#define BOARD 0
#define HAND1 1
#define HAND2 2
#define HAND3 3
#define HAND4 4
#define HAND5 5
#define HAND6 6
#define HAND7 7
#define HAND8 8
#define HAND9 9
#define HAND10 10


void setText(HWND handle, char* hand){
    SendMessage(handle, WM_SETTEXT, 0, (LPARAM)hand);
}


int main(int argc, char* argv[])
{
    RECT rc;
    HWND hwnd;
    HWND handles[20];

    bool found = false;
    char mainWindowName[] = "PokerStove - [";
    char windowName[100] = "";
    hwnd = GetDesktopWindow();
    hwnd = GetWindow(hwnd, GW_CHILD);
    //Ищем галвное окно PokerStove
    while (hwnd != 0){
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        GetWindowText(hwnd, windowName, 100);
        if (strlen(windowName) > 0 && strncmp(windowName, mainWindowName, strlen(mainWindowName)) == 0){
            //cout<<windowName<<endl;
            found = true;
            break;
        }
    }
    //если окно найдено
    if (found){

        //long style = GetWindowLong(hwnd, GWL_STYLE);//получаем стайл окна
        //SetWindowLong(hwnd, GWL_STYLE, (style^WS_VISIBLE));//делаем невидимым
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_CHILD);
        hwnd = GetWindow(hwnd, GW_CHILD);
        handles[BOARD] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND1] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND2] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND3] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND4] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND5] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND6] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND7] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND8] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND9] = hwnd;
        hwnd = GetWindow(hwnd, GW_HWNDNEXT);
        handles[HAND10] = hwnd;
        setText(handles[HAND1], "AdKs"); // Задаем текст нужных контролов (Проблема где-то здесь)
        setText(handles[HAND2], "AcJs");

        SendMessage(handles[BOARD], WM_GETTEXT, 100, (LPARAM)buffer); 
        cout<<buffer<<endl;
    } 

}


Как более грамотно добраться до хэндлов нужных мне окошек я придумать не смог, по этому решил проблему влоб. 
Проблема заключается в следующем: функция 
Код

SendMessage(handle, WM_SETTEXT, 0, (LPARAM)hand)

Срабатывает как нужно, нужный текст в окошке появляется, НО программа не работает. Если затать параметры таким образом и нажать Evalute, то ничего не происходить, как будто в полях ввода пусто. Есть один ньюанс - когда вводишь вручную текст с клавиатуры, цвет контрола меняется  на красный, если там какие-то недопустимые символы, т.е. программа обробатывает ввод пользователя на лету, а не в момент нажатия кнопки Evalute. Получается, что я задаю текст через WM_SETTEXT, но так как контрол не в фокусе или по каким-то другим причитам, программа считает что там все еще пусто. Если например после вызова WM_SETTEXT в поле добавить пробел и стереть его, то все отработает нормально. Подскажите пожалуйста, как мне выкрутиться и задать текст в контролы так, что бы программа работала нормально?
PM MAIL   Вверх
GremlinProg
Дата 2.1.2009, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Temdegon @  2.1.2009,  21:30 Найти цитируемый пост)
т.е. программа обробатывает ввод пользователя на лету, а не в момент нажатия кнопки Evalute. Получается, что я задаю текст через WM_SETTEXT, но так как контрол не в фокусе или по каким-то другим причитам, программа считает что там все еще пусто

в принципе, такое возможно, но по-моему, полностью отвязаться от данных класса EDIT врят-ли получилось , например клавиши delete, left, right, end, home и т.п. довольно непросто учитывать виртуально, поэтому, скорее всего, текст таки берется из EDIT'а, но в момент нажатия клавиш.

можно просто послать в окно WM_CHAR или сгенерировать какой-нибудь Ctrl (если обработка идет на WM_KEYxxx) сразу после WM_SETTEXT либо сгенерировать 2 символа после WM_SETTEXT: space + backspace

сгенерировать нажатия клавиш можно с помощью SendInput либо keybd_event, не забывая при этом поставить фокус ввода в EDIT

Добавлено через 2 минуты и 32 секунды
лучше генерировать end + space + backspace, чтобы не затирать ввод после SetWindowText


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Temdegon
Дата 2.1.2009, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.10.2008
Где: Minsk

Репутация: нет
Всего: 9



Решил проблему. Перед посылкой сообщения WM_SETTEXT, делаю WM_SETFOCUS для того же хэндла и все работает как нужно. 
Параллельно в тему вопрос по хэндлам контролов. Они назначаются как-то всегда одинаково? могу ли я хардкодом забить хэндлы контролов и потом использовать? или они всегда будут отличаться? А то код получения нужных мне хэндлов выглядит страшно громоздко и некрасиво. Возможен ли такой вариант, через findFindow, я буду получать хэндл главного окна, а потом прибавлять к нему какие-то заранее расчитанные смещения для полученя хэндлов дочерних кнотролов? Или такие "смещения" могут отличаться от запуска к запуску?

Это сообщение отредактировал(а) Temdegon - 2.1.2009, 23:51
PM MAIL   Вверх
GremlinProg
Дата 2.1.2009, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Temdegon @  3.1.2009,  01:48 Найти цитируемый пост)
Они назначаются как-то всегда одинаково? могу ли я хардкодом забить хэндлы контролов и потом использовать? или они всегда будут отличаться?

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


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Temdegon
Дата 3.1.2009, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.10.2008
Где: Minsk

Репутация: нет
Всего: 9



user posted image
(Скрин из Microsoft Spy++)
Вы имеете ввиду это?
А можно ли как-то получить хэндл имея этот ID? или нужно перебрать все дочерние окна и проверять их ID? Проблема в том, что приложение имеет достаточно сложную древовидную структуру, и я слабо себе представляю, как обойти все дочерние окна. Может есть какой-то уже готовый алгоритм обхода всех дочерних окон любой вложенности? Быстрый поиск в гугле ничего подходящего не дал. Дело в том, что весь этот код будет засунут в DLL в виде одной функции и вызываться из Java. Т.е. будет функция, принимающаяя несколько строк в  качестве аргументов, она будет засовывать их в нужные Edit-ы, нажимать кнопку запуска расчета, забирать готовый результат и возвращать его в Java-код. Сам расчет, выполняемых этой программой достаточно сложный и быстрым его назвать никак нельзя, не хотелось бы при каждом запуске этой функции заново по-кривому обходить все дочерние окна только что бы узнать их хэндлы, и тратить на это процессорное время. Но технология запуска native-кода из java не позваляет сохранить где-то хэндлы, полученные при первом запуске, и использовать их при повторном запуске функции. По этому хотелось бы добиться максимальной простоты и скорости в обходе дочерних окон? Может есть функция, которая по ID вернет хэндл окна?
PM MAIL   Вверх
GremlinProg
Дата 3.1.2009, 00:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Temdegon @  3.1.2009,  02:14 Найти цитируемый пост)
(Скрин из Microsoft Spy++)Вы имеете ввиду это?

да, это и есть идентификатор окна
Цитата(Temdegon @  3.1.2009,  02:14 Найти цитируемый пост)
Может есть функция, которая по ID вернет хэндл окна?

да, есть: GetDlgItem
первым аргументом ей нужно указать дескриптор корневого родительского окна
вторым - идентификатор для поиска
на счет любой вложенности - не уверен, но вроде бы GetDlgItem в глубину тоже ищет, если не находит на текущем уровне


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Temdegon
Дата 3.1.2009, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.10.2008
Где: Minsk

Репутация: нет
Всего: 9



Спасибо за помощь и быстрое реагирование! Почитаю про эту функцию и буду экспериментировать. К сожелению, не могу выразить благодарность в более актуальной форме, ибо недостаточно постов =(

Вроди как в глубину она не ищет, но все равно, это сильно упрощает получение хэндлов.

Это сообщение отредактировал(а) Temdegon - 3.1.2009, 01:05
PM MAIL   Вверх
Earnest
Дата 6.1.2009, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(Temdegon @  3.1.2009,  01:44 Найти цитируемый пост)
Вроди как в глубину она не ищет

Точно не ищет, но при известной глубине вложенности это не проблема.
Цитата(Temdegon @  3.1.2009,  01:44 Найти цитируемый пост)
 К сожелению, не могу выразить благодарность в более актуальной форме, ибо недостаточно постов =(

Я выразила за тебя smile 


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0545 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.