《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.xdnf.cn/news/1473081.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

纯javascript实现图片批量压缩打包zip下载后端ThinkPHP多国语言切换国际站

最近在做一个多国语言的工具站&#xff0c;需要实现多国语言切换&#xff0c;说到多国语言站&#xff0c;肯定是有2种方式&#xff0c;第一是子域名&#xff0c;第二就是子目录。根据自己的需要来确定。 后台配置如下&#xff1a; 前台显示&#xff1a; 前端纯javascript实现…

人工智能开发中的数据隐私

人工智能开发中的数据隐私对于建立用户信任和遵守严格法规至关重要。保护敏感信息可确保合乎道德的人工智能使用并防止有害的数据泄露。 为什么在人工智能开发中优先考虑数据隐私至关重要 人工智能的迅猛发展开启了一个前所未有的技术进步时代&#xff0c;彻底改变了各行各业&…

Python创建MySQL数据库

一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…

全新UI自助图文打印系统小程序源码 PHP后端 附教程

最新自助图文打印系统和证件照云打印小程序源码PHP后端&#xff0c;为用户用户自助打印的服务&#xff0c;包括但不限于文档、图片、表格等多种格式的文件。此外&#xff0c;它们还提供了诸如美颜、换装、文档打印等功能&#xff0c;以及后台管理系统&#xff0c;方便管理员对打…

SpringBoot之内容协商

现象演示 假设有一个需求是根据终端的不同&#xff0c;返回不同形式的数据&#xff0c;比如 PC 端需要以 HTML 格式返回数据&#xff0c;APP、小程序端需要以 JSON 格式返回数据。这时我们是 coding 几个相似的接口&#xff1f;还是在一个接口里面做复杂判断处理&#xff1f;两…

步进电机改伺服电机

步进电机&#xff1a; 42&#xff1a;轴径5mm 57&#xff1a;轴径8mm 86&#xff1a;轴径14mm 【86CME120闭环】// 12牛米 伺服电机&#xff1a; 40&#xff1a; 60&#xff1a; 80&#xff1a; 86&#xff1a; ECMA——C 1 0910 R S 4.25A 轴径…

树状数组实现 查找逆序对

题意&#xff1a; 输入一个整数n。 接下来输入一行n个整数 。 1< < n ,且每个数字只会出现一次 题解&#xff1a; 按每个数字的大小存入树状数组 #include<bits/stdc.h> using namespace std; #define ll long long const int N10000; int arr[N]; ll a[N];…

Ros2中goal_handle状态SUCCEED及ACCEPTED在rclpy中的死循环

动作通信开发中&#xff0c;我使用rclpy编写代码&#xff0c;进行feedback等操作&#xff0c;前期实现的较为顺利&#xff0c;但所有逻辑均编写完后&#xff0c;却无法将goal_handle提交为succeed状态&#xff0c;以下是我的部分代码&#xff1a; self.server ActionServer(se…

利用Redis bitmap 实现签到案例

数据库实现 设计签到功能对应的数据库表 CREATE TABLE sign_record (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键,user_id bigint NOT NULL COMMENT 用户id,year year NOT NULL COMMENT 签到年份,month tinyint NOT NULL COMMENT 签到月份,date date NOT NULL COMMENT 签…

GDP播放器 驱动视频播放器 PHP 系统源码 v4.4.3

最重要的是我们自己开发了源代码&#xff0c;因此无论您在使用此工具时遇到什么问题&#xff0c;我们都会快速解决。这个版本演示 分别支持PHP7.4/8.1/8.2三个版本 演示地址

8、Python中的字符串:字符串的基本操作及再论对象是否可变

引言 基于Python系列前面的几篇文章中&#xff0c;应该已经在脑海中对Python中的核心理念&#xff0c;有了一些认知&#xff0c;由于比较关键&#xff0c;这里再来回顾一下&#xff1a; 1、Python中一切皆对象2、对象分为可变对象和不可变对象3、区分重新赋值操作&#xff0c…

Dos(命令符窗口)命令

目录 1. 常用Windows组合键 2. 常用DOS命令 3. 复制操作 4. 当前路径 5. 查看电脑ip地址 6. 切换盘符: 7. 目录 8. 自动补齐 8. 进入某路径&#xff1a;cd 路径 9. 直接进入某个位置 10. 新建文件 11. 查看文件内容 12. 关机 13. 强行终止命令的执行&#xff1a;C…

java基于ssm+vue 旅游信息资源平台

1前台首页功能模块 旅游资源网站 &#xff0c;在系统首页可以查看首页、景点信息、酒店信息、客房信息、交流论坛、红色文化、个人中心、后台管理、客服等内容&#xff0c;如图1所示。 图1系统功能界面图 用户登录、用户注册&#xff0c;在注册页面可以填写用户名、密码、姓名…

如何第一次从零上传项目到GitLab

嗨&#xff0c;我是兰若&#xff0c;今天想给大家说下&#xff0c;如何上传一个完整的项目到与LDAP集成的GitLab&#xff0c;也就是说这个项目之前是不在git上面的&#xff0c;这是第一次上传&#xff0c;这样上传上去之后&#xff0c;其他小伙伴就可以根据你这个项目的git地址…

Maven 分模块设计与开发 继承

介绍 在 Maven 中进行分模块设计&#xff08;multi-module project&#xff09;&#xff0c;可以帮助将一个大型项目分解为更小、更易管理的模块。这种设计方式有助于提高项目的可维护性、复用性和团队协作效率。 继承关系 目录结构 引入父Maven 父坐标 在子项目中引入父亲…

什么是 DDoS 攻击及如何防护DDOS攻击

自进入互联网时代&#xff0c;网络安全问题就一直困扰着用户&#xff0c;尤其是DDOS攻击&#xff0c;一直威胁着用户的业务安全。而高防IP被广泛用于增强网络防护能力。今天我们就来了解下关于DDOS攻击&#xff0c;以及可以防护DDOS攻击的高防IP该如何正确选择使用。 一、什么是…

Windows Server 2016 搭建 网络负载平衡 服务

网络负载平衡功能的安装 添加角色 默认不动————功能 勾选上 < 网络负载平衡 > 在工具中————打开 < 网络负载平衡管理器 > 网络负载平衡群集创建 注意 : 提前 将两台 web 站点服务器 都安装好 < 网络负载平衡功能 > 右键 选择 ————新建群集 ——…

【ONLYOFFICE8.1】ONLYOFFICE8.1版本桌面编辑器测评

有宝子说office太贵&#xff0c;不适合个人和学生&#xff0c;而WPS不仅贵广告还多&#xff0c;那么有没有一款软件可以替代office和WPS呢&#xff1f;...当然有喽。当当当当&#xff01;它就是众望所归、备受好评的ONLYOFFICE。下面就和小编一起来探索和测评一下ONLYOFFICE8.1…

Apache Flink架构介绍

目录 一、Apache Flink架构组件栈 1.1 概述 1.2 架构图 1.3 架构分层组件说明 1.3.1 物理部署层 1.3.2 Runtime 核心层 1.3.3 API & Libraries层 二、Flink运行时架构 2.1 概述 2.2 架构图 2.3 架构角色和组件 2.3.1 Flink Clients客户端 2.3.2 JobManager 2.…

[SAP ABAP] 函数Function

Function函数与子例程类似&#xff0c;按照功能将代码模块化 我们可以使用事务码SE37查看需要使用的函数以及对该函数进行测试 我们也可以对STRING_SPLIT_AT_POSITION函数进行测试 1.函数调用 我们可以使用事务码SE38进入ABAP编辑器界面&#xff0c;使用"模式/Pattern&q…