无资源文件依赖的 MFC 计算器自定义控件






4.16/5 (22投票s)
2004年8月6日
6分钟阅读

147721

6817
一个可重用的计算器自定义控件,它工作起来和看起来都像一个手持计算器,可以通过简单地将cpp和h文件添加到项目中来在任何MFC应用程序中使用(无资源文件依赖)。
引言
这是一个简单的计算器自定义控件,您可以轻松地在您的应用程序中重用。易于重用,不一定要编写!
没有资源文件依赖,您可以在Visual Studio的资源编辑器中自由调整计算器的大小,并且可以更改字体和结果窗口的文本和背景颜色。
我将尝试将本文分为两个部分
- 用法:“我的应用程序需要一个计算器控件——请给我最少的使用信息。只要它能用,我不在乎它是怎么写的”。
- 分析编写MFC自定义控件相关的任何有趣的编码或其他特性。我将尝试涵盖我在过程中遇到的关键挑战、问题和陷阱。
用法
在您的应用程序中使用MFC计算器控件很简单
- 将文件CalculatorCtrl.cpp和CalculatorCtrl.h添加到您的项目中。
- 在Visual Studio .NET资源编辑器中,将一个自定义控件对象添加到您的对话框中,并调整到所需的计算器大小。控件将在运行时“扩展”以填充您在资源编辑器中分配的空间。
- 在资源编辑器的对象属性页面中,将“类”字段设置为“MFC CalculatorCtrl”。
- 通过在资源编辑器中右键单击该对象并从弹出菜单中选择“添加变量”,在您的对话框类中创建一个类型为
CCalculatorCtrl
的成员变量。 - 在您的对话框的
OnInitDialog()
中,使用下面描述的公共成员函数更改任何计算器默认值。 - 如果希望在用户按下“=”两次(表示他们已完成计算器使用并希望在您的应用程序中使用结果)时通知您的对话框,请记住调用
CCalculatorCtrl::SetDblEqualsReturns(TRUE)
。然后,通过在对话框的消息映射中添加类似以下内容的内容,为您的对话框类添加一个消息处理器,用于处理消息_MSG_CALCULATOR_EQUALS
。ON_MESSAGE(_MSG_CALCULATOR_EQUALS, OnCalculatorEquals)
无论哪种方式,都可以随时通过调用
CCalculatorCtrl::GetCalculatorValue()
来“获取”计算器控件当前的答案值。
该控件支持鼠标点击和键盘操作。键盘操作与Windows计算器相同,除了在计算出答案后第二次按下等于键,以表示用户希望在您的应用程序中使用计算结果。
公共函数
这些函数中的大多数都在示例程序的对话框类中使用
void SetDblEqualsReturns(BOOL bDblEqualsReturns)
如果
bDblEqualsReturns
为TRUE
,则当用户在完成计算后第二次按下“=”键时,控件将向对话框发送一个自定义消息_MSG_CALCULATOR_EQUALS
。(在示例程序中,这通过对话框类发送的消息框确认来实现。)如果您不调用此函数,则默认值为
FALSE
,即双等于不发送消息。在您的对话框的
OnInitDialog()
函数中调用此函数。BOOL GetDblEqualsReturns(void)
返回当前双等于状态(请参阅
SetDblEqualsReturns()
)。void SetNumFormat(LPCTSTR strNumFormat)
设置用于在计算器结果窗口中显示数字的(双精度)浮点数字格式字符串。在对话框的
OnInitDialog()
函数中调用此函数,并在调用CCalculatorCtrl::SetCalculatorValue()
之前调用。如果您不调用此函数,将使用默认格式字符串“%f”,该格式字符串的精度为6位小数。
void SetCalculatorValue(double fValue);
将计算器的初始值设置为
fValue
。double GetCalculatorValue(void);
返回计算器的当前答案。在处理
_MSG_CALCULATOR_EQUALS
消息的处理器中调用。void SetResultsWndFont(LOGFONT* pLogFont);
void GetResultWndFont(LOGFONT* pLogFont);
根据传递或返回的
LOGFONT
结构,设置/获取计算器结果窗口使用的字体。在对话框的OnInitDialog()
函数中调用此函数。void SetButtonFont(LOGFONT* pLogFont);
void GetButtonFont(LOGFONT* pLogFont);
根据传递或返回的
LOGFONT
结构,设置/获取计算器按钮使用的字体。在对话框的OnInitDialog()
函数中调用此函数。COLORREF SetResultsWndTxtClr(COLORREF rgbNewColour);
设置计算器结果窗口的文本颜色。在对话框的
OnInitDialog()
函数中调用此函数。COLORREF SetResultsWndBkClr(COLORREF rgbNewColour);
设置计算器结果窗口的背景颜色。
背景
CodeProject上还有其他文章详细介绍了编写MFC自定义控件的基础知识,我在这里不会重复基础知识。请参阅Andreas Saurwein的“Designing a Windows Control - Part 1”,以及Chris Maunder的“Creating Custom Controls”。
以下是一些代码中的有趣之处,我未在上述文章中找到涵盖的内容
在没有对话框资源的情况下使用Windows控件
设计目标是使此控件易于部署。虽然可以在项目之间复制资源,但这很麻烦且不整洁;因此,在这种情况下,控件由控件的PreSubclassWindow()
成员函数创建、调整大小和布局。在这里,我们使用GetWindowPlacement()
获取可用空间,并通过编程方式创建和布局控件。
控件中有25个CButton
和一个CEdit
。您会看到,按钮不是逐个创建的,而是在循环中创建的。每个按钮的ID都设置为常量NUMBERBUTTONS_BASEID
(定义在CPP文件顶部)加上循环计数器变量。
而不是为每个按钮设置单独的消息处理器,我使用了ON_COMMAND_RANGE
宏来实现一个单一的处理器函数(OnCalcButtonPressed()
)来处理来自按钮的消息,并将其转换为计算器行为。
控件中的键盘输入处理
上面两篇文章都没有涵盖计算器控件所需的键盘输入处理。
实现它并不像我希望的那么简单。我实现了一个ON_WM_KEYDOWN()
的处理器,在该处理器中,我将接收到的虚拟键转换为CButton
ID,然后调用我的OnCalcButtonPressed()
成员函数。
此外,有必要添加一个ON_WM_GETDLGCODE
的处理器,否则键盘输入不会在控件中“被消耗”,每次按下键时都会发出Windows的“默认哔哔”声音。
为了解决这个问题,在ON_WM_GETDLGCODE
处理器中,我们不调用CWnd
的默认实现,而是直接返回DLGC_WANTALLKEYS
。
// We want control to absorb all keystrokes UINT CCalculatorCtrl::OnGetDlgCode() { // return CWnd::OnGetDlgCode(); return DLGC_WANTALLKEYS; }
最后,我们需要捕获ESCAPE和RETURN键,因为ESCAPE键是计算器的“CE/C”键盘等效键,而RETURN键是“等于”按钮。如果我们不专门处理这个问题,这些键将被传递给对话框,并很可能导致对话框ONOK
或ONCANCEL
。
为确保ESCAPE和RETURN键不会在向上冒泡,我们实现了以下PreTranslateMessage
处理器:
BOOL CCalculatorCtrl::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if( pMsg->message == WM_KEYDOWN ) { if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE ) { ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); return TRUE; // DO NOT process further } } return CWnd::PreTranslateMessage(pMsg); }
我想,对于任何需要实现键盘输入处理的自定义控件来说,其中一些都是标准的做法,但对我来说是新的,而且我在Code Project或网上找不到太多相关的帮助,所以希望其中一些能有所帮助!
结论
无论这里的代码是否优雅,它似乎都能正常工作,并为任何MFC应用程序提供了一个快速的即插即用组件。希望您觉得有用。
如果您喜欢该控件或觉得这篇文章有趣,如果您能通过以下方式帮助我,我将不胜感激:
- 投票给这篇文章——我需要所有的鼓励!
- 请访问我的网站并阅读我的Web Update Wizard产品——这是一个低成本的组件,只需一行代码即可为您的应用程序添加“Web更新”功能。
- 如果您对销售预测软件感兴趣(或认识这样的人!),请查看我的另一个网站,在那里您可以了解我大部分时间在做什么——开发Prophecy,一个销售预测应用程序。
感谢您阅读我的文章。