[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]

Posted infoworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]相关的知识,希望对你有一定的参考价值。

场景

  1. 在使用WTL的自定义按钮[1]时, 按钮在禁用后,接着弹出一个进度条。这时候按钮的禁用按钮并没有被绘制。显示的还是黑色矩形,怎么回事?

说明

  1. 在需要处理一些数据完成后才允许用户点击,这时候就需要禁用按钮。

解决的过程

  1. 按钮显示黑色的矩形就是它的WM_PAINT或者WM_DRAWITEM并没有被执行。 原本重载的EnableWindow是以下写法。这里可以看出来在调用父类的EnableWindow之后,WM_PAINT并没有被执行。
BOOL BASSwitchButton::EnableWindow(BOOL bEnable)

	status_ = (bEnable)?kButtonStatusNormal:kButtonStatusDisable;
	return CWindowImpl::EnableWindow(bEnable);

  1. 改为修改按钮状态后发送绘制事件也不行,虽然没有黑色矩形框,但是按钮显示了原本的系统样式。结果还是需要在按钮启用之后鼠标移动到按钮上才会触发绘制事件。可以猜测出在调用系统的EnableWindow时,系统按钮有自己的一套显示样式,这个样式覆盖了原本自定义的样式,所以自定义的禁用样式只是显示了一瞬。
BOOL BASSwitchButton::EnableWindow(BOOL bEnable)

	status_ = (bEnable)?kButtonStatusNormal:kButtonStatusDisable;
	Invalidate(FALSE);
	UpdateWindow();
	return CWindowImpl::EnableWindow(bEnable);

  1. 注意,这里只有按钮禁用操作和显示弹出进度条对话框在同一个线程才会出现按钮的绘制事件丢失的现象。应该是对话框启动时会启动自己的事件循环,而原来的事件循环里的事件丢失了,导致按钮的禁用操作并没有接着发送一次绘图事件。

正确的修改方式

  1. 在猜测EnableWindow(FALSE)会显示系统禁用样式后,需要把绘制放在它之后再处理。
BOOL BASSwitchButton::EnableWindow(BOOL bEnable)

	auto result = CWindowImpl::EnableWindow(bEnable);
	status_ = (bEnable)?kButtonStatusNormal:kButtonStatusDisable;
	Invalidate(FALSE);
	UpdateWindow();
	return result;

例子

  1. 代码使用自定义按钮1[1]里的自定义按钮类。

参考

  1. 自定义按钮1_infoworld的博客

  2. 自定义按钮2_infoworld的博客

  3. NMCUSTOMDRAW (commctrl.h) - Win32 apps | Microsoft Learn

以上是关于[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]的主要内容,如果未能解决你的问题,请参考以下文章

[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]

[ATL/WTL]_[初级]_[Win32窗口自定义消息处理过程]

[ATL/WTL]_[初级]_[自定义多列TreeView]

[ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]

[ATL/WTL]_[中级]_[保存CBitmap到文件-保存屏幕内容到文件]

[JavaScript]_[初级]_[使用HTMLElement.dataset快速读写自定义属性]