4

我想知道画布的宽度和高度,但我只知道它的 HDC。

我试过这段代码:

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;

然而,它并没有返回 PaintBox1 画布的尺寸,而是我得到了PaintBox1放置它的表单的尺寸。

我究竟做错了什么?

4

2 回答 2

3

给定设备上下文的句柄,通常无法确定TCanvas与其关联的对象的尺寸。所有的后代TGraphicControl都共享其父控件的 DC,因为只有窗口控件可以具有设备上下文,并且TGraphicControl对象不是窗口控件。

TGraphicControl后代(包括TPaintBox)需要画布时,TControlCanvas回调控件的GetDeviceContext方法。该方法返回父控件的 DC 句柄,但在返回之前,它稍微修改了 DC:

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

也就是说,它移动原点以匹配当前控件的左上角,并更新剪辑区域以排除当前控件边界之外的任何内容。

某些情况下,您可能能够通过检查 DC 的剪辑区域(带有GetClipRgn)来确定画布的尺寸,但这仅适用于未以任何其他方式调整该区域的情况。剪辑区域可能小于控件的尺寸。(由于上面显示的调用,它永远不会变大IntersectClipRect。)

如您所见,您需要的不仅仅是 DC 句柄来获取您想要的信息。理想情况下,这将包括TControl参考;然后你可以阅读它的HeightWidth属性来了解控件画布的尺寸。

于 2013-09-05T19:45:43.130 回答
1

a 的句柄TCanvas指向 Windows 设备上下文 (DC)。假设显示设备上下文(而不是打印机、内存或信息 DC),则该 DC 的逻辑大小等于(总)屏幕分辨率,可通过GetDeviceCaps或获得GetSystemMetrics。(尽管您可以在该尺寸之外进行绘画,但输出将被削减)。

显示设备上下文的最大可见部分受其关联的窗口大小限制,该窗口大小可通过WindowFromDC和获得GetClientRect

当前可见部分可能受到当前框架的限制(例如TPaintBox来自没有窗口句柄的 Delphi VCL,而是依赖于框架将尺寸转换为父 DC 中控件的大小,这可以通过检查获得控件的尺寸)或当前设置的剪辑区域,可通过GetClipRgn.

于 2013-09-06T04:54:23.560 回答