在VC6中根据向导新建一个对话框程序,把向导生成的OK、Cancel和文本都删除,然后拖三个编辑框控件和一个按钮到界面上。为按钮添加响应函数:
void CNetxeditDlg::OnBtn1() 
{
// TODO: Add your control notification handler code here
MessageBox("Button1");
}
然后再添加一个OnOK函数:
void CNetxeditDlg::OnOK()
{
GetNextDlgTabItem(GetFocus())->SetFocus();
}
运行该程序,于是出现一个奇怪的现象:一运行,焦点停在第一个编辑框中,按回车,焦点会到第二个编辑框,再按回车,焦点到第三个编辑框,再按回车,焦点到了按钮上,再按回车,焦点又到了第一个编辑框中,而不是触发按钮的响应函数。改用按Tab键,焦点也是从第一个编辑框一直到第三个编辑框再到按钮上,此时按回车,按钮的响应函数才执行。请问这是怎么回事啊?两种情况下都是在按钮上有焦点的情况下按回车,可反应却不同?

解决方案 »

  1.   

    问题出现在ONOK上,删除了自带的ONOK后,好像还得自个加个什么东东。
      

  2.   

    你在OnOK中GetNextDlgTabItem(GetFocus())->SetFocus();引起的。回车时执行默认动作OnOK,你用代码把焦点设到了当前焦点控件的下一个控件,所以就出现这种现象了。
    你把你新加的按钮属性设上“default button”,或者edit控件有“multiline”和“want return”属性时就不会默认回车OnOK了。
      

  3.   

    我奇怪的是同样是输入焦点在按钮上,为什么按Tab键,焦点在按钮上时,按回车键会执行按钮的响应函数?或者说当按回车键时焦点从编辑框跳到按钮上,再按回车键,根据这句话:GetNextDlgTabItem(GetFocus())->SetFocus();焦点应该跳到下一个编辑框上。但是当焦点在一个按钮上时也应该执行它的响应函数才对啊。这两者是不是有点矛盾?
      

  4.   

    知道原因就好处理了,回车执行某按钮,是因为该按钮有default button属性,当你切换焦点到你的按钮时,给它设上这个属性就行了。 if(GetFocus()->GetDlgCtrlID() == IDC_BUTTON1)
    {
    CButton* pBtn = (CButton*)GetFocus();
    pBtn->SetButtonStyle(BS_DEFPUSHBUTTON, TRUE);
    }
      

  5.   

    补充,放在GetNextDlgTabItem(GetFocus())->SetFocus();之后
      

  6.   

    i am shuke 答非所问哈这个问题很好解释,按钮的焦点状态有点特殊。
    仔细看一下就会发现,执行LZ的OnOK的处理将焦点移至按钮上时,只出现了虚线框。
    (如果没用鼠标点过按钮,甚至虚线框也不会出现。)
    而使用Tab键将焦点移至按钮上时,不仅出现了虚线框,还出现了粗边框(不同主题下效果不同)。
    猜测此时按钮被赋予了临时的“缺省”属性,此时回车键只会识别这个按钮。你可以看看 COccManager::IsDialogMessage() 的实现
    (...\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\occdlg.cpp)
      

  7.   


    看我在5楼的答复,粗线就是因为有BS_DEFPUSHBUTTON属性。
      

  8.   

    windsonzhl你说的太对了,原来还没看出来这细小的差别,的确当用Tab键将焦点移到按钮上时有黑边框。To iamshuke:我在OnOK中实现回车自动调整控件焦点,按钮也没有default button属性,其实程序并不重要,我只是想探讨两者的区别和原因在哪里。一种是:按Tab键将焦点移到按钮上,然后按回车,程序响应了按钮的消息函数;另一种是按回车使焦点移到按钮上,此时再按回车,没有执行按钮的消息函数而是继续将焦点移到。看起来都是焦点到了按钮上,为什么两者不同,我想知道为什么会这样?原因在哪里?
      

  9.   


    有黑边框就是因为按钮有default button属性,有该属性时回车才能执行该按钮的动作。
    按tab切换焦点时,windows不单setfocus,对按钮还SetButtonStyle(BS_DEFPUSHBUTTON, TRUE);了,而你的代码中没有调用该代码。按5楼说的加上这段设置按钮属性的代码就行了。
      

  10.   

    还是看MSDN上的方案吧,原文就不贴了,搜Q92905。如果获得焦点的控件是push button,需要把黑边框从其它push button中去掉,并加到当前push button中。方法如下:1. 发送一个WM_GETDLGCODE消息。
    2. 如果返回值是DLGC_DEFPUSHBUTTON,就给这个有黑边框的按钮发送BM_SETSTYLE消息,用BS_PUSHBUTTON当wParam,这样就能去掉黑边框。
    3. 发送BM_SETSTYLE消息给当前获得焦点的push button,用BS_DEFPUSHBUTTON当作wParam参数,使其拥有黑边框。例程:case WM_KEYDOWN:            // Check for keys that need this processing such as the
                // TAB and arrow keys.
                if ( (wParam == VK_TAB)   ||
                     (wParam == VK_DOWN)  || (wParam == VK_UP) ||
                     (wParam == VK_RIGHT) || (wParam == VK_LEFT) )
                   {
                   // Set the focus to the first control, Button #1
                   // in this case.
                   hwndBtn1 = GetDlgItem(hParentDlg,IDBUTTON1);
                   SetFocus(hwndBtn1);               // Loop through all the controls and remove the
                   // dark border that the previous default push
                   // button has.
                   hwndCtrls = GetWindow(hParentDlg, GW_CHILD);
                   while (hwndCtrls)
                       {
                       wRet = (WORD)(DWORD)SendMessage(hwndCtrls,
                                               WM_GETDLGCODE, 0, 0L);                  if (wRet & DLGC_DEFPUSHBUTTON)
                        SendMessage(hwndCtrls, BM_SETSTYLE,
                                   (WPARAM)BS_PUSHBUTTON, TRUE);                  hwndCtrls = GetWindow(hwndCtrls, GW_HWNDNEXT);
                      }              // Give the hwndBtn1 button the default push button
                  // border.
                   SendMessage(hwndBtn1,  BM_SETSTYLE,
                               (WPARAM)BS_DEFPUSHBUTTON, TRUE);               return(0L);
                   }            break; 
      

  11.   

    To iamshuke:
    老兄,你别太固执了哈,建议你在Windows Xp的默认主题或经典主题下试试,
    任何按钮在真正获得焦点(Tab键走位或鼠标点击)后,都是带黑边框的。
      

  12.   

    我目前正用到让按钮显示位图,但是点击按钮之后出现的黑边框很碍眼,
    所以我就想能不能把那个黑边框去掉,所以专门研究过按钮状态问题。CButton::GetState()
    MSDN对这个函数的说明中,给出了按钮的3个状态值:0x0003(check)、
    0x0004(hilight) 和 0x0008(focus)。但是经实验发现,按钮在
    获得焦点后的状态值为 0x0208,也就是说出现了一个值为0x0200的
    未知状态(黑边框状态)。PS:CButton这个类适用于Button、Radio和CheckBox。
      

  13.   


    首先明确一下,回车键执行OnOK是对话框的缺省处理,与有无IDOK按钮无关。
    但当存在带DEFPUSHBUTTON的按钮时,对话框PreTranslateMessage处理回车键
    时会取这个按钮(如果有多个则取Tab走位顺序最靠前的)。LZ在9L的问题,目前查不到任何资料,看来只能去问微软了。
    SetFocus方法对按钮不适用,一定要编码更改按钮焦点的话,只能是调一下
    IsDialogMessage,例:MSG msg = {0};
    msg.hwnd = ::GetFocus();
    msg.message = WM_KEYDOWN;
    msg.wParam = VK_TAB;
    IsDialogMessage(&msg);※注:这段代码如果要在ON_BN_CLICKED消息响应中用,不能直接用,
    要触发一个定时器,在OnTimer中使用这段代码。
      

  14.   


    我晕,我的回复你确认看了吗?我怎么感觉是在对空气说话呢?!MSDN中的示例代码都贴上了,都被你无视了。
    提供两个关键字,BS_DEFPUSHBUTTON、DLGC_DEFPUSHBUTTON,别的不多说了,这个主题我也不会再回复了。