繁体   English   中英

使用SetClassLongPtr更改窗口背景

[英]Change window background using SetClassLongPtr

我有一个下拉菜单,用于更改窗口的背景。 该窗口默认为我的“冬季背景”。

wClass.hbrBackground = CreatePatternBrush(LoadBitmap(hInst, MAKEINTRESOURCE(WinterBG)));

每当在下拉菜单中选择一个项目时,它就会触发CBN_SELCHANGE,在这里我会抓住所选项目的长度和字符串。 我希望背景可以据此改变。

case WM_COMMAND:
    {
        switch(HIWORD(wParam))
        {
        case CBN_SELCHANGE:
            {
                ItemIndex = SendMessage((HWND)lParam, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
                int ItemLen = SendMessage((HWND)lParam, (UINT)CB_GETLBTEXTLEN, (WPARAM)0, (LPARAM)0);
                char* ListItem = (char*)malloc(ItemLen+1);
                (char)SendMessageA((HWND)lParam, (UINT)CB_GETLBTEXT, (WPARAM)ItemIndex, (LPARAM)ListItem);

                //////////////////////////////////////////////////////////////////////////////////////////////////
                // I am certain this can be optimized

                if ( ItemLen == 5 && ListItem[0] == 'S' ) // Spring
                {
                    MessageBox(NULL, L"Spring chosen", L"Confirmed", MB_ICONINFORMATION | MB_OK);
                    HBRUSH brush = CreatePatternBrush(LoadBitmap(wClass.hInstance, MAKEINTRESOURCE(SpringBG)));
                    SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG)brush);
                    InvalidateRect(hWnd, NULL, TRUE);
                    UpdateWindow(hWnd);
                }
.....

SetClassLongPtr无法正常工作。 更新窗口后(我阅读了InvalidateRect和UpdateWindow实现了该功能),没有任何变化-背景保留在我的“ WinterBG”上。

我是否正确使用SetClassLongPtr? 如果没有,我该如何更改背景?

我已经尝试了您要在一个简单的Win32项目中完成的工作,并设法使其工作。 为了使下面的代码正常工作,您需要确保两个位图都作为资源存在于VC ++项目中。 我在VC ++项目中定义了两个位图作为资源。 我没有像您一样使用任何菜单。 我正在处理WM_KEYDOWN消息,但是想法是一样的,这也应该在您的WM_COMMAND消息下起作用。 下面的代码执行以下操作:

  1. 从exe文件的资源部分加载位图。 为此,它需要一个HINSTANCE,可以在WndProc中使用GetWindowLongPtr(使用它而不是GetWindowLong来获得它,尤其是在为64位环境进行编码时,请参见https://docs.microsoft.com上有关此的Microsoft注释。 / en-us / windows / win32 / api / winuser / nf-winuser-getwindowlongw )。
  2. 使用与您使用的相同功能创建新画笔:“ CreatePatternBrush”。
  3. 使用此笔刷更改窗口的背景并存储返回的旧笔刷,以便以后可以将其删除。 您可以使用SetClassLongPtr来执行此操作(此处使用相同的64位注释)。 令人困惑的部分可能是最后一个参数,即LONG_PTR。 这似乎是指向读者的指针,但实际上它是__int64(64位整数)。
  4. 删除旧笔刷(以防止内存泄漏,尤其是当您希望在一个会话中多次执行此代码时)。
  5. 通过使整个工作区无效(参数NULL)并将repaint参数设置为TRUE来刷新窗口。

那应该做。 这是我的WndProc函数执行此操作的部分:

    case WM_KEYDOWN:
    switch (wParam)
    {
    case VK_F1:
        HINSTANCE hInst2 = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
        HBITMAP newBmp = LoadBitmapW(hInst2, MAKEINTRESOURCE(IDB_BITMAP2));
        HBRUSH newBrush = (HBRUSH)CreatePatternBrush(newBmp);
        HBRUSH oldBrush = (HBRUSH)SetClassLongPtr(hwnd, GCLP_HBRBACKGROUND, (LONG_PTR)newBrush);
        DeleteObject(oldBrush);
        InvalidateRect(hwnd, NULL, TRUE);
        break;
    }
    break;

小提示:上面代码中的最后一个“中断”只是因为在我的WndProc的底部调用了DefWindowProc。 在WndProc中处理WM_KEYDOWN消息时,应始终将其传递到DefWindowProc,以便Windows可以正确处理。 在您的菜单情况下,最后一个“ break”语句可能被“ return 0”代替。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM