《Windows API每日一練》8.3 scrollbar控件

在第三章SYSMETS2.C實例中,我們是通過CreateWindow函數創建窗口的參數窗口樣式中添加垂直或水平滾動條。本節我們將講述作為子窗口控件的滾動條。

本節必須掌握的知識點:

??? ????滾動條類

??? ????滾動條控件和著色

8.3.1 滾動條類

窗口滾動條與滾動條控件的異同

滾動條子窗口控件可以出現在父窗口客戶區的任何地方。可以使用預定義的“滾動條”窗口類和兩種滾動條樣式SBS_VERT 和SBS_HORZ之一來創建子窗口滾動條控件。

不同于按鈕控件,滾動條控件不發送 WM_COMMAND消息到父窗口。它們就像窗口滾動條一樣發送WM_VSCROLL和 WM_HSCROLL消息。在處理滾動條消息時,可以用IParam參數區分窗口滾動條和滾動條控件。如果IParam參數等于0,就說明它是窗口滾動條;如果等于滾動條窗口句柄,就說明它是滾動條控件。wParam參數的高位字和低位字部分對于窗口滾動條和滾動條控件的含義是一樣的。

與窗口滾動條有一個固定的寬度不同,Windows會通過CreateWindow調用(或之后的 MoveWindow調用)中指定的矩形尺寸來調整滾動條控件的尺寸。你可以產生長而窄的滾動 條控件或短而粗的滾動條控件。

如果想創建和窗口滾動條具有相同尺寸的滾動條控件,則可以使用GetSystemMetrics 獲得水平滾動條的高度:

GetSyscemMetrics (SM_CYHSCROLL) ;

或者獲得垂直滾動條的寬度:

GetSystemMetrics (SM_CXVSCROLL);

滾動條窗口樣式標識符 SBS_LEFTALIGN,SBS_RIGHTALIGN,SBS_TOPALIGN 和 SBS_BOTTOMALIGN都為滾動條提供標準尺寸。不過它們只適用于對話框中的滾動條。 可以使用與用于窗口滾動條同樣的函數來設置滾動條控件的范圍和位置:

