Getting results from a non thread blocking message box? - c++

Generally, message boxes work like this:
if(ShowMessageBox("Title","Text",MB_YES_NO) == MB_YES)
{
//the user responded yes
}
However, I'm working on a game where I have made the gui system, and when a messagebox is shown, there is still animation happening in the background so I cannot simply block the thread, the animation would stop.
Right now, the way it works is to show the message box, an IMessageHandler* must be provided and it is called with the dialog result.
I'm wondering if I'm overlooking something. Is there a better way to do this that might resemble more how it is usually done. How might other games approach it?
Thanks

There are multiple options, e.g...
Create a View-Model class that the message box reads from (title, message, button text) and writes to (result prior to closing), pass the VM to your message box before displaying it, then read result from VM after close.
(A better technique would to use a command pattern or place an event on the message box instead of passing VM to message box, then within command/event handler update VM).
Use a command pattern or an event to pass result from message box (prior to close) directly to caller (or to view model).
Use a show dialog style call to message box (blocking), however, do that on a separate thread, then write results to a place where main thread can read from.

Related

C++ Modal dialog box continuing adding texts

I have dialog box and in it, it has OK and Cancel buttons then it also has a ListBox to display text in two columns. I would like to continue adding text into the ListBox after the dialog box is shown. How can I do that? Because after I call DoModal() to show the dialog box, the code does not continue to execute. Or should I create two threads (one is display dialog box while another thread continues adding text to dialog box)?
Make your dialog 'pull' the data it needs, maybe polling the data source with window messages every second, or every 100ms or so. Or, if you go the 'two threads' route (the better but more complicated option), have your data source post a window message to your dialog when there is new data, and then have the dialog fetch the data it needs. The reason for this is that it's much easier to use the existing CDialog infrastructure to get a window that behaves like an actual dialog, compared to building a modal window that acts like a dialog but isn't really.
If you do go the two threads route, your division of labor should be: one thread that does all the UI work (including showing the dialog), and one that 'generates' data and lets the UI know when there is new data. So the worker thread should not do anything related to the UI, nor call any methods on the dialog directly - you can't access windows from several threads. The only cross-thread window communication should happen through window message (i.e., use ::SendMessage()). So certainly don't do something like myDialog->m_theList.AddString("blah") from another thread, or something like it.
Showing a dialog box modally halts further execution until you close the box. Instead of showing it modal, show it normal but make it always on top so you can continue executing the code after the call to DoModal(). Alternatively, populate the box with all the info it will need before you call DoModal().
If you decide to take the "two threads" approach you will discover that the controls on MFC dialogs should not be updated or accessed from a thread other than the one that created the dialog. Even if you have pointers to these controls available in another thread it is not thread-safe to access them. This rule applies whether or not the dialog is modal.
Instead, your second thread would need to PostMessage or SendMessage to the dialog window, so the updates occur on the thread that created the dialog (most likely the main UI thread of the application).

How to know if the Gtk::ComboBoxText is popup

