我想在C#中获取当前窗口句柄数和系统范围的窗口句柄限制.我该怎么做?
如果您阅读Raymond Chen的帖子,您可能会觉得它像我一样烦人.你只是"可能做错了",因为你正在做一些Windows无法做到的事情.
在我的应用程序中,当用户第一次访问标签页时,我创建并布置该页面上的所有控件.这需要相当长的时间 - 页面上很容易有50个控件.因此,在填充之后我不会丢弃标签页上的控件(如果可能的话),并将关闭的标签页集留给用户.
碰巧,有些用户从不想关闭任何标签页集.我为什么要强迫他们去?通过我的用户界面,他们可以快速导航到他们负责管理的300多套交易中的任何一套.他们的机器足够快,并且有足够的内存,使这一切都非常敏感.唯一的问题是Windows无法支持它.
为什么我使用控件,而不是其他一些UI技术?因为他们工作.我需要支持焦点事件,标签顺序,验证事件,动态布局和数据绑定 - 用户实际上在内存数据集中管理数十个表中的数千条记录.我需要做的开发 - 比如 - 使用无窗口控件实现一些东西是天文数字.
我只是"做错了",因为Windows对它可以支持的窗口句柄数量有一个硬限制.这个硬限制是基于一系列关于如何构建计算机UI的十多年假设.不是我"做错了什么".
无论如何,我的解决方案分为两部分.
首先,一个类可以告诉您进程正在使用多少个窗口句柄:
using System; using System.Runtime.InteropServices; namespace StreamWrite.Proceedings.Client { public class HWndCounter { [DllImport("kernel32.dll")] private static extern IntPtr GetCurrentProcess(); [DllImport("user32.dll")] private static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags); private enum ResourceType { Gdi = 0, User = 1 } public static int GetWindowHandlesForCurrentProcess(IntPtr hWnd) { IntPtr processHandle = GetCurrentProcess(); uint gdiObjects = GetGuiResources(processHandle, (uint)ResourceType.Gdi); uint userObjects = GetGuiResources(processHandle, (uint)ResourceType.User); return Convert.ToInt32(gdiObjects + userObjects); } } }
其次,我维护了最近最少使用的标签页对象缓存..NET框架不提供通用的LRU缓存类,所以我构建了一个,如果需要,可以在这里获取.每次用户访问标签页时,我都会将其添加到LRU缓存中.然后我检查我是否在窗户把手上跑得很低.如果是的话,我会丢弃最近最少使用的标签页上的控件,并继续这样做,直到我再次有足够的窗口句柄.