⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atlctrlxp.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 3 页
字号:
      // Make flat menu overlap with menu button at its bottom frame line
      if( lpParams ) {
         lpParams->rcExclude.bottom -= 1; // don't exclude bottom frame
         y -= 1;                          // and move up the menu
      }

#ifndef TPM_HORPOSANIMATION
      const UINT TPM_HORPOSANIMATION = 0x0400;
      const UINT TPM_HORNEGANIMATION = 0x0800;
      const UINT TPM_VERPOSANIMATION = 0x1000;
      const UINT TPM_VERNEGANIMATION = 0x2000;
#endif // TPM_HORPOSANIMATION
#ifndef TPM_NOANIMATION
      const UINT TPM_NOANIMATION = 0x4000;
#endif // TPM_NOANIMATION
      OSVERSIONINFO ovi;
      ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
      BOOL bRet = ::GetVersionEx(&ovi);
      if( bRet && 
          ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && 
          ovi.dwMajorVersion <= 4 ) 
      {
         // There are no menu-animations on Windows NT 4, so we
         // don't tinker with the flags. NT4 might fail otherwise.
         // Thanks to Andy Karels for this tip.
      }
      else {
         // We need to turn off animations because they mess up the first menu paint.
         // Thanks to Ramon Casellas for this tip.
         uFlags |= TPM_NOANIMATION;
         uFlags &= ~( TPM_HORPOSANIMATION | TPM_HORNEGANIMATION | TPM_VERPOSANIMATION | TPM_VERNEGANIMATION );
      }

      // Toggle menu fading/animation mode (Windows2K or later)
#ifndef SPI_GETMENUFADE
      const UINT SPI_GETMENUFADE = 0x1012;
      const UINT SPI_SETMENUFADE = 0x1013;
#endif // SPI_GETMENUFADE
#ifndef SPI_GETMENUANIMATION
      const UINT SPI_GETMENUANIMATION = 0x1002;
      const UINT SPI_SETMENUANIMATION = 0x1003;
#endif // SPI_GETMENUANIMATION
#ifndef SPI_GETANIMATION
      const UINT SPI_GETANIMATION = 0x0048;
      const UINT SPI_SETANIMATION = 0x0049;
#endif // SPI_GETANIMATION
      BOOL bMenuFading = FALSE;
      BOOL bMenuAnim = FALSE;
      if( ovi.dwMajorVersion >= 5 )
      {
         bRet = ::SystemParametersInfo(SPI_GETMENUFADE, 0, &bMenuFading, 0);
         bRet = ::SystemParametersInfo(SPI_GETMENUANIMATION, 0, &bMenuAnim, 0);
         bRet = ::SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE);
         bRet = ::SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE);
      }
#ifdef _CMDBAR_EXTRA_TRACE
      //ATLTRACE2(atlTraceUI, 0, "CmdBar - DoTrackPopupMenu:, bMenuFading = %s, bMenuAnim = %s\n",
       //  bMenuFading ? "true" : "false", bMenuAnim ? "true" : "false");
#endif

      // Figure out the size of the pressed button
      if( !m_bContextMenu ) GetItemRect(m_nPopBtn, &m_rcButton);

      CMenuHandle menuPopup = hMenu;

      ::EnterCriticalSection(&_Module.m_csWindowCreate);

      ATLASSERT(s_hCreateHook == NULL);

      s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this);

      s_hCreateHook = ::SetWindowsHookEx(WH_CBT, MyCreateHookProc, _Module.GetModuleInstance(), GetCurrentThreadId());
      ATLASSERT(s_hCreateHook != NULL);

      m_bPopupItem = false;
      m_bMenuActive = true;

      BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams);
      m_bMenuActive = false;

      ::UnhookWindowsHookEx(s_hCreateHook);

      s_hCreateHook = NULL;
      s_pCurrentBar = NULL;

      ::LeaveCriticalSection(&_Module.m_csWindowCreate);

      // Cleanup - convert menus back to original state
#ifdef _CMDBAR_EXTRA_TRACE
      //ATLTRACE2(atlTraceUI, 0, "CmdBar - TrackPopupMenu - cleanup\n");
