MFC程序設計中經常需要在標準控件的基礎上進行自繪以便獲得更美觀的界面。最近在自繪CStatic控件時發現程序不執行DrawItem函數,於是將解決的方法記錄下來備用。本文的編程環境爲VS2008。
問題描述
首先通過VS2008的窗體編輯器在對話框中加入一個Picture Control控件,如下圖所示。
爲了實現Picture Control控件的自繪,自定義一個CStatic的子類CMyStatic,CMyStatic包含頭文件MyStatic.h和MyStatic.cpp兩個文件。
MyStatic.h源代碼如下:
#pragma once
// CMyStatic
class CMyStatic : public CStatic
{
DECLARE_DYNAMIC(CMyStatic)
public:
CMyStatic();
virtual ~CMyStatic();
protected:
virtual void PreSubclassWindow();
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
DECLARE_MESSAGE_MAP()
};
MyStatic.cpp源代碼如下:
// MyStatic.cpp : 實現文件
//
#include "stdafx.h"
#include "MyStatic.h"
// CMyStatic
IMPLEMENT_DYNAMIC(CMyStatic, CStatic)
CMyStatic::CMyStatic()
{
}
CMyStatic::~CMyStatic()
{
}
BEGIN_MESSAGE_MAP(CMyStatic, CStatic)
END_MESSAGE_MAP()
// CMyStatic 消息處理程序
void CMyStatic::PreSubclassWindow()
{
// TODO: 在此添加專用代碼和/或調用基類
ModifyStyle(0, SS_OWNERDRAW); // 使窗口自繪
CStatic::PreSubclassWindow();
}
void CMyStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代碼以繪製指定項
CRect rcClient;
GetClientRect(&rcClient);
// 繪製邊框
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
pDC->DrawEdge(rcClient, EDGE_RAISED, BF_RECT);
// 繪製準星
int nLength = min(rcClient.right, rcClient.bottom) / 20;
pDC->MoveTo(rcClient.right / 2, rcClient.bottom / 2 - nLength);
pDC->LineTo(rcClient.right / 2, rcClient.bottom / 2 + nLength);
pDC->MoveTo(rcClient.right / 2 - nLength, rcClient.bottom / 2);
pDC->LineTo(rcClient.right / 2 + nLength, rcClient.bottom / 2);
}
自定義CMyStatic控件在PreSubclassWindow()函數中通過ModifyStyle()函數爲控件增加SS_OWNERDRAW屬性以便於控件在創建時進行自繪。然後在DrawItem()函數中增加了自繪代碼。
爲了使剛纔在主對話框中添加的Picture Control控件能夠與CMyStatic相關聯,需要在對話框對應的頭文件中加入CMyStatic變量:
CMyStatic m_wndTest; // 在主對話框關聯的類中添加CMyStatic成員變量
同時在主對話框對應的源文件中將變量與控件進行關聯:
void CtestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_TEST, m_wndTest); // 關聯成員變量和靜態控件
}
接着運行程序發現主對話框中的Picture Control控件消失了。
解決方法
解決方法是看了CButtonST的代碼後找到的,這是一個比較有名的MFC第三方按鈕控件。只需要將PreSubclassWindow()中的ModifyStyle()函數修改爲如下即可:
ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW, SWP_FRAMECHANGED);
重新運行程序,自繪成功。
起作用的其實是第一個參數SS_TYPEMASK,第三個參數SWP_FRAMECHANGED可加可不加。具體原因也不清楚,如果有人知道的話歡迎交流哦。