Обработка неверного дескриптора окна
Приложение извлекает дескрипторы окна, используя процедуры Enum*.
Бывает, что в то время как приложение управляет дескриптором (получить имя класса, статистику окна...) перечисляемого / созданного окна, дескриптор больше не действителен. Дескрипторы окна управления кодом защищены с помощью блока try/catch, но дескриптор окна сохраняется и последовательно используется для управления представленным окном.
Как обрабатывать время жизни окна? Можно ли обнаружить недействительность ручки?
Я хотел бы избегать блоков try/catch каждый раз, когда приложение использует дескрипторы окна.
4 ответа
У меня уже есть настоящее решение... но я не знал об этом до сих пор!
Спасибо всем за то, что вы разъяснили время жизни дескриптора окна, но на самом деле существует метод определения времени жизни дескриптора окна: CbtProc.
В случае, если ловушка установлена в масштабе всей системы, можно уведомить определенные приложения (все зависит от реальной реализации ловушки CBT) об уничтожении окна, что указывает на то, что конкретный дескриптор не будет действительным после уведомления.
Из документации:
HCBT_DESTROYWND Определяет дескриптор окна, которое должно быть уничтожено.
Конечно, доступ к дескрипторам, использующим подпрограммы WINAPI, должен быть синхронизирован с системой уведомлений, что, по-видимому, не дает хорошей осуществимости (ловушка CBT фактически блокирует уничтожение окна, поскольку она синхронизируется с логикой приложения).
Оконные дескрипторы безопасны, только если используются из потока, который создал окно. Из любого другого потока все, что вы можете знать о дескрипторе окна, это то, что он действовал когда-то в прошлом. Прямо сейчас, это может или не может быть, и если это так, это может относиться к другому окну, чем предполагалось полностью.
Вы можете передать его IsWindow()
чтобы подтвердить это.
Есть несколько предостережений, однако оба будут применяться практически к любому подходу к этому:
Поток не должен использовать IsWindow для окна, которое он не создал, потому что окно может быть уничтожено после вызова этой функции. Кроме того, поскольку оконные ручки перерабатываются, ручка может даже указывать на другое окно.
Если вы делаете это с окном в одном из ваших внешних приложений, вы можете добавить 2-й уровень проверки с помощью Set/GetProp() с уникальным идентификатором некоторого вида.
Вы можете использовать GetWindowInfo
функция. Возвращает 0, если дескриптор недействителен.