1. 程式人生 > >MFC 可以設定背景色、字型、字型顏色、透明背景的 Static 靜態文字控制元件

MFC 可以設定背景色、字型、字型顏色、透明背景的 Static 靜態文字控制元件

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