SeCScrollRange (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消息,就可以從這個消息返回一個畫刷來修改原來的顏色。

窗口滾動條

滾動條控件

消息

發送WM_VSCROLLWM_HSCROLL消息。不發送WM_COMMAND消息。wParam參數的意義是一樣的。lParam:當消息來自窗口滾動條時為NULL,來自滾動條控件時為滾動條的句柄。

寬度或高度

固定大小

//水平滾動條高度

GetSysMetricsSM_CYHSCROLL;

//垂直滾動條寬度

GetSysMetricsSM_CYVSCROLL

1、大小、位置均可設定;

2、在CreateWindowMoveWindow函數中指定,大小可自定義。

窗口樣式

WS_VSCROLL:垂直滾動條(在窗口右側)

WS_HSCROLL:水平滾動條(在窗口下方)

可用滾動條樣式和尺寸

SBS_VERTSBS_HORZ

S?SBS_TOPALIGN? BS_BOTTOMALIGNSBS_LEFTALIGNSBS_RIGHTALIGN等。

調用函數

的參數

SetScrollInfo(hwnd,SB_VERT,

&si,bRedraw);

SetScrollInfo(hwndScroll,SB_CTL,

&si,bRedraw);

自動鍵盤接口

滾動條控件還可以處理按鍵信息,但前提是它們擁有輸入焦點。下表顯示了鍵盤光標是如何轉換為滾動條消息的。

光標鍵

滾動條消息wParam

Home

SB_TOP

End

SB_BOTTOM

PageUp

SB_PAGEUP

PageDown

SB_PAGEDOWN

←或↑

SB_LINEUP

→或↓

SB_LINEDOWN

事實上,SB_TOP和SB_BOTTOM這兩個滾動條消息只能通過鍵盤產生。如果你想讓滾動條控件在鼠標單擊滾動條時取得輸入焦點,必須在CreateWindow函數的窗口類參數中加入WS_TABSTOP標識符。當滾動條獲得輸入焦點時,滾動條滑塊上會顯示一個閃爍的灰色塊。

為了給滾動條提供完整的鍵盤接口,需要做更多的工作。首先,WndProc窗口過程必須專門提供滾動條所需要的輸入焦點。為此,它會處理WM_SETFOCUS消息,這是父窗口得到輸入焦點時接收到的消息。WndProc只需把輸入焦點給其中一個滾動條:

SetFocus (hwndScroll[idFocus]);

這里的idFocus是一個全局變量。

但還需要一些方法通過鍵盤把輸入焦點從一個滾動條移到另一個,最好是使用Tab鍵。 這樣做會有一定難度,因為一旦滾動條獲得輸入焦點,它就會處理所有的按鍵信息。但是滾動條關心的只有光標鍵,它會忽視Tab鍵。解決這個問題的出路在于使用“窗口子類” 這一技術。

8.3.2 第52練:滾動條控件和著色

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

052? WIN32 API 每日一練

??? ?第52個例子COLORS1.C:滾動條控件和著色

??? ?CallWindowProc 函數

??? ?SetWindowLong函數

??? ?SetClassLong函數

??? ?GetDlgItem 函數

??? ?WM_CTLCOLORSCROLLBAR消息

??? ?WM_CTLCOLORSTATIC 消息

??? ?WM_SYSCOLORCHANGE消息

(c) www.bcdaren.com, 2020

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

#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");

??? (略)

??? 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"), EXT("Green"),TEXT("Blue") };

??? HINSTANCE hInstance;

??? int i, cxClient, cyClient;

??? TCHAR szBuffer[10];

??? switch (message)

??? {

??? case WM_CREATE:

??????? hInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);//獲取進程句柄

??????? //創建白色矩形靜態窗口控件ID:9--用來存放3個滾動條,可以隱掉后測試

??????? 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++) //生成3個滾動條控件

??????? {

??????????? //創建三個滾動條,范圍0-255,ID分別為0,1,2

//WS_TABSTOP標識符:當滾動條獲得輸入焦點時,

//滾動條滑塊上會顯示一個閃爍的灰色塊。

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

??????????????? WS_CHILD | WS_VISIBLE |

??????????????? WS_TABSTOP | SBS_VERT,? //垂直滾動條窗口類

??????????????? 0, 0, 0, 0,

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

??????????? //SB_CTL檢索滾動條控件的位置

//設置滾動條控件的滾動范圍

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

??????????? SetScrollPos(hwndScroll[i], SB_CTL, 0, FALSE); //滾動滑塊位置

??????????? //3個顏色名稱為"Red"、"Green"、"Blue"的靜態文本框,ID分別為3,4,5

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

??????????????? WS_CHILD | WS_VISIBLE | SS_CENTER, //將文本居中

??????????????? 0, 0, 0, 0,

??????????????? hwnd, (HMENU)(i + 3),

??????????????? hInstance, NULL);

??????????? //3個表示顏色值得靜態文本框,初始值為"0",IDs 6, 7, and 8

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

??????????????? WS_CHILD | WS_VISIBLE | SS_CENTER,

??????????????? 0, 0, 0, 0,

??????????????? hwnd, (HMENU)(i + 6),

??????????????? hInstance, NULL);

??????????? //為滾動條設置一個新的窗口過程ScrollProc,返回舊的窗口過程地址

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

??????????????? GWL_WNDPROC, (LONG)ScrollProc);

??????????? //創建3個畫刷

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

??????? }

??????? //創建靜態文本背景畫刷,3D 顯示元素的高亮顏色

??????? 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);

??????? //設置滾動條在主窗口大小和位置:寬cxClient/14,高cyClient -4*cyChar;

??????? 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:

??????? //獲取子窗口ID

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

??????? switch (LOWORD(wParam))

