关于IsDialogMessage函数的一点疑问,好久没来了,顺便散分。。。

yiruirui0507 2011-02-19 12:55:52
当程序中出现非模态对话框的时候,消息循环必须写成
[code=C]while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hDlg1,&msg))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//}
}
}

return msg.wParam;
}

[/code]
查了MSDN,知道了:
when isdialogmessage processes a message,it checks for keyboard message and converts them into selections for
the corresponding dialog box.
IsDialogMessage是检查对话框上的键盘消息的,我测试了一下:
在键盘上放置3个按钮,OK,BUTTON1,BUTTON2,缺省按钮是OK,三个按钮都有制表符TAB,运行的时候测试结果汇报如下:
当按下键盘上的TAB键焦点会在三个按钮之间进行切换,按下回车或者空格就会触发OK按钮(缺省按钮嘛)来关闭对话框。

当把IsDialogMessage注释掉之后,测试汇报:
此时运行默认焦点还是在OK上(缺省按钮),当按下TAB键时没有任何反应(证明了此函数确实是管理对话框的按键消息的)
当按下回车的时候也没有任何反应,但是,但是,特此强调的是:当按下空格键的时候,会触发消息关闭对话框。

问题来了:既然IsDialogMessage是管理键盘消息的,那按下空格跟按下回车,TAB不都是按键消息(WM_KEYDOWN)吗,为何,回车,TAB都没反应,空格却有反应呢?
特此到论坛求助,欢迎回答,先说谢谢!!!
...全文
824 38 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
yiruirui0507 2012-06-04
  • 打赏
  • 举报
回复
http://hi.baidu.com/zouhaifeng2008/blog/item/b1f55bcb159348f952664f19.html
万里鲲 2012-05-12
  • 打赏
  • 举报
回复
对话框
万里鲲 2012-05-12
  • 打赏
  • 举报
回复
请问下,如何响应键盘消息呢?
yiruirui0507 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 lactoferrin 的回复:]
ISDIALOGMESSAGE并不会判断消息是不是对话框消息,只是根据控件对WM_GETDLGCODE的回答判断是否自己来处理按键消息,如果这个消息有个控件通过WM_GETDLGCODE告诉ISDIALOGMESSAGE自己要处理消息,ISDIALOGMESSAGE就不会自作主张
[/Quote]

感谢你的分析,根据你的分析让我多了解了一些关于IsDialogMessage跟wm_getdlgcode消息。
看了你的分析,是这样理解吧:
首先执行IsDialogMessage函数,此函数会发送WM_GetDlgCode消息给对话框上的每个控件,来看是否这个控件自己处理这个消息,如果这个控件自己要处理这个消息那么IsDialogMessage就放行通过,如果不处理那么WINDOWS就执行默认处理对吧。
我测试了一下:
测试代码:
while (GetMessage(&msg, NULL, 0, 0))
{
int a=0;
char buf[10];
a=IsDialogMessage(hDlg1,&msg);
if(a==1)
{
itoa(a,buf,10);
MessageBox(NULL,buf,TEXT("WOCAO"),0);
}
//if (!IsDialogMessage(hDlg1,&msg))
//{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//}
}

