最近在使用MFC的过程中发现了几个有用的消息,可能有些在类视图的左边找不到,需要自己手动添加,但是感觉这些宏非常有用,在这里记录一下:
ON_UPDATE_COMMAND_UI_RANGE
这个消息的作用是批量修改菜单资源的状态,有时需要禁止一大堆菜单项时使用这个消息非常方便。
这个消息的用法如下:
在对话框的头文件中添加响应函数:
afx_msg void OnMenuItemUI(CCmdUI *pCmdUI);//点击卫片导入后更新菜单项状态
然后在对话框的消息映射之间添加上下面的代码:
ON_UPDATE_COMMAND_UI_RANGE(ID_BEGIN,ID_END,&OnMenuItemUI)
这个消息映射的第一个参数是一个起始的ID号,第二个参数是一个结束的ID号,第三个参数是消息响应函数。
void CMainFrame::OnMenuItemUI(CCmdUI *pCmdUI)
{
//如果某种条件满足时,更新指定ID的控件的状态
//注意下面的ID_ONE和ID_TWO要介于在消息映射中添加的ID_BEGIN 和ID_END之间。
//然后可以使用switch语句对需要处理的ID进行处理
if (flag)
{
switch (pCmdUI->m_nID)
{
case ID_ONE:
pCmdUI->Enable(false);
break;
case ID_TWO:
pCmdUI->Enable(false);
break;
default :
break;
}
}
}
ON_EN_KILLFOCUS
这个消息的用法如下:
在对话框的头文件中添加响应函数:
afx_msg void OnKillFocusEditBox();
然后在对话框的消息映射之间添加上下面的代码:
ON_EN_KILLFOCUS(IDC_ONE, &COutputParameterPage::OnKillFocusEditBox)
ON_EN_KILLFOCUS(IDC_TWO, &COutputParameterPage::OnKillFocusEditBox)
这个函数的作用主要是用来校验对话框中文本框(CEdit)的数据,当对话框中的文本框失去焦点(注意是对话框中的文本框,不是对话框)后这个函数就会被调用,上面的消息映射中对两个ID添加了这个函数,那么会在这两个ID表示的控件失去焦点后调用OnKillFocusEditBox这个函数。同时为了校验后更改文本框的内容,需要对该文本框添加一个成员变量(下面用m_data表示与ID_ONE关联的成员变量,并校验这个数据,用0.0表示出错的情况,将它修正成1.0)
void COutputParameterPage::OnKillFocusEditBox(){
//首先使用true将数据从控件传入成员变量中
UpdateData(true);
//校验成员变量m_data中的数据是否符合要求,如果不符合,修改后将它显示在控件中
if (m_data=0.0)
{
m_data=1.0
UpdateData(false);
}
}
发现上面这个消息有个问题,就是这个消息会触发两次。不知道是怎么回事,断点调试时发现一个文本框失去焦点时这个函数会触发,并且也会触发另外一个文本框失去焦点二进入这个事件。弄了好久,又是尝试自定义消息和自定义文本框(结果任然进去了两次),又是在PreTranslateMessage中截取EN_KILLFOCUS消息(这个消息的
LOWORD(wParam)一直为0,不为文本框的ID),这两中方法都没有逃离EN_KILLFOCUS这个消息的范畴,我都是想在EN_KILLFOCUS这个消息上做文章,但是怎么都成功不了。
如果不需要弹出对话框的话这个消息进去两次就两次,无所谓,但是要弹出对话框的话就肯定不能让他进去两次了。后来发现了一个方法,就是不要理会EN_KILLFOCUS这个消息,转而处理WM_LBUTTONDOWN消息,因为文本框的内容改变后肯定还会有一次鼠标左键单击事件,但是这个消息却不能在窗口类中直接添加消息映射,因为这个映射只会在鼠标点击对话框中的空白区时才会触发,如果你点击的是对话框中的文本框或者按钮这种控件是不会执行WM_LBUTTONDOWN这个消息的响应函数的。但是这显然与这里的要求不符合,我想做的是点击对话框的任何区域都要做一次验证。这就需要在PreTranslateMessage中截获WM_LBUTTONDOWN消息,然后处理就行了,这样无论点击对话框中的什么地方都会响应这个函数了。代码如下:OnKillFocusEditBox函数就是上面的校验函数,注意这时可以将OnKillFocusEditBox函数变成普通函数(声明前不需要afx_msg了)
BOOL COutputParameterPageMore::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message==WM_LBUTTONDOWN)
{
OnKillFocusEditBox();
}
return CPropertyPage::PreTranslateMessage(pMsg);
}