MFC 自定义非窗口类控件中实现 ON_COMMAND 和 ON_UPDATE_COMMAND_UI

MFC 定制界面会用到自定义非窗口类控件,因为每一个小按钮都从窗口继承时浪费资源,效率低。本文描述如何在自定义非窗口类控件中实现 ON_COMMAND 和 ON_UPDATE_COMMAND_UI。

一、ON_COMMAND

ON_COMMAND 是 MFC 的命令映射和传递机制,简化消息处理接口,步骤如下:

 1. 基类必须含 CCmdTarget

class AFX_EXT_CLASS HCtrl : public CCmdTarget
 2. 加DECLARE_MESSAGE_MAP()和BEGIN_MESSAGE_MAP

 3. 在主窗口的OnCmdMsg消息中加如下代码

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
    // 让自定义类第一次尝试该命令,不加这一句,收不到命令
    if (m_pHCtrl->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
        return TRUE;
 
    // 否则,执行默认处理
    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
4. 加入如下类似代码处理命令

BEGIN_MESSAGE_MAP(DynamicScan, HCtrl)
	ON_COMMAND(TID_NUCORRECTION, OnNucorrection)	// 不均匀校正
	ON_COMMAND(TID_NOISE, OnNoise)	// 模拟噪声设置
	ON_COMMAND(TID_FREEZE, OnFreeze)	// 冻结
END_MESSAGE_MAP()

好了,ON_COMMAND 功能完成,下面的功能更实用。

二、ON_UPDATE_COMMAND_UI

如果在逻辑代码中设置控件的状态,包括选择,不可用等,要设的地方很多,效率低,容易遗漏,不易修改。ON_UPDATE_COMMAND_UI 很好地解决了这个问题,基本原理是当进程空闲时,应用程序自动产生WM_IDLEUPDATECMDUI消息,更新所有控件状态。

1. 自定义更新类

// HCmdUI idle update through HCmdUI class
class AFX_EXT_CLASS HCmdUI : public CCmdUI
{
public:
	HCmdUI();

	virtual void Enable(BOOL bOn);
	virtual void SetCheck(int nCheck);
	virtual void SetText(LPCTSTR lpszText);
	virtual void SetRadio(BOOL bOn = TRUE);

	HCtrl* m_pUpdated;
};

2. 在自定义控件中加入如下代码

// 自动更新控件状态
void HCtrl::OnUpdateCmdUI(HCmdUI* pCmdUI, BOOL bDisableIfNoHndler)
{
	ASSERT_VALID(m_pWnd);

	// 先更新子控件
	int n = m_arChildren.GetCount();
	for( int i = 0; i < n; i++)
	{
		m_arChildren[i]->OnUpdateCmdUI( pCmdUI, bDisableIfNoHndler );
	}

	((HCmdUI*)pCmdUI)->m_pUpdated = this;	// 本控件指针

	pCmdUI->m_nID = m_nID;
	pCmdUI->DoUpdate(m_pWnd, bDisableIfNoHndler);

	((HCmdUI*)pCmdUI)->m_pUpdated = NULL;
}
3. 主窗口中添加消息处理

BEGIN_MESSAGE_MAP(HWnd, CWnd)
	.
	.
	.
	ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)	// WM_IDLEUPDATECMDUI 类视图中没有这个消息
END_MESSAGE_MAP()
LRESULT HWnd::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM)
{
	if (!(GetStyle() & WS_VISIBLE))
		return 0L;
	BOOL bDisableIfNoHndler = (BOOL)wParam;
	HCmdUI state;
	state.m_pOther = this;
	m_ctrFrame.OnUpdateCmdUI( &state, bDisableIfNoHndler );
	return 0L;
}
注意:mfc2010的类向导中没有WM_IDLEUPDATECMDUI这个消息,要手动添加消息处理。

4. 添加具体的处理函数

BEGIN_MESSAGE_MAP(PanlCtr, HCtrl)
	ON_UPDATE_COMMAND_UI(TID_SAVE, OnSaveUpdateUI)
END_MESSAGE_MAP()
void PanlCtr::OnSaveUpdateUI(CCmdUI *pCmdUI)
{
	if( !pCmdUI->m_pOther ) //CN_UPDATE_COMMAND_UI 不处理
		return;

	((HCmdUI*)pCmdUI)->m_pUpdated->setText( L"aaaaaaa" );
}

至此实现ON_UPDATE_COMMAND_UI。

以上只是这两个功能的一些要点,使用时根据实际情况调整。

有不妥之处请指正。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值