Qt bug where model dialog moves behind main window - c++

I have a bug that I am having a hard time solving. I have two windows.
Window A is the main window that contains a text box (in this simplified version). The user is able to edit the contents of this text box by clicking on it where Window B appears as a keypad. Besides the buttons for the numbers, there are 2 additional buttons, Enter and Done. If the user changes the value and presses Enter, then the value in the text box is immediately updated. Pressing Done will then exit the window.
However, if the user presses done without having first pressing enter, then a modal dialog will appear asking the user if they would like to save the value. Once a selection has been made, the model dialog and Window B will exit.
The bug occurs when the user enters a value and presses the Done button. When the modal dialog appears, Window B moves behind Window A. What should happen is that Window B stays ontop of Window A. Interestingly enough, when I step through the code, this bug never happens which is making it tricky to pinpoint.
Has anyone every ran into this issue before?
I am currently running Qt 5.9 on the latest version of Linux Mint (as of this writing)
Also, I have prepared a sample project that demonstrates this bug. Due to the larger complexity of it, I was unable to fit it into 1 file. If needed, I might be able to find some time this week to move everything in one file. However, I can post the Dropbox link if permitted.

Maybe the problem stems from a wrong setting of the parent child relationship of the [QDialog][1] classes.
The following passage might be crucial for your application, but it is hard to say, if you don't show a minimal-reproducible-example.
Note: The parent relationship of the dialog does not imply that the
dialog will always be stacked on top of the parent window. To ensure
that the dialog is always on top, make the dialog modal. This also
applies for child windows of the dialog itself. To ensure that child
windows of the dialog stay on top of the dialog, make the child
windows modal as well.

Related

Radio button does not redraw correctly

Fig1:
Fig2:
As in Fig1, after I clicked radio button, the radio button seems not get correctly painted, seems 50% transparent.
As in Fig2, after I move my mouse to hover the radio button again, it got correctly painted.
I have no idea about what is going on behind.
What are the possible reasons?
By the way, after I pressed a shortcut key PrtSc to get a screenshot(a freeware: Greeshot), this problem disappeared.
One hint I just found is: the dialog holding the radios were in modeless mode. The problem disappeared after I showed it as a modal dialog.
Actually, to achieve below goals, I am implementing the message pump for this dialog. Perhaps I am doing something wrong in the message pump logic. Continue to check the pump.
My Goal: user can interact with other windows while showing this dialog, one exception is: user should not be able to interact with the parent dialog of this dialog in question, so that database transaction may be issued prematurally.
I used to have a similar problem within wxWidgets. Turns out it's a long lasting bug that really never had been fixed. I now use a workaround with a simple wrapper function that 'enables' the element (places focus on it) and then 'unfocuses' it. Not sure in your current setup.
As a result, it seems I did something wrong in the message pump for the dialog in question.
I am implementing the message pump for this dialog.
To avoid user interact with the parent dialog of the dialog in question, I was ignoring message for the parent dialog and to children of parent dialog.
After I changed the above logic to below, the problem got solved.
EnableWindow(hParent, FALSE);
EnableWindow(hParent, TRUE);
So, I think I was doing something wrong in ignoring message, not sure exactly where.

Display and use the same MFC CList control in multiple dialogs

I am coding a test application for a windows CE device. This is the first time I am programming for a handheld device. I use MFC VC++ on Visual Studio 2008. I have found that there are many restrictions in the controls and what I could do with them when running the program on a handy versus when I run a similar program on a desktop computer.
Now, the device I am currently deploying my test program to, does not have a touchscreen and has few extra keys other that the numberpad 0-9 keys. So, I have to do with a simple GUI that uses keydowns to call specific functions like add, edit, delete etc... It also forces me to use separate dialogs for each of these functions so as to avoid unnecessary mouse cursor usage.
This leads me to my current problem: The 'ADD' dialog of my test app adds some user data to a CListCtrl that is on the 'MAIN' dialog. The 'EDIT/DELETE' dialog is to allow the user to select the desired data from its own CListCtrl and press the "ENTER" key, which thereby deletes the selected data from the 'MAIN' dialog's CListCtrl. Thus, both the main dialog and the 'EDIT/DELETE' dialog have CListCtrl with the exact same data. So, instead of having to use 2 separate list controls and using loops to copy the data to and fro among them, is there a way in which i could use the exact same CListCtrl (one and only one instance of the CListCtrl exists), but display it on 2 separate dialogs? This would remove all the copying code, as well as halve the amount of data in memory.
I tried passing a pointer to the MAIN dialog's CListCtrl to the 'EDIT/DELETE' dialog in hopes that I could redraw the control there, but in vain. I could call the RedrawWindow, RedrawItems commands, but they seem to have no effect in the 'EDIT/DELETE' dialog (I think it is because the control itself is not present on the edit/delete dialog). Any other suggestions?
You could temporarily change the parent of the ListCtrl using CWnd::SetParent to the EDIT/DELETE dialog, and set the position with CWnd::SetWindowPos to where you want to have it. When the dialog gets closed, set the parent back to the MAIN dialog.

