类别:MFC学习
日期:2016年7月18日
标题:MFC 的基础画图,对话框中的button和edit control
编号:0
MFC:微软基础类库(Microsoft Foundation Classes)是一个微软公司提供的类库,以C++类的形式封装了Windows API以及其他的底层特性,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。
具体的简介参见孙鑫的MFC教程视频。评论说MFC是过时的产物,其结构十分复杂令人发指,今天初次接触感觉和描述不差多少,有点像android和Tkinter的结合,又繁琐又复杂。但是暂且学一学,为以后的
GUI编程打下基础吧(难的我都能会何况简单的hhh)以后可能还需要接触Qt,.net,C#,wxWidgets, WTL,GTK之类的,在这里先M起来。
MFC的基础画图:
1.首先是用于画图的接口:GDI(Graphics Device Interface) 是Window提供的图形设备接口。 GDI包括一套用于绘图的函数集(如Ellipse,Rectangle 等)和一套用于绘图的工具(对象),包括:设备环境类和绘图对象类(如Pen、Brush、Front、Bitmap等)。
2.这个接口的”对象“是DC(
设备环境):设备环境DC(
Device Context),是一个由GDI创建的虚拟逻辑设备,保存了绘图操作中一些共同需要设置的信息,如当前的画笔、画刷、字体、坐标、颜色和背景等绘图属性。 DC中的“设备”是指显示器、打印机等输出设备,绘图时,绘制操作通过DC进行间接处理,Windows会自动将DC所描述的结构映射到相应的物理设备上。 从根本上来说,DC是Windows内部使用的数据结构,它存储着向设备输出时说需要的信息,应用程序利用它定义图形对象及其属性,并实现应用程序、设备驱动程序和输出设备之间绘图命令的转换。
微软官方的说法:设备转换器通过 DeviceContext 类来使用设备模拟器框架的内置功能。DeviceContext 是一种帮助器类,可用于管理设备信息、标记信息和连接(如果支持此类)。
DC的类和子类:(反正看不懂咯...)
这几个类的各自的用途:
-
-
- CPaintDC:
CPaintDC用于图像的重绘(这里不是很确定)。当窗口的某个区域需要重绘时激发窗口重绘消息WM_PAINT,相应消息处理函数CWnd::OnPaint将被调用。CPaintDC一般只用于OnPaint函数中,在处理完窗口重绘后, CPaintDC对象的析构函数把WM_PAINT消息从消息队列中清除,避免不断地重绘操作。坐标原点(0,0)是客户区的左上角。 - CClientDC:
CClientDC用于特定窗口客户区(窗口中除边框、标题栏、菜单栏、状态栏外的中间部分)的输出,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC,不需要显式释放DC资源。一般用于响应非重绘消息(如键盘和鼠标消息)的绘图操作。坐标原点(0,0)是客户区的左上角。 - CWindowDC:
CWindowDC在整个应用程序窗口上画图,而CClientDC和CPaintDC只能在客户区绘制图形;除非要自己绘制窗口边框和按钮,否则一般不用它。坐标原点(0,0)是屏幕的左上角。 - 备注:
一般不构造CDC对象
在CWnd类的OnPaint函数中,定义CPaintDC对象
CPaintDC dc(this);
在CWnd类的其它函数中,定义CClientDC和CWindowDC的对象
CClientDC dc(this);
CWindowDC dc(this);
- CPaintDC:
-
CDC类里面的一些用于画图的成员函数:
Arc:绘制一段弧
Chord:绘制弦形
Ellipse:绘制椭圆或圆
MoveTo:将当前位置移动到指定位置
LineTo:从当前位置到指定位置画一条直线(不包括当前的点)
Polyline:画连接指定点的折线段
PolyBezler:根据两个端点和两个控制点画贝塞尔曲线
Pie:画冰块
Polygon:根据两个或两个以上的顶点绘制一个多边形
Rectangle:根据指定的左上角和右下角坐标绘制一个矩形
RoundRect:画圆角矩形
SetPixel:画一个点
CDC一些画图用的类:
CPoint:描述一个点,封装Windows结构POINT 构造函数: CPoint(int initX,int initY); //点坐标
CRect:描述一个矩形,封装Windows结构RECT 构造函数: CRect(int l,int t,int r,int b);//左上右下顶点坐标
CSize:描述一个矩形区域的大小,封装Windows结构SIZE 构造函数: CSize(int initCX,initCY); //矩形的长度和宽度
CString:处理字符串 成员函数: Empty() //Forces a string to have 0 length.
GetAt() //Returns the character at a given position.
SetAt() //Sets a character at a given position.
CDC的文本显示:
CDC类的成员函数TextOut(),负责绘制文本,SetTextColor和SetBkColor可以设置输出文本的前景色和背景色:(缺省的前景色为黑色,背景色空)
void OnDraw(CDC* pDC)
{
pDC->TextOut(10, 10, "Test text"); //pDC->TextOut(x,y,m); x,y:输出位置的x坐标,y坐标 。 m:输出的字符串
pDC->SetTextColor(RGB(0, 128, 0)); //设置字符串颜色
pDC->TextOut(10, 30, "Test text");
}
编码问题(Unicode,ASCII)可能造成编译不通过 解决办法:
1:string -> _T(string) 解决办法
2:更改字符集
这一段是什么意思,看不懂
3.用于画图的函数是OnDraw(CDC *pDC)和OnPaint():
1.OnDraw(CDC *pDC):OnDraw是CView类的成员函数,不响应消息。
2.OnPaint():OnPaint是CWnd类的成员函数,相应WM_PAINT消息。
3.OnPaint函数会调用了CView::OnDraw函数。因而一般在OnDraw函数内添加绘图代码,完成绘图任务
4.例程:
//画一个五环
void CtestView::OnDraw(CDC* pDC)
{
CtestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDC=GetDC();
/*GetDC 函数:获取设备指针
函数功能描述:该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文的句柄.以后可以在GDI函数中用该句柄绘图.
这个对象就是用GetDC();函数创建的,我写个简单的源代码给你看,有个类名叫CDC,
CDC * GetDC(){
CDC *objDC = new CDC;
return objDC ;
}
当然实际的代码不是这样的。 */
CPen pen;
/*CPen画笔是绘图的基本工具,在MFC中画笔是CPen类的对象,它用来在DC上完成绘制线条的任务。初始时会有默认形态,但是可以根据个人喜好进行程序的编写从而改变其形态。*/
pen.CreatePen(PS_SOLID,2,RGB(0,0,255));
/*函数原型: CPen(Int style,int width ,COLORREF color); style:画笔的样式
width:画笔的宽度
color:画笔的颜色(颜色用RGB值来描述) */ [1]
CPen* oldpen=pDC->SelectObject(&pen);
/*DC选中画笔才能在设备上作画*/
pDC->SetBkMode(TRANSPARENT);
/*MFC里面封装有CDC类,CDC::SetBkMode()函数的第二个参数可以选择OPAQUE和TRANSPARENT。
输出的字符串时,发现存在背景色,这样的输出是破坏背景的。那需要使用什么方法来保持背景不变,而又能输出红色的字符串呢?比如按钮的文字颜色是黑色的,而背景是灰色的。这就需要使用SetBkMode函数来设置DrawText函数的输出方式,显示设备共有两种输出方式:OPAQUE和TRANSPARENT。
OPAQUE的方式是用当前背景的画刷的颜色输出显示文字的背景,而TRANSPARENT是使用透明的输出,也就是文字的背景是不改变的。
对透明的理解:在窗体或控件输出的字符串或图形是有背景色的。而窗体或控件也是有背景色的。这两种背景色一般是不同的, 这样输出图形或字符串时,两种背景(窗体或控件的背景色、符串或图形的背景色)重叠在一起了,影响美观,为了不让这两种背景重叠,可以设置背景模式为TRANSPARENT(透明的),即让输出的字符串或图形的背景色不可见。可以这样理解:把输出的字符串或图形的背景色看成是一物体,窗体或控件看成另一物体,字符串或图形在窗体或控件前面挡住窗体或控件了(因为输出 的字符串或图形是画在窗体或控件上的,所以可以这么类比),但是透过字符串或图形能看到窗体或控件。即字符串或图形的背 景色所代表的物体是透明的。*/
pDC->SelectStockObject(NULL_BRUSH);
//选择空画刷
pDC->SetTextColor(RGB(255,0,0));
//设置文字颜色
CRect rc(20,20,120,120);
//构造一个矩形区域
/*
类CRect是对Windows结构RECT的封装,凡是能用RECT结构的地方都可以用CRect代替。
结构RECT表示一个矩形的位置和尺寸,其定义为:
typedef struct tagRECT{
LONG left; //左上角x坐标
LONG top; //左上角y坐标
LONG right; //右下角x坐标
LONG bottom; //右下角y坐标
} RECT;
由于CRect提供了一些成员函数和重载运算符,使得CRect的操作更加方便。
CRect的构造函数 CRect有如下6个构造函数:
CRect( );
CRect( int l, int t, int r, int b );
CRect( const RECT& srcRect ); //拷贝构造函数,
SrcRect是一个RECT结构的引用
CRect( LPCRECT lpSrcRect ); //
LpSrcRect是一个指向RECT结构的指针 LPCRECT是个什么...
CRect( POINT point, SIZE size ); //
Point指定矩形的左上角顶点的坐标,size指定矩形的长度和宽度
CRect( POINT topLeft, POINT bottomRight ); //
topLeft指定矩形的左上角顶点的坐标,bottomRight指定矩形的右下角顶点的坐标
说明:分别以不同的方式构造CRect对象
*/
pDC->Ellipse(&rc);
//在矩形内画一个椭圆(填满)
pDC->SelectObject(oldpen);
CRect rc2(80,20,180,120);
pDC->Ellipse(&rc2);
CPen pen2;
pen2.CreatePen(PS_SOLID,2,RGB(255,0,0));
pDC->SelectObject(&pen2);
CRect rc3(140,20,240,120);
pDC->Ellipse(&rc3);
CPen pen3;
pen3.CreatePen(PS_SOLID,2,RGB(255,255,0));
pDC->SelectObject(&pen3);
CRect rc4(50,80,150,180);
pDC->Ellipse(&rc4);
CPen pen4;
pen4.CreatePen(PS_SOLID,2,RGB(0,255,0));
pDC->SelectObject(&pen4);
CRect rc5(110,80,210,180);
pDC->Ellipse(&rc5);
ReleaseDC(pDC);
}
[1]:画笔风格的参数:
PS_GEOMETRIC 创建一个几何画笔
PS_COSMETIC 创建一个装饰画笔
PS_ALTERNATE 创建一个设置其他像素的画笔
PS_USERSTYLE 创建一个使用由用户提供的风格矩阵的画笔
PS_ENDCAP_ROUND 尾帽为圆形的
PS_ENDCAP_SQUARE 尾帽为方形的
PS_ENDCAP_FLAT 尾帽为平坦的
PS_JOIN_BEVEL 成尖角连接
PS_JOIN_MITET 通过setMiterLimit函数设置的当前极限值范围内斜接;否则,成尖角连接
PS_JOIN_ROUND 成圆角连接
存留问题:
1.在使用CPen之前使用CBrush的话CPen的效果会被CBrush覆盖,不是很明白这里的机制。
2.使用CDC来使用selectObject的时候的格式还不是很明白,为什么通常的做法是设置一个指向变量(如CPen)的指针然后再用pDC->SelectObject(*指针);这样来使用?
5.有关清屏的方法:(还不是很懂)
void CTestView::OnClean()
{ CDC *pDC = GetDC(); CRect rc; GetClientRect(&rc); pDC->FillSolidRect(&rc, RGB(255, 255, 255)); ReleaseDC(pDC);
}
|
MFC的对话框程序:
1.edit control:
通过添加和edit control相关联的Value变量来获取edit control中的内容,而这个与edit control相关联的变量在同一个窗口的其他组件的函数中可以直接引用。
两个关键的函数:UpdateData(TRUE); 用窗体上控件中的内容来更新和控件相关连的变量的值(只能更新value类型的变量)
UpdateData(FALSE); 将控件的关联变量的值传给控件并改变控件状态
可以通过改变edit control的属性来设置其内容只能输入数字或者字符或者输入之后只显示*(密码框)或者只显示大写(小写)
2.button:这个组件和一般的button差不多。
//