关于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都没反应,空格却有反应呢?
特此到论坛求助,欢迎回答,先说谢谢!!!
...全文
825 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)
WINAPI,WinAPI手册,最全的WINAPI函数手册,WINAPI开发必备 目录 1 内容简介 14 前言 14 第一章 Win32 API概论 14 为什么使用 Wiu32 API 14 Win32 API 简介 15 第二章 窗口管理函数 16 第一节 易用特性函数(Accessibility Features) 20 SoundSentryProc 20 SystemParametersinfo 21 第二节 按钮函数(Button) 34 CheckDlgButton 34 CheckRadioButton 34 IsDlgButtonChecked 35 第三节 插入标记(^)函数(Caret) 36 CreateCaret 36 DestroyCaret 37 GetCaretBlinkTime 37 GetCaretPos 38 HideCaret 38 SetCaretBlinkTime 39 SetCaretPos 39 ShowCaret 40 第四节 组合框函数(Combo box) 40 CCHookProc 40 CFHookProc 42 ChooseColor 43 ChooseFont 44 CommDlgExtendedEorror 45 DlgDirListComboBox 47 DlgDirSelectEx 49 DlgDirSelectComboBoxEx 50 FindText 50 FRHookProc 51 GetFileTitle 52 GetOpenFileName 53 GetSaveFileName 54 OFNGookProc 54 OFNHookProcOldStyle 56 PagePaintHook 57 PageSetupDlg 58 pageSetupHook 58 PrintDlg 59 PrintdlgEx 60 PrintHookProc 61 ReplaceText 62 SetupHookProc 63 第五节 标函数(Cursor) 64 ClipCursor 64 CopyCursor 65 CreateCursor 65 DestroyCursor 66 GetClipCursor 67 GetCursor 67 GetCursorpos 67 LoadCursorFromFile 68 SetCursor 68 SetCursorPos 69 SetSystemCursor 69 ShowCursor 70 LoadCursor 71 第六节 对话框函数(Dialog Box) 72 CreateDialog 72 CreateDialoglndirect 73 CreateDialoglndirectParam 74 CreateDialogParam 76 DefDlgProc 77 DialogBox 78 DialogBoxlndirect 79 DialogBoxlndirectParam 80 DialogBoxParam 81 DialogProc 82 EndDialog 83 GetDialogBaseUnits 83 GetDigCtrllD 84 GetDigltem 85 GetDlgltemlnt 85 GetDlgltemText 86 GetNextDlgGroupltem 87 GetNexTDlgTabltem 88 IsDialogMessage 88 MapDialogRect 89 MessageBox 90 MessageBoxEx 93 SendDlgltemMessage 94 SetDlgltemlnt 95 SetDlgltemText 95 MessageBoxlndirect 96 第七节 编辑控制函数(Edit Control) 97 EditWordBreakproc 97 第八节 图标函数(Icon) 98 Copylcon 98 Createlcon 99 CreatelconFromResource 100 CreatelconFromResourceEx 101 Destroylcon 102 Create_cpm_mdorect_ZIWe 102 Drawlcon 103 DrawlconEx 104 ExtractAssociatedlcon 105 Extractlcon 106 ExtractlconEx 106 Getlconlnfo 107 LookuplconldFromDirectory 108 LookuplconldFrom 109 Loadlcon 110 第九节 键盘加速器函数(Keyboard Accelerator) 110 CopyAcceleratorTable 111 CreateAcceleratorTable 111 DestroyAcceleratorTable 112 LoadAccelerators 112 TranslateAccelerator 113 第十节 键盘输入函数(Keyboard Input) 114 ActivateKeyboadLayout 114 EnableWindow 115 GetActiveWindows 116 GetAsyncKeyState 116 GetFocus 117 GetKBCodePage 118 GetKeyboardLayout 118 GetKeyboardLayoutList 118 GetKeyboardLayoutName 119 GetKeyboardState 119 GetKeyNameText 120 GetKeyState 121 IsWindowEnabled 122 keybd_event 122 LoadKeyboardLayout 123 MapVirtualKey 124 MapVlrtualKeyEx 126 OemKeyScan 126 RegisterHotKey 127 SetActiveWindow 128 SetFocus 129 SetKeyboardState 130 ToAscii 130 ToAsciiCxToAsciiCx 131 ToUnicode 132 ToUnicodeEx 133 UnloadKeyboardL 134 UnreglsterHotKey 134 VkKeyScan 135 vkKeyScanEx 136 第十一节 列表框函数(List boX) 136 DlgDirList 136 DlgDirSelectEx(2) 137 第十二节 菜单函数(Menu) 138 CheckMenuRadlol 138 CreateMenu 139 CreatePopupMenu 140 DeleteMenu 140 DestroyMenu 141 DrawMenuBar 141 EnableMenultem 142 GetMenu 143 GetMenuDefaultltem 143 GetMenultemlD 144 GetMenultemlnfo 144 GetMenultemRect 145 getSubMenu 145 GetSystemMenu 146 HlllteMenultem 147 InsertMenultem 147 IsMenu 148 LoadMenu 149 LoadMenulndirect 149 MenultemFromPo 150 RemoveMenu 150 SetMenu 151 SetMenuDefaultltem 151 SetMenultemBitm 152 SetMenultemlnfo 153 TrackPopupMenu 154 TrackPopupMenuEx 155 AppendMenu 156 CheckMenultem 159 GetMenuCheckMarkDimensions 159 GetMenuState 160 GetMenuString 161 InsertMenu 161 ModifyMenu 163 第十三节 消息和消息总队列函数Message and Message Queue) 165 BroadcastSystemMessage 165 DispatchMessage 166 GetlnputState 167 GetMessage 167 GetMessageExtralnfo 168 GetMessagePos 168 GetMessageTime 169 GetQueueStatus 170 InSendMessage 171 InSendMessageEx 171 PeekMessage 172 PostMessage 173 PostQuitMessage 174 PostThreadMessage 175 RegisterWindowsMessage 176 ReplyMessage 176 SendAsyncProc 177 SendMessage 178 SendMessageCallback 178 SendMessageTImeout 179 SendNotifyMessage 181 SendMessageExtralnfo 181 TranslateMessage 182 WaltMessage 183 PostAppMessage 183 SetMessageQueue 183 第十四节 鼠标输入函数(Mouse Input) 183 DragDetect 183 GetCapture 184 GetDoubleCllckTime 184 GetMouseMovePoints 185 mouse_event 186 ReleaseCapture 188 SetCapture 188 SetDoubleCllckTime 189 SwapMouseButton 189 TrackMouseEvent 190 第十五节 多文档接口函数(Multiple Document Interface) 191 CreateMDIWindow 191 DefFrameProc 192 DefMDIChildProc 193 TranslateMdISysAccel 194 第十六节 资源函数(Resource) 195 BeginUpdateResource 195 CopyImage 195 EndUpdateResource 197 EnumResLangProc 197 EnumResNameProc 198 EnumResourceLanguages 199 EnumResourceNames 200 EnumResourceTypes 200 EnumResTypeProc 201 FlndResource 202 FindResourceEx 203 LoadImage 204 LoadResource 206 LockResource 207 SlzeofResource 207 UpdateResource 208 FreeResource 209 UnlockResource 209 第十七节 滚动条函数(Scroll Bar) 209 EnableScrollBar 209 GetScrolllnfo 210 ScrollDC 211 ScrollWindowEx 212 SetScrolllnfo 214 ShowScrollBar 215 GetScrollPos 215 GetScrollRange 216 ScrollWindow 217 SetScrollPos 218 SetScrollRange 219 第十八节 窗口函数(Window) 220 AdlustWindowRect 220 AdjustWindowRectEx 221 AnImateWindow 222 ArrangelconlcWindows 223 BeginDeferWindowPos 223 BromgWindowToTop 224 CascadeWindows 225 ChildWindowFromaPoint 225 ChildWindowFromaPointEx 226 CloseWindow 227 Create Window 227 CreateWindowEx 233 DeferWindowPos 235 DestroyWindow 238 EnableWindow 238 EndDeferWindowPos 239 EnumChildProc 240 EnumTreadWindows 240 EnumThreadWndProc 241 EnumWindows 241 EnumWindowsProc 242 FindWindow 243 FlndWindowEx 243 GetClientRect 244 GetDesktopWindow 244 GetForegroundWindow 245 GetLastActivePopup 245 GetNextWindow 246 GetParent 246 GetTopWindow 247 GetWindow 247 GetWindowPlacement 248 GetWindowRect 249 GetWindowText 249 IsChild 250 GetWindowTextLength 251 GetWlndowThreadprocessld 251 IsIconic 252 IsWindow 252 IsWindowUnicode 253 IsWindowVlslble 253 IsZoomed 254 MoveWindow 254 Openlcon 255 SetForegroundWindow 255 SetParent 256 SetWindowLong 256 SetWindowPlacement 259 SetWindowPos 260 SetWindowText 263 ShowOwnedPopups 263 ShowWindow 264 ShowWindowAsync 265 TileWindows 266 WindowFromPoint 267 WinMain 267 AnyPopup 269 EnumTaskWindows 269 GetSysModalWindow 269 GetWindowTask 269 SetSysModalWindow 269 第十九节 窗口类函数(Window Class) 270 GetClasslnfoEx 270 GetClassLong 270 GetClassName 271 GetWindowLong 272 RegisterClassEx 273 SetClassLong 274 SetWindowLong 275 GetClasslnfoEx 278 GetClassWord 279 GetWindowWord 279 RegisterClass 279 SetClassWord 280 SetWindowWord 281 第二十节 窗口过程函数(Window Procedure) 281 CallWindowProc 281 DefWindowProc 282 WindowProc 283 第二十一节 窗口属性函数(Window Property) 284 EnumProps 284 EnumPropsEx 284 GetProp 285 PropEnumProcEx 285 RemoveProp 286 SetProp 287

16,548

社区成员

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

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

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