基于对话框程序中让对话框捕获WM_KEYDOWN消息的实现方法

在对话框程序中,我们经常是利用对话框上的子控件进行命令响应来处理一些事件。如果我们想要让对话框(子控件的父窗口)类来响应我们的按键消息,我们可以通过ClassWizard对WM_KEYDOWN消息进行响应,当程序运行后,我们按下键盘上的按键,但对话框不会有任何的反应。这是因为在对话框程序中,某些特定的消息,例如按键消息,它们被Windows内部的对话框过程处理了(即在基类中完成了处理,有兴趣的读者可以查看MFC的源代码),或者被发送给子控件进行处理,所以我们在对话框类中就捕获不到按键的消息了。

既然我们知道了这个处理的过程,我们就可以找到底层处理按键消息的函数,然后在子类中重载它,就可以在对话框程序中处理按键消息了。在MFC中,是利用BOOL ProcessMessageFilter(int code, LPMSG lpMsg)这个虚函数来过滤或响应菜单和对话框的特定Windows消息。下面我们通过程序给大家演示基于对话框的应用程序对WM_KEYDOWN消息的捕获。

第一步:新建一个工程,选择MFC AppWizard (exe),工程名为WinSun,点击ok,进入下一步,选择Dialog based,点击Finish。

第二步:在CWinSunApp类上点击右键,选择Add Member Varialbe,增加一个类型为HWND,变量名m_hwndDlg的public的变量。

代码如下:


代码如下:

WinSun.h

class CWinSunApp : public CWinApp

{

public:

HWND m_hwndDlg;

CWinSunApp();

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CWinSunApp)

public:

virtual BOOL InitInstance();

//}}AFX_VIRTUAL

// Implementation

//{{AFX_MSG(CWinSunApp)

// NOTE - the ClassWizard will add and remove member functions here.

//    DO NOT EDIT what you see in these blocks of generated code !

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

第三步:在WinSun.cpp(CWinSunApp类)文件中的InitInstance()函数中添加如下代码:


代码如下:

WinSun.cpp

BOOL CWinSunApp::InitInstance()

{

AfxEnableControlContainer();

// Standard initialization

// If you are not using these features and wish to reduce the size

//  of your final executable, you should remove from the following

//  the specific initialization routines you do not need.

#ifdef _AFXDLL

Enable3dControls();                     // Call this when using MFC in a shared DLL

#else

Enable3dControlsStatic();      // Call this when linking to MFC statically

#endif

CWinSunDlg dlg;

m_pMainWnd = &dlg;

int nResponse = dlg.DoModal();

if (nResponse == IDOK)

{

// TODO: Place code here to handle when the dialog is

//  dismissed with OK

}

else if (nResponse == IDCANCEL)

{

// TODO: Place code here to handle when the dialog is

//  dismissed with Cancel

}

// Since the dialog has been closed, return FALSE so that we exit the

//  application, rather than start the application's message pump.

m_hwndDlg=NULL;

return FALSE;

}

第四步:在CWinSunApp类上点击右键,选择Add Virtual Function,在左边一栏里,选择ProcessMessageFilter,在右边按钮上选择Add and Edit,然后加入以下代码:


代码如下:

WinSun.cpp

BOOL CWinSunApp::ProcessMessageFilter(int code, LPMSG lpMsg)

{

// TODO: Add your specialized code here and/or call the base class

if(m_hwndDlg!=NULL)

{

//判断消息,如果消息是从对话框发出的或者其子控件发出的,我们就进行处理。sunxin

if((lpMsg->hwnd==m_hwndDlg) || ::IsChild(m_hwndDlg,lpMsg->hwnd))

{

//如果消息是WM_KEYDOWN,我们就弹出一个消息框。sunxin

if(lpMsg->message==WM_KEYDOWN)

{

AfxMessageBox("捕获WM_KEYDOWN消息成功!");

}

}

}

return CWinApp::ProcessMessageFilter(code, lpMsg);

}

第五步:在WinSunDlg.cpp(CWinSunDlg类)中的OnInitialDialog()函数中加入以下代码:


代码如下:

WinSunDlg.cpp

BOOL CWinSunDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog.  The framework does this automatically

//  when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE);                  // Set big icon

SetIcon(m_hIcon, FALSE);          // Set small icon

// TODO: Add extra initialization here

//将对话框的句柄传递到CWinSunApp类中。sunxin

((CWinSunApp*)AfxGetApp())->m_hwndDlg=m_hWnd;

return TRUE;  // return TRUE  unless you set the focus to a control

}

第六步:在对话框窗口销毁后,将CWinSunApp类中的变量m_hwndDlg置为NULL,为此我们在CWinSunDlg类上点击右键,选择Add Windows Message Handler,在左边一栏中选择WM_DESTROY,在右边按钮上选择Add and Edit,然后加入以下代码:


代码如下:

WinSunDlg.cpp

void CWinSunDlg::OnDestroy()

{

CDialog::OnDestroy();

// TODO: Add your message handler code here

((CWinSunApp*)AfxGetApp())->m_hwndDlg=NULL;

}

至此,我们的工作就做完了,现在我们可以按Ctrl+F5运行程序,看到我们想要的结果。

(0)

相关推荐

  • 基于对话框程序中让对话框捕获WM_KEYDOWN消息的实现方法

    在对话框程序中,我们经常是利用对话框上的子控件进行命令响应来处理一些事件.如果我们想要让对话框(子控件的父窗口)类来响应我们的按键消息,我们可以通过ClassWizard对WM_KEYDOWN消息进行响应,当程序运行后,我们按下键盘上的按键,但对话框不会有任何的反应.这是因为在对话框程序中,某些特定的消息,例如按键消息,它们被Windows内部的对话框过程处理了(即在基类中完成了处理,有兴趣的读者可以查看MFC的源代码),或者被发送给子控件进行处理,所以我们在对话框类中就捕获不到按键的消息了.

  • 微信小程序中使用ECharts 异步加载数据的方法

    官网例子都是同步的,怎么引入及同步demo请移步官网 <view class="container"> <ec-canvas id="mychart-dom-multi-bar" canvas-id="mychart-multi-bar" ec="{{ ecBar }}"></ec-canvas> <ec-canvas id="mychart-dom-multi-scatte

  • 小程序中监听页面滚动的几种方法实例

    目录 目录 实现效果 下面是Intersection Observer在MDN上的介绍 IntersectionObserver relativeToViewport 接受参数 Object margins observe(string targetSelector, function callback) 参数 Object res 小程序中监听页面的其他方法 page-meta scroll-view 总结 在工作中我们经常遇到需要监听页面中元素位置,当元素超出显示区域或即将显示到页面上,我们

  • Java程序中添加播放MIDI音乐功能的实现方法详解

    JAVA 在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐,如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了,可是网上很多播放MIDI的教程都是简单的几句话的例子.没有考虑资源的释放问题,如果程序长久运行的话,就会出现内存越耗越多的情况,最后会抛出一个 java.lang.OutOfMemoryError..在MIDI的播放中,一个类是比较重要的,那就是 MidiSystem 类,负责整个MIDI播放设备等的管理,其实就是 Seqencer,它

  • 在小程序中集成redux/immutable/thunk第三方库的方法

    一.前言 小程序给我们暴露了两个参数 require 和 module , require 用来在模块中加载其他模块, module 用来将模块中的方法暴露出去 module.exports = function(){} 所以只要需要让第三方库的代码使用这种形式的 export 就可以了 二.构建Redux的微信小程序包 打一个 Redux 包,让它可以兼容微信小城的加载方式 git clone https://github.com/reactjs/redux.git npm install #

  • 在WinForm应用程序中快速实现多语言的处理的方法

    在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化.在Winform应用程序中实现多语言也有常规的处理方式处理,不过需要针对每个语言版本,重新修改Winform界面的显示,对一些常规的辅助类,也需要引入一个统一的资源管理类来处理多语言的问题,相对比较繁琐.本篇随笔针对多语言的需求,希望尽量避免繁琐的操作,既能符合本地语种开发人员的开发习惯,又能快速实现Winform程序的多语言场景处理. 1.多语言开发的困惑和思路 在常规的多语言版本程序中,开发总是伴随着很多不愉快的事情,

  • iOS应用程序中通过dispatch队列控制线程执行的方法

    GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合block实现的GCD,把函数闭包(Closure)的特性发挥得淋漓尽致. dispatch队列的生成可以有这几种方式: 1. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_

  • 微信小程序中button去除默认的边框实例代码

    微信小程序中button去除默认的边框的实现方法如下所示: button { position:relative; display:block; margin-left:auto; margin-right:auto; padding-left:14px; padding-right:14px; box-sizing:border-box; font-size:18px; text-align:center; text-decoration:none; line-height:2.5555555

  • 在微信小程序中获取用户位置的详细过程

    目录 前言 wx.getLocation 腾讯位置服务 总结 前言 最近在学习微信小程序,在学习的过程中,有很多好玩的 API,经常点外卖的同学可能在小程序中遇到过,比如:某团.某了么都是有显示当前用户位置信息的,那么今天给大家介绍如何获取当前用户位置信息,听上去很不错,其实实践起来也不是很难. wx.getLocation 首先,我们需要来认识一下 wx.getLocation 这个 API 方法,我们先看看 微信官方文档 中是怎么说的 看我划红线的地方就可以了,文档中明确的表示这个 API

  • 基于Bootstrap模态对话框只加载一次 remote 数据的解决方法

    摘要: 前端框架 Bootstrap 的模态对话框,可以使用 remote 选项指定一个 URL,这样对话框在第一次弹出的时候就会自动从这个地址加载数据到 .modal-body 中,但是它只会加载一次,不过通过在事件中调用 removeData() 方法可以解决这个问题. 1. Bootstrap 模态对话框和简单使用 <div id="myModal" class="modal hide fade"> <div class="moda

随机推荐