第九章 子窗口控件(静态类别,滚动条类别)

静态类别

在CreateWindow函数中指定窗口类别为「static」,您就可以建立静态文字的子窗口控件。这些子窗口非常「文静」。它既不接收鼠标或键盘输入,也不向父窗口发送WM_COMMAND消息。

当您在静态子窗口上移动或者按下鼠标时,这个子窗口将拦截WM_NCHITTEST消息并将HTTRANSPARENT的值传回给Windows,这将使Windows向其下层窗口,通常是它的父窗口,发送相同的WM_NCHITTEST消息。父窗口常常将该消息传递给DefWindowProc,在这里,它被转换为显示区域的鼠标消息。

前六个静态窗口样式只简单地在子窗口的显示区域内画一个矩形或者边框。在下表的上部,「RECT」静态样式(左列)是填入图样的矩形样式;三个「FRAME」样式(右列)是没有填入图样的矩形轮廓:

SS_BLACKRECT

SS_GRAYRECT

SS_WHITERECT

SS_BLACKFRAME

SS_GRAYFRAME

SS_WHITEFRAME

「BLACK」、「GRAY」、「WHITE」并不意味着黑、灰和白色,这些颜色是由系统颜色决定的,如表9-4所示。

表9-4

 

静态控件

系统颜色

BLACK

COLOR_3DDKSHADOW

GRAY

COLOR_BTNSHADOW

WHITE

COLOR_BTNHIGHLIGHT

对这些样式,CreateWindow呼叫中的窗口文字字段被忽略。矩形的左上角开始于x位置坐标和y位置坐标,这些坐标都相对于父窗口。您也可以使用SS_ETCHEDHORZ、SS_ETCHEDVERT或者SS_ETCHEDFRAME ,采用灰色和白色建立一个形似阴影的边框。

静态类别也包括了三种文字样式:SS_LEFT、SS_RIGHT和SS_CENTER。它们建立左对齐、置右对齐和居中文字。文字在CreateWindow呼叫的窗口文字参数中给出,并且在以后可以用SetWindowText来改变它。当静态控件的窗口消息处理程序显示文字时,它使用DrawText函数以及DT_WORDBREAK、DT_NOCLIP和DT_EXPANDTABS参数。文字在子窗口的矩形内可以按文字进行换行。

这三种文字样式子窗口的背景通常为COLOR_BTNFACE,而文字本身是COLOR_WINDOWTEXT。在拦截WM_CTLCOLORSTATIC消息时,您可以通过呼叫SetTextColor来改变文字颜色,通过SetBkColor来改变背景颜色,并传回背景画刷句柄。后面的COLORS1程序展示了这一点。

最后,静态类别还包括了窗口样式SS_ICON和SS_USERITEM,但是当它们被用作子窗口控件时却没有任何意义。我们在讨论对话框时还要提及它们。

滚动条类别

我在第四章首次讨论了滚动条,也讨论了「窗口滚动条」和「滚动条控件」之间的一些区别。SYSMETS程序使用窗口滚动条,它出现在窗口的右边和底部。您可以在建立窗口时通过将标识符WS_VSCROLL、WS_HSCROLL或者两者都包含在窗口样式中,让窗口加上滚动条。现在我们准备建立一些滚动条控件,它们是能在父窗口的显示区域的任何地方出现的子窗口。您可以使用预先定义的窗口类别「scrollbar」以及两个滚动条样式SBS_VERT和SBS_HORZ中的一个来建立子窗口滚动条控件。

与按钮控件(以及将在后面讨论的编辑和清单方块控件)不同,滚动条控件不向父窗口发送WM_COMMAND消息,而是像窗口滚动条那样发送WM_VSCROLL和WM_HSCROLL消息。在处理卷动消息时,您可以通过lParam参数来区分窗口滚动条与滚动条控件。对子窗口滚动条其值为0,对于滚动条控件其值为滚动条窗口句柄。对窗口滚动条和滚动条控件来说,wParam参数的高字组和低字组的含义相同。

虽然窗口滚动条有固定的宽度,Windows使用CreateWindow呼叫中(或者在后面的MoveWindow呼叫中)给定的矩形尺寸来确定滚动条控件的尺寸。您可以建立细而长的滚动条控件,也可以建立短而粗的滚动条控件。

如果您想建立与窗口滚动条尺寸相同的滚动条控件,那么可以使用GetSystemMetrics取得水平滚动条的高度:

GetSystemMetrics (SM_CYHSCROLL) ;

或者垂直滚动条的宽度:

GetSystemMetrics (SM_CXVSCROLL) ;

根据Windows文件,滚动条窗样式标识符SBS_LEFTALIGN、SBS_RIGHTALIGN、SBS_TOP ALIGN和SBS_BOTTOMALIGN给出滚动条的标准尺寸,但是这些样式只在对话框中对滚动条有效。

对窗口滚动条,您可以使用同样的呼叫来建立滚动条控件的范围和位置:

SetScrollRange (hwndScroll, SB_CTL, iMin, iMax, bRedraw) ;

SetScrollPos (hwndScroll, SB_CTL, iPos, bRedraw) ;

SetScrollInfo (hwndScroll, SB_CTL, &si, bRedraw) ;

其区别在于:窗口滚动条将父窗口的句柄作为第一个参数,并且以SB_VERT或者SB_HORZ作为第二个参数。

令人吃惊的是,名为COLOR_SCROLLBAR的系统颜色不再用于滚动条。两端的按钮和小方块的颜色由COLOR_BTNFACE、COLOR_BTNHILIGHT、COLOR_BTNSHADOW、COLOR_BTNTEXT (用于小箭头)、COLOR_DKSHADOW和COLOR_BTNLIGHT决定。两端按钮之间区域的颜色由COLOR_BTNFACE和COLOR_BTNHIGHLIGHT决定。

如果您拦截了WM_CTLCOLORSCROLLBAR消息,那么可以在消息处理中传回画刷以取代该颜色。让我们来试一下。

COLORS1程序

为了解滚动条和静态子窗口的一些用法-也为了深入了解颜色-我们将使用COLORS1程序,如程序9-3所示。COLORS1在显示区域的左半部显示三种滚动条,并分别标以「Red」、「 Green」和「Blue」。当您挪动滚动条时,显示区域的右半部将变为三种原色混合而成的合成色,三种原色的数值显示在三个滚动条的下面。

程序9-3 COLORS1
        
COLORS1.C

