1、第二章 主要内容,窗口过程与消息 文本输出 滚动条,窗口过程与消息,窗口过程总是与已注册的特定窗口类相关联的,一个应用程序可以有几个窗口类,基于每个窗口类都可以创建多个窗口(通过CreateWindow等函数创建)。 WndProc被声明为CALLBACK回调函数,回调函数是输出函数中特殊的一种,能够在Windows环境下直接调用。一个应用程序至少有一个活动的窗口,因为在应用程序处理消息时,Windows会调用回调函数,即窗口过程。 窗口过程的名字可以任意指定,只需与窗口类结构的lpfnWndProc域指定的名字相同即可。,CreateWindow函数实例,hWnd = CreateWindo
2、w( lpszAppName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL );,窗口处理函数WndProc,LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch( uMsg ) case WM_PAINT :break;case WM_DESTROY :PostQuitMessage(0);break;default :retur
3、n( DefWindowProc( hWnd, uMsg, wParam,lParam ) );return( 0L ); ,lpfnWndProc域,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_A
4、PPLICATION ); wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);wc.lpszMenuName = lpszAppName; wc.lpszClassName = lpszAppName;,文本输出,文本输出是Win32应用程序最常见的客户区图形输出(文本输出也被看做是GDI图形输出),在字处理、排版等系统中应用广泛。 文本输出程序示例 获取设备描述表 WM_PAINT消息的响应和处理 字体的设置 文本的格式化输出 文本输出函数比较,文本输出程序示例,Dem
5、o: TextOut1.dsw 他利用GDI函数TextOut输出了两段文本,并采用了一些文本格式化技巧,实现文本对齐等。 SetTextAlign实现文本对齐等。SetTextAlign(hdc,A_RIGHT| A_TOP); 常用的文本对齐样式有:TA_LEFT,TA_CENTER,TA_RIGHT,TA_TOP,TA_BOTTOM,TA_BASELINE,获取设备描述表,设备描述表(DC:Device Context)是GDI内部保存的一种数据结构,它定义了一系列的图形对象、相关的属性及绘图模式等一些信息。Windows GDI函数依赖于设备描述表,实际上这些函数在设备描述表环境中显示
6、文本和图形设备描述表是Windows应用程序,也是输出设备之间的桥梁。所以,在屏幕上和打印机上输出文本和图形的操作过程是一样的。当程序获得设备描述表句柄后,Windows就是用默认的属性值填充设备描述表结构。然后就可以用这些获得的设备环境使用GDI函数绘制文本和图形了。当然,有一些GDI函数可以获取和改变设备描述表的属性值。,获取设备描述表(2),HDC:,获取设备描述表(3),调用BeginPaint返回设备描述表句柄 调用GetDC函数获得设备描述表句柄 使用CreateDC函数获得设备描述表句柄 其它获得设备描述表句柄的函数,调用BeginPaint返回设备描述表句柄,PAINTSTRU
7、CT ps ; hdc = BeginPaint (hwnd, ,调用GetDC函数获得设备描述表句柄,在一些非WM_PAINT消息的处理期间,也许程序需要绘制客户区或者想得到有关设备描述表的信息。这是利用GetDC函数可以返回设备描述表句柄,hdc=GetDC(hwnd); 用GetDC获得的设备描述表句柄需要用ReleaseDC函数释放。,使用CreateDC函数获得设备描述表句柄,前面两种方法都是针对视频显示器的,但获取设备描述表更通用的函数是CreateDC。他不但可以获得视频显示器的设备描述表句柄,还可以获得打印机及其他输出显示设备的设备描述表句柄。hdc = CreateDC(ps
8、zDriver,pszDevice,pszOutput,pData);同样,利用DeleteDC(hDC)函数可以释放设备描述表句柄。,其它获得设备描述表句柄的函数,WM_PAINT消息的响应和处理,Windows是一个多任务环境,显示设备视为多个应用程序公用的,某个应用程序的窗口上面可能被对话框或窗口覆盖。当撤销这些对话框或窗口时,这个应用程序窗口中就有一个“空洞”,这个“空洞”就是一块无效的客户区域。像这种情况还很多。 比如改变窗口尺寸后, 客户区的部分内容被遮盖, 窗口最消化、客户区的滚动等 WM_PAINT消息在Windows消息队列中的优先级很低,这就是其他许多消息能够先于WM_PA
9、INT消息被送交给窗口过程处理。只有在没有其他消息的情况下,才从队列中取出WM_PAINT消息进行处理。这样做是为了让应用程序首先完成影响窗口显示结果的其他操作,不致因为频繁地执行输出操作而引起显示器的闪烁。,WM_PAINT消息的响应和处理(2),Windows并非WM_PAINT消息的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息。这两个函数把客户区部分或全部标记成无效区域而要求重新显示。 InvalidateRect 重画一个指定矩形框范围内的客户区 InvalidateRgn 重画一个指定范围内的客户区。,Invali
10、dateRect和InvalidateRgn,BOOL InvalidateRect(HWND hWnd,CONST RECT *lpRect,BOOL bErase);BOOL InvalidateRgn(HWND hWnd,HRGN hRgn ,BOOL bErase);,字体的设置,case WM_CREATE:hdc = GetDC (hwnd) ;GetTextMetrics (hdc, ,字体属性结构,typedef struct tagTEXTMETRIC short tmHeight; / 字符高度short tmAscent; / 字符上部高度(基线以上)short tmDe
11、scent; / 字符下部高度(基线以下)short tmInternalLeading; / see belowshort tmExternalLeading; / recommended amount of leadingshort tmAveCharWidth; / avg. width of characters in fontshort tmMaxCharWidth; / max. width of any character in fontshort tmWeight; / weight of fontBYTE tmItalic; / italic font if value is
12、 nonzeroBYTE tmUnderlined; / underlined font if value is nonzeroBYTE tmStruckOut; / struckout font if value is nonzeroBYTE tmFirstChar; / value of first character for fontBYTE tmLastChar; / value of last character for fontBYTE tmDefaultChar; / see belowBYTE tmBreakChar; / see belowBYTE tmPitchAndFam
13、ily; / 低四位表示字体间距BYTE tmCharSet; / see belowshort tmOverhang; / see belowshort tmDigitizedAspectX; / see belowshort tmDigitizedAspectY; / see below TEXTMETRIC;,字体属性结构图示,三种逻辑字体,Windows 2000支持的三种类型的逻辑字体。 光栅字体 矢量字体 TrueType字体,光栅字体,光栅字体也叫位图字体,不能旋转或缩放,支持该字体是因为许多老的程序仍然依赖这些字体 Courier MS Sans Serif MS Serif,
14、 Small Symbol,矢量字体,矢量字体是从数学模型生成的,字符用线段绘制,可以缩放任意比例。 Modern Roman Script,TrueType字体,TrueType和新的OpenType是由直线和曲线命令生成的轮廓字体,两者都可以缩放和旋转。,文本的格式化输出,Windows API提供了对文本输出格式的强有力的支持,主要有三类函数可以用于文本的格式化。 获取和设置设备描述表的文本格式化属性的函数。 获取字体宽度信息的函数。 获取字符串宽度和高度信息的函数。,文本的格式化函数(1),1 文本对齐函数 (1) SetTextAlign 设置文本基于输出参考点的对齐方式。 UINT
15、 SetTextAlign(HDC hdc,UINT fMode);(2) GetTextAlign 获取文本基于输出参考点的对齐方式。 UINT GetTextAlign(HDC hdc);,文本的格式化函数(2),2 调整字符间距函数 (1) SetTextCharsetExtra 用于在文本输出是调整字符的输出间距,默认的字符间距为零。 Int SetTextCharsetExtra(HDC hdc,int nCharExtra);(2) GetTextCharsetExtra 程序可以通过本函数获取当前的字符间距。 Int GetTextCharsetExtra(HDC hdc);,文
16、本的格式化函数(3),3 文本和背景颜色函数 (1) SetTextColor 通过调用此函数可以改变指定环境中的文本颜色。 COLORREF SetTextColor(HDC hdc, COLORREF crColor);(2) SetBkColor 通过调用此函数可以改变指定环境中的背景颜色。 COLORREF SetBkColor(HDC hdc, COLORREF crColor);(3) GetTextColor 通过调用此函数可以获得指定环境中的文本颜色。 COLORREF GetTextColor(HDC hdc);(4) GetBkColor 通过调用此函数可以获得指定环境中的
17、背景颜色。 COLORREF GetBkColor(HDC hdc);,文本的格式化函数(4),4 段落对齐函数 (1) GetTextExtentPoint32 用于计算指定字符串的长度和宽度。 BOOL GetTextExtentPoint32(HDC hdc,LPCTRSTR lpString,int cbString,LPSIZE lpSize);(2) SetTextJustification 用于指定在字符串中,空格应占的字符数。 BOOL SetTextJustification(HDC hdc,int nBreakExtra,int nBreakCount); NBreakEx
18、tra:字符串中空格所占的长度 NBreakCount:空格的数目,文本输出函数比较DrawTextEx,DrawTextEx 与DrawText函数相比,多了一个指向DRAWTEXTPARAMS结构的指针,在这个结构中,可以设置制表符的宽度和输出矩形内左右空白区域的宽度等。因此DrawTextEx函数实现的功能更加强大。 Int DrawTextEx(HDC hdc,LPTSTR lpchText,int cchText,LPRECT lprc,UINT dwDTFormat,LPDRAWTEXTYPARAMS lpDTParams);,文本输出函数比较ExtTextOut,ExtTextO
19、ut 此函数是TextOut函数的扩展,功能更加强大。 ExtTextOut(hdc,xStart,yStart,文本输出函数比较TabbedTextOut,TabbedTextOut 如果希望输出多列文本,并且各行文本的每列需要按一定的方式对齐,那么使用TabbedTextOut最为方便。 TabbedTextOut(hdc,xStart,yStart,lpString,nCount,nNumTabs,lpnTabStops,xTabOrign);,滚动条,滚动条的特性和设置 在Win32应用程序中,滚动条很容易创建,只需在CreateWindow的第三个参数即窗口风格表示附中包括风格WS_
20、VSCROLL和WS_HSCROLL即可。 改进的文本输出程序实例 TextOut2.dsw 滚动条消息处理 当用户单机滚动条或者拖曳滚动框时,Windows给窗口过程发送WM_VSCROLL和WM_HSCROLL消息。这两个消息的wParam参数的低字节包含了一个称为“通知码”的标识符,分别标识每条消息产生的原因。,WS_VSCROLL设置,hwnd = CreateWindow (szAppName,TEXT (“TextOut2 with Scroll“),WS_OVERLAPPEDWINDOW | WS_VSCROLL ,CW_USEDEFAULT,CW_USEDEFAULT,CW_U
21、SEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL) ;,设置垂直滚动条,滚动条通知码,#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
22、SB_TOP 6 #define SB_LEFT 6 #define SB_BOTTOM 7 #define SB_RIGHT 7 #define SB_ENDSCROLL 8,滚动条信息结构和相关函数,滚动条信息结构和相关函数 typedef struct tagSCROLLINFO UINT cbSize; / SCROLLINFO结构的大小UINT fMask; / 标定对结构进行的操作方式int nMin; /滚动位置最小值int nMax; /滚动位置最大值UINT nPage; /窗口显示的页的大小int nPos; /滚动条当前位置int nTrackPos; /当前拖动时滚动框
23、的位置 SCROLLINFO, FAR *LPSCROLLINFO; typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;fMask是一些以SIF为前缀的标志,例如,当需要设置滚动条位置时,就需要将其设置为SIF_POS标志。其他标志还有SIF_RANGE和SIF_PAGE等。,滚动条信息结构和相关函数(2),1 SetScrollInfo 此函数用于设置滚动条的有关信息 int SetScrollInfo(HWND hwnd, int fnBar,LPCSCROLLINFO lpsi,BOOL fRedraw); 2 GetScrollInfo 此函数用于设置滚动条的有关信息 BOOL GetScrollInfo(HWND hwnd,int fnBar,LPCSCROLLINFO lpsi); 3 ScrollWindowEx 滚动指定的客户区内窗口的内容。 int ScrollWindowEx(HWND hWnd,int dx,int dy,CONST RECT *prcScroll,CONST RECT *prcClip,HRGN hrgnUpdate,LPRECT prcUpdate,UINT flags);,