Static control 透明,重影,長度問題

來源:互聯網
上載者:User

 

做MFC編程,Static控制項是會經常用到的了,而使Static控制項背景透明,以及改變文本的內容、字型、顏色等屬性,都是會比較容易碰到的情況。

王道做法當然是繼承CStatic然後重載OnPaint(),完全自己來畫,這樣能夠獲得最大的靈活性,但就是比較麻煩,像我這種比較懶的,就更喜歡用下面的懶方法了。

同樣建立一個CStatic的衍生類別,處理父視窗的反射訊息WM_CTLCOLOR,即添加HBRUSH CtlColor(CDC *pDC, UINT nCtlColor)這個訊息映射函數。注意,不是HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)!我也不知道具體原理,反正我用後者從來沒成功過,甚至程式都不會運行到裡面。。。

其實還有一個方法,就是處理父視窗的OnCtlColor(),更簡單一點,但是不符合封裝的原則,所以這裡就不提了。

C++代碼
  1. HBRUSH CSample::CtlColor(CDC* pDC,
    UINT nCtlColor)
  2. {
  3. // TODO: Change any attributes of the DC here
  4. pDC->SetBkMode(TRANSPARENT); // 設定透明背景
  5. pDC->SetTextColor(RGB(0, 0, 255)); // 設定文本顏色
  6. // TODO: Return a non-NULL brush if the parent's handler should not be called
  7. return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
    // 返回透明畫刷
  8. }

通過上述代碼,就可以得到彩色的文本以及透明的背景,但是,還存在一個問題,當該Static控制項的常值內容或者屬性,在運行過程中發生變化的時候,由於背景一直沒有擦除(為了實現透明),會出現重影,導致文本模糊成一團。

解決方案是,讓父視窗進行重繪更新,對,不要看錯了,是控制項所屬的父視窗,而不是控制項本身,讓控制項本身重繪也不會解決問題的,同樣我也不太清楚原理。。。

這裡還會引出一個問題,如果重繪整個父視窗,由於GDI並不內嵌雙緩衝,勢必造成嚴重的閃爍問題,解決辦法當然是只讓父視窗重繪控制項所佔的部分,其他部分不進行重繪,代碼如下:

C++代碼
  1. void CSample::SetText(const
    TCHAR *pszText)
  2. {
  3. this->SetWindowText(pszText);
  4. RECT stRect;
  5. // 擷取控制項位置
  6. this->GetWindowRect(&stRect);
  7. // 重要!調用父視窗的S2C函數進行座標轉換
  8. this->GetParent()->ScreenToClient(&stRect);
  9. // 重繪控制項所在地區,在這裡擦除背景
  10. this->GetParent()->InvalidateRect(&stRect,
    true);
  11. }

這樣就能夠實現動態改變文字屬性而不出現重影現象,注意這裡調用了父視窗的ScreenToClient()函數來進行座標的轉換,調用控制項本身的S2C函數的話,得到的座標無法用來進行下一步的重繪工作。

現在還有一個比較隱形問題,就是文本字串的長度,如果新的字串的長度比原來的長,而之前拖放Static控制項長度又不足的時候,就會造成超出的部分無法顯示,當然你大可以在拖放的時候就盡量弄得長一點,但是如果能隨著常值內容而自動調整控制項長度,那不是會好得多麼。

為了實現這樣的效果,上面的代碼要修改如下:

C++代碼
  1. void CSample::SetText(const
    TCHAR *pszText)
  2. {
  3. CDC *pDC = this->GetDC();
  4. // 擷取文本在當前繪圖環境下所佔的寬度和高度
  5. CSize clSize = pDC->GetTextExtent(pszText, _tcslen(pszText));
  6. RECT stRect;
  7. // 擷取控制項當前矩形地區
  8. this->GetWindowRect(&stRect);
  9. // 調整寬度為新文本所佔寬度
  10. stRect.right = stRect.left + clSize.cx;
  11. // 重要!調用父視窗S2C函數轉換座標
  12. this->GetParent()->ScreenToClient(&stRect);
  13. // 調整控制項大小以適應新文本
  14. this->MoveWindow(&stRect);
  15. // 重繪控制項以避免重影
  16. this->GetWindowRect(&stRect);
  17. this->GetParent()->ScreenToClient(&stRect);
  18. this->GetParent()->InvalidateRect(&stRect,
    true);
  19. }

同樣,這裡也是調用父視窗的S2C函數,這樣得到的座標才能正確使用。代碼經過上述修改,就實現了控制項隨文本動態調整寬度的效果。

以上只是實現Static背景透明、更改文本顏色以及動態調整控制項大小的簡單示範,實際的應用中可能還需要考慮很多情況,適當修改代碼,但基本原理是不變的。當然要獲得最大的靈活性,還是得自己來繪製了 - -

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.