如何通过只知道它的Handle来确定Canvas尺寸?

时间:2013-09-05 17:22:48

标签: delphi winapi canvas handle dimensions

我想知道画布的宽度和高度,但我只知道它的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的表单的尺寸。

我做错了什么?

2 个答案:

答案 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引用;然后,您只需阅读其HeightWidth属性即可了解控件的画布的尺寸。

答案 1 :(得分:1)

TCanvas的句柄指向Windows设备上下文(DC)。假设显示设备上下文(而不是打印机,内存或信息DC),则该DC的逻辑大小等于(总)屏幕分辨率,可由GetDeviceCapsGetSystemMetrics获得。 (虽然你可以超出这个尺寸进行绘画,但会减少输出。)

显示设备上下文的最大可见部分受其相关窗口大小的限制,该大小可由WindowFromDCGetClientRect获得。

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