网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
源代码在线查看: 10.3 颜色对话框.txt
10.3 颜色对话框
颜色对话框类似于Windows提供的画图程序中,选择【颜色\编辑颜色...】菜单项后出现的对话框,
如图 10.12所示。利用颜色对话框,可以让用户选择一种颜色,程序随后按照此颜色创建绘图所需
的画笔。
如图 10.12所示的颜色对话框看起来比较复杂。实际上, MFC为我们提供了一个类: CColorDialog,
可以很方便地创建这样的一个颜色对话框。该类的派生层次结构如图 10.13所示。由此,可以知道
颜色对话框也是一个对话框。
" ‘ I 373
第10
.盯
;"颜色基本'色咂}
自定义'色电):
广广广「广广广广
「rrrr广广广
| 穆.)i;自定义MtM!.仰自~ I 融|纯色也】础ω~.(\!):~
黯 l一旦」事蛐自定增ê.f&I I
图 10.12画图程序提供的颜色对话框
图 10.13 CColorDiaJog类的派生层次结构图
CColorDialog类的构造方法如下所示:
CColorDialog(clrlnit = 0 , DWORD dwFlags = 0 , CWnd* pParentWnd = NULL);
该构造函数具有三个参数,含义分别如下所述:
. clrlnit
指定默认的颜色选择。默认是黑色。
. dwFlags
指定一组标记,用来定制颜色对话框的功能和它的外观。
. pP缸entWnd指向颜色对话框父窗口或拥有者窗口的指针。为了在 Graphic程序中增加颜色对话框
的显示,首先为该程序增加一个菜单项,当用
户选择此菜单项时,程序将显示颜色对话框。将这个新菜单项放置在己有的"绘图"子菜单下,并将
其E设置为IDM_COLOR, Caption设置为颜色。接着为其增加一个命令响应,井选择 CGraphicView
类对此菜单项命令做出响应。然后在此响应函数中添加显示颜色对话框的代码,结果如例 10-12所
示。
~IJ 10-12
void CGraphicView: :OnColor()
CColorDialog dlg ;
dlg . DoModal() ;
运行 Graphic程序,选择【绘图飞颜色】菜单项,即可以看到出现了一个颜色对话框,并且可以看
到在该对话框左边颜色块的黑色块上有一个黑色的边框,说明默认选择的是黑色,这和我们刚才在
画图程序中所看到的颜色对话框是一样的。
下一步要做的事情就是应该将用户选择的颜色保存下来。 CColorDialog类有一个 CHOOSECOLOR结构
体类型的成员变量 : ID_cc oCHOOSECOLOR结构体的定义如例 10-13所示。
例 10-13
typedef struct { DWORD lStructSize; HWND hwndOwner ;
HWNDh工 nstance ;
COLORREF rgbResult ;
COLORREF *lpCustColors;
DWORD Flags ;
LPARAM lCustData;
LPCCHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} CHOOSECOLOR,女 LPCHOOSECOLOR ;
当用户单击颜色对话框上的【 OK】按钮后,这个结构体中的 rgbResult变量就保存了用户选择的颜
色。因此,在程序中通过这个变量就可以获得用户选择的颜色。.
在Graphic程序中,为了保存用户选择的颜色,为 CGraphicView类再增加一个 COLORREF类型的私有
成员变量 : ffi_clr,井在 CGraphicView类的构造函数中将其初始化为红色,即添加下面这行代码:
ffi_clr=RGB(255 , O, O) ;
然后在 OnColor函数中进行判断,如果用户单击的是【 OK】按钮,那么就将用户选择的颜色保存下
来。修改后的代码如例 10-14所示。
例 10-14
户」在
void CGraphicView: :OnColor()
--TIA -l=ld dD14o
ci{ DK αdqd
O(ODroa=o---gM;o
d a 14
L
m_clr=dlg .m_cc . rgbResult;
当用户选择颜色后,随后进行的绘图操作都应用此颜色来绘制,也就说应该按此颜色创建绘图用的
画笔。所以,修改 CGraphicView类 OnLButtonUp函数中己有的创建画笔的代码,将用户当前选择的
颜色(即 ffi clr变量)传递给 CPen构造函数的第三个参数。另外,还需要修改该函数中绘制点图形
的代码,应该用用户当前选择的颜色来设置像素点的
"‘I 375
第10
颜色,修改后的OnLButtonUp代码如例 10-15所示,其中加灰的代码为进行了修改的代码。
例 10-15
void CGraphicView :: OnLButtonUp(UINT nFlags , CPoint poi口t)
/ / TODO : Add your message handler code here and/ or call default CClientDC dc(this); CPen
pen(m_nLineStyle,m_nLineWidth, m_clr); dc . SelectObject(&pen) ; CBrush *pBrush=CBrush: :
FromHandle( (HBRUSH)GetStockObject(NULL_BRUSH)); dc . SelectObject(pBrush);
switch(m_nOraνI'ype)
{
case 1:
dc.SetPixel(point,m_c工r) ;
break;
case 2:
dc . MoveTo(m-ptOrigin);
dc . LineTo(point) ;
break;
case 3:
dc . Rectangle(CRect(m-ptOrigin,point)) ;
break;
case 4:
dc . Ellipse(CRect(m-ptOrigin , point)) ;
break;
}
CView: :OnLButtonUp(nFlags , point);
运行Graphic程序,单击【绘图飞颜色】菜单项,打开颜色对话框,选择某种颜色,然后进行绘图操
作,可以发现这时所绘制的图形边框的颜色就是刚才选择的颜色。
但是当再次打开颜色对话框时,它默认选择的仍是黑色,而不是刚才选择的颜色。这时,我们自然
就会想到应该像上面的处理一样,将用户选择的颜色(即 CGraphicView类的 mJlr变量保存的颜色
值〉设置回颜色对话框对象,因此,修改 CGraphicView类的 OnColor函数,添加如例10-16所示代
码中加灰显示的那行代码。
例10-16
vo工d CGraph工cView: :OnColor ( )
CColorDialog dlg; dlg .m_cc .rgbResult=m_clr;
if(工OOK==dlg .DoModal())
m_clr=dlg.m_cc . rgbResult;
376 I ~~~
VC++深λ详解
再次运行Graphic程序,先选择一种颜色,然后进行图形的绘制,可是当再次打开颜色对话框时,将
会发现结果仍不对,默认选中的颜色仍是黑色。
实际上,如果想要设置颜色对话框初始选择的颜色,则需要设置该对话框的 CC RGBINIT标记,这个
标记可以在创建颜色对话框时通过其构造函数的第二个参数来设置,也可以在该对话框创建之后,
设置其m cc成员变量的Flags成员。这里,采用后一种方法,修改CGraphicView类的OnColor函数,
添加如例 10-17所示代码中加灰显示的那行代码。
例 10-17
void CGraphicView: :OnColor()
CCol orDialog dlg ;
dlg.m_cc.Flags=CC_RGB工NIT;
dlg .m_cc .rgbResult=m_clr;
if (IDOK==dlg.DoModal())
.
m_clr=dlg.m_cc .rgbResult;
再次运行Graphic程序,选择【给图\颜色】菜单项,出现一个非法操作提示对话框,如图 10.14所
示。[电a牛二~二itLTJDEbwiibmry j咽··E
Debt啕Asser蚀111 Failed!
何咱酬:O:\VC++濒入·理I\CHAPTERI叭,G;-制削减明I\G;-砸在剧@同e: clgclr.cpp Lir晴:73
For时ormat阳、 onhc酬YOtWPI'(9'am can CeI ose eI\眉锢,蚀m faiUe,饵"世回响剧aI C++doan
帽、tatb.on眉目!f1:s.
{防@笃笃 Retryto由战唱。胃部lPkat阳、〉
旦巳J_旦ι」
图 10.14非法操作提示对话框
实际上,当在创建CColorDialog对象dlg时,它的数据成员m cc中的F1ags成员已经具有了一些初始
的默认标记。当我们将CC RGBINIT标记直接赋给Flags成员时,就相当于将F1ags成员初始默认的标
记都去掉了。
如果读者认为这种解释不太可信,可以构造一个 CString对象,然后利用该对象的 Fonnat函数将初
始的F1ags成员的值格式化,并用 MessageBox显示输出,记住输出的数值。然后在VC++编辑窗口中,
在CC RGBINIT符号上单击鼠标右键,从弹出的快捷菜单中选择【GoToDe白创onOfCC RGB时π】菜单项,
定位到该符号的定义处 CCOMMDLG.H文件中),可以看到F1ags成员可能取的值 (代码如例 10-18所
示,并且F1ags的取值可以通过或操作对这些数值进行组合),然后与刚才MessageBox显示的数值比
对一下,就可以
‘...... 1377
第 10
知道Flags的取值了。
11IJ 10-18
#define CC RGBINIT OxOOOOOOOl
#define CC FULLOPEN Ox00000002
#define CC PREVENTFULLOPEN Ox00000004
#define CC SHOWHELP Ox00000008
#define CC_ENABLEHOOK Ox00000010
#define CC ENABLETEMPLATE Ox00000020
#define CC ENABLETEMPLATEHANDLE Ox00000040 #if(WINVER >= Ox0400) #define CC SOL工 DCOLOR
Ox00000080 #define CC ANYCOLOR Ox00000100 #endif /* WINVER >= Ox0400 */
为了进一步验证 Flags的初始取值,可以根据得到的数值,再换成相应的符号值,井赋给Flags成员,
再运行程序,看看颜色对话框是否能够正确地显示就可以验证这一点了。
小技巧:在 VC I I开发环境中,同时按下 Ctrl键和 Tab键,就可以切换到
E
下一个窗口。
.
通过上述分析,可以知道,这里不能给 Flags标记直接赋值,应利用或操作 (1)将 CC RGBINIT标记
与 Flags先前的标记组合起来,即修改后的代码如下所示 :
dlg.m_cc.Flags 1= CC_RGBIN工 T;
再次运行 Graphic程序,打开颜色对话框,可以看到初始选择的就是红色。接着,选择其他某种颜
色并关闭该对话框。然后再打开颜色对话框,这时就可以看到现在选中的是先前选择的颜色了。
另外. Flags成员的取值还有一个常用标记: CC_FULLOPEN.该标记的作用就是让颜色对话框完全展
开。将上面那条代码修改为:
dlg.m_cc.Flags 1= CC_RGBINIT 1 CC_FULLOPEN;
再次运行 Graphic程序,打开颜色对话框,这时可以看到这个颜色对话框处于完全展开的状态。