zoukankan      html  css  js  c++  java
  • 精通 VC++ 实效编程280例

    菜单和关闭时重要的 Windows 资源之一。SDK 中,用 HCURSOR 和 HMENU 分别表示菜单和光标的句柄。MFC 中,CMenu 类封装了菜单的功能。

    23 动态添加和删除菜单项

    添加菜单项可以调用 CMenu::AppendMenu 或 CMenu::InserMenu 函数,删除菜单项可以调用 CMenu::RemoveMenu 或 CMenu::DeleteMenu 函数,最后调用 CWnd::DrawMenuBar 函数重画菜单。

    • CMenu::AppendMenu:在菜单末端添加菜单项。
    • CMenu::InserMenu:在菜单指定位置添加菜单项。
    • CMenu::RemoveMenu:移动菜单项,如果菜单项与弹出菜单相关联,将不将销毁弹出菜单的句柄,因此菜单可重用。
    • CMenu::DeleteMenu:删除菜单项,如果菜单项与弹出菜单相关联,将销毁弹出菜单的句柄,并释放其占用的内存。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #define ID_TEST_MENU                    10000
    void CMainFrame::OnAppendMenu()
    {
        //获得主菜单
        CMenu* pMenu = GetMenu();
        //获得子菜单
        CMenu* pSubMenu = pMenu->GetSubMenu(4);
        if (pSubMenu->GetMenuItemCount() == 4)
        {
            //在菜单末端添加菜单项
            pSubMenu->AppendMenu(MF_STRING,ID_TEST_MENU,_T("New Menu"));
            //重画菜单
            DrawMenuBar();
        }
    }
     
    void CMainFrame::OnInsertMenu()
    {
        //获得主菜单
        CMenu* pMenu = GetMenu();
        //获得子菜单
        CMenu* pSubMenu = pMenu->GetSubMenu(4);
        if (pSubMenu->GetMenuItemCount() == 4)
        {
            //在菜单指定位置添加菜单项
            pSubMenu->InsertMenu(4,MF_BYPOSITION,ID_TEST_MENU,_T("New Menu"));
            //重画菜单
            DrawMenuBar();
        }  
    }
     
    void CMainFrame::OnRemoveMenu()
    {
        //获得主菜单
        CMenu* pMenu = GetMenu();
        //获得子菜单
        CMenu* pSubMenu = pMenu->GetSubMenu(4);
        if (pSubMenu->GetMenuItemCount() == 5)
        {
            //删除菜单项
            pSubMenu->RemoveMenu(4,MF_BYPOSITION);
            //重画菜单
            DrawMenuBar();
        }
    }
     
    void CMainFrame::OnDeleteMenu()
    {
        //获得主菜单
        CMenu* pMenu = GetMenu();
        //获得子菜单
        CMenu* pSubMenu = pMenu->GetSubMenu(4);
        if (pSubMenu->GetMenuItemCount() == 5)
        {
            //删除菜单项
            pSubMenu->DeleteMenu(4,MF_BYPOSITION);
            //重画菜单
            DrawMenuBar();
        }
    }
    void CMainFrame::OnTestMenu()
    {
        AfxMessageBox(_T("测试菜单项命令"));  
    }

    24 在系统菜单中添加和删除菜单项

    在系统菜单中添加和删除菜单项,首先调用 CWnd::GetSystemMenu 函数获得系统菜单的指针,然后调用 CMenu::AppendMenu 或 CMenu::InsertMenu,CMenu::RemoveMenu 或 CMenu::DeleteMenu 函数添加和删除菜单项,最后调用 CWnd::DrawMenuBar 函数重画菜单。对于添加的菜单项,可以在 CWnd::OnSysCommand 重载函数中处理菜单命令。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    //在resource.h文件中添加宏定义
    #define ID_TEST_MENU                    10000
    BOOL CDemoDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        //...
        //获得系统菜单
        CMenu* pMenu = GetSystemMenu(FALSE);
        //删除系统菜单项
        pMenu->RemoveMenu(SC_MOVE,MF_STRING);
        //添加菜单项
        pMenu->InsertMenu(0,MF_BYPOSITION,ID_TEST_MENU,_T("New Menu"));
        //重画菜单
        DrawMenuBar();
        return TRUE;
    }
    void CDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
        if ((nID & 0xFFF0) == IDM_ABOUTBOX)
        {
            CAboutDlg dlgAbout;
            dlgAbout.DoModal();
        }
        else if(nID == ID_TEST_MENU)
        {
            AfxMessageBox(_T("测试菜单项命令"));
        }
        else
        {
            CDialog::OnSysCommand(nID, lParam);
        }
    }

    25 禁用关闭按钮

    禁用关闭按钮可以调用 CMenu::EnableMenuItem 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    BOOL CDemoDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        //...
        //获得系统菜单
        CMenu* pMenu = GetSystemMenu(FALSE);
        //禁用关闭按钮
        pMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED);
        return TRUE;
    }

    26 启用和禁用菜单项

    可以在类的 UPDATE_COMMAND_UI 消息处理函数中调用 CCmdUI::Enable 函数,启用和禁用菜单项。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //在CMainFrame类中添加成员变量
    public:
        BOOL m_bEnable1;
        BOOL m_bEnable2;
    //在CMainFrame类的构造函数中初始化成员变量
    CMainFrame::CMainFrame()
    {
        m_bEnable1 = TRUE;
        m_bEnable2 = FALSE;
    }
    //在CMainFrame类中为菜单项添加命令处理函数
     
    void CMainFrame::OnTestMenu1()
    {
        m_bEnable1 = FALSE;
        m_bEnable2 = TRUE; 
    }
     
    void CMainFrame::OnUpdateTestMenu1(CCmdUI* pCmdUI)
    {
        //启动或禁用菜单1
        pCmdUI->Enable(m_bEnable1);
    }
     
    void CMainFrame::OnTestMenu2()
    {
        m_bEnable1 = TRUE;
        m_bEnable2 = FALSE;
    }
     
    void CMainFrame::OnUpdateTestMenu2(CCmdUI* pCmdUI)
    {
        //启动或禁用菜单2
        pCmdUI->Enable(m_bEnable2);
    }

    27 设置菜单项的检查状态

    可以在类的 UPDATE_COMMAND_UI 消息处理函数中调用 CCmdUI::SetCheck 函数设置菜单项的检查状态(选中/不选中状态)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    //在CMainFrame类中添加成员变量
    public:
        int m_nCheck;
    //在CMainFrame类的构造函数中初始化成员变量
    CMainFrame::CMainFrame()
    {
        m_nCheck = 0;
    }
    //在CMainFrame类中为菜单项添加命令处理函数
    void CMainFrame::OnTestMenu()
    {
        if (m_nCheck == 0)
        {
            m_nCheck = 1;
        }
        else
        {
            m_nCheck = 0;
        }
         
    }
     
    void CMainFrame::OnUpdateTestMenu(CCmdUI* pCmdUI)
    {
        //设置菜单项检查状态
        pCmdUI->SetCheck(m_nCheck);
    }

    28 快捷菜单

    实现快捷菜单可以在 CWnd::OnContextMenu 重载函数中调用 CMenu::TrackPopupMenu 函数。

    在资源中添加1个菜单资源,ID 为 IDR_MENU。在菜单资源中添加1个子菜单,并添加菜单项。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //在CDemoView类中重载CWnd::OnContextMenu函数
    void CDemoView::OnContextMenu(CWnd* pWnd, CPoint point)
    {
        CMenu menu;
        //加载菜单
        if (!menu.LoadMenu(IDR_MENU))
        {
            return;
        }
        //获得子菜单
        CMenu* pPopupMenu = menu.GetSubMenu(0);
        //弹出菜单
        pPopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,pWnd);
    }
    void CDemoView::OnTestMenu1()
    {
        AfxMessageBox(_T("快捷菜单项1命令"));
    }
     
    void CDemoView::OnTestMenu2()
    {
        AfxMessageBox(_T("快捷菜单项2命令"));
    }

    29 获取光标的坐标

    可以在 WM_MOUSEMOVE 消息处理函数中获得光标的位置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    //在CDemoView类中添加成员变量
    public:
        CPoint m_Point;
    //在类中添加WM_MOUSEMOVE消息处理函数
    void CDemoView::OnMouseMove(UINT nFlags, CPoint point)
    {
        //保存光标坐标
        m_Point = point;
        //刷新客户区
        Invalidate();
        CView::OnMouseMove(nFlags, point);
    }
    //在类中重载CView::OnDraw函数
    void CDemoView::OnDraw(CDC* pDC)
    {
        //获得客户区坐标
        CRect rect;
        GetClientRect(rect);
        //绘制十字光标
        pDC->MoveTo(0,m_Point.y);
        pDC->LineTo(rect.Width(),m_Point.y);
        pDC->MoveTo(m_Point.x,0);
        pDC->LineTo(m_Point.x,rect.Height());
        //输出光标坐标
        CString strText = _T("");
        strText.Format(_T("%d,%d"),m_Point.x,m_Point.y);
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetTextAlign(TA_RIGHT | TA_BOTTOM);
        pDC->TextOut(m_Point.x,m_Point.y,strText);
    }

    30 限制光标的移动范围

    限制光标的范围可以调用 SDK 的 ClipCursor 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    //在CDemoView类中重载CView::OnDraw函数
    void CDemoView::OnDraw(CDC* pDC)
    {
        //获得客户区坐标
        CRect rect;
        GetClientRect(rect);
        rect.left = rect.left + rect.Width() / 4;
        rect.right = rect.right - rect.Width() / 4;
        rect.top = rect.top + rect.Height() / 4;
        rect.bottom = rect.bottom -rect.Height() / 4;
        //绘制光标移动范围
        pDC->Rectangle(rect);
    }
    //在CDemoView类中分别添加WM_LBUTTONDOWN和WM_LBUTTONUP消息处理函数
    void CDemoView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        //获得客户区坐标
        CRect rect;
        GetClientRect(rect);
        rect.left = rect.left + rect.Width() / 4;
        rect.right = rect.right - rect.Width() / 4;
        rect.top = rect.top + rect.Height() / 4;
        rect.bottom = rect.bottom - rect.Height() /4;
        //映射屏幕坐标
        ClientToScreen(rect);
        //限制光标移动范围
        ClipCursor(&rect);
        CView::OnLButtonDown(nFlags, point);
    }
     
    void CDemoView::OnLButtonUp(UINT nFlags, CPoint point)
    {
        //光标自由移动
        ClipCursor(NULL);
        CView::OnLButtonUp(nFlags, point);
    }

    31 自定义光标

    使用自定义光标,首先调用 CWinApp::LoadCursor函数加载光标,然后调用SDK的SetCursor函数设置光标。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //创建1个单文档的应用程序,并添加2个光标资源,在CDemoView类中添加成员变量
    public:
        HCURSOR m_hCursor;
    //在CDemoView类中重载CView::OnInitialUpdate函数
    void CDemo2View::OnInitialUpdate()
    {
        CView::OnInitialUpdate();
        //加载光标
        m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
    }
    //在CDemoView类中添加WM_SETCURSOR消息处理函数
    BOOL CDemo2View::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
        //设置光标
        ::SetCursor(m_hCursor);
        return TRUE;
    }
    //在CDemoView类中分别添加WM_LBUTTONDOWN和WM_LBUTTONUP消息处理函数
    void CDemo2View::OnLButtonDown(UINT nFlags, CPoint point)
    {
        //加载光标
        m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR2);
        //设置光标
        ::SetCursor(m_hCursor);
        CView::OnLButtonDown(nFlags, point);
    }
     
    void CDemo2View::OnLButtonUp(UINT nFlags, CPoint point)
    {
        //加载光标
        m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
        //设置光标
        ::SetCursor(m_hCursor);
        CView::OnLButtonUp(nFlags, point);
    }

    32 等待光标

    启动等待光标可以调用 CCmdTarget::BeginWaitCursor函数,结束等待光标可以调用CCmdTarget::EndWaitCursor函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void CDemo2View::OnLButtonUp(UINT nFlags, CPoint point)
    {
        //启动等待光标
        BeginWaitCursor();
        //休眠
        Sleep(5000);
        //结束等待光标
        EndWaitCursor();
        CView::OnLButtonDown(nFlags,point);
    }

    转自:http://www.cnblogs.com/iwanc/archive/2013/06/09/2987866.html 

    作者:爱玩C
    邮箱:iwanc@qq.com
    出处:http://www.iwanc.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    隐私保护政策
    童真儿童简笔画
    方块十字消
    iOS 判断一断代码的执行时间(从网上看的,自己实现一下)
    iOS BLOCK回调:(妖妖随笔)
    typedef struct
    #define和预处理指令
    UIActivityIndicatorView
    Expected a type 的错误
    iOS 本地化字符串—(妖妖随笔)
  • 原文地址:https://www.cnblogs.com/vranger/p/3986648.html
Copyright © 2011-2022 走看看