Windows: 限制一个 Window 可以拥有多少个区域?
Windows: Limit on how many regions a Window can have?
首先:对于区域,我不是指 Window 所在的区域(地球上的位置),而是 Window 区域:https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createrectrgn
操作系统:Windows10
编码环境:C\Win32
要更改 Windows 中 window 的形状,可以使用 SetWindowRgn() 函数。作为它的第二个参数,它需要一个 Window 创建的区域 - 例如 - 使用上面的 CreateRectRgn 等等。
我正在使用此函数每秒更新 window 的形状最多 10 次。
几秒钟后程序运行 SetWindowRgn returns 0,表示出错了。
我的第一个想法是,其中一个参数无效,但我会跟踪它们的状态(如果它们的状态有效,我会先检查一行):据我所知,Window 句柄从未改变, 将永远无效,直到 window exists/is 关闭(它不会关闭 t/isn,即使在 returns 0 之后)。
区域句柄也不是无效的,因为我(第 1 次)检查它是否已初始化(要将一个区域与另一个区域组合,目标区域需要存在),然后(第 2 次)如果它是 NULL(它不是好吧),然后(第三)如果它是一个有效的句柄(它也是)。我还使用 GetLastError() 来检查是否设置了错误(不是)。第三个参数不改变结果。
然后我想,也许,即使 Windows 文档说:
In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.
句柄未被删除,未使用的句柄堆积在内存中:不是这种情况(我用线程循环检查过,检查了 GetProcessHandleCount() 是否更改)
然后我开始对整个事情计时,看看是否有一些一致性,一些事情,总是在 SetWindowRgn returns 之前发生 0:时间并不总是相同,但我添加了一个变量来检查我使用 SetWindowRgn() 函数的次数:对于那个特定的 Window,我在代码中一直调用这个函数,正好是 4993,但我确实有 2来自同一进程的其他 Windows,总而言之,这让我在代码中调用了这个 Windows 函数 4995 次。
想象一下,CreateWindow 函数也调用此函数,可能调用 4998 次。在那么多之后,SetWindowRgn() 因 window 而失败。 (我不会再为其他 2 windows 使用它)。
整个事情目前在一个大线程中运行。我正在检查几乎每个 win32 调用,看看是否发生了错误(但有时我希望,它只会崩溃 :S )。
TL;DR: Windows 让我使用 SetWindowRgn() 大约 5000 次
我的问题现在是:这是真的吗?使用该功能的频率是否有限制?有没有可能,所有其他区域都在图形设备上杂乱无章,不会被清理,从而导致内存溢出? (也许以某种方式冲洗会有所帮助..)我是否刚刚解开了一个未记录的硬编码限制?我能做什么,仍然使用 SetWindowRgn()?
如果有些事情可能仍然不清楚,我深表歉意,如果你问我会澄清:),也感谢你的时间和回答!
正如问题下的评论所暗示的那样:问题是 GDI 资源泄漏。在任务管理器中检查了一些细节后,我注意到了这一点。正如 Barmark Shemirani 评论的那样: SetWindowRgn() 在恰好 10000 个 GDI 对象之后开始失败。
检查 List 上所有可能的对象对于查明泄漏是微不足道的。
代码中的问题是:我忘记删除不同 CombineRgn() 函数的 2 个结果。现在,我添加了 2 个 DeleteObject() 函数调用,现在一切正常。
指出问题的积分归评论者所有! :)
首先:对于区域,我不是指 Window 所在的区域(地球上的位置),而是 Window 区域:https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createrectrgn
操作系统:Windows10
编码环境:C\Win32
要更改 Windows 中 window 的形状,可以使用 SetWindowRgn() 函数。作为它的第二个参数,它需要一个 Window 创建的区域 - 例如 - 使用上面的 CreateRectRgn 等等。
我正在使用此函数每秒更新 window 的形状最多 10 次。
几秒钟后程序运行 SetWindowRgn returns 0,表示出错了。
我的第一个想法是,其中一个参数无效,但我会跟踪它们的状态(如果它们的状态有效,我会先检查一行):据我所知,Window 句柄从未改变, 将永远无效,直到 window exists/is 关闭(它不会关闭 t/isn,即使在 returns 0 之后)。
区域句柄也不是无效的,因为我(第 1 次)检查它是否已初始化(要将一个区域与另一个区域组合,目标区域需要存在),然后(第 2 次)如果它是 NULL(它不是好吧),然后(第三)如果它是一个有效的句柄(它也是)。我还使用 GetLastError() 来检查是否设置了错误(不是)。第三个参数不改变结果。
然后我想,也许,即使 Windows 文档说:
In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.
句柄未被删除,未使用的句柄堆积在内存中:不是这种情况(我用线程循环检查过,检查了 GetProcessHandleCount() 是否更改)
然后我开始对整个事情计时,看看是否有一些一致性,一些事情,总是在 SetWindowRgn returns 之前发生 0:时间并不总是相同,但我添加了一个变量来检查我使用 SetWindowRgn() 函数的次数:对于那个特定的 Window,我在代码中一直调用这个函数,正好是 4993,但我确实有 2来自同一进程的其他 Windows,总而言之,这让我在代码中调用了这个 Windows 函数 4995 次。
想象一下,CreateWindow 函数也调用此函数,可能调用 4998 次。在那么多之后,SetWindowRgn() 因 window 而失败。 (我不会再为其他 2 windows 使用它)。
整个事情目前在一个大线程中运行。我正在检查几乎每个 win32 调用,看看是否发生了错误(但有时我希望,它只会崩溃 :S )。
TL;DR: Windows 让我使用 SetWindowRgn() 大约 5000 次
我的问题现在是:这是真的吗?使用该功能的频率是否有限制?有没有可能,所有其他区域都在图形设备上杂乱无章,不会被清理,从而导致内存溢出? (也许以某种方式冲洗会有所帮助..)我是否刚刚解开了一个未记录的硬编码限制?我能做什么,仍然使用 SetWindowRgn()?
如果有些事情可能仍然不清楚,我深表歉意,如果你问我会澄清:),也感谢你的时间和回答!
正如问题下的评论所暗示的那样:问题是 GDI 资源泄漏。在任务管理器中检查了一些细节后,我注意到了这一点。正如 Barmark Shemirani 评论的那样: SetWindowRgn() 在恰好 10000 个 GDI 对象之后开始失败。
检查 List 上所有可能的对象对于查明泄漏是微不足道的。
代码中的问题是:我忘记删除不同 CombineRgn() 函数的 2 个结果。现在,我添加了 2 个 DeleteObject() 函数调用,现在一切正常。
指出问题的积分归评论者所有! :)