Question

I would like to know width and height of canvas but I know only its HDC.

I've tried with this code:

procedure TForm92.Button1Click(Sender: TObject);
var
  hBitmap: HGDIOBJ;
  Header: TBitmapInfoHeader;
begin
  hBitmap := GetCurrentObject(PaintBox1.Canvas.Handle, OBJ_BITMAP);
  GetObject(hBitmap, sizeof(TBitmapInfoHeader), @Header);
  ShowMessage(IntToStr(Header.biWidth));
end;

However it does not return me the dimensions of PaintBox1's Canvas, instead I am getting the dimensions of the form on which the PaintBox1 is placed.

What am I doing wrong?

Was it helpful?

Solution

Given only a handle to a device context, it's not generally possible to determine the dimensions of a TCanvas object associated with it. Descendants of TGraphicControl all share the DC of their parent control because only windowed controls can have device contexts, and TGraphicControl objects aren't windowed controls.

When a TGraphicControl descendant (including TPaintBox) needs a canvas, TControlCanvas calls back to the control's GetDeviceContext method. That method returns the DC handle of the parent control, but before returning, it modifies the DC a little:

Result := Parent.GetDeviceContext(WindowHandle);
SetViewportOrgEx(Result, Left, Top, nil);
IntersectClipRect(Result, 0, 0, Width, Height);

That is, it shifts the origin to match the upper left corner of the current control, and it updates the clipping region to exclude anything outside the current control's borders.

In some circumstances, you might be able to determine the canvas's dimensions by inspecting the DC's clipping region (with GetClipRgn), but that's only if the region hasn't been adjusted in any other ways. The clipping region might be smaller than the control's dimensions. (It will never be larger because of the call to IntersectClipRect shown above.)

As you can see, you need more than just the DC handle to get the information you want. Ideally, that will include a TControl reference; then you can just read its Height and Width properties to know the control's and the canvas's dimensions.

OTHER TIPS

The handle of a TCanvas points to a Windows device context (DC). Assuming a display device context (rather then a printer, memory, or information DC), then the logical size of that DC is equal to the (total) screen resolution, as obtainable by GetDeviceCaps or GetSystemMetrics. (Although you can paint beyond that dimensions, output will be cut).

The maximum visible part of a display device context is limited by its associated window size, which is obtainable by WindowFromDC and GetClientRect.

The current visible part may be limited by either the current framework (such as TPaintBox from the Delphi VCL which does not have a window handle and instead depends on the framework to translate the dimensions to the control's size within the parent's DC, which is obtainable by inspecting the control's dimensions) or by the current set clipping region, which is obtainable by GetClipRgn.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top