• [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
    • 2
    • 3
    • 4
    • 5
    1. 改为修改按钮状态后发送绘制事件也不行,虽然没有黑色矩形框,但是按钮显示了原本的系统样式。结果还是需要在按钮启用之后鼠标移动到按钮上才会触发绘制事件。可以猜测出在调用系统的EnableWindow时,系统按钮有自己的一套显示样式,这个样式覆盖了原本自定义的样式,所以自定义的禁用样式只是显示了一瞬。
    BOOL BASSwitchButton::EnableWindow(BOOL bEnable)
    {
    	status_ = (bEnable)?kButtonStatusNormal:kButtonStatusDisable;
    	Invalidate(FALSE);
    	UpdateWindow();
    	return CWindowImpl::EnableWindow(bEnable);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 注意,这里只有按钮禁用操作和显示弹出进度条对话框在同一个线程才会出现按钮的绘制事件丢失的现象。应该是对话框启动时会启动自己的事件循环,而原来的事件循环里的事件丢失了,导致按钮的禁用操作并没有接着发送一次绘图事件。

    正确的修改方式

    1. 在猜测EnableWindow(FALSE)会显示系统禁用样式后,需要把绘制放在它之后再处理。
    BOOL BASSwitchButton::EnableWindow(BOOL bEnable)
    {
    	auto result = CWindowImpl::EnableWindow(bEnable);
    	status_ = (bEnable)?kButtonStatusNormal:kButtonStatusDisable;
    	Invalidate(FALSE);
    	UpdateWindow();
    	return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    例子

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

    参考

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

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

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

  • 相关阅读:
    Vue前端整合后端的CRUD
    2022/7/26
    OpenWrt之opkg详解
    python之字符、字符串切片、三引号使用
    基于MxNet实现目标检测-CenterNet【附部分源码及模型】
    mojo 笔记 (Python/Cython)
    JavaScript之DOM进阶
    [CC2642R1][VSCODE+Embedded IDE+Cortex-Debug] TI CC2642R1 快速搭建VsCode开发环境
    力扣 667. 优美的排列 II
    Go:命令行参数解析包 flag 简介
  • 原文地址:https://blog.csdn.net/infoworld/article/details/127704675