一个奇怪的现象,请各位老大指点

testpwd 2010-08-25 03:56:55
在VC6中根据向导新建一个对话框程序,把向导生成的OK、Cancel和文本都删除,然后拖三个编辑框控件和一个

按钮到界面上。为按钮添加响应函数:


void CNetxeditDlg::OnBtn1()
{
// TODO: Add your control notification handler code here
MessageBox("Button1");
}


然后再添加一个OnOK函数:


void CNetxeditDlg::OnOK()
{
GetNextDlgTabItem(GetFocus())->SetFocus();
}


运行该程序,于是出现一个奇怪的现象:一运行,焦点停在第一个编辑框中,按回车,焦点会到第二个编辑框,再按回车,

焦点到第三个编辑框,再按回车,焦点到了按钮上,再按回车,焦点又到了第一个编辑框中,而不是触发按钮的响应函数。

改用按Tab键,焦点也是从第一个编辑框一直到第三个编辑框再到按钮上,此时按回车,按钮的响应函数才执行。

请问这是怎么回事啊?两种情况下都是在按钮上有焦点的情况下按回车,可反应却不同?
...全文
165 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamshuke 2010-08-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 windsonzhl 的回复:]
To iamshuke:
老兄,你别太固执了哈,建议你在Windows Xp的默认主题或经典主题下试试,
任何按钮在真正获得焦点(Tab键走位或鼠标点击)后,都是带黑边框的。
[/Quote]

我晕,我的回复你确认看了吗?我怎么感觉是在对空气说话呢?!MSDN中的示例代码都贴上了,都被你无视了。
提供两个关键字,BS_DEFPUSHBUTTON、DLGC_DEFPUSHBUTTON,别的不多说了,这个主题我也不会再回复了。
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 testpwd 的回复:]
看起来都是焦点到了按钮上,为什么两者不同,我想知道为什么会这样?原因在哪里?
[/Quote]

首先明确一下,回车键执行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中使用这段代码。
  • 打赏
  • 举报
回复
我目前正用到让按钮显示位图,但是点击按钮之后出现的黑边框很碍眼,
所以我就想能不能把那个黑边框去掉,所以专门研究过按钮状态问题。

CButton::GetState()
MSDN对这个函数的说明中,给出了按钮的3个状态值:0x0003(check)、
0x0004(hilight) 和 0x0008(focus)。但是经实验发现,按钮在
获得焦点后的状态值为 0x0208,也就是说出现了一个值为0x0200的
未知状态(黑边框状态)。

PS:CButton这个类适用于Button、Radio和CheckBox。
  • 打赏
  • 举报
回复
To iamshuke:
老兄,你别太固执了哈,建议你在Windows Xp的默认主题或经典主题下试试,
任何按钮在真正获得焦点(Tab键走位或鼠标点击)后,都是带黑边框的。
iamshuke 2010-08-26
  • 打赏
  • 举报
回复
还是看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;

iamshuke 2010-08-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 testpwd 的回复:]
windsonzhl你说的太对了,原来还没看出来这细小的差别,的确当用Tab键将焦点移到按钮上时有黑边框。

To iamshuke:我在OnOK中实现回车自动调整控件焦点,按钮也没有default button属性,其实程序并不重要,我只是想探讨两者的区别和原因在哪里。

一种是:按Tab键将焦点移到按钮上,然后按回车,程序响应了按钮的消息函数;

另一种是按回车使焦点移到按钮上,此时再按回车,没有执行按钮的消息函数而是继续将焦点移到。

看起来都是焦点到了按钮上,为什么两者不同,我想知道为什么会这样?原因在哪里?
[/Quote]

有黑边框就是因为按钮有default button属性,有该属性时回车才能执行该按钮的动作。
按tab切换焦点时,windows不单setfocus,对按钮还SetButtonStyle(BS_DEFPUSHBUTTON, TRUE);了,而你的代码中没有调用该代码。按5楼说的加上这段设置按钮属性的代码就行了。
testpwd 2010-08-26
  • 打赏
  • 举报
回复
windsonzhl你说的太对了,原来还没看出来这细小的差别,的确当用Tab键将焦点移到按钮上时有黑边框。

To iamshuke:我在OnOK中实现回车自动调整控件焦点,按钮也没有default button属性,其实程序并不重要,我只是想探讨两者的区别和原因在哪里。

