0

Im using EasyHook to hook google chrome, trying to prevent the window from being activated when sending clicks to it using PostMessage, i hooked WM_WINDOWPOSCHANGING and 'forced' it to remove the flags SWP_NOACTIVATE | SWP_NOZORDER, but when i send the PostMessage click:

lParam = MAKELPARAM(x, y);
PostMessageW(hWnd, WM_LBUTTONDOWN, 0x0001, lParam);
PostMessageW(hWnd, WM_LBUTTONUP, 0, lParam);

the window still get activated, i confirmed that the hook is working correctly, the problem is just finding the correct WINAPI to hook/intercept.

    typedef LRESULT __stdcall DefDlgProcWFunc(HWND, UINT, WPARAM, LPARAM);
    
    // Innermost hook handler
    LRESULT __stdcall DefDlgProcW_Hook(HWND   hWnd, UINT   Msg, WPARAM wParam, LPARAM lParam)
    {
        DefWindowProcW_Msg(hWnd, Msg, wParam, lParam, 1);
    
        // Innermost hook just call original
        return DefDlgProcW(hWnd, Msg, wParam, lParam);
    }
    
    
    
    void DefWindowProcW_Msg(HWND hWnd, UINT& Msg, WPARAM& wParam, LPARAM& lParam, int CalledByFunction)
    {
        if (!hooks_enabled)
            return;
    
        std::wstringstream str;

        HWND hwnd = nullptr;
        HWND hwndInsertAfter = nullptr;
        tagWINDOWPOS* wp;
        int x;
        int y;
        int cx;
        int cy;
        UINT flags;
    
        switch (Msg)
        {
            case WM_WINDOWPOSCHANGING:
            {
                wp = reinterpret_cast<tagWINDOWPOS*>(lParam);
                hwnd = wp->hwnd;
                hwndInsertAfter = wp->hwndInsertAfter;
                x = wp->x;
                y = wp->y;
                cx = wp->cx;
                cy = wp->cy;
                flags = wp->flags;
    
    
                HWND hWnd2 = FindWindow(0, L"New Tab - Google Chrome");
    
                str << L"\nWM_WINDOWPOSCHANGING"
                    << L"\nx:                   " << x  << L"        y:        " << y
                    << L"\nw:                   " << cx << L"        h:        " << cy
                    << L"\nhwnd:                " << hwnd
                    << L"\nflags:               " << flags
                    << L"\n";
                OutputDebugString(str.str().c_str());
    
                if (hWnd == hWnd2) {
                    OutputDebugString(L"CHROME!!!!\n");
                    wp->flags &= ~(SWP_NOACTIVATE | SWP_NOZORDER);
                    return;
                }
    
                return;
            }
        }
    }

This works:

Is it possible to prevent an application from being activated (brought to front) without using DLL injection?

but the cons is: you always need to call LockSetForegroundWindow before and after sending the message (to unlock), if i try to perform a click in the taskbar while it are locked no window is activated.

In the link there's a mention to SetWinEventHook with the event EVENT_SYSTEM_FOREGROUND it would not help as when the event is returned the window already changed.

I also tried hooking SetForegroundWindow, but looks like chrome is not calling it.

This is all window message triggered after sending a PostMessage click: https://i.stack.imgur.com/02WuI.png

My goal is to get it working using PostMessage, and not UI Automation/JavaScript.

Cesar
  • 41
  • 2
  • 5
  • 16
  • Why would you *remove* the `SWP_NOACTIVATE` and `SWP_NOZORDER` flags if you are trying to *prevent* activation? You should be *adding* those flags instead: `wp->flags |= (SWP_NOACTIVATE | SWP_NOZORDER);` – Remy Lebeau Jun 08 '22 at 02:53
  • @RemyLebeau The window is not being activated anymore, but its stoling the focus from the current active window – Cesar Jun 08 '22 at 03:26
  • 2
    The classic [XY Problem](https://xyproblem.info). Instead of trying to fix the effects of applying an inappropriate solution, just use the right approach: [UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32). Hard to justify avoiding the solution. – IInspectable Jun 08 '22 at 05:55
  • @IInspectable how do you click at a given position using UI Automation? from what i know, what you can do is call the default action of something that is recognized by the api? – Cesar Jun 08 '22 at 11:04
  • @joe The whole premise of UI Automation is that UI geometry becomes a non-issue. You do not click at a position. You interact with accessible objects at a more abstract level. UI Automation exists for many reasons, including the fact that [you can't simulate keyboard input with PostMessage](https://devblogs.microsoft.com/oldnewthing/20050530-11/?p=35513) (mouse input has the same issues). – IInspectable Jun 08 '22 at 11:14
  • Well, all you said i already know about, If you dot not click at a position, how this could help in the op question? that's why i ask, specially that op mentioned no `UI Automation`, if you have a div element of 400/200px and need to click at 150px, you cannot do this using `UI Automation`, "classic XY Problem", so your answer is a "class XY answer"? @Cesar you could try blocking the target window from calling `WM_SETFOCUS`. – Cesar Jun 08 '22 at 11:46
  • @Joey after i send the `PostMessage` click this is all message it triggers: https://i.imgur.com/04dKTVb.png, i tried 'intercepting' `WM_SETFOCUS`, and set `wParam` `lParam` to 0, but the window still stole focus. – Cesar Jun 08 '22 at 12:09
  • I tried returning 1 on both `WM_SETFOCUS` and `WM_KILLFOCUS` `An application should return zero if it processes this message.` but it stills stoling focus – Cesar Jun 08 '22 at 12:54
  • 1
    What's the specific reason for trying to avoid the solution? Clearly, you are not in command of the Windows API and how the system works. You cannot hope to fight the system and succeed, until you know every last little detail about (mouse) input handling and foreground activation. With every bit you learn, you'll see that your solution gets more and more complex. Maybe you just don't know enough yet to consider a different approach. Anyway: [How can I have a window that rejects activation but still receives pointer input?](https://devblogs.microsoft.com/oldnewthing/20160912-00/?p=94295). – IInspectable Jun 08 '22 at 13:20
  • @IInspectable i have set the `WS_EX_NO­ACTIVATE` exstyle to the window, it still stole focus – Cesar Jun 08 '22 at 13:48
  • 1
    Ignore anything from that article until you come across *"Another way is ..."*. As for your fiddling with window styles of Chrome bear in mind that a web browser these days is an *insanely* complex beast, as complex as an OS. As far as hooking goes, do realize that a web browser these days consist of *many* processes. You'll have to learn how the interact with each other to even find the right place(s) to hook into. Still, what's the striking reason for avoiding the real solution here? – IInspectable Jun 08 '22 at 13:55
  • `"You'll have to learn how the interact with each other to even find the right place(s) to hook into"` the problem is not the `hook`, as i mentioned its working, as when i modified the `flag` like @RemyLebeau mentioned, the window is `not` being activated anymore... `"As for your fiddling with window styles of Chrome"` i have verified with `spy++` and confirmed that all the browser windows got the `WS_EX_NO­ACTIVATE` exstyle applied, `"real solution here"` what's your real solution? `UI Automation`? could you tell me how to click at a given xy position using it? as its your real solution. – Cesar Jun 08 '22 at 14:14
  • 1
    UI Automation isn't designed to cheat in games. If that is your goal, then honestly, you don't even know what you're going up against. Cheating is **orders** of magnitude harder than learning to play. If you are hellbent on doing this, pick the easy route: Use `SendInput` and run your browser in a VM. – IInspectable Jun 08 '22 at 15:28

0 Answers0