I want to create a dialog window for change settings of an application. Below is a screenshot of Adobe Reader. After using Spy++, I guess that:
On the right side, all the control (buttons, combo boxes...ect) are belonged to a GroupBox.
For each category in the TreeView Control on the left side, there is a corresponding GroupBox which groups all the controls related to this category.
When users choose between different categories, it hides one GroupBox and shows another one GroupBox.
But in the source code (xxx.rc, resource file) below, I didn't see anywhere where I can specify the "parent" of a dialog item.
Even I open xxx.rc with "Resource View" (not viewed as codes), I can't find any option to specify the parent of a dialog item in its property page.
I would like to know how to assign a parent (which is a GroupBox in my case) to a dialog item, or group dialog items to a single group,in the .rc file, i.e when one create the dialog items. (I guess one can do so by modifying the .rc file.)
GROUPBOX "View",IDC_SECTION_VIEW,101,6,228,88
LTEXT "Default &Layout:",IDC_DEFAULT_LAYOUT_LABEL,107,19,108,9
COMBOBOX IDC_DEFAULT_LAYOUT,215,17,108,64,CBS_DROPDOWNLIST | WS_TABSTOP
LTEXT "Default &Zoom:",IDC_DEFAULT_ZOOM_LABEL,107,36,108,9
COMBOBOX IDC_DEFAULT_ZOOM,215,34,108,149,CBS_DROPDOWN | WS_TABSTOP
CONTROL "Show the &bookmarks sidebar when available",IDC_DEFAULT_SHOW_TOC,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,53,216,9
...
...
...
I would like to know how to assign a parent...
SetParent Windows API. You supply HWND of your control and the handle of the supposed new parent.
In resource script, the controls will be children of the dialog itself, but on runtime you are free to change this and group them into a hierarchy of your interest.
You might also want to consider putting the supposed child groups into separate dialog template and have it as "composite control" - to be instantiated separately and be a child of a higher level dialog.
UPD. Have a look at this simple project (C++/ATL): AtlChildDialog. In particular, at main dialog's WM_INITIDIALOG handler:
ATLVERIFY(m_ChildDialog.Create(m_hWnd, (LPARAM) this));
ATLVERIFY(m_ChildDialog.MoveWindow(50, 50, 200, 150));
m_ChildDialog.m_EditWindow.SetWindowText(_T("Some Text"));
m_ChildDialog.ShowWindow(SW_SHOWNORMAL);
m_ChildDialog.SetFocus();
All together on runtime:
Related
I my application, I have added a dropdown box to the standard windows file open dialog. This works fine, but I would like to position this drop box exactly below the file name and file mask edit controls, and its label exactly below the labels for these controls.
How can I get the positions of these controls and the corresponding labels (it depends on the Windows version and maybe even on theming, so using the constants that make the dialog look fine on my computer won't do)?
On Vista+, you should be using the IFileDialog, IFileOpenDialog and IFileDialogCustomize interfaces:
Common Item Dialog
Customizing the Dialog
You can use the IFileDialogCustomize::AddText() and IFileDialogCustomize::AddComboBox() methods to add a drop-down list and its label to the dialog, and if needed use the IFileDialogControlEvents::OnItemSelected event to react to the user selecting items in your drop-down list.
However, you cannot decide where custom controls are displayed when customizing this dialog. UI layout is controlled by the dialog itself:
The Common Item Dialog implementation found in Windows Vista provides several advantages over the implementation provided in earlier versions:
...
•Enables simple customization of the dialog, such as setting the label on the OK button, without requiring a hook procedure.
•Supports more extensive customization of the dialog by the addition of a set of data-driven controls that operate without a Win32 dialog template. This customization scheme frees the calling process from UI layout. Since any changes to the dialog design continue to use this data model, the dialog implementation is not tied to the specific current version of the dialog.
...
The only layout access it provides is the order in which you add your custom controls, and any visual grouping. So, you could use IFileDialogCustomize::StartVisualGroup() to create a new group, then call AddText() and AddComboBox() (in that order) to add those controls to the group, and then finally call IFileDialogCustomize::EndVisualGroup().
On the other hand, when using GetOpenFileName() instead, there are some different options for customizing that dialog, and they allow you much finer grain control over the dialog's layout:
Customizing Common Dialog Boxes
Open and Save As Dialog Box Customization
The preferred option is to create a custom dialog box template and specify it in the OPENFILENAME structure. Within the template, you can have whatever controls and layout you want, and then the template can be inserted as a child of a standard Explorer-style dialog, or as a replacement for a standard Old-style dialog. MSDN documents how to custom-position a template within an Explorer-style dialog:
Explorer-Style Custom Templates
To make room for the new controls, the system expands the default dialog box by the width and height of the custom dialog box. By default, all controls from the custom dialog box are positioned below the controls in the default dialog box. However, you can override this default positioning by including a static text control in your custom dialog box template and assigning it the control identifier value of stc32. (This value is defined in the Dlgs.h header file.) In this case, the system uses the control as the point of reference for determining where to position the new controls. All new controls above and to the left of the stc32 control are positioned the same amount above and to the left of the controls in the default dialog box. New controls below and to the right of the stc32 control are positioned below and to the right of the default controls. In general, each new control is positioned so that it has the same position relative to the default controls as it had to the stc32 control. To make room for these new controls, the system adds space to the left, right, bottom, and top of the default dialog box as needed.
The alternative, without using a custom template, is to obtain the dialog's own HWND directly (which can be gotten inside a hook function assigned to the OPENFILENAME::lpfnHook field) and then you have full access to do whatever you want with the dialog. Microsoft assigned fixed control IDs to the standard controls of an Explorer-style dialog (so you must specify the OFN_EXPLORER flag for this approach to work), and those IDs are consistent across Windows versions. Those IDs are meant to be used with the CDM_SETCONTROLTEXT and CDM_HIDECONTROL messages, but they can also be used with GetDlgItem() to get the HWND of certain dialog controls, in this case the cmb13, edt1 and stc3 controls:
cmb13
Drop-down combo box that displays the name of the current file, allows the user to type the name of a file to open, and select a file that has been opened or saved recently. This is for earlier Explorer-compatible applications without hook or dialog template. Compare with edt1.
edt1
Edit control that displays the name of the current file, or allows the user to type the name of the file to open. Compare with cmb13.
stc3
Label for the cmb13 combo box and the edt1 edit control
Once you have those HWNDs, you can manually query their current positions and sizes, add your custom drop-down list underneath them as needed, and resize the dialog's HWND to accommodate your drop-down list.
Whether you use a template or direct HWND manipulation, you would need to use a dialog hook function to process messages from your drop-down list as needed, such as the CBN_SELCHANGE notification.
Ist it possible, given a HMENU, to detect if it's a popup or a drop down menu?
I want to create a (deep, modified) copy of an existing menu, and depending on this property I need to use either CreatePopupMenu or CreateMenu, respectively.
As Raymond Chen says here (with my emphasis):
CreateMenu creates a horizontal menu bar, suitable for attaching to a
top-level window. This is the sort of menu that says "File, Edit", and
so on. CreatePopupMenu creates a vertical popup menu, suitable for
use as a submenu of another menu (either a horizontal menu bar or
another popup menu) or as the root of a context menu.
If you get the two confused, you can get strange menu behavior.
Windows on rare occasions detects that you confused the two and
converts as appropriate, but I wouldn't count on Windows successfully
reading your mind.
There is no way to take a menu and ask it whether it is horizontal or
vertical. You just have to know.
Not clear with hmenu:
1) If you talk about hmenu, corresponding to the existing window (class #32768), it is sufficient to verify (via GetGUIThreadInfo) GUITHREADINFO.flags: availability GUI_INMENUMODE without GUI_POPUPMENUMODE without GUI_SYSTEMMENUMODE means that this menu - drop down.
2) If you talk about hmenu, existing in memory, we must find the root parent of this hmenu (btw, for menu there may be more than one, in contrast to the root parent window).
Then call TrackPopupMenu for found root parent and on WM_ENTERIDLE get hwnd appropriate window (class #32768) and call GetClientRect: if Rect =0, then the root parent = menubar (which can be created via LoadMenu(Indirect) or via CreateMenu), which means that the original hmenu - drop down (which can be created not only via CreatePopupMenu, but also via CreateMenu).
As for link to R.Chen. In reality the system always remembers exactly how was created hmenu in memory. But this mechanism (like so much else concerning the menu) is undocumented and Raymond obviously did not consider it necessary to uncover it...
I have a MFC dialog based application.
The main dialog contain a child dialog (used in a CTabCtrl control).
CDialog mainDlgClass;
CMyChildDialog childDlgClass;
How I can be able to modify the controls of the child dialog from the main dialog or the possibility to send a message, eg: via PostMessage and using RegisterWindowMessage so I can modify the child dialog's controls?
I dont know howto retrieve a handle of the child dialog.
void mainDlgClass::check()
{
if(condition)
PostMessage_to_the_child_dialog(***);
OR
if(condition)
Modify_CStatic_text_on_the_child_dialog(***);
}
Edit:
Screenshot of the structure:
Resource editor
Main dialog + CTabCtrl containing the ChidlDialog
Child dialog have WS_CHILD property set.
Resolved.
Assuming that the second dialog is a child dialog of the main (it has WS_CHILD style), it must be created by the main dialog. Child dialog is confined to a client area of the parent window.
You can provide public member functions (accessors) in the child dialog class to be accessed by the main dialog and change whatever you need. Alternatively, you can access subclassed child’s dialog controls directly if they are declared public (led OOP-like).
The problem is that you may refer to a second dialog as child while it is not really a child (does not have WS_CHILD style). Nevertheless, you can use method described above if the second dialog is spawned as modeless.
If modal, the approach may differ, since the main dialog is disabled; therefore, user cannot access main dialog controls. If this is a case, could you please give us more information?
For example, under what circumstances, you want to alter controls.
I'm working on a Windows project with a simple dialog created with CreateWindowEx() it contains multiple panes loaded with CreateDialog() to load the layout from a resource file. On the child panes there are a number of controls including text boxes and buttons which I would like to use TAB to navigate around but all I get is the Windows 'bing' telling me that the key does not do anything. My message loop looks like this:
while( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) )
{
if( !IsDialogMessage(0, &msg) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
And each control window has WS_TABSTOP set in the style as well as the owner pane having WS_EX_CONTROLPARENT set.
Is there anything else I need to do to make the tab key work?
Thanks,
J
Try this:
http://support.microsoft.com/kb/71450 (How To Use One IsDialogMessage() Call for Many Modeless Dialogs)
You panes are modeless dialogs, and IsDialogMessage is responsible for handling Tab keys. I hope that this article exactly matches your case.
The WS_TABSTOP Style
The WS_TABSTOP style specifies the controls to which the user can move by pressing the TAB key or SHIFT+TAB keys.
When the user presses TAB or SHIFT+TAB, the system first determines whether these keys are processed by the control that currently has the input focus. It sends the control a WM_GETDLGCODE message, and if the control returns DLGC_WANTTAB, the system passes the keys to the control. Otherwise, the system uses the GetNextDlgTabItem function to locate the next control that is visible, not disabled, and that has the WS_TABSTOP style. The search starts with the control currently having the input focus and proceeds in the order in which the controls were createdthat is, the order in which they are defined in the dialog box template. When the system locates a control having the required characteristics, the system moves the input focus to it.
If the search for the next control with the WS_TABSTOP style encounters a window with the WS_EX_CONTROLPARENT style, the system recursively searches the window's children.
An application can also use GetNextDlgTabItem to locate controls having the WS_TABSTOP style. The function retrieves the window handle of the next or previous control having the WS_TABSTOP style without moving the input focus.
Source: MSDN.
if( !IsDialogMessage(0, &msg) )
The first argument should not be NULL, it must be the handle of a dialog. Painful here of course.
Often time I need to add a control to a dialog after the dialog has been generated via dialog template and CreateDialogIndirect. In these cases the tab order is set by the dialog template and there is no obvious way to change the tab order by including a newly created control.
I recently discovered that you can use SetWindowPos to accomplish this. Determine which control after which you want to insert the new control in the tab order then use SetWindowPos like this:
SetWindowPos(hNewControl, hOldControl, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
This changes the z-order of controls which, in turn, establishes the tab order.
I know this is an old question but here is how to do it at compile time (which is preferable in the vast majority of cases):
http://msdn.microsoft.com/en-us/library/7039hzb0(v=vs.80).aspx
My favourite method:
From the View menu, choose Tab Order.
Choose Assign Interactively.
Double-click the tab order box beside the control you want to be the
first control in the tab order.
Click the tab order box for each of the other controls.
Click anywhere on the form to save your changes and exit Tab Order
mode, or press ESC to exit Tab Order mode without saving your
changes.