Search code examples
windowswinapiwindowgdi

Windows: Limit on how many regions a Window can have?


First off all: with regions, I do not mean the region, for which that Window is for (Location on the planet), but rather the Window regions: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createrectrgn

The Operating System: Windows 10
Coding Environment: C \ Win32

To change the shape of a window in Windows, one can use the SetWindowRgn() function. As its second parameter, it takes a Window Region created - for example - with the CreateRectRgn from above and many more.

I am using this function to update the shape of a window up to 10 times per second.
After a few seconds of the program running the SetWindowRgn returns 0, which means that something went wrong.
My first idea was, that one of the paramter was invalid, but I keep track of their state (I check 1 line prior, if their state is valid): The Window Handle is never changed and as far as I know, will never be invalid, until as the window exists/is getting closed (which it doesn't/isn't, even after it returns 0).
The Region Handle is also not invalid, as I (1st) check if it is initialized (To combine a region with another one, the destination Region needs to exists), then (2nd) if it is NULL (which it isn't as well), and then (3rd) if it is a valid Handle (it also is). I Also use GetLastError(), to check, if an Error is set (It is not). The third parameter does not change the outcome.

I then thought, that maybe, even though the Windows Docs say:

In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.

That the Handles are not deleted, and unused handles are piling up in the memory: This is not the case (I checked with a threaded loop, that checks, wether the GetProcessHandleCount() changed or not)

Then I started timing the whole thing, to see, if there are some consistencies, some things, that allways happen before SetWindowRgn returns 0: The Time was not allways the same, but I added a variable to check how many times I use the SetWindowRgn() function: For that specific Window, I am calling this function allways exactly 4993 in Code, but I do have 2 other Windows from the same process, which all in all makes me call this Windows function 4995 times in code.
Imagining, that the CreateWindow functions call this function as well, it might be 4998 calls. After that many, SetWindowRgn() fails for that window. (I am not using it again for the other 2 windows).

The whole thing currently runs in one big thread. I am checking nearly every win32 call, to see if an error occoured (, but sometimes I wish, it would just crash instead :S ).

TL;DR: Windows let's me use SetWindowRgn() only about 5000 times

My Question now is: Is this true? Is there a limit on how often one can use that function? Might it be possible, that all the other regions are cluttered on the graphics device and won't be cleaned, resulting in a memory overflow? (Perhaps somehow flushing could help..) Did I just unravel an undocumented, hardcoded limit? What can I do, to still use SetWindowRgn()?

I appologize if some things may still be unclear and I will clarify, if you ask :), and also thank you for your time and answer!


Solution

  • As the comments under the question suggest correctly: The issue was a GDI resource leak. I noticed this after checking the details few in the task manager. As Barmark Shemirani commented: The SetWindowRgn() started to fail after exactly 10000 GDI Objects.
    Checking all the possible objects on the List was trivial to pinpoint the leak.

    The issue in the Code was: I forgot to delete 2 results of different CombineRgn() functions. Now, that I added 2 DeleteObject() funtion calls, everything works fine now.

    The Credits for pointing out the issue go to the commenters! :)