??????? {

??????? case SB_PAGEDOWN: color[i] += 15;

??????????? //繼續執行

??????? case SB_LINEDOWN: color[i] = min(255, color[i] + 1); break;

??????? case SB_PAGEUP: color[i] -= 15;

??????????? // 繼續執行

??????? 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); //重繪窗口,TRUE擦除背景

??????? //UpdateWindow(hwnd);//立即更新,不需要送入消息隊列

??????? return 0;

??????? //將要繪制控件時滾動條控件消息:

//wParam:滾動條控件的設備上下文的句柄DC,lParam:滾動條句柄

??? case WM_CTLCOLORSCROLLBAR:

??????? //返回畫刷句柄,用來修改三個滾動條內部的顏色

??????? i = GetWindowLong((HWND)lParam, GWL_ID);//獲取控件ID

//必須將句柄返回給畫刷。 系統使用畫刷繪制滾動條控件的背景。

??????? return (LRESULT)hBrush[i];

?? //將要繪制時,靜態控件消息---設定靜態文本的顏色

??? case WM_CTLCOLORSTATIC:

??????? i = GetWindowLong((HWND)lParam, GWL_ID); //獲取窗口ID

??????? if (i >= 3 && i <= 8) // 6個static text controls ID:3~8

??????? {

??????????? //設置靜態文本顏色

??????????? 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),//包含控件的對話框的句柄

??????? ?? //追蹤SHIFT鍵,改變TAB鍵切換的順序:

??????? ?? //按下SHIFT <0:2,1,0;未按下>0:0,1,2

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

??????? break;

??? case WM_SETFOCUS:

??????? idFocus = id;

??????? break;

??? }

??? //調用子窗口舊的窗口過程

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

}

/******************************************************************************

CallWindowProc 函數:子窗口類過程返回舊窗口過程

LRESULT CallWindowProcA(

? WNDPROC lpPrevWndFunc,

? HWND??? hWnd,

? UINT??? Msg,

? WPARAM? wParam,

? LPARAM? lParam

);

*******************************************************************************

SetWindowLong函數:設置子窗口類過程

LONG SetWindowLongA(

? HWND hWnd,

? int? nIndex,//設置窗口過程的新地址

? LONG dwNewLong//新窗口過程

);

*******************************************************************************

SetClassLong函數:將指定偏移量處的指定32位(long)值替換到指定窗口所屬類的額外類存儲器或WNDCLASSEX結構中。

DWORD SetClassLongA(

? HWND hWnd,?? //窗口的句柄,間接地,窗口所屬的類。

? int? nIndex, //將要被替換的值。

? LONG dwNewLong//替換值

);

注意? 此函數已被SetClassLongPtr函數取代。要編寫與Windows 32位和64位版本兼容的代碼,請使用SetClassLongPtr。

*******************************************************************************

GetDlgItem 函數用于獲取對話框模板中標識符(ID)對應的子窗口句柄。

HWND GetDlgItem(

? HWND hDlg,??? //對話框的窗口句柄

? int? nIDDlgItem//子窗口的標識符(ID)

);

返回值:對應標識符的子窗口的句柄(HWND)。

*******************************************************************************

WM_CTLCOLORSCROLLBAR消息:發送滾動條控件消息至父窗口

wParam:DC,lParam:滾動條句柄,

//必須返回畫筆句柄

WM_CTLCOLORSTATIC 消息:發送靜態控件消息至父窗口

WM_SYSCOLORCHANGE消息:更改系統顏色設置后,會將WM_SYSCOLORCHANGE消息發送到所有頂級窗口

*/

?????? 運行結果:

圖8-5 滾動條控件

?

總結

實例COLORS1.C在一個白色靜態文本框內繪制了3個滾動條控件,此外還繪制了6個靜態文本控件顯示RGB顏色及顏色值。在主窗口客戶區的左側繪制一個矩形,使用3個滾動條控件的RGB值創建一個畫刷,填充矩形背景。

