mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-07 05:18:00 +02:00
lcl: introduce TScreen.DisableForms, TScreen.EnableForms,
lcl: Disabling/Enabling forms before/after showing of modal form win32: remove win32 specific methods of disabling/enabling windows. Use new TScreen methods instead win32: disable/enable forms before/after showing some system dialog (fixes bug #0012366, bug #0012382) git-svn-id: trunk@18629 -
This commit is contained in:
parent
26293e4375
commit
1d777bebeb
@ -851,6 +851,9 @@ type
|
||||
procedure RemoveHandlerActiveFormChanged(
|
||||
OnActiveFormChanged: TScreenActiveFormChangedEvent);
|
||||
procedure RemoveAllHandlersOfObject(AnObject: TObject); override;
|
||||
|
||||
function DisableForms(SkipForm: TCustomForm; DisabledList: TList = nil): TList;
|
||||
procedure EnableForms(var AFormList: TList);
|
||||
public
|
||||
property ActiveControl: TWinControl read FActiveControl;
|
||||
property ActiveCustomForm: TCustomForm read FActiveCustomForm;
|
||||
|
@ -90,7 +90,8 @@ begin
|
||||
end;
|
||||
|
||||
function TCommonDialog.DoExecute : boolean;
|
||||
var CanClose: boolean;
|
||||
var
|
||||
CanClose: boolean;
|
||||
begin
|
||||
FCanCloseCalled := False;
|
||||
if Assigned(FOnShow) then
|
||||
@ -119,5 +120,5 @@ end;
|
||||
|
||||
function TCommonDialog.DefaultTitle: string;
|
||||
begin
|
||||
result := '';
|
||||
Result := '';
|
||||
end;
|
||||
|
@ -2050,7 +2050,7 @@ function TCustomForm.ShowModal: Integer;
|
||||
end;
|
||||
|
||||
var
|
||||
//WindowList: Pointer;
|
||||
DisabledList: TList;
|
||||
SavedFocusState: TFocusState;
|
||||
//SaveCursor: TCursor;
|
||||
//SaveCount: Integer;
|
||||
@ -2079,6 +2079,7 @@ begin
|
||||
Screen.FFocusedForm := Self;
|
||||
Screen.MoveFormToFocusFront(Self);
|
||||
Screen.MoveFormToZFront(Self);
|
||||
DisabledList := Screen.DisableForms(Self);
|
||||
ModalResult := 0;
|
||||
|
||||
try
|
||||
@ -2120,6 +2121,7 @@ begin
|
||||
DestroyHandle;
|
||||
end;
|
||||
finally
|
||||
Screen.EnableForms(DisabledList);
|
||||
if Screen.FSaveFocusedList.Count > 0 then
|
||||
begin
|
||||
Screen.FFocusedForm := TCustomForm(Screen.FSaveFocusedList.First);
|
||||
|
@ -72,8 +72,9 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
function TScreen.CustomFormIndex(AForm: TCustomForm): integer;
|
||||
begin
|
||||
Result:=FCustomForms.Count-1;
|
||||
while (Result>=0) and (CustomForms[Result]<>AForm) do dec(Result);
|
||||
Result := FCustomForms.Count - 1;
|
||||
while (Result >= 0) and (CustomForms[Result] <> AForm) do
|
||||
Dec(Result);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -81,8 +82,9 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
function TScreen.FormIndex(AForm: TForm): integer;
|
||||
begin
|
||||
Result:=FFormList.Count-1;
|
||||
while (Result>=0) and (Forms[Result]<>AForm) do dec(Result);
|
||||
Result := FFormList.Count - 1;
|
||||
while (Result >= 0) and (Forms[Result] <> AForm) do
|
||||
Dec(Result);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -248,6 +250,56 @@ begin
|
||||
inherited RemoveAllHandlersOfObject(AnObject);
|
||||
end;
|
||||
|
||||
{
|
||||
Disable all forms except SkipForm. If DisabledList is available then add forms
|
||||
to that list and return it, otherwise return new list. Used to show forms and
|
||||
other dialogs modal
|
||||
}
|
||||
function TScreen.DisableForms(SkipForm: TCustomForm; DisabledList: TList = nil): TList;
|
||||
var
|
||||
i: integer;
|
||||
AForm: TCustomForm;
|
||||
begin
|
||||
Result := DisabledList;
|
||||
if Result = nil then
|
||||
Result := TList.Create;
|
||||
for i := 0 to CustomFormCount - 1 do
|
||||
begin
|
||||
AForm := CustomForms[i];
|
||||
if (AForm <> SkipForm) and AForm.HandleAllocated then
|
||||
begin
|
||||
// we cannot use AForm.Enabled := False; since it checks csDesigning
|
||||
// but we need this for IDE too. We also cannot check AForm.Visible -
|
||||
// it returns wrong info for the forms opened in the designer
|
||||
if IsWindowEnabled(AForm.Handle) and IsWindowVisible(AForm.Handle) then
|
||||
begin
|
||||
EnableWindow(AForm.Handle, False);
|
||||
Result.Add(AForm);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
Enable all forms from AFormList and destroy list. Used to restore state after
|
||||
DisableForms
|
||||
}
|
||||
procedure TScreen.EnableForms(var AFormList: TList);
|
||||
var
|
||||
i: integer;
|
||||
AForm: TCustomForm;
|
||||
begin
|
||||
if AFormList = nil then
|
||||
Exit;
|
||||
for i := AFormList.Count - 1 downto 0 do
|
||||
begin
|
||||
AForm := TCustomForm(AFormList[i]);
|
||||
if (CustomFormIndex(AForm) <> -1) and AForm.HandleAllocated then
|
||||
EnableWindow(AForm.Handle, True);
|
||||
end;
|
||||
FreeAndNil(AFormList);
|
||||
end;
|
||||
|
||||
function EnumFontsNoDups(
|
||||
var LogFont: TEnumLogFontEx;
|
||||
var Metric: TNewTextMetricEx;
|
||||
|
@ -184,6 +184,7 @@ type
|
||||
|
||||
var
|
||||
CurDoubleBuffer: TDoubleBuffer = (DC: 0; Bitmap: 0; BitmapWidth: 0; BitmapHeight: 0);
|
||||
DisabledForms: TList = nil;
|
||||
|
||||
function CheckMouseMovement: boolean;
|
||||
// returns true if mouse did not move between lmousebutton down
|
||||
@ -1569,12 +1570,12 @@ begin
|
||||
if WParam = 0 then
|
||||
begin
|
||||
RemoveStayOnTopFlags(Window);
|
||||
DisableApplicationWindows(Window);
|
||||
DisabledForms := Screen.DisableForms(nil, DisabledForms);
|
||||
end
|
||||
else
|
||||
begin
|
||||
RestoreStayOnTopFlags(Window);
|
||||
EnableApplicationWindows(Window);
|
||||
Screen.EnableForms(DisabledForms);
|
||||
end;
|
||||
|
||||
// disable child windows of for example groupboxes, but not of forms
|
||||
|
@ -46,7 +46,6 @@ Type
|
||||
PWinControl: TWinControl; // control to paint for
|
||||
AWinControl: TWinControl; // control associated with (for buddy controls)
|
||||
List: TStrings;
|
||||
DisabledWindowList: TList;// a list of windows that were disabled when showing modal
|
||||
StayOnTopList: TList; // a list of windows that were normalized when showing modal
|
||||
needParentPaint: boolean; // has a tabpage as parent, and is winxp themed
|
||||
isTabPage: boolean; // is window of tabpage
|
||||
@ -102,10 +101,7 @@ function GetDesigningBorderStyle(const AForm: TCustomForm): TFormBorderStyle;
|
||||
function AllocWindowInfo(Window: HWND): PWindowInfo;
|
||||
function DisposeWindowInfo(Window: HWND): boolean;
|
||||
function GetWindowInfo(Window: HWND): PWindowInfo;
|
||||
function DisableWindowsProc(Window: HWND; Data: LParam): LongBool; stdcall;
|
||||
|
||||
procedure DisableApplicationWindows(Window: HWND);
|
||||
procedure EnableApplicationWindows(Window: HWND);
|
||||
procedure RemoveStayOnTopFlags(Window: HWND);
|
||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
||||
|
||||
@ -1082,7 +1078,6 @@ begin
|
||||
Result := Windows.RemoveProp(Window, PChar(PtrUInt(WindowInfoAtom)))<>0;
|
||||
if Result then
|
||||
begin
|
||||
WindowInfo^.DisabledWindowList.Free;
|
||||
WindowInfo^.StayOnTopList.Free;
|
||||
Dispose(WindowInfo);
|
||||
end;
|
||||
@ -1095,80 +1090,6 @@ begin
|
||||
Result := @DefaultWindowInfo;
|
||||
end;
|
||||
|
||||
{-----------------------------------------------------------------------------
|
||||
function: DisableWindowsProc
|
||||
Params: Window - handle of toplevel windows to be disabled
|
||||
Data - handle of current window form
|
||||
Returns: Whether the enumeration should continue
|
||||
|
||||
Used in LM_SHOWMODAL to disable the windows of application thread
|
||||
except the current form.
|
||||
-----------------------------------------------------------------------------}
|
||||
function DisableWindowsProc(Window: HWND; Data: LParam): LongBool; stdcall;
|
||||
var
|
||||
Buffer: array[0..15] of Char;
|
||||
begin
|
||||
Result:=true;
|
||||
|
||||
// Don't disable the current window form
|
||||
if Window = PDisableWindowsInfo(Data)^.NewModalWindow then exit;
|
||||
|
||||
// Don't disable any ComboBox listboxes
|
||||
if (GetClassName(Window, @Buffer[0], sizeof(Buffer))<sizeof(Buffer))
|
||||
and (StrIComp(Buffer, 'ComboLBox')=0) then exit;
|
||||
|
||||
if not IsWindowVisible(Window) or not IsWindowEnabled(Window) then exit;
|
||||
|
||||
PDisableWindowsInfo(Data)^.DisabledWindowList.Add(Pointer(Window));
|
||||
EnableWindow(Window,False);
|
||||
|
||||
if (Application <> nil) and (Application.MainForm <> nil) and
|
||||
Application.MainForm.HandleAllocated and (Window = Application.MainForm.Handle)
|
||||
then
|
||||
// In our windowproc we ignore WM_NCACTIVATE for the main form,
|
||||
// if it is not disabled.
|
||||
// Now we disable the mainform, so send WM_NCACTIVATE message;
|
||||
// when we showed the modal form, the mainform was not yet disabled
|
||||
Windows.SendMessage(Window, WM_NCACTIVATE, 0, 0)
|
||||
end;
|
||||
|
||||
var
|
||||
InDisableApplicationWindows: boolean = false;
|
||||
|
||||
procedure DisableApplicationWindows(Window: HWND);
|
||||
var
|
||||
DisableWindowsInfo: PDisableWindowsInfo;
|
||||
WindowInfo: PWindowInfo;
|
||||
begin
|
||||
// prevent recursive calling when the AppHandle window is disabled
|
||||
If InDisableApplicationWindows then
|
||||
exit;
|
||||
InDisableApplicationWindows:=true;
|
||||
New(DisableWindowsInfo);
|
||||
DisableWindowsInfo^.NewModalWindow := Window;
|
||||
DisableWindowsInfo^.DisabledWindowList := TList.Create;
|
||||
WindowInfo := GetWindowInfo(DisableWindowsInfo^.NewModalWindow);
|
||||
WindowInfo^.DisabledWindowList := DisableWindowsInfo^.DisabledWindowList;
|
||||
EnumThreadWindows(GetWindowThreadProcessId(DisableWindowsInfo^.NewModalWindow, nil),
|
||||
@DisableWindowsProc, LPARAM(DisableWindowsInfo));
|
||||
Dispose(DisableWindowsInfo);
|
||||
InDisableApplicationWindows := false;
|
||||
end;
|
||||
|
||||
procedure EnableApplicationWindows(Window: HWND);
|
||||
var
|
||||
WindowInfo: PWindowInfo;
|
||||
I: integer;
|
||||
begin
|
||||
WindowInfo := GetWindowInfo(Window);
|
||||
if WindowInfo^.DisabledWindowList <> nil then
|
||||
begin
|
||||
for I := 0 to WindowInfo^.DisabledWindowList.Count - 1 do
|
||||
EnableWindow(HWND(WindowInfo^.DisabledWindowList.Items[I]), true);
|
||||
FreeAndNil(WindowInfo^.DisabledWindowList);
|
||||
end;
|
||||
end;
|
||||
|
||||
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||
var
|
||||
AStyle: DWord;
|
||||
|
@ -58,6 +58,7 @@ uses
|
||||
type
|
||||
TApplicationState = record
|
||||
FocusedWindow: HWND;
|
||||
DisabledWindows: TList;
|
||||
end;
|
||||
|
||||
TOpenFileDialogRec = record
|
||||
@ -139,10 +140,12 @@ implementation
|
||||
function SaveApplicationState: TApplicationState;
|
||||
begin
|
||||
Result.FocusedWindow := Windows.GetFocus;
|
||||
Result.DisabledWindows := Screen.DisableForms(nil);
|
||||
end;
|
||||
|
||||
procedure RestoreApplicationState(AState: TApplicationState);
|
||||
begin
|
||||
Screen.EnableForms(AState.DisabledWindows);
|
||||
Windows.SetFocus(AState.FocusedWindow);
|
||||
end;
|
||||
|
||||
|
@ -72,7 +72,6 @@ type
|
||||
|
||||
TWin32WSCustomForm = class(TWSCustomForm)
|
||||
published
|
||||
class procedure CloseModal(const ACustomForm: TCustomForm); override;
|
||||
class procedure SetAllowDropFiles(const AForm: TCustomForm; AValue: Boolean); override;
|
||||
class procedure SetBorderIcons(const AForm: TCustomForm;
|
||||
const ABorderIcons: TBorderIcons); override;
|
||||
@ -321,11 +320,6 @@ begin
|
||||
Result := Params.Window;
|
||||
end;
|
||||
|
||||
class procedure TWin32WSCustomForm.CloseModal(const ACustomForm: TCustomForm);
|
||||
begin
|
||||
EnableApplicationWindows(ACustomForm.Handle);
|
||||
end;
|
||||
|
||||
class procedure TWin32WSCustomForm.SetAllowDropFiles(const AForm: TCustomForm;
|
||||
AValue: Boolean);
|
||||
begin
|
||||
@ -425,7 +419,6 @@ end;
|
||||
|
||||
class procedure TWin32WSCustomForm.ShowModal(const ACustomForm: TCustomForm);
|
||||
begin
|
||||
DisableApplicationWindows(ACustomForm.Handle);
|
||||
ShowWindow(ACustomForm.Handle, SW_SHOW);
|
||||
BringWindowToTop(ACustomForm.Handle);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user