gpt4 book ai didi

c++ - 调整大小时在窗口中绘图留下未绘制的边框

转载 作者:搜寻专家 更新时间:2023-10-31 00:01:33 24 4
gpt4 key购买 nike

我遇到的问题似乎微不足道,但我找不到解决方法。这里是。我有一个带有一些图形的窗口。

为了简单起见,可以说这是一个实心的绿色矩形,它填充了窗口的整个客户区域。我希望重新绘制此矩形并在每次窗口更改其大小时填充整个窗口。我最初所做的就是这个。我从 WM_SIZE 处理程序发布了 WM_PAINT 消息。

它可以工作,但是如果我快速移动鼠标,我会在绿色矩形周围看到一些未绘制(paint)的(白色)区域(实际上只有一侧或两侧,靠近鼠标所在的位置)。我对问题的理解是,处理用户输入(鼠标)的系统线程比我的WM_PAINT消息处理程序更快。这意味着当我开始绘制更新的矩形时(它的大小取自WM_SIZE),鼠标实际上移动了一点,系统绘制了一个新的窗口框架,该窗口框架与我尝试用绿色填充的窗口框架有所不同。这将在调整尺寸时移动的边框旁边创建未填充区域。

当我停止调整大小时,绿色最终会填满整个窗口,但是在调整大小期间,靠近边框的地方会出现一些闪烁,这很烦人。为了解决该问题,我尝试了以下方法。

bool finishedPainting;
RECT windowRect;

case WM_PAINT :
// ..... painting here

finishedPainting = TRUE;
break;

case WM_SIZE :
// .... some actions

// posting WM_PAINT
InvalidateRect(hWnd, NULL, FALSE);
PostMessage(hWnd, WM_PAINT, 0, 0);
break;

case WM_SIZING :
// this supposedly should prevent the system from passing
// new window size to WM_SIZE
if (!finishedPainting) memcpy((void*)lParam, &windowRect, sizeof(windowRect));
else {
// remember current window size for later use
memcpy(&windowRect, (void*)lParam, sizeof(windowRect));
finishedPainting = FALSE;
}
return TRUE;

它不起作用。作为一个细微的变化,我也尝试过。
bool  finishedPainting;
POINT cursorPos;

case WM_PAINT :
// ..... painting here

finishedPainting = TRUE;
break;

case WM_SIZE :
if (!finishedPainting) SetCursorPos(cursorPos.x, cursorPos.y);
else {
finishedPainting = FALSE;
GetCursorPos(&cursorPos);

// .... some actions

InvalidateRect(hWnd, NULL, FALSE);
PostMessage(hWnd, WM_PAINT, 0, 0);
}
break;

这也不起作用。据我了解,解决问题的方法在于以某种方式放慢鼠标的速度,以便仅在绘画完成后才将鼠标移动到屏幕上的下一个位置(拖动窗口的角或侧面)。

任何想法如何实现这一目标?还是我看问题和解决方案的方式根本上有问题?

// ================================================ ====

更新资料

我做了一些实验,这是我发现的

1)调整大小时,消息顺序为WM_SIZING-WM_NCPAINT-WM_SIZE-WM_PAINT。这对我来说有点奇怪。我希望WM_SIZE能够跟随WM_SIZING而不会受到WM_NCPAINT的干扰

2)在每个消息处理程序中,我在调整大小时正在检查窗口的宽度(为简单起见,我仅更改宽度)。令人惊讶的是,在WM_SIZE中测得的宽度与WM_SIZING中的宽度不同,但与WM_NCPAINT和WM_PAINT中的相同。因此,这不是一个问题,只是一个奇怪的事实。

3)我得出的结论是,窗缘附近发生闪烁的主要原因有两个。第一个是WM_NCPAINT在WM_PAINT之前。想象一下,您正在拉伸(stretch)窗户。新框架将首先出现(WM_NCPAINT首先出现),然后WM_PAINT填充客户区。当新的框架已经出现在屏幕上,但是它是空的时,人眼会捕捉到这短暂的时间。即使您指定不希望在重画之前删除窗口背景,新添加的区域仍为空,您可以一秒钟看到它。当您捕获右窗口边缘并将其快速向右移动时,可以很好地说明这种闪烁的原因。闪烁效果的另一个原因不太明显,当您捕获左窗边缘并将其向左移动时,效果最好。在此移动过程中,您会在右侧边缘看到未填充的区域。据我了解,效果是由此引起的。当用户调整大小时,Windows执行以下操作:A)发送WM_NCPAINT绘制新框架,B)将旧客户区的内容复制到新的左上角(在我们的示例中,它移到了左端), C)它发送WM_PAINT来填充新的客户区。但是,在B阶段,由于某种原因Windows会在右侧边缘产生那些未填充的区域,尽管似乎不应该这样做,因为旧内容应保持原样,直到在WM_PAINT期间重新粉刷为止。

好的,问题仍然存在-如何在调整大小时消除这些假象。据我现在所知,使用标准技术和功能是不可能的,因为它们是Windows在调整大小时执行的步骤序列所引起的。交换WM_NCPAINT和WM_PAINT可能会有所帮助,但这似乎超出了我们的控制(除非有一种我不知道的简单方法)。

最佳答案

您不应该自己发布或发送WM_PAINT消息。而是使用:: InvalidateRect来使窗口的某些部分无效,并让Windows决定何时发送WM_PAINT消息。

关于c++ - 调整大小时在窗口中绘图留下未绘制的边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9786218/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com