win32 自定义右键菜单

/****************************************************************************
几大主要问题:
1.通过处理WM_MOUSEACTIVATE,并返回MA_NOACTIVATE可以实现点窗口时不激活窗口(父窗口不会失去焦点)
2.CreateWindowEx时窗口的样式一定要有 WS_EX_TOPMOST 和 WS_POPUP ,并且设置窗口的父句柄。
3.用 ::ShowWindow(hWnd,SW_SHOWNOACTIVATE); 让窗口显示时无焦点
4.消息阻塞:用 GetMessage 来阻塞父窗口,不让代码继续往下执行直到菜单窗口消失为止。

未解决的问题:
1.菜单窗口不处于激活状态,所以未能收到键盘消息
2.窗口点击其他程序时,菜单不会自动消失
****************************************************************************/


/****************************************************************************
创建窗口 (不需要注册窗口类,只能创建一个)
****************************************************************************/
class CMyMenu
{
private:
    static WNDPROC OldWndProc;
    static LRESULT CALLBACK WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
public:
    static void CreateWnd(int x,int y,HWND PareWnd=NULL)  //创建窗口函数    
    {
        HWND hWnd = CreateWindowEx(WS_EX_TOPMOST,
            _T("#32770"),
            _T("Demo"),
            WS_POPUP| WS_BORDER,
            x,y,100,100,PareWnd,NULL,NULL,NULL) ;
            
        ::ShowWindow(hWnd,SW_SHOWNOACTIVATE);

        //把hWnd的默认窗口过程替换为WindowProc,返回默认函数过程的函数指针
        OldWndProc=(WNDPROC)SetWindowLong(hWnd,GWL_WNDPROC, (LONG) (WindowProc));


        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            //点击的不是菜单窗口就返回
            if ( msg.message==WM_LBUTTONDOWN || msg.message==WM_RBUTTONDOWN )
            {
                if ( msg.hwnd != hWnd )
                    ::PostMessage(hWnd,WM_CLOSE,NULL,NULL);
            }

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

    }
};

WNDPROC CMyMenu::OldWndProc=NULL;
LRESULT CALLBACK CMyMenu::WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch(message)
    {
    case WM_LBUTTONDOWN:
        {
            ::PostMessage(hWnd,WM_CLOSE,NULL,NULL);
        }
        break;

    case WM_MOUSEACTIVATE:
        return MA_NOACTIVATE ;

    case WM_CLOSE:
        DestroyWindow(hWnd); 
        break;

    case WM_DESTROY: 
        PostQuitMessage(0); //会退出消息循环 GetMessage
        break;

    default:
        return ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); //如果我们没有处理的再交给原窗口默认处理
    }
    return 0;
}



void CDemoDlg::OnRButtonUp(UINT nFlags, CPoint point)
{

    POINT pt;
    ::GetCursorPos(&pt);
    CMyMenu::CreateWnd(pt.x,pt.y,m_hWnd) ;



    CDialog::OnRButtonUp(nFlags, point);
原文地址:https://www.cnblogs.com/chechen/p/3944288.html