Windows 简介
- Windows: 基于图形界面的多任务操作系统
- 多任务:同时运行多个应用程序
- 窗口:应用程序通过窗口与用户交互
- 输入:鼠标单击/双击/拖放,菜单选择,键盘输入
- Windows 功能
- 工具:资源管理器,记事本,画图 …
- 函数库:作为 Windows 应用程序接口(API)提供
windows.h
- 应用程序类型
- 单文档应用
- 只能对一个文档数据操纵
- 必须首先结束当前文档的所有操作之后,才能进行下一个文档的操作
- 多文档应用
- 同时可以对多个文档的数据进行操作
- 不必等到一个文档的所有操作结束,就可以对其它文档进行操作,对不同文档的操作是在不同的子窗口中进行的
- 对话框应用
- 以对话框的形式操作一个文档数据
- 对文档数据的操作以各种“控件”(control)来实现
- 程序以按<确定>或<取消>等按钮来结束
- 单文档应用
消息驱动程序结构
- Windows 应用程序的结果属于消息(事件)驱动的结构:程序的任何一个动作都是在接收到一条消息后发生的
Windows 消息 | |
---|---|
WM_KEYDOWN/WM_KEYUP | 键盘按键 |
WM_CHAR | 字符 |
WM_LBUTTONDOWN/WM_LBUTTONUP/WM_LBUTTONDBLCLK/WM_MOUSEMOVE | 鼠标按键 |
WM_COMMAND | 菜单 |
WM_PAINT | 窗口内容刷新 |
WM_TIMER | 定时器消息 |
- 消息队列:Windows 系统会把属于各个应用程序的消息放入各自的消息队列
- 大部分消息关联到某个窗口
- 每个窗口有一个消息处理函数
- 消息循环:取消息-处理消息
- 取到 WM_QUIT,循环结束
- 可再入:函数的调用者要自带工作区(数据空间)
- 由于消息处理函数在处理一条消息时可能会主动产生一些新消息,这些消息并不放入消息队列,而是直接调用消息处理函数来处理这些消息,这样就有可能导致消息处理函数的一次执行还未结束,另一次执行就开始的现象,这可能会引起数据的不一致错误。
- 函数需要的数据要通过参数来传递
- 函数不能有 static 存储类的局部变量
- 在函数中访问全局变量也可能导致函数不可再入
Windows API
- 基于 Windows API 的过程式 Windows 应用程序设计
- 是一种基于过程抽象的程序设计范式
- 通过调用 API 函数编写程序的粒度太细、太繁琐,开发效率不高
- 主函数 WinMain:每个 Windows 应用程序都必须提供
- 注册窗口类(窗口基本信息)
- 窗口类的名字、窗口的基本风格、消息处理函数名、图标、光标、背景颜色以及菜单
- 每类窗口(不是每个窗口)都需要注册
- 创建应用程序主窗口
- 进入消息循环
- 为每类窗口提供一个消息处理函数,用于处理发送到它的消息
- 注册窗口类(窗口基本信息)
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance, //本实例标识,Handle
HINSTANCE hPrevInstance, //上一实例标识
LPSTR lpCmdLine, //命令行参数
int nCmdShow) //主窗口显示方式
{
//注册窗口类
RegisterClass(..., WindowProc, "my_window_class");
//创建并显示主窗口
HWND hWnd;
hWnd = CreateWindow("my_window_class", ..., x, y, width, height, ...);
ShowWindow(hWnd, nCmdShow);
//消息循环
while (GetMessage(&msg, NULL, 0, 0)){//从消息队列中取消息
DispatchMessage(&msg);
}
return msg.wParam;
}
//窗口消息处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, //窗口标识
UINT message, //消息标识
WPARAM wParam, //消息的参数1
LPARAM lParam) //消息的参数2
{
switch (message){
case WM_KEYDOWN:
//wParam 为扫描码
case WM_CHAR: //字符键消息
//wParam 为按键字符编码
case WM_COMMAND: //菜单消息
switch (wParam) {//wParam 菜单项标识
case ID_FILE_OPEN:
case ID_START_TIMER:
SetItimer(hWnd, 1, 1000, NULL);
}
case WM_LBUTTONDOWN:
//lParam 鼠标在窗口中位置
case WM_CLOSE:
DestroyWindow(hWnd);//关闭窗口
break;
case WM_DESTORY: //窗口被关闭
PostQuitMessage(0); //往本应用消息队列中放入 WM_QUIT
break;
default: //由系统做默认的消息处理
return DefWindownProc(hWnd, message, wParam, lParam);
}
return 0;
}
- 消息处理函数中生成新消息
- PostMessage: 放入消息队列
PostMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
- SendMessage: 直接调用消息处理函数
- PostMessage: 放入消息队列
- Resource
- 菜单:菜单 ID、菜单项 ID/显示文字
- 对话框:对话框 ID 和尺寸;对话框中各个控件的 ID、类型、尺寸与位置
- 资源文件(.rc):编译后作为应用程序一部分链接到目标文件中
- 资源描述有规定的格式
- 可以用 VC++的资源编辑器来进行可视化编辑
MFC
- 基于 MFC 和“文档–视”结构的面向对象 Windows 应用程序设计
- MFC(Microsoft Foundation Class library, 微软基础类库)
- MFC 提供了一些类来描述应用中对象的基本功能,应用程序可以通过继承这些类来实现各自的特殊功能
- 文档–视结构
- 文档:储存和管理程序中的数据
- 视:显示文档数据以及实现对文档数据进行操作时与用户的交互功能
- 一个文档对象对应一个或多个视对象
- MFC 提供的文档视框架主要由以下类构成
- CView
- CDocument
- CFrameWnd
- CDocTemplate
- CWinApp
- 类向导 Class Wizard
- 为应用程序中从 MFC 派生的类增加/删除成员
- 为应用程序增加/删除基于 MFC 的类
- 图形用户接口(GUI)设计
- 菜单:菜单由菜单项构成,每个菜单项包含标识,显示文字和提示文字,处理函数
- 对话框
- 绘图
- 坐标转换
窗口类
-
基本窗口类 CWnd
- 实现窗口的基本功能:一般的消息处理、窗口大小和位置管理、菜单管理、坐标系管理、滚动条管理、剪贴板管理、窗口状态管理、窗口间位置关系管理,等等
- 其它窗口类的基类
-
框架窗口类
- 提供对标题栏、菜单栏、工具栏、状态栏以及属于它的子窗口的管理功能
- CFrameWnd: 单文档应用主窗口
- CMDIFramWnd: 多文档应用主窗口
- CMDIChildWnd: 多文档应用子窗口
-
视类 CView
- 视窗口(简称视)位于单文档应用主窗口(CFrameWnd)和多文档应用子窗口(CMDIChildWnd)的客户区(可显示区)
- 实现程序数据的显示功能以及操作数据时与用户的交互功能
- CScrollView 带滚动功能
void CScrollView::SetScrollSizes( int nMapMode, //映射方式(坐标的逻辑单位,坐标轴方向) SIZE sizeTotal, //文档内容大小 const SIZE& sizePage = sizeDefault, //文档滚动页大小 const SIZE& sizeLine = sizeDefault //文档滚动行大小 ); //坐标转换函数 OnPrepareDC(&dc, NULL); //为ScrollView初始化dc dc.DPtoLP(&point); //从物理坐标转换逻辑坐标 dc.LPtoDP(&point);
- CEditView 具有编辑功能
- CFormView 具有表格功能
- CHtmlView 具有Web浏览功能
//CView 成员
CDocument *m_pDocument; //储存相应文档对象指针
CDocument *GetDocument() const;
virtual void OnDraw(CDC* pDC)=0; //处理窗口(视)刷新信息
virtual void OnInitialUpdate(); //视对象创建时被调用
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); //文档对象的数据发生改变时调用该函数刷新相应的视对象。默认处理:发送WM_PAINT消息
- 对话框类 CDialog
- 对话框是一种特殊的窗口,用于获取用户的输入信息
- CFileDialog: 文件打开/保存对话框
- CFontDialog: 字体选择对话框
- CColorDialog: 颜色选择对话框
- CPrintDialog: 打印对话框
- CFindReplaceDialog: 查找/替换对话框
CMyDlg dlg;
dlg.m_ = ...;
if (dlg.DoModal()==IDOK){
... = dlg.m_;
}
文档类
-
CDocument
- 对程序要处理的数据进行管理,包括磁盘文件 I/O。
- 一个 CDocument 类的对象至少要对应一个 CView 类的对象。
//CDocument 成员 void AddView(CView* pView); //给文档对象增加一个关联的CView类的对象 void RemoveView(CView* pView); //使一个CView对象脱离与文档对象的关联 virtual POSITION GetFirstViewPosition() const; //获取关联的第一个CView对象的位置 virtual CView* GetNextView(POSITION& rPosition) const; //获取指定位置的CView对象,rPosition自动往后移动一个位置 void UpdateAllViews(CView* pSender, LPARAM lHint=0L, CObject* pHint=NULL); //向关联的CView对象发送刷新消息。当pSender为NULL时,向关联的所有CView对象发送刷新消息 void SetModifiedFlag(BOOL bModified=TRUE); //设置文档修改标记 BOOL IsModified(); //判断文档是否被修改 virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); //把文档数据保存到文件名为 lpszPathName 的文件中去 virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual BOOL OnNewDocument(); virtual BOOL OnCloseDocument(); virtual void Serialize(CArchive& ar); //用于文档数据的序列化(写入磁盘文件或从磁盘文件读出),一般由OnSaveDocument和OnOpenDocument来调用
应用程序类
-
文档模板类
- 实现对文档、视窗口和框架窗口所构成的对象组的管理功能。(用于支持基于“文档-视”结构的应用框架)
- CDocTemplate: 文档模板的基类
CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass); //参数为文档、视以及框架窗口的类信息
- CSingleDocTemplate: 单文档模板类
- CMultiDocTemplate: 多文档模板类
-
应用类 CWinApp
- 提供了对 Windows 应用程序的各部分进行组合和管理的功能,其中包括对主窗口和文档模板的管理以及实现消息循环等
virtual BOOL InitInstance(); //应用程序初始化,包括注册窗口类、创建/显示主窗口等。它由WinMain调用 virtual int Run(); //实现消息循环,由WinMain调用 virtual int ExitInstance(); //由Run调用 virtual CWnd *GetMainWnd(); void AddDocTemplate(CDocTemplate* Template); //把一个文档模板加入到CWinApp类的对象中 afx_msg void OnFileNew(); //对 File|New 菜单消息的处理功能 afx_msg void OnFileOpen(); //对 File|Open 处理
其它类
-
绘图类
- CDC 绘图环境类:实现 Windows 应用程序中的绘图功能:文本以及几何图形(线、矩形、椭圆等)的输出
- CClientDC: CDC 派生类,用于在一个窗口的客户区绘图
- 应用框架调用 CView 的 OnDraw 成员函数时,会自动创建一个 CDC 类的对象,作为参数传给 OnDraw
//文本输出函数 virtual BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount); BOOL TextOut(int x, int y, const CString& str); virtual int DrawText(LPCTSTR lpszString, int nCount, LPRECT lpRect, UINT nFormat); int DrawText(const CString& str, LPRECT lpRect, UINT nFormat); virtual COLORREF SetTextColor(COLORREF crColor ); //设置字符和背景颜色 virtual COLORREF SetBkColor(COLORREF crColor); //几何图形输出函数 //线段 CPoint MoveTo(int x, int y);//定起点 CPoint MoveTo(POINT point); BOOL LineTo(POINT point); BOOL LineTo(int x, int y); //画矩形 BOOL Rectangle(int x1, int y1, int x2, int y2); BOOL Rectangle(LPCRECT lpRect); //画椭圆,参数为外接矩形 BOOL Ellipse(int x1, int y1, int x2, int y2); BOOL Ellipse(LPCRECT lpRect); //绘图工具选择函数 virtual CGdiObject* SelectStockObject(int nIndex); //选择系统提供的绘图工具 CPen* SelectObject(CPen* pPen); //选择自定义的笔 CBrush* SelectObject(CBrush* pBrush); virtual CFont* SelectObject(CFont* pFont);
-
绘图工具类
- CPen: 画笔,用于画线
- CFont: 字体
- CBrush:刷子,用于填充封闭图形
Cpen(int nPenStyle, int nWidth, COLORREF crColor); CBrush(COLORREF crColor); CFont(); BOOL CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL);
- CDC 绘图环境类:实现 Windows 应用程序中的绘图功能:文本以及几何图形(线、矩形、椭圆等)的输出
//绘图实例
void CMyView::OnDraw(CDC* pDC){
COLORREF old_text_color=pDC->SetTextColor(RGB(255,0,0)); //把字符颜色设置成“红”色。
COLORREF old_bk_color=pDC->SetBkColor(RGB(0,255,0)); //把字符背景颜色设置成“绿”色。
pDC->TextOut(0,0,”hello”); //在位置(0,0)处显示字符串"hello"
pDC->SetTextColor(old_text_color); //把原来的字符颜色选回CDC类的对象
pDC->SetBkColor(old_bk_color); //把原来的字符背景颜色选回CDC类的对象
CBrush brush(RGB(0,0,255)),*old_brush; //创建一个蓝色的刷子
old_brush = pDC->SelectObject(&brush); //把新刷子选进CDC类的对象,原来的刷子由old_brush指向
pDC->Rectangle(0,50,100,150); //画一个内部为蓝色的矩形,左上角:(0,50);右下角:(100,150)
pDC->SelectObject(old_brush); //把原来的刷子选回到CDC类的对象中,必须要做!
}
-
文件输入输出类
- CFile: 基于字节流的文件 I/O
- CArchive: 通过重载操作符 « » 实现了对基本数据类型和 MFC 类对象的文件 I/O
BOOL IsLoading() const; BOOL IsStoring() const;
-
常用数据类型类
- CPoint(点坐标)
- CRect(矩形信息)
- CSize(矩形的宽度/高度、点之间的偏移量等)
- CString