UpdateBounds (which only calls UpdateAnchor Rules)
procedure TWinControl.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
//...snip
UpdateBounds;
//...snip
end;
TOleControl Patch
I became aware of this problem when using a OLE control; it sends WM_WindowPosChanged and Delphi doesn't handle it correctly.
We have three choices:
don't call OleInPlaceObject.SetObjectRects. Dephi 5 didn't do it, and it worked fine
add a call to RequestAlign in Vcl.Controls.TWinControl.WMPosChanged
override WM_WindowPosChanged here in TOleControl, call inherited first, then do our own call to RequestAlign
The first option works; though i don't know the downside of not using SetObjectRects.
Reading the documentation, it seems that it is incorrect to use SetObjectsRects to perform resizing - but that didn't stop Imprise.
The TWebBrowser happens to send WM_WindowPosChanged, and it happens to screw us up.
The person who wrote this code didn't think that calling SetObjectRects would change the position, otherwise they wouldn't have still called SetBounds.
Perhaps the ideal fix is to do all the bounds setting first, then call SetObjectsRects.
The VCL fix workaround
I decided on limiting to fix to TOleControl, and leave everyone else broken if they happen to ever receive an WM_WindowPosChanged from Windows.
procedure TOleControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
LRect: TRect;
{$IFDEF WIN64}
Temp: TPoint;
{$ENDIF}
begin
if ((AWidth <> Width) and (Width > 0)) or ((AHeight <> Height) and (Height > 0)) then
begin
{$IFDEF WIN64}
Temp := Point(MulDiv(AWidth, 2540, Screen.PixelsPerInch), MulDiv(AHeight, 2540, Screen.PixelsPerInch));
if (FMiscStatus and OLEMISC_INVISIBLEATRUNTIME <> 0) or
((FOleObject.SetExtent(DVASPECT_CONTENT, @Temp) <> S_OK)) then
{$ELSE}
if (FMiscStatus and OLEMISC_INVISIBLEATRUNTIME <> 0) or
((FOleObject.SetExtent(DVASPECT_CONTENT, Point(
MulDiv(AWidth, 2540, Screen.PixelsPerInch),
MulDiv(AHeight, 2540, Screen.PixelsPerInch))) <> S_OK)) then
{$ENDIF}
begin
AWidth := Width;
AHeight := Height;
end;
{VCL bug workaround. The call to FOleInplaceObject.SetObjectRects
causes the control to send us back the WM_WINDOWPOSCHANGED message.
TWinControl does not properly handle aligning fixing during WM_WindowPosChanged
like it does for SetBounds.
SetBounds calls:
UpdateAnchorRules
UpdateExplicitBounds
RequestAlign
while WM_WindowPosChanged only calls:
UpdateBounds (which only calls UpdateAnchor Rules)
We have three choices:
- don't call OleInPlaceObject.SetObjectRects. Dephi 5 didn't do it, and it worked fine
- add a call to RequestAlign in Vcl.Controls.TWinControl.WMPosChanged
- override WM_WindowPosChanged here in TOleControl, call inherited first, then do our own call to RequestAlign
The first option works; though i don't know the downside of not using SetObjectRects.
Reading the documentation, it seems that it is incorrect to use SetObjectsRects to perform resizing.
The TWebBrowser *happens* to send WM_WindowPosChanged, and it *happens* to screw us up.
The person who wrote this code didn't think that calling SetObjectRects would change the position, otherwise they
wouldnt' have still called SetBounds.
Perhaps the ideal fix is to do all the bounds setting first, *then* call SetObjectsRects
}
{Removed. Call *after* inheirted SetBounds
if FOleInplaceObject <> nil then
begin
LRect := Rect(Left, Top, Left+AWidth, Top+AHeight);
FOleInplaceObject.SetObjectRects(LRect, LRect);
end;}
end;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
//moved from above. We need SetBounds to happen first. Delphi's WMWindowPosChanged does not handle resizing correctly
if FOleInplaceObject <> nil then
begin
LRect := Rect(Left, Top, Left+AWidth, Top+AHeight);
FOleInplaceObject.SetObjectRects(LRect, LRect);
end;
end;
The call to FOleInplaceObject.SetObjectRects causes the control to send us the
WM_WINDOWPOSCHANGED
message.TWinControl does not properly handle aligning fixing during
WM_WindowPosChanged
like it does for SetBounds.SetBounds calls:
while
WM_WindowPosChanged
only calls:TOleControl Patch
I became aware of this problem when using a OLE control; it sends
WM_WindowPosChanged
and Delphi doesn't handle it correctly.We have three choices:
The first option works; though i don't know the downside of not using SetObjectRects.
Reading the documentation, it seems that it is incorrect to use SetObjectsRects to perform resizing - but that didn't stop Imprise.
The TWebBrowser happens to send WM_WindowPosChanged, and it happens to screw us up.
The person who wrote this code didn't think that calling SetObjectRects would change the position, otherwise they wouldn't have still called SetBounds.
Perhaps the ideal fix is to do all the bounds setting first, then call SetObjectsRects.
The VCL fix workaround
I decided on limiting to fix to TOleControl, and leave everyone else broken if they happen to ever receive an
WM_WindowPosChanged
from Windows.