Letting the mouse pass through Windows C++

為{幸葍}努か 提交于 2019-12-07 05:53:55

问题


I am working on an Win32 C++ application where I want to ignore the mouse events and let is pass through to the window beneath my window. Basically the window below mine will handle the mouse event. I would prefer not to send the mouse message using SendMessage to the window beneath mine or use SetCapture. Is there a way basically to ignore the mouse event and let it pass through with Windows APIs or with styles? Note that my window is not transparent.

Thanks in advance for the help.


回答1:


So I found this question, and others, while attempting to create a music player that overlays a graphical display over the screen without impacting any other interaction, including e.g. dragging windows.

I've tried both the WM_NCHITTEST approach, as well as simply adding WS_EX_TRANSPARENT to my window. Neither of these approaches work -- they both seem to capture mouse click events, which is something I don't want.

However, by pure coincidence, I did manage to find a combination of flags I can pass to SetWindowLong(..., GWL_EXSTYLE, ...) that seem to do the trick, leading to the following code:

LONG cur_style = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, cur_style | WS_EX_TRANSPARENT | WS_EX_LAYERED);

It appears that this behavior is documented here:

Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through. However, if the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to other windows underneath the layered window.

The extended window style documentation is also very useful. For applications such as mine, where a window is not meant to be interacted with, WS_EX_NOACTIVATE may also be useful, as it prevents some user interactions.

For posterity's sake, I will note that the code I am using to ensure my window is always on top is the following:

SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);



回答2:


I would try handling WM_NCHITTEST and returning HTNOWHERE.

I believe the approaches that use WS_EX_TRANSPARENT will have other side effects and are only useful if the underlying window is owned by the same thread. From the question, it's not clear if the underlying windows are part of the same application or any old application underneath.




回答3:


I have been testing this with 2 different RDC solutions by 2 different 3rd parties. Each solution probably creates its own window differently, with different styles etc. If I do below in WindowProc:

    case WM_MOUSEMOVE:
    {   
        std::cout << "WM_MOUSEMOVE" << std::endl;
        VideoWindowWin32* window = reinterpret_cast<VideoWindowWin32*> (GetWindowLongPtr (hWnd, GWL_USERDATA));
        if (window)
        {               
            HWND rParent = GetParent(window->window);
            SetCapture(window->parent);
            //SendMessage(window->parent, uMsg, wParam, lParam);
        }
    }
    break;

Everything works with one of them. But it doesn't for the other.

I would appreciate if there is anything you could suggest.




回答4:


Based on Adrian McCarthy, but actually works for me (though only when the parent owns the child window, otherwise the window will catch the mouse again):

case WM_NCHITTEST: return HTTRANSPARENT;

HTNOWHERE just caused that the LoadCursor() for the window wasn't shown anymore.

These values seem to be possible:

#ifndef NONCMESSAGES

/*
 * WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes
 */
#define HTERROR             (-2)
#define HTTRANSPARENT       (-1)
#define HTNOWHERE           0
#define HTCLIENT            1
#define HTCAPTION           2
#define HTSYSMENU           3
#define HTGROWBOX           4
#define HTSIZE              HTGROWBOX
#define HTMENU              5
#define HTHSCROLL           6
#define HTVSCROLL           7
#define HTMINBUTTON         8
#define HTMAXBUTTON         9
#define HTLEFT              10
#define HTRIGHT             11
#define HTTOP               12
#define HTTOPLEFT           13
#define HTTOPRIGHT          14
#define HTBOTTOM            15
#define HTBOTTOMLEFT        16
#define HTBOTTOMRIGHT       17
#define HTBORDER            18
#define HTREDUCE            HTMINBUTTON
#define HTZOOM              HTMAXBUTTON
#define HTSIZEFIRST         HTLEFT
#define HTSIZELAST          HTBOTTOMRIGHT
#if(WINVER >= 0x0400)
#define HTOBJECT            19
#define HTCLOSE             20
#define HTHELP              21
#endif /* WINVER >= 0x0400 */


/*
 * SendMessageTimeout values
 */
#define SMTO_NORMAL         0x0000
#define SMTO_BLOCK          0x0001
#define SMTO_ABORTIFHUNG    0x0002
#if(WINVER >= 0x0500)
#define SMTO_NOTIMEOUTIFNOTHUNG 0x0008
#endif /* WINVER >= 0x0500 */
#if(WINVER >= 0x0600)
#define SMTO_ERRORONEXIT    0x0020
#endif /* WINVER >= 0x0600 */
#if(WINVER >= 0x0602)
#endif /* WINVER >= 0x0602 */

#endif /* !NONCMESSAGES */


来源:https://stackoverflow.com/questions/13069717/letting-the-mouse-pass-through-windows-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!