解决纯win32应用程序按钮不会自动出现焦点的粗框、WS_TABSTOP属性失效

本文介绍了如何在纯Win32应用程序中解决按钮焦点显示问题,通过添加WS_TABSTOP样式并捕获WM_SETCURSOR消息实现焦点边框动态显示。同时,通过处理消息队列解决Tab键切换焦点不生效的问题,使得控件能够正确响应键盘操作。
摘要由CSDN通过智能技术生成

1.按钮获得焦点的粗框

在Dev C++中创建一个Windows Application项目,在自带的初始代码的基础上开发,在消息循环WM_CREATE中使用CreateWindow/Ex()来创建控件,类名写上Button(在头文件commctrl.h中,还可以使用WC_BUTTON作为类名),样式加上BS_PUSHBUTTON,编译运行,效果如图:
在这里插入图片描述
当它获得焦点(用鼠标按住,然后离开按钮,再松开鼠标)时,看样子并没有变化。但是如果我们把样式改为BS_DEFPUSHBUTTON时,效果如图:
在这里插入图片描述
但是,设置了这个样式后,只要这个样式还在,那么就一直有蓝色边框(没有启用6.0组件视觉样式的是黑色边框)。但是,如果开发过MFC、.NET、VBasic的话,就可以发现它们的按钮是,如果有很多按钮,谁有键盘焦点,谁就有边框。如果细心观察,MessageBox()的按钮也会这样。
当按钮获得焦点后,按空格键就相当于是鼠标点击了,为了给用户不错的体验,知道当前焦点在哪个按钮上,给它加上蓝色边框,更合适。起先我觉得,MFC和MessageBox()的按钮与我们自己创建的不是一种,但是后来我实验了一下,先挂一个CBT Hook,在回调中调用GetDlgItem()GetClassName()取得按钮类名,然后输出,发现类名就是一般的按钮Button
于是,我开始尝试手动实现。要捕获按钮控件的焦点事件,可以加上BS_NOTIFY样式,这样当获得/失去焦点时,会产生WM_COMMAND消息,wParam的高位字就是捕获的动作(BN_SETFOCUS获得焦点,BN_KILLFOCUS失去焦点),在这里面对给获得焦点的按钮加上BS_DEFPUSHBUTTON样式,失去焦点删除这个样式。似乎可行了。

2.使用Tab键切换焦点

给所有控件加上WS_TABSTOP样式,预期效果是按下Tab键,焦点会转移到下一个控件,从而允许按空格或者其他按键操作控件。可是在Dev C++默认的代码之上开发,却压根没有作用。怎么办?
我搜索了一通,发现这个网页,原来有人也有一样的困惑。
https://social.msdn.microsoft.com/Forums/en-US/b4c80260-7acf-4989-bce7-d377e33e61d7/tabstop-not-working-on-a-pure-win32-application
其中给出的办法是分发消息时做一下判断IsDialogMessage(),如果为假再发送给消息处理函数,为真就不动,会自己处理。具体就是:
在入口函数WinMain()的最后找到对消息队列的处理,如下:

/*
	This is the heart of our program where all input is processed and
	sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
	this loop will not produce unreasonably high CPU usage
*/
while (GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
	TranslateMessage(&msg); /* Translate key codes to chars if present */
	DispatchMessage(&msg); /* Send it to WndProc */
}

加上对消息的判断,如下:

while (GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
	if (!IsDialogMessage(hwnd, &msg)) {
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
}

运行后效果就是,按下Tab,焦点果然顺利地后移了。它还附赠一个惊喜:不需要手动对按钮焦点作处理,它会自己帮助我们为焦点按钮加上边框。
演示

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值