home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / dlgcbr.zip / README.TXT < prev    next >
Text File  |  1994-11-22  |  11KB  |  251 lines

  1. DLGCBAR: Dialog with Control Bars
  2.  
  3. In a Microsoft Foundation Classes application, control bars such as 
  4. status bars and toolbars are typically attached to a frame window.  
  5. However, for many applications a simple dialog-based user interface 
  6. is sufficient.  MFC does not provide built-in support for adding 
  7. control bars to dialogs.
  8.  
  9. DLGCBR is a sample application which demonstrates how to add a status 
  10. bar and toolbar to a dialog.  In addition, it demonstrates a number of 
  11. techniques related to using a modeless dialog as the main window of a 
  12. MFC application.
  13.  
  14. Note that even though this is possible with MFC, if you want to write 
  15. an app which using a single dialog window and contains a menu, toolbar, 
  16. and status bar, you should consider using MFC's CFormView class and 
  17. the document-view architecture, which provides more robust support 
  18. for these features. 
  19.                  
  20. Adding Control Bars to a Dialog 
  21. ===============================
  22.  
  23. To add a control bar to a dialog, you must create the control bar as 
  24. usual, then make room for the control bar within the client area of 
  25. the dialog.  To get the control bar to function properly, the dialog 
  26. must duplicate some of the functionality of frame windows.  If you 
  27. want ON_UPDATE_COMMAND_UI handlers to work for the control bars, you 
  28. also need to derive new control bar classes and handle the 
  29. WM_IDLEUPDATECMDUI message.  If your dialog is not the main window
  30. of your application, you will also need to modify its parent frame
  31. window to pass the WM_IDLEUPDATECMDUI message on to the dialog's
  32. control bars.
  33.  
  34. In the sample program, the class CModelessMain is used to implement 
  35. the dialog's support for control bars.  The classes CDlgToolBar and 
  36. CDlgStatusBar extended the control bar classes so ON_UPDATE_COMMAND_UI 
  37. will work for control bars within a dialog.
  38.  
  39. To make room for a control bar within the client area of the dialog, 
  40. follow these steps in your dialog's OnInitDialog() function:
  41.  
  42. 1.  Create the control bars.  
  43.  
  44. 2.  Figure out how much room the control bars will take using the 
  45.     reposQuery option of RepositionBars():
  46.  
  47.     CRect rcClientStart;
  48.     CRect rcClientNow;
  49.     GetClientRect(rcClientStart);
  50.     RepositionBars(AFX_IDW_CONTROLBAR_FIRST, 
  51.                    AFX_IDW_CONTROLBAR_LAST,
  52.                    0, reposQuery, rcClientNow);
  53.  
  54. 3.  Move all the controls in your dialog, to account for space used 
  55.     by control bars at the top or left of the client area.  If your 
  56.     dialog contains a menu, you will also need to account for the 
  57.     space used by the menu:
  58.  
  59.     CPoint ptOffset(rcClientStart.left - rcClientNow.left, 
  60.                     rcClientStart.top - rcClientNow.top);
  61.     ptOffset.y += ::GetSystemMetrics(SM_CYMENU);
  62.  
  63.     CRect rcChild;
  64.     CWnd* pwndChild = GetWindow(GW_CHILD);
  65.     while (pwndChild)
  66.     {
  67.        pwndChild->GetWindowRect(rcChild);
  68.        rcChild.OffsetRect(ptOffset);
  69.        pwndChild->MoveWindow(rcChild, FALSE);
  70.        pwndChild = pwndChild->GetNextWindow();
  71.     }
  72.  
  73. 4.  Increase the dialog window dimensions by the amount of space 
  74.     used by the control bars:
  75.  
  76.     CRect rcWindow;
  77.     GetWindowRect(rcWindow);
  78.     rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
  79.     rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
  80.     MoveWindow(rcWindow, FALSE);
  81.  
  82. 5.  Position the control bars using RepositionBars().
  83.  
  84. To update the first pane of a status bar with menu item text, you must 
  85. handle WM_MENUSELECT, WM_ENTERIDLE, and WM_SETMESSAGESTRING in your 
  86. dialog class.  You need to duplicate the functionality of the CFrameWnd 
  87. handlers for these messages.  See the CModelessMain class in the sample 
  88. program for examples of these message handlers.
  89.  
  90. To allow ON_UPDATE_COMMAND_UI handlers to work for other status bar panes 
  91. and for toolbar buttons, you must derive new control bar classes and 
  92. implement a message handler for WM_IDLEUPDATECMDUI.  This is necessary 
  93. because the default control bar implementations of OnUpdateCmdUI() assume 
  94. the parent window is a frame window.  However, it doesn't do anything but 
  95. pass the parent window pointer on to a function which only requires a 
  96. CCmdTarget pointer.  So you can temporarily tell OnUpdateCmdUI() that the 
  97. parent window pointer you are giving it is a CFrameWnd pointer, to keep 
  98. the compiler happy.  For example,
  99.  
  100.     LRESULT CDlgToolBar::OnIdleUpdateCmdUI(WPARAM wParam, 
  101.                                            LPARAM lParam)
  102.     {
  103.        if (IsWindowVisible())
  104.        {
  105.           CFrameWnd* pParent = (CFrameWnd*)GetParent();
  106.           if (pParent)
  107.              OnUpdateCmdUI(pParent, (BOOL)wParam);
  108.        }
  109.        return 0L;
  110.     }
  111.                 
  112. To pass WM_IDLEUPDATECMDUI messages on to dialogs other than the main
  113. window, save dialog pointer(s) in your frame window class and create 
  114. a WM_IDLEUPDATECMDUI handler in that class.  The handler should send 
  115. the WM_IDLEUPDATECMDUI message on to the dialog(s) child windows using
  116. CWnd::SendMessageToDescendants(), then perform default processing for 
  117. the message within the frame window.
  118.  
  119. What the Sample App Does
  120. ========================
  121. The sample application displays a list of windows.  As the user changes the 
  122. selection in the listbox, additional information about the window is 
  123. displayed.  Menu options are provided to refill the list immediately and to 
  124. set an interval for automatic updates. 
  125.  
  126. The CWndListDlg class, in wndlist.h and wndlist.cpp, implements the main 
  127. dialog window which displays the window list.  The class CRateDlg, in 
  128. ratedlg,h and ratedlg.cpp, implements a dialog which allows the user to 
  129. set the rate for automatic updates.
  130.  
  131. Additional Techniques
  132. =====================
  133. The sample program implements a number of additional features related
  134. to using a modeless dialog as the main window of your application.  These
  135. are described briefly below.  For further information, see the indicated
  136. KB articles and the source listed in the cross-reference at the end of 
  137. this file.
  138.  
  139. Modeless Dialogs
  140. ----------------
  141. The class CModelessDialog, defined in the files modeless.h and modeless.cpp, 
  142. is a reusable class which implements modeless dialogs, as described in KB 
  143. article Q103788. 
  144.     
  145. Making a Modeless Dialog the Main Window
  146. ----------------------------------------
  147. To use a modeless dialog as the main window, you need to allocate an instance 
  148. of your modeless dialog class and call Create() to create the window.  You 
  149. also need to save a pointer to the window in m_pMainWnd.  Otherwise, MFC will 
  150. immediately exit your application.
  151.  
  152. In addition, you need to provide a way to shut your app down when the dialog 
  153. is closed.  The class CModelessMain, defined in the files mdlsmain.h and 
  154. mdlsmain.cpp, implements a WM_CLOSE handler which calls PostQuitMessage() to 
  155. shut the app down.  
  156.           
  157. This is the minimum amount of work required to implement a modeless dialog 
  158. as the main window.  CModelessMain adds several additional features to improve 
  159. the appearance of the dialog.
  160.       
  161. Providing an Application-Specific Icon for the Dialog          
  162. -----------------------------------------------------   
  163. KB article Q87976 describes two methods for creating a dialog box with a custom 
  164. icon.  CModelessMain uses the first method, which draws the icon in a WM_PAINT 
  165. handler.  CModelessMain loads the icon in its Create() function, and assumes the 
  166. icon has the same resource ID as the dialog it is associated with.  
  167.          
  168. Adding a Menu to the Dialog
  169. ---------------------------
  170. Even though you are using a dialog as the main window of your app, you may still 
  171. need a menu.  KB article Q84129 discusses restrictions on dialogs which contain 
  172. menus.
  173.  
  174. This sample does not try to enforce the style limitations on dialogs, nor does 
  175. it include support for an accelerator table.  However, it does include support 
  176. for MFC's ON_UPDATE_COMMAND_UI handlers to maintain the state of menu items.  
  177. (ON_COMMAND handlers work automatically.)
  178.  
  179. Menu item states are maintained by processing the WM_INITMENUPOPUP message.  The 
  180. code for this message handler is based on the code in CFrameWnd::OnInitMenuPopup.
  181. This implementation does not support context-sensitive help. 
  182.  
  183. Adding Status Bar Support
  184. -------------------------
  185. CModelessMain contains support for a status bar at the bottom of the dialog window.  
  186. When you create a dialog, you specify the array of indicator IDs, and the number of 
  187. indicator IDs.  CModelessMain then creates a status bar for you in OnInitDialog(),
  188. using the technique discussed above.  
  189.  
  190. CModelessMain provides default support for ID_INDICATOR_CAPS, ID_INDICATOR_NUM, and 
  191. ID_INDICATOR_SCRL in OnUpdateKeyIndicator().  The sample program shows how you can 
  192. add your own status bar panes by adding a clock to the status bar.                                      
  193.  
  194. CModelessMain also supports the ID_VIEW_STATUSBAR menu option through 
  195. OnStatusBarCheck() and OnUpdateStatusBarMenu().
  196.  
  197. Adding Toolbar Support
  198. ----------------------
  199. CModelessMain also contains support for a toolbar at the top of the dialog window.  
  200. When you create a dialog, you specify the array of button IDs, the number of 
  201. button IDs, and the resource ID of the toolbar bitmap.  CModelessMain then creates 
  202. a toolbar for you in OnInitDialog(), as discussed above.  
  203.  
  204. CModelessMain also supports the ID_VIEW_TOOLBAR menu option through OnToolBarCheck() 
  205. and OnUpdateToolBarMenu().
  206.  
  207. Limiting the App to a Single Instance
  208. -------------------------------------
  209. This sample uses a technique similar to that described in KB article Q109175 to 
  210. locate the previous instance of the application.  However, instead of searching for 
  211. a matching class name, it searches for a matching caption.  This allows us to use 
  212. the normal dialog class for our main window.            
  213.  
  214.                                              
  215. Cross Reference
  216. ===============
  217.  
  218. Technique        File        Class/Function    
  219. ---------------------    --------------  -------------------------
  220. Modeless dialog        modeless.h    CModelessDialog    
  221.             modeless.cpp
  222.         
  223. Modeless dialog as    dlgcbar.cpp    CTheApp::InitInstance
  224.    main window          mdlsmain.h    CModelessMain
  225.             mdlsmain.cpp
  226.                                                      
  227. App-specific Icon    mdlsmain.h    CModelessMain::OnPaint
  228.             mdlsmain.cpp    CModelessMain::OnEraseBkgnd
  229.                     CModelessMain::OnQueryDragIcon
  230.                     CModelessMain::Create                                                     
  231.                                                      
  232. Menu management        mdlsmain.h    CModelessMain::OnInitMenuPopup
  233.             mdlsmain.cpp
  234.                                                         
  235. Dialog statusbar    mdlsmain.h    CModelessMain::OnInitDialog
  236.             mdlsmain.cpp    CModelessMain::OnMenuSelect
  237.             dlgbars.h    CModelessMain::OnEnterIdle
  238.             dlgbars.cpp    CModelessMain::OnSetMessageString  
  239.                     CModelessMain::OnUpdateKeyIndicator
  240.                     CModelessMain::OnStatusBarCheck
  241.                     CModelessMain::OnUpdateStatusBarMenu 
  242.                     CDlgStatusBar
  243.                                        
  244. Dialog toolbar        mdlsmain.h    CModelessMain::OnInitDialog
  245.             mdlsmain.cpp    CModelessMain::OnToolBarCheck
  246.             dlgbars.h    CModelessMain::OnUpdateToolBarMenu
  247.             dlgbars.cpp    CDlgToolBar
  248.                                                                             
  249. Single-instance App    dlgcbar.h    CTheApp::InitInstance    
  250.             dlgcbar.cpp    CTheApp::FirstInstance
  251.