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

git-svn-id: branches/fixes_2_0@60279 -
This commit is contained in:
mattias 2019-02-02 18:39:33 +00:00
parent 1ba8ad7485
commit 239b73fdac
2 changed files with 81 additions and 39 deletions

View File

@ -287,26 +287,6 @@ begin
TWin32WSWinControl.SetText(ComboBox, ComboBox.Items[Index]);
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.
// The original function was about 2400 lines.
@ -1471,8 +1451,7 @@ end;
procedure TWindowProcHelper.DoMsgEnable;
begin
if WParam <> 0 Then
LMessage.Msg := LM_SETEDITABLE;
LMessage.Msg := LM_ENABLE;
if Window = Win32WidgetSet.AppHandle then
if WParam = 0 then
begin
@ -1484,13 +1463,8 @@ begin
Screen.EnableForms(DisabledForms);
end;
// disable child windows of for example groupboxes, but not of forms
if Assigned(lWinControl) and not (lWinControl is TCustomForm) then
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
// When themes are not enabled, it is necessary to redraw the BitMap associated
// with the TCustomBitBtn so Windows will reflect the new UI appearence.
if not ThemeServices.ThemesEnabled and (lWinControl is TCustomBitBtn) then
DrawBitBtnImage(TCustomBitBtn(lWinControl), TCustomBitBtn(lWinControl).Caption);
end;

View File

@ -1212,23 +1212,91 @@ begin
end;
{------------------------------------------------------------------------------
Method: EnableWindow
Params: HWnd - handle to window
BEnable - whether to enable the window
Returns: If the window was previously disabled
Method: EnableWindow Response to bug #0033923
Params: HWnd - handle to window
BEnable - whether to enable the window
Returns: If the window was previously disabled.
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;
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
OldEnable: Boolean;
lWinControl: TWinControl;
IsForm: Boolean;
RequestedEnable: Boolean;
begin
OldEnable := IsWindowEnabled(HWnd);
if OldEnable <> BEnable then
Result := Boolean(Windows.EnableWindow(HWnd, BEnable))
lWinControl := GetWin32WindowInfo(HWnd)^.WinControl;
if not Assigned(lWinControl) then
Exit;
IsForm := lWinControl.InheritsFrom(TCustomForm);
if IsForm then
RequestedEnable := BEnable
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;
{------------------------------------------------------------------------------