10.3颜⾊对话框
MFC为我们提供了⼀个类:CColorDialog类,可以很⽅便创建⼀个颜⾊对话框。
CColorDialog类构造函数:
CColorDialog( COLORREF clrInit =0, DWORD dwFlags =0, CWnd* pParentWnd =NULL);
第⼀个参数指定默认颜⾊选择,默认是⿊⾊。
第⼆个参数来设置对话框的功能和它的外观。
第三个参数指向⽗窗⼝或者拥有者窗⼝指针。
在绘图⼦菜单下添加颜⾊菜单项,ID设置为IDM_COLOR,在视类中为该菜单项添加命令消息响应函数。
void CGraphicView::OnColor()
{
// TODO: Add your command handler code here
CColorDialog dlg;
dlg.DoModal();
}
运⾏如图。默认选中颜⾊为⿊⾊。
下⼀步要做的就是将⽤户选择的颜⾊保存下来。CColorDialog类有⼀个CHOOSECOLOR结构体类型的成员变量:m_cc。
typedef struct{// cc
DWORD lStructSize;
HWND hwndOwner;
HWND hInstance;
COLORREF rgbResult;
COLORREF* lpCustColors;
DWORD Flags;
LPARAM lCustData;
沈阳特产LPCCHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} CHOOSECOLOR;
当⽤户单击颜⾊对话框上⾯的OK之后,颜⾊就保存到rgbResult变量中了。
接下来为视类添加⼀个COLORREF类型的私有成员变量:m_clr,,并在视类的构造函数中初始化为红⾊。
void CGraphicView::OnColor()
{
// TODO: Add your command handler code here
CColorDialog dlg;
if(IDOK==dlg.DoModal())
{
m_clr=dlg.bResult;
}
}
写英文在之前创建画笔以及画点中,将代码修改为:
CPen pen(m_nLineStyle,m_nLineWidth,m_clr);
dc.SetPixel(point,m_clr);
运⾏,但是再次打开颜⾊对话框时,默认的选择仍然还是⿊⾊。
因此利⽤之前的⽅法进⾏修改:
void CGraphicView::OnColor()
{
// TODO: Add your command handler code here
CColorDialog dlg;
dlg.bResult=m_clr;
if(IDOK==dlg.DoModal())
{
m_clr=dlg.bResult;
}
}
但是运⾏,发现问题并没有解决,实际上要想设置颜⾊对话框初始选择的颜⾊,需要设计对话框的CC_RGBINIT标记。dlg.bResult=m_clr;后⾯加:
dlg.m_cc.Flags|=CC_RGBINIT;
将CC_RGBINIT与Flags先前的标记组合起来。
dlg.m_cc.Flags|=CC_RGBINIT|CC_FULLOPEN;
运⾏程序,就会发现颜⾊对话框处于选中颜⾊的阶段并且完全展开。如图。
10.4字体对话框
与颜⾊对话框⼀样,字体对话框创建也很简单。MFC提供了⼀个相应的类:CFontDialog。
CFontDialog类的构造函数:
CFontDialog( LPLOGFONT lplfInitial =NULL, DWORD dwFlags = CF_EFFECTS | CF_SCREENFON
TS, CDC* pdcPrinter =NULL, CWnd* pParentWnd =N ULL);
第⼀个参数允许⽤户设置⼀些字体的特征;第⼆个参数设置与字体相关的标记;第三个参数是打印上下⽂的指针;第四个参数是字体对话框⽗窗⼝的指针。
在绘图⼦菜单中添加⼀个字体的菜单项,ID为IDM_FONT,接着在视类中为该菜单项添加命令消息响应函数。
void CGraphicView::OnFont()
{
// TODO: Add your command handler code here
CFontDialog dlg;
dlg.DoModal();
}
当⽤户通过字体对话框选择某种字体后,应该将其保存起来。CFontDialog类有⼀个CHOOSEFONT
张建武结构体的数据成员:m_cf。
typedef struct{// cf
DWORD lStructSize;
HWND hwndOwner;
HDC hDC;
LPLOGFONT lpLogFont;
INT iPointSize;
DWORD Flags;
DWORD rgbColors;
LPARAM lCustData;
LPCFHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
HINSTANCE hInstance;
LPTSTR lpszStyle;
WORD nFontType;
WORD ___MISSING_ALIGNMENT__;
INT nSizeMin;
INT nSizeMax;
} CHOOSEFONT;
陶侃lpLogFont指向逻辑字体(LOGFONT)的指针。
typedef struct tagLOGFONT {// lf
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
张飞性格BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT;
lfFaceName存放的是字体名称。
⾸先⽤CFont类构造⼀个字体对象,然后利⽤CFont类的CreateFontIndirect成员函数根据指定特征的逻辑字体(LOGFONT)来初始化这个字体对象。
为了保存⽤户选择的字体,为视类增加⼀个CFont成员变量:m_font,再增加⼀个CString类型的成员变量:m_strFontName,⽤来保存所选字体的名称,并在视类构造函数中初始化为空。
void CGraphicView::OnFont()
{
// TODO: Add your command handler code here
CFontDialog dlg;
if(IDOK==dlg.DoModal())
{
m_font.CreateFontIndirect(dlg.m_cf.lpLogFont);
m_strFontName=dlg.m_cf.lpLogFont->lfFaceName;
}
Invalidate();
}
接下来将⽤户选择的字体显⽰出来,可以在视类OnDraw函数中实现。在OnFont函数最后调⽤Invalidate函数让窗⼝⽆效,当下⼀次发⽣WM_PAINT消息时,窗⼝就可以重绘。
void CGraphicView::OnDraw(CDC* pDC)
{
CGraphicDoc* pDoc =GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CFont *pOldFont=pDC->SelectObject(&m_font);
pDC->TextOut(0,0,m_strFontName);
pDC->SelectObject(pOldFont);
}
但是再次选择绘图字体菜单项时,程序就会出现⾮法操作。原因就是如果⼀个对象已经和⼀个字体资源相关联了,⾸先得切断这种关联,释放该字体资源,才能与新资源相关联。
晚上泡的茶第二天能喝吗要释放先前的资源,可以利⽤CGdiObject类(CPen类,CFon类,CBitmap类,CBrush类都派⽣于该类)的DeleteObject成员函数来实现。
如果想判断m_font对象是否与某个字体资源相关联,可以利⽤CGdiObject类对象的数据成员m_hObject来判断,该变量保存了与CGdiObject对象相关联的Windows GDI资源的句柄。土豆色拉
void CGraphicView::OnFont()
{
// TODO: Add your command handler code here
CFontDialog dlg;
if(IDOK==dlg.DoModal())
告诉你个秘密{
if(m_font.m_hObject)
m_font.DeleteObject();
m_font.CreateFontIndirect(dlg.m_cf.lpLogFont);
m_strFontName=dlg.m_cf.lpLogFont->lfFaceName;
}
Invalidate();
}
运⾏如图,⼀切正常。