对于控件的自绘,首先,就是派生一个基于CButton的类。而后自定义一个Create函数,DrawButton函数。重载presubclasswindow函数与DrawItem函数,最后在派生类中的OnCreate函数里面调用SetWindowRgn函数设定好我们控件的区域。这就是控件自绘时程序执行的几个重要的函数快。
下面,我们先看看实现:
下面先给出源码:
int CMybutton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CButton::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
SetWindowRgn(m_hRgn,true);
return 0;
}
void CMybutton::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0,BS_OWNERDRAW | BS_PUSHBUTTON);
CButton::PreSubclassWindow();
}
void CMybutton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
CDC* pDC = CDC::FromHandle(lpDrawItemStruct -> hDC);
CRect rect;
GetClientRect(rect);
DrawButton(pDC, &rect, lpDrawItemStruct -> itemState);
}
void CMybutton::DrawButton(CDC * pDC, CRect * pRect, UINT state)
{
// 创建内存设备
HRGN hBaseRgn = CreateRectRgn(0, 0, 0, 0);
HBRUSH hBrush;
COLORREF ltInner; //左上内存边框的颜色
ltInner = GetSysColor(COLOR_3DHILIGHT);
COLORREF rbOuter; //右下外侧边框的颜色
rbOuter = GetSysColor(COLOR_3DDKSHADOW);
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hRgn);
CString text;
GetWindowText(text);
CSize Extent=pDC->GetTextExtent(text);
CPoint pt=CPoint(m_CenterPoint.x-Extent.cx/2,m_CenterPoint.y-Extent.cy/2);
SetTextColor(pDC->GetSafeHdc(),RGB(255,0,0));
CombineRgn(hBaseRgn, hRgn, 0, RGN_COPY);
OffsetRgn(hBaseRgn, 1, 1);
CombineRgn(hBaseRgn, hRgn, hBaseRgn, RGN_DIFF);//得到左上框的部分并上色为红色
hBrush = CreateSolidBrush(ltInner);
FillRgn(*pDC, hBaseRgn, hBrush);
DeleteObject(hBrush);
CombineRgn(hBaseRgn, hRgn, 0, RGN_COPY);
OffsetRgn(hBaseRgn, -1, -1);
CombineRgn(hBaseRgn, hRgn, hBaseRgn, RGN_DIFF);//得到右上框的部分并上色为红色
hBrush = CreateSolidBrush(rbOuter);
FillRgn(*pDC, hBaseRgn, hBrush);
DeleteObject(hBrush);
if (state & ODS_SELECTED)
{
//向一个点中添加x,y坐标
pt.Offset(1,1);
}
TextOut(pDC->GetSafeHdc(), pt.x, pt.y, text, text.GetLength());
}
BOOL CMybutton::Create(LPCTSTR lpszCaption, DWORD dwStyle, const CPoint point, const HRGN hRgn, CWnd* pParentWnd, UINT nID)
{
// store region in member variable
DeleteObject(m_hRgn);
m_hRgn = CreateRectRgn(0, 0, 31, 31);
CRect box(0, 0, 0, 0);
if (m_hRgn != 0)
CombineRgn(m_hRgn, hRgn, 0, RGN_COPY);
// make sure that region bounding rect is located in (0, 0)
GetRgnBox(m_hRgn, &box);
// update position of region center for caption output
m_CenterPoint = CPoint(box.Width()/2,box.Height()/2);
box.OffsetRect(point);
return CButton::Create(lpszCaption, dwStyle, box, pParentWnd, nID);
}
以上是派生类中cpp文件的代码,其头文件的代码我就不啰嗦了。你自己也应该会!在Create函数中,主要就是计算出我们自绘的控件的区域的中点,以便,我们在这里输出文字。接下来就是presubclasswindow函数了,在这里,我们设定控件的样式为自绘属性。然后就会调用OnCreate函数块中的SetWindowRgn函数,设定好控件的区域,在此区域中你可以自绘控件。就是调用DrawItem函数了。在DrawItem函数里面,我们调用的是DrawButton函数,这个函数完成控件边框的绘制。其实主要就是
CombineRgn,FillRgn两函数的调用。同时我们利用OffsetRgn函数来实现控件边框的真实化。
好了,我分析的也差不多了。下面就是看你自己了。
这段时间,其实比较迷茫。毕竟大二了,现在学习很蒙。不过还是理清了思路。由于我是学C++的,因此,STL一定要学好,数据结构结合STL把这两块学好了,面试时也就有了底气。其次,我之前比较重视VC,一心搞软件开发。现在也放下来了。开发这一块不急,应该把技术学好,不说精通,也要熟练。因此,在大学面试之前,也就是大三结束时,多线程编程,网络编程以VC++为基础这两块要熟练。希望,我的学习路线对你有帮助。