Handle WM_NOTIFY of a grand child control - c++

I've a MFC dialog and an ActiveX grid control on it. Whenever user tries to edit a date type grid cell, I'm creating a CDateTimeCtrl and showing inside the grid. This control is being created as a child to the grid control, but is a variable in the dialog class.
Now, I'd like to handle the DTN_DATETIMECHANGE message of this date control in my dialog's class. I can see in Spy++, that these messages being sent to the grid control, but how do we handle this in the grand parent's (dialog) class?

Have you tried creating it as a sibling, but just higher in the Z order? You might need to add WS_CLIPSIBLINGS to the parent dialog's style to avoid issues where the grid paints over the date control.
An alternate techique is to use an intermediate child that acts as forwarder, so grid contains forwarder which contains date control. That way your code still receives the notifications; and you still get the appropriate HWND containment effects. (The forwarder typically has no border, and just resizes its only child to take up its entire client area, so is not visible to an end-user.)

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.

MFC Tab control without tabs?

I'm wanting to make something like a tab control, but without visible tabs at the top.
I would prefer to have the tabs selected from a list or tree at the left hand side of the page, something like this...
Selecting the list/tree item at the left changes everything on the right-hand side of the dialog.
I know I could do this by individually showing/hiding all the fields on the RHS, depending on the selected view, but this is unmanageable to design, when there are at least 10 different designs. C++ doesn't let me design groups and make them visible/invisible in one go. I would prefer to design them as totally separate dialog resources, and then bring them in, like a tab control.
I believe Windows Forms has a ContentControl, which is like a tab control without the tabs, which sounds perfect, but MFC doesn't seem to have this.
Is there a way to do this nicely? Or maybe even a 3rd party control to handle it?
In MFC you would do this by making a child modeless dialog for each group. For each dialog turn off the titlebar style and border style and it will blend in to the parent window instead of looking like a dialog. Create all the dialogs, then use ShowWindow to show/hide one at a time.
Minor detail: Put an invisible control (like a group box) on the parent window to serve as a landmark. When you create each dialog use MoveWindow to position and size it on the landmark.
Use window style WS_EX_CONTROLPARENT in the parent window to help with tab key navigation from parent to child.
Yes you can using DIALOG resources. Set the DIALOG Style to Child, Border to None, Title Bar to False. You can then add implementation classes/files for each DIALOG. The dialogs are then inserted/removed to and fro the parent as a child components by setting the containing window as the dialog's parent (i.e., SetParent)

Child Windows that does not occupy client area

In the Win32 API (pure win32), The Menu bar does not occupy any area from the client area of the window. Which means the origin coordinates of the client area is right under the menu bar to the left.
When we create child window controls using CreateWindow (or any other method), that window takes some area of the client-area.
eg:- Creating a button which is at (xPos = 0, yPos = 0) and (width=width_of_client_area, height=20).
After creating the button if you'll use a GDI function like this, it'll be drew below the button:
Rectangle(hdc, 0,0, 200, 200);
But when creating a menu bar, it doesn't occupy client area. (GDI will not be drew under menu).
FINAL QUESTION:
How can i create a control on my parent window like the menu bar ?
The menu is rendered in the non-client area of the window, which is driven by a completely different set of window messages. Keep in mind that you don't actually create child windows for these types of controls. You will need to provide all the rendering and event handling for the customization you want to add. This means that if you want to add a button or checkbox you will need to implement it yourself. You can get your started with a handful of steps but there may be other things that need to be done depending on your requirements.
The first step is to process the WM_NCCALCSIZE message. This will allow you to adjust the size of the non-client area so that you have more space to draw the custom control. Basically you will pass this message on to the default window proc then modify the location and dimensions (just drop the top down X pixels) before returning.
The next step is to handle WM_NCPAINT message. Pass the message on to the default window proc then draw your custom visuals in the area you have reserved. You will be working with a window DC so you can draw to the entire window. It's important to keep this in mind so you don't destroy anything in the client area.
The last item that needs to be done is to handle mouse messages like WM_NCMOUSEMOVE. If the mouse event occurs outside the area where your control is located pass the message to the default window proc, otherwise handle the message yourself and skip the default proc. you will need to manage some state data for keeping track of when a button is down or not so as not to cause conflicts with the default window proc.
Keep in mind that when you want to draw directly to the non-client area you need to call GetWindowDC() instead of GetDC() to acquire a device context.
[Note: A good Google dance will be something like "WinAPI non-client area"]

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.

Bona fide transiant windows with WinAPI?

I want to create a Window like when a context menu pops up or clicking the menubar. I want a Window that will be like this and that I can take over its paint event. Sort of like what is created when you select a sub tool in Photoshop.
EDIT:I want to know how to create controls like the one that comes when you select a sub tool in Photoshop, these do not seem to have a parent window. Those little description popups are a good example of this type of window, and menu items, those rectangles have no parent window.
Thanks
EDIT2: see this: http://cdn-viper.demandvideo.com/media/CB3C805F-421E-45AE-8359-39D59D8F0165/jpeg/20412728-192C-462A-AF8E-1F30BA77AE05_2.jpg
You will notice the window for the sub tools, it is not constrained to a parent window.
But how do they get a nice shadow
around it, and how does it still stay
with the main window without a parent?
That's your real question.
There are several ways of getting the shadow. One is that the window is actually two windows, the "shadow" plus the "main" window.
When you create the flyout window (that's what it's called), you position it near the toolbar. If the toolbar gets a WM_MOVE message, it's your responsibility to call MoveWindow() on the flyout to keep it lined up.
Edited to add
The dwExStyle parameter of CreateWindowEx() should include WS_EX_LAYERED and probably WS_EX_TRANSPARENT, because the 'shadow' will use alpha blending. The hWndParent parameter is the application's main window. The x and y parameters must be calculated as an offset of whatever button the window is to be associated with.