Cant focus Firemonkey application when modal dialog open, unless modal dialog itself is clicked

I have an application in which users, upon logging in, are prompted with a modal dialog where they must choose the facility they wish to work out of. At this stage, the application looks like this:
The modal dialog is shown by calling this method:
bool __fastcall ShowFacChoiceForm()
{
TFacChoiceForm *Form = new TFacChoiceForm( Application );
bool Result = ( Form->ShowModal() == mrOk );
delete Form;
return Result;
}
In this case, TFacChoiceForm inherits from TForm so the ShowFacChoiceForm() function is calling the standard TForm.ShowModal method documented here.
The issue I am running into is that if my application loses focus, it cannot become the active window again unless the modal dialog itself is clicked. To better illustrate this, I will present the following scenario:
Lets say its Friday afternoon and I decide to goof off a bit and read some web comics. With my application open, I open up another window on top of it, like so:
Then, out of nowhere my boss comes in for a performance review, and I attempt to refocus my application by clicking somewhere on the main form. For example, at the position of this red X in the next image.
In the above image, I have clicked at the location of the red X. Now, both the form containing the web comic, and my application are inactive. Thus, my application does not come to the front of the screen.
However, if I am able to click somewhere on the modal dialog, like the red X in the following image...
...then my application comes to the front like one would expect.
To solve this, I have looked at using something like SetForegroundWindow from the Windows API, but I have not been able to find a way to trigger the event, since my main form does not fire events while I have a modal dialog open.
My question is, how can I make sure that if the user clicks anywhere on my application that it is brought to the front? Is there a property I can edit in my form to do this?
If you set modalresult to mrcancel in the ondeactivate of the modal dialog then the main form will get focus when its clicked. You can then check if the user is logged in the mousedown event of the main form and if not, show the modal dialog again.

button keyboard focus issues

How would one prevent the little dotted square that appears on a button when it has the keyboard focus in a dialog. (w/ apologies for the technical jargon). At one point I hacked together a solution by subclassing a button WindowProc and subverting some windows messages, but wanted to know the correct way.
There's actually a problem with another control in the dialog also involving the keyboard. This other control is actually also a button, but being used as a group box or panel, not as a functioning button. But when I hit the tab key in the dialog, this group box "button" comes to the foreground obscuring the static controls on top of it, so I wanted to prevent that.
For both of the above, I tried turning off WS_TABSTOP - didn't help.)
Both of my problems mentioned above were solved by subclassing the WndProcs and returning 0 in response to message 0x128 and discarding it. Even Spy++ could not identify this message 0x128, and I don't have it in any header. But its sent to every control in the dialog the first time tab is hit in the dialog.
(I did try BN_SETFOCUS as described above and also WM_SETFOCUS but it didn't help.)
So if anyone knows where to find what windows message 0x128 is...
The correct way is to write your own button control instead of using the default Windows one.
Alternatively, you can prevent if from ever getting keyboard focus.

"Sticky" MFC popup menu

I currently have some toolbar buttons with a small arrow on the side (TBSTYLE_EX_DRAWDDARROWS) that, when clicked, result in a popup context menu being displayed under the button. This is done by constructing a custom popup menu and calling TrackPopupMenu.
The client now wants to be able to select multiple options from the menu before it closes, so that multiple options can be be modified without the need to re-open the menu and wait for an intermediate redraw between each change.
For example:
User clicks dropdown button
Dropdown menu appears (modal, waits indefinitely for user action)
User clicks some item (e.g., toggle a checkmark)
Timer (e.g., 500ms) starts
If timer expires, the menu is closed and all selected actions are executed.
User clicks another item before the timer expires, go back to 4.
The best I can come up with is to redisplay the menu by calling TrackPopupMenu multiple times. This makes the menu "flicker" when you select an item, and will probably require me to start a thread in order to do the timeouts, which I would rather avoid.
Rather than a menu, put up a dialog box with the options on it. A dialog can easily do all that is required.
A menu that doesn't close when you click it will just seem wrong. A dialog that closes by itself will seem wrong too, but it's probably the least of two evils.
Edit: If there's anything I've learned with Microsoft, it's don't try to fight the default behavior. You're asking for trouble if you do.
If you're building your menu dynamically I can see how automatic sizing can be handy, but it's not hard to do in a dialog either - make the dialog really big and before it becomes visible, enumerate the children and take a union of all their rectangles, then resize to that. Checking the boundaries to make sure they're on-screen is just a few if statements with OffsetRect. Checkboxes are trivial; icons less so, but still not bad.
One additional enhancement that would be easy to add is to dismiss the dialog immediately on a double-click.
Following #Mark Ransom's answer, you should put up a dialog box. But you can make the dialog modeless and make it close itself when you click outside of it (i.e., the dialog loses focus). That way it could behave more like a menu.
Notice that normal menus never go away by themselves, you always have to click somewhere outside the menu (or one of its options) to make it disappear.