Windows Gdi 应用-入门篇 (VC SDK)(2)
// 获取字体
CFont* pfont = GetFont();
CFont* def_font;
if (pfont)
def_font = cDC.SelectObject(pfont);//选入字体
CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(0xBD, 0xBA, 0xBD));
CPen* pOldPen = cDC.SelectObject(&pen);//选入画笔
CBrush br(0x00f2f2f2);
for ( int i = 0; i < m_nCount; i++ )
{
GetItemRect (i, rcItem);
//填充面板背景
cDC.FillRect(rcItem, &br);
rcItem.bottom--;
if(i == 0) rcItem.left += 2;
//对每个面板画圆角矩形
cDC.RoundRect(rcItem, CPoint(5, 5));
//画面板上的文字
UINT nNewStyle = GetPaneStyle(i);
//如果style为SBPS_DISABLED,则跳过不画
if ((nNewStyle & SBPS_DISABLED) != 0) continue;
CString text = GetPaneText(i);
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_TOP | DT_LEFT;
rcItem.left += 3;
rcItem.top += 3;
cDC.DrawText(text, rcItem, uFormat);
}
if (pfont)
cDC.SelectObject(def_font);//恢复字体
//画右下角小标志(这里画了六个小圆圈)
if (GetStyle() & SBARS_SIZEGRIP)
{
CRect rc;
GetClientRect(&rc);
rc.left = rcItem.right;
rc.right--;
rc.bottom--;
rc.left = rc.right - rc.Width() / 4;
rc.top = rc.bottom - rc.Width();
int w = rc.Width();
rc.top++;
rc.left++;
cDC.SelectObject(GetStockObject(GRAY_BRUSH));
cDC.Ellipse(&rc);
rc.OffsetRect(-w, -w);
cDC.Ellipse(&rc);
rc.OffsetRect(w, 0);
cDC.Ellipse(&rc);
rc.OffsetRect(-w, w);
cDC.Ellipse(&rc);
rc.OffsetRect(-w, 0);
cDC.Ellipse(&rc);
rc.OffsetRect(2 * w, -2 * w);
cDC.Ellipse(&rc);
}
cDC.SelectObject(pOldPen);//恢复画笔
}
上面的函数我们可以多次看到SelectObject的调用,这就是前面所说的绘图函数基本上都是有状态的。这个状态保存在HDC中,而SelectObject则设置HDC的状态。通常称为选入。至于注释中的恢复是怎么回事呢?这要从CPen CBrush CFont等等说起了,它们是对GDI对象的封装。GDI对象通过CreatePen CreateBrush CreateFont等等函数创建,返回一个HGDIOBJ。这些对象不使用的时候需要销毁,用DeleteObject函数,但是如果一个HGDIOBJ被选入到一个HDC中的时候,它就不能被销毁,这样就造成了GDI资源的泄漏。解决这一问题通常有两种做法:
- 上一篇:让程序只运行一个实例的方法
- 下一篇:弹出窗口杀手(下)