How to keep track of dirty controls in a dialog - c++

I was wondering how Windows applications typically keep track of dirty controls in a dialog, so that when the user clicks a button like "Apply" or "Save," the application knows which controls' values to commit.
I see that edit controls have an EM_GETMODIFY message, which will tell you whether the contents of the edit control have been modified, but I don't think that type of message is available for other controls like date-time pickers or combo boxes.
So I suspect that this would be done by monitoring change notifications sent from the controls to the parent dialog. But if that's the case, how might the change events be flagged or stored? I thought that perhaps that whenever a change occurs, the application could store the control's ID or hwnd in a std::unordered_set, and then iterate through the set when it's time to commit. Or is there another, more accepted and efficient way? Thank you for any guidance.

Related

Getting title bar double-clicks

I am working on a MFC C++ application. I was working on a dialog that has SystemMenu property set to FALSE, so it does not have the ability to maximize. I want to handle the double-click message on the title bar. How can I do that?
EDIT:
I hope this time it will be clear for everybody. I have a dialog that does not have system menu (and system buttons or icon). When the user double-clicks the titlebar of that dialog, I want the program to call function x();.
Technically, you would have to handle WM_NCLBUTTONDBLCLK and check if the double click occurred in the caption area of the window, possibly by sending it WM_NCHITTEST and testing that the return value is HTCAPTION.
(Update: As JohnCz rightfully points out, sending WM_NCHITTESTis not actually necessary, since WM_NCLBUTTONDBLCLK already carries its result in wParam.)
Then you would only have to send WM_SYSCOMMAND with SC_MAXIMIZE in wParam to the window to maximize it.
In practice, however, it will not achieve much if your dialog box is not ready to handle size changes and layout its controls accordingly. This feature did not come out of the box in MFC last time I checked.
I think there is some kind of confusion here:
Frédéric Hamidi
You are correct, handling WM_NCLBUTTONDBLCLK message is the right way to go, however it is no necessary to call HitTest, since WM_NCLBUTTONDBLCLK message delivers hit information that MFC framework translates in the WM_NCLBUTTONDBLCLK handler.
Victor,
What is exactly that you are trying to achieve by handling WM_NCLBUTTONDBLCLK message?
Maybe there is some other way to fulfill your requirement once you make it clear to us.
The fact that you do not have system menu, does not prevent your app from receiving non-client area messages.

How to move the cursor to the last opened window (possibly popup) in c++

I need to move the mouse to the last opened window. This last window will be a popup created by whatever website.
I guess all I need is to get the position of the last opened window and use SetMousePos, right?
I'm not really familiar with the windows API and any help is welcome - Thanks!
Edit:
To answer the questions, we are writing a program that gets malware data. Unfortunately some malware only start working after the mouse moves to a popup they opened. Its a research-based application
I haven't tested this but I believe you could try the following:
Enumerate running processes and order by PID.
The highest number PID should be the "newest" process.
For the newest process enumerate its windows (use GetWindowThreadProcessId)
At this point I guess you'd have to pick which window you think is the "main" window, for example if the malware opens two windows I don't know how you're going to choose which one to give focus to?
Of your picked HWND get its position on the desktop.
Use SetMousePos to move the mouse to the position of the window.
I haven't included all the API's you'll need for these tasks as its generally quite easy to find on here :)
One way to track recently opened windows is to use SetWinEventHook to listen to the EVENT_OBJECT_CREATE and EVENT_OBJECT_SHOW events. In the callback, filter:
just events with a non-null HWND where idObject==OBJID_WINDOW to get just window creation events (vs other creation events such as for items within a listbox)
for top-level only windows, also filter by checking GetAncestor(hwnd, GA_PARENT) is GetDesktopWindow()
And check that the window is indeed currently visible (WS_VISIBLE style is set in GetWindowLong(GWL_STYLE)).
Also filter by GetWindowThreadProcessId() and via the thread/process you pass into SetWinEventHook if you only care about HWNDs from a specific app.
The reason for checking both of these events is that some windows are created hidden and then shown, others are created fully visible, while others are created once, then shown/hidden many times over their lifetime.
You can then cache this 'last known created hwnd' in a global and check it as needed, using GetWindowRect() to get its location, and SetCursorPos() to move the mouse to that location.
--
If the most recent popup is an active window which takes focus - as is the case with dialogs, but not usually the case with 'pop-under' windows - you can use GetGUIThreadInfo(NULL, ...) to determine the currently active HWND, which might be the one you are looking for, returned in the GUITHREADINFO.hwndActive member of the struct you pass it.

How does one tell when the state of a child window changes in WTL?

I've written a simple GUI using WTL:
I've got everything figured out as far as setting up the window is concerned, and also wired up the menus and such to call whatever I wish. But I need to know when, for example, someone checks one of the checkboxes in the list view, or when someone clicks on a button.
Do these child windows send a message to the main window notifying of the state change, and is that notification generally consistent between child window types?
Child notifications are typically sent to the parent window in the form of WM_NOTIFY or WM_COMMAND messages.
Some child notifications are common across most control types (e.g. NM_CLICK and NM_CUSTOMDRAW), but in general you'll need to look at the notifications reference for each control type on MSDN to see what's available. To start, the reference for listview notifications are here and the button notifications are here.

Creating Drawer-like window

How do you create a window that is attached to the side of parent window opens like a drawer?
In such a way that you don't lose focus of parent window.
What you basically need to do is create yourself a custom control representing your drawer. I'm not sure if that's something you're familiar with or not, but if not there are plenty of tutorials about, such as this one.
I imagine what you'd do is designate part of your control to be the "handle", which if clicked upon "opens" the drawer. You would achieve this by handling the WM_LBUTTONDOWN/WM_LBUTTONUP messages in your control's window procedure, and changing its size from its closed size to its open size when clicks are detected. I haven't used it before, but you might be able to simply achieve animation using AnimateWindow.
You'd probably also want to have your control send it's parent window a notification whenever it is opened or closed, so that your parent window can re-size or move other controls if necessary. You can achieve this by sending a WM_NOTIFY message to the parent window with your own notification code, or using your own custom message. Your parent window would then have to respond to such messages in its window procedure.
As far as I'm aware there's no specific examples to be found addressing your exact requirements, so I probably can't supply much more info at the moment. If there's anything else in particular you need to know to get this running, don't hesitate to ask.

"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.