Thread: handle messages even when the window isn't active

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    53

    Question handle messages even when the window isn't active

    Is there a way to make sure the window runs it's procedure and handles it's messages even if it is inactive or minimized?

    Thanks in advance.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    At the WinAPI level the message dispatcher (GetMessage(), TranslateMessage(), DispatchMessage() etc.) should take care of that naturally.

    If there's a problem can you post the relevent code sections?

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    23
    If a window has been created it will still receive messages while inactive, minimised, hidden.

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    53
    here's some part of the code (from the window procedure)

    Code:
    	
    case WM_KEYDOWN:
    		switch(wParam)
    		{
    			case VK_UP:
    				pCur.y=pCur.y-10;  //I declared pCur as a static POINT//
    			        SetCursorPos(pCur.x,pCur.y);
    				break;
    			case VK_DOWN:
    				pCur.y=pCur.y+10;
    				SetCursorPos(pCur.x,pCur.y);
    				break;
    			case VK_LEFT:
    				pCur.x=pCur.x-10;
    				SetCursorPos(pCur.x,pCur.y);
    				break;
    			case VK_RIGHT:
    				pCur.x=pCur.x+10;
    				SetCursorPos(pCur.x,pCur.y);
    				break;
    }
    as you can see, it is supposed to change the coordinates of the cursor using keyboard input. It manages the job when it is active, but when it is minimized, it won't happen.

    After i posted the question, i suddenly realised that the problem wasn't the messsages, it was about the keyboard focus. Sorry about the misinformation. Anyway, is there a way i can keep the program working, even when it is minimized?

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    23
    when the window is minimised it wont have keyboard focus, you can use a hook to capture the keyboard information SetWindowsHookEx Function, Using Hooks

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Yes, it is about keyboard focus. Only the foreground window can receive keyboard input.

    Unfortunately making this work from the background gets just a little complex. You will need to dabble in DLL injection and global hooks, which is not the easiest of programming. Basically you need to create a DLL that contains a global keyboard hook which will intercept keystrokes and deal with them.

    LowLevelKeyboardProc Callback Function (Windows)

  7. #7
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Low level keyboard hooks don't require dlls:
    Quote Originally Posted by From your link
    This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop
    For example (a to exit):
    Code:
    #include <windows.h>
    
    LRESULT CALLBACK LLKeyProc(int action, WPARAM wParam, LPARAM lParam)
    {
        if(action == HC_ACTION)
        {
            PKBDLLHOOKSTRUCT pKey = (PKBDLLHOOKSTRUCT)lParam;
            printf("Got key press %x\n", pKey->vkCode);
            if(pKey->vkCode == 'a')
            {
                PostQuitMessage(0);
            }
        }
        return CallNextHookEx(NULL, action, wParam, lParam);
    }
    
    int main(int, char**)
    {
        HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, &LLKeyProc, NULL, 0);
        if(hook)
        {
            while(WaitMessage())
            {
                MSG msg = {0};
                while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    if(msg.message == WM_QUIT)
                    {
                        goto exit;
                    }
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
    exit:
            UnhookWindowsHookEx(hook);
        }
        return 0;
    }
    Last edited by adeyblue; 04-30-2011 at 10:07 AM. Reason: Complete forgot about WaitMessage

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    However... if you scroll to the bottom of that page and look... the low level keyboard hook, which is what our friend needs is a global hook, requiring that it be in a DLL...

    Also from the same page...

    SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
    (Empahsis mine...)

    I ran into this with a mouse hook some years back. Couldn't get the thing to work for the life or me... build a DLL and set the hook from the DLL and away it goes.

  9. #9
    Registered User
    Join Date
    Mar 2011
    Posts
    23
    yes, msdn says
    You must place a global hook procedure in a DLL separate from the application installing the hook procedure. The installing application must have the handle to the DLL module before it can install the hook procedure. To retrieve a handle to the DLL module, call the LoadLibrary function with the name of the DLL. After you have obtained the handle, you can call the GetProcAddress function to retrieve a pointer to the hook procedure. Finally, use SetWindowsHookEx to install the hook procedure address in the appropriate hook chain. SetWindowsHookEx passes the module handle, a pointer to the hook-procedure entry point, and 0 for the thread identifier, indicating that the hook procedure should be associated with all threads in the same desktop as the calling thread.

  10. #10
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    As an example of form.... there's the DLL from that mouse hook project...
    Code:
    #define WIN32_LEAN_AND_MEAN
    #define _WIN32_WINNT 0x400
    #pragma comment(linker, "/heap:128")
    #define MMAPI  __declspec(dllexport)
    
    #include <windows.h>
    
    /////////////////////////////////////////////////////////////////
    //  Handle double click
    //  
    
    BOOL RevButtons = 0;
              
    void SendClick(void)
      { if (!RevButtons)
          { mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
            mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
            mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
            mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0); } 
        else
          { mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
            mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
            mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
            mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0); } }
    
    /////////////////////////////////////////////////////////////////
    // Mouse mod process
    //
    int lastdir = 1;          // wheel tracker
    BOOL mbutton = 0;         // settings
    BOOL hysterisis = 0; 
    HHOOK mmhook = NULL;      // mouse hook handle
    PMSLLHOOKSTRUCT mhs;
    
    MMAPI LRESULT CALLBACK MouseTracker(int code, WPARAM wparm, LPARAM lparm)
      { if (code < 0)
          return CallNextHookEx(mmhook,code,wparm,lparm); 
        // get struct address
        mhs = (PMSLLHOOKSTRUCT)lparm; 
        // process the message
        switch (wparm)
          { case WM_MBUTTONDOWN :  // replace with lbutton dblclick
              { if (mbutton) 
                  { SendClick();
                    return 1; }
                break; }  
            case WM_MBUTTONUP :
              { if (mbutton)
                  { return 1; }
                break; }    
            case WM_MOUSEWHEEL :  // drop 1 msg on wheel reverses
              { if (hysterisis)
                  if (((lastdir < 0) && ((int)mhs->mouseData > 0)) ||
                      ((lastdir > 0)  && ((int)mhs->mouseData < 0)))
                    { lastdir = (int)mhs->mouseData;
                      return 1;   } } }
        return CallNextHookEx(mmhook,code,wparm,lparm); }
        
    /////////////////////////////////////////////////////////////////
    //  Enable features
    //
    MMAPI void WINAPI SetMButton(BOOL dblclk)
      { mbutton = (dblclk & 1); }
    
    MMAPI void WINAPI SetMWheel(BOOL rollback)
      { hysterisis = (rollback & 1); }
      
    /////////////////////////////////////////////////////////////////
    // Set the windows hook
    // if goforit = 1 hook is set, 0 to release
    // Returns hook status 1 = active, 0 = not
    //
    HINSTANCE hdll;   // dll handle
    
    MMAPI BOOL WINAPI SetMHook(BOOL goforit)
      { if (goforit)
          { if (mmhook)
              return 1; 
            mmhook      = SetWindowsHookEx(WH_MOUSE_LL,&MouseTracker,hdll,0); 
            RevButtons  = GetSystemMetrics(SM_SWAPBUTTON); }
        else
          { if (mmhook)
              { if (UnhookWindowsHookEx(mmhook))
                    mmhook = NULL; } }
        return (mmhook != NULL); }      
    
    /////////////////////////////////////////////////////////////////
    //  DLL entry point
    //
    BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
      { if (reason == DLL_PROCESS_ATTACH)
          hdll = hinst;
        return 1; }
    Load the DLL... call the SetMHook function and the DLL is then injected into each process. There just wasn't any other way to do it.

  11. #11
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Can you people not compile and run code that's in front of you? Where's the required dll? Does it not work? Can't you use Process Explorer and verify that even if you use a dll it never gets injected anywhere? Can't you put two and two together and figure, 'Gee, if the OS is gonna call me in my own process context (which doesn't happen with the other global hooks, only the LL ones), what would be the point of it injecting stuff into another process?'

    EDIT:
    Now I find it, paragraph under the one I quoted in my last post:
    Quote Originally Posted by msdn
    However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
    Quote Originally Posted by msdn
    However, the WH_MOUSE_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
    Ah, smug mode. I can't hang around here saving your necks all day, I think I'll make a start on that ironing.

    Proof, as if it were needed - Imageshack - 34435171.png
    Last edited by adeyblue; 04-30-2011 at 03:37 PM.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Adeyblue... the guys who wrote the Operating System disagree with you... what can I say?

  13. #13
    Registered User
    Join Date
    Mar 2011
    Posts
    53
    Last week there was a topic on key loggers. How did it work?

  14. #14
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by new_in_c++ View Post
    Last week there was a topic on key loggers. How did it work?
    Well, I suppose you could re-read the thread and find out...

  15. #15
    Registered User
    Join Date
    Mar 2011
    Posts
    53
    Quote Originally Posted by CommonTater View Post
    Well, I suppose you could re-read the thread and find out...
    Yes, i have already read it. I'm asking how it managed to read keys even though the window was invisible. It hasn't got any of those hooks or low level keyboard procedures.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Send Key To Active Window
    By thatsgreat2345 in forum C++ Programming
    Replies: 2
    Last Post: 11-12-2006, 02:17 PM
  2. active window ...
    By twomers in forum C++ Programming
    Replies: 1
    Last Post: 02-20-2006, 08:05 AM
  3. Re: Active Child Window
    By icc_81 in forum C++ Programming
    Replies: 2
    Last Post: 03-31-2004, 03:33 PM
  4. Setting active window
    By bennyandthejets in forum Windows Programming
    Replies: 1
    Last Post: 10-14-2003, 09:22 AM
  5. How to Handle the messages of Clild windows ??
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 03-24-2003, 04:32 AM

Tags for this Thread