此外,還根據3個滾動條控件的值(0~255)分別創建3個畫刷,設置3個靜態文本顏色,創建一個高亮系統顏色畫刷作為靜態文本控件的背景色。

實例COLORS1.C還創建了一個窗口子類,定義了一個新的滾動條子窗口控件過程,用于處理鍵盤接口TAB鍵,切換焦點窗口。

主窗口過程對于WM_CREATE消息的處理。首先創建一個存放3個滾動條控件的靜態文本框。接著創建3個滾動條控件,并將滾動條滾動范圍設置為0~255,與RGB顏色值對應。初始滾動條滑塊位置為0。然后在滾動條控件的上方和下方分別創建3個靜態文本控件,用于顯示RGB顏色和顏色值。最后調用SetWindowLong函數設置滾動條控件新的窗口過程ScrollProc,并返回Windows預定義的滾動條控件默認窗口過程,存入OldScroll[i]數組。接著創建一個靜態文本背景畫刷,并獲取對話框字體的高。

WM_SIZE消息的處理:調用SetRect函數在主窗口右側繪制一個矩形框。調用MoveWindow函數調整靜態文本框控件和滾動條控件的大小。

WM_SETFOUCUS消息處理:調用SetFocus函數將當前idFocus滾動條控件設為焦點窗口。

WM_VSCROLL消息處理:調用GetWindowLong函數獲取滾動條控件ID,并依據wParam

參數低字值調整滾動條滑塊位置。滑塊位置即顏色值,修改3個靜態文本顏色值,并以此生成新畫刷填充主窗口右側矩形背景色。

WM_CTLCOLORSCROLLBAR消息處理:將要繪制滾動條控件時接收此消息,該消息的wParam:滾動條控件的設備上下文的句柄DC;lParam:滾動條句柄。調用GetWindowLong依據滾動條控件句柄獲取滾動條控件ID,并返回畫刷return (LRESULT)hBrush[ID];

WM_CTLCOLORSTATIC消息處理:將要繪制靜態文本控件時接收此消息,調用GetWindowLong依據靜態文本控件句柄獲取控件ID,并更新靜態文本顏色和顏色值。

WM_SYSCOLORCHANGE消息處理:如果更改系統顏色,則刪除舊靜態文本背景畫刷,重新依據系統顏色生成新的靜態文本背景畫刷。

WM_DESTROY消息處理:刪除創建的新GDI畫刷對象。

窗口子類

滾動條控件的窗口過程在Windows內部。但是你可以調用GetWindowLong來獲取這 個窗口過程的地址,使用GWL_WNDPROC標識符作為參數即可。此外,還可以通過調用SetWindowLong,為滾動條設置一個新的窗口過程。這種技術被稱為“窗口子類”。它的功能非常強大。它可以讓你連接到已有的窗口過程,在你的程序中處理一些消息,并將其他消息傳遞給舊的窗口過程。

在COLORS1中,能初步處理滾動條消息的窗口過程名為ScroMProc,它列在 C0L0RS1.C文件的結束部分。由于COLORS1中的ScrollProc是一個被Windows調用的函數,因此它必須被定義成CALLBACK類型。

對這三個滾動條中的每一個COLORS1都使用SetWindowLong來設置新的滾動條窗口過程的地址,同時獲得現有滾動條窗口過程的地址:

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

GWL_VMDPROC,(LONG) ScrollProc));

現在,ScrollProc獲得了 Windows發送給COLORS1程序中三個滾動條的所有消息(當然不包括在其他程序中的滾動條)。當它收到Tab或Shift-Tab擊鍵信息后,此ScrollProc 窗口過程只需更改輸入焦點到下一個(或前一個)滾動條即可。它使用CallWindowProc來調 用舊的滾動條窗口過程。

背景著色

在COLORS1定義它的窗口類時,給它的客戶區指定了一個黑色的背景畫刷:

wndclass.hbrBackground = CreateSolidBrush (0);

