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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> отлов WM_CLOSE в длл 
V
    Опции темы
12usver12
Дата 23.4.2010, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Есть оконная прога, которая динамически подключает длл , в длл реализованы функи и код DllMain , каким образом в длл отловить(перехватить) сообщение WM_CLOSE  например, посланное этой проге ? 
PM MAIL   Вверх
GremlinProg
Дата 23.4.2010, 13:16 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(12usver12 @  23.4.2010,  15:12 Найти цитируемый пост)
каким образом в длл отловить(перехватить) сообщение WM_CLOSE  например, посланное этой проге ? 

используй сабклассинг и перехватывай все что хочешь


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


Эксперт
****


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

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



Или hook.


--------------------
...
PM   Вверх
GremlinProg
Дата 23.4.2010, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



кстати, только заметил: название темы не соответствует ее описанию, процесс не чужой,
убираю "в контексте другого процесса"?


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


Бывалый
*


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

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



Код

LRESULT CALLBACK xWndProc( HWND hwnd, UINT uMsg,  
                         WPARAM wParam, LPARAM lParam ) 
{ 

    switch(uMsg) 
    { 
        OutputDebugStringA("loop");
    case WM_DESTROY : {OutputDebugStringA("WM_DESTROY "); PostQuitMessage( 0 ); }break; 
    case WM_CLOSE :  { OutputDebugStringA("WM_CLOSE");Sleep(2000); CloseHandle(CreateFile("M:\\work.txt",GENERIC_WRITE|GENERIC_READ,1|2,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));}
    default : return DefWindowProc( hwnd, uMsg, wParam, lParam ); 
    } 
    return 0; 
} 
HINSTANCE h_inst = 0;
DWORD WINAPI MonitorThread(LPVOID lpParam)
{
    HINSTANCE hInstance = h_inst;
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = xWndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = "test";
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

    if (!RegisterClassEx(&wcex))
    {
        MessageBox(NULL,
            "Call to RegisterClassEx failed!",
            "Win32 Guided Tour",
            NULL);

        return 1;
    }
    HWND hWnd = CreateWindow(
        "test",
        "test",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 100,
        NULL,
        NULL,
        hInstance,
        NULL
        );
    ShowWindow(hWnd,
        SW_HIDE);
    UpdateWindow(hWnd);

    // Main message loop:
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;

}


BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
      HANDLE hThread;

    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        h_inst = hinstDLL;



делаю такую фичу - не работает, взял за основу пример из MSDN , в окнах я не сильно силен... что может быть не так ?
PM MAIL   Вверх
GremlinProg
Дата 23.4.2010, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



ничего общего с задачей этот, даже недописанный код не имеет

последовательность действий должна быть примерно такая:
1. в дллмайне, при присоединении к процессу, пускаем новый поток
2. в потоке можно перебрать потоки текущего процесса
3. найти среди них гуишный
4. перебрать для него все окна
5. найти главное
6. субклассить это окно своей оконной процедурой

первый поток нужен только во избежание дедлоков (настоящих, будущих)

Добавлено через 3 минуты и 59 секунд
если нет желания заморачиваться, то пункты 2-5 можно заменить на любой вариант FindWindow


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


Эксперт
****


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

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



Цитата(12usver12 @  23.4.2010,  16:03 Найти цитируемый пост)
что может быть не так ?

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

если делать по твоему, то надо все равно найти главное окно и на нем создать дочернее,
причем даже так WM_CLOSE не поймаешь

так можно поймать только что-нить наподобии WM_DESTROY,
т.е. определить, когда окно удалит все дочерние компоненты (включая твой)
но это будет уже после WM_CLOSE

вобщем, лучше сабклассинг, ну или, хук, как предлагает Earnest,
просто сабклассинг немного попроще


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


Бывалый
*


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

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



хорошо а если с хуком то я так понимаю - перехватывать GetMessage нужно и смотреть на msg.message ?
а вообще как лучше определить что окно является главным ?...
 
