430 likes | 649 Views
VC++ 程序设计. Windows 程序工作机制图. Windows 的事件驱动机制. Windows 程序设计是针对 事件 或 消息 的处理进行. 消息 是描述事 件发生的信息 ( 如按下鼠标或键盘 ). Windows 程序 的执行顺序取决于事件发生的顺序,程序的执行顺序是由顺序产生的 消息 驱动的,但是 消息 的产生往往并不要求有次序之分。. Windows 消息. Windows 应用程序利用 Windows 消息 (Message) 与应用程序及系统进行信息交换。. 消息号:由事先定义好的消息名标识. 消息.
E N D
Windows的事件驱动机制 • Windows程序设计是针对事件或消息的处理进行 消息是描述事 件发生的信息 (如按下鼠标或键盘) Windows程序的执行顺序取决于事件发生的顺序,程序的执行顺序是由顺序产生的消息驱动的,但是消息的产生往往并不要求有次序之分。
Windows 消息 Windows应用程序利用Windows消息(Message)与应用程序及系统进行信息交换。 消息号:由事先定义好的消息名标识 消息 字参数(wParam) :用于提供消息的附加信息 长字参数(lParam) :用于提供消息的附加信息
MSG结构 typedef struct tagMSG { HWND hwnd; //接受消息的窗口句柄 UINT message; //消息名字(WM_COMMAND,WM_PAINT等) WPARAM wParam; //参数,包含有关消息的附加信息, //不同消息其值有所不同 LPARAM lParam; //参数,具体意义由消息名字决定 DWORD time; // 指定消息送至队列的时间 POINT pt; //指定消息发送时屏幕光标的位置 }MSG; typedef struct tagPOINT { LONG x; LONG y; } POINT;
消息的分类 • 常用的消息有: • 窗口管理、初始化、输入、系统、剪贴板、控制处理,控制通知、非用户区、MDI、DDE 及应用程序自定义消息 • 系统定义消息的前缀: • BM 按钮控制 CB组合框架 DM 下压式按钮 EM 编辑控制 LB列表框 SBM 滚动条 WM 窗口消息 • 消息的取值 • 系统定义(0x0000~0x03FE, 0x8000~0xBFFF) • 用户定义内部消息 0x0400~0x07FF) • 外部消息(0xC000~0xFFFF)
Windows应用程序常用消息 • WM_LBUTTONDOWN 单击鼠标左键产生,类似的有:WM_LBUTTONUP, WM_RBUTTONUP, WM_RBUTTONDOWN,WM_MBUTTONUP • WM_KEYDOWN 按下非系统键时触发 • WM_CHAR 与WM_KEYDOWN参数不同 • WM_CREATE 程序创建时 • WM_CLOSE 关闭窗口 • WM_DESTROY 由DestroyWindows发出 • WM_QUIT 由PostQuitMessage发出 • WM_PAINT 窗口重绘时
Windows常用数据类型 • WORD 16位无符号整数 • LONG 32位有符号整数 • DWORD 32位无符号整数 • HANDLE 句柄 • UNIT 32位无符号整数 • BOOL boolean • LPTSR 指向字符串的32的指针 • LPCSTR 指向字符串常量的32的指针
RECT结构 typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom; } RECT;
窗口 按钮 图标 滚动条 输出设备 控制 文件 句柄是一个4字节长的数值,用于标识应用程序中不同的对象和同类对象中不同的实例 句柄类型 应用程序通过 句柄访问相应 的对象信息 常用句柄类型及其说明 HWND 窗口句柄 HDC 设备环境句柄 HBITMAP 位图句柄 HCURSOR 光标句柄 HICON 图标句柄 HFONT 字体句柄 HMENU 菜单句柄 HPEN 画笔句柄 HFILE 文件句柄 HBRUSH 画刷句柄HINSTANCE 当前实例句柄
Windows程序一般都包含windows.h头文件,它包含了其他windows头文件.这些头文件的某些也包含了其他的头文件。其中最重要的和最基本的是: Windows程序一般都包含windows.h头文件,它包含了其他windows头文件.这些头文件的某些也包含了其他的头文件。其中最重要的和最基本的是: • windef.h基本类型定义; • winnt 支持unicode的类型定义; • winbase.h 内核函数; • winuser.h 用户接口 • wingdi.h 图形设备接口
Win32程序First的解读 #include "stdafx.h" #include "First.h“ #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_FIRST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); //注册窗口类 // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; }
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FIRST); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }
ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_FIRST); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCTSTR)IDC_FIRST; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); }
WNDCLASSEX结构定义在winuser.h中: typedef struct tagWNDCLASSEXW { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICON hIconSm; } WNDCLASSEX;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
创建窗口函数 CreateWindow()函数原型: HWND CreateWindow( LPCTSTR lpszClassName,//窗口类名 LPCTSTR lpszTitle , //窗口标题名 DWORD dwstyle, //窗口的样式 int x,int y, //窗口坐标 int nwidth,int height, //窗口宽度和高度 HWND hwndParent , //父窗口句柄 HMENU hMenu, //菜单句柄 HINSTANCE hInstance,//应用程序句柄 LPVOID lpParam //参数指针 );
常用窗口样式 标识 说明 WS_BORDER 创建一带边框的窗口 WS_CAPTION 创建一带标题栏的窗口 WS_VSCROLL 创建一带垂直滚动条的窗口 WS_MAXIMIZEBOX 创建一带最大化框的窗口 WS_MAXIMIZE 创建一最大尺寸的窗口 WS_MINIMIZEBOX 创建一带最小化框的窗口 WS_MINIMIZE 创建一最小尺寸的窗口 WS_OVERLAPPED 创建一带边框和标题的窗口 WS_OVERLAPPEDWINDOW 创建一带边框、标题栏、系统菜单及最大、 最小 化框的窗口 WS_POPUP 创建一弹出式窗口 WS_POPUPWINDOW 创建一带边框和系统菜单的弹出式窗口 WS_SYSMENU 创建一带系统菜单的窗口 WS_HSCROLL 创建一带水平滚动条的菜单
显示窗口ShowWindow • ShowWindow(hwnd, nCmdShow); nCmdShow的值: SW_HIDE 隐藏 SW_SHOWNORMAL 正常 SW_SHOWMINIMIZE 最小化, SW_RESTORE 恢复 SW_SHOWNOACTIVE 不激活 • UpdateWindow(hwnd); //更新窗口
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) {
PAINTSTRUCT结构 typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT;
case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break;
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TCHAR* szHello; szHello = _T("Hello World Win32!"); RECT rt; GetClientRect(hWnd, &rt); DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER|DT_SINGLELINE|DT_VCENTER); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }
WM_PAINT产生的情况 均产生 WM_PAINT 消息 用户区移动或显示 用户窗口改变大小 程序通过滚动条滚动窗口 下拉式菜单关闭并需要恢复被覆盖的部分 Windows清除对话框等对象,并需要恢复被覆盖的部分
Windows图形设备接口 • GDI(Graphics Device Interface)和windows 设备驱动程序来支持设备无关性。 • 设备描述表(Device Context)是一个用来确定任何设备的GDI输出位置和形象的属性集合。 • 应用程序并不能直接存取设备描述表,但是,应用程序可以使用描述表的句柄 来间接地存取设备描述表及其属性。 • 当程序为设备描述表要求一个句柄时,就将创建一个设备描述表,它包含了所有的属性和默认值,应用程序可以修改这些属性。 应用程序对图形的操作参照设备描述表的属性执行。
Windows绘图的一般步骤 • 获取设备环境 • 创建绘图工具(修改设备描述表的属性) • 1). 创建绘图工具 • 2). 选入设备环境 • 使用常用绘图函数绘制图形 • 删除绘图工具
获取设备环境 • BeginPaint hdc=BeginPaint(hwnd, &ps); EndPaint(hwnd,&ps); • GetDC hdc=GetDC(hwnd); ReleaseDC(hwnd,hdc);
绘图工具 • 画笔的使用 创建: HPEN hp; hp=GetStockObject(BLACK_PEN); hp=CreatePen(int nPenStyle,int nwidth,COLORREF rgbColor); 选入设备环境 SelectObject(hdc,hp); 删除画笔: DeleteObject(hp);
画刷的使用 创建: HRUSH hBr; hBr=GetStockObject(nBrushStyle); hBr=CreateBrush(COLORREF rgbColor); hBr=CreateHatchBrush(int nHatchStyle, COLORREF rgbColor); 选入设备环境 SelectObject(hdc,hBr); 删除画刷:DeleteObject(hBr); • 设置颜色 RGB(255, 0, 0) //Red, Green, Blue
常用绘图函数 • BOOL MoveToEx(HDC hdc,int x,int y,LPPOINT lpPoint); //画笔位置 • BOOL LineToEx(HDC hdc,int x,int y);//画线 • BOOL PolyLine(HDC hdc,LPPOINT lpPoints,int nCount); // 画多边形 • BOOL Arc(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); //画弧 • BOOL Pie(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); //画饼图
//画矩形 • BOOL Rectangle(HDC hdc,int x1,int y1,int x2,int y2) // 画矩形并用当前刷子填充 • BOOL RoundRect(HDC hdc,int x1,int y1, int x2,int y2,int nHeight,int nWidth); //画椭圆并用当前刷子填充 • BOOL Ellipse(HDC hdc,int x1,int y1,int x2,int y2); //画多边形并填充 • BOOL Polygon(HDC hdc,LPPOINT lpPoints, int nCount);
case WM_PAINT: hDC=BeginPaint(hWnd,&PtStr); hPen=(HPEN)GetStockObject(BLACK_PEN); hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH); SelectObject(hDC,hBrush); SelectObject(hDC,hPen); RoundRect(hDC,50,120,100,200,15,15); SelectObject(hDC,hBrush); Ellipse(hDC,150,50,200,150); SelectObject(hDC,hBrush); Pie(hDC,250,50,300,100,250,50,300,50); EndPaint(hWnd,&PtStr); break;
文本的输出方法与字体的设置 文本输出使用TextOut()或DrawText()函数。 文字的大小与字体都是由设备描述表中的字体相关属性控制的,其用法与画笔和画刷相类似,使用方法请参考MSDN。
DrawText()和TextOut()函数 int DrawText( HDC hDC, // handle to DC LPCTSTR lpString, // text to draw int nCount, // text length LPRECT lpRect, // formatting dimensions UINT uFormat// text-drawing options ); BOOL TextOut( HDC hdc, // handle to DC int nXStart, // x-coordinate of starting position int nYStart, // y-coordinate of starting position LPCTSTR lpString, // character string int cbString// number of characters );
控件概述 • 控件具有窗口属性。可以使用ShowWindow()和MoveWindow()等函数来管理控件 • 以独立的子窗口存在:通过调用CreateWindow() 或CreateWindowsEx() 创建,通过SenMessage (hDlgWnd,BM_SETCHECK,1,0)向子窗口发送消息 • 子窗口向父窗口发送WM_COMMAND消息通信 • 标准控件有:BUTTON,COMBOBOX,EDIT, LISTBOX, SCROLLBAR ,STATIC等
子窗口控件操作函数 • (1)激活或禁止窗口 • EnableWindow(HWND hwnd,BOOL bEnable); • (2)移动或改变窗口大小 • BOOL MoveWindow(HWND hwnd,int x,int y, int nWidth,int nHeight,BOOL bReprint); • (3)设置窗口标题或文本 • BOOL SetWindowText(HWND hwnd,LPCTSTR lpszString); • BOOL SetDlgItemText(HWND hdlg,int ID, LPCTSTR lpszString);
(4)获得窗口标题或文本 • Int GetWindowText(HWND hwnd,LPSTR lpszstring,int nMax); • Int GetDlgItemText(HWND hdlg,int ID,LPSTR lpszString,int nMax); • 返回值从指定的控获取的文本字节数 (5)关闭窗口 • BOOL DestroyWindow(HWND hwnd);
编辑框控件 • (1)创建使用CreateWindow或CreateWindowEx函数 • 样式:ES_AUTOHSCROLL, ES_AUTOVSCROL L,ES_CENTER,ES_MULTILINE等十种 (2)消处传递与按钮相同 • 编辑框向应用程序EN_SETFOCUS, EN_KILLFOCUS ,EN_CHANGE,EN_UPDATE等 • 应用程序向编辑框:EM_GETRECT, EM_SETRECT, EM_SETHANDLE,EM_GETHANDLE,EM_LINELENGHT,EM_GETFONT,EM_GETSEL等