2013 duilib入門簡明教程 -- 部分bug (11)

 1、WindowImplBase的bug
    在第8個教程 【2013 duilib入門簡明教程 -- 完整的自繪標題欄(8)】中,能夠發現窗口最大化以後有兩個問題,
    一、最大化按鈕的樣式仍是沒變 ,正確的樣式應該是這樣的
    二、再次點擊最大化按鈕,不能還原到正常大小。
    這個是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);
        }
    }

 

2、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

     不過我喜歡更簡短的定義:html

#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
}

 

 

 
相關文章
相關標籤/搜索