Reputation: 937
I'm trying to align my child form after the main form "side by side", but have some difficulties
To reproduce the problem create new VCL application and add one button to the form:
procedure TForm1.Button1Click(Sender: TObject);
var
Form: TForm1;
begin
Application.CreateForm(TForm1, Form);
Form.BorderStyle := bsSingle;
Form.Left := Left + Width;
Form.Top := Top;
Form.Show;
end;
And result:
After using Winapi.DwmApi
:
DXR1 := 0;
DXL2 := 0;
if (Win32MajorVersion >= 6) and DwmCompositionEnabled then begin
DwmGetWindowAttribute(Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1));
Winapi.Windows.GetWindowRect(Handle, R2);
DXR1 := R2.Right - R1.Right;
DYT1 := R2.Top - R1.Top;
end;
FormJob.Left := Left + Width - DXR1;
FormJob.Top := Top - DYT1;
FormJob.Show;
if (Win32MajorVersion >= 6) and DwmCompositionEnabled then begin
DwmGetWindowAttribute(FormJob.Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1));
Winapi.Windows.GetWindowRect(FormJob.Handle, R2);
DXL2 := R1.Left - R2.Left;
DYT2 := R2.Top - R1.Top;
end;
FormJob.Left := FormJob.Left - DXL2;
FormJob.Top := FormJob.Top + DYT2;
And now this is completely aligned on both Windows 7 and Windows 10
But to do that I need to show the child form first. If I call DwmGetWindowAttribute
for child (and invisible) form before showing I get the same values as for GetWindowRect
.It is impossible to get this before showing?
Upvotes: 6
Views: 1863
Reputation: 937
Thanks to comment of Jonathan Potter now I have such code and it works:
var
R1, R2: TRect;
DXR1, DXL2, DYT1, DYT2: Integer;
bCloak: BOOL; // Can't use Boolean here
begin
Application.CreateForm(TFormJob, FormJob);
if (Win32MajorVersion >= 6) and DwmCompositionEnabled then begin
DXR1 := 0;
DXL2 := 0;
DYT1 := 0;
DYT2 := 0;
if (DwmGetWindowAttribute(Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1)) = S_OK) and
Winapi.Windows.GetWindowRect(Handle, R2) then begin
DXR1 := R2.Right - R1.Right; // Right width of the shadow for parent
DYT1 := R2.Top - R1.Top; // Top height of the shadow for parent
end;
bCloak := True; // Make form invisible
DwmSetWindowAttribute(FormJob.Handle, DWMWA_CLOAK, @bCloak, SizeOf(bCloak));
FormJob.Show; // Draw invisible form
if (DwmGetWindowAttribute(FormJob.Handle, DWMWA_EXTENDED_FRAME_BOUNDS, @R1, SizeOf(R1)) = S_OK) and
Winapi.Windows.GetWindowRect(FormJob.Handle, R2) then begin
DXL2 := R1.Left - R2.Left; // Left width of the shadow for child
DYT2 := R2.Top - R1.Top; // Top height of the shadow for child
end;
FormJob.Left := Left + Width - DXR1 - DXL2;
FormJob.Top := Top - DYT1 + DYT2;
bCloak := False; // Make form visible
DwmSetWindowAttribute(FormJob.Handle, DWMWA_CLOAK, @bCloak, SizeOf(bCloak));
end
else begin
FormJob.Left := Left + Width;
if FormJob.Left + FormJob.Width > Screen.DesktopRect.Right then
FormJob.Left := Screen.DesktopRect.Right - FormJob.Width;
FormJob.Top := Top;
FormJob.Show;
end;
Actually this code less readable and contain the same as original code, but this can help in the future when it is will be necessary to draw custom drawing form.
Upvotes: 9