Как получить текущий счетчик окон и лимит дескриптора окна в .NET?

Я хочу получить текущее количество оконных ручек и ограничение ширины окна всей системы на С#. Как мне это сделать?

Ответ 1

Если вы прочитаете пост Раймонда Чена, вы, вероятно, найдете его таким же раздражающим, как я. Вы только "возможно, что-то не так", потому что вы делаете то, на что не способен Windows.

В моем приложении при первом посещении пользователем страницы вкладки я создаю и размещаю все элементы управления на этой странице. Это занимает заметное количество времени - на странице может легко быть 50 элементов управления. Поэтому я не отбрасываю элементы управления на закладке после ее заполнения, если это вообще возможно, и оставляю закрытие наборов страниц вкладок до пользователя.

Как это бывает, некоторые пользователи никогда не хотят закрывать какие-либо наборы страниц вкладок. Почему я должен их заставлять? С моим пользовательским интерфейсом они могут быстро перемещаться к любому из 300 + наборов транзакций, за которые они отвечают за управление. Их машины достаточно быстры, и у них достаточно памяти, чтобы сделать это очень отзывчивым. Единственная проблема заключается в том, что Windows не может ее поддерживать.

Почему я использую элементы управления, а не некоторые другие технологии пользовательского интерфейса? Потому что они работают. Мне нужно поддерживать фокусные события, порядок табуляции, события проверки, динамическую компоновку и привязку данных - пользователи фактически управляют тысячами записей в десятках таблиц в DataSet в памяти. Объем разработки, который я должен был бы сделать - скажем - реализовать что-то, используя элементы управления без окон, является астрономическим.

Я только "делаю это неправильно", потому что Windows имеет жесткое ограничение на количество оконных дескрипторов, которые он может поддерживать. Этот жесткий предел основан на куче десятилетних предположений о том, как можно создать пользовательский интерфейс компьютера. Это не я, кто "делает что-то неправильно".

Во всяком случае, мое решение в этом состоит из двух частей.

Сначала класс, который может рассказать вам, сколько окон обрабатывает ваш процесс:

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 framework не предоставляет общий класс кеша LRU, поэтому я создал один, который вы можете получить здесь, если вам это нужно. Каждый раз, когда пользователь посещает вкладку, я добавляю ее в LRU Cache. Затем я проверяю, не работает ли я на окнах. Если да, я отбрасываю элементы управления на странице с последними используемыми закладками и продолжаю делать это, пока у меня не будет достаточно оконных дескрипторов снова.

Ответ 2

Как сказал Raymond Chen некоторое время назад, если вы думаете о ограничениях на дескриптор окна, вы, вероятно, делаете что-то неправильно:)

В любом случае, я уверен, нет специального способа С# для этого, потому что он очень системный. Вы можете использовать те же функции, которые будут использоваться в приложении С++. Вызовите функции, используя P/Invoke. Чтобы узнать, как писать импорт, перейдите в pinvoke.net.

Изменить. Насколько я понимаю ваш вопрос, я полагаю, вы уже знаете, как это сделать в приложении Win32.