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


Автор: kapbepucm 20.9.2007, 16:22
Окно сторонней программы с кучей кнопок. Надо Handle конкретной кнопки получить. Знаю расположение, надпись "Start" и кнопка активна (Enter'ом сразу нажимается).
Пробывал разные способы, но получил только Handle родительского окна. Может кнопка просто нарисована? Подскажите что-нибудь.

Автор: zkv 20.9.2007, 16:36
посмотри спаем (spy++ в составе VS) ID кнопки, через него и дотягивайся

Автор: Alexeis 20.9.2007, 17:39
kapbepucm, Так FindWindow и ищет только родительские окна. 

Цитата

To search child windows, beginning with a specified child window, use the FindWindowEx function.

Автор: NikeDeForest 20.9.2007, 18:32
Я делал глобальный хук на правую кнопку мыши и щелкал над необходимым мне элементом чужого приложения

Автор: Alexeis 20.9.2007, 19:02
NikeDeForest, Ну это примерно как пушкой по воробьям smile . 

Автор: Mihhail 20.9.2007, 21:27
Цитата(kapbepucm @  20.9.2007,  20:22 Найти цитируемый пост)
Окно сторонней программы с кучей кнопок. Надо Handle конкретной кнопки получить. Знаю расположение, надпись "Start" и кнопка активна (Enter'ом сразу нажимается).Пробывал разные способы, но получил только Handle родительского окна.

Если известен Handle родительского окна, перебираем дочерние окна и проверяем надписи на них.
Код

HwSt = GetWindow( Handle, GW_CHILD );
while( HwSt ){
   GetWindowText( HwSt, str, max );
   if( !strcmp( str, "Start" ) ) break;
   HwSt = GetNextWindow( HwSt, GW_HWNDNEXT );
   }
if( HwSt ) ...... //Найдено нужное  


Если известны примерные координаты кнопки можно воспользоваться функцией:
HWND ChildWindowFromPoint(
    HWND hWndParent,    // handle to parent window
    POINT Point               // structure with point coordinates
   );

Автор: kapbepucm 21.9.2007, 08:06
Спасибо, сейчас попробую!

Автор: NiJazz 21.9.2007, 09:04
http://forum.vingrad.ru/forum/topic-170520/anchor-entry1242772/0.html

Автор: kapbepucm 21.9.2007, 12:56
А есть хороший програмный способ узнать HWND дочернего окна, незная HWND родителя но зная заголовок? Например хочу увидеть все кнопки "OK".

Автор: Alexeis 21.9.2007, 13:19
  По крайней мере можно найти все окна и пройтись по всем дочерним компонентам...

Автор: NikeDeForest 21.9.2007, 18:22
Alexeis, мне так проще показалось smile

Автор: Alexeis 21.9.2007, 20:24
NikeDeForest, так я не с точки зрения простоты, а с точки зрения нагрузки на систему.

Автор: kapbepucm 2.10.2007, 16:23
Цитата(Alexeis @  21.9.2007,  13:19 Найти цитируемый пост)
По крайней мере можно найти все окна и пройтись по всем дочерним компонентам...
Не могу нигде пример найти... Задача: есть форма чужого процесса с кучей кнопок (явно дочки). Есть несколько кнопок "OK". Мне надо знать HWND всех этих кнопок. Покажите алгоритм пробега по дочкам. Уже, наверно, самостоятельно не справлюсь...
smile smile smile 

Автор: Alexeis 2.10.2007, 16:53
kapbepucm, так Mihhail в своем уже показал перебор дочерних компонентов. 

Автор: kapbepucm 3.10.2007, 07:56
Странно, но данным примером я нахожу первую дочку и больше ничего... Может есть способ иначе действующий?

Автор: SenkraD 3.10.2007, 08:16
kapbepucm,  вот кусок кода с Архангельского по Builder но всё кроме вывода API:
Код

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UChildWin1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// для варианта поиска окна редактирования
AnsiString S = "Edit";
HWND hEdit;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
char buf[256], buf2[256];

bool __stdcall EnumChild(HWND hWind, LPARAM lParam)
{
 SendMessage(hWind, WM_GETTEXT, sizeof(buf), (LPARAM)(LPCTSTR)buf);
 GetClassName(hWind,buf2,sizeof(buf2));
 Form1->Memo1->Lines->Add(AnsiString(buf) + " - класс " + AnsiString(buf2));
// для варианта поиска окна редактирования
/* if(AnsiString(buf2) == *(AnsiString *)lParam)
 {
  hEdit = hWind;
  return false;
 }*/
 return true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
 HWND hWnd;
 // получение дескриптора окна
 if(! (hWnd = FindWindow("SciCalc","Калькулятор")))
 {
  WinExec("Calc", SW_SHOWNA);
  hWnd = FindWindow("SciCalc","Калькулятор");
 }
 // получение списка дочерних окна
 EnumChildWindows(hWnd, (WNDENUMPROC)EnumChild, 0);
 // для варианта поиска окна редактирования
 //EnumChildWindows(hWnd, (WNDENUMPROC)EnumChild, (LPARAM)&S);
 // получение списка разделов меню
 HMENU HM = GetMenu(hWnd);
 HMENU SubM = NULL;
 int CountM = GetMenuItemCount(HM);
 int CountS;

 for(int i = 0; i < CountM; i++)
 {
  GetMenuString(HM, i, buf, sizeof(buf), MF_BYPOSITION);
  Memo2->Lines->Add(buf);
  if(SubM = GetSubMenu(HM, i))
  {
   CountS = GetMenuItemCount(SubM);
   for(int k = 0; k < CountS; k++)
   {
    GetMenuString(SubM, k, buf, sizeof(buf), MF_BYPOSITION);
    Memo2->Lines->Add("   " + AnsiString(buf));
   }
  }
 }
}
//---------------------------------------------------------------------------


Автор: kapbepucm 3.10.2007, 13:54
Попытасля поработать с калькулятором- всё работает идеально (все дочки видны). Но если перейти к моей сторонней форме, то средствами EnumChildWindows или GetWindow нахожу только одну дочку без заголовка с каким-то классом Container60000000. Некоторое время назад комплекс VS потерпел у меня крах (по независящим от меня обстоятельствам пока не имею возможности это исправить), поэтому не могу пользоваться SPY++. Как поступать дальше?
NikeDeForest, по-подробнее расскажи как пушкой по воробьям, что-то даже это направляет меня к одной и той-же дочке...

Автор: Earnest 3.10.2007, 16:29
Скорее всего, форма и содержит одно окно-контейнер, а все кнопки - уже в нем.
Проверь это дело с помошью Спая.
И ищи не конкретно в данном окне, а в этой самой дочке.
Кстати, вложенность может быть и глубже...

Автор: NikeDeForest 3.10.2007, 19:20
запуск хука
Код

 hModule=::LoadLibrary("OnClick.dll");                  
                        uk=(return_hw*)::GetProcAddress((HMODULE)hModule,"return_hw");
                       (uk)(true,hInst,hWnd);


остановка хука
Код

uk(false,hInst,hWnd);
                    FreeLibrary(hModule);
                    break;



сама длл с хуком

Код


HWND hw_client; //здесь будет хендл окна
HHOOK hHOOK;

HINSTANCE hInst;
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    hw_client=0;
    
    hInst=HINSTANCE(hModule);
    return TRUE;
}


//функция перехватчик сообщения
LRESULT CALLBACK CatchMessage(int code, WPARAM wParam, LPARAM lParam)
{


LONG tempHook=CallNextHookEx(hHOOK,code,wParam,lParam);

if(code==HC_ACTION)
{
    {
          //здесь хендл окна над которым был щелчек
       hw_client=((tagMSG*)lParam)->hwnd; 
       
    }
}
if(code<0)
return tempHook;

return 0;
}



// Эксопортируемая функция, возвращающая хендл окна
DllExport void  __stdcall return_hw(bool State, HINSTANCE hInstance)
{
    if(State==true)
    {
      hHOOK=SetWindowsHookEx(WH_GETMESSAGE, &CatchMessage,hInst,0);
    }
    else
        UnhookWindowsHookEx(hHOOK);

    
}




Это по сути пример, переделанный из книги "С++ глазами хакера". Если есть эта книга, то туда глянь. Там в том числе и описано то, что тебе здесь уже предлагали - пробежать все окна (в том числе дочерние).

Автор: NikeDeForest 3.10.2007, 19:48
Вот, это будет для тебя более фундаментально и полезно http://www.rsdn.ru/article/baseserv/hookdll.xml

Автор: kapbepucm 25.10.2007, 08:32
Приветствую, это опять я. "Допрашивая" спая, удалось выяснть как там всё устроено. Как Earnest говорил, там многоуровневая вложеность. Теперь задача несколько поменялась. Мне надо пройтись от дочки до "первого" родителя. Подскажите, как это можно реализовать, изначально зная только HWND.

Автор: Andrey44 26.10.2007, 09:02
Цитата

Как Earnest говорила smile 


Изначально зная HWND чего?

Если кнопки то GetParent(hwnd) и так далее до главного окна.

Автор: kapbepucm 26.10.2007, 13:28
Русский язык допускает обращаться к неопределённому лицу как к лицу муж. рода smile
А по делу, GetParent- это первое, что я испытывал; так я получал 0 в ответ smile. Потому и спрашиваю, может что ещё есть. 

Автор: Andrey44 26.10.2007, 13:56
Подожди, а зачем тебе зная HWND кнопки получать HWND родителя? smile 

Автор: kapbepucm 26.10.2007, 14:13
Хочу понять, почему то, что умеет спай, не могу реализовать я (стандартными функциями API). Собственоручно выяснил, что у главного родителя нет детей, а у дочерней кнопки нет родителя- так спай имеет другое (я думаю он прав) мнение. Что за $$$$$? На стандартном виндовском калькуляторе всё получается smile

Автор: Andrey44 26.10.2007, 15:01
 smile Не понял, так что, кнопка сама по-себе живет?

Автор: kapbepucm 26.10.2007, 16:02
Судя по тому, что GetParent говорит, да smile

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