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

📄 rtmenu.cpp

📁 vc++编写的界面源代码,对C++爱好者是很发的帮助。
💻 CPP
📖 第 1 页 / 共 3 页
字号:

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CRTWndMenu class : management of the window used by system to display popup menus
//
class CRTWndMenu
{
public:
    CRTWndMenu (HWND hWnd);
   ~CRTWndMenu ();

public:
    static CRTWndMenu* FromHandle (HWND hWnd, bool bPermanent = true);

protected:
    void OnWindowPosChanging (WINDOWPOS* pWP);
    void OnEraseBkgnd ();
    void OnPrint (CDC* pDC, bool bOwnerDrawnItems);
    void OnNcPaint ();
    void OnShowWindow (bool bShow);
    void OnNcDestroy ();

private:
    static LRESULT CALLBACK WindowsHook (int code, WPARAM wParam, LPARAM lParam);
    static LRESULT CALLBACK SubClassMenuProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

protected:
    HWND m_hWnd;
    CRect m_rcMenu;
    CPoint m_ptMenu;
    CBitmap m_bmpBkGnd;

    static CMap <HWND, HWND, CRTWndMenu*, CRTWndMenu*> ms_WndMenuMap;
    static DWORD ms_dwRefCount;
    static HHOOK ms_hHookOldMenuCbtFilter;

friend class CRTMenu;
};

///////////////////////////////////////////////////////////////////////////////
void CRTMenu::InitializeHook ()
{
    CRTWndMenu::ms_dwRefCount++;

    if ( CRTWndMenu::ms_hHookOldMenuCbtFilter == NULL )
    {
        CRTWndMenu::ms_hHookOldMenuCbtFilter = ::SetWindowsHookEx (WH_CALLWNDPROC, CRTWndMenu::WindowsHook, AfxGetApp()->m_hInstance, ::GetCurrentThreadId());
    }
}

