仿酷狗音乐播放器开发日志二十三 修复Option控件显示状态不全的bug(附源码)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 转载请说明原出处,谢谢~~          整个仿酷狗工程的开发将近尾声,现在还差选项设置窗体的部分,显然在设置窗体里用的最多的就是OptionUI控件,我在写好大致的布局后去测试效果,发现Option控件的显示效果很不理想。

转载请说明原出处,谢谢~~


         整个仿酷狗工程的开发将近尾声,现在还差选项设置窗体的部分,显然在设置窗体里用的最多的就是OptionUI控件,我在写好大致的布局后去测试效果,发现Option控件的显示效果很不理想。在源码中可以知道(属性列表中列的不全面)Option提供了8种显示状态,分别为

<Attribute name="normalimage" default="" type="STRING" comment="普通状态图片"/>
<Attribute name="hotimage" default="" type="STRING" comment="鼠标悬浮的状态图片"/>
<Attribute name="pushedimage" default="" type="STRING" comment="鼠标按下的状态图片"/>
<Attribute name="focusedimage" default="" type="STRING" comment="获得焦点时的状态图片"/>
<Attribute name="disabledimage" default="" type="STRING" comment="禁用的状态图片"/>
<Attribute name="selectedimage" default="" type="STRING" comment="选中的状态图片"/>
<Attribute name="selectedhotimage" default="" type="STRING" comment="选中的鼠标悬浮的的状态图片"/>
<Attribute name="foreimage" default="" type="STRING" comment="前景图片"/>

        这些属性可以大致模仿出check控件分别在选中和非选中状态下的一些效果,我设置了其中的normalimage、hotimage、pushedimage、disabledimage、selectedimage、selectedhotimage属性,但是在测试时发现,只有 pushedimage 属性没有效果,也就是check控件和option控件没有被按下的状态的效果,同时也注意到原控件没有提供选中的鼠标按下的的状态图片,这就让Option控件和Check控件的效果很不好。查看源码后发现问题。原代码如下:

	void COptionUI::PaintStatusImage(HDC hDC)
	{
		m_uButtonState &= ~UISTATE_PUSHED;

		if( (m_uButtonState & UISTATE_HOT) != 0 && IsSelected() && !m_sSelectedHotImage.IsEmpty()) {
			if( !DrawImage(hDC, (LPCTSTR)m_sSelectedHotImage) )
				m_sSelectedHotImage.Empty();
			else goto Label_ForeImage;
		}
		else if( (m_uButtonState & UISTATE_SELECTED) != 0 ) {
			if( !m_sSelectedImage.IsEmpty() ) {
				if( !DrawImage(hDC, (LPCTSTR)m_sSelectedImage) ) m_sSelectedImage.Empty();
				else goto Label_ForeImage;
			}
			else if(m_dwSelectedBkColor != 0) {
				CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwSelectedBkColor));
				return;
			}	
		}

		CButtonUI::PaintStatusImage(hDC);

Label_ForeImage:
		if( !m_sForeImage.IsEmpty() ) {
			if( !DrawImage(hDC, (LPCTSTR)m_sForeImage) ) m_sForeImage.Empty();
		}
	}
        可以看到,代码的第一句就把按下状态给去掉了,虽然不知道作者这样写的意图,但我觉得这是不对的,去掉这句代码后Option控件在非选中状态下就可以显示鼠标按下的状态了。

        随后我给Option控件增加了一个selectedpushedimage属性,用来设置选中的鼠标按下的的状态图片,让Option的显示状态更加完全,为了使用这个属性,需要修改SetAttribute函数,另外增加了两个函数SetSelectedPushedImage和GetSelectedPushedImage,这是修改后的PaintStatusImage函数:

		if( (m_uButtonState & UISTATE_PUSHED) != 0 && IsSelected() && !m_sSelectedPushedImage.IsEmpty()) {
			if( !DrawImage(hDC, (LPCTSTR)m_sSelectedPushedImage) )
				m_sSelectedPushedImage.Empty();
			else goto Label_ForeImage;
		}
		else if( (m_uButtonState & UISTATE_HOT) != 0 && IsSelected() && !m_sSelectedHotImage.IsEmpty()) {
			if( !DrawImage(hDC, (LPCTSTR)m_sSelectedHotImage) )
				m_sSelectedHotImage.Empty();
			else goto Label_ForeImage;
		}
		else if( (m_uButtonState & UISTATE_SELECTED) != 0 ) {
			if( !m_sSelectedImage.IsEmpty() ) {
				if( !DrawImage(hDC, (LPCTSTR)m_sSelectedImage) ) m_sSelectedImage.Empty();
				else goto Label_ForeImage;
			}
			else if(m_dwSelectedBkColor != 0) {
				CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwSelectedBkColor));
				return;
			}	
		}

		CButtonUI::PaintStatusImage(hDC);

