一、WindowImplBase的bug    在第8个教程【2013 duilib入门简明教程 -- 完整的自绘标题栏(8)】中,可以发现窗口最大化之后有两个问题,
    1、最大化按钮的样式还是没变  ,正确的样式应该是这样的  
    2、再次点击最大化按钮,不能还原到正常大小。
    这个是WindowImplBase的bug,已经提交给官方有一段时间了,但是貌似没有被合并到SVN上去,所以这里说明一下,
我们需要在WindowImplBase的OnSysCommand函数里,在if( ::IsZoomed(*this) != bZoomed )里面加上下面这段代码:

  1. if( ::IsZoomed(*this) != bZoomed )
  2. {
  3. CControlUI* pbtnMax = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("maxbtn"))); // 最大化按钮
  4. CControlUI* pbtnRestore = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("restorebtn"))); // 还原按钮
  5. // 切换最大化按钮和还原按钮的状态
  6. if (pbtnMax && pbtnRestore)
  7. {
  8. pbtnMax->SetVisible(TRUE == bZoomed); // 此处用表达式是为了避免编译器BOOL转换的警告
  9. pbtnRestore->SetVisible(FALSE == bZoomed);
  10. }
  11. }

复制代码

二、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,加上一个名字空间,以防和一些开源库冲突,
    一些著名的开源库喜欢如下定义:

  1. #ifdef _UNICODE
  2. typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_t;
  3. #else
  4. typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > string_t;
  5. #endif

复制代码

不过我喜欢更简短的定义:

  1. #ifdef _UNICODE
  2. typedef std::wstring string_t;
  3. #else
  4. typedef std::string  string_t;
  5. #endif

复制代码

下面是我常用的Unicode定义:

  1. #include <string>
  2. #include <sstream>
  3. namespace duilib
  4. {
  5. #ifdef _UNICODE
  6. typedef wchar_t              char_t;
  7. typedef std::wstring         string_t;
  8. typedef std::wstringstream   stringstream_t;
  9. #else
  10. typedef char                 char_t;
  11. typedef std::string          string_t;
  12. typedef std::stringstream    stringstream_t;
  13. #endif
  14. }

复制代码

duilib教程之duilib入门简明教程11.部分bug的更多相关文章

  1. duilib教程之duilib入门简明教程17.事件处理和消息响应

    界面的显示方面就都讲完啦,下面来介绍下控件的响应.    前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEGIN_ME ...

  2. duilib教程之duilib入门简明教程14.部分bug 2

    上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃      如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口都用new生成,_t ...

  3. duilib教程之duilib入门简明教程15.自绘控件

    在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如菜单控件 ...

  4. duilib教程之duilib入门简明教程13.复杂控件介绍

    首先将本节要介绍的控件全部拖到界面上,并调整好位置,如图:  然后将Name属性改成其他名字,         不能是[控件名+UI+数字]这种,因为这是DuiDesigner默认的名字,它不会实际写 ...

  5. duilib教程之duilib入门简明教程3.第一个程序 Hello World

    小伙伴们有点迫不及待了么,来看一看Hello World吧:新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #in ...

  6. duilib教程之duilib入门简明教程1.前言

    关于duilib的介绍就不多讲了,一来不熟,二来小伙伴们想必已经对比了多个界面库,也无需赘述.下面进入正题:    不看广告看疗效! 已有众多知名公司采用duilib做为界面库,如华为网盘.PPS(P ...

  7. duilib教程之duilib入门简明教程9.界面布局

    上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayout,这样 ...

  8. duilib教程之duilib入门简明教程2.VS环境配置

    既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的.    其实吧,duilib的定位好 ...

  9. duilib教程之duilib入门简明教程16.结合win32和MFC

    虽然duilib自带在MFC中使用duilib的Demo,但只是MFC窗口和duilib窗口不重叠的情况.如果要在MFC窗口中嵌入duilib控件,或者在duilib控件中嵌入MFC的控件的话,就没有 ...

随机推荐

  1. Unicode - 16 位统一超级字符集

    描述 (DESCRIPTION) 国际标准 ISO 10646 定义了 通用字符集 (Universal Character Set, UCS). UCS 包含所有别的字符集标准里的字符,并且保证了 ...

  2. nginx 简单使用

    一,下载 http://nginx.org/en/download.html 这个是我下载的windows版本 二,解压后目录 三,修改配置文件 (由于80端口很可能被 SQL Server Repo ...

  3. netstat -pa --unix >>test.txt

    netstat -pa --unix >>test.txt 输出套接字 命名socket信息

  4. 带你彻底理解RSA算法原理,很简单的

    1. 什么是RSA RSA算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法. 在了解RSA算法之前,先熟悉下几个术语 根据密钥的使用方法,可以将密码分为 对称密码 和 公钥密码 对称 ...

  5. vue for 循环例子 2

    demo <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf- ...

  6. webpack4.0高级

    环境变量 webpack --env.NODE_ENV=local --env.production --progress Tree Shaking 移除JS上下文字未被引用的代码 只支持ES6的im ...

  7. H5调用百度地图导航

    template <div class="map"> <div class="content_flex"><img src=&qu ...

  8. C/C++各个周期的学习

    C/C++ 程序的生命周期 编写时: 要点:业务,数据结构,控制解耦:健壮:易修改:清晰简单无歧义:易重用:低耦合高内聚:易链接:速度快(时间复杂度,空间复杂度,cache友好): 书籍:<c+ ...

  9. MapReduce计算原理及步骤

    步骤:input从HDFS读取内容, split()切割分片内容,key/value, map()方法对输入的key/value进行计算处理,先写到内存,在内存中进行分区.排序,之后将Key/valu ...

  10. 47 ubuntu指令整理学习

    0 引言 在使用ubutnu时,积累了大量命令笔记.但是这些笔记比较零散,没有系统性,不便于查找和使用.通过系统性.分门别类地整理,希望可以增强对指令的记忆,提高工作效率,对ubuntu的使用更加地道 ...