PM MAIL   Вверх
GremlinProg
Дата 23.4.2010, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(12usver12 @  23.4.2010,  17:14 Найти цитируемый пост)
а если с хуком то я так понимаю - перехватывать GetMessage нужно и смотреть на msg.message ?

да, если WM_CLOSE будет укладываться в очередь потока, твой хук его перехватит
Цитата(12usver12 @  23.4.2010,  17:14 Найти цитируемый пост)
а вообще как лучше определить что окно является главным ?

в принципе, это дело индивидуальное,
обычно, у такого окна нет ни родителя, ни владельца (если оно плавающее) см. GetAncestor
( правда всегда есть риск перепутать плавающее окно с обычным диалогом, вызванным через MessageBox )

лучше ориентироваться на перекрытые окна,
а еще лучше - посмотреть на него из spy

Добавлено @ 15:55
а еще у такого окна владельцем может быть десктоп - GetDesktopWindow


Это сообщение отредактировал(а) GremlinProg - 23.4.2010, 16:14


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


Бывалый
*


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

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



хм вроде такой вариант идет...
Код

перебор окон 
для каждого hwnd принадлежащее процессу
if (GetWindowLongA(hwnd, GWL_HINSTANCE) == GetModuleHandle(0)) то главное

PM MAIL   Вверх
GremlinProg
Дата 23.4.2010, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



если такое окно единственное - можно и так :)
а вообще, база исполняемого модуля - не показатель,
так можно определить только то, что процедура этого окна находится в exe, а не dll


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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



GremlinProg, вариант вроде сервер (exe) передает клиенту (dll) указатель на callback RegistreNewOmWmMessageHandler(UMSG msg, void (*lpfnNewCallBack)(HWND, UMSG, DWORD lParam, DWORD wParam) ), который может дернуть dll и соотвественно зарегить свой обработчик через EXE не рассматривается?

Говорят же что процесс не чужой, а родной.. вероятно его можно немного подредактировать для удобства...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
GremlinProg
Дата 26.4.2010, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



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

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

p.s.: инетерфейс не в смысле interface, а в смысле учет в исходной программе экспортируемой функции такого рода


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


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Я собственно делаю так
Код

HHOOK hHookQuit = NULL;
LRESULT CALLBACK QuitHookProc(int code, WPARAM wParam, LPARAM lParam);

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
   switch (fwdreason)
   {
      case DLL_PROCESS_ATTACH:
      {
         hInstDLL = hinstDLL;
         hHookQuit = SetWindowsHookEx(WH_GETMESSAGE, QuitHookProc, hInstDLL, GetCurrentThreadId());
      }break;

      case DLL_PROCESS_DETACH:
      {
         if(hHookQuit)
         {
            UnhookWindowsHookEx(hHookQuit);
         }
      }break;
   }
   return 1;
}


LRESULT CALLBACK QuitHookProc(int code, WPARAM wParam, LPARAM lParam)
{
   PMSG pmsg;
   pmsg = (PMSG)lParam;

   if(code < 0) return CallNextHookEx(hHookQuit, code, wParam, lParam);

   if(pmsg->message == WM_QUIT)
   {
      // Тут выполняем свои гнусные действия
   }

   return CallNextHookEx(hHookQuit, code, wParam, lParam);
}




--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
12usver12
Дата 26.4.2010, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



thx Dem_max , очень хорошее решение...
хотя я уже остановился на сабклассинге
 
Код

if (GetWindowLongA(hwnd, GWL_HINSTANCE) == GetModuleHandle(0) && !GetParent)

это далеко не идеальное решение, но в рамках моего случая это с головой достаточно.
А вообще "главного" окна может и не быть - может быть несколько равнозначных окон, которые стоят 
на верхнем уровне, как показала прога wndviewer, и при корректном закрытии приложения каждое из них, получается, получает WM_CLOSE

Это сообщение отредактировал(а) 12usver12 - 26.4.2010, 14:05
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0712 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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