Messages in opencv window - c++

I want to send data to opencv program in order to tell it when to start recording from a camera. I want to send WM_COPYDATA message to a named opencv window and make it handle the message.
I assume SetWindowsHookEx with WH_GETMESSAGE is the way to go? As far as I looked it requires creating a dll and I'd like to avoid additional files.
Also I found a way to break the loop once 'X' of named window is clicked but before it does break out, it pops out once again after I do click 'X':
HWND hwnd = (HWND)cvGetWindowHandle("NamedWindow");
while (IsWindowVisible(hwnd)) {
// Functions
}
So I think the best way would to be to handle a WM_CLOSE message.
Edit: Ok, I solved it simply by switching from while loop to do-while loop, however, in my opinion, handling a WM_CLOSE message is more appropriate way.
I could create my own window and that would do too but I don't know how to print an image like cv::imshow("namedwindow", mat) does.

Related

Win32 API: App Freezes after opening dialog window

I am trying to open "Open File Dialog" of an already opened notepad app on a button click event with win32 API. Here is the code:
void onButonClicked()
{
HWND hWnd = ::FindWindow(NULL, L"Untitled - Notepad");
HMENU hWndMenu = ::GetMenu(hWnd);
HMENU hWndSubMenu = ::GetSubMenu(hWndMenu, 0);
SendMessage(hWnd, WM_COMMAND, GetMenuItemID(hWndSubMenu, 1), 0);
}
This works fine and opens the "Open Dialog". But it freezes my app. If I try to move my app window with mouse, it hangs and shows "Not Responding" on title bar. I have also tried opening this dialog window in a separate thread, but no luck. How to solve this issue?
The code you show us looks like you want to control NOTEPAD:
The reason why it blocks is simple. SendMessage send the WM_COMMAND message to NOTEPAD and waits until it is processed. Notpad itself receives the WM_COMMAND message and shows it file open dialog and waits for the user input.
This is all done inside the handling of the WM_COMMAND message and SendMessage will only return when this handling is done. So either the user aborts the dialog, or he selects a file and the file gets opened.
PS: Your question is not detailed enough what yo really want to do.
In the comments you state:
I want to open a file with win32 code without user intervention.
In that case your entire approach is wrong. Pass the name of the file to ShellExecuteEx, and let the system open the file.
As for why your current code blocks, that's simple enough. SendMessage is synchronous and only returns once the message has been processed. And the message processing completes when the modal file dialog is closed. But hacking away at Notepad in this manner is never the correct solution to a problem. Please refrain.
To prevent your program from hanging, you can use PostMessage instead of SendMessage:
PostMessage(hWnd, WM_COMMAND, GetMenuItemID(hWndSubMenu, 1), 0);
You may want to further study the difference: What is the difference between Send Message and Post Message and how these relate to C# ,WPF and Pure windows programming?
In general there is a very big difference between SendMessage and PostMessage in the windows API.
SendMessage will run the associated callback (i.e. the thing supposed to receive the message) directly and return after the message has been completely processed. This is 'blocking' your app because notepad only returns from this call after the (modal) file dialog has returned.
PostMessage will add a message to the applications message queue and return immediately; at some later point the application (notepad) will process this message.
All of this said what you are doing is probably not a good idea - this kind of remote control of other applications raises some serious security concerns.

Send keybinds to a non-active window

So this has been bothering me for quite a while now.
I have a program for sending keys to a window (user may select processes from a CComboBox, etc.), and I'm now trying for quite a while to figure out how it would be possible to send key-binds to a window (background !).
I know about this keybd_event function and the SendInput function. I use neither of them in my current code, as they require the window to be in the foreground.
Short said, my program can send keys and text to any (valid) window.
PostMessage(m_hwndEx, WM_CHAR, nKey, 0x00140001);
I have tried various solutions with SendMessage and PostMessage, but nothing seems to work.
Assume the program sends CTRL+SHIFT+F (as example). How would this be possible ? I would appreciate some pointer function(s) or even an external library if the 'basic' functions do not work for this matter.
I do not want the window to be in the foreground.

::PostMessage doesn't work when I am tabbed in to another program

