Russian Qt Forum
Октябрь 01, 2024, 16:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Помогите пожалуйста обратиться к окну  (Прочитано 7150 раз)
linuxoid
Гость
« : Октябрь 11, 2007, 15:33 »

Ситуация следующая: я в QProcess выполняю команду вследствии которой открывается окно с программой. Так вот как мне обратиться к этому окну в событии???
Я хочу передать при нажатии на кнопку в своём виджете исскуственное событие нажатия клавиши клавиатуры, а чтобы это сделать мне нужно как-то обратиться к нему!Может быть есть какое-нить событие перехватывающее появление нового окна?помогите чем кто может пожалуйста!
Записан
Steven_Orko
Гость
« Ответ #1 : Октябрь 11, 2007, 15:54 »

Никак. То, что ты хочешь сделать, можно только с помощью платформо-зависимых средств. Посмотри доки по оконным менеджерам и т.д. и т.п. В для Windows - findWindow по имени окна, в Linux XQueryTree и просматриваешь атрибуты окна.
Записан
linuxoid
Гость
« Ответ #2 : Октябрь 12, 2007, 08:01 »

а сигналов случаем нету для такого дела?
Записан
Steven_Orko
Гость
« Ответ #3 : Октябрь 12, 2007, 08:43 »

Используя QProcess, ты запускаешь НОВЫЙ процесс.

1. Для того, чтобы один процесс что-то сообщил другому, необходимо использовать DCOP или DBus (Возможен вариант самописного механизма обмена). Совсем не обязательно, что разработчик программы, чей процесс ты пытаешься запустить, вообще знаешь о таких вещах. Возможно они появились позже момента создания программы.
2.
Для получения сообщения тебе в своей программе также необходима привязка к DCOP или DBus. Это у тебя есть?
3. Ну и предпоследнее. Откуда постороннему процессу знать, что ты хочешь получить от него сообщение о появлении окна? И какого именно окна? Верно, не знает.
4. Если говорить о QProcess, то класс слишком разрастется, если в него еще добавить распознавание, что за процесс запускается: с GUI или без.

Вот такими рассуждениями приходим к выводу, что сигнала специального нет.

Как я уже говорил, тебе надо просто после запуска процесса перебрать все созданные окна на предмет наличия окна запускаемого процесса. Название окна ты ведь знаешь. Сравнишь, получишь  какой-нибудь UID или HANDLE окна. Ну а дальше уже посылай ему сообщения. Все это делается только платформо-зависимыми средствами. Для Linux тебе придется использовать Xlib, для винды не помню имя либы, но по названию функции FindWindow в MSDN найдешь ее описание.
Тут уже как тебе будет легче. Если для одной платформы, то ее и используй, если для двух, то условная компиляция тебе в руки. )))
Записан
Emc
Гость
« Ответ #4 : Октябрь 12, 2007, 14:16 »

ну можно слушать standardOutput - а при открытие окна выдавать спец сообщение (winId например), а потом QWidget::find ( WId id )
Записан
T800
Гость
« Ответ #5 : Октябрь 17, 2007, 13:07 »

Ну если пошла такая пьянка, то для общения между процессами (даже между разными программами на одной машине) можно и TCP/IP-стек использовать. А вот если хочется имитировать именно ввод с клавиатуры, то придется использовать платформу.
Записан
linuxoid
Гость
« Ответ #6 : Октябрь 19, 2007, 09:43 »

НУ спасибо люди добрые!Вы меня конечно не обрадовали, но информации вполне достаточно для продвижения!С П А С И Б О!
Записан
linuxoid
Гость
« Ответ #7 : Октябрь 19, 2007, 16:29 »

Чё то я никак не могу продвинуться может будут у кого ещё какие нить соображения Непонимающий
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #8 : Октябрь 22, 2007, 22:43 »

та вторая прога тоже твоя?
или нет?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
linuxoid
Гость
« Ответ #9 : Октябрь 23, 2007, 13:31 »

НЕД
Записан
Steven_Orko
Гость
« Ответ #10 : Октябрь 23, 2007, 17:28 »

Рассказываю, как это можно сделать под Линукс описанным мною выше способом, ибо под Винду щас ничего не пишу.

Часть 1.
1. Запускаешь ту программу, в окно которой тебе надо послать сообщение.
2. Смотришь название окна.

Часть вторая.
Существует несколько спецификация для оконных менеджеров. Некоторые оконные менеджеры могут вообще ее не поддерживать. Однако, исторически склалось, что в Линуксе окно имеет несколько атрибутов. Один из аттрибутов - это как раз то самое название окна, которое ты видишь на экране в полосочке наверху.
Читаем XLIB Reference Manual и видим, что за получение значения этого аттрибута отвечает функция