#endif

      ATLASSERT(m_stackMenuWnd.GetSize() == 0);

      // These updates are also from the original WTL CommandBar control
      // but they actually solves some paint problems with submenus in this
      // control as well.
      UpdateWindow();
      CWindow wndTL = GetTopLevelParent();
      wndTL.UpdateWindow();

      // Restore menu fade/animation mode (Windows2K or later)
      if( ovi.dwMajorVersion >= 5 )
      {
         bRet = ::SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) bMenuFading, SPIF_SENDWININICHANGE);
         bRet = ::SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) bMenuAnim, SPIF_SENDWININICHANGE);
      }

      // Restore the menu items to the previous state for all menus that were converted
      if( m_bImagesVisible )
      {
         HMENU hMenuSav;
         while( (hMenuSav = m_stackMenuHandle.Pop()) != NULL ) {
            menuPopup = hMenuSav;
            BOOL bRet = FALSE;
            // Restore state and delete menu item data
            for( int i = 0; i < menuPopup.GetMenuItemCount(); i++ ) {
               CMenuItemInfo mii;
               mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;
               bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
               ATLASSERT(bRet);

               _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
               if( pMI != NULL && pMI->IsCmdBarMenuItem() )
               {
                  mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
                  mii.fType = pMI->fType;
                  mii.fState = pMI->fState;
                  mii.dwTypeData = pMI->lpstrText;
                  mii.cch = lstrlen(pMI->lpstrText);
                  mii.dwItemData = NULL;

                  bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
                  // This one triggers WM_MEASUREITEM
                  menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText);
                  ATLASSERT(bRet);

                  delete [] pMI->lpstrText;
                  delete pMI;
               }
            }
         }
      }
      return bTrackRet;
   }

   // Implementation - Hook procs
   
   static LRESULT CALLBACK MyCreateHookProc(int nCode, WPARAM wParam, LPARAM lParam)
   {
      LRESULT lRet = 0;
      TCHAR szClassName[7];

      if( nCode == HCBT_CREATEWND )
      {
         HWND hWndMenu = (HWND)wParam;
#ifdef _CMDBAR_EXTRA_TRACE
         //ATLTRACE2(atlTraceUI, 0, "CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n", hWndMenu);
#endif

         ::GetClassName(hWndMenu, szClassName, 7);
         if( ::lstrcmp(_T("#32768"), szClassName) == 0 ) {
            s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu);

            // Subclass to a flat-looking menu
            CFlatMenuWindow* wnd = new CFlatMenuWindow(m_rcButton.right - m_rcButton.left, m_xpstyle.clrFrame, m_xpstyle.clrBackground, m_xpstyle.clrMenu);
            wnd->SubclassWindow(hWndMenu);
            wnd->SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_DRAWFRAME);
            ::SetRectEmpty(&m_rcButton);
         }
      }
      else if( nCode == HCBT_DESTROYWND )
      {
         HWND hWndMenu = (HWND)wParam;
#ifdef _CMDBAR_EXTRA_TRACE
         //ATLTRACE2(atlTraceUI, 0, "CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n", hWndMenu);
#endif

         ::GetClassName(hWndMenu, szClassName, 7);
         if( ::lstrcmp(_T("#32768"), szClassName) == 0 )
         {
            ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent());
            s_pCurrentBar->m_stackMenuWnd.Pop();
         }
      }
      else if( nCode < 0 )
      {
         lRet = ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam);
      }
      return lRet;
   }

   // Implementation - ownerdraw overridables and helpers

   LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
   {
      // Update colors
      _GetSystemSettings();
      // Allow WTL Command Bar to set its settings...
      bHandled = FALSE;
      return 0;
   }

   // Ownerdrawn menu

   void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
   {
      _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;

      if( (pmd->fType & MFT_SEPARATOR) != 0 ) // separator - is really small
      {
         lpMeasureItemStruct->itemHeight = 5;
         lpMeasureItemStruct->itemWidth  = 0;
      }
      else
      {
         // ** Removed 'static' as suggested by Ilya Kheifets.
         CFont fontBold;
         // Compute size of text - use DrawText with DT_CALCRECT
         CWindowDC dc = m_hWnd;
         HFONT hOldFont;
         if( (pmd->fState & MFS_DEFAULT) != 0 ) {
            // Need bold version of font
            LOGFONT lf;
            m_fontMenu.GetLogFont(lf);
            lf.lfWeight += 200;
            fontBold.CreateFontIndirect(&lf);
            ATLASSERT(!fontBold.IsNull());
            hOldFont = dc.SelectFont(fontBold);
         }
         else {
            hOldFont = dc.SelectFont(m_fontMenu);
         }

         RECT rcText = { 0 };
         dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
         dc.SelectFont(hOldFont);

         int cx = rcText.right - rcText.left;

         LOGFONT lf;
         m_fontMenu.GetLogFont(lf);
         int cy = lf.lfHeight;
         if( cy < 0 ) cy = -cy;
         cy += 10;

         // Height of item is the bigger of these two
         lpMeasureItemStruct->itemHeight = max(cy, (int) m_szButton.cy + 2);

         // Width is width of text plus a bunch of stuff
         cx += 2 * s_kcxTextMargin;       // L/R margin for readability
         cx += s_kcxGap;                  // Space between button and menu text
         cx += 2 * m_szButton.cx;         // Button width (L=button; R=empty margin)

         // Windows adds 1 to returned value
         cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1;
         lpMeasureItemStruct->itemWidth = cx;      // done deal
      }
   }

   void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
   {
      _MenuItemData* pmd = (_MenuItemData*) lpDrawItemStruct->itemData;
      CDCHandle dc = lpDrawItemStruct->hDC;
      const RECT& rcItem = lpDrawItemStruct->rcItem;

      bool bSelected = (lpDrawItemStruct->itemState & ODS_SELECTED) != 0;
      bool bDisabled = (lpDrawItemStruct->itemState & ODS_GRAYED) != 0;
      bool bChecked = (lpDrawItemStruct->itemState & ODS_CHECKED) != 0;

      if( LOWORD(lpDrawItemStruct->itemID) == (WORD) -1 ) bSelected = false;
      
      RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect
      ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically

      int cxButn = m_szButton.cx;
      RECT rcIcon = rcItem;
      RECT rcText = rcItem;
      rcText.left += cxButn + s_kcxGap;
      rcIcon.right = rcText.left;

      // Draw background

      if( !bDisabled && bSelected ) 
      {
         CBrush brush;
         CPen pen;
         brush.CreateSolidBrush(m_xpstyle.clrHighlight);
         pen.CreatePen(PS_SOLID, 1, m_xpstyle.clrHighlightBorder);
         HPEN hOldPen = dc.SelectPen(pen);
         HBRUSH hOldBrush = dc.SelectBrush(brush);
         dc.Rectangle(&rcItem);
         dc.SelectPen(hOldPen);
         dc.SelectBrush(hOldBrush);
      }
      else 
      {
         CBrush brushIcon;
         CBrush brushText;
         brushIcon.CreateSolidBrush(m_xpstyle.clrMenu);
         brushText.CreateSolidBrush(m_xpstyle.clrBackground);      
         dc.FillRect(&rcIcon, brushIcon);
         dc.FillRect(&rcText, brushText);
      }

      // Draw item

      if( (pmd->fType & MFT_SEPARATOR) != 0 ) 
      {
         // Draw separator

         CPen pen;
         pen.CreatePen(PS_SOLID, 1, m_xpstyle.clrMenu);
         HPEN hOldPen = dc.SelectPen(pen);

         RECT rc = rcText;
         rc.top += (rc.bottom - rc.top) / 2;   // vertical center
         rc.left += s_kcxTextMargin + 4;
         dc.MoveTo(rc.left, rc.top);
         dc.LineTo(rc.right, rc.top);

         dc.SelectPen(hOldPen);
      }
      else  // Not a separator
      {      
         
         // Draw icon

         int iButton = pmd->iButton;
         if( iButton >= 0 ) {
            // Calc drawing point
            SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
            sz.cx /= 2;
            sz.cy /= 2;
            POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
            if( bDisabled ) {
               DrawShadowIcon(dc, m_hImageList, point, iButton);
            }
            else {
               if( bSelected ) {
                  // Draw shadow
                  if( (m_dwExtendedStyle & CBR_EX_NOWIGGLE) == 0 ) {
                     point.x++;
                     point.y++;
                     DrawShadowIcon(dc, m_hImageList, point, iButton);
                     point.x -= 2;
                     point.y -= 2;
                  }
                  else {
                     DrawShadowIcon(dc, m_hImageList, point, iButton);
                  }
               }
               // Draw the image
               ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
            }
         }
         else {
            // No image - look for custom checked/unchecked bitmaps
            CMenuItemInfo info;
            info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
            ::GetMenuItemInfo( (HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info );
            if( bChecked || info.hbmpUnchecked != NULL ) {
               bool bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
               DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked);
            }
         }

         // Draw text

         COLORREF clrText;
         if( bDisabled ) clrText = m_xpstyle.clrGreyText;
         else if( bSelected ) clrText = m_xpstyle.clrSelMenuText;
         else clrText = m_xpstyle.clrMenuText;

         rcText.right -= cxButn;
         rcText.left += s_kcxTextMargin;
         dc.SetBkMode(TRANSPARENT);
         DrawMenuText(dc, rcText, pmd->lpstrText, clrText); // finally!        
      }
   }

   void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color) const

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -