使用SetClassLongPtr改变窗口背景
Change window background using SetClassLongPtr
我有一个下拉菜单,我想用它来改变我的窗口的背景;窗口默认设置为"Winter background"。
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消息下工作。下面的代码做了以下事情:
- 从exe文件的资源部分加载位图。它需要一个HINSTANCE,在你的windowproc中,你可以使用GetWindowLongPtr(使用这个代替GetWindowLong,特别是当你为64位环境编码时,参见https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongw中微软对此的说明)。
- 创建一个新的画笔,使用相同的功能:'CreatePatternBrush'。
- 使用此笔刷更改窗口背景并存储返回的旧笔刷,以便您可以随后删除它。你可以使用SetClassLongPtr(同样的64位注意事项适用于这里)来做到这一点。令人困惑的部分可能是最后一个参数,它是一个LONG_PTR。这可能看起来像一个指向阅读器的指针,但实际上它是一个__int64(64位整数)。
- 删除旧的刷(以防止内存泄漏,特别是如果您希望在会话中多次执行此代码)。
- 通过使整个客户端区域(参数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;
小注释:上面代码中的最后一个'break'只是因为在我的windowproc的底部调用了DefWindowProc。当在你的windowproc中处理WM_KEYDOWN消息时,它应该总是传递给DefWindowProc,这样它就可以被Windows正确处理。在您的菜单情况下,最后的'break'语句可能会被'return 0'取代。
相关文章:
- 如何设置与其背景图像大小相对应的窗口大小?
- 如何为使用创建窗口创建的窗口创建自定义背景颜色
- 使用winapi使用按钮更改窗口的背景颜色
- 如何在QT中获取背景应用程序窗口标题
- 一个标签,其背景一方面是透明的,另一方面是上部窗口
- 无法更改另一个窗口内窗口的背景颜色
- 将鼠标和键盘输入传递到背景窗口而不会失去焦点
- 鼠标单击背景窗口,而无需移动鼠标C
- 在父窗口中更改背景颜色
- 窗口 - 锁定程序背景
- 背景过程没有窗口
- 打开不同的图像文件,并使用GDI 库在主应用程序窗口的背景上绘制它们
- 在 MFC 窗口中使用 PNG 作为背景图像
- C++(LINUX)使用DevIL设置X11窗口背景
- OpenFrameworks中的透明背景窗口
- (2.3.1)将背景纹理的比例设置为渲染窗口大小
- 无法更改窗口背景
- 窗口背景,如窗口 7 的标题栏
- C++ Win32 窗口背景不重绘
- 好奇心:背景C++窗口.SFML/SDL类型和Qt(GUI)类型之间的差异