duilib教程之duilib入门简明教程11.部分bug
一、WindowImplBase的bug 在第8个教程【2013 duilib入门简明教程 -- 完整的自绘标题栏(8)】中,可以发现窗口最大化之后有两个问题,
1、最大化按钮的样式还是没变
,正确的样式应该是这样的
2、再次点击最大化按钮,不能还原到正常大小。
这个是WindowImplBase的bug,已经提交给官方有一段时间了,但是貌似没有被合并到SVN上去,所以这里说明一下,
我们需要在WindowImplBase的OnSysCommand函数里,在if( ::IsZoomed(*this) != bZoomed )里面加上下面这段代码:
- if( ::IsZoomed(*this) != bZoomed )
- {
- CControlUI* pbtnMax = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("maxbtn"))); // 最大化按钮
- CControlUI* pbtnRestore = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("restorebtn"))); // 还原按钮
- // 切换最大化按钮和还原按钮的状态
- if (pbtnMax && pbtnRestore)
- {
- pbtnMax->SetVisible(TRUE == bZoomed); // 此处用表达式是为了避免编译器BOOL转换的警告
- pbtnRestore->SetVisible(FALSE == bZoomed);
- }
- }
复制代码
二、CDuiString的bug (重温了一下 Effective C++,发现这就是条款24所指出的问题,看来读书百遍不如写代码一遍啊)
在Notify处理消息时会有很多if语句,我通常喜欢把常量放在双等号前面,变量放在后面,比如:
if( _T("click") == msg.sType )
{
}
但是却发现并没有进到这个if里,调试发现,将常量调到前面时,并没有进入到CDuiString重载的 == 函数里面,所以这里必须将常量放到后面。
if( msg.sType == _T("click") )
{
}
这个bug的原因是因为将常量放在前面时,并没有调用CDuiString重载的 == 函数,而是调用了CDuiString重载的 ()函数,然后用系统自带的==函数做比较,而系统自己的==函数只是比较两个指针的首地址是否相等。_T("click") 的首地址指向的是一块临时变量,而msg.sType 是返回了CDuiString里面那个字符串的指针,很显然这两个指针地址是不相等的,所以我们只能把它放在前面,或者直接调用_tcscmp
if( ! _tcscmp( _T("click"), msg.sType) )
{
}
当然,如果要解决这个bug,就要重载多个==操作符,
由于CDuiString是将==函数作为成员函数重载的,所以只有CDuiString对象在操作符左边时,才会调用这个重载函数,如果想要CDuiString对象在右边时也能调用重载的==函数,那么必须将重载操作符放到外部。这里我们可以看一下MFC的CString是怎么重载的:
CString 重载了5个==操作符,都是友元函数,定义在#include里面。
再看下STL的std::string :
std::string重载了3个==操作符,都是全局函数,定义在#include里面。
不过需要提醒的是,我稍微看了下CDuiString的代码,有很多漏洞,比如在清零字符串时,只是调用了 m_szBuffer[0] = ''; 并不是调用memset,那么就会有以下问题,我们随意现在用下面两种方式给CDuiString 附值,然后监视字符串数组的内容,可以发现虽然显示是正确的,但是在零值后面的值全部是乱码:![]()
![]()
这样的话,虽然_tcslen、_tcscmp等函数能用,但是还有很多函数都会出问题的。
所以这个CDuiString能不用则不用,如果嫌MFC生成的exe体积大,可以用WTL的CString,如果WTL也不想用,那就只好用STL的string了。
当然,为了保证代码的兼容性,一些简单的处理还是用CDuiString比较好,比如 msg.sType。
而逻辑处理等复杂的场景,最好用久经考验的代码。 虽然微软的CString很强大,而用STL的string时可能不方便,但是我现在越来越喜欢STL的string啦,当然,我是定义了一个string_t,加上一个名字空间,以防和一些开源库冲突,
一些著名的开源库喜欢如下定义:
- #ifdef _UNICODE
- typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_t;
- #else
- typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > string_t;
- #endif
复制代码
不过我喜欢更简短的定义:
- #ifdef _UNICODE
- typedef std::wstring string_t;
- #else
- typedef std::string string_t;
- #endif
复制代码
下面是我常用的Unicode定义:
- #include <string>
- #include <sstream>
- namespace duilib
- {
- #ifdef _UNICODE
- typedef wchar_t char_t;
- typedef std::wstring string_t;
- typedef std::wstringstream stringstream_t;
- #else
- typedef char char_t;
- typedef std::string string_t;
- typedef std::stringstream stringstream_t;
- #endif
- }
复制代码
duilib教程之duilib入门简明教程11.部分bug的更多相关文章
- duilib教程之duilib入门简明教程17.事件处理和消息响应
界面的显示方面就都讲完啦,下面来介绍下控件的响应. 前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEGIN_ME ...
- duilib教程之duilib入门简明教程14.部分bug 2
上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃 如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口都用new生成,_t ...
- duilib教程之duilib入门简明教程15.自绘控件
在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如菜单控件 ...
- duilib教程之duilib入门简明教程13.复杂控件介绍
首先将本节要介绍的控件全部拖到界面上,并调整好位置,如图: 然后将Name属性改成其他名字, 不能是[控件名+UI+数字]这种,因为这是DuiDesigner默认的名字,它不会实际写 ...
- duilib教程之duilib入门简明教程3.第一个程序 Hello World
小伙伴们有点迫不及待了么,来看一看Hello World吧:新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #in ...
- duilib教程之duilib入门简明教程1.前言
关于duilib的介绍就不多讲了,一来不熟,二来小伙伴们想必已经对比了多个界面库,也无需赘述.下面进入正题: 不看广告看疗效! 已有众多知名公司采用duilib做为界面库,如华为网盘.PPS(P ...
- duilib教程之duilib入门简明教程9.界面布局
上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayout,这样 ...
- duilib教程之duilib入门简明教程2.VS环境配置
既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的. 其实吧,duilib的定位好 ...
- duilib教程之duilib入门简明教程16.结合win32和MFC
虽然duilib自带在MFC中使用duilib的Demo,但只是MFC窗口和duilib窗口不重叠的情况.如果要在MFC窗口中嵌入duilib控件,或者在duilib控件中嵌入MFC的控件的话,就没有 ...
随机推荐
- vue cli3 vue.config配置
跳地址:https://cli.vuejs.org/zh/config/#publicpath
- jq-demo-购物车
首页 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title& ...
- mui框架开发aop的跨页面传值
mui开发跨平台app,其实不乏会涉及到跨页面传值,今天给大家简单介绍一种常用也是简单的传值方法 咱在这里设置一个场景,就是两个页面进入到同一页面展示不同的元素,此时需要在这两个页面各自设置一个区别的 ...
- 约数个数求和+线性筛约数——bzoj3994
这题首先要会线性筛约数个数,并求出前缀和 bool vis[maxn]; int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[ma ...
- github如何用浏览器直接打开项目里的html页面?
very easy 第一步 点击html页面 第二步,在地址栏前加 htmlpreview.github.io/?就可以访问
- detours学习
最近学习detours3.0,总结下学习过程,给后来学习者一点参考,也便于自己以后复习 首先应该知道detours可以干什么,学习之前最好看一下detours文档,这个文档很简单,只有4篇文章,相对比 ...
- CSS3:目录
ylbtech-CSS3:目录 1.返回顶部 1. http://www.runoob.com/css3/css3-tutorial.html 2. 2.返回顶部 3.返回顶部 4.返回顶部 ...
- topjui.core.js
var defaultConfig = { pageLoadComplete: false, config: { ctx: "", mainPage: false, pkName: ...
- MySQL数据库迁移详细步骤
转载自:http://sofar.blog.51cto.com/353572/1598364 ===================================================== ...
- sql基础学习
学习参考网站:http://www.runoob.com/sql/sql-tutorial.html 一.SQL命令 1.SELECT 语句 用于从数据库中选取数据. select column_na ...