當你更改COLORS1的滾動條設置時,程序必須創建一個新的畫刷,并把新畫刷句柄存入窗口類的結構中。正如我們使用GetWindowLong和SetWindowLong來獲取和設置滾動 條窗口過程一樣,我們可以使用GetClassWord和SetClassWord來獲取和設置這個畫刷的句柄。

你可以創建新的畫刷,把句柄存入到窗口類結構中,然后刪除舊的畫刷:

DeleteObject ((HBRUSH)

?????? ?????? SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)

????????????? ?????? CreaceSolidBrush (RGB (colort[0], color[1], color[2]))));

下一次Windows重新給窗口背景著色的時候,Windows將使用這個新畫刷。如果要強制 Windows擦除背景,我們可以讓客戶區的右半部分失效:

InvalidateRect (hwnd, &rcColor, TRUE);

函數的第三個參數輸入TRUE(非零值),表明我們希望在窗口重繪之前擦除背景。

InvalidateRect函數會讓Windows把WM_PAINT消息放在窗口過程的消息隊列中。由于WM_PAINT消息屬于低優先級消息。因此,如果你仍然在移動鼠標或光標鍵,此消息將不會立即被處理。另一種情況是,如果你希望窗口在顏色修改后立即更新,則可以在 InvalidateRect函數被調用后調用下面的函數:

UpdateWindow (hwnd);

不過,這個函數可能會拖慢鍵盤和鼠標處理速度。

COLORS1的WndProc函數不直接處理WM_PAINT消息,而是將它傳遞給 DefWindowProc函數。WM_PAINT消息在Windows中的默認處理方式僅僅是調用 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) IParam, GWL_ID);

???????????? return (LRESULT) hBrush [i];

這些畫刷必須在處理WM_DESTROY消息期間被銷毀:

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

?????? DeleteObject (hBrush [i]));

類似地,靜態文本框中文本的著色是通過處理WM_CTLCOLORSTATIC消息和調用 SetTextCoIor函數完成的。文本的背景通過調用SetBkColor設置為系統顏色 COLOR_BTNHIGHLIGHT。這會導致文本的背景與滾動條后面的靜態矩形控件具有相同的顏色。對于靜態文本控件,這種文本的背景顏色只應用于字符串中每個字符背后的矩形框,而不是控件窗口的整個寬度。要做到這一點,窗口過程必須返回一個COLOR_BTNHIGHLIGHT顏色的畫刷句柄。這個被稱為hBrushStatic的畫刷是在 WM_CREATE處理期間產生的,并在WM_DESTROY消息處理期間被銷毀。

程序在WM_CREATE消息處理期間產生COLOR_BTNHIGHLIGHT顏色的畫刷,并在程序生命周期中使用它。但這樣我們會碰到一個小問題。如果C0L0R_BTNHIGHL1GHT 顏色在程序運行過程中被改變了,靜態矩形的顏色會改變,文本背景顏色會改變,但整個文本窗口控件的背景仍將保持原有的COLOR_BTNHIGHLIGHT顏色。

為解決這一問題,COLORS 1在處理WM_SYSCOLORCHANGE消息時簡單地用新顏色重新創建hBrushStatic。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40800.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40800.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40800.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python常量與變量的終極指南:從基礎到進階的15個要點

今天&#xff0c;我們將一起揭開Python中最基本但也極其重要的概念——常量與變量的神秘面紗。別擔心&#xff0c;我會用最簡單直白的語言&#xff0c;讓你從入門到略有小成&#xff0c;一步步掌握這些核心知識。準備好你的筆記本&#xff0c;讓我們開始這場Python之旅吧&#…

在Linux環境下搭建Redis服務結合內網穿透實現通過GUI工具遠程管理數據庫

