MFC 可以設定背景色、字型、字型顏色、透明背景的 Static 靜態文字控制元件
阿新 • • 發佈:2019-01-27
MFC庫裡沒有符合這個條件的控制元件,於是我自己寫了一個,初步測試有效。
注:可以設定透明背景,但還不能做到透明度設定(如50%透明度)
如果設定了背景色,就不保留透明背景
預設背景色是透明的
// 設定背景色(若clr為CLR_NONE,則背景透明) void SetBackgroundColor(COLORREF clr){m_clrBackground = clr;} // 設定文字前景色 void SetTextColor(COLORREF clr){m_clrText = clr;} // 設定文字字型 void SetFont(CString strFaceName, LONG nHeight);
如何使用:
1.先將RichStatic.h和RichStatic.cpp新增入工程2.對話方塊新增Static控制元件後,增加一個控制元件變數,型別設定為CRichStatic(或手動新增,在對話方塊類DoDataExchange中新增DDX_Control)
原始碼:
#pragma once // CRichStatic class CRichStatic : public CStatic { DECLARE_DYNAMIC(CRichStatic) public: CRichStatic(); virtual ~CRichStatic(); protected: afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg LRESULT OnSetText(WPARAM,LPARAM); DECLARE_MESSAGE_MAP() virtual void PreSubclassWindow(); private: COLORREF m_clrText; // 文字前景色 COLORREF m_clrBackground; // 文字背景色 CFont *m_pTextFont; // 文字字型 CBitmap m_Bmp; // 儲存背景用的點陣圖物件 BOOL m_selfCreated; public: // 設定背景色(若clr為CLR_NONE,則背景透明) void SetBackgroundColor(COLORREF clr){m_clrBackground = clr;} // 設定文字前景色 void SetTextColor(COLORREF clr){m_clrText = clr;} // 設定文字字型 void SetFont(CString strFaceName, LONG nHeight); public: virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/); };
// RichStatic.cpp : 實現檔案 // #include "stdafx.h" #include "RichStatic.h" // CRichStatic IMPLEMENT_DYNAMIC(CRichStatic, CStatic) CRichStatic::CRichStatic(): m_clrText(0), m_clrBackground(CLR_NONE), m_hFont(NULL), m_selfCreated(FALSE), m_xAlignment(X_LEFT), m_yAlignment(Y_TOP) { } CRichStatic::~CRichStatic() { if (m_selfCreated && m_hFont != NULL) { DeleteObject(m_hFont); // 若字型物件為物件自己建立並且不為NULL,則銷燬掉以釋放核心物件 } } BEGIN_MESSAGE_MAP(CRichStatic, CStatic) ON_MESSAGE(WM_SETTEXT,OnSetText) ON_WM_ERASEBKGND() END_MESSAGE_MAP() // CRichStatic 訊息處理程式 void CRichStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { if (m_clrBackground != CLR_NONE) // 若背景色不為CLR_NONE(CLR_NONE表示無背景色),則繪製背景 { RECT rect; GetWindowRect(&rect); CBrush brush; brush.CreateSolidBrush(m_clrBackground); ::SelectObject(lpDrawItemStruct->hDC, brush.m_hObject); // 設定畫刷顏色 ::SelectObject(lpDrawItemStruct->hDC, GetStockObject(NULL_PEN)); // 設定筆為空筆(不繪製邊界) Rectangle(lpDrawItemStruct->hDC, 0, 0,rect.right - rect.left, rect.bottom - rect.top); } CString strCaption; // 標題文字 GetWindowText(strCaption); if (m_hFont != NULL) { ::SelectObject(lpDrawItemStruct->hDC, m_hFont); } // 計算輸出字串的橫縱座標 int x = 0, y = 0; if (X_LEFT != m_xAlignment || Y_TOP != m_yAlignment) // 不是左對齊或不是頂對齊 { CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect crect; GetWindowRect(&crect); CSize size = pDC->GetTextExtent(strCaption); if (X_RIGHT == m_xAlignment) // 右對齊 { x = crect.Width() - size.cx; } else if (X_CENTER == m_xAlignment) // X居中對齊 { x = (crect.Width()- size.cx) / 2; } if (Y_BOTTOM == m_yAlignment) // 頂對齊 { y = crect.Height() - size.cy; } else if (Y_CENTER == m_yAlignment) // Y居中對齊 { y = (crect.Height() - size.cy) / 2; } } // 設定dc字串顏色 ::SetTextColor(lpDrawItemStruct->hDC, m_clrText); TextOut(lpDrawItemStruct->hDC, x, y, strCaption, strCaption.GetLength()); } void CRichStatic::PreSubclassWindow() { CStatic::PreSubclassWindow(); ModifyStyle(0, SS_OWNERDRAW); } void CRichStatic::SetFont(CString strFaceName, LONG nHeight) { if (m_selfCreated && m_hFont != NULL) { DeleteObject(m_hFont); // 若字型物件為物件自己建立並且不為NULL,則銷燬掉以釋放核心物件 } CFont cfont; LOGFONT lf; memset(&lf, 0, sizeof lf); // 清空LOGFONT結構體,之後對其賦值 lf.lfHeight = nHeight; _tcscpy_s(lf.lfFaceName, strFaceName.GetBuffer()); // 將字型名拷貝到LOGFONT結構體中 VERIFY(cfont.CreateFontIndirect(&lf)); // 建立新的字型 m_hFont = (HFONT)cfont.m_hObject; m_selfCreated = TRUE; // 標記字型為自己建立的 } void CRichStatic::SetFont(HFONT hFont) { if (m_selfCreated && m_hFont != NULL) { DeleteObject(m_hFont); // 若字型物件為物件自己建立並且不為NULL,則銷燬掉以釋放核心物件 } m_hFont = hFont; m_selfCreated = FALSE; // 標記字型非自己建立 } void CRichStatic::SetFont(const CFont *pFont) { if (m_selfCreated && m_hFont != NULL) { DeleteObject(m_hFont); // 若字型物件為物件自己建立並且不為NULL,則銷燬掉以釋放核心物件 } m_hFont = (HFONT)pFont->m_hObject; m_selfCreated = FALSE; // 標記字型非自己建立 } BOOL CRichStatic::OnEraseBkgnd(CDC* pDC) { // 當背景色為透明時,需要儲存與拷貝顯示主框的顯示區域 if (m_clrBackground == CLR_NONE) { if (m_Bmp.GetSafeHandle() == NULL) { CRect Rect; GetWindowRect(&Rect); CWnd *pParent = GetParent(); ASSERT(pParent); pParent->ScreenToClient(&Rect); // 將座標轉換為與主對話方塊相對應 // 拷貝對應區域主框顯示的內容 CDC *pDC = pParent->GetDC(); CDC MemDC; MemDC.CreateCompatibleDC(pDC); m_Bmp.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height()); CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp); MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY); MemDC.SelectObject(pOldBmp); MemDC.DeleteDC(); // 刪除記憶體DC,否則記憶體洩漏 pParent->ReleaseDC(pDC); } else // 將主框顯示的內容拷貝回去 { CRect Rect; GetClientRect(Rect); CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp); pDC->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY); MemDC.SelectObject(pOldBmp); MemDC.DeleteDC(); // 刪除記憶體DC,否則記憶體洩漏 } } return TRUE; } LRESULT CRichStatic::OnSetText(WPARAM wParam,LPARAM lParam) { LRESULT Result = Default(); Invalidate(); UpdateWindow(); return Result; }