Font *pOldFont=pDC->SelectObject(&m_font);
pDC->TextOut(0,0,m_strFontName);
pDC->SelectObject(pOldFont);
}
按照上面的代码运行后,选择字体,显示 OK。再选择一次,按下OK 就会出现非法操作的错误的提示了。会出现这样的原因主要是因为第一次选择字体之后,m_font对象已经和某种字体资源关联了。当再一次选择字体之后,m_font对象试图与新的字体资源关联这时就出错了。要让对象与新的资源关联之前,应该先切断当前关联的资源。要释放先前的资源,可以用CGdiObject类(字体、画笔、画刷等都是派生于它)的DeleteObject函数来实现。该对象通过通过释放所有为Windows GDI对象所分配的资源,从而删除与CGdiObject对象相关联的Windows GDI对象,同时与CGdiObject对象相关的存储空间并不会受到影响。
想判断m_font对象是否已经关联,最简单的方法就是用CGdiObject对象的数据成员m_hObject来判断,该变量保存了与CGdiObject对象相关联的GDI资源句柄。代码就上面写的那个,把注释去掉就OK了。
下面再创建一个示例对话框,用来显示线型和线宽所生产的示例,首先是创建一个组框,ID改为 ID_SAMPLE 。对于编辑框控件来说,当用户在其上面进行对文本进行改变时,它会向其父窗口,即对话框发送一个EN_CHANGE通知信息。同样的,当用户单击单选按钮的时候,该按钮会向对话框发送一个BN_CLICKED信息。为了获取这两个通知信息,以反应出用户所做的选择,先生成这几个控件的响应函数,直接在相应空间上双击就可以了。我们在这四个响应函数中都添加一个让窗口失效的函数,然后在ONPAINT函数中去绘制线条。
view plain
void CSettingDlg::OnChangeLineWidth()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
Invalidate();
}
void CSettingDlg::OnRadio1()
{
Invalidate();
}
void CSettingDlg::OnRadio2()
{
Invalidate();
}
void CSettingDlg::OnRadio3()
{
Invalidate();
}
void CSettingDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
UpdateData();
CPen pen(m_nLineStyle,m_nLineWidth,m_clr);
dc.SelectObject(&pen);
CRect rect;
GetDlgItem(IDC_SAMPLE)->GetWindowRect(&rect);
ScreenToClient(&rect);
dc.MoveTo(rect.left+20,rect.top+rect.Height()/2);
dc.LineTo(rect.right-20,rect.top+rect.Height()/2);
// Do not call CDialog::OnPaint() for painting messages
}
在上面代码中,要记得添加 UpdateData函数,不然用户做出的改变,函数并不会更新。然后呢在获取组框的坐标时,用了 GetWinDowRect函数,如果直接用它获取到的坐标然后去相应地画线,那么在程序运行的时候是看不到线条的,因为该函数返回的坐标的相对于屏幕左上方为源点的坐标,而我们要获取的是相对于客户区左上角为远点的坐标,两个坐标相差较多,所以会看不到线,这时候,可以调用ScreenToClient函数来转换该坐标,然后就可以进行绘画了。
接下来介绍一下怎么改变对话框和控件的背景以及文本颜色,是通过响应WM_CTLCOLOR消息来实现的。
view plain
afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );
详情在MSDN中查询。该函数返回将被用来绘制控件背景的画刷的句柄。当一个子控件将要被绘制的时候,它都会向它的父窗口发送一个WM_CTLCOLOR消息来准备一个DC(即pDC参数),以便于使用正确的颜色来绘制控件。
首先为对话框添加一个画刷对象,并在构造函数中初始化它
view plain
m_brush.CreateSolidBrush(RGB(0,0,255));
要修改某个指定控件的背景和文本颜色的话,可以先用GetDlgCtrlID()这个函数来获取ID,然后再进行相应的操作。例如要是编辑框和组框的背景为蓝色,字体为红色,那么代码如下:
view plain
HBRUSH CSettingDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// TODO: Return a different brush if the default is not desired
if(pWnd->GetDlgCtrlID()==IDC_LINE_STYLE)
{
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkMode(TRANSPARENT);
return m_brush;
}
if(pWnd->GetDlgCtrlID()==IDC_LINE_WIDTH)
{
pDC->SetTextColor(RGB(255,0,0));
// pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(RGB(0,0,255));
return m_brush;
}
if(pWnd->GetDlgCtrlID()==IDC_TEXT)