delegating events from always-on-top window to other windows Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

delegating events from always-on-top window to other windows

Post by pxhai »

Hello friends,

I want to make an application for fun, to display a dog running and waving tail across screen. I set it to transparent and user can see things under it as usual. This window is always-on-top.

The problem is, I don't want this shaped-window to receive and process any external events (mouse, keyboard etc.), instead it ignores and delegates events to other under-layer windows, allowing users to work like without that dog. Is it possible and how to do it?

Thanks in advance
Romas
I live to help wx-kind
I live to help wx-kind
Posts: 176
Joined: Mon Jun 16, 2008 11:07 am
Location: Kaunas

Post by Romas »

If the platform would be windows and you would like to make a little hack I would say:

All You need to do is to handle WM_NCHITTEST message and return HTTRANSPARENT.
Everything requires a line of code.
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

Post by pxhai »

Thank you for your reply.
I made an override of wxFrame::MSWWndProc(), like following:

virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
if(message == WM_NCHITTEST)
{
return HTTRANSPARENT;
}

return wxFrame::MSWWindowProc(message, wParam, lParam);
}

It doesn't work as I expected. The underlying window isn't set focus.
My idea is, when user clicks on the shaped window, they actually clicks on the beneath window of another application.
Currently I'm researching on wxTopLevelWindow source code to find the method the wx authors use. It seems that they use direct function call from WinAPI to set the region and don't care about processing mouse event, windows automatically handles it.
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

Post by pxhai »

up

My application will have these features:
1. Run on top of all windows, like screensaver
2. doesn't respond to mouse events. When user clicks on the screen, he actually clicks on the windows under that top layer.

any suggestions will be appreciated. Thanks
Romas
I live to help wx-kind
I live to help wx-kind
Posts: 176
Joined: Mon Jun 16, 2008 11:07 am
Location: Kaunas

Post by Romas »

WM_NCHITTEST is good for windows in the same thread, so making window "transparent" for other windows in different thread or process it is useless.

I do not know how to help you. I doubt that you will find easy solution for this. You still need to capture window messages and pass it to windows below to your window.
Everything requires a line of code.
Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Post by Auria »

If it's something like a screensaver, you probably want to simply draw directly to the screen, and not create any window at all.

http://docs.wxwidgets.org/stable/wx_wxscreendc.html might help
"Keyboard not detected. Press F1 to continue"
-- Windows
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

Post by pxhai »

If it's something like a screensaver, you probably want to simply draw directly to the screen, and not create any window at all.

http://docs.wxwidgets.org/stable/wx_wxscreendc.html might help
No, I mean it runs on top of all windows, like screensaver, but it allows mouse clicks to pass through.

The solution is unbelievably simple: only one line of code on windows:

Code: Select all

::SetWindowLong((HWND)this->GetHandle(), GWL_EXSTYLE, ::GetWindowLong((HWND)this->GetHandle(), GWL_EXSTYLE) | WS_EX_TRANSPARENT);
Thank you for all the helps.

If anyone knows how to do this on Linux or Mac, please suggest your solutions to us.
Romas
I live to help wx-kind
I live to help wx-kind
Posts: 176
Joined: Mon Jun 16, 2008 11:07 am
Location: Kaunas

Post by Romas »

This is a window style, that makes a window to be the last in the painting queue. This one is not connected with mouse/keyboard input...
WS_EX_TRANSPARENT
Specifies that a window created with this style should not be painted until siblings beneath the window (that were created by the same thread) have been painted. The window appears transparent because the bits of underlying sibling windows have already been painted.
Everything requires a line of code.
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

Post by pxhai »

@Romas: I'm not so sure about painting queue and transparency, because I let wxTopLevelWindow::SetTransparent() handle the alpha blending effect, but adding WS_EX_TRANSPARENT style to the window allows all mouse events to pass through it to the beneath windows. It does work. And it's not limited within windows created in the same thread/process, but also windows of other applications in different processes.

regards
Romas
I live to help wx-kind
I live to help wx-kind
Posts: 176
Joined: Mon Jun 16, 2008 11:07 am
Location: Kaunas

Post by Romas »

I wont argue with you, but it simply cannot work :)

EDIT:
A little research gave me result, that WS_EX_TRANSPARENT will not give a desired result when using alone. You also need to add WS_EX_LAYERED style...
Everything requires a line of code.
pxhai
Earned a small fee
Earned a small fee
Posts: 21
Joined: Sun Mar 02, 2008 5:31 pm
Location: US

Post by pxhai »

Hi Romas, as I said earlier, I let wxTopLevelWindow handle the transparent effect. I think winapi already added WS_EX_LAYERED to the window, and no need to set it again (no harm if OR it though). I add WS_EX_TRANSPARENT later, and it works perfectly.
Post Reply