一、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<cstringt.h>里面。
    再看下STL的std::string :
    std::string重载了3个==操作符,都是全局函数,定义在#include<string>里面。
 
  不过需要提醒的是,我稍微看了下CDuiString的代码,有很多漏洞,比如在清零字符串时,只是调用了 m_szBuffer[0] = '\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
}
 
 

2013 duilib入门简明教程 -- 部分bug (11)的更多相关文章

  1. 2013 duilib入门简明教程 -- 部分bug 2 (14)

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

  2. duilib入门简明教程 -- 部分bug (11) (转)

    原文转自:http://www.cnblogs.com/Alberl/p/3344886.html  一.WindowImplBase的bug     在第8个教程[2013 duilib入门简明教程 ...

  3. 2013 duilib入门简明教程 -- 总结 (20)

        duilib的入门系列就到尾声了,再次提醒下,Alberl用的duilib版本是SVN上第个版本,时间是2013.08.15~       这里给出Alberl最后汇总的一个工程,戳我下载,效 ...

  4. 2013 duilib入门简明教程 -- 自绘控件 (15)

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

  5. 2013 duilib入门简明教程 -- 第一个程序 Hello World(3)

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

  6. 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)

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

  7. 2013 duilib入门简明教程 -- FAQ (19)

        虽然前面的教程几乎把所有的知识点都罗列了,但是有很多问题经常在群里出现,所以这里再次整理一下.     需要注意的是,在下面的问题中,除了加上XML属性外,主窗口必须继承自WindowImpl ...

  8. 2013 duilib入门简明教程 -- 界面布局(9)

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

  9. 2013 duilib入门简明教程 -- 前言(1)

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

随机推荐

  1. 在Javascript中onclick()方法应用

    <html> < head> < script type="text/javascript"> function onclick1(){ ale ...

  2. ASP.NET图形验证码的生成

    效果: 调用方法: int[] r = QAPI.VerifImage.RandomList();//取得随机数种子列 );//产生验证码字符 pictureBox1.Image = QAPI.Ver ...

  3. css3的动画特性

    css3 的过渡动画,有些时候会产生一些其他问题. 比如:你想先改一个css属性,之后再进行动画过渡,结果实际上你会发现,css属性和动画是同步进行的.这个应该是在编译阶段就确定好了. 所以只能通过s ...

  4. clang: error: linker command failed with exit code 1 (use -v to see invocati

    安装了 pod 的项目,如果仍旧打开 xcodeproject 文件, 运行时会弹出此 bug

  5. mvc 返回值

    mvc返回值为Model类型 public ActionResult Index(T result) { return View(result); } view中的对象即为页面中的Model数据,之后 ...

  6. 两种让tableview返回顶部的方法

    1. [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:_currentRow inSection:0] animat ...

  7. struts2 框架处理流程

    struts2 框架处理流程 流程图如下: 注意:StrutsPrepareAndExecuteFilter替代了2.1.3以前的FilterDispatcher过滤器,使得在执行Action之前可以 ...

  8. 【Beta】Daily Scrum Meeting第七次

    1.任务进度 学号 已完成 接下去要做 502 发布任务到服务器 测试 509 将各api的处理逻辑放到类里面 让主api调用这些类 517 删除任务和教师的控件及逻辑 提交报课审核信息 530 完善 ...

  9. CSS垂直水平居中方法总结

    在布局的时候经常能用到居中,在此总结一下 html结构: <div class="wrap"> <div class="content"> ...

  10. 关于mysql ERROR 1045 (28000)错误的解决办法

    错误情景: 使用Navicat打开mysql的时候弹出错误框 错误代码: ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' ( ...