文章目錄 前言1. 安裝Docker步驟2. 使用docker拉取redis鏡像3. 啟動redis容器4. 本地連接測試4.1 安裝redis圖形化界面工具4.2 使用RDM連接測試 5. 公網遠程訪問本地redis5.1 內網穿透工具安裝5.2 創建遠程連接公網地址5.3 使用固定TCP地址遠程訪問 前言 本文主要介紹如何在Li…

mysql 9 新特新

mysql9新特性 新特性Audit Log NotesC API NotesCharacter Set SupportCompilation NotesComponent NotesConfiguration NotesData Dictionary NotesData Type NotesDeprecation and Removal NotesEvent Scheduler NotesJavaScript ProgramsOptimizer NotesPerformance Schema …

Spring中的事件監聽器使用學習

一、什么是Spring中的事件監聽機制&#xff1f; Spring框架中的事件監聽機制是一種設計模式&#xff0c;它允許你定義和觸發事件&#xff0c;同時允許其他組件監聽這些事件并在事件發生時作出響應。這種機制基于觀察者模式&#xff0c;提供了一種松耦合的方式來實現組件間的通信…

Linux 系統性能分析與故障排查:從入門到進階

Linux 系統性能分析與故障排查&#xff1a;從入門到進階 作為系統管理員或 IT 專業人員&#xff0c;掌握系統性能分析和故障排查技能至關重要。這些技能可以幫助你識別和解決系統性能問題&#xff0c;確保系統穩定運行。本文將介紹系統性能分析和故障排查的基本方法&#xff0…

CTF實戰:從入門到提升

CTF實戰&#xff1a;從入門到提升 &#x1f680;前言 沒有網絡安全就沒有國家安全&#xff0c;網絡安全不僅關系到國家整體信息安全&#xff0c;也關系到民生安全。近年來&#xff0c;隨著全國各行各業信息化的發展&#xff0c;網絡與信息安全得到了進一步重視&#xff0c;越…

XAML 框架橫向對比

多年來&#xff0c;基于 XAML 的 UI 框架有了很大的發展。下面的圖表很好地證明了這個觀點。XAML UI 框架的三大巨頭&#xff1a;Avalonia UI、Uno Platform 和 .NET MAUI 都支持跨平臺的應用。事實上&#xff0c;除了 Avalonia UI&#xff0c;對跨平臺 XAML 的需求是它們發展的…

【深度學習】圖形模型基礎(5):線性回歸模型第四部分:預測與貝葉斯推斷

1.引言 貝葉斯推斷超越了傳統估計方法&#xff0c;它包含三個關鍵步驟&#xff1a;結合數據和模型形成后驗分布&#xff0c;通過模擬傳播不確定性&#xff0c;以及利用先驗分布整合額外信息。本文將通過實際案例闡釋這些步驟&#xff0c;展示它們在預測和推斷中的挑戰和應用。…

Unity 使用AVProMovieCapture實現Game視圖屏幕錄制

內容將會持續更新&#xff0c;有錯誤的地方歡迎指正&#xff0c;謝謝! Unity 使用AVProMovieCapture實現Game視圖屏幕錄制 TechX 堅持將創新的科技帶給世界&#xff01; 擁有更好的學習體驗 —— 不斷努力&#xff0c;不斷進步&#xff0c;不斷探索 TechX —— 心探索、心…

【云計算】公有云、私有云、混合云、社區云、多云

公有云、私有云、混合云、社區云、多云 1.云計算的形態1.1 公有云1.2 私有云1.3 混合云1.4 社區云1.5 多云1.5.1 多云和混合云之間的關系1.5.2 多云的用途1.5.3 影子 IT 和多云1.5.4 優缺點 2.不同云形態的對比 1.云計算的形態 張三??在家做飯吃&#xff0c;這是 私有云&…

liunx上修改Firefox版本號

在Linux上修改Firefox的版本號并不直接推薦也不鼓勵&#xff0c;因為這可能會影響到瀏覽器的安全性、兼容性和自動更新功能。但如果你因為某些特殊測試場景確實需要修改其顯示的版本號&#xff08;請注意&#xff0c;這樣做可能會引發不可預料的問題&#xff09;&#xff0c;可…