Label_ForeImage:
		if( !m_sForeImage.IsEmpty() ) {
			if( !DrawImage(hDC, (LPCTSTR)m_sForeImage) ) m_sForeImage.Empty();
		}
          这样就可以让Option控件显示出9种状态了,完全可以模仿出真正的Option控件的样子,这是我做的一部分的设置窗体的样子:




           这里给出完整的状态属性列表:

<Attribute name="normalimage" default="" type="STRING" comment="普通状态图片"/>
<Attribute name="hotimage" default="" type="STRING" comment="鼠标悬浮的状态图片"/>
<Attribute name="pushedimage" default="" type="STRING" comment="鼠标按下的状态图片"/>
<Attribute name="focusedimage" default="" type="STRING" comment="获得焦点时的状态图片"/>
<Attribute name="disabledimage" default="" type="STRING" comment="禁用的状态图片"/>
<Attribute name="selectedimage" default="" type="STRING" comment="选中的状态图片"/>
<Attribute name="selectedhotimage" default="" type="STRING" comment="选中的鼠标悬浮的的状态图片"/>
<Attribute name="selectedpushedimage" default="" type="STRING" comment="选中的鼠标按下的的状态图片"/>
<Attribute name="foreimage" default="" type="STRING" comment="前景图片"/>

        另外因为需要大量重复使用Option控件,为了避免重复设置属性,我这里给出我的仿酷狗设置窗体的Default标签,方便大家用,大家根据自己的情况再去修改:

<Default name="CheckBox" value="textcolor="#FF454545" disabledtextcolor="#FF454545" width="10" height="14" textpadding="16,1,0,0" align="left" normalimage="file='UI\setting\check_normal.png' dest='0,0,14,14'" hotimage="file='UI\setting\check_hover.png' dest='0,0,14,14'" pushedimage="file='UI\setting\check_down.png' dest='0,0,14,14'" disabledimage="file='UI\setting\check_disable.png' dest='0,0,14,14'" selectedimage="file='UI\setting\checked_normal.png' dest='0,0,14,14'" selectedhotimage="file='UI\setting\checked_hover.png' dest='0,0,14,14'" selectedpushedimage="file='UI\setting\checked_down.png' dest='0,0,14,14'" autocalcwidth="true""/>

总结:

        其实还可以在写一个selecteddisabledimage属性,用来给选中状态下的Option控件设置禁用效果,这个代码我目前不需要,就不写了,留给大家自己写吧,很简单的。

        修改好的OPtion控件下载地址:点击打开链接

Redrain 2014.8.25

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
Rust 前端开发 JavaScript
Tauri 开发实践 — Tauri 日志记录功能开发
本文介绍了如何为 Tauri 应用配置日志记录。Tauri 是一个利用 Web 技术构建桌面应用的框架。文章详细说明了如何在 Rust 和 JavaScript 代码中设置和集成日志记录,并控制日志输出。通过添加 `log` crate 和 Tauri 日志插件,可以轻松实现多平台日志记录,包括控制台输出、Webview 控制台和日志文件。文章还展示了如何调整日志级别以优化输出内容。配置完成后,日志记录功能将显著提升开发体验和程序稳定性。
71 1
Tauri 开发实践 — Tauri 日志记录功能开发
|
13天前
|
监控 开发者
鸿蒙5.0版开发:使用HiLog打印日志(ArkTS)
在HarmonyOS 5.0中,HiLog是系统提供的日志系统,支持DEBUG、INFO、WARN、ERROR、FATAL五种日志级别。本文介绍如何在ArkTS中使用HiLog打印日志,并提供示例代码。通过合理使用HiLog,开发者可以更好地调试和监控应用。
56 16
|
1月前
|
开发框架 缓存 安全
开发日志:IIS安全配置
开发日志:IIS安全配置
开发日志:IIS安全配置
|
1月前
|
开发工具 git
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
39 1
|
3月前
|
人工智能 Java Spring
Spring框架下,如何让你的日志管理像‘AI’一样智能,提升开发效率的秘密武器!
【8月更文挑战第31天】日志管理在软件开发中至关重要,不仅能帮助开发者追踪问题和调试程序,还是系统监控和运维的重要工具。在Spring框架下,通过合理配置Logback等日志框架,可大幅提升日志管理效率。本文将介绍如何引入日志框架、配置日志级别、在代码中使用Logger,以及利用ELK等工具进行日志聚合和分析,帮助你构建高效、可靠的日志管理系统,为开发和运维提供支持。
68 0
|
15天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
128 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
232 3
|
3月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
132 3
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1637 14
|
1月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
34 0