ZouHuiDong 2022-12-03 06:52 采纳率: 0%
浏览 21

大量重绘窗口时,如何避免 Win32 控件闪烁?

我的一个 Win32 程序运行时需要大量重绘,但这样会导致它的 Win32 控件闪烁。

此外,我还通过在窗口过程函数中处理 WM_CTLCOLORSTATIC 消息,使我的控件背景透明了:

case WM_CTLCOLORSTATIC:
{
	HDC hdc = (HDC)wParam;
	SetBkMode(hdc, TRANSPARENT);
	SetTextColor(hdc, RGB(255, 0, 0));
	return (LRESULT)GetStockObject(NULL_BRUSH); // 控件背景透明
}

为了解决控件闪烁的问题,我已经尝试了在主窗口中启用 WS_CLIPCHILDREN 属性,但是它会导致我的控件背景不再透明。

请问怎样能在窗口大量重绘的情况下,使我的控件不闪烁,而且背景是透明的?

 

为了说明 WS_CLIPCHILDREN 属性会导致控件背景不再透明,以下附了一份代码。代码中创建了一个窗口和一个透明背景的 Static 控件,但是由于启用了 WS_CLIPCHILDREN 属性,控件背景变得不透明了。(这个代码用的是 main 函数,而不是 WinMain,需要控制台项目编译)

#include <windows.h>
#include <thread>

#define IDC_STATIC 100

//////////// 设置是否启用 WS_CLIPCHILDREN 样式
//////////// 启用时可以避免闪烁,但是控件背景不透明了
bool g_bEnableStyle = true;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HINSTANCE hInstance = GetModuleHandle(0);
	static HWND hStatic;

	switch (msg)
	{
	case WM_CREATE:
	{
		hStatic = CreateWindow(
			L"static",
			L"我是透明控件",
			WS_CHILD | WS_VISIBLE,
			20, 22, 100, 20,
			hwnd,
			(HMENU)IDC_STATIC,
			hInstance,
			NULL
		);

		hStatic = CreateWindow(
			L"button",
			L"BTN",
			WS_CHILD | WS_VISIBLE,
			220, 22, 100, 20,
			hwnd,
			(HMENU)IDC_STATIC,
			hInstance,
			NULL
		);

		break;
	}

	case WM_CTLCOLORSTATIC:
	{
		HDC hdc = (HDC)wParam;

		SetBkMode(hdc, TRANSPARENT);
		SetTextColor(hdc, RGB(255, 0, 0));

		return (LRESULT)GetStockObject(NULL_BRUSH);
	}

	case WM_CLOSE:
		DestroyWindow(hwnd);
		PostQuitMessage(NULL);
		exit(0);
		break;
	}

	return DefWindowProc(hwnd, msg, wParam, lParam);
}

void initwindow(int w, int h, int mode, LRESULT(_stdcall* WindowProcess)(HWND, UINT, WPARAM, LPARAM), LPCTSTR strWndTitle)
{
	// 窗口类
	WNDCLASSEX WndClassEx;
	MSG Msg;

	// 隐藏cmd
	if (mode == 0)
		ShowWindow(GetConsoleWindow(), SW_HIDE);

	// 填写结构体
	WndClassEx.cbSize = sizeof(WNDCLASSEX);
	WndClassEx.style = CS_VREDRAW | CS_HREDRAW;
	WndClassEx.lpfnWndProc = WindowProcess;
	WndClassEx.cbClsExtra = 0;
	WndClassEx.cbWndExtra = 0;
	WndClassEx.hInstance = GetModuleHandle(0);
	WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClassEx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	WndClassEx.lpszMenuName = NULL;
	WndClassEx.lpszClassName = strWndTitle;
	WndClassEx.hIconSm = NULL;

	// 注册窗口类
	RegisterClassEx(&WndClassEx);

	// 创建窗口
	HWND hWnd = CreateWindowEx(
		WS_EX_WINDOWEDGE,
		strWndTitle,
		strWndTitle,
		WS_OVERLAPPEDWINDOW | (g_bEnableStyle ? WS_CLIPCHILDREN : 0),
		200, 200, w, h,
		NULL,
		NULL,
		GetModuleHandle(0),
		NULL
	);

	// 显示窗口
	ShowWindow(hWnd, SW_SHOWNORMAL);

	// 更新窗口
	UpdateWindow(hWnd);

	clock_t time = clock();

	// 循环获得消息
	while (GetMessage(&Msg, NULL, NULL, NULL))
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);

		// 模拟大量重绘
		if (clock() - time >= 10)
		{
			InvalidateRect(hWnd, nullptr, true);
			time = clock();
		}
	}
}

int main()
{
	initwindow(640, 480, 0, WndProc, L"mywnd");
	return 0;
}
  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-12-03 10:11
    关注
    评论

报告相同问题?

问题事件

  • 创建了问题 12月3日

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大