designer: fix painting (visible only on windows)

- use symmetric DC.Restore for all DC.Save calls
  - set control for designer DC since it is not always possible to retrieve control from DC (especially it is impossible on windows)
  - if GetDCOriginRelativeToWindow return False use another approach to retrieve this origin (using known DC control)
  - formatting

git-svn-id: trunk@19064 -
This commit is contained in:
paul 2009-03-22 16:00:04 +00:00
parent dcab697872
commit 0a20153a4d
3 changed files with 88 additions and 49 deletions

View File

@ -2157,46 +2157,51 @@ end;
procedure TControlSelection.DrawGrabbers(DC: TDesignerDeviceContext);
var
OldBrushColor:TColor;
g:TGrabIndex;
OldBrushColor: TColor;
g: TGrabIndex;
Diff: TPoint;
RestoreBrush: boolean;
procedure FillRect(RLeft,RTop,RRight,RBottom: integer);
procedure FillRect(RLeft, RTop, RRight, RBottom: integer);
begin
if not DC.RectVisible(RLeft,RTop,RRight,RBottom) then exit;
if not RestoreBrush then begin
if not DC.RectVisible(RLeft, RTop, RRight, RBottom) then Exit;
if not RestoreBrush then
begin
DC.Save;
with DC.Canvas do begin
OldBrushColor:=Brush.Color;
Brush.Color:=GrabberColor;
with DC.Canvas do
begin
OldBrushColor := Brush.Color;
Brush.Color := GrabberColor;
end;
RestoreBrush:=true;
RestoreBrush := True;
end;
DC.Canvas.FillRect(Rect(RLeft,RTop,RRight,RBottom));
DC.Canvas.FillRect(Rect(RLeft, RTop, RRight, RBottom));
//DC.Canvas.TextOut(RLeft,RTop,dbgs(ord(g)));
end;
begin
if (Count=0) or (FForm=nil) or LookupRootSelected
or OnlyInvisiblePersistentsSelected then exit;
if (Count=0) or (FForm=nil) or LookupRootSelected or
OnlyInvisiblePersistentsSelected then Exit;
Diff:=DC.FormOrigin;
Diff := DC.FormOrigin;
//debugln(['[DrawGrabbers] ',' DC=',Diff.X,',',Diff.Y,' Grabber1=',FGrabbers[0].Left,',',FGrabbers[0].Top]);
// debugln(['[DrawGrabbers] ',' DC=',Diff.X,',',Diff.Y,' Grabber1=',FGrabbers[0].Left,',',FGrabbers[0].Top]);
RestoreBrush:=false;
for g:=Low(TGrabIndex) to High(TGrabIndex) do
RestoreBrush := False;
for g := Low(TGrabIndex) to High(TGrabIndex) do
FillRect(
FGrabbers[g].Left-Diff.X
,FGrabbers[g].Top-Diff.Y
,FGrabbers[g].Left-Diff.X+FGrabbers[g].Width
,FGrabbers[g].Top-Diff.Y+FGrabbers[g].Height
);
Include(FStates,cssGrabbersPainted);
Include(FStates, cssGrabbersPainted);
if RestoreBrush then
begin
DC.Canvas.Brush.Color:=OldBrushColor;
DC.Restore;
end;
end;
procedure TControlSelection.DrawMarkerAt(DC: TDesignerDeviceContext;
@ -2208,11 +2213,12 @@ var
procedure FillRect(RLeft, RTop, RRight, RBottom: integer);
begin
if not DC.RectVisible(RLeft, RTop, RRight, RBottom) then exit;
if not RestoreBrush then begin
if not RestoreBrush then
begin
DC.Save;
OldBrushColor:=DC.Canvas.Brush.Color;
DC.Canvas.Brush.Color:=MarkerColor;
RestoreBrush:=true;
RestoreBrush := True;
end;
DC.Canvas.FillRect(Rect(RLeft,RTop,RRight,RBottom));
end;
@ -2225,7 +2231,10 @@ begin
FillRect(ALeft+AWidth-MarkerSize,ATop+AHeight-MarkerSize
,ALeft+AWidth,ATop+AHeight);
if RestoreBrush then
begin
DC.Canvas.Brush.Color:=OldBrushColor;
DC.Restore;
end;
end;
procedure TControlSelection.DrawMarkers(DC: TDesignerDeviceContext);
@ -2360,8 +2369,10 @@ var
DrawRubberLine(x1,y2,x2,y2);
DrawRubberLine(x1,y1,x1,y2);
DrawRubberLine(x2,y1,x2,y2);
if RestorePen then begin
if RestorePen then
begin
DC.Canvas.Pen.Color:=OldPenColor;
DC.Restore;
Include(FStates,cssRubberbandPainted);
end;
end;
@ -2997,7 +3008,11 @@ begin
end;
if RestorePen then
begin
DC.Canvas.Pen.Color:=OldPenColor;
DC.Restore;
end;
DC.Restore;
Include(FStates,cssGuideLinesPainted);
end;

View File

@ -1202,7 +1202,7 @@ begin
if TheMessage.DC <> 0 then begin
Include(FFlags,dfNeedPainting);
DDC.SetDC(Form, TheMessage.DC);
DDC.SetDC(Form, Sender as TWinControl, TheMessage.DC);
{$IFDEF VerboseDesignerDraw}
writeln('TDesigner.PaintControl D ',Sender.Name,':',Sender.ClassName,
' DC=',DbgS(DDC.DC,8),
@ -2570,6 +2570,7 @@ begin
if (ControlSelection.Count > 1) and IsSelected then
ControlSelection.DrawMarkerAt(aDDC,
ItemLeft, ItemTop, NonVisualCompWidth, NonVisualCompWidth);
aDDC.Restore;
end;
end;
end;
@ -2585,11 +2586,11 @@ begin
if (Form=nil) or (not Form.HandleAllocated) then exit;
//writeln('TDesigner.DrawDesignerItems B painting');
DesignerDC:=GetDesignerDC(Form.Handle);
DDC.SetDC(Form,DesignerDC);
DesignerDC := GetDesignerDC(Form.Handle);
DDC.SetDC(Form, Form, DesignerDC);
DoPaintDesignerItems;
DDC.Clear;
ReleaseDesignerDC(Form.Handle,DesignerDC);
ReleaseDesignerDC(Form.Handle, DesignerDC);
end;
procedure TDesigner.CheckFormBounds;
@ -2623,22 +2624,23 @@ end;
procedure TDesigner.DoPaintDesignerItems;
begin
// marker (multi selection markers)
if (ControlSelection.SelectionForm=Form)
and (ControlSelection.Count>1) then begin
if (ControlSelection.SelectionForm = Form) and (ControlSelection.Count > 1) then
begin
ControlSelection.DrawMarkers(DDC);
end;
// non visual component icons
DrawNonVisualComponents(DDC);
// guidelines and grabbers
if (ControlSelection.SelectionForm=Form) then begin
if (ControlSelection.SelectionForm=Form) then
begin
if EnvironmentOptions.ShowGuideLines then
ControlSelection.DrawGuideLines(DDC);
ControlSelection.DrawGrabbers(DDC);
end;
// rubberband
if ControlSelection.RubberBandActive
and ((ControlSelection.SelectionForm=Form)
or (ControlSelection.SelectionForm=nil)) then begin
if ControlSelection.RubberBandActive and
((ControlSelection.SelectionForm = Form) or (ControlSelection.SelectionForm = nil)) then
begin
ControlSelection.DrawRubberBand(DDC);
end;
end;

View File

@ -49,6 +49,7 @@ type
private
FCanvas: TCanvas;
FDC: HDC;
FDCControl: TWinControl;
FDCOrigin: TPoint; // DC origin on desktop
FFlags: TDesignerDCFlags;
FFormClientOrigin: TPoint; // Form client origin on desktop
@ -63,7 +64,7 @@ type
public
constructor Create;
destructor Destroy; override;
procedure SetDC(AForm: TCustomForm; aDC: HDC);
procedure SetDC(AForm: TCustomForm; ADCControl: TWinControl; ADC: HDC);
procedure Clear;
procedure Save;
procedure Restore;
@ -71,11 +72,9 @@ type
property Canvas: TCanvas read FCanvas;
property DC: HDC read FDC;
property Form: TCustomForm read FForm;
property FormOrigin: TPoint
read GetFormOrigin;// DC origin relative to designer Form
property FormOrigin: TPoint read GetFormOrigin;// DC origin relative to designer Form
property DCOrigin: TPoint read GetDCOrigin; // DC origin on Desktop
property FormClientOrigin: TPoint
read GetFormClientOrigin;// Form Client Origin on desktop
property FormClientOrigin: TPoint read GetFormClientOrigin;// Form Client Origin on desktop
property DCSize: TPoint read GetDCSize;
end;
@ -330,12 +329,13 @@ var
CurFormClientOrigin: TPoint;
CurFormOrigin: TPoint;
begin
if not (ddcDCOriginValid in FFlags) then begin
CurFormClientOrigin:=FormClientOrigin;
CurFormOrigin:=FormOrigin;
FDCOrigin.X:=CurFormOrigin.X-CurFormClientOrigin.X;
FDCOrigin.Y:=CurFormOrigin.Y-CurFormClientOrigin.Y;
Include(FFlags,ddcDCOriginValid);
if not (ddcDCOriginValid in FFlags) then
begin
CurFormClientOrigin := FormClientOrigin;
CurFormOrigin := FormOrigin;
FDCOrigin.X := CurFormOrigin.X - CurFormClientOrigin.X;
FDCOrigin.Y := CurFormOrigin.Y - CurFormClientOrigin.Y;
Include(FFlags, ddcDCOriginValid);
end;
Result:=FDCOrigin;
end;
@ -353,20 +353,41 @@ end;
function TDesignerDeviceContext.GetFormClientOrigin: TPoint;
// returns the Form Client Origin on desktop
begin
if not (ddcFormClientOriginValid in FFlags) then begin
FFormClientOrigin:=FForm.ClientOrigin;
Include(FFlags,ddcFormClientOriginValid);
if not (ddcFormClientOriginValid in FFlags) then
begin
FFormClientOrigin := FForm.ClientOrigin;
Include(FFlags, ddcFormClientOriginValid);
end;
Result:=FFormClientOrigin;
Result := FFormClientOrigin;
end;
function TDesignerDeviceContext.GetFormOrigin: TPoint;
// returns the DC origin relative to the form client origin
// For example: The DC of the client area of the form itself will return 0,0
var
AControlOrigin: TPoint;
begin
if not (ddcFormOriginValid in FFlags) then
begin
GetDCOriginRelativeToWindow(FDC, FForm.Handle, FFormOrigin);
if not GetDCOriginRelativeToWindow(FDC, FForm.Handle, FFormOrigin) then
begin
// For some reason we cannot retrieve DC origin. It can happen for exmample
// when DC is not controld DC but double buffer DC. Lets use another trick
if FDCControl <> nil then
begin
AControlOrigin := FDCControl.ClientToScreen(Point(0, 0));
FFormOrigin := FForm.ClientToScreen(Point(0, 0));
FFormOrigin.X := AControlOrigin.X - FFormOrigin.X;
FFormOrigin.Y := AControlOrigin.Y - FFormOrigin.Y;
end
else
FFormOrigin := Point(0, 0);
if GetWindowOrgEx(FDC, @AControlOrigin) <> 0 then
begin
Dec(FFormOrigin.X, AControlOrigin.X);
Dec(FFormOrigin.Y, AControlOrigin.Y);
end;
end;
Include(FFlags, ddcFormOriginValid);
// DebugLn(['New origin: ', FFormOrigin.X, ':', FFormOrigin.Y]);
end;
@ -385,11 +406,12 @@ begin
inherited Destroy;
end;
procedure TDesignerDeviceContext.SetDC(AForm: TCustomForm; aDC: HDC);
procedure TDesignerDeviceContext.SetDC(AForm: TCustomForm; ADCControl: TWinControl; ADC: HDC);
begin
Clear;
FDC:=aDC;
FForm:=AForm;
FDC := ADC;
FDCControl := ADCControl;
FForm := AForm;
end;
procedure TDesignerDeviceContext.Clear;