【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏

编程入门 行业动态 更新时间:2024-10-25 10:32:25

【MFC】08.MFC<a href=https://www.elefans.com/category/jswz/34/1771421.html style=消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏"/>

【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏

本专栏上几篇文章讲解了MFC几大机制,今天带领大家学习MFC自定义消息以及常用控件,最常用的控件请查看本专栏第一二篇文章,今天这篇文章介绍工具栏,菜单和状态栏,以及菜单创建大总结。

文章目录

  • MFC消息分类:
  • 菜单创建方法总结
      • 1.对话框上直接添加菜单资源:
      • 2. 在WM_CREATE消息处理中加载菜单,设置菜单
      • 3.框架类Create方法中创建
      • 4.使用CMenu对象创建
  • MFC范围宏:
  • 工具栏控件
  • 状态栏控件
  • 右键消息处理:
  • 总结

MFC消息分类:

  • Windows下的常用消息(标准消息)

    win32 WM_CREATE WM_PAINT

  • 在Win32消息前添加ON_

    WM_COMMAND 菜单按钮,加速键是单独处理的

  • 用户自定义消息:

    #define MY_MSG WM_USER+N
    用户自定义消息,我们在MFC中使用通配:ON_MESSAGE(ID,PFUN)也就是说:
    在消息映射中,
    BEGIN_MESSAGE_MAP(CMyFrameWdn,CFreamWnd)ON_WM_CREATE()
    END_MESSAGE_MAP()而这个消息,MFC早就帮我们写好了,我们可以自己去看一看,由于这是一个虚函数,我们也可以重写:
    在类中:
    int OnCreate(LPCRATESTRUCT cs){AfxMessageBox(L"WM_CREATE");return 0;
    }
    我们运行发现,这时候,WM_CREATE消息,处理的时候,就是我们自己写的函数了
    
  • 用户自定义消息:
    首先,我们需要去定义宏,我们自定义消息:
    #define MY_MSG WM_USER+1
    用户自定义消息,MFC已经帮我们写好了统配消息映射:ON_MESSAGE()
    接下来,我们来看看官方定义:

#define ON_MESSAGE(message, memberFxn) \{ message, 0, 0, 0, AfxSig_lwl, \(AFX_PMSG)(AFX_PMSGW) \(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \(memberFxn)) },

那么我们就可以自己定义函数:

  1. 首先,设置签名:
	afx_msg LRESULT onMyMsg(WPARAM,LPARAM);
  1. 实现:
LRESULT CMenuToolBarDlg::onMyMsg(WPARAM W,LPARAM L)
{AfxMessageBox(L"My_Msg");return 0;
}

这里就弹一个消息框
3. 我们发送消息看看:

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码AfxMessageBox(L"onCreate");SendMessage(MY_MSG, 0, 0);return 0;
}

这里是重写了Create函数,发送了我们自定义的消息

菜单创建方法总结

之前几篇文章中我们已经讲解过了好几种加载菜单的方法,今天我们来总结一下

1.对话框上直接添加菜单资源:

这种方法可谓是非常简单了,直接在对话框属性上添加菜单,MFC会自动帮我们生成代码:
首先我们创建菜单资源:

然后到对话框属性中设置就可以了:

这样就算设置好了,我们运行:

我们发现对话框已经创建好了

2. 在WM_CREATE消息处理中加载菜单,设置菜单

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码HMENU hMenu = LoadMenu((HINSTANCE)GetWindowLongPtr(m_hWnd, GWLP_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));::SetMenu(m_hWnd, hMenu);return 0;
}

这样运行之后,我们发现菜单也创建出来了

3.框架类Create方法中创建

我们前面在介绍MFC几大机制的时候,介绍了框架类,我们使用框架类的Create方法也可以创建菜单:
基本使用方法就是CFRame::Create(…);

4.使用CMenu对象创建

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码CMenu menu;menu.LoadMenuW(IDR_MENU1);this->SetMenu(&menu);return 0;
}

使用CMenu这种方法也可以创建菜单,但是创建了菜单之后,点击之后,会崩溃:

(这里我创建的MFC是基于对话框的,之前在基于单文档架构的时候会崩溃)
这是应为CMenu对象被析构
解决方法:在类中声明CMenu成员,new出来,这样就不会被析构:
我们首先声明成员:CMenu* menu = new CMenu;
这样时候,我们函数这样写:

int CMenuToolBarDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码menu->LoadMenuW(IDR_MENU2);this->SetMenu(menu);return 0;
}

