当前位置:文档之家› MFC编程基础 2 文档_视图结构应用程序

MFC编程基础 2 文档_视图结构应用程序

MFC编程基础 2 文档_视图结构应用程序
MFC编程基础 2 文档_视图结构应用程序

第2章文档/视图结构应用程序

1. 文档/视图结构的思想是将数据的管理与显示分离,其中文档用于管理应用程序的数据,而视图是用户界面,用于显示、打印文档中的数据,并管理与用户的交互。

2. SDI具有文档/视图结构的应用程序框架,该框架包括应用程序类、窗口框架类、文档类和视图类,编程的任务是在文档类和视图类中添加适当的代码。其中文档类中一个重要的成员函数是OnNewDocument(),用户在此添加代码完成对数据的初始化;而视图类中最重要的成员函数是OnDraw(),通过在该函数中添加代码实现窗口内容的输出。

3. 通过介绍几种SDI结构的典型应用程序来了解其结构及设计方法,典型应用包括:

?利用画笔、画刷等工具及位图处理的方法实现文字和图形的输出。

?利用定时器控件制作动画程序。

?对鼠标和键盘进行编程的基本方法。

?文件、字体、颜色等几种通用对话框的使用方法及自定义对话框的设计、调用方法。

?菜单的设计方法。

2.1 文档/视图结构

SDI 应用程序由AppWizard 创建好后,即使没有编写一行代码,仍然可以运行,并且具有一个标准Windows应用程序所需要的组成成份,程序员的工作就是往这个框架添加必要的代码。以下通过一个简单实例说明文档/视图结构应用程序的创建过程。

【例2.1】创建一个如图所示的应用程序,在窗口中显示一个矩形框,框中显示“同舟共济自强不息”。

假定本例的工程名为TEST ,程序创建过程如下:

(1)利用AppWizard 创建一个SDI 应用程序框架。

(2)文档类是存放数据的主要地方,本例在其中说明一个存放矩形框数据的CRect 类对象r 和一个存放字符串的CString 对象s ,方法为:

在工作区的“ClassView ”中,双击CTESTDoc 类,在该类代码中添加如下代码:public:

CRect r;

CString s;

说明:

CRect 是MFC 定义的一个类,有4 个数据成员:left 、top 、right 和bottom 。(left, top) 和(right, bottom )分别表示一个矩形左上角坐标和右下角坐标。

(3)在文档类的成员函数OnNewDocument() 中完成数据成员的初始化。方法为:在工作区的ClassView 中展开CTESTDoc 类,找到其成员函数OnNewDocument() ,在其中添加代码:

BOOL CTESTDoc::OnNewDocument()

{ if (!Cdocument::OnNewDocument())

return FALSE;

// TODO: add reinitialization code here

// (SDI documents will reuse this document)

r=CRect(100,60,260,100);

s=”同舟共济自强不息”;

return TRUE;

} 说明:阴影部分为添加的代码。

(4)在工作区的“Class View ”中展开视图类CTESTView 类,找到其成员函数OnDraw() ,添加输出矩形框和文字的代码:

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

pDC->Rectangle(pDoc->r);

pDC->TextOut(110,70,pDoc->s);

}

说明:

①GetDocument() 是视图类的一个重要成员函数,其返回值是指向当前文档的指针。视图类中的成员函数通过它访问文档类的公有数据成员。

②函数OnDraw() 是实现输出的关键函数,绝大多数的显示工作都是在这个函数中完成的。其参数pDC 指向窗口中央的客户区对象,程序使用了客户区对象的Rectangle 和TextOut 函数绘制矩形和输出文字。

( 5 ) 运行程序,结果如图所示。

(一)SDI 应用程序框架

1.应用程序类

每个应用程序类必须从CWinApp 派生出自己的应用程序类,该类封装了包括初始化、运行和结束的整个过程,其名称是AppWizard 根据工程名称自动命名的,规则如下:(1)如果工程名符合标识符的命名规则,则应用程序类名由字母C 、工程名和App 三部分组成。例如,工程名为TEST ,则应用程序类名为CTESTApp 。

(2)如果工程名以数字开始,则应用程序类名由字母Cmy 、工程名和App 三部分组成。例如,工程名为1TEST ,则应用程序类名为CMy1TESTApp 。

(3)忽略工程名的汉字。

文档类和视图类的命名规则与应用程序类类似,区别在于在后面分别添加了Doc 和View 。

2.窗口框架类

从CMainWnd 派生,提供了一个SDI 窗口的所有功能,如显示一个标题、一个菜单栏、一个工具栏等。所有SDI 应用程序窗口框架类都是CMainFrame ,但是性质是有区别的。

3.文档类

从CDocument 类派生出来,是应用程序进行数据定义和初始化的地方。文档类的数据成员只有被说明成公有成员才能被视图类中的成员函数访问,其重要成员函数是OnNewDocument() ,是进行数据成员初始化的地方。程序开始时会自动调用该函数。

4.视图类

从CView 中派生出来,是程序的用户界面,用于显示、打印存储在文档类对象中的数据,并管理与用户的交互。重要成员函数有:

(1)GetDocument() 函数

该函数的返回值是指向与当前视图相关联的文档对象的指针,因而通过它可以访问文档类对象中的公有私有成员。其一般使用形式为:

CTESTDoc* pDoc = GetDocument();

说明:

①在不同的应用程序中,pDoc 所指向的文档类对象的名称是不一样的。若工程名称为TEST ,则文档类的名称为CTESTDoc ,若工程名为ABC ,则文档类名为CABCDoc ,则应用CABCDoc* pDoc 定义。