In our Program we have a Dialog from a separate dll open to display infomation. I need to close this dialog when our system timer causes the system to lock.
I send information to the dll by registering a system message in both my MainFrm and EditDisplayDll
SYSTEMLOCK = RegisterWindowMessage("SystemLock");
When I sent the message via
::PostMessage(GetActiveWindow()->m_hWnd,SYSTEMLOCK,0,0);
The message correctly sends to my EditDisplayDll and closes the dialog when the system locks; however, if I alt tab while waiting for the timeout and use another program(firefox, outlook, etc.) the message never correctly calls to the EditDisplayDll. The MainFrm and other windows inside of the MainFrm correctly lockout and hide themselves in either case.
I have tried also using HWND_BROADCAST with PostMessage and SendNotifyMessage. I have also tried to use FindWindow() and FindWindowEx() to specifically call the EditDisplayDll.
I cannot use something like GetDlgItem() because my MainFrm.cpp doesn't have access to this dll.
My decision to use GetActiveWindow() was because I believe it looks to windows specific to my program no matter what window I am in as seen in the imagery in Foreground Vs Active window
Finally, my question is, is there a way to call all Windows in my program no matter what program I am currently in or is there another way I could get access to the specific IDD of the EditDisplayDll in order to send the SYSTEMLOCK message to it?
CWnd *cWndED = FindWindow(_T("EditDisplay"),_T("EditDisplay")); HWND
hwnd = (HWND)cWndED;
You should use win32 API ::FindWindow with proper class, window name. And do not cast CWnd pointer to HWND. Your code should look like:
HWND hWnd = ::FindWindow(_T("ProperClass"), _T("ProperNmae"));
if (hWnd != NULL)
{
::PostMessage(hWnd, YOUR_MESSAGE, ....);
}
I will suggest you to find your Dll window class and name using Spy++ and then try to find that using above method. Remember it's always better to use native API for this kind of tasks.
FindWindow is a good solution if you know both, name of the window and the element.
If you want to get the HWND of your window - no element inside the window -, you can pass as first parameter NULL.
::FindWindow(NULL, _T("WindowName"));
Back to your code: If you are lucky your PostMessage does nothing, otherwise the active window may catch your message. Who knows how/if it is handled in the active window ? Use the PostMessage if you have a valid IsWindow(HWND) from FindWindow or FindWindowEx.
In case you want a CWnd from your HWND take a look at this. (The call may be slow)
HWND hWnd = ::FindWindow(_T("ClassName"), _T("WindowName"));
if (hWnd && IsWindow(hWnd))
{
::PostMessage(hWnd, MESSAGE_TO_BE_SEND, lParam_or_Flags);
}

How to use mouse hook so current window never sees specific mouse message?

I want some window to never receive mouse wheel up/downs, i can control this messages trough my mouse hook fine but is there a way to make a window never receive those messages?
I can validate the window trough mouse hook and check if its active then just never send that message to it.
I installed mouse hook globally so i believe i have everything needed.
AFAIK hooks may not block the message from reaching the wndproc of the appropriate window.
You may however achieve what you need by subclassing the appropriate windows. That is, replace the window procedure of the appropriate window (use SetWindowLongPtr with GWL_WNDPROC flag) by your wndproc. It should pass all the messages to the original wndproc, apart from those that you want to filter-out.

C++ - Dialog box question

This is a more concrete question that is connected with my previous one.
I have an application that uses a timer. The code is written the way the my WM_TIMER handler call a DialogBoxParam(...) with some custom message handler (let's call it DlgProc).
This is done somewhat the following way:
case WM_TIMER:
{
// Routine, that displays a special message box
DisplayMessageBox(...);
return 0;
}
Now, if I make DlgProc handle the messages like this (see the code), this would result in tons of dialog boxes (one per WM_TIMER call).
switch (msg)
{
case WM_INITDIALOG:
// (...)
return TRUE;
case WM_COMMAND:
// (...)
return TRUE;
return FALSE;
}
But if I add a dummy WM_PAINT handler (return TRUE;) to my DlgProc, this results in exactly one shown DialogBox and 100% CPU load (that's because I receive tons of WM_PAINT messages).
Q:
What can be done here if I want my application to show exactly ONE dialog box and have no CPU load for WM_PAINT processing? (I mean like, have behaviour similiar to draw unique dialog box and fully pause the parent window).
Also it would be great if someone explains what actually happens in this situation and why do I receive gazillions of WM_PAINT messages to my dialog box and why their processing (with return TRUE) results in preventing the other dialog boxes creation.
Thank you.
1) You should disable the timer after the first WM_TIMER signal is caught if you want to show only one single dialog box. You can do this using KillTimer().
2) Windows wants to keep the GUI up-to-date. Whenever a region on the screen should be updated, it is invalidated using InvalidateRect or InvalidateRgn. Now, for every "invalid" screen part, WM_PAINT is called in order to make in "valid" again.
If you don't do it (or just parts of it), Windows will call WM_PAINT again ... and again. One way is to call ValidateRect. In many cases BeginPaint() and EndPaint() are used to do the job.
3) Maybe most important: you should not just return FALSE! Try DefWindowProc() for windows and DefDlgProc() for dialogs. They will also take care of WM_PAINT appropriately.
It's not that you registered for WM_PAINT, something must cause it (even if you don't add WM_PAINT: handler), look for re/draw functions (like InvalidateRect())