mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-04 18:20:34 +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(
|
procedure RemoveHandlerActiveFormChanged(
|
||||||
OnActiveFormChanged: TScreenActiveFormChangedEvent);
|
OnActiveFormChanged: TScreenActiveFormChangedEvent);
|
||||||
procedure RemoveAllHandlersOfObject(AnObject: TObject); override;
|
procedure RemoveAllHandlersOfObject(AnObject: TObject); override;
|
||||||
|
|
||||||
|
function DisableForms(SkipForm: TCustomForm; DisabledList: TList = nil): TList;
|
||||||
|
procedure EnableForms(var AFormList: TList);
|
||||||
public
|
public
|
||||||
property ActiveControl: TWinControl read FActiveControl;
|
property ActiveControl: TWinControl read FActiveControl;
|
||||||
property ActiveCustomForm: TCustomForm read FActiveCustomForm;
|
property ActiveCustomForm: TCustomForm read FActiveCustomForm;
|
||||||
|
@ -90,7 +90,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TCommonDialog.DoExecute : boolean;
|
function TCommonDialog.DoExecute : boolean;
|
||||||
var CanClose: boolean;
|
var
|
||||||
|
CanClose: boolean;
|
||||||
begin
|
begin
|
||||||
FCanCloseCalled := False;
|
FCanCloseCalled := False;
|
||||||
if Assigned(FOnShow) then
|
if Assigned(FOnShow) then
|
||||||
@ -119,5 +120,5 @@ end;
|
|||||||
|
|
||||||
function TCommonDialog.DefaultTitle: string;
|
function TCommonDialog.DefaultTitle: string;
|
||||||
begin
|
begin
|
||||||
result := '';
|
Result := '';
|
||||||
end;
|
end;
|
||||||
|
@ -2050,7 +2050,7 @@ function TCustomForm.ShowModal: Integer;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
//WindowList: Pointer;
|
DisabledList: TList;
|
||||||
SavedFocusState: TFocusState;
|
SavedFocusState: TFocusState;
|
||||||
//SaveCursor: TCursor;
|
//SaveCursor: TCursor;
|
||||||
//SaveCount: Integer;
|
//SaveCount: Integer;
|
||||||
@ -2079,6 +2079,7 @@ begin
|
|||||||
Screen.FFocusedForm := Self;
|
Screen.FFocusedForm := Self;
|
||||||
Screen.MoveFormToFocusFront(Self);
|
Screen.MoveFormToFocusFront(Self);
|
||||||
Screen.MoveFormToZFront(Self);
|
Screen.MoveFormToZFront(Self);
|
||||||
|
DisabledList := Screen.DisableForms(Self);
|
||||||
ModalResult := 0;
|
ModalResult := 0;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -2120,6 +2121,7 @@ begin
|
|||||||
DestroyHandle;
|
DestroyHandle;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
|
Screen.EnableForms(DisabledList);
|
||||||
if Screen.FSaveFocusedList.Count > 0 then
|
if Screen.FSaveFocusedList.Count > 0 then
|
||||||
begin
|
begin
|
||||||
Screen.FFocusedForm := TCustomForm(Screen.FSaveFocusedList.First);
|
Screen.FFocusedForm := TCustomForm(Screen.FSaveFocusedList.First);
|
||||||
|
@ -72,8 +72,9 @@ end;
|
|||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
function TScreen.CustomFormIndex(AForm: TCustomForm): integer;
|
function TScreen.CustomFormIndex(AForm: TCustomForm): integer;
|
||||||
begin
|
begin
|
||||||
Result:=FCustomForms.Count-1;
|
Result := FCustomForms.Count - 1;
|
||||||
while (Result>=0) and (CustomForms[Result]<>AForm) do dec(Result);
|
while (Result >= 0) and (CustomForms[Result] <> AForm) do
|
||||||
|
Dec(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -81,8 +82,9 @@ end;
|
|||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
function TScreen.FormIndex(AForm: TForm): integer;
|
function TScreen.FormIndex(AForm: TForm): integer;
|
||||||
begin
|
begin
|
||||||
Result:=FFormList.Count-1;
|
Result := FFormList.Count - 1;
|
||||||
while (Result>=0) and (Forms[Result]<>AForm) do dec(Result);
|
while (Result >= 0) and (Forms[Result] <> AForm) do
|
||||||
|
Dec(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -248,6 +250,56 @@ begin
|
|||||||
inherited RemoveAllHandlersOfObject(AnObject);
|
inherited RemoveAllHandlersOfObject(AnObject);
|
||||||
end;
|
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(
|
function EnumFontsNoDups(
|
||||||
var LogFont: TEnumLogFontEx;
|
var LogFont: TEnumLogFontEx;
|
||||||
var Metric: TNewTextMetricEx;
|
var Metric: TNewTextMetricEx;
|
||||||
|
@ -184,6 +184,7 @@ type
|
|||||||
|
|
||||||
var
|
var
|
||||||
CurDoubleBuffer: TDoubleBuffer = (DC: 0; Bitmap: 0; BitmapWidth: 0; BitmapHeight: 0);
|
CurDoubleBuffer: TDoubleBuffer = (DC: 0; Bitmap: 0; BitmapWidth: 0; BitmapHeight: 0);
|
||||||
|
DisabledForms: TList = nil;
|
||||||
|
|
||||||
function CheckMouseMovement: boolean;
|
function CheckMouseMovement: boolean;
|
||||||
// returns true if mouse did not move between lmousebutton down
|
// returns true if mouse did not move between lmousebutton down
|
||||||
@ -1569,12 +1570,12 @@ begin
|
|||||||
if WParam = 0 then
|
if WParam = 0 then
|
||||||
begin
|
begin
|
||||||
RemoveStayOnTopFlags(Window);
|
RemoveStayOnTopFlags(Window);
|
||||||
DisableApplicationWindows(Window);
|
DisabledForms := Screen.DisableForms(nil, DisabledForms);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
RestoreStayOnTopFlags(Window);
|
RestoreStayOnTopFlags(Window);
|
||||||
EnableApplicationWindows(Window);
|
Screen.EnableForms(DisabledForms);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// disable child windows of for example groupboxes, but not of forms
|
// disable child windows of for example groupboxes, but not of forms
|
||||||
|
@ -46,7 +46,6 @@ Type
|
|||||||
PWinControl: TWinControl; // control to paint for
|
PWinControl: TWinControl; // control to paint for
|
||||||
AWinControl: TWinControl; // control associated with (for buddy controls)
|
AWinControl: TWinControl; // control associated with (for buddy controls)
|
||||||
List: TStrings;
|
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
|
StayOnTopList: TList; // a list of windows that were normalized when showing modal
|
||||||
needParentPaint: boolean; // has a tabpage as parent, and is winxp themed
|
needParentPaint: boolean; // has a tabpage as parent, and is winxp themed
|
||||||
isTabPage: boolean; // is window of tabpage
|
isTabPage: boolean; // is window of tabpage
|
||||||
@ -102,10 +101,7 @@ function GetDesigningBorderStyle(const AForm: TCustomForm): TFormBorderStyle;
|
|||||||
function AllocWindowInfo(Window: HWND): PWindowInfo;
|
function AllocWindowInfo(Window: HWND): PWindowInfo;
|
||||||
function DisposeWindowInfo(Window: HWND): boolean;
|
function DisposeWindowInfo(Window: HWND): boolean;
|
||||||
function GetWindowInfo(Window: HWND): PWindowInfo;
|
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 RemoveStayOnTopFlags(Window: HWND);
|
||||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
procedure RestoreStayOnTopFlags(Window: HWND);
|
||||||
|
|
||||||
@ -1082,7 +1078,6 @@ begin
|
|||||||
Result := Windows.RemoveProp(Window, PChar(PtrUInt(WindowInfoAtom)))<>0;
|
Result := Windows.RemoveProp(Window, PChar(PtrUInt(WindowInfoAtom)))<>0;
|
||||||
if Result then
|
if Result then
|
||||||
begin
|
begin
|
||||||
WindowInfo^.DisabledWindowList.Free;
|
|
||||||
WindowInfo^.StayOnTopList.Free;
|
WindowInfo^.StayOnTopList.Free;
|
||||||
Dispose(WindowInfo);
|
Dispose(WindowInfo);
|
||||||
end;
|
end;
|
||||||
@ -1095,80 +1090,6 @@ begin
|
|||||||
Result := @DefaultWindowInfo;
|
Result := @DefaultWindowInfo;
|
||||||
end;
|
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;
|
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||||
var
|
var
|
||||||
AStyle: DWord;
|
AStyle: DWord;
|
||||||
|
@ -58,6 +58,7 @@ uses
|
|||||||
type
|
type
|
||||||
TApplicationState = record
|
TApplicationState = record
|
||||||
FocusedWindow: HWND;
|
FocusedWindow: HWND;
|
||||||
|
DisabledWindows: TList;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TOpenFileDialogRec = record
|
TOpenFileDialogRec = record
|
||||||
@ -139,10 +140,12 @@ implementation
|
|||||||
function SaveApplicationState: TApplicationState;
|
function SaveApplicationState: TApplicationState;
|
||||||
begin
|
begin
|
||||||
Result.FocusedWindow := Windows.GetFocus;
|
Result.FocusedWindow := Windows.GetFocus;
|
||||||
|
Result.DisabledWindows := Screen.DisableForms(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure RestoreApplicationState(AState: TApplicationState);
|
procedure RestoreApplicationState(AState: TApplicationState);
|
||||||
begin
|
begin
|
||||||
|
Screen.EnableForms(AState.DisabledWindows);
|
||||||
Windows.SetFocus(AState.FocusedWindow);
|
Windows.SetFocus(AState.FocusedWindow);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -72,7 +72,6 @@ type
|
|||||||
|
|
||||||
TWin32WSCustomForm = class(TWSCustomForm)
|
TWin32WSCustomForm = class(TWSCustomForm)
|
||||||
published
|
published
|
||||||
class procedure CloseModal(const ACustomForm: TCustomForm); override;
|
|
||||||
class procedure SetAllowDropFiles(const AForm: TCustomForm; AValue: Boolean); override;
|
class procedure SetAllowDropFiles(const AForm: TCustomForm; AValue: Boolean); override;
|
||||||
class procedure SetBorderIcons(const AForm: TCustomForm;
|
class procedure SetBorderIcons(const AForm: TCustomForm;
|
||||||
const ABorderIcons: TBorderIcons); override;
|
const ABorderIcons: TBorderIcons); override;
|
||||||
@ -321,11 +320,6 @@ begin
|
|||||||
Result := Params.Window;
|
Result := Params.Window;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TWin32WSCustomForm.CloseModal(const ACustomForm: TCustomForm);
|
|
||||||
begin
|
|
||||||
EnableApplicationWindows(ACustomForm.Handle);
|
|
||||||
end;
|
|
||||||
|
|
||||||
class procedure TWin32WSCustomForm.SetAllowDropFiles(const AForm: TCustomForm;
|
class procedure TWin32WSCustomForm.SetAllowDropFiles(const AForm: TCustomForm;
|
||||||
AValue: Boolean);
|
AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
@ -425,7 +419,6 @@ end;
|
|||||||
|
|
||||||
class procedure TWin32WSCustomForm.ShowModal(const ACustomForm: TCustomForm);
|
class procedure TWin32WSCustomForm.ShowModal(const ACustomForm: TCustomForm);
|
||||||
begin
|
begin
|
||||||
DisableApplicationWindows(ACustomForm.Handle);
|
|
||||||
ShowWindow(ACustomForm.Handle, SW_SHOW);
|
ShowWindow(ACustomForm.Handle, SW_SHOW);
|
||||||
BringWindowToTop(ACustomForm.Handle);
|
BringWindowToTop(ACustomForm.Handle);
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user