/*------------------------------------------------------------------------

COLORS1.C -- Colors Using Scroll Bars

(c) Charles Petzold, 1998

-------------------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

LRESULT CALLBACK ScrollProc(HWND, UINT, WPARAM, LPARAM) ;


int idFocus ;

WNDPROC OldScroll[3] ;


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

static TCHAR szAppName[] = TEXT ("Colors1") ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;



wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = CreateSolidBrush (0) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;



if (!RegisterClass (&wndclass))

{

MessageBox ( NULL, TEXT ("This program requires Windows NT!"),

szAppName, MB_ICONERROR) ;

return 0 ;

}

hwnd = CreateWindow (szAppName, TEXT ("Color Scroll"),

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;



ShowWindow (hwnd, iCmdShow) ;

UpdateWindow (hwnd) ;



while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

static COLORREF crPrim[3] = { RGB (255, 0, 0), RGB (0, 255, 0),

RGB (0, 0, 255) } ;

static HBRUSH hBrush[3], hBrushStatic ;

static HWND hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect ;

static int color[3], cyChar ;

static RECT rcColor ;

static TCHAR *szColorLabel[] = { TEXT ("Red"), TEXT ("Green"),

TEXT ("Blue") } ;

HINSTANCE hInstance ;

int i, cxClient, cyClient ;

TCHAR szBuffer[10] ;



switch (message)

{

case WM_CREATE :

hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;



// Create the white-rectangle window against which the

// scroll bars will be positioned. The child window ID is 9.



hwndRect = CreateWindow (TEXT ("static"), NULL,

WS_CHILD | WS_VISIBLE | SS_WHITERECT,

0, 0, 0, 0,

hwnd, (HMENU) 9, hInstance, NULL) ;



for (i = 0 ; i < 3 ; i++)

{

// The three scroll bars have IDs 0, 1, and 2, with

// scroll bar ranges from 0 through 255.



hwndScroll[i] = CreateWindow (TEXT ("scrollbar"), NULL,

WS_CHILD | WS_VISIBLE |

WS_TABSTOP | SBS_VERT,

0, 0, 0, 0,

hwnd, (HMENU) i, hInstance, NULL) ;



SetScrollRange (hwndScroll[i], SB_CTL, 0, 255, FALSE) ;

SetScrollPos (hwndScroll[i], SB_CTL, 0, FALSE) ;



// The three color-name labels have IDs 3, 4, and 5,

// and text strings "Red", "Green", and "Blue".



hwndLabel [i] = CreateWindow (TEXT ("static"), zColorLabel[i],

WS_CHILD | WS_VISIBLE | SS_CENTER,

0, 0, 0, 0,

hwnd, (HMENU) (i + 3),

hInstance, NULL) ;



// The three color-value text fields have IDs 6, 7,

// and 8, and initial text strings of "0".



hwndValue [i] = CreateWindow (TEXT ("static"), TEXT ("0"),

WS_CHILD | WS_VISIBLE | SS_CENTER,

0, 0, 0, 0,

hwnd, (HMENU) (i + 6),

hInstance, NULL) ;



OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i],

GWL_WNDPROC, (LONG) ScrollProc) ;



hBrush[i] = CreateSolidBrush (crPrim[i]) ;

}



hBrushStatic = CreateSolidBrush (

GetSysColor (COLOR_BTNHIGHLIGHT)) ;



cyChar = HIWORD (GetDialogBaseUnits ()) ;

return 0 ;



case WM_SIZE :

cxClient = LOWORD (lParam) ;

cyClient = HIWORD (lParam) ;

SetRect (&rcColor, cxClient / 2, 0, cxClient, cyClient) ;



MoveWindow (hwndRect, 0, 0, cxClient / 2, cyClient, TRUE) ;



for (i = 0 ; i < 3 ; i++)

{

MoveWindow (hwndScroll[i],

(2 * i + 1) * cxClient / 14, 2 * cyChar,

cxClient / 14, cyClient - 4 * cyChar, TRUE) ;



MoveWindow (hwndLabel[i],

(4 * i + 1) * cxClient / 28, cyChar / 2,

cxClient / 7, cyChar, TRUE)



MoveWindow (hwndValue[i],

(4 * i + 1) * cxClient / 28,

cyClient - 3 * cyChar / 2,

cxClient / 7, cyChar, TRUE) ;

}

SetFocus (hwnd) ;

return 0 ;



case WM_SETFOCUS :

SetFocus (hwndScroll[idFocus]) ;

return 0 ;



case WM_VSCROLL :

i = GetWindowLong ((HWND) lParam, GWL_ID) ;



switch (LOWORD (wParam))

{

case SB_PAGEDOWN :

color[i] += 15 ;

// fall through

case SB_LINEDOWN :

color[i] = min (255, color[i] + 1) ;

break ;



case SB_PAGEUP :

color[i] -= 15 ;

// fall through

case SB_LINEUP :

color[i] = max (0, color[i] - 1) ;

break ;



case SB_TOP :

color[i] = 0 ;

break ;



case SB_BOTTOM :

color[i] = 255 ;

break ;



case SB_THUMBPOSITION :

case SB_THUMBTRACK :

color[i] = HIWORD (wParam) ;

break ;



default :

break ;

}

SetScrollPos (hwndScroll[i], SB_CTL, color[i], TRUE) ;

wsprintf (szBuffer, TEXT ("%i"), color[i]) ;

SetWindowText (hwndValue[i], szBuffer) ;



DeleteObject ((HBRUSH)

SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)

CreateSolidBrush (RGB (color[0], color[1], color[2])))) ;



InvalidateRect (hwnd, &rcColor, TRUE) ;

return 0 ;



case WM_CTLCOLORSCROLLBAR :

i = GetWindowLong ((HWND) lParam, GWL_ID) ;

return (LRESULT) hBrush[i] ;



case WM_CTLCOLORSTATIC :

i = GetWindowLong ((HWND) lParam, GWL_ID) ;



if (i >= 3 && i <= 8) // static text controls

{

SetTextColor ((HDC) wParam, crPrim[i % 3]) ;

SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNHIGHLIGHT));

return (LRESULT) hBrushStatic ;

}

break ;

case WM_SYSCOLORCHANGE :

DeleteObject (hBrushStatic) ;

hBrushStatic = CreateSolidBrush (GetSysColor(COLOR_BTNHIGHLIGHT)) ;

return 0 ;

case WM_DESTROY :

DeleteObject ((HBRUSH)

SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)

GetStockObject (WHITE_BRUSH))) ;



for (i = 0 ; i < 3 ; i++)

DeleteObject (hBrush[i]) ;



DeleteObject (hBrushStatic) ;

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}



LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message,

WPARAM wParam, LPARAM lParam)

{

int id = GetWindowLong (hwnd, GWL_ID) ;

switch (message)

{

case WM_KEYDOWN :

if (wParam == VK_TAB)

SetFocus (GetDlgItem (GetParent (hwnd),

(id + (GetKeyState (VK_SHIFT) < 0 ? 2 : 1)) % 3)) ;

break ;

case WM_SETFOCUS :

idFocus = id ;

break ;

}

return CallWindowProc (OldScroll[id], hwnd, message, wParam,lParam) ;

}

COLORS1利用子窗口进行工作,该程序使用10个子窗口控件:3个滚动条、6个静态文字窗口和1个静态矩形框。COLORS1拦截WM_CTLCOLORSCROLLBAR消息来给红、绿、蓝3个滚动条的内部着色,并拦截WM_CTLCOLORSTATIC消息来着色静态文字。

您可以使用鼠标或者键盘来挪动滚动条,从而利用COLORS1作为一种实验颜色显示的开发工具,为您自己的Windows程序选择漂亮的颜色(或者,您可能更喜欢难看的颜色)。COLORS1的显示如图9-3所示。不幸的是,这些颜色在印表纸上被显示为不同深浅的灰色。

 

 

图9-3 COLORS1的屏幕显示

COLORS1不处理WM_PAINT消息,所有的工作几乎都是由子窗口完成的。

显示区域右半部显示的颜色实际上是窗口的背景颜色。SS_WHITERECT样式的静态子窗口显示在显示区域的左半部。三个滚动条是SBS_VERT样式的子窗口控件,它们被定位在SS_WHITERECT子窗口的顶部。另外六个SS_CENTER样式(居中文字)的静态子窗口提供卷标和颜色值。COLORS1在WinMain函数中用CreateWindow建立它的普通重迭式窗口和10个子窗口。SS_WHITERECT和SS_CENTER静态窗口使用窗口类别「static」;三个滚动条使用窗口类别「scrollbar」。

CreateWindow呼叫中的x位置、y位置、宽度和高度参数最初设为0,因为位置和大小都取决于显示区域的尺寸,而它目前尚未确定。COLORS1的窗口消息处理程序在接收到WM_SIZE消息时,就使用MoveWindow给10个子窗口重新确定大小。所以,每当您对COLORS1窗口进行缩放时,滚动条的尺寸就会按比例变化。

当WndProc窗口消息处理程序收到WM_VSCROLL消息时,lParam参数的高字组就是子窗口的句柄。我们可以使用GetWindowWord来得到子窗口的ID:

i = GetWindowLong ((HWND) lParam, GWL_ID) ;

对于这三个滚动条,我们已经按习惯将其ID设为0、1、2,所以WndProc能区别出是哪个滚动条在产生消息。

由于子窗口的句柄在建立时就被储存在数组中,所以WndProc就能对相对应的滚动条消息进行处理,并通过呼叫SetScrollPos来设定相对应的新值:

SetScrollPos (hwndScroll[i], SB_CTL, color[i], TRUE) ;

WndProc也改变滚动条底部子窗口的文字:

wsprintf (szBuffer, TEXT ("%i"), color[I]) ;

SetWindowText (hwndValue[i], szBuffer) ;

自动键盘接口

滚动条控件也能处理键盘输入,但是只有在拥有输入焦点时才行。下表说明怎样将键盘光标键转变为卷动消息:

表9-5

 

游标键

卷动消息的wParam值

Home

SB_TOP

End

SB_BOTTOM

Page Up

SB_PAGEUP

Page Down

SB_PAGEDOWN

左或上

SB_LINEUP

右或下

SB_LINEDOWN

事实上,SB_TOP和SB_BOTTOM卷动消息只能用键盘产生。在使用鼠标按动卷动列时,如果想使该卷动列获得输入焦点,那么您必须将WS_TABSTOP标识符包含到CreateWindow呼叫的窗口类别参数中。当滚动条拥有输入焦点时,在该滚动条的小方框上将显示一个闪烁的灰色块。

为了给滚动条提供全面的键盘接口,还需要另外一些工作。首先,WndProc窗口消息处理程序必须使滚动条拥有输入焦点,它是通过处理WM_SETFOCUS消息来完成这一点的,该WM_SETFOCUS消息是当滚动条获得输入焦点时其父窗口接收到的。WndProc给其中一个滚动条设定输入焦点。

SetFocus (hwndScroll[idFocus]) ;

其中idFocus是一个整体变量。

但是,还需要一些借助键盘尤其是Tab键,来从一个滚动条转换到另一个滚动条的方法。这比较困难,因为一旦某个滚动条拥有了输入焦点,它就处理所有的键盘输入,但滚动条只关心光标键,而忽略Tab键。解决这一两难处境的方法是「窗口子类别化」。我们将用它来给COLORS1增加使用Tab键从一个滚动条跳到另一个滚动条的功能。

窗口子类别化(Window Subclassing)

滚动条控件的窗口消息处理程序是Windows内部的。但是,将GWL_WNDPROC标识符作为参数来呼叫GetWindowLong,您就可以得到这个窗口消息处理程序的地址。另外,您可以呼叫SetWindowLong给该滚动条设定一个新的窗口消息处理程序,这个技术叫做「窗口子类别化」,非常有用。它能让您给现存的窗口消息处理程序设定「挂勾」,以便在自己的程序中处理一些消息,同时将其它所有消息传递给旧的窗口消息处理程序。

在COLORS1中对卷动消息进行初步处理的窗口消息处理程序叫做ScrollProc,它在COLORS1.C文件的尾部。由于ScrollProc是COLORS1中的函数,而Windows将呼叫COLORS1,所以ScrollProc必须被定义为callback函数。

对三个滚动条中的每一个,COLORS1使用SetWindowLong来设定新的滚动条窗口消息处理程序的地址,并取得现存滚动条窗口消息处理程序的地址:

OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i], GWL_WNDPROC,

(LONG) ScrollProc)) ;

现在,函数ScrollProc得到了Windows发送到COLORS1中三个滚动条(当然不是其它程序中的滚动条)的滚动条窗口消息处理程序的全部消息。ScrollProc窗口消息处理程序在接收到Tab或者Shift-Tab键时,就将输入焦点改变到下一个(或者上一个)滚动条。它使用CallWindowProc呼叫旧的滚动条窗口消息处理程序。

给背景着色

当COLORS1定义它的窗口类别时,也为其显示区域背景定义了一个实心的黑色画刷:

wndclass.hbrBackground = CreateSolidBrush (0) ;

当您改变COLORS1的滚动条设定时,程序必须建立一个新的画刷,并将该新画刷句柄放入窗口类别结构中。如同使用GetWindowLong和SetWindowLong能得到并设定滚动条窗口消息处理程序一样,用GetClassWord和SetClassWord能得到这个画刷的句柄。

您可以建立新的画刷并将其句柄插入窗口类别结构中,然后删除旧的画刷:

DeleteObject ((HBRUSH)

SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)

CreateSolidBrush (RGB (color[0], color[1], color[2])))) ;

Windows下一次重新为窗口的背景着色时,将使用这个新画刷。为了强迫Windows抹掉背景,我们将使整个显示区域无效:

InvalidateRect (hwnd, &rcColor, TRUE) ;

TRUE(非零)值作为第三个参数,表示希望在重新着色之前删去背景。

InvalidateRect使Windows在窗口消息处理程序的消息队列中放进一个WM_PAINT消息。由于WM_PAINT消息的优先等级比较低,所以,如果您还在使用鼠标或者光标键移动滚动条的话,这个消息将不会立即被处理。如果您想在颜色改变之后使该窗口立即变成最新的(目前的),那么您可以在InvalidateRect之后增加下面的叙述:

UpdateWindow (hwnd) ;

但这会使得键盘和鼠标处理变慢。

COLORS1中的WndProc函数不处理WM_PAINT消息,而是将其传给DefWindowProc。Windows对WM_PAINT消息的内定处理只是呼叫BeginPaint和EndPaint使窗口生效。因为在InvalidateRect呼叫中已经指定背景要被抹掉,所以BeginPaint呼叫使Windows发出一个WM_ERASEBKGND(删除背景)消息,WndProc也将忽略这个消息。Windows用窗口类别中指定的画刷将显示区域的背景抹去,这样就处理了这个消息。

在终止以前进行清除总是一个好主意,因此在处理WM_DESTROY消息处理期间,再一次呼叫DeleteObject:

DeleteObject ((HBRUSH)

SetClassLong (hwnd, GCL_HBRBACKGROUND,

(LONG) GetStockObject (WHITE_BRUSH))) ;

给滚动条和静态文字着色

在COLORS1中,三个滚动条的内部和六个文字字段中的文字着色为红、绿和蓝色。滚动条的着色是通过处理WM_CTLCOLORSCROLLBAR消息来完成的。

在WndProc中,我们为画刷定义了一个由三个句柄组成的静态数组:

static HBRUSH hBrush [3] ;

在处理WM_CREATE期间,我们建立三个画刷:

for (I = 0 ; I < 3 ; I++)

hBrush[0] = CreateSolidBrush (crPrim [I]) ;

其中crPrim数组中包含三种原色的RGB值。在WM_CTLCOLORSCROLLBAR处理期间窗口消息处理程序传回这三画刷中的一个:

case        WM_CTLCOLORSCROLLBAR:

i = GetWindowLong ((HWND) lParam, GWL_ID) ;

return (LRESULT) hBrush [i] ;

在处理WM_DESTROY消息的过程中,这些画刷必须被删除:

for (i = 0 ; i < 3 ; i++)

DeleteObject (hBrush [i])) ;

同样地,静态文字字段中的文字是在处理WM_CTLCOLORSTATIC消息中呼叫SetTextColor来着色的。文字背景用SetBkColor函数设定为系统颜色COLOR_BTNHIGHLIGHT,这导致文字背景颜色和滚动条与文字后面的静态矩形控件的颜色一样。对于静态文字控件,这种文字背景颜色只用于字符串中每个字符后面的矩形,而不会用于整个控件窗口。为了实作这一点,窗口消息处理程序还必须传回COLOR_BTNHIGHLIGHT颜色画刷的句柄。这个画刷被称为hBrushStatic,它在WM_CREATE消息处理期间建立,在WM_DESTROY消息处理期间清除。

在WM_CREATE消息处理期间依据COLOR_BTNHIGHLIGHT颜色建立画刷,并且在执行期间使用这一画刷时,我们遇到了一个小问题。如果程序在执行期间改变了COLOR_BTNHIGHLIGHT颜色,那么静态矩形的颜色将发生变化,并且文字背景的颜色也会变化,但是文字窗口控件的整个背景将保持原有的COLOR_BTNHIGHLIGHT颜色。

为了解决这个问题,COLORS1也简单地通过使用新颜色重新建立hBrushStatic来处理WM_SYSCOLORCHANGE消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值