MFC OnChar、OnKeyDown、OnKeyUp和PreTranslateMessage的关系

假设按下键盘上的任意一个键,则OnChar、OnKeyDown、OnKeyUp均会被调用。它们被调用的先后顺序为:

1、OnKeyDown

2、OnChar

3、OnKeyUp

在对话框应用程序中,无论用户是否操作鼠标或键盘,PreTranslateMessage函数始终不断地被调用。MSDN中关于PreTranslateMessage函数的说明如下:

Used by class CWinApp to translate window messages before they are dispatched to the TranslateMessage and DispatchMessage Windows functions.

在默认情况下,对话框应用程序无法响应OnChar、OnKeyDown和OnKeyUp事件。因为与之对应的消息被对话框上的控件截取了。验证方法是将对话框上的所有控件都删除,此时利用OutputDebugString函数不添加任何断点调试运行程序,将发现对话框应用程序能响应全部的OnChar、OnKeyDown和OnKeyUp事件了。如果我们想在对话框应用程序中对特定的按键消息进行处理,可以重载PreTranslateMessage函数。例如下面通过重载PreTranslateMessage函数来屏蔽对话框应用程序对”Esc“和”Enter“键的响应(对话框应用程序有一个默认按钮,缺省为“确定”按钮,可通过编程修改。当用户按下回车键时相当于按下这个默认按钮,即“确定”按钮。另外,当用户按下“Esc“键时,相当于按下对话框的”取消“按钮,即使”确定“或”取消“按钮已经被删除,这种操作依然有效。)

BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类

	if(pMsg->wParam == VK_ESCAPE)  
	{  
		return true;  
	} 

	if(pMsg->wParam == VK_RETURN)  
	{  
		return true;  
	} 

	/*当按下字母A键时,不论大小写与否,wParam最初都为65,然后再为97。即OutputDebugString会被调用至少两次。
	添加断点调试OutputDebugString调用两次,不添加则三次!(VS2008已测)*/
	if( pMsg->wParam==(97) || pMsg->wParam==(65))
	{
		OutputDebugString(_T("WM_CHAR: a \n"));
	}
	return CDialog::PreTranslateMessage(pMsg);
}


  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 MFC 计算器的代码: 首先,可以使用 MFC 库中的 CWnd 类来创建窗口和处理事件。我们需要创建一个派生自 CWnd 的类,我们称之为 CCalculatorWnd。 CCalculatorWnd.h 文件: ```cpp #pragma once class CCalculatorWnd : public CWnd { public: CCalculatorWnd(); protected: afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() private: CString m_strDisplay; double m_dResult; CString m_strOperator; BOOL m_bDecimal; BOOL m_bNewNumber; BOOL m_bError; }; ``` CCalculatorWnd.cpp 文件: ```cpp #include "stdafx.h" #include "Calculator.h" #include "CalculatorWnd.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CCalculatorWnd::CCalculatorWnd() { m_strDisplay = _T("0"); m_dResult = 0.0; m_strOperator = _T(""); m_bDecimal = FALSE; m_bNewNumber = TRUE; m_bError = FALSE; } BEGIN_MESSAGE_MAP(CCalculatorWnd, CWnd) ON_WM_CHAR() ON_WM_LBUTTONDOWN() ON_WM_PAINT() END_MESSAGE_MAP() void CCalculatorWnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if (m_bError) { m_strDisplay = _T("0"); m_dResult = 0.0; m_strOperator = _T(""); m_bDecimal = FALSE; m_bNewNumber = TRUE; m_bError = FALSE; } switch (nChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (m_bNewNumber) { m_strDisplay = _T(""); m_bNewNumber = FALSE; } m_strDisplay += nChar; break; case '.': if (m_bNewNumber) { m_strDisplay = _T("0"); m_bNewNumber = FALSE; } if (!m_bDecimal) { m_strDisplay += nChar; m_bDecimal = TRUE; } break; case '+': case '-': case '*': case '/': if (!m_strOperator.IsEmpty()) { OnLButtonDown(0, CPoint(0, 0)); } m_bNewNumber = TRUE; m_bDecimal = FALSE; m_strOperator = nChar; break; case '=': OnLButtonDown(0, CPoint(0, 0)); m_strOperator = _T(""); break; case '\b': if (m_strDisplay.GetLength() > 1) { m_strDisplay = m_strDisplay.Left(m_strDisplay.GetLength() - 1); } else { m_strDisplay = _T("0"); m_bNewNumber = TRUE; } break; case 'c': case 'C': m_strDisplay = _T("0"); m_dResult = 0.0; m_strOperator = _T(""); m_bDecimal = FALSE; m_bNewNumber = TRUE; break; } Invalidate(); } void CCalculatorWnd::OnLButtonDown(UINT nFlags, CPoint point) { double dOperand = _wtof(m_strDisplay); if (m_strOperator.IsEmpty()) { m_dResult = dOperand; } else { switch (m_strOperator[0]) { case '+': m_dResult += dOperand; break; case '-': m_dResult -= dOperand; break; case '*': m_dResult *= dOperand; break; case '/': if (dOperand == 0.0) { m_strDisplay = _T("Error"); m_bError = TRUE; return; } else { m_dResult /= dOperand; } break; } } CString strResult; strResult.Format(_T("%g"), m_dResult); m_strDisplay = strResult; m_bNewNumber = TRUE; m_bDecimal = FALSE; } void CCalculatorWnd::OnPaint() { CPaintDC dc(this); CRect rcClient; GetClientRect(&rcClient); CBrush brush; brush.CreateSolidBrush(RGB(255, 255, 255)); dc.FillRect(&rcClient, &brush); CFont font; font.CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial")); dc.SelectObject(&font); rcClient.DeflateRect(5, 5); dc.DrawText(m_strDisplay, &rcClient, DT_RIGHT | DT_SINGLELINE | DT_VCENTER); } ``` 最后,在主函数中创建窗口并运行: ```cpp #include "stdafx.h" #include "Calculator.h" #include "CalculatorWnd.h" #ifdef _DEBUG #define new DEBUG_NEW #endif int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); AfxWinInit(hInstance, NULL, ::GetCommandLine(), 0); CCalculatorWnd wnd; wnd.Create(NULL, _T("Calculator"), WS_OVERLAPPEDWINDOW, CRect(0, 0, 200, 200)); wnd.ShowWindow(nCmdShow); wnd.UpdateWindow(); MSG msg; while (::GetMessage(&msg, NULL, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return (int)msg.wParam; } ``` 现在,你就可以编译和运行代码,得到一个简单的 MFC 计算器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值