home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / shell / fileview / cstathlp.cpp next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  10.8 KB  |  385 lines

  1. //THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  2. //ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  3. //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright  1994-1996  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //    PROGRAM:        CSTATHLP.CPP
  9. //
  10. //    PURPOSE:  Implements the  CStatusHelper class to assist managing the strings for the
  11. //           status bar.  Here we provide menu ID to string ID mapping  services using a mapping 
  12. //           structure in the module's resources.  This code assumes that the status bar is a standard Windows
  13. //           status bar control.
  14. //
  15. //    PLATFORMS:    Windows 95
  16. //
  17. //    SPECIAL INSTRUCTIONS: N/A
  18. //
  19.  
  20. #include "fileview.h"
  21.  
  22. //
  23. //   FUNCTION:     CStatusHelper::CStatusHelper
  24. //
  25. //   PURPOSE:  Constructor for the CStatusHelper class
  26. //
  27. //   PARAMETERS:
  28. //  hWnd            HWND of the Status Bar control to work with.
  29. //  hInst           HINSTANCE of the module we're in.
  30. //
  31. CStatusHelper::CStatusHelper(HWND hWnd, HINSTANCE hInst)
  32.     {
  33.     m_hWnd=hWnd;
  34.     m_hInst=hInst;
  35.  
  36.     m_uIDCur=0xFFFFFFFF;    //Nothing shown yet.
  37.  
  38.     m_pST=NULL;
  39.     m_pPMM=NULL;
  40.     m_pSMM=NULL;
  41.     m_hMemSMM=NULL;
  42.  
  43.     //With this FALSE, many other members are ignored.
  44.     m_fMapped=FALSE;
  45.     return;
  46.     }
  47. //
  48. //   FUNCTION:  CStatusHelper::~CStatusHelper
  49. //
  50. //   PURPOSE: Destructor for the CStatusHelper class. 
  51. //
  52. CStatusHelper::~CStatusHelper(void)
  53.     {
  54.     //Free up anything from MessageMap
  55.     if (NULL!=m_pPMM)
  56.         {
  57.         LocalFree((HLOCAL)m_pPMM);
  58.         m_pPMM=NULL;
  59.         }
  60.  
  61.     if (NULL!=m_pST)
  62.         {
  63.         delete m_pST;
  64.         m_pST=NULL;
  65.         }
  66.  
  67.     if (NULL!=m_pSMM)
  68.         {
  69.         LocalFree((HLOCAL)m_pSMM);
  70.         UnlockResource(m_hMemSMM);
  71.         m_pSMM=NULL;
  72.         }
  73.  
  74.     if (NULL!=m_hMemSMM)
  75.         {
  76.         FreeResource(m_hMemSMM);
  77.         m_hMemSMM=NULL;
  78.         }
  79.  
  80.     return;
  81.     }
  82. //
  83. //   FUNCTION: CStatusHelper::MessageMap
  84. //
  85. //   PURPOSE:    Initializes a CStatusHelper for automated processing of
  86. //  WM_MENUSELECT messages as well as setting up a list of messages
  87. //  that we can display using identifiers instead of string
  88. //  pointers.  See MenuSelect and MessageDisplay members.
  89. //
  90. //  PARAMETERS:
  91. //  hWndOwner - HWND of the window owning menus we're interested in serving
  92. //  uIDRMap - UINT identifying a resource mapping ID values to string ID values
  93. //  idsMin - UINT specifying the lowest string ID to load
  94. //  idsMax - UINT specifying the hightest string ID to load
  95. //  cchMax - UINT maximum string length
  96. //  uIDPopupMin - UINT of the lowest ID to assign to popup menus
  97. //  uIDPopupMax - UINT of the highest ID to assign to popup menus
  98. //  uIDStatic- UINT of the ID for the quiescent state message
  99. //  uIDBlank - UINT of the ID for a blank message
  100. //  uIDSysMenu - UINT of the ID for the system menu
  101. //
  102. //  RETURN VALUE:
  103. //  BOOL     TRUE if the function was successful,
  104. //                  FALSE otherwise.
  105. //
  106. //   COMMENTS:  This function is the initializer for the CStatusHelper class.
  107. //  If it fails, then the caller should delete the object.
  108. // 
  109. BOOL CStatusHelper::MessageMap(HWND hWndOwner, UINT uIDRMap
  110.     , UINT idsMin, UINT idsMax, UINT cchMax, UINT uIDPopupMin
  111.     , UINT uIDPopupMax, UINT uIDStatic, UINT uIDBlank, UINT uIDSysMenu)
  112.     {
  113.     HMENU           hMenu;
  114.     HRSRC           hRes;
  115.     UINT            i;
  116.     USHORT          uID;
  117.     DWORD           dwSize;
  118.     PSTATMESSAGEMAP pSMM;
  119.  
  120.     // Check if we even got a valid window in the constructor
  121.     // or if we've already been called.
  122.     if (!IsWindow(m_hWnd) || m_fMapped)
  123.         return FALSE;
  124.  
  125.     //Parameter validation
  126.     if (idsMax < idsMin || uIDPopupMax < uIDPopupMin)
  127.         return FALSE;
  128.  
  129.     //Cache away all this vital information
  130.     m_hWndOwner  =hWndOwner;
  131.     m_idsMin     =idsMin;
  132.     m_idsMax     =idsMax;
  133.     m_cMessages  =(USHORT)(idsMax-idsMin+1);
  134.  
  135.     m_uIDPopupMin=uIDPopupMin;
  136.     m_uIDPopupMax=uIDPopupMax;
  137.     m_cPopups    =(USHORT)(uIDPopupMax-uIDPopupMin+1);
  138.     m_uIDStatic  =uIDStatic;
  139.     m_uIDBlank   =uIDBlank;
  140.     m_uIDSysMenu =uIDSysMenu;
  141.  
  142.     //Get a stringtable with all the messages
  143.     m_pST=new CStringTable(m_hInst);
  144.  
  145.     if (NULL==m_pST)
  146.         return FALSE;
  147.  
  148.     if (!m_pST->FInit(idsMin, idsMax, CCHSTATUSMSGMAX))
  149.         return FALSE;
  150.  
  151.     //Load the STATMESSAGEMAP array from resources
  152.     hRes=FindResource(m_hInst, MAKEINTRESOURCE(uIDRMap), RT_RCDATA);
  153.  
  154.     if (NULL==hRes)
  155.         return FALSE;
  156.  
  157.     m_hMemSMM=LoadResource(m_hInst, hRes);
  158.  
  159.     if (NULL==m_hMemSMM)
  160.         return FALSE;
  161.  
  162.     pSMM=(PSTATMESSAGEMAP)LockResource(m_hMemSMM);
  163.  
  164.     if (NULL==pSMM)
  165.         return FALSE;
  166.  
  167.     // Now get the size of the resource
  168.     dwSize = SizeofResource(m_hInst, hRes);
  169.  
  170.     // Resources are ReadOnly data so copy it to memory that can
  171.     // be used
  172.     m_pSMM = (PSTATMESSAGEMAP)LocalAlloc(LPTR, dwSize);
  173.     if (NULL==m_pSMM)
  174.         return FALSE;
  175.     CopyMemory(m_pSMM, pSMM, dwSize);
  176.  
  177.     //Sort these for binary search lookup.
  178.     Sort();
  179.  
  180.     //Allocate an array of POPUPMENUMAP structures
  181.     m_pPMM=(PPOPUPMENUMAP)LocalAlloc(LPTR
  182.         , sizeof(POPUPMENUMAP)*m_cPopups);
  183.  
  184.     if (NULL==m_pPMM)
  185.         return FALSE;
  186.  
  187.     //Initialize the array mapping popup menus to specific IDs.
  188.     uID=uIDPopupMin;
  189.     hMenu=GetMenu(m_hWndOwner);
  190.  
  191.     for (i=0; i < m_cPopups; i++)
  192.         {
  193.         m_pPMM[i].hMenu=GetSubMenu(hMenu, i);
  194.         m_pPMM[i].uID  =uID++;
  195.         }
  196.  
  197.     //All done!
  198.     m_fMapped=TRUE;
  199.     return TRUE;
  200.     }
  201. //
  202. //   FUNCTION: CStatusHelper::MenuSelect
  203. //
  204. //   PURPOSE:  Displays the appropriate message for whatever is in the
  205. //  parameters of a WM_MENUSELECT message.  This can only be called
  206. //  if StatStripMessageMap has already been called and must be used
  207. //  with the same menu the owner window had at the time of that call.
  208. // 
  209. //   PARAMETERS:
  210. //  wItem           WORD identifying the selected item
  211. //  wFlags          WORD specifying the type of menu item
  212. //  hMenu           HMENU of the menu selected.
  213. //
  214. void CStatusHelper::MenuSelect(WORD wItem, WORD wFlags, HMENU hMenu)
  215.     {
  216.     USHORT          uID;
  217.  
  218.     if (!m_fMapped)
  219.         return;
  220.  
  221.     //Case 1:  Menu was cancelled, display static string
  222.     if (0==wItem && (WORD)0xFFFF==wFlags)
  223.         uID=m_uIDStatic;
  224.     else
  225.         {
  226.         //Case 2:  System menu selected by itself.
  227.         if ((MF_POPUP & wFlags) && (MF_SYSMENU & wFlags))
  228.             uID=m_uIDSysMenu;
  229.         else
  230.             {
  231.              //  Case 3:  A popup menu was chosen:
  232.              //  Find the ID for the popup menu index in wItem
  233.             if (MF_POPUP & wFlags)
  234.                 uID=IDFromHMenu((HMENU)wItem);
  235.             else
  236.                 //Case 4:  A menu item is selected
  237.                 if (0!=wItem)
  238.                     uID=(UINT)wItem;
  239.                 else
  240.                     //Case 5:  Nothing is selected (e.g. separator)
  241.                     uID=m_uIDBlank;
  242.            }
  243.         }
  244.  
  245.     //Display the message
  246.     MessageDisplay(uID);
  247.     return;
  248.     }
  249. //
  250. //   FUNCTION:       CStatusHelper::MessageDisplay
  251. //
  252. //   PURPOSE:  Displays the appropriate message for a given ID value.  This
  253. //  can only be called if MessageMap has already been called.
  254. //
  255. //   PARAMETERS: 
  256. //     uID             UINT of the message to display.  This is not a string ID but an ID 
  257. //                       in the STATMESSAGEMAP structure that maps to a string ID.
  258. //
  259. void CStatusHelper::MessageDisplay(UINT uID)
  260.     {
  261.     UINT        idsMsg;
  262.  
  263.     if (!m_fMapped)
  264.         return;
  265.  
  266.     //If we're already displaying this ID, nothing we need to do
  267.     if (m_uIDCur==uID)
  268.         return;
  269.  
  270.     //Go look up the string ID to display.
  271.     idsMsg=IStringFromID(uID);
  272.  
  273.     //Display it.
  274.     SetWindowText(m_hWnd, (*m_pST)[idsMsg]);
  275.     return;
  276.     }
  277. //
  278. //   FUNCTION:       CStatusHelper::Sort          (Private)
  279. //
  280. //   PURPOSE:   Performs a selection sort on the STATMESSAGEMAP array that we
  281. //  load from resources.  Since we expect that the data is partially
  282. //  sorted (we tend to place things in resources in groups of
  283. //  seqential values), since the number of messages is usually
  284. //  less than 200, and since we're usually doing this stuff on startup
  285. //  (which takes a long time anyway), a cimple selection sort is a
  286. //  better choice than a more complex qsort.
  287. //
  288. void CStatusHelper::Sort(void)
  289.     {
  290.     UINT            i, j, k;
  291.     STATMESSAGEMAP  smm;
  292.  
  293.     for (j=0; j < (UINT)(m_cMessages-1); j++)
  294.         {
  295.         k=j;
  296.         smm.uID   =m_pSMM[j].uID;
  297.         smm.idsMsg=m_pSMM[j].idsMsg;
  298.  
  299.         for (i=j+1; i < (UINT)m_cMessages; i++)
  300.             {
  301.             if (m_pSMM[i].uID < smm.uID)
  302.                 {
  303.                 smm.uID   =m_pSMM[i].uID;
  304.                 smm.idsMsg=m_pSMM[i].idsMsg;
  305.                 k=i;
  306.                 }
  307.             }
  308.  
  309.         smm.uID         =m_pSMM[j].uID;
  310.         smm.idsMsg      =m_pSMM[j].idsMsg;
  311.         m_pSMM[j].uID   =m_pSMM[k].uID;   ;
  312.         m_pSMM[j].idsMsg=m_pSMM[k].idsMsg;;
  313.         m_pSMM[k].uID   =smm.uID;
  314.         m_pSMM[k].idsMsg=smm.idsMsg;
  315.         }
  316.  
  317.     return;
  318.     }
  319. //
  320. //   FUNCTION:       CStatusHelper::IDFromHMenu (Private)
  321. //
  322. //   PURPOSE:   Given a specific popup menu index, searches through m_pPMM for
  323. //  a match and returns the ID associated with that menu.
  324. //
  325. //   PARAMETERS:
  326. //       hMenu           HMENU to of he popup menu.
  327. //
  328. //   RETURN VALUE:
  329. //       USHORT          ID associated with the menu handle.
  330. // 
  331. USHORT CStatusHelper::IDFromHMenu(HMENU hMenu)
  332.     {
  333.     USHORT      uID=m_uIDBlank;      //Default is empty
  334.     UINT        i;
  335.  
  336.     for (i=0; i < m_cPopups; i++)
  337.         {
  338.         if (m_pPMM[i].hMenu==hMenu)
  339.             {
  340.             uID=m_pPMM[i].uID;
  341.             break;
  342.             }
  343.         }
  344.  
  345.     return uID;
  346.     }
  347. //
  348. //   FUNCTION:     CStatusHelper::IStringFromID (Private)
  349. //
  350. //   PURPOSE:  Performs a binary search in a STATMESSAGEMAP array looking for
  351. //  a specific item ID returning the string ID for that item.
  352. //
  353. //   PARAMETERS: 
  354. //        uID             USHORT item ID to locate.
  355. //
  356. //   RETURN VALUE:
  357. //       UINT            String ID associated with wItem.
  358. // 
  359. UINT CStatusHelper::IStringFromID(USHORT uID)
  360.     {
  361.     UINT        iLow =0;
  362.     UINT        iHigh=m_cMessages-1;
  363.     UINT        iMid;
  364.  
  365.     while (TRUE)
  366.         {
  367.         iMid=(iLow+iHigh) >> 1;
  368.  
  369.         if (uID < m_pSMM[iMid].uID)
  370.             iHigh=iMid-1;
  371.         else
  372.             {
  373.             if (uID > m_pSMM[iMid].uID)
  374.                 iLow=iMid+1;
  375.             else
  376.                 break;    //Equality
  377.             }
  378.  
  379.         if (iHigh < iLow)
  380.             break;
  381.         }
  382.  
  383.     return m_pSMM[iMid].idsMsg;
  384.     }
  385.