②在OnDraw函数中,这个语句是自动生成的。在用户自定义的视图类成员函数中,如果需要访问文档类对象的公有数据成员,则应添加这样的语句。

(2)OnDraw() 函数

在视图类中,OnDraw() 是一个很重要的成员函数,用于实现输出。一般来说,窗口中的内容都是OnDraw() 输出的。

初始的OnDraw()函数如下:

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument(); // 获得指向文档类对象的指针

ASSERT_VALID(pDoc); // 检查pDoc 是否有效,若无效结束程序

// TODO: add draw code for native data here

}

说明:

OnDraw()函数有两种调方法:

①自动调用:当窗口发生变化视图需要重新绘制时,应用程序会自动调用该函数。

②手工调用:当程序中的数据改变了需要重新显示时,可以通过调用Invalidate() 和InvalidateRect() 函数,引发对Ondraw() 的调用。需要注意的是,不是直接调用Ondraw()函数。

Invalidate(TRUE) // 擦除窗口原有的内容,重新绘制。

Invalidate(FALSE) // 窗口原有的内容保留,再进行绘制。

InvalidateRect( 矩形, TRUE) // 擦除矩形区域内原有内容,重新绘制这个区域。

InvalidateRect( 矩形, FALSE) // 矩形区域内原有内容保留,再绘制这个区域。

2.2 图形和文字的输出

窗口中央的客户区是一个输出文字和图形的区域。

简单的文字和图形输出

文字输出

形式:

BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount);

说明:

从坐标(x,y) 开始显示lpszString 字符串,其中参数nCount 指定字符串中的字节数。

画点

形式:

COLORREF SetPixel(int x, int y, COLORREF crColor);

COLORREF SetPixel(POINT point, COLORREF crColor);

说明:

①POINT 是MFC 定义的结构类型,表示平面上的一个点。它的两个重要元素是x 和y ,分别表示一个点的x 坐标值和y 坐标值。与POINT 类似的是CPoint 类,两个数据成员也是x 和y 。

②COLORREF 是一个32 位整数类型,用于表示颜色,其第0 、1 、2 字节分别存放了一种颜色的红、绿、蓝的值。用三种颜色合成一种颜色的函数是RGB ,例如:COLORREF C1=RGB(0, 0, 0) ;// 合成黑色

COLORREF C2=RGB(255, 255, 255); // 合成白色

COLORREF C3=RGB(255, 0, 0); // 合成红色

COLORREF C4=RGB(0, 255, 0); // 合成绿色

COLORREF C5=RGB(0, 0,255); // 合成蓝色

COLORREF C6=RGB(255, 255, 0); // 合成亮黄色

COLORREF C7=RGB(0,255, 255); // 合成青色

COLORREF C8=RGB(255, 0, 255); // 合成品红色

COLORREF C9=RGB(0, 0,128); // 合成深蓝色

COLORREF C10=RGB(0, 128, 0); // 合成深绿色

COLORREF C11=RGB(128, 128, 128); // 合成深灰色

COLORREF C12=RGB(128, 128, 128); // 合成浅灰色

③使用指定颜色crColor 在坐标(x,y) 或点point 处画一个点,返回用于画点的颜色。

画线

画线需要调用两个函数:首先调用MoveTo 函数确定线段的起点,然是调用LineTo 确定线段的终点。

形式:

CPoint MoveTo(int x,int y);

CPoint MoveTo(POINT point);

BOOL LineTo(int x, int y);

BOOL LineTo(POINT point);

说明:(x,y)或point 是线段的起点或终点坐标。

画矩形

形式:

BOOL Rectangle(int x1, int y1, int x2, int y2);

BOOL Rectangle(LPCRECT lpRect);

说明:(x1,y1) 和(x2,y2) 是所画矩形的左上角和右下角坐标, lpRect 是指向矩形的指针。

画椭圆

形式:

BOOL Ellipse(int x1, int y1, int x2, int y2);

BOOL Ellipse(LPCRECT lpRect);

说明:

(x1,y1) 和(x2,y2) 是椭圆外接矩形的左上角和右下角坐标, lpRect 是指向外接矩形的指针。

获取客户区的大小

使用Wnd 类的成员函数GetClientRect 可以将客户区的坐标放入一个CRect 类的对象中,然后调用成员函数计算到高度和宽度。

形式:

void GetClientRect( LPRECT lpRect ) const;

【例2.2】改变窗口时,矩形框和文字总是显示在窗口的中央

void CTESTView::OnDraw(CDC* pDC)

{

CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CRect a,b;

int w=160;

int h=40;

GetClientRect(&a);

b.left=(a.Width()-w)/2;

b.top=(a.Height()-h)/2;

b.right=b.left+w;

b.bottom=b.top+h;

pDC->Rectangle(b);

pDC->TextOut(b.left+10,b.top+10,"同舟共济、自强不息!");

}

【例2.3】编写一个程序,绘制如图所示的-2π~2π之间的sin 曲线。

因为需要使用sin() 函数,所以在TEST.CPP 的开始添加文件包含命令。

#include "math.h"

程序代码:

…………………………………………………………

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CRect rect;

GetClientRect(rect);

int x0=rect.Width()/2;

int y0=rect.Height()/2;

pDC->MoveTo(20,y0);

pDC->LineTo(rect.Width()-20,y0);

pDC->MoveTo(x0,20);

pDC->LineTo(x0,rect.Height()-20);

double step=3.14159/100;

for(int i=-200;i<200;i++ )

pDC->SetPixel(x0+(i/300.0)*rect.Width()/2,y0-sin(step*i)*rect.Height()/4,RGB(255,0,0));

}

