Win32: Combobox loses focus when clicking its child window - c++

I have a c++ Win32 application with a node-based GUI where I create a dynamic combobox with CreateWindowEx when the user presses a certain key within the GUI. I want the user to be able to click outside of the combobox Rect in order to make the combobox disappear.
To do this, I'm currently destroying the combobox inside a WM_KILLFOCUS notification of its DlgProc (so any click outside of it destroys it). However, it seems that the WM_KILLFOCUS notification is sent anytime one of its child windows gains focus. For example, if I click in the combobox's edit text region, the combobox itself loses focus since that child gains focus. Given my setup, this causes the combobox to be removed when clicking within it's Rect.
How can I prevent this behavior? Basically I want to be able to detect when anything other than the combobox or its child windows gains focus, rather than simply detecting if the combobox itself loses focus.

You can determine, whether focus moves to a different control from inside the WM_KILLFOCUS handler. This message receives
[a] handle to the window that receives the keyboard focus.
through its wParam argument.
Use the CB_GETCOMBOBOXINFO message to retrieve a COMBOBOXINFO structure, that contains window handles to all contributing windows (hwndCombo, hwndItem, and hwndList). Comparing the wParam value to all of those window handles allows you to determine, whether focus moves inside the combo box or outside.
While this answers the question that was asked, the real solution would be to handle the CBN_KILLFOCUS notification instead. It is sent to the control parent when the combo box loses keyboard focus, ignoring focus change events internal to the combo box control.

Related

window procedures for dialog box controls

I've created a dialog box with buttons in it using Visual Studio's resource editor, and I want the buttons to display different icons under different circumstances.
I gather that in order to set an icon for a button, I need to send a BM_SETIMAGE message to a window procedure for that button.
I'm not clear on what handling such a message would involve, but I haven't gotten to the point of figuring that out, because I don't see how to associate a window procedure to a button in the first place. I'm used to associating a window to its window procedure by passing a pointer to the procedure into the function that initializes the window, but that doesn't seem to apply here since the buttons are initialized automatically when I initialize the dialog box.
I thought there might be a way to specify window procedures for controls in the resource editor, but if there is, I'm missing it.

How to set the control's initial position in dialog in MFC?

In MFC, I've made a resizing dialog in MFC and I put one control on a dialog like slider.
After the build, I found that the slider does not move when I resize the dialog.
So I made OnSize() then I set the position. It works.
However, there is one problem which is the different between control's first position and second position in Onsize().
So I want to make so that there is no difference in control's position between the first run dialog and after resizing.
How to set the control's initial position in dialog in MFC?
Ignore all WM_SIZE messages you receive until OnInitDialog is executed...
WM_INITDIALOG is fired when the dialog ist just before to be shown or was already shown (if it has the visible style).

Hide "Close Window" option from taskbar

I want to make a window that has an icon on the taskbar, but does not have the option to be closed from there. I could simply intercept WM_CLOSE, but then a non-functional option still remains on the window's taskbar menu. There are other questions on stackoverflow pertaining to that method, but none that describe how to hide the option itself. How can I accomplish this?
The Taskbar button uses the same menu that is assigned to the window itself. There is no way to differentiate whether the menu is being invoked by clicking on the Taskbar versus clicking on the window (or even if it is being invoked by mouse or keyboard, for that matter). If you disable the "Close" item, the user would not be able to close the window at all. So just don't do it.

Use dialog controls without stealing focus

I have a modeless CDialog that contains controls, some CButtons and a CScrollbar. The CDialog is parented off of an edit box that I want to keep focus at all times. The problem is that whenever the user uses the controls, clicking a button or on the scrollbar, the control steals focus from the edit box, causing both the parent window to draw without focus (grayed-out header bar), and causing the control to take all the keyboard input. Is there a way for the controls to respond to mouse actions but not steal focus?
The controls and the dialog are all created with WS_CHILD. The controls are parented off the dialog, and the dialog is parented off of the edit box.
I've tried setting focus back after the controls are used, but that causes the parent window to flicker as it loses and then regains focus. Basically I want something that works like a combo box, where the scroll bar can be clicked or dragged around, but keyboard input still goes to the dialog itself, not just the scroll bar, and the whole thing never loses focus.
I haven't done anything like this for a long time, so I'm sure there are a million little details, but I think the starting point is to override the handling of WM_MOUSEACTIVATE.
I am a little confused about child-parent relationship you described.
Can you explain what do you mean by:
The CDialog is parented off of an edit box that I want to keep focus at all times
Any window hosting other windows inside of the client area is a parent of those windows. It is impossible to create window without WS_CHILD that is contained by other window.
Therefore all dialog’s controls are children of this dialog. It is also possible that child window hosts another child window.
CDialog is just an MFC representation of a dialog window; the same applies to other controls. For example CButton is an MFC class that wraps handle of the window’s window that is predefined as window button control.
Dialog never has focus unless is empty (does not have any controls). If dialog contains even one control, this control always has focus.
What focus means is that any given window receives mouse and keyboard messages. Only one control can have focus at any given time. In order for scroll bar to process mouse click or keyboard to move slider, scroll bar must have focus; therefore some other control must give it up.
Combo box drop box (I think this is what you are referring to) is not a child of the dialog. It is a popup window that for the duration has keyboard focus and captures mouse. When it drops down, dialog is deactivated and once dropdown hides, dialog state is changed back to active hence focus never changes, it returns to the control that had focus when dialog was deactivated.
What you are trying to do is probably possible but it would require a lot of coding. Probably hooking messages would do the job but I think it would be going against the stream.

Scrollbar moves back after WM_VSCROLL

I have a window with its own H and V scrolling. I'm handling the event like this:
case WM_VSCROLL:
SetScrollPos(hWnd, SB_VERT, (int)HIWORD(wParam), TRUE);
break;
all I want is for the position of the scroll bar to stay once I release my mouse but what it's doing is just going back to the top after. What am I doing wrong?
Thanks
The wParam parameter of the WM_VSCROLL message is either SB_TOP, SB_BOTTOM, SB_PAGEUP, SB_PAGEDOWN, SB_LINEUP, SB_LINEDOWN, SB_THUMBPOSITION, or SB_THUMBTRACK, where the names ought to explain themselves.
SB_TOP and SB_BOTTOM means that the scrolling window is to go to the top or bottom, respectively. These messages can be sent by right-clicking a vertical scroll bar and selecting "Top" and "Bottom". (Look in Windows Notepad, Win XP+, for instance.)
SB_PAGEUP and SB_PAGEDOWN means a page (screen) up or down. These are sent if you click somwhere on the scrollbar beside on the thumb or the up or down arrows, or if you use the scrollbar's right-click menu.
SB_LINEUP and SB_LINEDOWN are sent when the user clicks the up and down buttons on the scrollbar, or selects the appropriate right-click menu commands.
SB_THUMBTRACK is sent continuously when the user scrolls by dragging the thumb of the scrollbar.
SB_THUMBPOSITION is sent when the user has released the thumb.
See the MSDN article WM_VSCROLL for more information.
So, when you receive a WM_VSCROLL message, you first need to do the scrolling itself. If, for instance, you are writing a text editor, then you need to redraw the text, but with a different row at the top of the window. Then you need to update the scrollbar to its new position, preferably by means of SetScrollInfo, but you can also use the old SetScrollPos function.
In the case section, the system is processing a WM_VSCROLL message. It will run the default window procedure after your SetScrollPos. In the default window procedure, the system itself will set the scroll bar's thumb position. So, although SetScrollPos takes effects, the system change the thumb position after that anyway. I think you should do your SetScrollPos after calling the default window procedure, i.e., maybe after returning this funciton, and then you can SetScrollPos.