Status XFetchName(Display *display,  Window w, char **window_name_return).
Первый параметр - это структура дисплея, которую ты можешь получить через qt_xdisplay() (Qt 3 series).
Второй параметр - это идентификатор окна, у которого надо подсмотреть название.
В третий параметр возвращается само название. Только фигня в том, что эта строка может быть в разных форматах.
Так, например, если название только из латинских букв, то это будет обычный string, если там есть национальные буквы, то это будет скорее всего COMPOUD_STRING, если не ошибся с написанием типа.

Часть 3.
Как я уже говорил про спецификации для оконных менеджеров, их много. Но есть одна спецификация, которой стараются придерживаться KDE и Gnome, - это icccm. Причем есть несколько версий, на данный момент последняя 2 с хвостиком.
Также на сайте KDE можно найти спецификацию для их оконного менеджера, в которой уже есть новый атрибут у окна, содержащий его название, причем в UNICODE, что несколько облегчает жизнь. Причем, там же упоминается, что, если этот новый атрибут окна существует, то надо использовать именно его. Я считываю его таким образом:

Код:
int iCount = 0;
Atom atom_NET_WM_NAME = XInternAtom(qt_xdisplay(), "_NET_WM_NAME", false);
Atom* pAtoms = XListProperties(qt_xdisplay(), wID, &iCount);

bool bExist = false;
for (int iIndex = 0; iIndex < iCount; ++iIndex)
{
if (pAtoms[iIndex] == atom_NET_WM_NAME)
{
bExist = true;
break;
}
}

if (bExist)
{
std::vector<unsigned char> propertyValue = charProperty(atom_NET_WM_NAME, wID);
return toTypeUTF8_STRING(propertyValue);
} else
{
QString strWM_NAME;
char *cName;
Status retCode = XFetchName(qt_xdisplay(), wID, &cName);
strWM_NAME = cName;
if (0 != retCode) XFree(cName);
return strWM_NAME;
}

Часть 4.
Тебе надо перебрать все открытые окна, на премет нахождения того, которое тебе надо. Я в своей недоделанной проге делаю так:
Код:
Window* lstChldWindow; //Массив дочерних окон корневого окна
unsigned int iCountChildWindow;   //Количество элементов в массиве
//Получаю массив дочерних окон корневого окна
Status iResult = XQueryTree(qt_xdisplay(), static_cast<Window>(wID), &rootWindow, &parentWindow, &lstChldWindow, &iCountChildWindow);

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

Код:
XWindowAttributes attrWnd;
XGetWindowAttributes(qt_xdisplay(), wID, &attrWnd);
Здесь все просто:
Первый параметр - указатель на структуру дисплея.
Второй - идентификатор окна,
Третий - указатель на структуру аттрибутов окна.

Ремарка. Сорри, возможно я тебя запутал. На самом деле, имя окна и другая инфа - это свойства окна, а вот аттрибуты - это было только что выше.

Часть 5.
Тут ты уже имеешь идентификатор окна, которое тебе надо. Осталось послать ему событие. Для этого Xlib тоже имеет необходимые функции:

Код:
XSendEvent(Display* display, Window w, Bool propagate, long event_mask, XEvent* event_send);


typedef struct {
        int type;
        unsigned long serial;
        Bool send_event;
        Display *display;
        Window window;
        Atom message_type;
        int format;
        union {
                 char b[20];
                 short s[10];
                 long l[5];
              } data;
} XClientMessageEvent;


Часть заключительная.
В итоге, то самое стороннее окно получит событие от сервера X, как если бы это событие породил пользователь. Вот и все. Тебе осталось почитать маны по Xlib, и у тебя все получится.

Чтобы это сделать для Винды, попроси еще кого-нибудь. Но алгоритм все равно тот же: найти окно, послать ему сообщение средствами платформы (в данном случае Винды).


P.S. Орфографию не проверяю, т.к. уже уходить надо. Удачи.

Записан
Tonal
Гость
« Ответ #11 : Октябрь 24, 2007, 06:44 »

Да, для винды примерно так же.
FindWindow - поиск по имени или классу (можно подсмотреть Spy++ или подобными утилитами)
И посылка нужного сообщения.

Кроме того, есть функции для эмуляции действий мыши или клавиатуры.
Записан
linuxoid
Гость
« Ответ #12 : Октябрь 24, 2007, 08:49 »

ну спасибо Дружище!!о таком подробном ответе можно было только мечтать) Теперь есть от чего оттолкнуться!Обращайся если нужно будет помочь Подмигивающий
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 23.