return msg.wParam;
}
把IsDialogMessage的返回值赋给变量a,如果a==1,表示这个消息是对话框消息(也就是说对话框上没有控件要处理此消息)如果a==0,表示这个消息不是对话框消息(表示对话框上的某个有焦点的控件自己要处理这个消息对吧)
继续:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
。。。。。。。。。。。
case IDM_ABOUT:
hDlg1=CreateDialog(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
此处建了一个非模态对话框,回调函数是About
继续:
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{HWND hwnd=GetDlgItem(hDlg,IDOK);
pSubclassOldEditProc=(WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(LONG)BTNWNDPROC);
return TRUE;}
。。。。。。。
我在此对话框的初始化消息中修改了OK按钮的窗口过程函数地址,新的窗口过程函数名字为:BTNWNDPROC
继续:
LRESULT CALLBACK BTNWNDPROC(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_KEYDOWN:
case WM_KEYUP:
switch(wParam)
{
case VK_RETURN:
case VK_SPACE:
MessageBox(hwnd,TEXT("XX"),TEXT("YY"),0);
break;
case VK_TAB:
MessageBox(hwnd,TEXT("TAB"),TEXT("TAB"),0);
}
return 0;
}
return CallWindowProc(pSubclassOldEditProc,hwnd,message,wParam,lParam);
}
我改变了这个OK按钮的窗口过程函数,在里面自己处理了回车,空格,TAB键消息。
到此测试完毕:
回头分析:
根据你前面说的IsDialogMessage会发送WM_GETDLGCODE消息判断是否控件自己处理这个消息,如果控件自己处理了,他就不拦截了对吧。
运行程序,默认OK按钮有焦点,此时我按下TAB键,会执行
a=IsDialogMessage(hDlg1,&msg);
if(a==1)
{
itoa(a,buf,10);
MessageBox(NULL,buf,TEXT("WOCAO"),0);
}
此时判断的结果是:这个TAB键被OK按钮自己进行了处理,IsDialogMessage就不处理了,因此应该返回a=0才对吧,但是我运行发现输出的a=1,这里咋么理解?莫非哪里又没理解对?请解释,如果不好交流可以联系我的QQ:1071545795,这样方便发送工程给你测试。
gfm688 2011-02-20
  • 打赏
  • 举报
回复
[Quote]
When IsDialogMessage processes a message, it checks for keyboard messages and converts them into selections for the corresponding dialog box. For example, the TAB key, when pressed, selects the next control or group of controls, and the DOWN ARROW key, when pressed, selects the next control in a group.
[/Quote]

MSDN都说IsDialogMessage处理TAB键了,当然是返回1了,怎么你还说TAB键被OK按钮自己进行了处理
yiruirui0507 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 lactoferrin 的回复:]
DialogBoxParam等函数会将主窗口禁用
然后内部有像while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hDlg1,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
//}
}
}

r……
[/Quote]
OK,比较感谢,差不多可以结贴了。
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
DialogBoxParam等函数会将主窗口禁用
然后内部有像while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hDlg1,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
//}
}
}

return msg.wParam;
} 这样的消息循环,都是差不多的
yiruirui0507 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 lactoferrin 的回复:]
返回DLGC_WANTTAB9不是说这不是对话框消息,而是指这个消息不需要IsDialogMessage特殊处理
一般情况下给对话框控件的都是对话框消息,IsDialogMessage内部也有
TranslateMessage(&msg);
DispatchMessage(&msg);
来分发消息
[/Quote]

多谢,对了,顺便说下用dialogbox创建的模态对话框是如何处理的呢?是不是它内部全部都处理好了?
模态对话框的消息跟非模态对话框的消息处理有什么区别吗,这个我也知道一点,不是很清楚,麻烦你在这里说说吧。
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
返回DLGC_WANTTAB9不是说这不是对话框消息,而是指这个消息不需要IsDialogMessage特殊处理
一般情况下给对话框控件的都是对话框消息,IsDialogMessage内部也有
TranslateMessage(&msg);
DispatchMessage(&msg);
来分发消息
yiruirui0507 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 lactoferrin 的回复:]
IsDialogMessage不会向所有控件发送WM_GETDLGCODE,只是向有可能会处理IsDialogMesage第二参数指定的消息的控件发送WM_GETDLGCODE,这样的控件通常是那个消息的目标的目的窗口,如果是按键消息,目的窗口就是焦点窗口
[/Quote]
哦,写在控件的消息处理程序中,我写在对话框中是因为MSDN中有句话是这么说的。
IsDialogMessage sends WM_GETDLGCODE messages to the dialog box procedure to determine which keys should be processed
经过测试确实是应该写在控件的窗口过程函数中。
我说一下IsDialogMessage的返回值情况你看对吗

