home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 19
/
CD_ASCQ_19_010295.iso
/
vrac
/
dlgcbr.zip
/
README.TXT
< prev
next >
Wrap
Text File
|
1994-11-22
|
11KB
|
251 lines
DLGCBAR: Dialog with Control Bars
In a Microsoft Foundation Classes application, control bars such as
status bars and toolbars are typically attached to a frame window.
However, for many applications a simple dialog-based user interface
is sufficient. MFC does not provide built-in support for adding
control bars to dialogs.
DLGCBR is a sample application which demonstrates how to add a status
bar and toolbar to a dialog. In addition, it demonstrates a number of
techniques related to using a modeless dialog as the main window of a
MFC application.
Note that even though this is possible with MFC, if you want to write
an app which using a single dialog window and contains a menu, toolbar,
and status bar, you should consider using MFC's CFormView class and
the document-view architecture, which provides more robust support
for these features.
Adding Control Bars to a Dialog
===============================
To add a control bar to a dialog, you must create the control bar as
usual, then make room for the control bar within the client area of
the dialog. To get the control bar to function properly, the dialog
must duplicate some of the functionality of frame windows. If you
want ON_UPDATE_COMMAND_UI handlers to work for the control bars, you
also need to derive new control bar classes and handle the
WM_IDLEUPDATECMDUI message. If your dialog is not the main window
of your application, you will also need to modify its parent frame
window to pass the WM_IDLEUPDATECMDUI message on to the dialog's
control bars.
In the sample program, the class CModelessMain is used to implement
the dialog's support for control bars. The classes CDlgToolBar and
CDlgStatusBar extended the control bar classes so ON_UPDATE_COMMAND_UI
will work for control bars within a dialog.
To make room for a control bar within the client area of the dialog,
follow these steps in your dialog's OnInitDialog() function:
1. Create the control bars.
2. Figure out how much room the control bars will take using the
reposQuery option of RepositionBars():
CRect rcClientStart;
CRect rcClientNow;
GetClientRect(rcClientStart);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,
AFX_IDW_CONTROLBAR_LAST,
0, reposQuery, rcClientNow);
3. Move all the controls in your dialog, to account for space used
by control bars at the top or left of the client area. If your
dialog contains a menu, you will also need to account for the
space used by the menu:
CPoint ptOffset(rcClientStart.left - rcClientNow.left,
rcClientStart.top - rcClientNow.top);
ptOffset.y += ::GetSystemMetrics(SM_CYMENU);
CRect rcChild;
CWnd* pwndChild = GetWindow(GW_CHILD);
while (pwndChild)
{
pwndChild->GetWindowRect(rcChild);
rcChild.OffsetRect(ptOffset);
pwndChild->MoveWindow(rcChild, FALSE);
pwndChild = pwndChild->GetNextWindow();
}
4. Increase the dialog window dimensions by the amount of space
used by the control bars:
CRect rcWindow;
GetWindowRect(rcWindow);
rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
MoveWindow(rcWindow, FALSE);
5. Position the control bars using RepositionBars().
To update the first pane of a status bar with menu item text, you must
handle WM_MENUSELECT, WM_ENTERIDLE, and WM_SETMESSAGESTRING in your
dialog class. You need to duplicate the functionality of the CFrameWnd
handlers for these messages. See the CModelessMain class in the sample
program for examples of these message handlers.
To allow ON_UPDATE_COMMAND_UI handlers to work for other status bar panes
and for toolbar buttons, you must derive new control bar classes and
implement a message handler for WM_IDLEUPDATECMDUI. This is necessary
because the default control bar implementations of OnUpdateCmdUI() assume
the parent window is a frame window. However, it doesn't do anything but
pass the parent window pointer on to a function which only requires a
CCmdTarget pointer. So you can temporarily tell OnUpdateCmdUI() that the
parent window pointer you are giving it is a CFrameWnd pointer, to keep
the compiler happy. For example,
LRESULT CDlgToolBar::OnIdleUpdateCmdUI(WPARAM wParam,
LPARAM lParam)
{
if (IsWindowVisible())
{
CFrameWnd* pParent = (CFrameWnd*)GetParent();
if (pParent)
OnUpdateCmdUI(pParent, (BOOL)wParam);
}
return 0L;
}
To pass WM_IDLEUPDATECMDUI messages on to dialogs other than the main
window, save dialog pointer(s) in your frame window class and create
a WM_IDLEUPDATECMDUI handler in that class. The handler should send
the WM_IDLEUPDATECMDUI message on to the dialog(s) child windows using
CWnd::SendMessageToDescendants(), then perform default processing for
the message within the frame window.
What the Sample App Does
========================
The sample application displays a list of windows. As the user changes the
selection in the listbox, additional information about the window is
displayed. Menu options are provided to refill the list immediately and to
set an interval for automatic updates.
The CWndListDlg class, in wndlist.h and wndlist.cpp, implements the main
dialog window which displays the window list. The class CRateDlg, in
ratedlg,h and ratedlg.cpp, implements a dialog which allows the user to
set the rate for automatic updates.
Additional Techniques
=====================
The sample program implements a number of additional features related
to using a modeless dialog as the main window of your application. These
are described briefly below. For further information, see the indicated
KB articles and the source listed in the cross-reference at the end of
this file.
Modeless Dialogs
----------------
The class CModelessDialog, defined in the files modeless.h and modeless.cpp,
is a reusable class which implements modeless dialogs, as described in KB
article Q103788.
Making a Modeless Dialog the Main Window
----------------------------------------
To use a modeless dialog as the main window, you need to allocate an instance
of your modeless dialog class and call Create() to create the window. You
also need to save a pointer to the window in m_pMainWnd. Otherwise, MFC will
immediately exit your application.
In addition, you need to provide a way to shut your app down when the dialog
is closed. The class CModelessMain, defined in the files mdlsmain.h and
mdlsmain.cpp, implements a WM_CLOSE handler which calls PostQuitMessage() to
shut the app down.
This is the minimum amount of work required to implement a modeless dialog
as the main window. CModelessMain adds several additional features to improve
the appearance of the dialog.
Providing an Application-Specific Icon for the Dialog
-----------------------------------------------------
KB article Q87976 describes two methods for creating a dialog box with a custom
icon. CModelessMain uses the first method, which draws the icon in a WM_PAINT
handler. CModelessMain loads the icon in its Create() function, and assumes the
icon has the same resource ID as the dialog it is associated with.
Adding a Menu to the Dialog
---------------------------
Even though you are using a dialog as the main window of your app, you may still
need a menu. KB article Q84129 discusses restrictions on dialogs which contain
menus.
This sample does not try to enforce the style limitations on dialogs, nor does
it include support for an accelerator table. However, it does include support
for MFC's ON_UPDATE_COMMAND_UI handlers to maintain the state of menu items.
(ON_COMMAND handlers work automatically.)
Menu item states are maintained by processing the WM_INITMENUPOPUP message. The
code for this message handler is based on the code in CFrameWnd::OnInitMenuPopup.
This implementation does not support context-sensitive help.
Adding Status Bar Support
-------------------------
CModelessMain contains support for a status bar at the bottom of the dialog window.
When you create a dialog, you specify the array of indicator IDs, and the number of
indicator IDs. CModelessMain then creates a status bar for you in OnInitDialog(),
using the technique discussed above.
CModelessMain provides default support for ID_INDICATOR_CAPS, ID_INDICATOR_NUM, and
ID_INDICATOR_SCRL in OnUpdateKeyIndicator(). The sample program shows how you can
add your own status bar panes by adding a clock to the status bar.
CModelessMain also supports the ID_VIEW_STATUSBAR menu option through
OnStatusBarCheck() and OnUpdateStatusBarMenu().
Adding Toolbar Support
----------------------
CModelessMain also contains support for a toolbar at the top of the dialog window.
When you create a dialog, you specify the array of button IDs, the number of
button IDs, and the resource ID of the toolbar bitmap. CModelessMain then creates
a toolbar for you in OnInitDialog(), as discussed above.
CModelessMain also supports the ID_VIEW_TOOLBAR menu option through OnToolBarCheck()
and OnUpdateToolBarMenu().
Limiting the App to a Single Instance
-------------------------------------
This sample uses a technique similar to that described in KB article Q109175 to
locate the previous instance of the application. However, instead of searching for
a matching class name, it searches for a matching caption. This allows us to use
the normal dialog class for our main window.
Cross Reference
===============
Technique File Class/Function
--------------------- -------------- -------------------------
Modeless dialog modeless.h CModelessDialog
modeless.cpp
Modeless dialog as dlgcbar.cpp CTheApp::InitInstance
main window mdlsmain.h CModelessMain
mdlsmain.cpp
App-specific Icon mdlsmain.h CModelessMain::OnPaint
mdlsmain.cpp CModelessMain::OnEraseBkgnd
CModelessMain::OnQueryDragIcon
CModelessMain::Create
Menu management mdlsmain.h CModelessMain::OnInitMenuPopup
mdlsmain.cpp
Dialog statusbar mdlsmain.h CModelessMain::OnInitDialog
mdlsmain.cpp CModelessMain::OnMenuSelect
dlgbars.h CModelessMain::OnEnterIdle
dlgbars.cpp CModelessMain::OnSetMessageString
CModelessMain::OnUpdateKeyIndicator
CModelessMain::OnStatusBarCheck
CModelessMain::OnUpdateStatusBarMenu
CDlgStatusBar
Dialog toolbar mdlsmain.h CModelessMain::OnInitDialog
mdlsmain.cpp CModelessMain::OnToolBarCheck
dlgbars.h CModelessMain::OnUpdateToolBarMenu
dlgbars.cpp CDlgToolBar
Single-instance App dlgcbar.h CTheApp::InitInstance
dlgcbar.cpp CTheApp::FirstInstance