【擴散模型】LCM LoRA:一個通用的Stable Diffusion加速模塊

潛在一致性模型&#xff1a;[2310.04378] Latent Consistency Models: Synthesizing High-Resolution Images with Few-Step Inference (arxiv.org) 原文&#xff1a;Paper page - Latent Consistency Models: Synthesizing High-Resolution Images with Few-Step Inference (…

ELK優化之Filebeat部署

目錄 1.安裝配置Nginx 2.安裝 Filebeat 3.設置 filebeat 的主配置文件 4.修改Logstash配置 5.啟動配置 6.kibana驗證 主機名ip地址主要軟件es01192.168.9.114ElasticSearches02192.168.9.115ElasticSearches03192.168.9.116ElasticSearch、Kibananginx01192.168.9.113ng…

【鎖】各種鎖的概念

解釋一下什么是樂觀鎖、悲觀鎖、自旋鎖、互斥鎖、讀寫鎖、排他鎖、共享鎖、統一鎖、分段鎖&#xff1f; 定義角度不同&#xff0c;通常把&#xff08;樂觀鎖、悲觀鎖&#xff09;、&#xff08;自旋鎖、互斥鎖&#xff09;、&#xff08;讀寫鎖、排他鎖、共享鎖&#xff09;、…

Redis---9---集群(cluster)

將新增的6387節點&#xff08;空槽號&#xff09;作為master節點加入原集群 Redis—9—集群&#xff08;cluster&#xff09; 是什么 定義 ? 由于數據量過大&#xff0c;單個Master復制集難以承擔&#xff0c;因此需要對多個復制集進行集群&#xff0c;形成水平擴展每個復…

Selenium 切換窗口

環境&#xff1a; Python 3.8 selenium3.141.0 urllib31.26.19說明&#xff1a; driver.current_window_handle # 返回當前窗口的句柄 driver.window_handles # 返回當前由driver啟動所有窗口句柄&#xff0c;是個列表 driver.switch_to.window(handle) # 根據 handle 切換窗口…

5個實用的文章生成器,高效輸出優質文章

在自媒體時代&#xff0c;優質內容的持續輸出是吸引讀者、提升影響力的關鍵。然而&#xff0c;對于許多自媒體創作者來說&#xff0c;頻繁的創作難免會遭遇靈感枯竭、創作不出文章的困擾。此時&#xff0c;文章生成器便成為了得力的助手。文章生成器的優勢能夠快速自動生成高質…

代碼隨想錄算法訓練營第13天|二叉樹的遞歸遍歷、二叉樹的迭代遍歷、二叉樹的統一迭代法、102.二叉樹的層序遍歷

打卡Day13 1.理論基礎2.二叉樹的遞歸遍歷3.二叉樹的迭代遍歷3.二叉樹的統一迭代法4.102.二叉樹的層序遍歷擴展107. 二叉樹的層序遍歷 II199.二叉樹的右視圖637.二叉樹的層平均值429.N叉樹的層序遍歷515.在每個樹行中找最大值116.填充每個節點的下一個右側節點指針117. 填充每個…

如何保證接口冪等性

如何保證接口冪等性 1、冪等性是什么&#xff1f; 接口冪等性是指用戶對于同一操作發起的一次請求或者多次請求的結果是一致的&#xff0c;不會因為多次點擊而產生了不同的結果。 2、使用冪等性的場景有哪些&#xff1f; 頁面點擊保存按鈕時&#xff0c;不小心快速點了兩次…

Python面試題-6

1. 請解釋Python中的動態類型。 Python中的動態類型 Python是一種動態類型語言&#xff0c;這意味著你不需要在編程時聲明變量的類型&#xff0c;而是在運行時自動推斷類型。在Python中&#xff0c;變量的類型是在程序運行時決定的&#xff0c;這意味著同一個變量可以在不改變…