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


Автор: kiLLProg 1.10.2008, 13:25
Всем привет.
Пишу программу, которая перехватывает клики мыши и ведёт протокол нажатий в Memo. Сообщения перехватывает хук в ДЛЛке, но не могу переправить события кликов в управляющее приложение, которое загружает хук. Помогите исправит эту проблему. Заранее благодарен.

Код В ДЛЛ:
Код

#include <windows.h> 
#pragma argsused 

MOUSEHOOKSTRUCT* psMouseHook; // Для анализа сообшений от мыши 
HWND h; 

extern "C" __declspec(dllexport) LRESULT CALLBACK MouseHook(int,WPARAM,LPARAM); 

//--------------------------------------------------------------------------- 
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) 
{ 
    return 1; 
} 

//--------------------------------------------------------------------------- 
// Ловушка мыши 
LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam) 
{ 
  int x1, y1; 

  /* 
  if(wParam==WM_MOUSEMOVE || wParam==WM_NCMOUSEMOVE) 
  { 
  */ 

    //h = FindWindow("TForm1", "Form1"); 
    psMouseHook=(MOUSEHOOKSTRUCT*)(lParam); 
    HWND par_win = psMouseHook->hwnd;//дескриптор окна над которым находится мышка 
    HWND main_wind = FindWindow(NULL, "Form1");//ищем окно, загрузившее нашу dll с ловушкой 

    switch( LOWORD( wParam ) ) 
    { 
      case WM_LBUTTONDOWN: 
        //PostMessage(h, 1, 0, 0); 
        // Посылаем сообщение приложению 
        PostMessage(main_wind, 1, (WPARAM)par_win, (LPARAM)psMouseHook->hwnd); 
        Beep(1000, 200); 
        break; 
    }    

   /* 
    if (wParam == WM_LBUTTONDOWN) 
    { 
      //PostMessage(h, WM_LBUTTONDOWN, 0, 0); 
      PostMessage(h, 1, 0, 0); 
      Beep(1000, 200); 
    } 
   */ 
return 0; 
} 


Сообщения доходят до приложения(при PostMessage(main_wind, WM_CLOSE, 0, 0) прога подвисает), возможно я просто неправильно их обрабатываю. 
А обрабатываю эти сообщения так:

Код

// компонент ApplicationEvents 
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, 
      bool &Handled) 
{ 
  switch(Msg.message) 
  { 
    //case WM_LBUTTONDOWN:   // пробую так и сяк, не помогает... 
    case 1: 
      Memo1->Lines->Add("Левый клик !!!"); 
      break; 
    //case WM_LBUTTONDBLCLK: 
    case 2: 
      Memo1->Lines->Add("Двойной левый клик !!!"); 
      break; 
   } 
   if (Msg.message == 1) 
   { 
     Memo1->Lines->Add("Левый клик !!!"); 
   } 
}

Автор: ama_kid 1.10.2008, 14:31
1) Мне почему-то кажется, что сообщение с номером 1 системой будет понято неправильно...
2) глобальный мышиный хук WH_MOUSE_LL можно ставить и внутри своего приложения, его незачем пихать в dll (если нет других противопоказаний). 

Вывод: тебе надо внимательнее почитать про принцип работы системных сообщений и про хуки...

Автор: kiLLProg 1.10.2008, 14:45
Из-за большого числа комментариев проге, тебе должно было понятно, что пробовал я так и сяк. Плюс еще, событие двойного клика перехватывает только хук в дЛЛ. Я пробовал и без длл, но я хочу нормально разобраться postMessag"ем.

Автор: 586 1.10.2008, 19:11
Цитата(kiLLProg @  1.10.2008,  14:25 Найти цитируемый пост)
psMouseHook=(MOUSEHOOKSTRUCT*)(lParam); 

Глобальные переменные опасны при многопоточности. Определи эту переменную ВНУТРИ функции MouseHook.

Цитата(kiLLProg @  1.10.2008,  14:25 Найти цитируемый пост)
PostMessage(main_wind, 1, (WPARAM)par_win, (LPARAM)psMouseHook->hwnd); 

замени на
Код
PostMessage(main_wind, WM_USER+1, wParam, (LPARAM)psMouseHook->hwnd);