…………………………………………………………

去掉窗口的“无标题”及设置新标题

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

cs.style &=~FWS_ADDTOTITLE; //去掉无标题

m_strTitle="绘制sin曲线"; //设置新标题

return TRUE;

}

画笔和画刷

自定义画笔

CPen 是MFC 中的一个类,它封装了一个Winndows GDI 画笔,并提供了用于操作画笔的若干函数。画笔的创建和使用过程一般为:

CPen pen, *oldpen; // 定义画笔pen 和指向画笔的指针oldpen

pen.CreatePen(PS_SOLID,3,RGB(255,0,0)); // 创建一支红色能画实线 3 号粗细

的画笔

oldpen=pDC->SelectObject(&pen); // 选用新的画笔pen ,让oldpen指向

旧的画笔

pDC->MoveTo(10,10);

pDC->LineTo(50,50);

pDC->SelectObject(oldpen); // 恢复使用旧的画笔说明:

(1)CreatePen() 是CPen 的成员函数,用于创建画笔。其使用形式为:

BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );

其中:nPenStyle 为所画线的样式,其取值见表;nWidth 线的宽度;crColor 为线的颜色。

(2)SelectObject() 是CDC 类的成员函数,其作用是将一个新的GDI 对象选入到设备环境中,新选用的对象取代原来的对象,然后返回指向原对象的指针。函数原型为:CPen* SelectObject( Cpen* pPen ); // 选用新的画笔

Cbrush* SelectObject( Cbrush* pBrush ); // 选用新的画刷

virtual Cfont* SelectObject( Cfont* pFont ); // 选用新的字体

Cbitmap* SelectObject( Cbitmap* pBitmap ); // 选用新的位图

自定义画刷

画刷是用来填充图形的工具。CBrush 是MFC 中的一个类,它封装了一个Windows GDI 画刷,并提供了用于操作画刷对象的若干方法。画刷的创建和使用过程一般为:CBrush brush; // 定义画刷对象brush

brush.CreateHatchBrush(HS_CROSS,RGB(0,255,0)); // 构造绿色十字线风格的

画刷

pDC->SelectObject(&brush); // 选择一个新的画刷

pDC->Ellipse(100,10,200,110); // 用新的画刷画圆说明:

(1)CreateHatchBrush () 是CBrush 的成员函数,用于创建画刷。其使用形式为:BOOL CreateHatchBrush(int nIndex , COLORREF crColor );

其中:nIndex 指定了阴影风格,其取值见表;crColor 为画刷的颜色。

(2)创建画刷的另一个函数是CreateSolidBrush() ,其作用是创建用单一颜色填充的画刷。其函数原形为:

BOOL CreateSolidBrush(COLORREF crColor );

【例2.4】编写一个程序,输出如图所示的图形。

…………………………………………………………

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CPen pen,*oldpen;

pen.CreatePen(PS_SOLID,3,RGB(255,0,0));

oldpen=pDC->SelectObject(&pen);

pDC->MoveTo(10,10);

pDC->LineTo(100,100);

pDC->Ellipse(100,10,200,110);

Cbrush brush;

brush.CreateHatchBrush(HS_CROSS,RGB(0,255,0));

pDC->SelectObject(&brush);

pDC->Ellipse(220,10,320,110);

pDC->SelectObject(oldpen);

pDC->MoveTo(320,100);

pDC->LineTo(410,10);

pen.DeleteObject();//释放画笔资源

brush.DeleteObject();

}

…………………………………………………………

位图处理

CBitmap 是MFC 中的一个类,它封装了Winndows GDI 的位图处理,其成员函数主要是装载和操作位图。通过一个实例说明显示位图的一般过程。

【例2.5】编一程序显示Windows 主目录中的Soap Bubbles.bmp ,如图所示。

(1)导入位图

导入位图就是把存放在磁盘上的位图文件作为资源导入到应用程序中,方法是:

选择“插入| 资源”命令,在弹出的“插入资源”对话框中,选定“Bitmap ”,然后选择“导入”命令导入Soap Bubbles.bmp 。

(2)装载位图

装载位图就是把应用程序位图资源装载到一个Cbitmap 对象中。

CBitmap b;

b.LoadBitmap(IDB_BITMAP1); //LoadBitmap 将位图资源装载到CBitmap 对象

(3)读取位图信息

BITMAP bm; // 说明bm 为BITMAP 结构类型的变量

b.GetBitmap(&bm); // 把位图的大小等信息读入bm 中

int w=bm.bmWidth; // 把位图的宽度赋给w

int h=bm.bmHeight; // 把位图的高度赋给h

(4)构造内存设备环境,并将位图装入该设备环境

CDC m;

m.CreateCompatibleDC(NULL);

m.SelectObject(&b);

(5)将位图从内存设备环境复制到真正的设备环境中

pDC->StretchBlt(0,0,(int)w*f,(int)h*f,&m,0,0,w,h,SRCCOPY);

说明:

BitBlt 是CDC 类的成员函数,用于复制位图到真正的设备环境中。其函数原型为:BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );

其中:(x,y) 为位图显示区域左上角的坐标;nWidth 和nHeight 是显示区域的宽度和高度;pSrcDC 指向内存设备环境;(xSrc, ySrc) 为原图欲显示区域左上角的坐标;dwRop 指定复制方式,常用值为SRCCOPY ,表示按原图复制。

…………………………………………………………

void CMyView::OnDraw(CDC* pDC)

{ CMyDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CBitmap b;

b.LoadBitmap(IDB_BITMAP1);

BITMAP bm;

b.GetBitmap(&bm);

int w=bm.bmWidth;

int h=bm.bmHeight;

CDC m;

m.CreateCompatibleDC(NULL);

m.SelectObject(&b);

pDC->StretchBlt(0,0,w/2,h/2,&m,0,0,w,h,SRCCOPY);

}

…………………………………………………………

2.3 定时器

在Visual C++中可以创建一个时钟,以一定的时间间隔发出定时器消息WM_TIMER。利用定时器,可以制作闹钟、动画等。

创建定时器

创建定时器使用SetTimer 函数。其一般形式为:

UINT SetTimer(UINT nIDEvent , UINT nElapse , void * lpfnTimer ) 说明:

(1)nIDEvent: 定时器标识,任何一个非0 整数

(2)nElapse :时间间隔,单位毫秒

(3)lpfnTimer :一般设置为NULL ,表示WM_TIMER 消息加入应用程序的消息队列,由CWnd 类对象处理WM_TIMER 消息。

撤销定时器

撤销定时器使用KillTimer 函数。其一般形式为:

BOOL KillTimer int nIDEvent );

说明:nIDEvent 为撤销的定时器标识。

【例2.6】用定时器控制蝴蝶在窗口中飞舞,如图所示。

(1)在视图类中定义数据成员

public:

int w,h,I; // 变量w 存放位图宽度,h 存放高度,I 控制位图的交替

CBitmap b1,b2; // 说明两个存放位图的CBitmap 对象

(2)在视图类构造函数分别装载两幅图到CBitmap 对象

CTESTView::CTESTView()

{

// TODO: add construction code here

I=0;

b1.LoadBitmap(IDB_BITMAP1);

BITMAP BM;

b1.GetBitmap(&BM);

w=BM.bmWidth;

h=BM.bmHeight;

b2.LoadBitmap(IDB_BITMAP2);

}

(3)单击左键创建定时器,定时器标识为1 ,以200ms 的时间间隔发出定时器消息。

void CTESTView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

SetTimer(1,200,NULL);

CView::OnLButtonDown(nFlags, point);

}

(4)每隔200ms 执行视图的定时器消息处理函数。

void CTESTView::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

I=(I+1)%2; //I 为0 显示第一幅图像,I 为 1 显示第二幅图像

Invalidate(FALSE); // 调用OnDraw() 函数

CView::OnTimer(nIDEvent);

}

(5)在OnDraw() 函数中交替显示两幅对象,达到动画的效果

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CDC m;

if (I==0)

{ m.CreateCompatibleDC(NULL);

m.SelectObject(&b1);

pDC->BitBlt(100,100,w,h,&m,0,0,SRCCOPY);

}

else

{ m.CreateCompatibleDC(NULL);

m.SelectObject(&b2);

pDC->BitBlt(100,100,w,h,&m,0,0,SRCCOPY);

}

}

(6)单击右键撤消定时器

void CTESTView::OnRButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

KillTimer(1); // 撤消定时器

CView::OnRButtonDown(nFlags, point);

}

2.4 鼠标和键盘消息处理

鼠标和键盘是操纵计算机的主要工具。对鼠标和键盘进行编程是程序设计人员必须掌握的基本技术。

鼠标消息处理

当用户进行鼠标操作时,便会发出如下的消息。

WM_LBUTTONDOWN :按下鼠标左键

WM_LBUTTONUP :释放鼠标左键

WM_LBUTTONDBLCLK :双击鼠标左键

WM_RBUTTONDOWN :按下鼠标右键

WM_RBUTTONUP :释放鼠标右键

WM_RBUTTONDBLCLK :双击鼠标右键

WM_MOUSEMOVE :鼠标移动

与上述鼠标消息相对应的消息处理成员函数为( 以WM_LBUTTONDOWN 为例) :void CTest1View::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CView::OnLButtonDown(nFlags, point);

}

其中:

①nFlags 参数包含了Shift 、Ctrl 和Alt 键的状态信息,如表 3 所示。

② point 的值是当前鼠标指针位置。

【例2.7】显示鼠标指针的位置

(1)在文档类中添加数据成员

public: CPoint a; //存放鼠标指针位置

(2)在OnNewDocument()中进行如下的初始化

a= CPoint(-1,-1); //程序开始运行时显示(-1,-1)

(3)视图键盘消息处理函数中把鼠标单击的位置存放在文档类的a中。

void CTESTView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CTESTDoc *pDoc=GetDocument();

pDoc->a=point;

Invalidate();

CView::OnLButtonDown(nFlags, point);

}

(4)OnDraw()函数

在OnDraw()函数中输出鼠标单击的位置。

void CTESTView::OnDraw(CDC* pDC)

{

CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CString s;

s.Format("x=%d,y=%d",pDoc->a.x,pDoc->a.y);

pDC->TextOut(10, 10, s);

}

【例2.8 】设计一个如图所示的画图程序。要求按下鼠标右键画圆,按住鼠标左键移动画线。

(1)在文档类中添加数据成员。

public:

CPoint c1, c2; // 存放一条线段两端的位置

int f1, f2;

CRect r;

(2)在OnNewDocument() 中进行如下的初始化。

f1=0; //f1 为1 表示处于画线状态,当前位置是一线段的起点

f2=0; //f2 为1 表示需要画线

(3)编写视图类的各键盘消息处理函数

// 按下左键画线开始,文档类的f1 赋值1 ,c1 记录下当前鼠标位置。

void CTESTView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CTESTDoc *p=GetDocument();

p->c1=point;

p->f1=1;

//Invalidate(FALSE);

CView::OnLButtonDown(nFlags, point);

}

