CMFCRibbonEdit的按键消息响应

        CMFCRibbonEdit是实现位于功能区栏的编辑控件。在这里简单介绍下其使用方法及消息响应。以下在VS2008SP1环境:
1.新建一个多文档Ribbon工程,名称为:TestRibbon;
2.按如下添加一个菜单项:

3.右键此菜单项," 添加事件处理程序",在这里我们添加到视图类,如下图所示:
void CTestRibbonView::OnEditTest() 
{
    AfxMessageBox(_T("测试"));
}
4.在 MainFrm.cpp文件里面的 InitializeRibbon函数,添加如下代码:
    CMFCRibbonPanel *pPanelTest = pCategoryHome->AddPanel(_T("测试")); 
    CMFCRibbonEdit *pEditTest = new CMFCRibbonEdit(ID_EDIT_TEST, 120, _T("输入文本:\nq"));
    pPanelTest->Add(pEditTest);
5.运行如下图所示:

6.在编辑框里输入完文本按回车,可以发现调用了两次 AfxMessageBox(_T("测试")),这不合乎我们平时的要求,根据源码发现 CMFCRibbonEdit在按键消息处理 PreTranslateMessage处,当按键为回车键时调用 NotifyCommand通知命令并使其失去焦点,却又在 OnKillFocus再次调用 NotifyCommand通知命令,所以一共触发了两次。解决的方法有多种,在这里我想截获编辑框的按键消息以处理以后更多的要求,继续分析源码可知 CMFCRibbonEdit基类的基类,即 CMFCRibbonBaseElement有个可重写的 OnProcessKey方法。比较了BCGControlBar12版本的 BCGPRibbonEdit.cpp和VC2008SP1的 afxribbonedit.cpp,可以发现CMFCRibbonEdit在按键消息处理 PreTranslateMessage处并没有调用 OnProcessKey,而CBCGPRibbonEdit有调用 OnProcessKey,只需要简单重写下就可以。而对 CMFCRibbonEdit就比较麻烦,下面是其中一种解决方法:
派生类头文件:
#pragma once

//
// CKofMFCRibbonEdit

class CKofMFCRibbonEdit : public CMFCRibbonEdit
{
	friend class CKofMFCRibbonRichEditCtrl;
	DECLARE_DYNCREATE(CKofMFCRibbonEdit)

protected:
	CKofMFCRibbonEdit();

public:
	CKofMFCRibbonEdit(UINT nID, int nWidth, LPCTSTR lpszLabel = NULL, int nImage = -1);
	virtual ~CKofMFCRibbonEdit();

	virtual CMFCRibbonRichEditCtrl* CreateEdit(CWnd* pWndParent, DWORD dwEditStyle);
	virtual BOOL OnProcessKey(UINT nChar);
};

//
// CKofMFCRibbonRichEditCtrl

class CKofMFCRibbonRichEditCtrl : public CMFCRibbonRichEditCtrl
{
	friend class CKofMFCRibbonEdit;

public:
	CKofMFCRibbonRichEditCtrl(CMFCRibbonEdit& edit);
	virtual ~CKofMFCRibbonRichEditCtrl();

	virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
	DECLARE_MESSAGE_MAP()
};
派生类实现文件:
#include "stdafx.h"
#include "KofMFCRibbonEdit.h"

//
// CKofMFCRibbonEdit

IMPLEMENT_DYNCREATE(CKofMFCRibbonEdit, CMFCRibbonEdit)

CKofMFCRibbonEdit::CKofMFCRibbonEdit(UINT uiID, int nWidth, LPCTSTR lpszLabel, int nImage)
:CMFCRibbonEdit(uiID, nWidth, lpszLabel, nImage)
{
}

CKofMFCRibbonEdit::CKofMFCRibbonEdit()
{
}

CKofMFCRibbonEdit::~CKofMFCRibbonEdit()
{
}

CMFCRibbonRichEditCtrl* CKofMFCRibbonEdit::CreateEdit( CWnd* pWndParent, DWORD dwEditStyle )
{
	ASSERT_VALID(this);
	ASSERT_VALID(pWndParent);

	CMFCRibbonRichEditCtrl* pWndEdit = new CKofMFCRibbonRichEditCtrl(*this);

	if (!pWndEdit->Create(dwEditStyle, CRect(0, 0, 0, 0), pWndParent, m_nID))
	{
		delete pWndEdit;
		return NULL;
	}

	if (m_bHasSpinButtons)
	{
		CreateSpinButton(pWndEdit, pWndParent);
	}

	return pWndEdit;
}

BOOL CKofMFCRibbonEdit::OnProcessKey( UINT nChar )
{
	switch (nChar)
	{
	case VK_RETURN:
		if (!IsDroppedDown())
		{
			TRACE(_T("Press Enter Key\r"));
			if (m_pWndEdit->GetSafeHwnd() != NULL)
			{
				if (m_pWndEdit->GetTopLevelFrame() != NULL)
				{
					m_pWndEdit->GetTopLevelFrame()->SetFocus();
				}
			}			
			return TRUE;
		}		
		break;
	}
	return FALSE;
}

//
// CKofMFCRibbonRichEditCtrl

CKofMFCRibbonRichEditCtrl::CKofMFCRibbonRichEditCtrl(CMFCRibbonEdit& edit)
:CMFCRibbonRichEditCtrl(edit)
{
}

CKofMFCRibbonRichEditCtrl::~CKofMFCRibbonRichEditCtrl()
{
}

BEGIN_MESSAGE_MAP(CKofMFCRibbonRichEditCtrl, CMFCRibbonRichEditCtrl)
END_MESSAGE_MAP()

BOOL CKofMFCRibbonRichEditCtrl::PreTranslateMessage( MSG* pMsg )
{
	if (pMsg->message == WM_KEYDOWN && !m_edit.IsDisabled ())
	{
		CKofMFCRibbonEdit *pedit = (CKofMFCRibbonEdit *)&m_edit;
		if (pedit->OnProcessKey ((UINT)pMsg->wParam))
		{
			return TRUE;
		}
	}
	return CMFCRibbonRichEditCtrl::PreTranslateMessage(pMsg);
}
7.在 MainFrm.cpp文件里面添加以及修改如下内容:
#include "KofMFCRibbonEdit.h"
CMFCRibbonPanel *pPanelTest = pCategoryHome->AddPanel(_T("测试"));
CKofMFCRibbonEdit *pEditTest = new CKofMFCRibbonEdit(ID_EDIT_TEST, 120, _T("输入文本:\nq"));
pPanelTest->Add(pEditTest);
8.重新运行,可以发现只调用一次 AfxMessageBox(_T("测试"))
注:以上未在VS2010中测试。未有VC2010的相关部分源码,可能已经修改成与CBCGPRibbonEdit一样。CMFCRibbonComboBox的按键消息也可类似实现。以上文章若有错误,欢迎指出。

2012年5月14日 修正DECLARE_DYNCREATE问题
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值