精通 VC++ 实效编程280例 - 02 菜单和光标[转]

菜单和关闭时重要的 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 

时间: 2024-10-11 05:13:38

精通 VC++ 实效编程280例 - 02 菜单和光标[转]的相关文章

精通 VC++ 实效编程280例 - 01 窗口[转]

窗口是屏幕上的一个矩形区域.窗口分为3种:重叠窗口.弹出窗口和子窗口.每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”.在 MFC 中,CWnd 类为各种窗口提供了基类. 1 通过 HWND 获得 CWnd 指针 通过 HWND 获得 Cwnd 指针可以调用 Cwnd::FromHandle 函数. 1 2 3 4 5 6 7 8 void CDemoDlg::OnButton1() {     HWND hWnd = GetSafeHwnd();  //获得当前窗口的句柄    

精通 VC++ 实效编程280例 - 03 控制栏 [转]

Windows 应用程序的控制栏包括工具栏和状态栏等.在工具栏中可以添加按钮和控件,实现快捷操作.在状态栏中可以显示一些提示信息.MFC 中,控制栏中的工具栏和状态栏分别通过 CToolBar 类和 CstatusBar 类实现,它们的父类都为 CContorlBar 类. 33 创建工具栏 创建工具栏,首先创建一个工具栏资源,然后构造一个 CToolBar 类对象,接下来调用 CToolBar::CreateEx 函数创建工具栏窗口,最后调用 CToolBar::LoadToolBar 函数加

VC/MFC 编程技巧大总结

1 toolbar默认位图左上角那个点的颜色是透明色,不喜欢的话可以自己改. 2 VC++中 WM_QUERYENDSESSION WM_ENDSESSION 为系统关机消息. 3 Java学习书推荐:<java编程思想> 4 在VC下执行DOS命令 a. system("md c:\\12"); b. WinExec("Cmd.exe /C md c:\\12", SW_HIDE); c. ShellExecute ShellExecute(NULL,

Android界面编程——导航栏及菜单(六)

Android界面编程--导航栏及菜单 2.7导航栏及菜单 2.7.1  ActionBar ActionBar是Android3.0(API 11)开始增加的新特性,ActionBar出现在活动窗口的顶部,可以显示标题.icon.Actions按钮.可交互View,可实现应用程序级的导航,如图2.7-1所示 图2.7-1 其中 1. App icon: 主要用于展示App的Logo,如果当前界面不是一级界面,还可以展示返回航. 2.View Control: 用于切换不同的视图或者展示非交互信

Spark2.0从入门到精通:Scala编程、大数据开发、上百个实战案例、内核源码深度剖析视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

linux下C语言socket网络编程简例

转自:http://blog.csdn.net/kikilizhm/article/details/7858405 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后打印出来,然后关闭.程序里有详细的说明,其中对具体的结构体和函数的实现可以参考其他资料. 程序说明: 这里服务器的端口号和ip地址使用固定的设置,移植时可以根据具体情况更改,可以改写为参数传递更好,这里为了方便,使用固定的. 移

VC++界面编程之--仿Facebook透明登录窗口

1. 开发工具:VC++ DUIEngine: 该工程由DUIEngine创建,没了解过DUIE的同学,可以看前面的DUIE配置文章:点击打开链接 编译DUIE工程时,请选择"全部重新构建"构建所有的工程,以确保所有的更改都能生效.因为当你修改XML文件后,VS不会把其当做更新项,进行重新构建. 2. 制作图像文件,并拷贝至DUIE工程的skin\image文件夹下: DUIE的皮肤默认图像文件都是PNG类型的,所以尽量不要用bmp格式的,以免有些半透明的效果无法显示. 还有一点是:有

ios学习记录 day44 UI20 Storyboard 高级可视化编程 + 单例

可视化编程 : 5.0之前 xib  5.0之后 Storyboard 注意事项:1.在AppDelegate中不用代码初始化一个window   2.在general  设置 Main Interface(创建的时候自动设置的) weak可以指向 但是没有拥有权   strong有拥有权 单例特性: 1.唯一性  创建的对象永远指向同一块内存地址     2.不释放   从打开程序到后台关闭 对象都不释放 单例安全:加锁@synchronized  防止同一块内存被创建两次,破坏唯一性 //单

积累的VC编程小技巧之图标、光标及位图

1.图标透明 (1).Windows中的图标其实是有两个图像组成的,其中一个用于与它要显示的位置的图像做"AND"操作,另一个作"XOR"操作. 透明:用"白色"AND,用"黑色"XOR反色:用"白色"AND,用"白色"XOR正常色:用"黑色"AND,用正常颜色XOR.(2). WIN9X中好像是对像素的操作实现透明的WIN2K中就有API直接实现透明了!WIN2K中