Windows 编程技术 2005年9月 2018/12/31
Windows API for 2000/XP实例精解 第一章 概述 第二章 文本输出和滚动条 第三章 深入GDI 第四章 键盘、鼠标和计时器 第五章 资源 第六章 Windows 2000标准控件 第七章 驱动器、目录和文件 2018/12/31
第一章 主要内容 Windows 家族简介 Win32 API 基础 Win32 API 应用程序框架结构 Unicode字符 第一章 主要内容 Windows 家族简介 Win32 API 基础 Win32 API 应用程序框架结构 Unicode字符 2018/12/31
第一章 §3 Win32 API 应用程序框架结构 Demo: “Hello” 应用程序实例 i 当按下键盘上的任意一个键时,窗口显示的文本颜色将随机地发生改变。 应用程序实例 i 2018/12/31
第一章 §3 Win32 API 应用程序框架结构(二) 头文件的类型 函数和数据结构 消息结构 窗口类结构 矩形结构 消息机制 消息循环 消息及消息处理 句柄、标识符 i i i i i i i i i 2018/12/31
头文件的类型 在每一个用C编写的Windows程序中,都会用到一个头文件WINDOWS.H。它是包含了其它头文件的综合文件。 WINDEF.H 基本类型的定义。 WINNT.H 支持Unicode的类型定义。 WINGDI.H 图形设备接口的定义。 WINUSER.H 用户接口的定义。 WINBASE.H 内核函数的定义。 WINSOCK.H和WINSOCK2.H 用于网络通信的套接字的定义。 2018/12/31
函数和数据结构 在Windows应用程序中有一个入口函数WinMain int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow) 为了与早期的版本兼容,这里未用,其值总是NULL 程序运行时的显示方式(正常、最大化、最小化等) 该句柄唯一地标识了该程序 运行程序的命令行参数串 2018/12/31
消息结构 消息结构定义一个用于发送的消息,在程序接收到消息后,根据其中包含的信息做出相应的处理。 typedef struct tagMSG { HWND hwnd; //获得消息的窗口句柄 UINT message; //消息标志 WPARAM wParam; //消息的附加信息 LPARAM lParam; //消息的附加信息 DWORD time; //消息的发送时间 POINT pt; //当消息发送时,鼠标所处的屏幕位置 } MSG, *PMSG 2018/12/31
窗口类结构 窗口类用来标识处理窗口消息的窗口过程。在一个窗口类的基础上可以创建多个窗口的实例。 例如: typedef struct tagWNDCLASSW { UINT style; // 窗口类的风格 WNDPROC lpfnWndProc; // 指向窗口过程的指针 int cbClsExtra; // 分派给窗口类的扩展的字节数 int cbWndExtra; // 分派给窗口实例的扩展的字节数 HINSTANCE hInstance; // 窗口的实例句柄 HICON hIcon; // 类图标的句柄 HCURSOR hCursor; // 类鼠标指针的句柄 HBRUSH hbrBackground; // 刷新背景所用的画刷的句柄 LPCWSTR lpszMenuName; // 窗口类包含的菜单的名称 LPCWSTR lpszClassName; // 窗口类名 } WNDCLASSW, *PWNDCLASSW; 例如: 2018/12/31
窗口类结构实例 WNDCLASS wc; // Register the main application window class. //............................................ wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = lpszAppName; 2018/12/31
注册窗口类 if ( !RegisterClass( &wc ) ) return( FALSE ); 2018/12/31
创建窗口函数 HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ); 2018/12/31
消息机制 主要解决两个问题 消息循环 消息及消息处理 i i 2018/12/31
消息循环 msg结构 只要从消息队列中取出的消息的message域不为WM_QUIT,则返回非零, while( GetMessage( &msg, NULL, 0, 0) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } 只要从消息队列中取出的消息的message域不为WM_QUIT,则返回非零, 把消息发送到窗口处理程序中,或者说,回调窗口处理程序 进行一些键盘消息转换 2018/12/31
消息及消息处理 窗口过程接收的每一个消息都是用数值标示的,并在WINUSER.H中作了定义。 例如:WM_PAINT, WM_KEYDOWN, WM_DESTROY 一般用switch和case的结构来确定窗口过程接收到的是什么消息。 例如 2018/12/31
switch case结构 switch (message) { case WM_CREATE: ...... return 0 ; case WM_SIZE: case WM_PAINT : case WM_DESTROY : PostQuitMessage (0) ; } return DefWindowProc (hwnd, message, wParam, lParam) ; 2018/12/31
WM_PAINT消息 (a) 在创建窗口时,客户区将变得无效。 (b) 改变应用程序窗口的大小时,窗口的整个客户区将变得无效。 此时,整个客户区都是无效的。在程序运行函数UpdateWindow时,将发送第一个WM_PAINT的消息,只是窗口过程在客户区域画一些东西。 (b) 改变应用程序窗口的大小时,窗口的整个客户区将变得无效。 因为在定义窗口类的第一个域style时,曾经将标志设置为CS_HREDRAW和CS_VREDRAW,这一设置将指示Windows在窗口改变大小后,使整个窗口无效。此时,又将发送一个WM_PAINT的消息。 (c) 在移动窗口并发生窗口重叠时,窗口客户区将变得无效。 此时,Windows将不会保存本窗口中被另外一个窗口覆盖部分的客户区内容。此时,窗口客户区将变成无效,发送一个WM_PAINT的消息。 2018/12/31
对WM_PAINT消息的处理 对消息WM_PAINT的处理,一般都从BeginPaint函数调用开始,其调用方法是: HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hWnd, &ps); 结束时,一般通过调用EndPaint函数完成, EndPaint(hWnd, &ps); 2018/12/31
WM_KEYDOWN消息 当系统侦测到用户键盘按键信息时,就会产生一个WM_KEYDOWN的消息 2018/12/31
WM_DESTROY消息 这个消息指示Windows根据用户输入的命令来清除窗口。该消息在用户单击“Close”按钮或在程序的系统菜单(通过单击窗口图标或使用快捷键[Alt+space]获得)。 通过调用函数PostQuitMessage以标准的方式响应WM_DESTROY消息以退出消息循环。 2018/12/31
2 1 8 3 5 7 6 WinMain ( hInst, hPrev, … ) { MSG msg; ReigsterClass (…); CreateWindow (…); ShowWindow (…); UpdateWindow (…); While ( GetMessage (&msg…)) { TranslateMessage (…); DispatchMessage (…); } return msg.wParam; WM_CREATE 消息队列 2 1 8 WM_QUIT 3 WndProc ( hWnd, msg, wParam, lParam ) { switch ( msg ) { case WM_CREATE : … case WM_PAINT : case WM_KEYDOWN : case WM_DESTROY : PostQuitMessage(0); break; default : return( DefWindowProc ( ... ) ); } return (0); WM_CLOSE 5 7 WM_DESTROY case WM_CLOSE : DestroyWindow (...); 2018/12/31 6
1、初始化过程调用CreateWindow,为程序建立了一个窗口,送出WM_CREATE直接给窗口函数,后者可在此做些初始化操作 2、程序运行过程中,不断以GetMessage从消息队列中抓取消息,如果这个消息是WM_QUIT, GetMessage会传回0而结束循环,进而结束整个程序 3、 DispatchMessage把消息分派至窗口函数。消息将在该处被识别并处理 4、程序不断进行2和3的操作 5、当使用者按下系统菜单的Close命令项时,系统送出WM_CLOSE。通常程序不拦截此消息,于是DefWindowProc处理它 6、 DefWindowProc收到WM_CLOSE后,调用DestroyWindow把窗口清除。 DestroyWindow本身又会送出WM_DESTROY 7、程序对WM_DESTROY的标准反应是调用PostQuitMessage 8、 PostQuitMessage没什么其它操作,就只送出WM_QUIT消息,准备让消息循环中的GetMessage取得,如步骤2,结束消息循环 2018/12/31
句柄 句柄是一个32位的数,代表一个对象。常用的句柄有: HANDLE:指向对象的句柄。 HBITMAP:指向位图的句柄。 HBRUSH:指向画刷的句柄。 HCURSOR:指向鼠标光标的句柄。 HDC:指向设备环境的句柄。 HFILE:指向文件的句柄。 HGLOBAL:指向全局内存块的句柄。 HMETAFILE:指向元文件的句柄。 HMODULE:指向模块的句柄。 HMUNU:指向菜单的句柄。 HPEN:指向画笔的句柄。 HWND:指向窗口的句柄。 2018/12/31
标识符 在Windows头文件中定义 CS 窗口类风格选项 CW 创建窗口选项 WM 窗口消息选项 MB 消息框选项 IDI 图标的ID号 IDC 光标的ID号 2018/12/31
数据类型 以C/C++的类型作为Windows程序的基本类型,为了区别某些基本类型相同,但意义不同的类型,因此在WINDOWS.H文件中用容易记忆的标示符进行重新定义,如 HANDLE, HWND, UINT, BYTE, WORD, DWORD, LONG, BOOL, LPSTR等等。 i 2018/12/31
Unicode字符是ASCII字符编码的扩展。 在Unicode中,每个字符是16位的。 在C语言中,涉及到的字符都只占一个字节,即sizeof(char)为1。引入Unicode和宽字符的概念后,char数据类型没有改变。但用wchar_t来表示基于双字节的。即: typedef unsigned short wchar_t; 2018/12/31
第二章 主要内容 窗口过程与消息 文本输出 滚动条 2018/12/31
窗口过程与消息 窗口过程总是与已注册的特定窗口类相关联的,一个应用程序可以有几个窗口类,基于每个窗口类都可以创建多个窗口(通过CreateWindow等函数创建)。 WndProc被声明为CALLBACK回调函数,回调函数是输出函数中特殊的一种,能够在Windows环境下直接调用。一个应用程序至少有一个活动的窗口,因为在应用程序处理消息时,Windows会调用回调函数,即窗口过程。 窗口过程的名字可以任意指定,只需与窗口类结构的lpfnWndProc域指定的名字相同即可。 2018/12/31
CreateWindow函数实例 hWnd = CreateWindow( lpszAppName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, NULL, hInstance, NULL ); 2018/12/31
窗口处理函数WndProc { switch( uMsg ) { case WM_PAINT : break; LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_PAINT : break; case WM_DESTROY : PostQuitMessage(0); default : return( DefWindowProc( hWnd, uMsg, wParam,lParam ) ); } return( 0L ); 2018/12/31
lpfnWndProc域 // Register the main application window class. WNDCLASS wc; // Register the main application window class. //............................................ wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = lpszAppName; wc.lpszClassName = lpszAppName; 2018/12/31
文本输出 文本输出是Win32应用程序最常见的客户区图形输出(文本输出也被看做是GDI图形输出),在字处理、排版等系统中应用广泛。 文本输出程序示例 获取设备描述表 WM_PAINT消息的响应和处理 字体的设置 文本的格式化输出 文本输出函数比较 2018/12/31
文本输出程序示例 Demo: TextOut1.dsw 他利用GDI函数TextOut输出了两段文本,并采用了一些文本格式化技巧,实现文本对齐等。 SetTextAlign实现文本对齐等。 SetTextAlign(hdc,A_RIGHT| A_TOP); 常用的文本对齐样式有:TA_LEFT,TA_CENTER,TA_RIGHT,TA_TOP,TA_BOTTOM,TA_BASELINE 2018/12/31
获取设备描述表 设备描述表(DC:Device Context)是GDI内部保存的一种数据结构,它定义了一系列的图形对象、相关的属性及绘图模式等一些信息。Windows GDI函数依赖于设备描述表,实际上这些函数在设备描述表环境中显示文本和图形设备描述表是Windows应用程序,也是输出设备之间的桥梁。所以,在屏幕上和打印机上输出文本和图形的操作过程是一样的。当程序获得设备描述表句柄后,Windows就是用默认的属性值填充设备描述表结构。然后就可以用这些获得的设备环境使用GDI函数绘制文本和图形了。当然,有一些GDI函数可以获取和改变设备描述表的属性值。 2018/12/31
获取设备描述表(2) 调用BeginPaint返回设备描述表句柄 调用GetDC函数获得设备描述表句柄 使用CreateDC函数获得设备描述表句柄 其它获得设备描述表句柄的函数 2018/12/31
调用BeginPaint返回设备描述表句柄 PAINTSTRUCT ps ; hdc = BeginPaint (hwnd, &ps) ; PAINTSTRUCT的结构: typedef struct tagPAINTSTRUCT { HDC hdc; // 设备描述表句柄 BOOL fErase; // 擦除无效矩形背景 RECT rcPaint; // 标识无效矩形 BOOL fRestore; // 保留 BOOL fIncUpdate; // 保留 BYTE rgbReserved[32]; // 保留 } PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT; 2018/12/31
在一些非WM_PAINT消息的处理期间,也许程序需要绘制客户区或者想得到有关设备描述表的信息。这是利用GetDC函数可以返回设备描述表句柄, hdc=GetDC(hwnd); 用GetDC获得的设备描述表句柄需要用ReleaseDC函数释放。 2018/12/31
使用CreateDC函数获得设备描述表句柄 hdc = CreateDC(pszDriver,pszDevice,pszOutput,pData); 同样,利用DeleteDC(hDC)函数可以释放设备描述表句柄。 2018/12/31
其它获得设备描述表句柄的函数 设备描述表 描述 获取和释放设备描述表句柄的函数 视频显示器 支持在视频显示器的客户区中绘图 BeginPaint和EndPaint GetDC和ReleaseDC GetDCEx和ReleaseDC CreateDC和DeleteDC 打印机设备 支持在打印机和绘图仪上的绘图操作 内存设备 把一部分内存视为虚拟设备,对内存中的数据(如位图)直接操作 CreateCompatibleDC和DeleteDC 设备信息 返回默认的设备数据 2018/12/31
WM_PAINT消息的响应和处理 Windows是一个多任务环境,显示设备视为多个应用程序公用的,某个应用程序的窗口上面可能被对话框或窗口覆盖。当撤销这些对话框或窗口时,这个应用程序窗口中就有一个“空洞”,这个“空洞”就是一块无效的客户区域。像这种情况还很多。 比如改变窗口尺寸后, 客户区的部分内容被遮盖, 窗口最消化、客户区的滚动等 WM_PAINT消息在Windows消息队列中的优先级很低,这就是其他许多消息能够先于WM_PAINT消息被送交给窗口过程处理。只有在没有其他消息的情况下,才从队列中取出WM_PAINT消息进行处理。这样做是为了让应用程序首先完成影响窗口显示结果的其他操作,不致因为频繁地执行输出操作而引起显示器的闪烁。 2018/12/31
InvalidateRect 重画一个指定矩形框范围内的客户区 InvalidateRgn 重画一个指定范围内的客户区。 WM_PAINT消息的响应和处理(2) Windows并非WM_PAINT消息的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息。这两个函数把客户区部分或全部标记成无效区域而要求重新显示。 InvalidateRect 重画一个指定矩形框范围内的客户区 InvalidateRgn 重画一个指定范围内的客户区。 2018/12/31
InvalidateRect和InvalidateRgn BOOL InvalidateRect (HWND hWnd, CONST RECT *lpRect, BOOL bErase); BOOL InvalidateRgn (HWND hWnd, HRGN hRgn ,BOOL bErase); 2018/12/31
字体的设置 使用GetTextMetrics函数获取设备描述表中的字体信息 使用CreateFont或CreateFontIndirect函数创建逻辑字体 使用SelectObject函数将字体选入DC 2018/12/31
文本的格式化输出 Windows API提供了对文本输出格式的强有力的支持,主要有三类函数可以用于文本的格式化。 获取和设置设备描述表的文本格式化属性的函数。 获取字体宽度信息的函数。 获取字符串宽度和高度信息的函数。 2018/12/31
文本的格式化函数(1) 1 文本对齐函数 (1) SetTextAlign 设置文本基于输出参考点的对齐方式。 (2) GetTextAlign 获取文本基于输出参考点的对齐方式。 2018/12/31
文本的格式化函数(2) 2 调整字符间距函数 (1) SetTextCharsetExtra 用于在文本输出是调整字符的输出间距,默认的字符间距为零。 (2) GetTextCharsetExtra 程序可以通过本函数获取当前的字符间距。 2018/12/31
文本的格式化函数(3) 3 文本和背景颜色函数 (1) SetTextColor 改变指定环境中的文本颜色。 (2) SetBkColor 改变指定环境中的背景颜色。 (3) GetTextColor 获得指定环境中的文本颜色。 (4) GetBkColor 获得指定环境中的背景颜色。 2018/12/31
文本的格式化函数(4) 4 段落对齐函数 (1) GetTextExtentPoint32 用于计算指定字符串的长度和宽度。 (2) SetTextJustification 用于指定在字符串中,空格应占的字符数。 2018/12/31
文本输出函数比较 DrawTextEx ExtTextOut TabbedTextOut 2018/12/31
滚动条 滚动条的特性和设置 滚动条的创建:在CreateWindow的第三个参数即窗口风格表示附中包括风格WS_VSCROLL和WS_HSCROLL 改进的文本输出程序实例 TextOut2.dsw 滚动条消息处理 当用户单机滚动条或者拖曳滚动框时,Windows给窗口过程发送WM_VSCROLL和WM_HSCROLL消息。这两个消息的wParam参数的低字节包含了一个称为“通知码”的标识符,分别标识每条消息产生的原因。 2018/12/31
WS_VSCROLL设置 hwnd = CreateWindow (szAppName, TEXT ("TextOut2 with Scroll"), WS_OVERLAPPEDWINDOW | WS_VSCROLL , CW_USEDEFAULT, NULL, hInstance, NULL) ; 设置垂直滚动条 2018/12/31
滚动条通知码 #define SB_LINEUP 0 #define SB_LINELEFT 0 #define SB_LINEDOWN 1 #define SB_LINERIGHT 1 #define SB_PAGEUP 2 #define SB_PAGELEFT 2 #define SB_PAGEDOWN 3 #define SB_PAGERIGHT 3 #define SB_THUMBPOSITION 4 #define SB_THUMBTRACK 5 #define SB_TOP 6 #define SB_LEFT 6 #define SB_BOTTOM 7 #define SB_RIGHT 7 #define SB_ENDSCROLL 8 2018/12/31
滚动条信息结构和相关函数 滚动条信息结构和相关函数 typedef struct tagSCROLLINFO { UINT cbSize; // SCROLLINFO结构的大小 UINT fMask; // 标定对结构进行的操作方式 int nMin; // 滚动位置最小值 int nMax; // 滚动位置最大值 UINT nPage; // 窗口显示的页的大小 int nPos; // 滚动条当前位置 int nTrackPos; // 当前拖动时滚动框的位置 } SCROLLINFO, *SCROLLINFO; fMask是一些以SIF为前缀的标志,例如,当需要设置滚动条位置时,就需要将其设置为SIF_POS标志。其他标志还有SIF_RANGE和SIF_PAGE等。 2018/12/31
滚动条信息结构和相关函数(2) 1 SetScrollInfo 此函数用于设置滚动条的有关信息 2 GetScrollInfo 此函数用于获得滚动条的有关信息 3 ScrollWindowEx 滚动指定的客户区内窗口的内容 2018/12/31
第三章 主要内容 Windows GDI 的基本概念和原理 颜色、画笔和画刷 GDI 绘图函数 GDI 映射模式 位图 2018/12/31
Windows GDI的基本概念和原理 Windows GDI即图形设备接口,是Windows系统的重要组成部分,是Windows系统实现图形界面的基础。 GDI 绘图函数具有设备无关性 从程序员的角度看,GDI提供了几百个函数调用和一些相关的结构、宏和数据类型,便于程序员对显示器、打印机等硬件设备进行图输出 设备描述表;程序有绘图请求时被创建并得以维持,他负责为程序准备相关的信息,起到为程序屏蔽具体物理设备的作用。当程序希望获得具体物理设备信息时,可以通过一些GDI函数来获得。 2018/12/31
颜色、画笔和画刷 画笔和画刷是应用程序进行图形输出时最常用的工具,应用程序能够选择Windows系统备用的画笔和画刷进行绘图,也能够创建自定义的画笔和画刷,并将他们选入设备描述表中,按照自定义的风格进行图形绘制。 色度学理论认为,任何颜色都可以由红、绿、蓝三种基本颜色按不同的比例混合得到,例如:黄色可以由红、绿各一半混合而成。因此,红、绿、蓝被称为三原色,简称RGB三原色。 2018/12/31
颜色 Windows采用32位无符号长整数表示色彩 COLORREF COLORREF RGB (BYTE r, BYTE g, BYTE b) 获取红、绿、蓝的分量值: BYTE GetRValue (DWORD rgb); BYTE GetGValue (DWORD rgb); BYTE GetBValue (DWORD rgb); GetDeviceCaps (HDC hdc, int nIndex) 2018/12/31
关于画笔 逻辑画笔是一种GDI对象,有线宽、线形、颜色等属性 hPen = GetStockObject(WHITE_PEN); 备用画笔(stock pen) hPen = GetStockObject(WHITE_PEN); hOldPen = SelectObject(hdc,hPen); 自定义画笔 Cosmetic: 线宽(width)、线形(style)、颜色(color) Geometric:线宽(width)、线形(style)、颜色(color) 式样、填充图案、端点样式、连接样式 2018/12/31
关于画笔 创建自定义画笔所使用的函数 创建画笔的工作大多在WM_CREATE消息期间完成 CreatePen CreatePenIndirect ExCreatePen 创建画笔的工作大多在WM_CREATE消息期间完成 Cosmetic画笔 Geometric画笔 2018/12/31
关于画笔 DeleteObject(hPen); SelectObject(hdc,hOldPen); 在WM_DESTROY消息期间,应用程序即将结束,程序不再需要以创建的逻辑画笔,所以应该将这些画笔删除以释放其占用的系统资源。 DeleteObject(hPen); SelectObject(hdc,hOldPen); 画笔程序实例 PenCreating.cpp 2018/12/31
画刷相关函数和结构 CreateSolidBrush 创建一个solid画刷(solid画刷使用指定的颜色定义的纯色画刷) GetStockObject 创建一个stock画刷 CreateHatchBrush 创建一个hatch画刷,hatch画刷是以一定的图案进行填充的位图,图形不在以纯色填充,而是一些纹理图案。 CreatePatternBrush 创建基于GDI位图的pattern画刷。 CreateBurshIndirect 此函数使用定义的结构间接创建画刷。 2018/12/31
GDI绘图函数与结构 GDI绘图函数是实现图形界面窗口内容的最基本的工具 1 画点和画线 2 绘制曲线 3 绘制填充区域 2018/12/31
画点和画线 (1) SetPixel 此函数用于设置指定点的颜色信息 (2) GetPixel 此函数用于获得指定点的颜色信息 (3) LineTo 此函数使用设备描述表中的画笔来画出一条线 (4) MoveToEx 此函数用于移动画笔到指定的点 2018/12/31
画点和画线(2) (5) Polyline 此函数用于一次绘制一条连续直线,各段直线的段点由数组指定。 (6) PolylineTo 此函数把当前画笔所在的点作为连续直线的起点,并把连续直线的终点作为新的画笔位置点,用于一次绘制一条连续直线。 (7) PolyPolyline 此函数用于一次绘制几条连续直线,常用在希望一次性地定义并绘制整个图形 2018/12/31
绘制曲线 (1) Arc 此函数以(0,0)为基准点绘制椭圆弧线。在默认情况下,椭圆弧按逆时针方向绘制。 (2) ArcTo 绘制椭圆弧线。在默认情况下,椭圆弧按逆时针方向绘制。有一条直线从当前位置连到椭圆弧开始点,当前位置更新为椭圆弧结束点。 2018/12/31
绘制曲线 (3) PolyBezier 此函数用于绘制一条或多条三次Bezier样条曲线。 (4) PolyDraw 2018/12/31
绘制填充区域 (1) Rectangle 从左上角(upX,upY)向右下角(lowX,lowY)绘制矩形.用当前笔画显示矩形,用当前画刷自动填充矩形. (2) Ellipse 通过指定椭圆的边界矩形来定义椭圆. (3) Pie 扇形图是一个包含弧和两条线的对象,这两条线分别以弧的端点和中心点为端点 (4) Chord 此函数用于绘制弦图 (5) RoundRect 绘制圆角矩形 (6) Polygon 绘制多边形的填充区域 2018/12/31
GDI映射模式 坐标系统 几种映射模式的比较 窗口和视口 映射模式程序实例 MapMode 2018/12/31
坐标系统 在Windows应用程序中,有两种坐标系统:设备坐标和逻辑坐标。 设备坐标系统直接与硬件设备的显示相关,以像素为度量单位。水平轴(即x轴)的正方向从左向右,垂直轴(即y轴)的正方向从上向下,并且整个坐标轴的单位和方向固定不变。设备坐标系统可分为:屏幕坐标系统、窗口坐标系统和客户区坐标系统。 逻辑坐标系统与设备描述表的属性映射模式相关,他是一种允许自定义的坐标系统,坐标轴方向、单位和原点位置都可以重新定义。 2018/12/31
坐标系统(续) 绝大多数GDI函数都使用逻辑坐标,而非GDI函数都永远使用设备坐标,所有的消息也都使用设备坐标。 逻辑坐标系统下绘出的图形必须映射到设备坐标系统下,才能在屏幕上显示出来。 使设备坐标和逻辑坐标下的坐标相互转换的函数: BOOL DPtoLP( HDC hdc, LPPOINT lpPoints, // array of points int nCount // count of points in array ); BOOL LPtoDP( HDC hdc, LPPOINT lpPoints, int nCount ); 2018/12/31
几种映射模式的比较 int SetMapMode(HDC hdc,int mode); 说明:mode指定新的映射模式, 映射方式 逻辑单位 坐标系正方向 MM_TEXT 像素 Y向下,X向右 MM_LOMETRIC 0.1毫米 Y向上,X向右 MM_HIMETRIC 0.01毫米 MM_LOENGLISH 0.01英吋 MM_HENGGLIST 0.001英寸 MM_TWIPS 1/1440英寸 MM_ISOTROPIC 任意(x=y) 可选 MM_ANISOTROPIC 任意 说明:mode指定新的映射模式,可以由如下一些情况 int SetMapMode(HDC hdc,int mode); 说明:mode指定新的映射模式, 2018/12/31
窗口和视口 窗口和视口是WindowsGDI种两个很重要的概念,从逻辑坐标映射为设备坐标实际上就是从窗口到视口的映射。 窗口是以逻辑单位为单位指定窗口的新的水平尺寸和垂直尺寸。 视口是基于设备坐标的,以像素为单位,指定视口的新的水平尺寸和垂直尺寸。 视口有视口原点和视口范围两个基本属性: 2018/12/31
窗口和视口函数 BOOL SetWindowExtEx (HDC hdc, int Xextent, int Yextent, LPSIZE size); BOOL SetViewportExtEx (HDC hdc, int Xextent, int Yextent, LPSIZE size); BOOL SetViewportOrgEx (HDC hdc, int X, int Y, LPPOINT OldOrg); 2018/12/31
位图 设备相关位图DDB DDB位图程序实例screensnap.c 设备无关位图DIB DIB位图程序实例DIBtoDDB.c 位图是Windows应用程序中存储图像信息的方法之一。用于表示来自真实世界的复杂图像。从结构上来说,位图是一个二维像素位数组,通常按照从左向右、自顶向下的顺序记录各像素位的信息。 设备相关位图DDB DDB位图程序实例screensnap.c 设备无关位图DIB DIB位图程序实例DIBtoDDB.c 2018/12/31
内存设备描述表 内存设备描述表位于内存中,并不是真正的图形输出设备,程序也不能直接显示存储在其内的信息。同时,创建的GDI位图对象仅能被选入内存设备描述表中。由于这些特性,在位图的输出过程中,内存设备描述表发挥了巨大的作用,可是实现许多特殊的位图显示效果。例如,程序可以在选入内存设备描述表种的位图中绘图,然后“拷贝”到显示设备描述表中进行显示;通过创建多个内存设备描述表,可以对选入其内的位图进行像素位的光栅操作,以实现某些特殊的显示效果。 HDC hdcMem=CreateCompatibleDC(hDC); HBITMAP hmemBM=CreateCompatibleBitmap(hDC); SelectObject(hdcMem,hmemBM); 2018/12/31
DDB位图操作函数BitBlt BOOL BitBlt( HDC hdcDest, int nXOrignDest, int nYOrignDest, int nWidth, int nHeight, HDC hdcSrc, int nXOrignSrc, int nYOrignSrc, DWORD dwRop); BitBlt(hdcMem, 0, 0, cxScreen, cyScreen, hdcDeskTop, 0, 0 , SRCCOPY); 2018/12/31
BitBlt参数示例图 2018/12/31
实现位图透明的方法 前景:透明的地方为白色,不透明的地方可以任意色(A) 背景:任意色(B) 增加一个与前景位图大小一样的黑白位图(Mask),前景中需要透明的地方使该Mask为黑色,而不透明的地方使该Mask为白色 两次调用BitBlt实现: (背景 按位或SRCPAINT Mask ) 按位与SRCAND 前景 人: ( B | 1 ) & A A 底: ( B | 0 ) & 1 B 或 =〉 与 2018/12/31
设备无关位图 与DDB位图相比,DIB是一种外部的位图格式,经常存储为以BMP为后缀的位图文件(有时也以DIB为后缀),非常适于图像交换。 要点: DIB位图的结构 DIB位图的显示和装载 DIB位图转换DDB位图 2018/12/31
DIB位图的结构 应用程序可以完全访问DIB为图的内容,并把他们加载到内存中;也可以创建自己定义的DIB为图,并把他们存入Windows的位图文件(BMP)中。 需要结构: .位图文件头结构 BITMAPFILEHEADER .位图信息结构 BITMAPINFOHEADER .位图颜色表 RGBQUAD .位图像素数据 2018/12/31
DIB位图转换DDB位图 CreateDIBitmap 此函数用于将DIB位图转换为DDB位图。 LoadBitmap 在资源文件中定义位图后,利用此函数装载DIB位图并得到转换后的DDB位图句柄 LoadImage 可从资源或文件中装载DIB位图,并转换为DDB位图 2018/12/31
第四章 主要内容 键盘和鼠标一直以来都是应用程序的标准输入设备,尽管目前的Windows 2000和Windows XP所支持的可作为输入设备的类型越来越多,但暂时还离不开传统的键盘和鼠标。在新一代操作系统下,传统的输入设备又增加了许多功能,例如,从Windows 2000系统开始,Windows应用程序支持鼠标的一种称为Xbuttons的功能,能使用户更方便地进行网络浏览。计时器在Windows应用程序中也有很广泛的应用。 键盘 鼠标 计时器 2018/12/31
键盘 输入焦点的概念 产生的键盘消息中包括接收该消息的窗口的句柄。于是,此消息就可以进入指定应用程序的消息循环,并由消息循环中的DispatchMessage函数发送至各个窗口过程中去。 窗口过程通过捕获WM_SETFOCUS和WM_KILLFOCUS消息来判断它的窗口何时拥有输入焦点。 2018/12/31
击键消息 有四类击键消息,当按下一个键时,Windows会把WM_KYEDOWN,或WM_SYSKEDOWN消息放入有输入焦点的窗口的消息队列中。当释放一个键时,Windows会把WM_KEYUP或者WM_SYSKEYUP放入消息队列中。 对所有的击键消息,消息参数wParam是虚拟键码,表示按下或释放的键。而消息参数lParam则包含属于击键的其他数据。 2018/12/31
字符消息 对下列键的单击能产生字符消息 WM_CHAR 任意字符键和数字键 Backspace键 [ Ctrl+H ] \b Enter键 [ Ctrl+M ] \r Esc键 [ Ctrl+[ ] [Ctrl+Enter]组合键 [ Ctrl+J ] \n Tab键 [ Ctrl+I ] \t 2018/12/31
字符消息(2) 实际上,以上所示的键的单击也只会产生击键消息 ,但程序的消息循环中的函数TranslateMessage 会为用户把击键消息转换成字符消息。 while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } 2018/12/31
插入符 标明字符、文本或图形即将插入的位置 处理WM_SETFOCUS消息时创建并显示插入符 处理WM_KILLFOCUS消息时删除插入符 2018/12/31
鼠标 鼠标作为一种定位输入设备,在Windows中得到了广泛的应用。通过鼠标的键击、双击和拖动功能,用户可以很容易地操作基于Windows图形界面的应用程序。 常见鼠标有单键、双键、三键等几种类型,以重视与网络浏览的五健鼠标在Windows 2000系统中也得到支持。 每个鼠标光标中都有一个单像素点被定义为鼠标的热点 每次鼠标事件发生的位置就是当前鼠标的热点的位置 2018/12/31
鼠标消息 当鼠标事件发生后,系统将产生的鼠标消息发送到相应的应用程序的消息队列。一般来讲,鼠标消息只会发送给热点下面的程序窗口,而不管该窗口是否是活动的。 鼠标消息有两类: 客户区鼠标消息 非客户区鼠标消息 与鼠标有关的操作 鼠标键双击 捕获鼠标 鼠标响应程序实例 MouseClick.c 2018/12/31
客户区鼠标消息 Windows 2000系统中,共定义了13种客户区鼠标消息: 鼠标键 按下 释放 双击 左键 中键 右键 X键 鼠标移动 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK 中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK 右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK X键 WM_XBUTTONDOWN WM_XBUTTONUP WM_XBUTTONDBLCLK 鼠标移动 WM_MOUSEMOVE x = LOWORD (lParam); // 鼠标发生时的x坐标位置 y = HIWORD (lParam); // 鼠标发生时的y坐标位置 2018/12/31
客户区鼠标消息 wParam的取值情况 MK_CONTROL: The CTRL key is down. MK_LBUTTON: The left mouse button is down. MK_MBUTTON: The middle mouse button is down. MK_RBUTTON: The right mouse button is down. MK_SHIFT: The SHIFT key is down. 2018/12/31
非客户区鼠标消息 对应于每条客户区的鼠标消息,都有一条非客户区鼠标消息,只不过消息的名称稍有不同 如WM_LBUTTONDOWN对应于WM_NCLBUTTONDOWN。 另外, 包含在非客户区鼠标消息lParam参数中的坐标信息是基于屏幕坐标系的,即坐标原点在窗口屏幕的左上角。 2018/12/31
鼠标键双击 在默认的情况下,Win32应用程序并不支持鼠标键的双击,只有在注册窗口类时注明该窗口类具有CS_DBLCLKS风格后才支持。 wndclass.style = CS_HREDRAW| CS_VREDRAW| CS_DBLCLKS; 双击鼠标左键会产生下面的一系列鼠标消息: (1) WM_LBUTTONDOWN (2) WM_LBUTTONUP (3) WM_LBUTTONDBLCLK (4) WM_LBUTTONUP 在默认情况下,系统设定的双击时间间隔是500毫秒,使用函数SetDoubleClickTime可以改变这一值。 2018/12/31
捕获鼠标 在通常情况下,只有当鼠标光标位于某一窗口的客户区或者非客户区时,该窗口的窗口过程才能接收到鼠标消息,甚至当鼠标热点不在此窗口上方时,也能捕获到鼠标消息,这就涉及到鼠标捕获的问题。 SetCapture(hWnd); 指定另外一个窗口捕获鼠标或者使用ReleaseCapture函数,都会使窗口失去对鼠标消息的捕获。 ReleaseCapture(); 函数GetCapture能返回正在捕获鼠标消息的窗口句柄: if(hWnd==GetCapture()) 2018/12/31
计时器和计数器消息 在Windows应用程序中,计时器是性能非常好的一种输入设备,它按照预定的时间间隔向用户的程序发送一条计时器消息。 计时器消息WM_TIMER按指定的时间间隔发送到程序的消息队列中,其参数wParam是计时器唯一的标识符(整型值),lParam参数为零。 程序可以同时拥有多于一个的计时器。 2018/12/31
计时器函数 SetTimer 此函数用于设置和指定时间的间隔值 UINT_PTR SetTimer ( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc); KillTimer 清楚建立的计时器,并清空程序消息队列中的WM_TIMER消息。 BOOL KillTimer (HWND hWnd, UINT_PTR uIDEvent); 2018/12/31
第五章 主要内容 资源和资源脚本文件 菜单和快捷键资源 图标、光标和字符串资源 对话框 第五章 主要内容 资源是Windows应用程序用户界面的重要组成部分,菜单、快捷键、图标、光标、对话框和字符串等都是不同的资源类型。资源的使用极大地方便了Windows应用程序的界面设计。 资源是数据,在程序运行是通过调用API函数装入内存,也可以随时从内存中释放 资源和资源脚本文件 菜单和快捷键资源 图标、光标和字符串资源 对话框 2018/12/31
资源和资源脚本文件 资源也是一种数据,他们在资源脚本文件(文本文件,以.RC为文件扩展名)中定义了应用程序所需的数据,即菜单、对话框、图标等资源数据。 资源编译器负责创建并编译资源脚本文件。 resource.h文件伴随资源脚本文件一起生成,定义资源标识符的值;在使用资源标识符的源文件中必须用#include语句包含该文件。 2018/12/31
菜单和快捷键资源 菜单的结构 菜单和菜单相关操作 菜单消息 实现更复杂的菜单项 快捷键资源 菜单和快捷键程序实例 菜单是Windows图形用户界面中窗口的重要组成部分。使用菜单可以使用户了解并方便地使用应用程序提供的各项功能;使用快捷键资源可使菜单的操作更方便。 菜单的结构 菜单和菜单相关操作 菜单消息 实现更复杂的菜单项 快捷键资源 菜单和快捷键程序实例 2018/12/31
菜单的结构 IDM_MYMENU1 MENU DISCARDABLE BEGIN POPUP "文件(&F)" …… …… …… END POPUP "编辑(&E)" MENUITEM "撤销(&U)\tCtrl+Z", IDM_EDIT_UNDO MENUITEM SEPARATOR MENUITEM "剪切(&X)\tCtrl+X", IDM_MENUITEM MENUITEM "复制(&C)\tCtrl+C", IDM_EDIT_COPY MENUITEM "粘贴(&P)\tCtrl+V", IDM_EDIT_PASTE MENUITEM "删除(&D)\tDel", IDM_EDIT_DELETE 2018/12/31
菜单和菜单相关操作 1 菜单资源的加载 2 菜单的动态创建 3 菜单项的属性 4 插入和删除菜单项 通过资源编译器创建菜单资源很容易,用户只需为其窗键的菜单栏添加菜单项或者弹出式菜单,并给每个菜单项指定一个全局唯一的标识符(自定义或由编译器分配)以及菜单项标题。 1 菜单资源的加载 2 菜单的动态创建 3 菜单项的属性 4 插入和删除菜单项 2018/12/31
菜单资源的加载 在创建菜单资源后,有三种方法可以实现菜单与程序窗口的关联: (1) 在窗口类中加载菜单 (2) 创建窗口时加载菜单 wndclass.lpszMenuName = lpMenuName; (2) 创建窗口时加载菜单 HMENU LoadMenu (HINSTANCE hInstance, LPCTSTR lpMenuName); CreateWindow(……,HMENU,……); (3) 动态加载菜单 应用程序窗口调用函数LoadMenu获取菜单句柄后,还可以通过调用函数SetMenu动态地加载菜单,以提高程序的灵活性。 BOOL SetMenu(HWND hWnd, HMENU hMenu); 2018/12/31
菜单的动态创建 HMENU CreateMenu(VOID); //创建一个空菜单 HMENU CreatePopupMenu(VOID);//创建空的弹出式菜单。 (1) AppendMenu 在指定菜单的末尾加入一新的菜单项,可以指定该菜单项的内容、外观和行为等属性。 2018/12/31
(2) InsertMenuItem 在菜单的指定位置处插入一新菜单项 MENUITEMINFO mii; // 菜单项信息结构 InsertMenuItem (hMenu, SC_CLOSE, FALSE, &mii); 2018/12/31
菜单项的属性 菜单项的禁止或者激活状态 菜单项的选中或者取消选中状态 菜单项显示的内容和标识符值 EnableMenuItem 改变菜单项的激活、禁止和灰化状态 BOOL EnableMenuItem (HMENU hMenu, UINT uItem, UINT uEnable); CheckMenuItem 用于选中或者取消选中菜单项,默认的选中状态是在菜单项的左边做一复选框选中标记。 DWORD CheckMenuItem ( HMENU hmenu, UINT uIDCheckItem, UINT uCheck); 2018/12/31
菜单消息 WM_COMMAND消息是用户选择某个菜单项时,发送给窗口过程的消息。该消息的LOWORD(wParam)包含了菜单项的标识符,HIWORD(wParam)始终为0 。 lParam始终为0。 WM_INITMENU是程序的顶层菜单被激活前的一瞬间发送到窗口过程。 WM_INMENUPOPUP是弹出式菜单被激活前的一瞬间发送到窗口过程的。 WM_CONTEXTMENU消息通知窗口用户单击了鼠标右键,并要求弹出浮动菜单。 2018/12/31
快捷键资源(1) 1 资源脚本文件中描述的快捷键 IDR_MYACCELERATOR ACCELERATORS DISCARDABLE BEGIN "E", IDM_DRAW_ELLIPSE, VIRTKEY, CONTROL, NOINVERT "N", IDM_FILE_NEW, VIRTKEY, CONTROL, NOINVERT "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT "Q", IDM_FILE_EXIT, VIRTKEY, CONTROL, NOINVERT "R", IDM_DRAW_RECT, VIRTKEY, CONTROL, NOINVERT "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT "^T", IDM_FILE_TEXT, ASCII, NOINVERT "^D", IDM_FILE_DRAW, ASCII, NOINVERT "^Z", IDM_EDIT_UNDO, ASCII, NOINVERT "^X", IDM_EDIT_CUT, ASCII, NOINVERT "^C", IDM_EDIT_COPY, ASCII, NOINVERT "^V", IDM_EDIT_PASTE, ASCII, NOINVERT END 2018/12/31
快捷键资源(2) 2 加载和翻译快捷键 HACCEL hAccel; ...... hAccel= LoadAccelerators(hInstance,lpAccelName); while (GetMessage (&msg, NULL, 0, 0)) { if(!TranslateAccelerator(hwnd, hAccel, &msg)) TranslateMessage (&msg) ; DispatchMessage (&msg) ; } 2018/12/31
图标、光标和字符串资源 图标、光标本质上都是位图,只不过它们都被限制了一定的尺寸,分别被用在不同的地方。字符串也是一种资源类型,它给程序提供了另外一种输出文本字符串的方法。 2018/12/31
图标 Windows 2000应用程序支持三种不同的图标尺寸: 使用资源编辑器中的图形编辑器创建图标,自动在资源脚本文件中添加: ( 48X48 ) 、( 32X32 )和 ( 16X16 )图标。 小图标:在应用程序最小化时,显示在应用程序窗口的左上角; 大图标:用于桌面图标或大图标视图中。 三种图标都使用同一个标识符或者名称,系统直到把不同的尺寸的图标用在何处。 使用资源编辑器中的图形编辑器创建图标,自动在资源脚本文件中添加: IDI_MYICON ICON DISCARDABLE ”iconl.ico” 装载图标: WNDCLASS wndclass; wndclass.hIcon = LoadIcon ( hInstance, MAKEINTRESOURCE ( IDI_MYICON ) ); 2018/12/31
函数LoadImage也可以将图标资源装载到应用程序的窗口类,并且功能更强。 函数SetClassLong非常有用,它可以在程序执行期间,动态地更改窗口类指定的图标、光标、菜单甚至窗口过程等属性。 2018/12/31
使用自定义的光标 系统提供了一些预定义的鼠标光标。标识符为IDC_ARROW, IDC_MOVE, IDC_WAIT或IDC_CROSS等。 在资源脚本文件中,自定义光标的描述如下: IDC_MYCURSOR CURSOR DISCARDABLE “cursor1.cur” 自定义的光标资源保存在文件(如cursor1.cur)中,在定义窗口类时,可以把自定义的光标设置为窗口类默认的光标。 wndclass.hCursor = LoadCursor ( hInstance, MAKEINTRESOURCE (IDC_MYCURSOR) ); 2018/12/31
使用自定义的光标 特别是在鼠标消息WM_MOUSEMOVE的处理期间,这个函数非常有用。 case WM_MOUSEMOVE: hCursor = LoadCursor ( hInst, MAKEINTRESOURCE( IDC_MYCURSOR ) ); SetCursor (hCursor); 2018/12/31
使用字符串资源 使用字符串资源,提供了一种完全不同的使用字符串的方法,字符串被放在资源脚本文件中。程序在需要它们时,通过每个字符串唯一的标识符来获得字符串。 2018/12/31
对话框 对话框是一种提供用户与应用程序交互的弹出式窗口。当用户单击菜单的某个菜单项或者按钮时,会弹出一个对话框窗口,用户可以从中读取信息、写入文本内容、设置某些选项等。 对话框分为模态和非模态对话框两种。模态对话框不允许用户在关闭对话框之前切换到该应用程序的其他窗口;相反,非模态对话框则允许这样做。 模态对话框 模态对话框程序实例 ModeDlg. c 非模态对话框 非模态对话框程序实例ModelessDlg.c 通用对话框 用对话框程序实例COMMONDLG 2018/12/31
模态对话框 对话框过程 (1)DialogBox从对话框模板资源中创键模态对话框。 INT_PTR DialogBox (HINSTANCWE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC DialogFunc); (2) EndDialog 通知系统清除对话框,并将控制交给程序的窗口过程。 BOOL EndDialog(HWND hDlg, INT_PTR nResult); 2018/12/31
模态对话框 (3) DialogProc 当模态对话框创建后,程序将发生在对话框中的事件消息传送到对话框过程中进行处理,而不是交给程序的窗口过程。 BOOL CALLBACK DialogProc (HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam); WM_INITDIALOG消息:处理对话框的初始化工作 WM_COMMAND消息:处理控件单击 LOWORD (wParam):控件标识符 lParam:控件的窗口句柄 2018/12/31
非模态对话框 (1) 在资源中定义的非模态对话框模板与模态对话框十分类似,只是对话框的样式通常包括标识符WS_VISIBLE。否则,默认情况下系统不会将对话框显示出来。 STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU; 1 创建非模态对话框 CreateDialog用于创建非模态对话框,并立即返回创建的对话框的窗口句柄。 HWND CreateDialog (HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc); 关闭非模态对话框: DestroyWindow ( HWND hwnd ); 2018/12/31
通用对话框 对于Win32应用程序的一些通用任务,如打开文件、打印文档等,Windows 2000提供了一些通用的对话框。这些通用对话框包含在系统的通用对话框库(COMMDLG.H头文件)中。使用通用对话框来完成这些通用任务,用户很容易接收,这样的应用程序具有一致的界面风格,用户不需要时间去熟悉那些风格各异的对话框或者菜单,而且系统提供的通用对话框的功能也是十分强大的。 1 通用对话框的类型 通用对话框库中包含以下几种通用对话框: “字体”对话框。 “颜色”对话框。 “打开”和“另存为”文件对话框。 “查找”和“替换”编辑对话框。 “打印”、“打印机属性表”和“页面设置”打印对话框。 2018/12/31
第六章 主要内容 控件(Control,也称为控制)是一种子窗口,应用程序用它来与其它窗口一起完成简单的输入输出操作。控件是Windows图形用户界面的重要组成部分之一。 最常使用控件的地方是在对话框中。但是控件也能用在普通窗口或者其他窗口中,只是两种使用控件的方法有所不同。 Windows系统为编写界面风格一致的应用程序提供了大量的标准控件和其它控件(如通用控件)。 控件概述 标准控件 2018/12/31
控件概述 控件是一种子窗口。在很大程度上,子窗口与一般的窗口类似,但在窗口风格、外观、创建方法和窗口属性等方面两者都有所不同。 子窗口 控件分类 消息通信 补充说明 2018/12/31
控件分类 控件的创建方式有两种: 一种是在对话框模板中指定控件。 另一种方式是以创建子窗口的方法来创建控件,如可以用函数CreateWindow和CreateWindowEx来创建它们。 hwndButton1 = CreateWindow( "BUTTON", "请确认(&C)", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 80, 220, 100, 30, hwnd, (HMENU)IDC_MYOK, hInst, NULL); 2018/12/31
标准控件 标准控件是由Windows系统直接支持的,主要包括按钮控件、滚动条控件、静态控件、列表框控件、编辑框控件、多信息编辑框控件和组合框控件等。 控件类型 窗口类名称 描述 按钮控件 BUTTON 供用户单击或者选择的,并通知父窗口用户的动作 静态控件 STATIC 为其它控件提供描述性信息的文本或者图形 编辑框控件 EDIT 允许用户查看或者编辑文本 多信息编辑框控件 RICHEDIT 允许用户查看或者编辑文本,并允许格式化文本段落,嵌入COM对象 列表框控件 LISTBOX 提供一个列表,让用户从中选取一个或者多个项 组合框控件 COMBOBO 该控件时编辑框和列表框的有机组合,用户可以选择或者编辑其中的项 滚动条控件 SCROLLBAR 通过滚动快在滚动条上的移动来改变客户窗口中显示的内容 2018/12/31
通用控件 通用控件与标准控件十分类似,不过他们不是由Windows系统提供直接支持的子窗口。Windows的通用控件动态链接库(Common Control DLL)提供了对通用控件的支持, 在创建通用控件之前,必须保证通用控件动态链接库已经被加载,函数InitCommonControlsEx用于检查该库加载与否 2018/12/31
消息通信 函数SendMessage和函数SendDlgItemMessage分别用于向程序窗口和对话框中的控件发送消息。 LRESULT SendMessage ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); LONG SendDlgItemMessage( HWND hDlg, // handle of dialog box int nIDDlgItem, // identifier of control UINT Msg, // message to send WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); 2018/12/31
当控件的状态发生改变(如用户在控件内进行输入)时,控件就会向父窗口发送通知消息,父窗口就是根据这些通知消息获取用户想要进行的操作。 标准控件的通知消息通常也是WM_COMMAND,LOWORD(wParam)中包含的是发送通知消息的控件的标识符,高字位是通知代码;参数lParam则包含了控件的句柄。 2018/12/31
补充说明 使用函数GetDlgItem或者GetDlgCtlID,可以获得对话框中的控件的句柄或标识符 HWND GetDlgItem ( HWND hDlg, // handle of dialog box int nIDDlgItem // identifier of control ); int GetDlgCtrlID ( HWND hwndCtl); // handle of control 2018/12/31
标准控件 按钮控件 静态控件 滚动条控件 编辑框控件 列表框控件 组合框控件 标准控件程序实例之一 标准控件程序实例之二 标准控件程序实例之三 2018/12/31
按钮控件 按钮控件 下压按钮 单选按钮 复选框 组框 2018/12/31
按钮控件(1) 1 创建按钮控件 hwndButton = CreateWindow( “BUTTON”, “按钮文本”, WS_CHILD| WS_VISIBLE | BS_PUSHBUTTON, 0,0,0,0, hwnd, (HMENU)IDC_MYBUTTON, hInstance,NULL); 2018/12/31
按钮控件(2) 2 按钮控件通知消息 应用程序创建按钮控件之后,可以通过接收控件发出的消息,得知用户将要进行的操作,并且可以通过向指定的按钮发送向指定的按钮发送消息对其进行操作。 case WM_COMMAND: switch ( HIWORD(wParam) ) { case BN_CLICKED: switch ( LOWORD(wParam) ) case 控件标识符常量: SendMessage ( hwndButton,BM_CLICK,0,0 ); ...... break; } 2018/12/31
BN_DBLCLK或BN_DOUBLECLICKED BN_UNPUSHED或BN_UNHILITE 按钮控件(3) 按钮控件通知码 通知码 产生的原因 BN_CLICKED 单击按钮控件 BN_KILLFOCUS 按钮控件失去输入焦点 BN_DBLCLK或BN_DOUBLECLICKED 双击按钮控件 BN_SETFOCUS 按钮控件得到输入焦点 BN_DISABLE 按钮控件被禁用 BN_PAINT 按钮控件控件被重绘 BN_PUSHED或 BN_HILITE 按钮控件处于按下状态 BN_UNPUSHED或BN_UNHILITE 按钮控件处于弹起状态 2018/12/31
IMAGE_BITMAP或IMAGE_ICON BST_CHECKED或BST_UNCHECKED 应用程序(父窗口)可向按钮控件(子窗口)发出按钮消息 消息类型 wParam参数 lPara参数 描述 BM_CLICK 使按钮发生单击动作 BM_GETCHECK 返回复选框或圆形按钮的选中状态 BM_GETIMAGE IMAGE_BITMAP或IMAGE_ICON 返回按钮上的位图或图标的句柄 BM_GETSTATE 返回复选框或按钮的状态 BM_SETCHECK BST_CHECKED或BST_UNCHECKED 设置复选框或圆形按钮的选中状态 BM_SETIMAGE 位图或图标的句柄 设置按钮上的位图或图标 BM_SETSTATE TRUE或FALSE 设置当前按钮是否有输入焦点 BM_SETSTYLE 按钮样式 改变按钮控件的样式,并决定是否重绘按钮 2018/12/31
静态控件 静态控件是一种单向交互的控制,只能提供一些静态的文本或者图形信息,一般不用于响应用户的输入(处理有SS_NOTIFY风格的除外)。创建静态控件的过程如下: hwndStatic=CreateWindow(“STATIC”, “静态文本”, WS_VISIBLE |WS_CHILD | SS_CENTER, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL); 2018/12/31
滚动条控件 窗口滚动条 只需将WS_VSCROLL或 WS_HSCROLL窗口风格加入到窗口类的风格中,系统会负责创建他们。 滚动条控件 由函数CreateWindow或CreateWindowEx创建,是一种子窗口。预定义的窗口类是SCROLLBAR 窗口滚动条和滚动条控件都发送WM_VSCROLL或者WM_HSCROLL消息,不同的是窗口滚动条消息的lParam参数值为零,而滚动条控件消息的lParam参数为控件子窗口的句柄。 2018/12/31
滚动条控件(2) 滚动条控件的创建 hwndScrollBar=CreateWindowEx(0L,”SCROLLBAR”, (LPSTR)NULL,WS_CHILD|SBS_HORZ, 0,0,0,0, hwnd, (HMENU)IDC_MYSCROLLBAR, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL); 2018/12/31
滚动条控件(3) 滚动条控件向父窗口发送的消息 消息WM_VSCROLL或WM_HSCROLL实现滚动效果 消息WM_CTLCOLORSCROLLBAR可以改变滚动条控件窗口的颜色 case WM_CTLCOLORSCROLLBAR: // 滚动条着色 return (LRESULT)brScroll ; 2018/12/31
滚动条控件(4) 设置滚动条控件滑动位置 SetScrollPos ( hwndScrollBar, SB_CTL, clrTest, TRUE); 获得当前滚动条的滚动框的位置 int GetScrollPos ( HWND hWnd, int nBar ); 返回当前滚动条的最小和最大滚动范围 BOOL GetScrollRange( HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos ); 设置滚动条的最小和最大滚动范围 BOOL SetScrollRange( HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw ); 2018/12/31
编辑框控件 创建编辑框控件 hwndEdit=CreateWindow(TEXT(“EDIT”),NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_LEFT| ES_MULTILINE|ES_AUTOVSCROLL, 0,0,0,0, hwnd,(HMUNU)IDC_MYEDIT, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL); 编辑框控件的窗口风格类型 表6-9 2018/12/31
编辑框控件(2) 编辑框控件向父窗口发送消息 父窗口向编辑框控件发送消息 WM_COMMAND: HIWORD ( wParam ) 通知码 SendMessage 2018/12/31
列表框控件 创建列表框控件 hwndList=CreateWindow ( TEXT(“LISTBOX”), NULL, WS_CHILD|WS_VISIBLE|LBS_NOTIFY| WS_VSCROLL|WS_BORDER, 0,0,0,0,hwnd, (HMENU)IDC_MYLIST, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL); 2018/12/31
列表框控件(1) 列表框的类型 其他风格参数 单选列表框 多选列表框 ( LBS_MULTIPLESEL ) LBS_NOTIFY:列表框可以响应单、双击列表项 2018/12/31
列表框控件(2) 列表框控件发出的消息 当用户在列表框中进行选择操作,或者列表框控件失去输入焦点时,列表框控件会向其父窗口发送通知消息。 LOWORD(wParam) — 控件的标识符 HIWORD(wParam) — 消息的通知码 lParam — 控件的窗口句柄 2018/12/31
列表框控件(3) 向列表框控件发送的消息 常用消息类型 使用函数 SendMessage LB_ADDSTRING – 末尾增加列表项 LB_INSERTSTRING – 在指定位置插入列表项 2018/12/31
组合框控件 创建组合框控件 hwndComboBox = CreateWindow (“COMBOBOX”, NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP| CBS_DROPDOWN, 0,0,0,0,hwnd, (HMENU)IDC_MYCOMBOX, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL); 2018/12/31
组合框控件(2) 组合框消息 组合框控件发出的通知码包含在WM_COMMAND消息的wParam参数的高字位中,它们与列表框及编辑框控件的通知消息存在许多相似和对应关系。 标准控件程序实例之三 StdControl3 演示了列表框控件和组合框控件的创建和使用。 2018/12/31
第七章 文件的输入/输出 ( I/O ) 在标准的C语言中,文件的输入输出操作: 在Win32 API中 fopen, fclose, fwrite, fseek 在Win32 API中 ………… 2018/12/31
主要内容 创建和打开文件 读取、写入、移动和删除文件 查找文件 文件操作实例 2018/12/31
创建和打开文件 创建任何一种文件可使用函数CreateFile 2018/12/31
CreateFile hFile = CreateFile ( "C:\\FILE.DOC", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 2018/12/31
读取、写入、移动和删除文件 第一次打开文件,文件指针存放于文件开头 文件指针所指位置为下一次读取或写入的地方 随着文件内容的读取或写入,文件指针移动 使用函数SetFilePointer移动文件指针 2018/12/31
读取、写入、移动和删除文件 ReadFile WriteFile DeleteFile CopyFile MoveFile 2018/12/31
关闭 每次调用CreateFile之后,在退出作用之前关闭打开的对象句柄 BOOL CloseHandle ( HANDLE hObject ); 2018/12/31