Suppose if i create a thread using CreateThread, and I want a modal or modeless dialog in that thread. Do i need to use a seperate message loop for that like I have here,
while(GetMessage(&msg, 0, 0, 0)) // Get any window messages
{
TranslateMessage(&msg); // Translate the message
DispatchMessage(&msg); // Dispatch the message
}
But for modal dialog, you don't use that, so why shouldn't it work when i create a dialog?
When you use a modal dialog, it creates its own message queue, that's why it works. If you want to use modeless dialogs then you will have to create a message queue yourself.
From the documentation for DialogBox:
The DialogBox macro uses the CreateWindowEx function to create the dialog box. (snip) and starts its own message loop to retrieve and dispatch messages for the dialog box.
Related
I am using OleCreatePropertyFrame to display property pages of the webcam. But, I wasn't able to make the dialog modal or close the frame externally when closing the camera.
OleCreatePropertyFrame(
NULL, // Parent window
0, 0, // Reserved
lpcostr, // Caption for the dialog box
1, // Number of objects (just the filter)
&pFilterUnk, // Array of object pointers.
caGUID.cElems, // Number of property pages
caGUID.pElems, // Array of property page CLSIDs
0, // Locale identifier
0, NULL // Reserved
);
Any help is appreciated.
OleCreatePropertyFrame is standard API for modal dialog box meaning that it is supposed that the mesasge box is displayed until closed interactively. That is, you are not supposed to be able to close it from code.
This function always creates a modal dialog box and does not return until the dialog box is closed.
One of the ways to make the dialog modal is to re-implement property page host (IPropertyPage and friends) and put it into your customized UI as a modeless window or otherwise. It is quite doable overall, and mostly expects basic knowledge of COM.
Another [traditional?] trick to close standard modal UI externally is to PostQuitMessage into the inner message loop of OleCreatePropertyFrame API so that it closes the dialog box in response to non-interactive signal, and then remove pending WM_QUIT message from the outer message loop, added by the API after closing the dialog in attempt to forward quit command further.
We have a dialog X, that can be opened by different threads (also main thread) as modal. Multiple modal X dialogs, at the same time from different threads is possible.
We want to close all X (only X) modal dialogs, if the main window handles a SC_CLOSE message.
The question is; From the main window, how can we close all modal X dialogs, when it recieves the SC_CLOSE message? Only X! So, PostQuitMessage doesn't help, because it closes whole app, we don't want to close the app, if other modal dialogs like Y, Z ... are opened.
Info: Main window can handle SC_CLOSE message, when we have the opened modal X dialog from main thread also from other threads. And X has no child modal window.
My current solution is;
All modal X dialogs have been registered in a collection (thread-safely), during openning of them.
if the main window becomes the SC_CLOSE-message, then iterating all dialog is now possible. Then use one of those 2 lines, for each dialog.
::PostMessage(pDlg->GetSafeHwnd(), WM_COMMAND, IDOK, 0); //end dialog with idok
::PostMessage(pDlg->GetSafeHwnd(), WM_CLOSE, 0, 0); //or, close dialog
I know it is not the best solution, but hope helps someone.
Don't try to iterate all childs of main window to find dialogs. it won't help. Owner of the dialogs, doesn't mean that it is the parent of the dialogs.
I have a multi-threaded application that may display a MessageBox for a user's interaction. The message box itself is displayed from a worker thread, after a user picks a context menu command from the app's system tray icon, so the user can technically continue using the app while the message box is displayed. This works great until a user issues "Exit" command, at which point I need to find a way to close any open message boxes.
I did my homework and I was able to obtain HWND handle for the main (dialog) window of the message box (using this method.) I checked the HWND to be correct using Spy++, so HWND itself is not the issue. What happens is that when I do PostMessage(hMsgBoxWnd, WM_CLOSE, 0, 0); from another thread to the message box, it simply ignores this message and doesn't close.
Any idea how to close the message-box by its window handle?
MessageBox() simply does not process WM_CLOSE in all sitations:
SendMessage/PostMessage WM_CLOSE to MessageBox window does not always work
You should use PostThreadMessage to post to the threads specific message queue
I'm working on an application to detect a pop-up dialog and then
automatically dismiss it. I'm writing this as a C++/Win32 app. The
dialog box is generated by IE 7 and I can detect the window, but
several methods to get the OK button to "click" have failed.
Doing searches for other people's solutions, sending these messages to
the button handle seems to have worked in a lot of situations:
PostMessage( handle, WM_LBUTTONDOWN, 0, 0 );
PostMessage( handle, WM_LBUTTONUP, 0, 0 );
PostMessage( handle, BM_SETSTATE, 1, 0 );
It has no effect on the button state in my tests though.
I can send tab characters to the main window and see that the OK
button gets focus, but then sending return characters does nothing.
To learn more about this I used Spy++ to get information about the
window hierarchy and what messages are delievered when I manually
click the OK button.
Looking at the message log and reading about WM_MOUSEACTIVATE seamed
to offer a solution. The log info shows that 0002166C was the button
window. So in my code I tried this:
GetClassNameA( handle, str, str_size );
if( strcmp( str, "Internet Explorer_Server" ) != 0 )
return TRUE; // Not the window we're interested in.
// Send a message to activate the button window and have it process a mouse click.
PostMessage( handle, WM_MOUSEACTIVATE, (WPARAM) dialog_handle, MAKELPARAM( HTCLIENT, WM_LBUTTONDOWN );
Based on the window hierarchy and message log, I think the window with
the class name "Internet Explorer_Server" is the button. Maybe I'm
wrong, because it does seem like an odd class name for a button...
Below is a link to the window hierarchy image, message log when I
manually click the OK button. Last is the code that's executed on a 1
second timer ticket, looking for the window.
Any insight and help is appreciated!
Image of the window hierarchy, source, window messages, and test dialog source are available here:
https://sites.google.com/site/matthewmillersmiscellanea/Home/
Ideally, you should create a DLL which exports a Global CBT Window Hook. This would allow you to get early notification when a dialog is going to be created. This would avoid the need to drain resources by constantly polling.
Once you've detected that a dialog is about to be created, you have two options:
1) Prevent the dialog creation.
I don't recommend this, it causes all sorts of problems with code that was fully expecting a valid HWND to be returned by CreateDialog();
2) Asynchronously control the dialog.
We achieved this by using PostMessage with a Registered user message and picking it up by hooking the WNDPROC. When you get this message, then you have to decide how to kill the dialog that you're in.
There are multiple ways to exit the dialog:
a) Simulate pressing OK, Cancel, Abort, No buttons using WM_COMMAND(BN_CLICKED) (as Chris comments). You can use GetDlgItem(), look for the WindowText and make your choice. However, this doesn't work for non-US-English. There may be some distance in leveraging the Accessibility API here though.
b) Simulate closing the dialog with PostMessage(WM_CLOSE, m_hWnd). This doesn't always work as expected - some dialogs have no [X] close button and their client code is expecting a specific button to be pressed instead.
c) Simulate user input using the SendInput() API. This worked around dialogs that had anti-popup-killer code in them :)
Our final solution was a rule+heuristic-based approach that had a configuration file which we could tweak when the app/IE dialogs changed their ID's, class names or parent class names.
To close continually a specific popup given that you know the window class name and window caption
#define UNICODE
#include <windows.h>
#pragma comment(lib, "user32")
int main (int nn, char ** aa)
{
while (true) {
HWND iHandle = FindWindow (L"theWindowClassName", L"theWindowCaption");
if (iHandle > 0) SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
Sleep (200); // check 5 times per second
}
return 0;
}
if one is not known or too generic (e.g. "Dialog") you can omit it by passing a null
HWND iHandle = FindWindow (L"theWindowClassName", 0);
or
HWND iHandle = FindWindow (0, L"theWindowCaption");
of course this will close all windows with the given names.
I have an application that currently has a message loop. If I were to create a modal dialog box with the DialogBox method would the current message loop receive messages from the dialog as well or would they be withheld by the runtime?
DialogBox creates its own message loop so your message loop will not run. From the documentation:
The function displays the dialog box (regardless of whether the
template specifies the WS_VISIBLE style), disables the owner window,
and starts its own message loop to retrieve and dispatch messages for
the dialog box.
Your existing message loop will not receive the messages for the dialog box. All messages for the dialog would be received by the DLGPROC method that you're passing as the last parameter to the DialogBox function.