当程序中出现非模态对话框的时候,消息循环必须写成
while (GetMessage(&msg, NULL, 0, 0)) 
{
if (!IsDialogMessage(hDlg1,&msg))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//}
}
} return msg.wParam;
}
查了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都没反应,空格却有反应呢?
特此到论坛求助,欢迎回答,先说谢谢!!!

解决方案 »

  1.   

    备注:尽管IsDialogMessage函数是为无模态对话框而扩展的,但可以用含有控制的任何一个窗口来使用它。当 IsDialogMessage处理一个消息时,它检测键盘信息并把它们转变成对响应对话框的选择命令。例如当按下tab时选择下一个控制或控制组,当按下down时选择控制组的下一个控制。
      

  2.   

    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. 
      

  3.   


    感谢回答,貌似跟我的问题对不上吧,还请仔细看下我的问题。
    我在对话框的窗口过程函数中加入了
    LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch (message)
    {
    case WM_INITDIALOG:
    return TRUE; case WM_COMMAND:
    if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
    {
    DestroyWindow(hDlg1);
    return TRUE;
    }
    break;
    case WM_KEYDOWN:
    MessageBox(hDlg,TEXT("A"),TEXT("B"),0);
    return 0;
    case WM_CLOSE:
    DestroyWindow(hDlg1);
    hDlg1=0;
    return TRUE;
    }
        return FALSE;
    }case WM_KEYDOWN:测试这个消息压根就没响应,这到底是咋么回事呢?
    那TAB键的消息不也是WM_KEYDOWN吗?咋么。。望指点
      

  4.   

    按那个意思就是tab,上,下,左右的键都不会响应了,如果不响应的话,那WM_KEYDOWN,keyup也不会响应了,当然我这没那环境,测试不了,你看下其它键在这个时候是否响应WM_KEYDOWN
      

  5.   


    你测试这个时有没有IsDialogMessage
      

  6.   


    你空格咋么还会响应?按下空格不也属于WM_KEYDOWN吗?如何解释?
      

  7.   


    有根没有两个情况都测试了,都没响应WM_KEYDOWN消息。
    莫非对话框就不响应WM_KEYDOWN消息?只响应WM_COMMAND消息。
      

  8.   

    貌似在Windows程序设计里面对话框一章有讲到。记不太清了,回家研究下~
      

  9.   

    通常dlg不处理“WM_KEYDOWN”他需要translate后的键如TAB。
      

  10.   

    至于“空格”对话框把他看作“OK”,你可以在OK中大个断点看看。
      

  11.   

    原因应该是这个,你在按键时,焦点窗口不是对话框,而是上面的控件,所以你按键对话框的窗口过程是不会收到WM_KEYDOWN的,但你按tab有用是因为IsDialogMessage作了转换,按空格能关闭是因为焦点是按钮,它的窗口过程处理了消息
      

  12.   

    按键时窗口焦点不是对话框,而是上面的控件,因此对话框的窗口过程是不会响应WM_KEYDOWN的,这句能理解。此时的分析是否是这样:按键时比如按下TAB,此时接收这个按键的应该是当前获得焦点的窗口才对吧,也就是OK按钮,然而这里的这个消息却被ISDIALOGMESSAGE给拦截并转换了?ISDIALOGMESSAGE是判断一个消息是否是对话框消息的,这里的按下TAB键消息是对话框消息?换句话说:如何判断一个消息是否是对话框消息?
    迷迷糊糊的,没理解明白这个过程。
      

  13.   

    感觉你的这句话有点矛盾吧,对话框不处理WM_KEYDOWN也就是说不处理按键消息,你又说需要翻译后的TAB,
    翻译后的TAB不也是按键消息吗,连WM_KEYDOWN都不处理了,那肯定对TAB也没用了啊,WM_KEYDOWN包含TAB键的。请问如何解释。
      

  14.   

    首先要知道键盘消息属于队列消息,因此不会在GetMessage中被分发,而是从GetMessage返回,
    所以如果你按了tab
    在WM_KEYDOWN到达控件的窗口过程前,ISDIALOGMESSAGE有机会处理它
    IsDialogMessage会像对话框的可能接受这个WM_KEYDOWN控件发送WM_GETDLGCODE消息来知道这些控件是否需要处理tab如果没有控件处理tab,则tab可以被用作选择控件的按键,IsDialogMessage就会改变焦点窗口
      

  15.   

    你说的键盘消息属于队列消息,不会在GetMessage中被分发,而是从GetMessage返回
    这句话是什么意思,求解释,消息分发第一次听说,谢谢。
      

  16.   

    消息分发就是把根据窗口把消息给窗口过程(call它)
    消息有两种,一种是队列消息,一种是非队列消息
    PostMessage,按键,产生队列消息,SendMessage,CreateWindow产生非队列消息
    GetMessage在执行的过程中,会分发所有的非队列消息(调用对应的窗口过程),处理完非队列消息后,如果还有队列消息,就根据队列的顺序取出一个返回,否则继续等消息队列消息一般会由TranslateMessage转换,然后由DispatchMessage分发至窗口过程IsDialogMessage处理的是队列消息,只有队列消息才能被GetMessage和PeekMessage取回
      

  17.   

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

  18.   

    ISDIALOGMESSAGE并不会判断消息是不是对话框消息,只是根据控件对WM_GETDLGCODE的回答判断是否自己来处理按键消息,如果这个消息有个控件通过WM_GETDLGCODE告诉ISDIALOGMESSAGE自己要处理消息,ISDIALOGMESSAGE就不会自作主张
      

  19.   

    消息发送的是不是ISDIALOGMESSAGE中指定的对话框的控件是很好判断的,只需要比较控件的父窗口就行了
      

  20.   


    MSDN都说IsDialogMessage处理TAB键了,当然是返回1了,怎么你还说TAB键被OK按钮自己进行了处理
      

  21.   

    汗,你就没看清楚MSDN咋么说的,你先看看WM_GETDLGCODE消息介绍吧。
      

  22.   

    你要在BTNWNDPROC中处理WM_GETDLGCODE
    case WM_GETDLGCODE:
    OutputDebugStringA("aaa");
    return 2;这里2代表我要处理tab键
    这样如果焦点在IDOK,你按tab就不会有切换控件的功能,因为可能处理消息的控件说自己要处理这个消息IsDialogMessage不会像所有控件发送WM_GETDLGCODE,只是向有可能会处理消息(IsDialogMesage第二参数指定的)控件发送WM_GETDLGCODE,这样的控件通常是焦点窗口
      

  23.   

    你学MFC多长时间了!我现在正在学WINDOWS编程和网络编程,可以交流一下!
      

  24.   

    IsDialogMessage不会向所有控件发送WM_GETDLGCODE,只是向有可能会处理IsDialogMesage第二参数指定的消息的控件发送WM_GETDLGCODE,这样的控件通常是那个消息的目标的目的窗口,如果是按键消息,目的窗口就是焦点窗口
      

  25.   

    怎么又有错,如果是按键消息,目的窗口一般都是是焦点窗口,除非是用PostMessage向不是焦点窗口发的
      

  26.   

    你对谁说话?我很少用MFC,我都是直接用api的,MFC把本来很清楚的事情搞麻烦
      

  27.   

    哦,写在控件的消息处理程序中,我写在对话框中是因为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。分析的没错吧。
      

  28.   

    返回DLGC_WANTTAB9不是说这不是对话框消息,而是指这个消息不需要IsDialogMessage特殊处理
    一般情况下给对话框控件的都是对话框消息,IsDialogMessage内部也有
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
    来分发消息
      

  29.   


    多谢,对了,顺便说下用dialogbox创建的模态对话框是如何处理的呢?是不是它内部全部都处理好了?
    模态对话框的消息跟非模态对话框的消息处理有什么区别吗,这个我也知道一点,不是很清楚,麻烦你在这里说说吧。
      

  30.   

    DialogBoxParam等函数会将主窗口禁用
    然后内部有像while (GetMessage(&msg, NULL, 0, 0)) 

    if (!IsDialogMessage(hDlg1,&msg)) 

    TranslateMessage(&msg); 
    DispatchMessage(&msg);  
    //} 

    } return msg.wParam; 
    } 这样的消息循环,都是差不多的
      

  31.   

    http://hi.baidu.com/zouhaifeng2008/blog/item/b1f55bcb159348f952664f19.html