这样创建就没有问题了。

MFC范围宏:

我们在处理按钮或者菜单消息等的时候,我们有时候有这种需求:连续几个按钮,都有着相同的回调方法,这时候,我们就可以使用范围宏:

  1. 首先我们来创建这样一个菜单:

    我们将这三个菜单ID设置为连续,我这里是32273,32274,32275
    我们到消息映射中使用范围宏来处理:
    我们首先来看一下范围宏的定义:
#define ON_COMMAND_RANGE(id, idLast, memberFxn) \{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_RANGE, \(AFX_PMSG) \(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT) > \(memberFxn)) },

我们到消息映射中添加:

ON_COMMAND_RANGE(ID_32773,ID_32775,onRangle)

然后我们定义回调函数:

void CMenuToolBarDlg::onRangle(UINT id)
{CString str;str.Format(L"按钮id = %d", id);AfxMessageBox(str);
}

这样我们就可以统一处理这三个按钮了:

工具栏控件

  1. 我们到资源中创建工具栏对象:
  2. 然后,我们加载工具栏:
    首先我们要在类中声明CToolBar成员:
    CToolBar toolBar
    然后,到Create函数中加载工具栏:
	if (!toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS) || !toolBar.LoadToolBar(IDR_TOOLBAR1)){ AfxMessageBox(TEXT("Failed to create toolbar!"), NULL, NULL);return FALSE;}m_toolBar.EnableDocking(CBRS_ALIGN_ANY);this->EnableDocking(CBRS_ALIGN_ANY);this->DockControlBar(&m_toolBar,AFX|IDW_DOCKBAR_TOP);

很多软件的提示栏,我们鼠标移动到上面的时候,都有提示信息,我们也可以到工具栏的按钮上面添加提示信息:
比如紫色\n按钮
\n之前的信息会出现在状态栏上,之后的信息,我们鼠标移动到上面的时候,会直接显示.

状态栏控件

状态栏控件我们不需要添加资源,直接在创建窗口的时候加载就可以了:

类中添加成员
SCtatusBar statusBar;onCreate消息中:
statusBar.CreateEx(this);

我们发现状态栏只有一项,如果我们想添加,就要定义一个全局数组:
UNIT g_arr[]= {0,ID_TIME,2,};
我们再来设置:

指示器 
statusBar.SetIndicators(g_arr,3);
//ID---表示字符串
statusBar.SetPaneInfo(1,ID_TIME,SBPS_NORMAL,100);

这时候就发现可以分项了。
我们来处理一下状态栏:
我们设置系统时间到状态栏上:
消息映射:

ON_WM_TIMER()
void CMenuToolBarDlg::OnTimer(UINT_PTR id)
{SYSTEMTIME time;::GetLocalTime(&time);CString str;str.Format(L"%d-%d-%d %d:%d:%d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);staubar.SetPaneText(1, str);
}

右键消息处理:

以前我们处理右键单击消息都是通过消息来处理的,今天我来带领大家使用MFC的另一种方式:
消息映射:

N_WM_CONTEXTMENU()

处理:

void onContextMenu(CWnd*,CPoint pt){CMenu menu;menu.LoadMenu(IDR_MENU1);CMenu* pPopMenu = menu.GetSubMenu(0);::tRACKpOPUPmENU(PpOPmENU->m_hMenu,TPM_CENTERALIGN,pt.x,pt.y,0,this->hWnd,NULL);;
}

我们通常使用右键来弹出右键菜单,这里介绍一种方式,弹出右键菜单的时候,可以初始化:

void onInitMenuPopup(CMenu* pMenu,UINT,BOOL){::CheckMenuItem(pMenu->m_hMenu,ID_DEL,MF_CHECKED);
}

总结

最后总结一下容易出现的误区:

  1. 我们使用MFC消息映射的时候,很多时候都需要我们自己写函数,但是很多时候我们会写错,不知道参数该些什么,返回值该写什么,实际上,我们查看宏定义(就是消息映射上的宏)就可以看到函数名称,返回值,参数等
  2. 或者我们再定义宏的时候,可以在括号里写上消息ID和回调函数,就可以解决上述问题
    好了,今天的分享就到这里,大家如果发现有什么错误,还请及时指出来,我们大家共同进步!!!

更多推荐

【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏

本文发布于:2024-02-27 02:35:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1704882.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:消息   自定义   控件   工具栏   状态栏

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!