// 移动鼠标时根据f1 的值判断当前位置是否处于画线状态,

// 如果处于画线状态,则f2 赋值1 ,并把鼠标当前位置记录在c2 中。

void CTESTView::OnMouseMove(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CTESTDoc *p=GetDocument();

if (p->f1==1)

{ p->f2=1;

p->c2=point;

Invalidate(FALSE);

}

CView::OnMouseMove(nFlags, point);

}

// 释放左键画线结束,文档类f1 和f2 赋值0 。

void CTESTView::OnLButtonUp(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CTESTDoc *p=GetDocument();

p->f1=0;

p->f2=0;

CView::OnLButtonUp(nFlags, point);

}

// 视图的OnRButtonDown() 函数将以单击处为圆心半径为30 的圆的数据存放到文档类的r 中。

void CTESTView::OnRButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CTESTDoc *p=GetDocument();

int radius;

radius=30;

p->r=Crect(point.x-radius,point.y-radius,point.x+radius,point.y+radius);

Invalidate(FALSE);

Cview::OnRButtonDown(nFlags, point);

}

//OnDraw() 函数绘制图形

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

if (pDoc->f2==1)

{ pDC->MoveTo(pDoc->c1);

pDC->LineTo(pDoc->c2);

pDoc->c1=pDoc->c2;

}

pDC->Ellipse(pDoc->r);

}

键盘消息处理

当用户操作键盘时,视图类接收到由Windows 发出的键盘消息。重要的键盘消息是:(1)WM_KeyDown 事件:按下键盘上的一个键。

(2)WM_KeyUp 事件:释放键盘上的一个键。

与上述键盘消息相对应的消息处理成员函数为( 以WM_KeyDown 为例) :void CTESTView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

// TODO: Add your message handler code here and/or call default

Cview::OnKeyDown(nChar, nRepCnt, nFlags);

}

其中:

①nChar 为用户所操作的那个键的代码,它告诉消息处理函数用户所操作的物理键。

② nRepCnt 为按键的重复次数。

③ nFlags 为扫描码、转换键码和按键组合状态。

2.5 对话框

Visual C++ 提供了一组通用对话框类,每一个类对应一种标准对话框,可供程序员在编程时直接使用,如表所示。使用通用对话框的过程如下:

(1)说明一个通用对话框类对象;

(2)调用其成员函数,设置设置属性;

(3)打开对话框;

(4)根据用户的选择进行编程。

文件对话框

构造函数

CFileDialog( BOOL bOpenFileDialog , LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY |

OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );

说明:

①若bOpenFileDialog 为TRUE ,则显示打开对话框,否则显示另存为对话框。

②lpszDefExt 指定缺省的扩展名。

③lpszFileName 指定缺省的文件名。

④lpszFilter 用于指明可供选择的文件类型和相应的扩展名。它的属性值是由一组元素或用“| ”符号分开的分别表示不同类型文件的多组元素组成。例如,若要在打开文件类型列表框时显示如图所示的三种文件类型供用户选择,则Filter 属性应设为:

"Documents(*.DOC)|*.DOC|Text Files(*.TXT)|*.txt|All Files|*.* ||"

⑤其它参数一般使用缺省值

DoModal()函数

DoModal() 函数的功能是打开打话框。其使用形式为:

对象.DoModal()

GetPathName() 用于获取用户选择的包括路径在内的文件名。其函数原形为:CString GetPathName( ) const;

GetFileName () 用于获取用户选择的文件名,不包括路径。其函数原形为:

CString GetPathName( ) const;

GetFileExt( ) 返回文件扩展名

GetFileTitle( ) 返回文件主名(不含扩展名)

【例2.9】编写一个如图所示的图形浏览程序。若用户单击左键,则弹出打开对话框,用户选择一个图片文件后就在客户区显示该图片。

(1)在文档类中添加一个公有数据成员m_filename ,用于存放用户选择的包括路径在内的文件名。

public:

CString filename;

(2)在文档类的OnNewDocument() 函数中对数据成员filename 进行初始化。

filename= "" ;

(3)通过“建立类向导”为视图类添加WM_LBUTTONDOWN 消息处理函数,并编写代码。

void CTESTView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler =code here and/or call default

CTESTDoc* pDoc=GetDocument();

CFileDialog dlg(TRUE,NULL,NULL,NULL,"BMP Files(*.BMP)|*.BMP||");

if ( dlg.DoModal()==IDOK )

{ pDoc->filename=dlg.GetPathName();

Invalidate();

}

CView::OnLButtonDown(nFlags, point);

}

(4)在OnDraw() 函数中,显示位图。

void CTESTView::OnDraw(CDC* pDC)

{ CTESTDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

if ( pDoc->filename!="" )

{ HBITMAP hbitmap;

hbitmap=(HBITMAP)LoadImage(NULL,pDoc->filename,

IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

CDC m;

CRect rect;

m.CreateCompatibleDC(pDC);

GetClientRect(rect);

m.SelectObject(hbitmap);

pDC->BitBlt(20,20,rect.Width()-20,rect.Height()-20,&m,0,0,SRCCOPY);

}

}

说明:加载磁盘上的一个.bmp 文件应使用LoadImage() 。其函数原型为:

HANDLE LoadImage(HINSTANCE hinst , LPCTSTR lpszName , UINT uType , int cxDesired , int cyDesired , UINT fuLoad );

其中:hinst 可以用NULL ,lpszName 是图象在磁盘上的文件名,uType 表示图象的类型,fuLoad 的值为LR_LOADFROMFILE 表示从文件中导入位图。

颜色对话框

颜色对话框属于CColorDialog 类。其一般使用形式为:

CColorDialog dlg; // 说明dlg 为CColorDialog 类的对象

dlg.DoModal(); // 打开颜色对话框

COLORREF c= dlg. GetColor(); // 获取用户选择的颜色并赋给 c 说明:

①GetColor() 是CColorDialog 的成员函数,其返回值是用户选择的颜色。

②若用户选择了“取消”,没有选择颜色,则GetColor() 的返回值是对话框的默认值。

【例2.10】编写一个如图所示的应用程序。若用户单击左键,则弹出颜色对话框,用户选择一种颜色后就以鼠标单击处为圆心画一个圆,圆的半径随机产生。

(1)在文档类中添加三个公有的数据成员:

CRect r[100]; // 存放圆的数据

COLORREF c[100]; // 存放对应数组r 的圆的颜色

int n; // 目前圆的数量

(2)在文档类的OnNewDocument() 函数中对数据成员n 进行初始化。

n=0;

(3)通过“建立类向导”为视图类添加WM_LBUTTONDOWN 消息处理函数,代码: void CMy0601aView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CMy0601aDoc *pDoc=GetDocument();

CColorDialog dlg;

dlg.DoModal();

pDoc->c[pDoc ->n]=dlg.GetColor();

int r=rand()%50+10;

CRect rect(point.x-r,point.y-r,point.x+r,point.y+r);

pDoc->r[pDoc->n]=rect;

pDoc->n++;

Invalidate();

CView::OnLButtonDown(nFlags, point);

}

(4)在OnDraw() 函数中,用数组 c 的颜色绘出所有的圆

void CMy0601aView::OnDraw(CDC* pDC)

{ CMy0601aDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CBrush newbrush,*oldbrush;

for(int i=0;in;i++)

{ newbrush.CreateSolidBrush(pDoc->c[i]);

oldbrush=pDC->SelectObject(&newbrush);

pDC->Ellipse(pDoc->r[i]);

pDC->SelectObject(oldbrush);

newbrush.DeleteObject(); // 删除画刷

}

}

字体对话框

字体对话框属于CFontDialog 类。其一般使用形式为:

CFontDialog dlg; // 说明dlg 为CFontDialog 类的对象

dlg.DoModal(); // 打开字体对话框

LOGFONT font; // 说明font 为LOGFONT 类型结构变量

dlg.GetCurrentFont (& font ); // 把用户选择的字体送入变量font 中

COLORREF c= dlg. GetColor(); // 把用户选择的颜色赋给变量 c

Cfont cf; // 说明cf 为Cfont 类的对象

cf.CreateFontIndirect(&font); // 用font 中的数据构造字体

pDC->SelectObject(&cf); // 选用新字体

pDC->SetTextColor(); // 选用新颜色

pDC->TextOut(10,10," 同舟共济自强不息!"); // 用新的字体和颜色输出文字

说明:

①LOGFONT 是Visual C++ 定义的结构类型,用于存放有关字体的参数。

②GetCurrentFont () 是字体对话框的成员函数,把字体数据送入font 中。

【例2.11】编写一个如图所示的应用程序。若用户单击左键,则弹出如图所示的字体对话框,然后用用户选择的字体后输出“同舟共济自强不息!”

(1)在文档类中添加两个公有的数据成员:

public:

LOGFONT font; // 存放有关字体的数据

COLORREF c; // 存放字体颜色

(2)通过“建立类向导”为视图类添加WM_LBUTTONDOWN 消息处理函数,代码: void CMy0601aView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CMy0601aDoc *pDoc=GetDocument();

CFontDialog dlg;

dlg.DoModal();

dlg.GetCurrentFont(&pDoc->font);

pDoc->c=dlg.GetColor();

Invalidate();

CView::OnLButtonDown(nFlags, point);

}

(3)在OnDraw() 函数中,用选定的颜色和字体输出文字

void CMy0601aView::OnDraw(CDC* pDC)

{ CMy0601aDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CFont cf;

cf.CreateFontIndirect(&pDoc->font);

pDC->SelectObject(&cf);

pDC->SetTextColor(pDoc->c);

pDC->TextOut(10,10,"同舟共济自强不息!");

}

调用自定义对话框

MFC经典绘图方法总结

MFC经典绘图方法总结 Windows 绘图的实质就是利用windows提供的图形设备接口GDI(Graphics Device Interface)将图形会制在显示器上。 为了支持GDI绘图,MFC提供了两种重要的类: 设备上下文DC(Device Context)类,用于设置绘图属性和绘制图形; 绘图对象类,封装了各种GDI绘图对象,包括画笔、刷子、字体、位图、调色板和区域。 CDC类介绍: 在MFC中,CDC是设备上下文类的基类,派生类包括:CClientDC, CPaintDC, CWindowDC, CMetaFileDC类 CClientDC 客户区设备上下文,绘制客户区时 CPaintDC 一般发生在窗口需要重绘时 CWindwDC 可以绘制整个窗口,通常在窗口WM_NCPAINT消息的响应函数CWnd::OnNCPaint()中使用 CMetaFileDC 专门用于图元文件的绘制,图元文件记录一组GDI命令,重建图形输出。 CDC包含m_hDC和m_hAttribDC二个设备上下文。CDC指导所有对m_hDC的输出GDI调用(SetTextColor)以及对m_hAttribDC的大部分属性GDI调用(GetTextColor)。 CDC对象的重要函数如下: 1、为指定设备创建上下文virtual BOOL CreateDC(...) 比如创建一个为屏幕的设备上下文 CDC dc; dc.CreateDC("DISPLAY", NULL, NULL,NULL); 2、创建内存设备上下文,与指定设备上下文兼容virtual BOOL CreateCompatibleDC( CDC * pDC) 3、删除CDC对象对应的Windows设备上下文, 通常不调用该函数而是使用析构程序virtual BOOL DeleteDC(); 4、将HDC句柄转化为设备上下文的句柄: CDC *pDC=CDC::FromHandle( hDC ) 5、选择GDI对象入选到设备上下文中,一共有五种形式: CPen * SelectObject( CPen * pPen) ; CBrush * SelectObject( CBrush * pBrush) ; virtual CFont * SelectObject( CFont * pFont) ; CBitmap * SelectObject( CBitmap * pBitmap) ; int SelectObject( CRgn * pRgn) ;