Цитата(kiLLProg @  1.10.2008,  14:25 Найти цитируемый пост)
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, 
      bool &Handled) 
{ 
  switch(Msg.message) 
  { 
    //case WM_LBUTTONDOWN:   // пробую так и сяк, не помогает... 
    case 1: 
      Memo1->Lines->Add("Левый клик !!!"); 
      break; 
    //case WM_LBUTTONDBLCLK: 
    case 2: 
      Memo1->Lines->Add("Двойной левый клик !!!"); 
      break; 
   } 
   if (Msg.message == 1) 
   { 
     Memo1->Lines->Add("Левый клик !!!"); 
   } 
}

замени на
Код
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, 
      bool &Handled) 
{ 
  if(Msg.mesage == (WM_USER+1))
  {
    switch(Msg.wParam) 
    { 
    case WM_LBUTTONDOWN: 
      Memo1->Lines->Add("Левый клик !!!"); 
      break; 
    case WM_LBUTTONDBLCLK: 
      Memo1->Lines->Add("Двойной левый клик !!!"); 
      break; 
   } 
    Handled = true;
    return;
  }
  Handled = false;
}

код ловушки:
Код
LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam) 
{ 
    if(nCode >= 0)
    {
        MOUSEHOOKSTRUCT *psMouseHook=(MOUSEHOOKSTRUCT*)(lParam); 
        HWND par_win = 0;
        if(psMouseHook) par_win = psMouseHook->hwnd;
        HWND main_wind = FindWindow(NULL, "Form1");

        if(main_wind) PostMessage(main_wind, WM_USER+1, wParam, (LPARAM)par_win); 
    }    
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

Автор: kiLLProg 2.10.2008, 12:33
Спасибо за ответ! Реально, чудесным образом заработало как надо! Изменил код ДЛЛ на ваш и код обработчика то же. Но ваш обработчик сообщений не обрабатывал события от хука как и у меня.  Я мутил со структурой  msg. Получал координати курсора, а потом решил просматривать wParamы. Раньше это не прокатывало, но изменив код моей дЛЛ на ваш, все заработало.

Код в приложении:
Код

hile (GetMessage(&msg,(HWND)(NULL),0,0)) // Цикл обработки сообщений
    {
      LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
      TranslateMessage(&msg);

      x = msg.pt.x;
      y = msg.pt.y;

      // Вот тут теперь всё у меня срабатывает, а раньше такого не было
      if (msg.wParam == WM_LBUTTONDOWN)
        Form1->Memo1->Lines->Add("!!!!WM_LBUTTONDOWN!!!!");
      if (msg.wParam == WM_LBUTTONDBLCLK)
        Form1->Memo1->Lines->Add("!!!!WM_LBUTTONDBLCLK!!!!");

      DispatchMessage(&msg);
    }


Код в ДЛЛ:

Код

LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam) 
{ 
    if(nCode >= 0)
    {
        MOUSEHOOKSTRUCT *psMouseHook=(MOUSEHOOKSTRUCT*)(lParam); 
        HWND par_win = 0;
        if(psMouseHook) par_win = psMouseHook->hwnd;
        HWND main_wind = FindWindow(NULL, "Form1");

        switch(wParam)
        {
          case WM_LBUTTONDOWN:
            // так тоже работает ну, т.к par_win = psMouseHook->hwnd;

            //if(main_wind) PostMessage(main_wind, WM_USER+1, wParam, (LPARAM)par_win);
            PostMessage(main_wind, WM_USER+1, wParam, (LPARAM)psMouseHook->hwnd);
            break;
          case WM_LBUTTONDBLCLK:
            PostMessage(main_wind, WM_USER+1, wParam, (LPARAM)psMouseHook->hwnd);
            break;
        }    
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}


Спасибо и за такое решение проблемы. Но я бы хотел разобраться с разработчиком, вроде все логично, но что то там не так.

Вот исходник моей проги по глобальному перехвату координат курсора и кликов мыши.
Буду ждать ответов.




Автор: 586 3.10.2008, 23:00
Перехватывать оконные сообщения можно по-разному...
Код
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TButton *Button1;
    TMemo *Memo1;
    void __fastcall Button1Click(TObject *Sender);
private:    // User declarations

protected:
    virtual void __fastcall WndProc(Messages::TMessage &Message);

public:        // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Автор: J0ker 3.10.2008, 23:57
Цитата(kiLLProg @  1.10.2008,  14:45 Найти цитируемый пост)
Из-за большого числа комментариев проге, тебе должно было понятно, что пробовал я так и сяк.

интересный способ прогрммирования  smile 

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