一种是:按Tab键将焦点移到按钮上,然后按回车,程序响应了按钮的消息函数;

另一种是按回车使焦点移到按钮上,此时再按回车,没有执行按钮的消息函数而是继续将焦点移到。

看起来都是焦点到了按钮上,为什么两者不同,我想知道为什么会这样?原因在哪里?

[Quote=引用 7 楼 windsonzhl 的回复:]
i am shuke 答非所问哈

这个问题很好解释,按钮的焦点状态有点特殊。
仔细看一下就会发现,执行LZ的OnOK的处理将焦点移至按钮上时,只出现了虚线框。
(如果没用鼠标点过按钮,甚至虚线框也不会出现。)
而使用Tab键将焦点移至按钮上时,不仅出现了虚线框,还出现了粗边框(不同主题下效果不同)。
猜测此时按钮被赋予了临时的“缺省”属性,此时回车键只会识别这个按钮。

你可以看……
[/Quote]
iamshuke 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 windsonzhl 的回复:]
i am shuke 答非所问哈

这个问题很好解释,按钮的焦点状态有点特殊。
仔细看一下就会发现,执行LZ的OnOK的处理将焦点移至按钮上时,只出现了虚线框。
(如果没用鼠标点过按钮,甚至虚线框也不会出现。)
而使用Tab键将焦点移至按钮上时,不仅出现了虚线框,还出现了粗边框(不同主题下效果不同)。
猜测此时按钮被赋予了临时的“缺省”属性,此时回车键只会识别这个按钮。

你可以看……
[/Quote]

看我在5楼的答复,粗线就是因为有BS_DEFPUSHBUTTON属性。
  • 打赏
  • 举报
回复
i am shuke 答非所问哈

这个问题很好解释,按钮的焦点状态有点特殊。
仔细看一下就会发现,执行LZ的OnOK的处理将焦点移至按钮上时,只出现了虚线框。
(如果没用鼠标点过按钮,甚至虚线框也不会出现。)
而使用Tab键将焦点移至按钮上时,不仅出现了虚线框,还出现了粗边框(不同主题下效果不同)。
猜测此时按钮被赋予了临时的“缺省”属性,此时回车键只会识别这个按钮。

你可以看看 COccManager::IsDialogMessage() 的实现
(...\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\occdlg.cpp)
iamshuke 2010-08-25
  • 打赏
  • 举报
回复
补充,放在GetNextDlgTabItem(GetFocus())->SetFocus();之后
iamshuke 2010-08-25
  • 打赏
  • 举报
回复
知道原因就好处理了,回车执行某按钮,是因为该按钮有default button属性,当你切换焦点到你的按钮时,给它设上这个属性就行了。

if(GetFocus()->GetDlgCtrlID() == IDC_BUTTON1)
{
CButton* pBtn = (CButton*)GetFocus();
pBtn->SetButtonStyle(BS_DEFPUSHBUTTON, TRUE);
}

gameslq 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 iamshuke 的回复:]
你在OnOK中GetNextDlgTabItem(GetFocus())->SetFocus();引起的。

回车时执行默认动作OnOK,你用代码把焦点设到了当前焦点控件的下一个控件,所以就出现这种现象了。
你把你新加的按钮属性设上“default button”,或者edit控件有“multiline”和“want return”属性时就不会默认回车OnOK了。
[/Quote]

楼主想实现回车自动调整控件焦点.
testpwd 2010-08-25
  • 打赏
  • 举报
回复
我奇怪的是同样是输入焦点在按钮上,为什么按Tab键,焦点在按钮上时,按回车键会执行按钮的响应函数?

或者说当按回车键时焦点从编辑框跳到按钮上,再按回车键,根据这句话:

GetNextDlgTabItem(GetFocus())->SetFocus();

焦点应该跳到下一个编辑框上。但是当焦点在一个按钮上时也应该执行它的响应函数才对啊。

这两者是不是有点矛盾?

iamshuke 2010-08-25
  • 打赏
  • 举报
回复
你在OnOK中GetNextDlgTabItem(GetFocus())->SetFocus();引起的。

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

长尾巴的悟空 2010-08-25
  • 打赏
  • 举报
回复
问题出现在ONOK上,删除了自带的ONOK后,好像还得自个加个什么东东。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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