MFC程序结构分析

MFC程序结构分析2008-11-08 16:39 分类:VC\MFC 字号:大中小 1 Windows程序工作原理 WINDOWS 程序设计是一种完全不同于传统的DOS 方式的程序设计方法,它是一种事件驱动方式的程序设计模式。在程序提供给用户的界面中有许多可操作的可视对象。用户从所有可能的操作中任意选择,被选择的操作会产生某些特定的事件,这些事件发生后的结果是向程序中的某些对象发出消息,然后这些对象调用相应的消息处理函数来完成特定的操作。WINDOWS 应用程序最大的特点就是程序没有固定的流程,而只是针对某个事件的处理有特定的子流程,WINDOWS 应用程序就是由许多这样的子流程构成的。 从上面的讨论中可以看出,WINDOWS 应用程序在本质上是面向对象的。程序提供给用户界面的可视对象在程序的内部一般也是一个对象,用户对可视对象的操作通过事件驱动模式触发相应对象的可用方法。程序的运行过程就是用户的外部操作不断产生事件,这些事件又被相应的对象处理的过程。下面是WINDOWS 程序工作原理的示意图。 2 建立应用程序 在介绍AppWizard 的时候,我们已经建立了一个名字为TEST 的工程,事实上这个框

架程序已经可以编译运行了。在BUILD 菜单中选择REBUILD ALL 菜单项,系统开始编译由 APPWIZARD 自动生成的程序框架中所有文件中的源代码,并且链接生成可执行的应用程 序。在BUILD 菜单中选择EXECUTE 菜单项,应用程序就开始开始运行了,虽然我们没有编 写一行代码,但是可以看出由系统自动生成的应用程序的界面已经有了一个标准WINDOWS 应用程序所需的几个组成部分,我们要做的事情是往这个应用程序添加必要的代码以完成 我们所需要的功能。 接下来将要对WINDOWS 自动生成的这个应用程序框架作详细的介绍,让你对MFC 方式的 WINDOWS 应用程序的工作原理有全面的认识,只有这样你才会知道应该如何往程序框架当 中添加需要的代码。 3 程序结构剖析 为了让您对MFC 方式的程序的框架有一个总体的认识,这里设计了一个表示程序中的 主要类之间的关系的图表:

MFC程序结构分析

主题: MFC深入浅出 1.MFC深入浅出 MFC概述 2. 3. 1.MFC是一个编程框架 2. 3.MFC (Microsoft Foundation Class Library) 中的各种类结 合起来构成了一个应用程序框架,它的目的就是让程序员在此基础 上来建立Windows下的应用程序,这是一种相对SDK来说更为简单 的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了 用户接口的标准实现方法,程序员所要做的就是通过预定义的接口 把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++ 提供了相应的工具来完成这个工作:AppWizard可以用来生成初步 的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用 户接口;ClassWizard用来协助添加代码到框架文件;最后,编译, 则通过类库实现了应用程序特定的逻辑。 4. 5. 6. 7. 1.封装 2. 3.构成MFC框架的是MFC类库。MFC类库是C++类库。这 些类或者封装了Win32应用程序编程接口,或者封装了应用 程序的概念,或者封装了OLE特性,或者封装了ODBC和DAO 数据访问的功能,等等,分述如下。 4. 5.(1)对Win32应用程序编程接口的封装 6. 7.用一个C++ Object来包装一个Windows Object。例 如:class CWnd是一个C++ window object,它把Windows window(HWND)和Windows window有关的API函数封装在C++ window object的成员函数内,后者的成员变量m_hWnd就 是前者的窗口句柄。 8. 9.(2)对应用程序概念的封装

MFC原理结构说明

JEI
N.
MFC 原理結構說明
捷胤工業有限公司 總合研究所 (JISC)
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
? 質流控制器(Mass?Flow?Controller)簡稱 MFC。簡 易的詮釋 MFC 是一種流量與控制閥組的精密組機 電組合,其測量方式與一般流量計最大的差別, 是在於它是利用熱感溫差 非接觸方式測量氣體 是在於它是利用熱感溫差、非接觸方式測量氣體 之質量流速。
N.
MFC 簡介
? MFC 應用於I C 工業、真空工業、食品工業、化 學工業以及醫療儀器等行業,需要求高精確度、 高穩定度及高品質等氣體流量控制,如:蝕刻、 物理 化學氣相沉積 高穩定度來達成 其應用 物理、化學氣相沉積、高穩定度來達成,其應用 之層面乃遍佈高科技產業。
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
Intel
Connector
N.
MFC 主要結構
Mass flow sensor
CO .
Bypass
Zero switch
LT D
Control valve Outlet Block
PCB
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
? 製程氣體中許多是有腐蝕性或容易液
化的氣體,其與氣體接觸的部份均是 化的氣體 其與氣體接觸的部份均是 以抗腐蝕性強的 SUS‐316L 做為材質, 整顆鑄造而成。
N.
MFC 本體 (Block)
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

