找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 221|回复: 0

2013 duilib入门简明教程 -- 部分bug (11)

[复制链接]

52

主题

62

回帖

0

积分

版主

积分
0
发表于 2013-10-21 14:24:37 | 显示全部楼层 |阅读模式
一、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
    在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<cstringt.h>里面。    再看下STL的std::string :    std::string重载了3个==操作符,都是全局函数,定义在#include<string>里面。   不过需要提醒的是,我稍微看了下CDuiString的代码,有很多漏洞,比如在清零字符串时,只是调用了 m_szBuffer[0] = &#39;\0&#39;; 并不是调用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. }
复制代码
来自为知笔记(Wiz)


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

果子博客
扫码关注微信公众号

Archiver|手机版|小黑屋|风叶林

GMT+8, 2026-2-1 04:41 , Processed in 0.101001 second(s), 20 queries .

Powered by 风叶林

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表