I am writing a simple GUI, in which I have a ComboBoxText. I write a log message when ever the user clicks on the ComboBoxText.
I have tried almost all the button release and popup signals but no results. The only thing which works is signal_changed() but I don't not need that. Please help me, below is my sample code :
myCombo->signal_button_release_event().connect(sigc::mem_fun(this,&ComboBoxText::ComboInput),false);
and here is the call back function:
bool ComboBoxText::ComboInput(GdkEventButton *pEvt) {
// Here do the desired stuffs !!
return false; }
Use GTK+ property popup-shown. Not sure about Gtkmm syntax, probably property_popup_shown().get_value().
If you need a signal to listen to, connect to popdown or notify::popup-shown (the latter is invoked when property value changes; again, I'm not sure about Gtkmm syntax).
The idea here was to fire an event when the ComboBoxText is clicked. After some readings I figured it out that the ComboBoxText does not fire any on_click event as such.
One could mask a key press event (which by the way gets fired) and call the signal handler. This might not be handy for people who specifically looking for a on_click event but for those who are working with a keyboard or touch screen device. Here is a small chunk of code :`
mCombo.add_events(Gdk::KEY_PRESS_MASK);
mCombo.signal_event().connect(sigc::mem_fun(this,&ClassName::Handler),false);
cheers :)

What does WindProc do for me?

I have a multiple dialog MFC client app that i am working on. This client can receive a lot of messaging (>10Hz) to the main dialog, which often performs some small function, then forwards that message onto the another dialog for processing.
In my specific case, the main dialog receives messages relating to a vehicle location, updates a couple fields on that GUI, then passes it on vi a PostMessage to a window that displays all the vehicle information.
So basically, my question is this: what is the difference b/w posting the message, or just calling the dialog.update (which is a function i created)?
Well, since we don't know what your dialog.update() does, how are we to know what the difference is?
If you are doing another PostMessage, I'm not sure what the point of that is. Your program has to wait for another iteration of the message loop to retrieve your newly posted message and possibly another message could be received before that one is posted. Instead of PostMessage, you could use SendMessage which will send the message straight to the WndProc without having to iterate the message loop for another message.
I am thinking that if you are multi-threaded, then sending or posting messages will be a little more thread safe since Windows should switch contexts automatically. If you are single threaded, then it probably shouldn't matter.
I believe your application is multithreaded, and one of the thread is receivng the data, and is different than GUI thread. You should use PostMessage only from other thread to this dialog, and not SendMessage or direct call.
If you are receiving too many messages, you should buffer them - either by count (say 5000), or by some timeout. You may keep the messages into vector, list or any other collection you like. Later, when sending, post the address of this collection as WPARAM (or LPARAM) to the dialog. Dialog will get it, in a single bunch and would process it. This approach may not be correct as I am not aware about other design perspetives of your application.
You would need to trial-and-error approach, see where you get the actual performance and stability benefits.

A blocking but non-modal QDialog?

I have a stack of images on which I want to perform some operations. After processing each image, my program should pop up a dialog to prompt the user if they want to proceed with the next image or to abort. Before that, they should have an opportunity to do some manual changes either on the images or on the parameters. Anyway, they must have access to the windows of the applications, while the execution of the method that called the dialog should be blocked until the dialog is closed.
I tried to solve this with a QMessageBox, but if I open it via exec(), it blocks the entire application, and if I use show(), the execution of the program goes on without waiting for user's reaction.
Is there a convenient way to block the calling method or function with a dialog but permit the user to interact with other windows?
Thanks in advance for any hint.
You should split your method that you want to block into two parts. In the end of first part you need to show your dialog without blocking and connect "Next" button (for example) of the dialog to the slot that must contains second part of your old method. This slot will be executed only when user presses the button.
It's the right way to do it in Qt. You need posibly to change your code logic to implement this.
Also, do you really need the second dialog? You can place "Next" button to your main widget. You can also create another modal dialog that will contain some settings and "Next" button.

Closing a MessageBox automatically

I have a third party encryption library, which may create a MessageBox if key creation fails. The failure can be caused by bad random number generation or other rarities, and in most cases, trying again will result in success. My code will attempt key creation up to three times before deciding it failed.
Now, the issue is that the program may be used with automation. If a MessageBox is created during automation, it will block the process forever, because there's nobody to click the 'OK' button.
Does anyone know of a way to catch when this message box is created and automatically close it?
Anything is fair game, as long as it's not something that will make security suites angry. This means no hooking or code tunneling.
In summary, I need to catch when a MessageBox is created and close it. The MessageBox's creation is outside of my control. Modifying the code at runtime is not acceptable.
Also, I've noticed there are some other similar questions, but they don't have the same requirements.
EDIT: Additional note, I can find the message box via searching through all windows until I find one with a matching title and then send it a WM_CLOSE message, but I don't think this is a great solution. I also have no guarantee that the message box has been/will be displayed, or how long after my call it will be displayed. It could display instantly, it could display 1200 ms later, or it could not display at all.
Just before you begin the encryption process, install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, or if that doesn't work post a WM_CLOSE (or a BM_CLICK to a relevant button if selecting an option is necessary). Uninstall the hook after the process for not messing with every possible dialog your application pops up.
That sounds like bad design on the part of that library. Generally any sort of utility library (like encryption) has no business invoking any kind of GUI (unless you explicitly ask it to).
Is there possibly some configuration or setting in this library that could disable its use of message boxes?
If not, I'd suggest that you might want to investigate using a different library. After all, if the designers of this library have already made this kind of poor design decision once, then there may be other unfortunate surprises lurking in there.
You can hope that it will be found by GetForegroundWindow, but this may catch other applications. The more brute force way is to iterate over all windows with EnumWindows looking for something that has a caption or text equal to this shown by the library.
I have once "remote controlled" an application by sending mouse click events to some controls. I guess you would have to do this in a separate thread that is watching for Events if a window is opened. Pretty ugly but working...
Create a new thread. If your function fails and a Message Box is opened, obtain a handle to the message box by looping through the windows (GetTopWindow, GetNextWindow) and comparing the window's process id to the one returned from GetCurrentProcessId().
Or, you can avoid all the hard work and just hook the MessageBox API with detours. It's not very hard, and if you don't want to pay for detours, you can do it manually.
Call VirtualProtect and set the memory protection at MessageBox at PAGE_EXECUTE_READWRITE
Create a naked function, and use it as a trampoline.
Create a function identical in parameters to MessageBox (this will be your hook)
Create a jump from MessageBox to your hook function.