1

Following code makes quite some troubles:

procedure TForm1.Button1Click(Sender: TObject);
var dc : HDC;
    meta : TMetafile;
    metaCanv : TMetafileCanvas;
    cr : TRect;
    sz : TSize;
begin
     dc := GetDC(0);
     SetWindowExtEx(dc, 4800, 1300, @sz);
     ShowMessage(Format('size %d, %d', [sz.cx, sz.cy]));

     meta := TMetafile.Create;

     meta.SetSize(4500, 1300);

     metaCanv := TMetafileCanvas.Create(meta, dc);
     try
        IntersectClipRect(metaCanv.Handle, 0, 0, 4600, 1300);

        cr := metaCanv.ClipRect;

        with cr do
             ShowMessage(Format('clip rect: %d, %d, %d, %d', [Top, Left, Bottom, Right]));

     finally
            metaCanv.Free;
            meta.Free;
     end;


     DeleteDC(dc);
end;

The problem is that the clipping rectangle is bound to the display resolution e.g. if your screen has 1920 pixels width the clipping rectangle is bound to this value.

Note it is NOT a problem to remove clipping at all and paint lines event to the complete bottom rect corner. The problem arises if a clipping region is set (e.g. to the complete metafile width/height as shown in the example) and then paint the line -> it is clipped to the screen width/height.

I know that I could use e.g. a printer dc as reference which will basically fix the problem but there are a few side effects (e.g. gdi+ drawing on metafiles with such dc's simply does not work).

Anyone knows how to "trick" the system such that this odd clipping behaviour is not there any more?

mrabat
  • 802
  • 7
  • 15
  • I cant't see the "odd clipping", works as desired, whats your intention for using the clipping? – bummi Mar 21 '13 at 10:50
  • what you can't see odd clipping? doesn't the showmessage show a different value than 4600, 1300? At least on my computer (and others) this code shows 3600, 1200 (which is my desktop width) and others just show values around 1920x1200 (Most common nowadays). – mrabat Mar 21 '13 at 12:43
  • 1
    I think the default cliprect is against the desktop size, as that is the visible part of your metafile not the drawable part. You might want to look into http://stackoverflow.com/questions/9739124/weirdness-with-setwindowext-and-setwindowextex-negative-height-upside-down to setup your metafile and see if that gives you a better cliprect. If not: it shouldn't matter as you can draw outside your cliprect. – Jeroen Wiert Pluimers Mar 21 '13 at 13:15
  • If you use IntersectClipRect then you say to the Win API to intersect the rect you give with the current (screen sized) clipping rectangle. If you want to avoid it, use setClipRgn instead of the one above. – The Bitman Apr 17 '18 at 15:06

1 Answers1

3

ClipRect being the only part in which you can draw is a false presumption.

The documentation on TCustomCanvas.ClipRect:

Use ClipRect to determine where the canvas needs painting.

This is easily verified by drawing beyond ClipRect and trying to show what has been drawn, for example as follows:

procedure TForm1.Button1Click(Sender: TObject);
var
  MetaFile: TMetafile;
  MetaCanvas: TMetafileCanvas;
begin
  MetaFile := TMetafile.Create;
  try
    MetaCanvas := TMetafileCanvas.Create(MetaFile, 0);
    try
      MetaFile.SetSize(4500, 1300);
      MetaCanvas.LineTo(4500, 1300);
    finally
      MetaCanvas.Free;
    end;
    Canvas.Draw(-4400, -1200, MetaFile);
  finally
    MetaFile.Free;
  end;
end;

enter image description here

NGLN
  • 43,011
  • 8
  • 105
  • 200
  • 2
    Thank you! you saved my day. I was completly unaware of the fact that the cliprect function does not return the actual setup clipping region but rather only the part which needs to be repainted - so it now completely makes sense that gdi assumes nothing needs to be painted behind the screen resolution. – mrabat Mar 21 '13 at 13:48