home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / dlgcbr.zip / MDLSMAIN.CPP < prev    next >
C/C++ Source or Header  |  1994-06-30  |  15KB  |  472 lines

  1. /*****************************************************************************
  2.   MDLSMAIN.CPP
  3.  
  4.   Purpose:  
  5.       Implements CModelessMain, a reusable class for creating modeless
  6.       dialogs which act as main application windows.  The dialog contains
  7.       a status bar and a tool bar.  It provides support for ID_VIEW_STATUS_BAR
  8.       and ID_VIEW_TOOLBAR commands, as well as CAPS, NUM, and SCRL key 
  9.       indicators.
  10.  
  11.   Functions:
  12.       CModelessMain::CModelessMain()            -- constructor
  13.       CModelessMain::~CModelessMain()            -- destructor
  14.       CModelessMain::Create()                    -- Create dialog window   
  15.       CModelessMain::OnClose()                -- handle WM_CLOSE   
  16.       CModelessMain::OnEnterIdle()            -- handle WM_ENTERIDLE
  17.       CModelessMain::OnEraseBkgnd()            -- handle WM_ERASEBKGND  
  18.       CModelessMain::OnInitDialog()            -- initialize dialog  
  19.       CModelessMain::OnInitMenuPopup()        -- handle WM_INITMENUPOPUP
  20.       CModelessMain::OnMenuSelect()            -- handle WM_MENUSELECT
  21.       CModelessMain::OnPaint()                -- handle WM_PAINT
  22.       CModelessMain::OnQueryDragIcon()        -- handle WM_QUERYDRAGICON
  23.       CModelessMain::OnSetMessageString()     -- handle WM_SETMESSAGESTRING
  24.       CModelessMain::OnStatusBarCheck()       -- ID_VIEW_STATUS_BAR handler
  25.       CModelessMain::OnToolBarCheck()            -- ID_VIEW_TOOLBAR handler     
  26.       CModelessMain::OnUpdateKeyIndicator()    -- update key indicator items
  27.       CModelessMain::OnUpdateStatusBarMenu()    -- update ID_VIEW_STATUS_BAR items
  28.       CModelessMain::OnUpdateToolBarMenu()    -- update ID_VIEW_TOOLBAR items
  29.  
  30.   Development Team:
  31.       Mary Kirtland
  32.  
  33.   Written by Microsoft Product Support Services, Premier ISV Support
  34.   Copyright (c) 1994 Microsoft Corporation. All rights reserved.
  35. \****************************************************************************/
  36.  
  37. #include "stdafx.h"   
  38. #include <afxpriv.h>
  39. #include "mdlsmain.h"
  40.  
  41. #ifdef _DEBUG
  42.     #undef THIS_FILE
  43.     static char BASED_CODE THIS_FILE[] = __FILE__;
  44. #endif
  45.  
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CModelessMain 
  48.  
  49. IMPLEMENT_DYNAMIC(CModelessMain, CModelessDialog)
  50.  
  51. BEGIN_MESSAGE_MAP(CModelessMain, CModelessDialog)
  52.     //{{AFX_MSG_MAP(CModelessMain)
  53.     ON_WM_CLOSE()
  54.     ON_WM_PAINT()
  55.     ON_WM_ERASEBKGND()
  56.     ON_WM_QUERYDRAGICON()
  57.     ON_WM_ENTERIDLE()
  58.     ON_WM_INITMENUPOPUP()
  59.     ON_WM_MENUSELECT()     
  60.     ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString) 
  61.     //}}AFX_MSG_MAP
  62.     
  63.     // Standard View menu options
  64.     ON_COMMAND(ID_VIEW_STATUS_BAR, OnStatusBarCheck)  
  65.     ON_COMMAND(ID_VIEW_TOOLBAR, OnToolBarCheck)
  66.     ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateStatusBarMenu)
  67.     ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateToolBarMenu) 
  68.     
  69.     // Standard status bar mode indicators    
  70.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyIndicator)
  71.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, OnUpdateKeyIndicator)
  72.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, OnUpdateKeyIndicator)
  73.     
  74. END_MESSAGE_MAP()
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CModelessMain Construction/Destruction
  78.  
  79. CModelessMain::CModelessMain() 
  80. {  
  81.     m_hIcon = NULL;  
  82.     
  83.     m_nIDTracking     = 0;
  84.     m_nIDLastMessage  = 0;
  85.     
  86.     m_lpaIDStatusBar  = NULL;
  87.     m_cIDStatusBar    = 0;  
  88.     
  89.     m_lpaIDToolBar    = NULL;
  90.     m_cIDToolBar      = 0;
  91.     m_nIDBitmap          = 0;
  92. }
  93.         
  94. CModelessMain::~CModelessMain()
  95. {
  96. }
  97.  
  98. ////////////////////////////////////////////////////////////////////////////
  99. // CModelessMain::Create
  100. //        Create saves away information about the status bar and toolbar,
  101. //        loads the dialog icon, and creates the dialog window.  It assumes
  102. //        the dialog icon has the same resource ID as the dialog template
  103. //        itself.        
  104.  
  105. BOOL CModelessMain::Create(UINT nIDTemplate,
  106.                            const UINT FAR* lpaIDStatus, int cIDStatus,
  107.                            const UINT FAR* lpaIDToolbar, int cIDToolbar,
  108.                            UINT nIDBitmap) 
  109. {                                             
  110.     m_hIcon = AfxGetApp()->LoadIcon(nIDTemplate);
  111.     
  112.     m_lpaIDStatusBar = lpaIDStatus;
  113.     m_cIDStatusBar   = cIDStatus;        
  114.     
  115.     m_lpaIDToolBar   = lpaIDToolbar;
  116.     m_cIDToolBar     = cIDToolbar;
  117.     m_nIDBitmap         = nIDBitmap;
  118.     
  119.     return CModelessDialog::Create(nIDTemplate);
  120. }
  121.  
  122. BOOL CModelessMain::Create(LPCSTR lpszTemplateName, 
  123.                            const UINT FAR* lpaIDStatus, int cIDStatus,
  124.                            const UINT FAR* lpaIDToolbar, int cIDToolbar,
  125.                            UINT nIDBitmap) 
  126. {                                                
  127.     ASSERT(lpszTemplateName != NULL);                 
  128.     
  129.     m_hIcon = AfxGetApp()->LoadIcon(lpszTemplateName);
  130.     
  131.     m_lpaIDStatusBar = lpaIDStatus;
  132.     m_cIDStatusBar   = cIDStatus;
  133.     
  134.     m_lpaIDToolBar   = lpaIDToolbar;
  135.     m_cIDToolBar     = cIDToolbar;
  136.     m_nIDBitmap         = nIDBitmap;
  137.     
  138.     return CModelessDialog::Create(lpszTemplateName);
  139. }       
  140.  
  141.         
  142. /////////////////////////////////////////////////////////////////////////////
  143. // CModelessMain::OnClose
  144. //        OnClose handles the WM_CLOSE message by posting a WM_QUIT message
  145. //        (so the app shuts down), after performing default processing to
  146. //        actually close the window.
  147.  
  148. void CModelessMain::OnClose() 
  149. {
  150.     CModelessDialog::OnClose();
  151.     PostQuitMessage(0);
  152. }
  153.            
  154. /////////////////////////////////////////////////////////////////////////////
  155. // CModelessMain::OnInitDialog
  156. //        OnInitDialog centers the dialog on the screen and creates the status
  157. //        and toolbars.  To make sure the control bars don't overlap any
  158. //        dialog controls, the dialog's client area is expanded by the amount
  159. //        of space required for the control bars.
  160.  
  161. BOOL CModelessMain::OnInitDialog()
  162. {
  163.     CModelessDialog::OnInitDialog();
  164.         
  165.     // Create status bar at the bottom of the dialog window                   
  166.     if (m_statusBar.Create(this))
  167.     {                           
  168.         m_statusBar.SetIndicators(m_lpaIDStatusBar, m_cIDStatusBar);
  169.         OnSetMessageString(AFX_IDS_IDLEMESSAGE);
  170.     }             
  171.  
  172.     // Create toolbar at the top of the dialog window
  173.     if (m_toolBar.Create(this))
  174.     {
  175.         m_toolBar.LoadBitmap(m_nIDBitmap);
  176.         m_toolBar.SetButtons(m_lpaIDToolBar, m_cIDToolBar);
  177.     }             
  178.  
  179.     // We need to resize the dialog to make room for control bars.
  180.     // First, figure out how big the control bars are.
  181.     CRect rcClientStart;
  182.     CRect rcClientNow;
  183.     GetClientRect(rcClientStart);
  184.     RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 
  185.                    0, reposQuery, rcClientNow);
  186.     
  187.     // Now move all the controls so they are in the same relative
  188.     // position within the remaining client area as they would be
  189.     // with no control bars.  We also need to account for the menu bar!
  190.     // We'll assume a single line menu bar, as the dialog manager does.
  191.     CPoint ptOffset(rcClientStart.left - rcClientNow.left,
  192.                     rcClientStart.top - rcClientNow.top); 
  193.     ptOffset.y += ::GetSystemMetrics(SM_CYMENU);
  194.                         
  195.     CRect  rcChild;                    
  196.     CWnd* pwndChild = GetWindow(GW_CHILD);
  197.     while (pwndChild)
  198.     {                               
  199.         pwndChild->GetWindowRect(rcChild);
  200.         rcChild.OffsetRect(ptOffset);
  201.         pwndChild->MoveWindow(rcChild, FALSE);
  202.         pwndChild = pwndChild->GetNextWindow();
  203.     }
  204.  
  205.     // Adjust the dialog window dimensions
  206.     CRect rcWindow;
  207.     GetWindowRect(rcWindow);
  208.     rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
  209.     rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
  210.     MoveWindow(rcWindow, FALSE);
  211.     
  212.     // And position the control bars
  213.     RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); 
  214.     
  215.     // Finally, center the dialog on the screen
  216.     CenterWindow();
  217.     return TRUE;
  218. }
  219.                  
  220. /////////////////////////////////////////////////////////////////////////////
  221. // CModelessMain::OnPaint
  222. // CModelessMain::OnEraseBkgnd
  223. // CModelessMain::OnQueryDragIcon
  224. //        These functions are used to display a custom icon for the dialog.
  225. //
  226. //       These functions use a technique described in KB article Q87976
  227. //        to display a custom icon for our dialog window.  We assume that
  228. //        the icon has been loaded into m_hIcon.
  229.                  
  230. void CModelessMain::OnPaint() 
  231. {
  232.     CPaintDC dc(this);
  233.     if (IsIconic() && m_hIcon)
  234.     {
  235.         // Erase the icon background when placed over other app window
  236.         DefWindowProc(WM_ICONERASEBKGND, (WORD)dc.m_hDC, 0L);
  237.         
  238.         // Center the icon
  239.         CRect rc;
  240.         GetClientRect(&rc);
  241.         rc.left = (rc.right - ::GetSystemMetrics(SM_CXICON))/2;
  242.         rc.top  = (rc.bottom - ::GetSystemMetrics(SM_CYICON))/2;
  243.         
  244.         // Draw the icon
  245.         dc.DrawIcon(rc.left, rc.top, m_hIcon);
  246.     }
  247. }
  248.  
  249. BOOL CModelessMain::OnEraseBkgnd(CDC* pDC) 
  250. {
  251.     if (IsIconic() && m_hIcon)
  252.         return TRUE;
  253.     else    
  254.         return CModelessDialog::OnEraseBkgnd(pDC);
  255. }
  256.  
  257. HCURSOR CModelessMain::OnQueryDragIcon() 
  258. {
  259.     return (HCURSOR)m_hIcon;
  260. }
  261.    
  262. /////////////////////////////////////////////////////////////////////////////
  263. // CModelessMain::OnInitMenuPopup
  264. //        OnInitMenuPopup updates the state of items on a popup menu.  
  265. //
  266. //      This code is based on CFrameWnd::OnInitMenuPopup.  We assume the
  267. //        application does not support context sensitive help.
  268.  
  269. void CModelessMain::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
  270. {
  271.     if (!bSysMenu)
  272.     {
  273.         ASSERT(pPopupMenu != NULL);
  274.         
  275.         // check the enabled state of various menu items
  276.         CCmdUI state;        
  277.         state.m_pMenu = pPopupMenu;
  278.         ASSERT(state.m_pOther == NULL);
  279.         
  280.         state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
  281.         for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  282.              state.m_nIndex++)
  283.         {
  284.             state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);
  285.             if (state.m_nID == 0)
  286.                 continue; // menu separator or invalid cmd - ignore it
  287.                 
  288.             ASSERT(state.m_pOther == NULL);
  289.             ASSERT(state.m_pMenu != NULL);
  290.             if (state.m_nID == (UINT)-1)
  291.             {
  292.                 // possibly a popup menu, route to first item of that popup
  293.                 state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
  294.                 if (state.m_pSubMenu == NULL ||
  295.                     (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
  296.                     state.m_nID == (UINT)-1)
  297.                 {                                 
  298.                     continue; // first item of popup can't be routed to
  299.                 }
  300.                 state.DoUpdate(this, FALSE);  // popups are never auto disabled
  301.             }
  302.             else
  303.             {
  304.                 // normal menu item
  305.                 // Auto enable/disable if command is _not_ a system command
  306.                 state.m_pSubMenu = NULL;
  307.                 state.DoUpdate(this, state.m_nID < 0xF000);
  308.             }
  309.         }
  310.     }
  311. }
  312.  
  313. /////////////////////////////////////////////////////////////////////////////
  314. // CModelessMain::OnEnterIdle
  315. //        OnEnterIdle updates the status bar when there's nothing better to do.
  316. //      This code is based on CFrameWnd::OnEnterIdle.
  317.  
  318. void CModelessMain::OnEnterIdle(UINT nWhy, CWnd* pWho) 
  319. {
  320.     if (nWhy != MSGF_MENU || m_nIDTracking == m_nIDLastMessage)
  321.         return;
  322.         
  323.     OnSetMessageString(m_nIDTracking);
  324.     ASSERT(m_nIDTracking == m_nIDLastMessage);        
  325. }
  326.  
  327. /////////////////////////////////////////////////////////////////////////////
  328. // CModelessMain::OnMenuSelect
  329. //        OnMenuSelect updates the status bar message, based on the state
  330. //        of the dialog menu.  
  331. //
  332. //      This code is based on CFrameWnd::OnMenuSelect.  We assume the
  333. //        application does not support context sensitive help.
  334.  
  335. void CModelessMain::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) 
  336. {
  337.     // set the tracking state
  338.     if (nFlags == 0xFFFF)
  339.     {
  340.         // cancel menu operation (go back to idle now)
  341.         m_nIDTracking = AFX_IDS_IDLEMESSAGE;
  342.         OnSetMessageString(m_nIDTracking);    // set string now
  343.         ASSERT(m_nIDTracking == m_nIDLastMessage);
  344.     }
  345.     else if (nItemID == 0 ||
  346.              nFlags & (MF_SEPARATOR|MF_POPUP|MF_MENUBREAK|MF_MENUBARBREAK))
  347.     {
  348.         // nothing should be displayed
  349.         m_nIDTracking = 0;
  350.     }
  351.     else if (nItemID >= 0xF000 && nItemID < 0xF1F0)
  352.     {
  353.         // special string table entries for system commands    
  354.         m_nIDTracking = ID_COMMAND_FROM_SC(nItemID);
  355.         ASSERT(m_nIDTracking >= AFX_IDS_SCFIRST &&
  356.                m_nIDTracking < AFX_IDS_SCFIRST + 31);
  357.     }
  358.     else
  359.     {
  360.         // track on idle
  361.         m_nIDTracking = nItemID;
  362.     }        
  363. }
  364.  
  365. /////////////////////////////////////////////////////////////////////////////
  366. // CModelessMain::OnSetMessageString
  367. //        OnSetMessageString updates the status bar text.  
  368. //
  369. //          This code is based on CFrameWnd::OnSetMessageString.  We assume
  370. //          a string ID is always passed in wParam.
  371.  
  372. LRESULT CModelessMain::OnSetMessageString(WPARAM wParam, LPARAM lParam)
  373. {
  374.     UINT    nIDMsg = (UINT)wParam;
  375.     CString strMsg;
  376.     
  377.     if (nIDMsg)
  378.     {
  379.         if (strMsg.LoadString(nIDMsg) != 0)
  380.             m_statusBar.SetWindowText(strMsg);
  381.         else
  382.             TRACE1("Warning: no message line prompt for ID %x%04X\n", nIDMsg);
  383.     }   
  384.     
  385.     UINT nIDLast     = m_nIDLastMessage;
  386.     m_nIDLastMessage = nIDMsg;
  387.     m_nIDTracking    = nIDMsg;
  388.     return nIDLast;  
  389.     
  390. }
  391.  
  392. /////////////////////////////////////////////////////////////////////////////
  393. // CModelessMain::OnStatusBarCheck
  394. //        OnStatusBarCheck toggles the status of the status bar when the
  395. //        corresponding View option is selected from the menu.  
  396.  
  397. void CModelessMain::OnStatusBarCheck() 
  398. {
  399.     m_statusBar.ShowWindow(m_statusBar.IsWindowVisible() ? SW_HIDE : SW_SHOWNA);
  400. }
  401.  
  402. /////////////////////////////////////////////////////////////////////////////
  403. // CModelessMain::OnUpdateStatusBarMenu
  404. //        OnUpdateStatusBarMenu checks or unchecks the View option,
  405. //        depending on whether or not the status bar is visible.  
  406.  
  407. void CModelessMain::OnUpdateStatusBarMenu(CCmdUI* pCmdUI) 
  408. {
  409.     ASSERT(pCmdUI->m_nID == ID_VIEW_STATUS_BAR);
  410.     pCmdUI->SetCheck(m_statusBar.IsWindowVisible());
  411. }
  412.  
  413. /////////////////////////////////////////////////////////////////////////////
  414. // CModelessMain::OnToolBarCheck
  415. //        OnToolBarCheck toggles the status of the toolbar when the
  416. //        corresponding View option is selected from the menu.  
  417.  
  418. void CModelessMain::OnToolBarCheck() 
  419. {
  420.     m_toolBar.ShowWindow(m_toolBar.IsWindowVisible() ? SW_HIDE : SW_SHOWNA);
  421. }
  422.  
  423. /////////////////////////////////////////////////////////////////////////////
  424. // CModelessMain::OnUpdateToolBarMenu
  425. //        OnUpdateToolBarMenu checks or unchecks the View option,
  426. //        depending on whether or not the toolbar is visible.
  427.  
  428. void CModelessMain::OnUpdateToolBarMenu(CCmdUI* pCmdUI) 
  429. {
  430.     ASSERT(pCmdUI->m_nID == ID_VIEW_TOOLBAR);
  431.     pCmdUI->SetCheck(m_toolBar.IsWindowVisible());
  432. }
  433.       
  434. /////////////////////////////////////////////////////////////////////////////
  435. // CModelessMain::OnUpdateKeyIndicator
  436. //        OnUpdateKeyIndicator enables or disables one of the key indicators
  437. //        in a status bar.  It recognizes the CAPS, NUM, and SCRL keys.
  438.  
  439. void CModelessMain::OnUpdateKeyIndicator(CCmdUI* pCmdUI)
  440. {
  441.     UINT nVK;
  442.  
  443.     switch (pCmdUI->m_nID)
  444.     {
  445.     case ID_INDICATOR_CAPS:
  446.         nVK = VK_CAPITAL;
  447.         break;
  448.  
  449.     case ID_INDICATOR_NUM:
  450.         nVK = VK_NUMLOCK;
  451.         break;
  452.  
  453.     case ID_INDICATOR_SCRL:
  454.         nVK = VK_SCROLL;
  455.         break;
  456.  
  457.     default:
  458.         TRACE1("Warning: OnUpdateKeyIndicator - unknown indicator 0x%04X\n",
  459.             pCmdUI->m_nID);
  460.         pCmdUI->ContinueRouting();
  461.         return; // not for us
  462.     }
  463.  
  464.     pCmdUI->Enable(::GetKeyState(nVK) & 1);
  465.         // enable static text based on toggled key state
  466.     ASSERT(pCmdUI->m_bEnableChanged);
  467. }           
  468.  
  469.  
  470.  
  471.  
  472.