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问题