比如这里我在BTNWNDPROC中写入了WM_getdlgcode,并且返回了DLGC_WANTTAB9(也就是2)表示我这个控件自己会处理这个按键消息,不需要您对话框操心,因此这个消息就不在属于对话框消息了,即:IsDialogMessage返回0。分析的没错吧。
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 hai72 的回复:]
你学MFC多长时间了!我现在正在学WINDOWS编程和网络编程,可以交流一下!
[/Quote]
你对谁说话?我很少用MFC,我都是直接用api的,MFC把本来很清楚的事情搞麻烦
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
怎么又有错,如果是按键消息,目的窗口一般都是是焦点窗口,除非是用PostMessage向不是焦点窗口发的
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
IsDialogMessage不会向所有控件发送WM_GETDLGCODE,只是向有可能会处理IsDialogMesage第二参数指定的消息的控件发送WM_GETDLGCODE,这样的控件通常是那个消息的目标的目的窗口,如果是按键消息,目的窗口就是焦点窗口
yaoyao_cn 2011-02-20
  • 打赏
  • 举报
回复
你学MFC多长时间了!我现在正在学WINDOWS编程和网络编程,可以交流一下!
Lactoferrin 2011-02-20
  • 打赏
  • 举报
回复
你要在BTNWNDPROC中处理WM_GETDLGCODE
case WM_GETDLGCODE:
OutputDebugStringA("aaa");
return 2;这里2代表我要处理tab键
这样如果焦点在IDOK,你按tab就不会有切换控件的功能,因为可能处理消息的控件说自己要处理这个消息

IsDialogMessage不会像所有控件发送WM_GETDLGCODE,只是向有可能会处理消息(IsDialogMesage第二参数指定的)控件发送WM_GETDLGCODE,这样的控件通常是焦点窗口
yiruirui0507 2011-02-20
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 gfm688 的回复:]
引用
When IsDialogMessage processes a message, it checks for keyboard messages and converts them into selections for the corresponding dialog box. For example, the TAB key, when pressed, selects the ne……
[/Quote]
汗,你就没看清楚MSDN咋么说的,你先看看WM_GETDLGCODE消息介绍吧。
yiruirui0507 2011-02-19
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 lactoferrin 的回复:]
消息发送的是不是ISDIALOGMESSAGE中指定的对话框的控件是很好判断的,只需要比较控件的父窗口就行了
[/Quote]
恩,应该是这样判断一个消息是否属于对话框消息的:接收到了一个键盘消息,然后看看当前有焦点的控件是否是此对话框的子窗口即可。
Lactoferrin 2011-02-19
  • 打赏
  • 举报
回复
消息发送的是不是ISDIALOGMESSAGE中指定的对话框的控件是很好判断的,只需要比较控件的父窗口就行了
Lactoferrin 2011-02-19
  • 打赏
  • 举报
回复
ISDIALOGMESSAGE并不会判断消息是不是对话框消息,只是根据控件对WM_GETDLGCODE的回答判断是否自己来处理按键消息,如果这个消息有个控件通过WM_GETDLGCODE告诉ISDIALOGMESSAGE自己要处理消息,ISDIALOGMESSAGE就不会自作主张
yiruirui0507 2011-02-19
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 lactoferrin 的回复:]
消息分发就是把根据窗口把消息给窗口过程(call它)
消息有两种,一种是队列消息,一种是非队列消息
PostMessage,按键,产生队列消息,SendMessage,CreateWindow产生非队列消息
GetMessage在执行的过程中,会分发所有的非队列消息(调用对应的窗口过程),处理完非队列消息后,如果还有队列消息,就根据队列的顺序取出一个返回,否则继续等消息

队列消息一般会……
[/Quote]
感谢回答,
仍然有个问题:
ISDIALOGMESSAGE是判断一个消息是否是对话框消息的
换句话说:如何判断一个消息是否是对话框消息?
按下一个TAB键盘,会触发WM_KEYDOWN,这个WM_KEYDOWN消息应该是当前拥有焦点的控件的才对吧,也就是说这个消息根本不是对话框的消息,即:ISDIALOGMESSAGE没有拦截到此消息,因为当前有焦点的不是对话框,而是对话框上的控件。不知道我这么理解对不对?
我的意思是:WM_KEYDOWN不也可以是某个对话框上的控件上触发的吗,为何就说是对话框消息?
这点不明白
加载更多回复(17)

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