《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;

        defaultbreak;

        }

        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.mfbz.cn/a/776296.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

带你了解“Java新特性——模块化”

Java平台从Java 8向Java 9及更高版本的进化&#xff0c;其中引入了一个重要的新特性——模块系统&#xff08;Project Jigsaw&#xff09;。模块系统的目的是解决大型应用的依赖管理问题&#xff0c;提升性能&#xff0c;简化JRE&#xff0c;增强兼容性和安全性&#xff0c;并提…

一文了解常见DNS问题

当企业的DNS出现故障时&#xff0c;为不影响企业的正常运行&#xff0c;团队需要能够快速确定问题的性质和范围。那么有哪些常见的DNS问题呢&#xff1f; 域名解析失败&#xff1a; 当您输入一个域名&#xff0c;但无法获取到与之对应的IP地址&#xff0c;导致无法访问相应的网…

Blazor 逐键搜索并动态反馈到url

Blazor 逐键搜索并动态反馈到url 源码 前言: 今天打开了 spotify 网页版找歌, 突然发现这个功能很抓眼球,于是试试blazor能不能模仿一下. 1. 节省时间,直接用模板开搞 新建项目,使用 Bootstrap Blazor App 模板 , 命名为 b22dynamicURL BootstrapBlazor简介: BootstrapBlaz…

数据库概念题总结

1、 2、简述数据库设计过程中&#xff0c;每个设计阶段的任务 需求分析阶段&#xff1a;从现实业务中获取数据表单&#xff0c;报表等分析系统的数据特征&#xff0c;数据类型&#xff0c;数据约束描述系统的数据关系&#xff0c;数据处理要求建立系统的数据字典数据库设计…

SQL注入方法

文章目录 前言如何测试与利用注入点手工注入思路工具sqlmap-r-u-m--level--risk-v-p--threads-batch-smart--os-shell--mobiletamper插件获取数据的相关参数 前言 记录一些注入思路和经常使用的工具&#xff0c;后续有用到新的工具和总结新的方法再继续补充。 如何测试与利用注…

使用 OpenCV 和 Python 进行车道检测和物体检测(YOLO)

本项目旨在开发一个集车道检测与物体检测功能于一体的智能视觉分析系统&#xff0c;利用先进的计算机视觉技术和深度学习模型&#xff0c;实现实时的道路场景理解和目标识别。系统主要依托OpenCV这一强大的计算机视觉库&#xff0c;以及Python作为编程语言&#xff0c;融合了车…

CentOS7.9下yum升级Apache HTTP Server2.4.6到2.4.60

1、CentOS7.9系统默认的Apache版本 在CentOS7.9上&#xff0c;如果使用yum安装Apache HTTP Server是最多到2.4.6版本的&#xff0c;这是因为el7下官方仓库的最高版本就是2.4.6&#xff0c;证据如下&#xff1a; $ yum info httpd ...... Installed Packages Name : ht…

Jetpack Compose实战教程(五)

Jetpack Compose实战教程&#xff08;五&#xff09; 第五章 如何在Compose UI中使用基于命令式UI的自定义View 文章目录 Jetpack Compose实战教程&#xff08;五&#xff09;一、前言二、本章目标三、开始编码3.1 先让自定义控件能跑起来3.2给自定义控件使用compose的方式赋值…

【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)

文章目录 定义简单工厂模式案例 | 代码Phone顶层接口设计Meizu品牌类Xiaomi品牌类PhoneFactory工厂类Customer 消费者类 工厂方法模式案例 | 代码PhoneFactory工厂类 Java高级特性---工厂模式与反射的高阶玩法方案&#xff1a;反射工厂模式 总结 其实工厂模式就是用一个代理类帮…

Java项目:基于SSM框架实现的学生公寓管理中心系统【ssm+B/S架构+源码+数据库+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的学生公寓管理中心系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

【CentOS 7.6】Linux版本 portainer本地镜像导入docker安装配置教程,不需要魔法拉取!(找不着镜像的来看我)

吐槽 我本来根本不想写这篇博客&#xff0c;但我很不解也有点生气&#xff0c;CSDN这么大没有人把现在需要魔法才能拉取的镜像放上来。 你们都不放&#xff0c;根本不方便。我来上传资源。 portainer-ce-latest.tar Linux/amd64 镜像下载地址&#xff1a; 链接&#xff1a;h…

加法器的基本操作

基本单元 与门(AND) 全1为1&#xff0c;有0为0 或门(OR) 全0为0&#xff0c;有1为1 非门(NOT) 为1则0&#xff0c;为0则1 异或门(XOR) 两个输入端&#xff0c;相同为0&#xff0c;不同为1 与非门(NADD) 全1为0&#xff0c;有0为1 或非门(NOR) 全0为1&#xff0c;有1为0。刚…

H5 Canvas实现转盘效果,控制指定数字

效果图 实现思路&#xff1a; 用Canvas画圆&#xff0c;然后再画扇形&#xff0c;然后中奖的开始用一张图片代替&#xff0c;点击的时候触发转动效果。 实现代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"><tit…

UNDO 表空间使用率高 active段占用高 无对应事务执行

UNDO表空间使用率告警&#xff0c;查看占用情况 active段占比很高 select tablespace_name,status,sum(bytes/1024/1024) mb from dba_undo_extents group by tablespace_name,status;不同状态的含义&#xff1a;**ACTIVE **&#xff1a;有活动事务在使用 Undo&#xff0c;这…

【JavaSE】数据类型与变量

目录 1. 字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.3.1 整型变量 3.3.2 长整型变量 3.3.3 短整型变量 3.3.4 字节型变量 3.4 浮点型变量 3.4.1 双精度浮点型 3.4.2 单精度浮点型 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3…

WEB安全-靶场

1 需求 2 语法 3 示例 男黑客|在线渗透测试靶场|网络安全培训基地|男黑客安全网 4 参考资料

windows 7 安装IPP协议,支持Internet打印

1 windows 7 安装IPP协议,支持Internet打印 #控制面板--打开或关闭Windows功能 3 复制Printers 文件夹 到 c:\inetpub\wwwroot\,复制msw3prt.dll到c:\windows\system32\ 4 打开IIs管理器 #报错:模块列表中不存在此处理程序所需的指定模块。如果您添加脚本映射处理程序映射&…

【力扣】数组中的第K个最大元素

一、题目描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入: [3,2,1,5,…

记一次EasyExcel的错误使用导致的频繁FullGC

记一次EasyExcel的错误使用导致的频繁FullGC 一、背景描述二、场景复现三、原因分析四、解决方案五、思考复盘 一、背景描述 繁忙的校招结束了&#xff0c;美好的大学四年也结束了&#xff0c;作者也有10个月没有更新了。拿到心仪的offer之后也开始了苦B的打工生活。 最近接到…

汽车信息安全--欧盟汽车法规

目录 General regulation 信息安全法规 R155《网络安全及网络安全管理系统》解析 R156《软件升级与软件升级管理系统》解析 General regulation 欧洲的汽车行业受到一系列法律法规的约束&#xff0c;包括 各个方面包括&#xff1a; 1.安全要求&#xff1a;《通用安全条例&a…