我想知道画布的宽度和高度,但我只知道它的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的Canvas的尺寸,而是获取放置PaintBox1
的表单的尺寸。
我做错了什么?
答案 0 :(得分: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
引用;然后,您只需阅读其Height
和Width
属性即可了解控件的和画布的尺寸。
答案 1 :(得分:1)
TCanvas
的句柄指向Windows设备上下文(DC)。假设显示设备上下文(而不是打印机,内存或信息DC),则该DC的逻辑大小等于(总)屏幕分辨率,可由GetDeviceCaps
或GetSystemMetrics
获得。 (虽然你可以超出这个尺寸进行绘画,但会减少输出。)
显示设备上下文的最大可见部分受其相关窗口大小的限制,该大小可由WindowFromDC
和GetClientRect
获得。
当前可见部分可能受当前框架的限制(例如来自Delphi VCL的TPaintBox
,它没有窗口句柄,而是依赖于框架将维度转换为控件的大小。父级DC,可通过检查控件的尺寸获得)或当前设置的裁剪区域,可通过GetClipRgn
获得。