LCL: Win32: Fixed not every TGroupBox child follows parent's Enabled property. Issue #34763. Patch by BrunoK

git-svn-id: trunk@60224 -
This commit is contained in:
michl 2019-01-25 23:34:24 +00:00
parent eadf172288
commit 14ebc45053
2 changed files with 81 additions and 39 deletions

View File

@ -287,26 +287,6 @@ begin
TWin32WSWinControl.SetText(ComboBox, ComboBox.Items[Index]); TWin32WSWinControl.SetText(ComboBox, ComboBox.Items[Index]);
end; end;
procedure EnableChildWindows(WinControl: TWinControl; Enable: boolean);
var
i: integer;
ChildControl: TWinControl;
begin
for i := 0 to WinControl.ControlCount-1 do
begin
if WinControl.Controls[i] is TWinControl then
begin
ChildControl := TWinControl(WinControl.Controls[i]);
if not Enable or ChildControl.Enabled then
begin
EnableWindow(ChildControl.Handle, Enable and ChildControl.Enabled);
EnableChildWindows(ChildControl, Enable and ChildControl.Enabled); // Recursive call
end;
end;
end;
end;
// A helper class for WindowProc to make it easier to split code into smaller pieces. // A helper class for WindowProc to make it easier to split code into smaller pieces.
// The original function was about 2400 lines. // The original function was about 2400 lines.
@ -1471,8 +1451,7 @@ end;
procedure TWindowProcHelper.DoMsgEnable; procedure TWindowProcHelper.DoMsgEnable;
begin begin
if WParam <> 0 Then LMessage.Msg := LM_ENABLE;
LMessage.Msg := LM_SETEDITABLE;
if Window = Win32WidgetSet.AppHandle then if Window = Win32WidgetSet.AppHandle then
if WParam = 0 then if WParam = 0 then
begin begin
@ -1484,13 +1463,8 @@ begin
Screen.EnableForms(DisabledForms); Screen.EnableForms(DisabledForms);
end; end;
// disable child windows of for example groupboxes, but not of forms // When themes are not enabled, it is necessary to redraw the BitMap associated
if Assigned(lWinControl) and not (lWinControl is TCustomForm) then // with the TCustomBitBtn so Windows will reflect the new UI appearence.
EnableChildWindows(lWinControl, WParam<>0);
// ugly hack to give bitbtns a nice look
// When no theming active, the internal image needs to be
// recreated when the enabled state is changed
if not ThemeServices.ThemesEnabled and (lWinControl is TCustomBitBtn) then if not ThemeServices.ThemesEnabled and (lWinControl is TCustomBitBtn) then
DrawBitBtnImage(TCustomBitBtn(lWinControl), TCustomBitBtn(lWinControl).Caption); DrawBitBtnImage(TCustomBitBtn(lWinControl), TCustomBitBtn(lWinControl).Caption);
end; end;

View File

@ -1212,23 +1212,91 @@ begin
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
Method: EnableWindow Method: EnableWindow Response to bug #0033923
Params: HWnd - handle to window Params: HWnd - handle to window
BEnable - whether to enable the window BEnable - whether to enable the window
Returns: If the window was previously disabled Returns: If the window was previously disabled.
Enables or disables mouse and keyboard input to the specified window or Enables or disables mouse and keyboard input to the specified window or
control. control and updates the graphical appearance of the control
------------------------------------------------------------------------------
Note June 2018: ~bk
In normal lazarus behavior, Enable is called by
1° - TWinControl.InitializeWnd (wcfInitializing in TWinControl.FWinControlFlags)
2° - When property TWinControl.Enabled changes : TWinControl.CMENABLEDCHANGED
To satisfy W10 new behaviour, if the aHWND parameter effectively changes the
Enabled state of its window, except if it is a TCusomForm descendant,
all its direct children will be asked to update their UI state if needed and
recusively propagate down the Controls children tree.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TWin32WidgetSet.EnableWindow(HWnd: HWND; BEnable: Boolean): Boolean; function TWin32WidgetSet.EnableWindow(HWnd: HWND; BEnable: Boolean): Boolean;
procedure EnableChildren(AWinControl: TWinControl; Enable: Boolean);
var
i: Integer;
ChildControl: TControl;
ChildWinControl: TWinControl absolute ChildControl;
RequestedEnable: Boolean;
EnabledOld: Boolean;
EnabledNew: Boolean;
begin
for i := 0 to AWinControl.ControlCount - 1 do begin
ChildControl := AWinControl.Controls[i];
if ChildControl is TWinControl then begin
if not ChildWinControl.HandleAllocated then Continue;
RequestedEnable := ChildWinControl.Enabled and Enable;
EnabledOld := IsWindowEnabled(ChildWinControl.Handle);
Windows.EnableWindow(ChildWinControl.Handle, RequestedEnable);
EnabledNew := IsWindowEnabled(ChildWinControl.Handle);
if (EnabledOld = EnabledNew) or (ChildWinControl.ControlCount < 1)
or (EnabledNew <> RequestedEnable)
then
Continue;
EnableChildren(ChildWinControl, RequestedEnable);
end
else
ChildControl.Invalidate;
end;
end;
function GetParentEnabled(AWinControl: TWinControl): Boolean;
var
ParentHandle: HWND;
ParentControl: TWinControl;
begin
ParentControl := AWinControl.Parent;
Result := not Assigned(ParentControl) or ParentControl.InheritsFrom(TCustomForm);
if not Result then begin
ParentHandle := GetParent(HWND);
Result := ParentHandle = 0;
if not Result then
Result := IsWindowEnabled(ParentHandle);
end;
end;
var var
OldEnable: Boolean; lWinControl: TWinControl;
IsForm: Boolean;
RequestedEnable: Boolean;
begin begin
OldEnable := IsWindowEnabled(HWnd); lWinControl := GetWin32WindowInfo(HWnd)^.WinControl;
if OldEnable <> BEnable then if not Assigned(lWinControl) then
Result := Boolean(Windows.EnableWindow(HWnd, BEnable)) Exit;
IsForm := lWinControl.InheritsFrom(TCustomForm);
if IsForm then
RequestedEnable := BEnable
else else
Result := not OldEnable; RequestedEnable := BEnable and GetParentEnabled(lWinControl);
Result := Boolean(Windows.EnableWindow(HWnd, RequestedEnable));
if (wcfInitializing in TWinControlAccess(lWinControl).FWinControlFlags) or IsForm then
Exit;
// Result contains WS_DISABLED style. True means disabled
if (Result <> RequestedEnable) or (lWinControl.ControlCount < 1) then
Exit;
EnableChildren(lWinControl, RequestedEnable);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------