MFC视图结构框架分析

MFC文档视图结构框架分析 1:程序的“导火索”---theApp CmyApp theApp; 在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。 class CWinApp : public CWinThread { DECLARE_DYNAMIC(CWinApp) public: // Constructor CWinApp(LPCTSTR lpszAppName = NULL); ………… } CWinApp::CWinApp(LPCTSTR lpszAppName) { if (lpszAppName != NULL) m_pszAppName = _tcsdup(lpszAppName); else m_pszAppName = NULL; // initialize CWinThread state AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL); pThreadState->m_pCurrentWinThread = this; ASSERT(AfxGetThread() == this); m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId();

《MFC》综合开发案例分析1

、八 前言 21 世纪最激烈的竞争当属人才的竞争,一个具有多学科知识的复合性人才或许是一个企业发展壮大所不可或缺的重要因素。因此,企业人事管理工作的好坏不但可以直接影响到企业的人力资源管理,而且会间接的影响到企业整体管理。随着社会的发展,科技的进步,计算机的应用在社会各领域中都得到了普及,越来越多的人都感受到利用计算机进行各类管理的科学和便捷;认识到管理信息系统对于管理工作的重要性。利用计算机对企业人事进行管理是必然趋势,人事管理系统是企业管理工作中不可缺少的。所以在这次课程设计中,我选择开发人事管理系统。人事管理系统的功能主要有增加记录,删除记录,筛选记录,排序记录。这就要求它应该能够为用户提供有好美观的窗口界面、充足可靠的信息数据、简单方便的维护手段和灵活多变的查询方式以及快捷而准确的查询结果。所以,对于人事管理系统的设计主要包括数据库的建立、维护以及应用程序的开发两个方面。对于前者而言要求建立起数据一致性及完整性强、数据安全性好的数据库。对于后者而言则要求具备应用程序功能全, 易使用等,运行稳定等特点。因此,拟选用的开发软件是Microsoft 公司出品的Visual C++6.0 MFC 平台进行系统的开发。

目录 1 课题综述 (1) 1.1 人事管理信息系统来源 (1) 1.2 人事管理系统的意义 (1) 1.3 预期目标 (2) 1.4 面对的问题 (2) 1.5 需解决的关键技术等 .............................................. 2 2 人事管理系统分析 (2) 2.1 涉及的基础知识 (3) 2.2 解决问题的基本思路 (11) 2.3 总体方案 (11) 2.4 功能模块框图 (11) 3.1 部署连接(图) (12) 3.2 算法描述 (12) 3.3 详细流程图 .................................................. 14 4 代码编写 4.1 增加记录的代码 . (15) 4.2 删除记录的代码 (16) 4.3 排序记录的代码 (17) 4.4 筛选记录的代码 ................................................ 17 5 运行与测试 3 人事管理系统设计 ....................... 12 15 18

MFC 通用控件祥解解析

CHeadCtrl 表头控制(CHeaderCtrl)通常应用在窗口中的文本或数据的列表之上。一般为数据列的标题,可以包括多个部分,用户可以拖动每个部分并可以控制每列的宽度。表头控制类提供了普通表头控制的基本方法,只有在WINDOWS95以后版本系统中才提供,其方法包含在afxcmn.h文件中,一般与标签控制(CTabCtrl)和列表控制(CListCtrl)组合使用。 (一)表头控制的对象结构 1、表头控制对象的建立方法 CHeaderCtrl &cheaderCtrl 建立表头控制对象 Create 建立表头并绑定对象 CHeaderCtrl::Create的格式如下:BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 其返回值非零时初始化成功,否则失败。 参数dwStyle用来确定表头控制类型;rect用来确定表头控制的大小和位置;ParentWnd 用来确定表头控制的父窗口;nID用来表示表头控制的标志。 表头控制风格包括: HDS_BUTTONS 表示表头控制外观类似按钮; HDS_HORZ 表示表头控制为水平排列; HDS_VERT 表示表头控制为垂直排列; HDS_HIDDEN 表示表头控制为隐藏模式。 它也可以使用普通类控制风格,包括: CCS_BOTTOM 设置控制位置在父窗口的底部并与父窗口同样宽度; CCS_NODIVIDER 在控制顶部形成两个像素的高亮区; CCS_NOHILITE 在控制顶部形成一个像素的高亮区; CCS_NOMOVEY 在响应WM_SIZE消息时重置大小并水平排列;

MFC9.0类别组织框架图

MFC Hierarchy Chart Part 1 of 3 Classes Derived From CObject

MFC Hierarchy Chart Part 2 of 3 Classes That Derive From CCmdTarget or CWnd

? Microsoft Corporation. All Rights Reserved. Structures Run-Time Object Model Support Synchronization/Thread Support OLE Type Wrappers DHTML Support OLE Automation Types Controls Helper Classes Frame Windows Support Helper Template Manager Support Memory Management State Support Managed Types MFC Hierarchy Chart Part 3 of 3 Classes Not Derived From CObject Legend The Version 9.0 Feature Pack adds new classes to the Microsoft Foundation Class Library. New classes are indicated with a star. Managers, Control Support and Helper classes all provide logical and data support for individual controls or groups of controls. Managers have the word “Manager” in their name. They typically aggregate and coordinate functionality that would otherwise be handled by individual classes. Control Support classes usually provide logical and data support for individual controls. Note: All MFC classes are native C++ classes, with the exception of CWin32Windows, a managed type.

相关主题
文本预览
相关文档 最新文档