自绘CStatic控件不执行DrawItem函数的解决方法
程序员文章站
2022-05-28 12:47:58
...
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可加可不加。具体原因也不清楚,如果有人知道的话欢迎交流哦。