How to set an OpenCV window to be a Click-through window? - c++

i have a problem making my window a "click-through" window.
I have tried some methods i found online for windowsAPI but with no luck, the mouse won't pass through the created window.
My OS is Windows 10.
Any solutions?
Thanks.

Ok, finally found the problem with the windows API functions. the handle passed to them was wrong, the opencv cvGetWindowHandle() returns the wrong handle, using the handle return from FindWindow() i was able to make my window click-through.
//-Init an opencv window
cv::namedWindow("foo");
HWND hwnd = FindWindow(NULL,"foo"); //-Work!
HWND hwnd = (HWND)cvGetWindowHandle("foo");//-Doesn't Work.
//-Set window to be click-through.
LONG lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
lExStyle |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle);
//-Set the window to always be on top.
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

Related

Change external app window from tool to overlapped

I'm using Unity to build games. It has a main window and dockable windows. I have several screens. I undock some windows to other screens, however I'm also using other apps, and when I come back to the main Unity window, I don't want the child windows to go in front of my other app windows.
Using Spy++, I saw that the child windows have WS_POPUP and WS_EX_TOOLWINDOW styles, so I did this:
EnumWindows(FindUnityWindows, NULL);
And:
BOOL CALLBACK FindUnityWindows(HWND hwnd, LPARAM lParam)
{
char class_name[80];
GetClassName(hwnd, class_name, sizeof(class_name));
int processid = GetWindowThreadProcessId(hwnd, NULL);
if (!strcmp(class_name, "UnityContainerWndClass"))
{
long style = GetWindowLong(hwnd, GWL_STYLE);
style |= WS_OVERLAPPED;
style &= ~(WS_POPUP);
long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
exstyle |= WS_EX_APPWINDOW;
exstyle &= ~(WS_EX_TOOLWINDOW);
ShowWindow(hwnd, SW_HIDE);
SetWindowLong(hwnd, GWL_STYLE, style);
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
ShowWindow(hwnd, SW_SHOW);
}
return TRUE;
}
Which effectively changes the styles (I checked in Spy++), but the windows behaviour doesn't change. I don't have a tab in the taskbar, and the windows still appears when I activate the main window.
What more can I do?

How to make a Win32 control created without WS_VISIBLE visible?

Suppose hCtl is a handle to a control created without the WS_VISIBLE flag such as:
HWND hCtl = CreateWindowEx(0, WC_STATIC, L"some text",
WS_CHILD | SS_NOTIFY, // no WS_VISIBLE flag
0, 0, 0, 0, hWndParent, (HMENU)IDC_STATIC1, g_hInst, 0);
Is there a more straightforward way to make it visible than the following?
void make_visible(HWND hCtl, HWND hWndParent) {
SetWindowLongPtr(hCtl, GWL_STYLE,
GetWindowLongPtr(hCtl, GWL_STYLE) | WS_VISIBLE);
RECT rc{};
GetClientRect(hCtl, &rc);
MapWindowRect(hCtl, hWndParent, &rc);
InvalidateRect(hWndParent, &rc, TRUE);
UpdateWindow(hWndParent);
//ShowWindow(hCtl, SW_SHOW); // no use: does not update window
//SetWindowPos(hCtl, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); // no use: does not update window
}
To make a child control visible, call SetWindowPos like this:
SetWindowPos(hCtl, 0, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
Your code to call MapWindowRect, InvalidateRect, UpdateRect etc. should be removed.
Perhaps the real problem you have is that you have created the static control with zero width and height.
The normal way to make a window visible is only the function ShowWindow. There is no need dealing with flags and so on. Usually you use SW_SHOW as a parameter for a child window. Check the other values and use what you think is appropriate.
If the window has a visible rectangle and isn't covered by another window it will show up. Even UpdateWindow calls are not needed. The window will show up in the next paint cycle. If your control has a size of 0,0,0,0 (as it was created) it will never show up.
There is also a ShowWindowAsync function for the use if the window is on a different thread to avoid blocking.
BTW: I don't understand what you try with invalidating the parent window area. If there is a child window clipping (WS_CLIPCHILDREN) it has no effect.
I believe your problem is that you're explicitly setting the WS_VISIBLE style yourself and then calling ShowWindow, which confuses Windows into believing that the window is already visible and doesn't need to be repainted.
Just call ShowWindow. There should be no need to explicitly set WS_VISIBLE yourself because ShowWindow already does it. You should not need to forcibly repaint your control.
Additionally, if you find some need to explicitly invalidate your control, it should be sufficient to just do InvalidateRect(hCtl, NULL) and not bother with GetClientRect and MapWindowRect.

Why CreateWindowEx will add WS_CAPTION by default?

I'm trying to create an window by CreateWindowEx, but seams even I give both dwExStyle dwStyle value 0, the window still have WS_CAPTION style.
Code snippet as following:
_hWnd = CreateWindowExW(iExStyle, pszClassName, pszTitle, iStyle | WS_CLIPCHILDREN, dX, dY, dWidth, dHeight,
hWndParent, 0, hInstance, NULL);
ASSERT(GetWindowLong(_hWnd, GWL_STYLE) & WS_CAPTION == 0); //<---- This will failed.
dwStyle = 0x00000000L means WS_OVERLAPPED or WS_TILED, this window has a title bar and a border.
Window Styles
As emax says, WS_OVERLAPPED (0) is the default and results in:
The window is an overlapped window. An overlapped window has a title bar and a border. Same as the WS_TILED style.
If you are creating a child window you must specify WS_CHILD and if you are creating a "popup" window you must use WS_POPUP or WS_POPUPWINDOW.
A tooltip for example would use WS_POPUP and WS_EX_TOOLWINDOW + WS_EX_TOPMOST...

Child window disappears on scrolling

HWND hwndDlg=GetDesktopWindow();
HWND hImage=CreateWindow(_T("STATIC"), _T(""), SS_CENTERIMAGE | SS_REALSIZEIMAGE | SS_BITMAP | WS_CHILD | WS_VISIBLE,
550, 480, 10, 10, hwndDlg, NULL,
(HINSTANCE)GetWindowLong(hwndDlg, GWLP_HINSTANCE),
NULL);
LPWSTR imgPath = getImagePath();
HBITMAP bitmap = (HBITMAP)LoadImageW(NULL,imgPath, IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
SendMessage(hImage, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)bitmap);
With this piece of code i'm able to create a child window to the current window and make a picture appear on that window. It works as expected. But my problem is when i scroll the child window and the picture disappear. What am I doing wrong? I'm totally new with windows programming. Please help me out.
http://i.stack.imgur.com/VO0uD.png
You may see the screenschot in the above link

Layered window: Why's the edge rounded automatically?

I am trying to draw a hbitmap with a layeredwindow directly onto the screen. this also works now how it should, yet the left upper corner of the image is always rounded.
I'm creating the window with:
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT
, szWindowClass, 0,
WS_VISIBLE
, 150,250, width, height, 0, NULL, hInstance, NULL);
Could anyone help me please to solve this problem?
You are using WS_VISIBLE as the window style, which is equivalent to WS_OVERLAPPED | WS_VISIBLE. Overlapped windows have rounded corners at the top.
Use WS_POPUP | WS_VISIBLE instead.