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


 一、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
}

 

 

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM