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

View File

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

View File

@ -49,6 +49,7 @@ type
private private
FCanvas: TCanvas; FCanvas: TCanvas;
FDC: HDC; FDC: HDC;
FDCControl: TWinControl;
FDCOrigin: TPoint; // DC origin on desktop FDCOrigin: TPoint; // DC origin on desktop
FFlags: TDesignerDCFlags; FFlags: TDesignerDCFlags;
FFormClientOrigin: TPoint; // Form client origin on desktop FFormClientOrigin: TPoint; // Form client origin on desktop
@ -63,7 +64,7 @@ type
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure SetDC(AForm: TCustomForm; aDC: HDC); procedure SetDC(AForm: TCustomForm; ADCControl: TWinControl; ADC: HDC);
procedure Clear; procedure Clear;
procedure Save; procedure Save;
procedure Restore; procedure Restore;
@ -71,11 +72,9 @@ type
property Canvas: TCanvas read FCanvas; property Canvas: TCanvas read FCanvas;
property DC: HDC read FDC; property DC: HDC read FDC;
property Form: TCustomForm read FForm; property Form: TCustomForm read FForm;
property FormOrigin: TPoint property FormOrigin: TPoint read GetFormOrigin;// DC origin relative to designer Form
read GetFormOrigin;// DC origin relative to designer Form
property DCOrigin: TPoint read GetDCOrigin; // DC origin on Desktop property DCOrigin: TPoint read GetDCOrigin; // DC origin on Desktop
property FormClientOrigin: TPoint property FormClientOrigin: TPoint read GetFormClientOrigin;// Form Client Origin on desktop
read GetFormClientOrigin;// Form Client Origin on desktop
property DCSize: TPoint read GetDCSize; property DCSize: TPoint read GetDCSize;
end; end;
@ -330,12 +329,13 @@ var
CurFormClientOrigin: TPoint; CurFormClientOrigin: TPoint;
CurFormOrigin: TPoint; CurFormOrigin: TPoint;
begin begin
if not (ddcDCOriginValid in FFlags) then begin if not (ddcDCOriginValid in FFlags) then
CurFormClientOrigin:=FormClientOrigin; begin
CurFormOrigin:=FormOrigin; CurFormClientOrigin := FormClientOrigin;
FDCOrigin.X:=CurFormOrigin.X-CurFormClientOrigin.X; CurFormOrigin := FormOrigin;
FDCOrigin.Y:=CurFormOrigin.Y-CurFormClientOrigin.Y; FDCOrigin.X := CurFormOrigin.X - CurFormClientOrigin.X;
Include(FFlags,ddcDCOriginValid); FDCOrigin.Y := CurFormOrigin.Y - CurFormClientOrigin.Y;
Include(FFlags, ddcDCOriginValid);
end; end;
Result:=FDCOrigin; Result:=FDCOrigin;
end; end;
@ -353,20 +353,41 @@ end;
function TDesignerDeviceContext.GetFormClientOrigin: TPoint; function TDesignerDeviceContext.GetFormClientOrigin: TPoint;
// returns the Form Client Origin on desktop // returns the Form Client Origin on desktop
begin begin
if not (ddcFormClientOriginValid in FFlags) then begin if not (ddcFormClientOriginValid in FFlags) then
FFormClientOrigin:=FForm.ClientOrigin; begin
Include(FFlags,ddcFormClientOriginValid); FFormClientOrigin := FForm.ClientOrigin;
Include(FFlags, ddcFormClientOriginValid);
end; end;
Result:=FFormClientOrigin; Result := FFormClientOrigin;
end; end;
function TDesignerDeviceContext.GetFormOrigin: TPoint; function TDesignerDeviceContext.GetFormOrigin: TPoint;
// returns the DC origin relative to the form client origin // 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 // For example: The DC of the client area of the form itself will return 0,0
var
AControlOrigin: TPoint;
begin begin
if not (ddcFormOriginValid in FFlags) then if not (ddcFormOriginValid in FFlags) then
begin 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); Include(FFlags, ddcFormOriginValid);
// DebugLn(['New origin: ', FFormOrigin.X, ':', FFormOrigin.Y]); // DebugLn(['New origin: ', FFormOrigin.X, ':', FFormOrigin.Y]);
end; end;
@ -385,11 +406,12 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TDesignerDeviceContext.SetDC(AForm: TCustomForm; aDC: HDC); procedure TDesignerDeviceContext.SetDC(AForm: TCustomForm; ADCControl: TWinControl; ADC: HDC);
begin begin
Clear; Clear;
FDC:=aDC; FDC := ADC;
FForm:=AForm; FDCControl := ADCControl;
FForm := AForm;
end; end;
procedure TDesignerDeviceContext.Clear; procedure TDesignerDeviceContext.Clear;