DisableProcessWindowsGhosting

Днес ще ви запозная с една интересна функция – DisableProcessWindowsGhosting ще ви покажа и как да се използва от Delphi. Ето какво е предназначението и… нека имаме процес който по някаква причина не може да си обработва опашката от съобщения. Той не може да я обработва, но има Windows Manager-a по някаква причина съумява да извършва следните дейности – resize, close, minimize на прозорците. Което разбира се води до още по-голям хаос когато процеса най-сетне съумее да обработи заявката.

За да се спре това поведение е разработена следната функция: DisableProcessWindowsGhosting в user32.dll която до спирането на процеса изключва тази особенност. Функцията е от най-любимите ми – нито има параметри, нито има резултат. Дефиницията на C e:

VOID WINAPI DisableProcessWindowsGhosting(void);

За първи път се среща в Windows XP (NT 5.1 SP1) и Windows 2003 (NT 5.2). Ето и примерен код на Delphi:

procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'), 'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;

Понякога при използването на Delphi 7 под WinXP+ се получава странен проблем – ако се изведе модален прозорец със ShowModal и от този прозорец се изведе 2-ри модален (примерно с MessageDlg) се случва втория модален да се подпъхне между основния прозорец и първия модален. Което води до аматьорско поведение на приложението – решението е потребителя да натисне alt-tab и още веднъж alt-tab така, че приложението да изчертае наново всички прозорци коректно ИЛИ да се използва горния код.

Проблема възниква с приложения до Delphi7 и не може да се възпроизведе на Win2000 или WinNT поради бъг във VCL. Нямам представа дали вече проблема е отстранен в актуалните версии, носят се слухове че в Delphi 2006 проблема вече бил фиксиран на ниво VCL, но там проблемите са на малко идеологическо ниво. Според мен едва Delphi 2007 успява да стабилизира средата до някакво по-прилично ниво. Delphi 2005 и 2006 ще ги запомня с грандиозните сривания на самата среда и затова много разработчици останаха на старите и стабилни версии (5,6 и 7).

1 comments
Metalnib
Metalnib

Честа практика е при показването на прозореца(OnShow) да се напише BringToFront - този метод предпочитах и обикновенно върши работа.

Другия вариянт е да се сложи следния код на Application.OnIdle събитието

if Assigned(Screen.ActiveForm) then
begin
if (fsModal in Screen.ActiveForm.FormState) and
(Application.DialogHandle <= 0)) then
begin
Screen.ActiveForm.BringToFront;
end;
end;