///////////////////////////////////////////////////////////////////////////////
void CRTMenu::UninitializeHook ()
{
    if ( CRTWndMenu::ms_dwRefCount == 0 )
    {
        return;
    }
    if ( --CRTWndMenu::ms_dwRefCount == 0 )
    {
        POSITION pos = CRTWndMenu::ms_WndMenuMap.GetStartPosition();

        while ( pos != NULL )
        {
            HWND hKey;
            CRTWndMenu* pVal;

            CRTWndMenu::ms_WndMenuMap.GetNextAssoc (pos, hKey, pVal);
            delete pVal;
        }
        CRTWndMenu::ms_WndMenuMap.RemoveAll();

        if ( CRTWndMenu::ms_hHookOldMenuCbtFilter != NULL )
        {
            ::UnhookWindowsHookEx (CRTWndMenu::ms_hHookOldMenuCbtFilter);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
CMap <HWND, HWND, CRTWndMenu*, CRTWndMenu*> CRTWndMenu::ms_WndMenuMap;
DWORD CRTWndMenu::ms_dwRefCount = 0;
HHOOK CRTWndMenu::ms_hHookOldMenuCbtFilter = NULL;

///////////////////////////////////////////////////////////////////////////////
CRTWndMenu::CRTWndMenu (HWND hWnd)
    : m_hWnd (hWnd), m_rcMenu (0, 0, 0, 0), m_ptMenu (-0xFFFF, -0xFFFF)
{
}

///////////////////////////////////////////////////////////////////////////////
CRTWndMenu::~CRTWndMenu ()
{
    WNDPROC oldWndProc = (WNDPROC)::GetProp (m_hWnd, _WndPropName_OldProc);

    if ( oldWndProc != NULL )
    {
        ::SetWindowLong (m_hWnd, GWL_WNDPROC, (DWORD)(DWORD_PTR)oldWndProc);
        ::RemoveProp (m_hWnd, _WndPropName_OldProc);
    }
    ms_WndMenuMap.RemoveKey (m_hWnd);
}

///////////////////////////////////////////////////////////////////////////////
CRTWndMenu* CRTWndMenu::FromHandle (HWND hWnd, bool bPermanent)
{
    CRTWndMenu* pWnd = NULL;

    if ( ms_WndMenuMap.Lookup (hWnd, pWnd) )
    {
        return pWnd;
    }
    if ( bPermanent )
    {
        return NULL;
    }
    pWnd = new CRTWndMenu (hWnd);
    ms_WndMenuMap.SetAt (hWnd, pWnd);

    return pWnd;
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnWindowPosChanging (WINDOWPOS* pWP)
{
    if ( GetWinVersion() < wvWinXP )
    {
        pWP->cx += SM_CXSHADOW;
        pWP->cy += SM_CXSHADOW;
    }
    pWP->y--;
    m_ptMenu.x = pWP->x;
    m_ptMenu.y = pWP->y;
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnEraseBkgnd ()
{
    if ( !IsWindowVisible (m_hWnd) )
    {
        CClientRect rc (m_hWnd);

        if ( m_bmpBkGnd.m_hObject != NULL )
        {
            m_bmpBkGnd.DeleteObject();
        }
        m_bmpBkGnd.Attach (GetScreenBitmap (CRect (m_ptMenu.x, m_ptMenu.y, rc.right+m_ptMenu.x+10,
                                                   rc.bottom+m_ptMenu.y+10)));
    }
}

///////////////////////////////////////////////////////////////////////////////
void DrawShadow (HDC hDCIn, HDC hDCOut, RECT& rc)
{
    for ( int x = 0; x < rc.right-1; x++ )
    {
        int nEnd = ( x > rc.right-SM_CXSHADOW*2 ) ? rc.right-SM_CXSHADOW-x : SM_CXSHADOW;

        for ( int y = ( x < 2 ) ? 2-x : x > rc.right-SM_CXSHADOW-3 ? x-rc.right+SM_CXSHADOW+3 : 0; y < nEnd; y++ )
        {
            int nMakeSpec = 78+(3-(x==0?0:(x==1?(y<2?0:1):(x==2?(y<2?y:2):y))))*5;
            COLORREF cr = GetPixel (hDCIn, x+SM_CXSHADOW, rc.bottom-y-1);
            COLORREF cr2 = RGB(((nMakeSpec * int(GetRValue(cr))) / 100),
			                   ((nMakeSpec * int(GetGValue(cr))) / 100),
			                   ((nMakeSpec * int(GetBValue(cr))) / 100));
			SetPixel (hDCOut, x+SM_CXSHADOW, rc.bottom-y-1, cr2);
        }
    }
    for ( x = 0; x < SM_CXSHADOW; x++ )
    {
        for ( int y = ( x < 2 ) ? 2-x : 0; y < rc.bottom-x-SM_CXSHADOW-((x>0)?1:2); y++ )
        {
            int nMakeSpec = 78+(3-(y==0?0:(y==1?(x<2?0:1):(y==2?(x<2?x:2):x))))*5;
            COLORREF cr = GetPixel (hDCIn, rc.right-x-1, y+SM_CXSHADOW);
            COLORREF cr2 = RGB(((nMakeSpec * int(GetRValue(cr))) / 100),
			                   ((nMakeSpec * int(GetGValue(cr))) / 100),
			                   ((nMakeSpec * int(GetBValue(cr))) / 100));
			SetPixel (hDCOut, rc.right-x-1, y+SM_CXSHADOW, cr2);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnPrint (CDC* pDC, bool bOwnerDrawnItems)
{
    CWindowRect rc (m_hWnd);
    CBrushDC br (pDC->m_hDC);
    CPenDC pen (pDC->m_hDC, ::GetSysColor (COLOR_3DDKSHADOW));

    rc.OffsetRect (-rc.TopLeft());
    m_rcMenu = rc;

    if ( GetWinVersion() < wvWinXP )
    {
        rc.right -= SM_CXSHADOW;
        rc.bottom -= SM_CXSHADOW;
    }
    pDC->Rectangle (rc);
    pen.Color (HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +75, 0));
    rc.DeflateRect (1, 1);
    pDC->Rectangle (rc);
    rc.DeflateRect (1, 1);
    pDC->Rectangle (rc);

    if ( bOwnerDrawnItems && !CRTMenuItem::ms_rcMRUMenuBarItem.IsRectEmpty() &&
         CRTMenuItem::ms_rcMRUMenuBarItem.bottom == m_ptMenu.y+1 )
    {
        pen.Color (HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +20, 0));
        pDC->MoveTo (CRTMenuItem::ms_rcMRUMenuBarItem.left-m_ptMenu.x-3, 0);
        pDC->LineTo (CRTMenuItem::ms_rcMRUMenuBarItem.left-m_ptMenu.x+CRTMenuItem::ms_rcMRUMenuBarItem.Width()-5, 0);
    }
    if ( GetWinVersion() < wvWinXP )
    {
        rc.right += SM_CXSHADOW+2;
        rc.bottom += SM_CXSHADOW+2;

        CDC cMemDC;
        cMemDC.CreateCompatibleDC (pDC);
        HGDIOBJ hOldBitmap = ::SelectObject (cMemDC.m_hDC, m_bmpBkGnd);
        pDC->BitBlt (0, rc.bottom-SM_CXSHADOW, SM_CXSHADOW*2, SM_CXSHADOW, &cMemDC, 0, rc.bottom-SM_CXSHADOW, SRCCOPY);
        pDC->BitBlt (rc.right-SM_CXSHADOW, rc.bottom-SM_CXSHADOW, SM_CXSHADOW, SM_CXSHADOW, &cMemDC, rc.right-SM_CXSHADOW, rc.bottom-SM_CXSHADOW, SRCCOPY);
        pDC->BitBlt (rc.right-SM_CXSHADOW, 0, SM_CXSHADOW, SM_CXSHADOW*2, &cMemDC, rc.right-SM_CXSHADOW, 0, SRCCOPY);
        DrawShadow (cMemDC.m_hDC, pDC->m_hDC, rc);
        ::SelectObject (cMemDC.m_hDC, hOldBitmap);
    }
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnNcPaint ()
{
    CWindowDC cDC (CWnd::FromHandle (m_hWnd));
    CDC* pDC = &cDC;
    CWindowRect rc (m_hWnd);

    m_ptMenu.x = rc.left;
    m_ptMenu.y = rc.top;
    rc.OffsetRect (-rc.TopLeft());

    if ( rc != m_rcMenu )
    {
        m_rcMenu = rc;

        CBrushDC br (pDC->m_hDC);
        CPenDC pen (pDC->m_hDC, ::GetSysColor (COLOR_3DDKSHADOW));

        if ( GetWinVersion() < wvWinXP )
        {
            rc.right -= SM_CXSHADOW;
            rc.bottom -= SM_CXSHADOW;
        }

        pDC->Rectangle (rc);
        pen.Color (HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +75, 0));
        rc.DeflateRect (1, 1);
		pDC->Rectangle (rc);
        rc.DeflateRect (1, 1);
		pDC->Rectangle (rc);
		
        if ( !CRTMenuItem::ms_rcMRUMenuBarItem.IsRectEmpty() &&
             CRTMenuItem::ms_rcMRUMenuBarItem.bottom == m_ptMenu.y+1 )
        {
            pen.Color (HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +20, 0));
            pDC->MoveTo (CRTMenuItem::ms_rcMRUMenuBarItem.left-m_ptMenu.x-3, 0);
            pDC->LineTo (CRTMenuItem::ms_rcMRUMenuBarItem.left-m_ptMenu.x+CRTMenuItem::ms_rcMRUMenuBarItem.Width()-5, 0);
        }
        if ( GetWinVersion() < wvWinXP )
        {
            rc.right += SM_CXSHADOW+2;
            rc.bottom += SM_CXSHADOW+2;

            DrawShadow (pDC->m_hDC, pDC->m_hDC, rc);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnShowWindow (bool bShow)
{
    if ( !bShow )
    {
        delete this;
    }
}

///////////////////////////////////////////////////////////////////////////////
void CRTWndMenu::OnNcDestroy ()
{
    delete this;
}

///////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK CRTWndMenu::WindowsHook (int code, WPARAM wParam, LPARAM lParam)
{
    CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;

    // Not a real loop (just for 'break' branchment)
    while ( code == HC_ACTION )
    {
        HWND hWnd = pStruct->hwnd;

        // Normal and special handling for menu 0x10012
        if ( pStruct->message != WM_CREATE && pStruct->message != 0x01E2 )
        {
            break;
        }
        CWnd* pFrame = CWnd::GetForegroundWindow();

		if ( pFrame == NULL || !CRTMenu::GetXPLookNFeel (pFrame) || !CRTMenu::m_bEnableSkin )
        {
            break;
        }
        TCHAR sClassName[10];
        int Count = ::GetClassName (hWnd, sClassName, lengthof(sClassName));

        // Check for the menu-class
        if ( Count != 6 || _tcscmp (sClassName, _T("#32768")) != 0 )
        {
            break;
        }
        VERIFY(CRTWndMenu::FromHandle (pStruct->hwnd, false) != NULL);

        if ( ::GetProp (pStruct->hwnd, _WndPropName_OldProc) != NULL )
        {
            // Already subclassed
            break;
        }
        // Subclass the window
        WNDPROC oldWndProc = (WNDPROC)(LONG_PTR)::GetWindowLong (pStruct->hwnd, GWL_WNDPROC);

        if ( oldWndProc == NULL )
        {
            break;
        }
        ASSERT(oldWndProc != SubClassMenuProc);

        if ( !SetProp (pStruct->hwnd, _WndPropName_OldProc, oldWndProc) )
        {
            break;
        }
        if ( !SetWindowLong (pStruct->hwnd, GWL_WNDPROC,(DWORD)(DWORD_PTR)SubClassMenuProc) )
        {
            ::RemoveProp (pStruct->hwnd, _WndPropName_OldProc);
            break;
        }
        // Success !
        break;
    }
    return CallNextHookEx (CRTWndMenu::ms_hHookOldMenuCbtFilter, code, wParam, lParam);
}

///////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK CRTWndMenu::SubClassMenuProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    WNDPROC oldWndProc = (WNDPROC)::GetProp (hWnd, _WndPropName_OldProc);
    CRTWndMenu* pWnd = NULL;

    switch ( uMsg )
    {
    case WM_NCCALCSIZE:
        {
            LRESULT lResult = CallWindowProc (oldWndProc, hWnd, uMsg, wParam, lParam);

            if ( GetWinVersion() < wvWinXP )
            {
                NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)lParam;

                lpncsp->rgrc[0].right -= SM_CXSHADOW;
                lpncsp->rgrc[0].bottom -= SM_CXSHADOW;
            }
            return lResult;
        }

    case WM_WINDOWPOSCHANGING:
        if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
        {
            pWnd->OnWindowPosChanging ((LPWINDOWPOS)lParam);
        }
        break;

    case WM_ERASEBKGND:
        if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
        {
            pWnd->OnEraseBkgnd();
        }
        break;

    case WM_PRINT:
        {
            BYTE nCheck = CRTMenuItem::ms_nCheck;
            LRESULT lResult = CallWindowProc (oldWndProc, hWnd, uMsg, wParam, lParam);
            bool bOwnerDrawnItems = nCheck != CRTMenuItem::ms_nCheck;

            if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
            {
                pWnd->OnPrint (CDC::FromHandle ((HDC)wParam), bOwnerDrawnItems);
            }
            return lResult;
        }

    case WM_NCPAINT:
        if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
        {
            pWnd->OnNcPaint();
            return 0;
        }
        break;

    case WM_SHOWWINDOW:
        if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
        {
            pWnd->OnShowWindow (wParam != 0);
        }
        break;

    case WM_NCDESTROY:
        if ( (pWnd=CRTWndMenu::FromHandle (hWnd)) != NULL )
        {
            pWnd->OnNcDestroy();
        }
        break;
    }
    return CallWindowProc (oldWndProc, hWnd, uMsg, wParam, lParam);
}

⌨️ 快捷键说明

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