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

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

Related

Win32: Combobox loses focus when clicking its child window

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.

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.

MFC Unclickable Button (Running away from cursor on MouseMove)

How would i make a button that will change it's position on MouseMove Event if the cursor is close enough to the center of the button in MFC ?
WM_MOUSEMOVE is not delivered to the button if the cursor is not over it (and is not captured, but you don't want that). So you have to process WM_MOUSEMOVE in the parent dialog. If you want your button to be a self-contained control, you have to subclass the parent window upon button creation.
Subclassing, in this context, means:
- you retrieve and store the parent's window proc address with GetParent()->GetWindowLong(GWL_WNDPROC)
- you set it to your procedure with SetWindowLong()
- in the procedure, you call the parent's previous window proc, after handling WM_MOUSEMOVE the way you want.
The WM_MOUSEMOVE coordinates will be relative to the screen, but you'll probably want to track the button position relative to the window that contains it. Use the ScreenToClient method on the parent window to convert, then you can compare the coordinates to see if it's close. Then use MoveWindow to move the button.
If you track the mouse cursor position you can determine when the cursor gets close to or enters the button window rect. You can then use the SetWindowPos() function to reposition the button window in the parent window client area.

Combobox hidden on resize

Whenever I resize my controls in my window, in response to a WM_SIZE message, they resize and redraw themselves fine. But my combobox control (a dropdown list) disappears whenever I give it a resize message, until I hover over it to bring it back.
There are two possibilities, either it is not redrawing when I resize it, or it is being hidden by my tab control. So how would I solve this problem?
I think the problem is probably the tab control hiding your control.
You can use SetWindowPos to set its z-order with specifying SWP_NOMOVE and SWP_NOSIZE.
You can also use BringWindowToTop to bring the combobox to the top of your z-order.

How to get the window position and update to other windows?

I have 2 dialog boxes in which I will display 1 dialogbox at a time..If I click NEXT in the first dialog box,I will hide the first dialog box and display the second dialog and vice versa...Now say If I move the dialog box after clicking NEXT in the first dialog..and when I click BACK(in the second dialog) ...it goes back to its previous position(to diaplay the first dialog box)..so I have decided to get the current window's position and update to the other window position so that it doesnt move even If I click next/back..I am not sure how to get the windows position and update to other..please help me if you guys know about this..
You can create an OnMove handler for WM_MOVE messages to detect when your window moves. In the handler, you can either move the other window directly with MoveWindow, or you can send a private message to the window (something in the WM_APP range would be best) and let it move itself. Use GetWindowRect to get the width and height to pass to MoveWindow.