Delphi获取控件界面图像“新招”


众所周知,Delphi是一种可视化编程方式的软件,在某些Delphi软件中,常常需要获取一些界面控件的图像,如TImage、TPaintBox、TPanel等控件。获取这些界面控件图像时,一般都是采用直接截屏的办法,但直接截屏的办法有一个缺陷,就是当这些控件完全或者部分被遮挡后,并不能获取其完整界面的图像。对TImage的截屏更是受到限制,因为除了BMP类型图像(即TImage.Picture.Graphic是TBitmap),其它格式图像时根本没法获取其有效画布(Canvas)。

其实,在Delphi中采用截屏获取一些界面控件图像的办法,是一种惯性思维,是借用其它语言的办法,其它语言用截屏获取界面图像是不得已,如C/C++在编写Windows界面程序时,在响应绘制窗口消息时,往往都没有理会WM_PAINT消息的WPARAM参数(这个参数本应该是绘制窗口时所使用的设备上下文DC,但一般情况下是NULL,不能直接使用),而是使用BeginPaint或者GetDC等API获取窗口设备上下文DC后,来绘制界面的;而Delphi则不完全一样:除标准控件外,都是通过TWinControl和TGraphicControl,或者它们的派生类的WMPaint消息过程来绘制控件界面的,而WMPaint过程中Message.DC参数(也就是WM_PAINT消息的WPARAM参数)是有效的设备上下文DC(为什么这里的DC是有效的,本文就不详细解释了,可参阅VCL源码),这也就是说,除了标准控件外,只要我们有一个有效的设备上下文DC,就可以发送WM_PAINT消息给这些控件,让它们将“自己”完整的画在我们给定的设备上下文DC上!

Ok,既然Delphi界面控件有这种“得天独厚”的优势,我们为什么不利用起来,而非要去截屏呢。下面就是本文所说的获取控件界面图像“新招”代码:


type
TWControl = class(TWinControl) end;

function GetControlBitmap(Control: TControl): TBitmap; overload;
begin
Result := TBitmap.Create;
Result.PixelFormat := pf24Bit;
Result.Canvas.Brush.Color := TWControl(Control).Color;
Result.Width := Control.Width;
Result.Height := Control.Height;
if Control is TWinControl then
TWControl(Control).PaintWindow(Result.Canvas.Handle)
else
Control.Perform(WM_PAINT, Result.Canvas.Handle, 0);
end;

function GetControlBitmap(Control: TControl; Rect: TRect): TBitmap; overload;
var
Bitmap: TBitmap;
begin
if IsRectEmpty(Rect) then
begin
Result := nil;
Exit;
end;
Bitmap := GetControlBitmap(Control);
if (Rect.Right - Rect.Left <> Control.Width) or
(Rect.Bottom - Rect.Top <> Control.Height) then
begin
Result := TBitmap.Create;
Result.PixelFormat := pf24Bit;
Result.Width := Rect.Right - Rect.Left;
Result.Height := Rect.Bottom - Rect.Top;
Result.Canvas.CopyRect(Classes.Rect(0, 0, Result.Width, Result.Height),
Bitmap.Canvas, Rect);
Bitmap.Free;
end
else
Result := Bitmap;
end;

实现代码很简单,稍具Delphi基础就可读懂。有一点还是要说明一下,因为本文过程不能获取标准控件的界面图像,所以在获取容器类控件界面图像时,干脆舍弃了所有的子控件界面,获取的容器类控件界面图像只包括其自身。

当然,上面也说了,本办法也有局限性,即不能获取标准控件的界面图像,所以在某些需求下,使用截屏获取控件界面图像还是有必要的。

下面的例子代码获取TImage的部分界面图像(被注释的语句是获取TImage完整界面图像):


var
Bitmap: TBitmap;
begin
Bitmap := GetControlBitmap(Image1, Rect(50, 10, 250, 180));
// Bitmap := GetControlBitmap(Image1);
Canvas.Draw(0, 0, Bitmap);
Bitmap.Free;
end;

下面是例子运行界面截图:

截图

截图右面是TImage控件,其上边被遮挡了一部分(超出窗体);左边是获取的TImage部分界面图像,其中就包含了TImage上边被遮挡的部分图像。

指导和建议请来信:mao.maozefa@gmail.commaozefa@hotmail.com

后记:获取控件界面图像过程代码已于2009.11.25修改。


联系电话:
020-00000000
联系电话:
020-00000000
联系电话:
020-12345678