CSDN博客

img lwjghhh

抓屏的技巧

发表于2004/10/22 16:25:00  734人阅读

这里有一些抓屏的技巧汇总,是本人平时编程积累下来的。在这里写出来,希望对大家有用。其实其技巧也不难,只要知道几个API函数,再加一些设备描述表的操作,你几乎可以做出非常好的抓屏软件。废话少说,现在开始介绍吧:

一,抓取全屏:
这个几乎可以说是抓屏中最简单的一个了,相信很多人都会,但为了讲述完整,这里也列举出来。思想很简单,取得屏幕的设备描述表,赋值给一个Canvas的句柄,这时该Canvas就相当于有了屏幕的画布了。再将这个画布复制给一个位图对象即可,代码如下:

procedure GetDesktopBim(FScreen:TBitmap);
var
    FCanvas:TCanvas;
    dc:HDC;
begin
     FCanvas:=TCanvas.Create();
     try
       Fscreen.Width := screen.width;
       Fscreen.Height := screen.Height;
//取得屏幕设备描述表,0指屏幕
       dc:=GetDC(0);
//将屏幕设备描述表赋给画布的句柄,此时画布就代表整个屏幕了
       FCanvas.Handle:=dc;
//把整个屏幕复制到BITMAP中,之后就可以将画布对象和设备描述表释放,
       Fscreen.Canvas.CopyRect(Rect (0, 0, screen.Width, screen.Height),
                                fCanvas,
                                Rect (0, 0, Screen.Width, Screen.Height));
     finally
       FCanvas.Free;
       ReleaseDC (0, dc);
     end;
end;

二,局部抓屏:
有时候并不需要抓取整个屏幕,只需要其中一部分,那么应该怎么做到呢。仔细看看那些抓屏软件,当抓取局部屏幕时,你看你的屏幕全部静止了,连QQ好友来信息,头像也不动了应该想到了吧,其实它是先将整个屏幕抓下来,放在真正的屏幕上面,让你在这个抓下来的屏幕上面操作。

一般来说,抓局部的屏幕有几种类型,这里只说明三种:

第一种是矩形,这个当然是最简单的啦,因一整个静止的位图都摆在你的面前了,你只处理鼠标的点下,移动,弹起消息,整个过程就像我们做一个小画图程序画一个矩形一样。最后将这个区域的位图拷贝到你抓屏窗口就行了。代码有些凌乱,这里就不列出来了。应该也不是很难吧。

第二种情况是画椭圆,在屏幕画布画出一个椭圆,然后将这个椭圆拷贝到抓屏窗口上。但问题是如何拷贝椭圆形的图呢。其实这里它拷贝的还是一个矩形,但拷到抓屏窗口上时,作了一些改变以下是关键代码,是我以前作的程序中的一些代码,这里不好作出一般性的代码,所以只好将以前的代码拉下来,应该可以看得懂的:
{这是实现位图蒙板的代码,先在抓屏窗体中画布全画为白,白色为0,而用屏幕位图窗体画的椭圆形为大小,给抓屏窗体的画布画一个黑色的椭圆,黑色为1。之后调用API函数BitBlt将屏幕位图窗体中选取的椭圆外框(矩形)全部复制给抓屏窗体,但其复制模式为SRCPAINT,即椭圆外框的位图与抓屏窗体画布进行and运算,结果椭圆外框的位图只有在抓屏窗体中黑色区域即椭圆部分的图像得到显示,而其他部分都被与掉了,所以看到的就只有椭圆部分位图,而其余的以白色代替了。这就是椭圆抓屏的实现技术}
      Form1.ScrImage.Canvas.Pen.Color:=clWhite;
      Form1.ScrImage.Canvas.Brush.Style:=bsSolid;
      Form1.ScrImage.Canvas.Brush.Color:=clWhite;
      Form1.ScrImage.Canvas.Rectangle(0,0,width,Height);
      Form1.ScrImage.Canvas.Pen.Color:=clBlack;
      Form1.ScrImage.Canvas.Brush.Color:=clBlack;
      Form1.ScrImage.Canvas.Ellipse(0,0,width,Height);
      image1.Canvas.Ellipse(orgPoint.X,orgPoint.Y,X,Y);
      BitBlt (Form1.ScrImage.Canvas.Handle, 0, 0,width ,Height,
      Image1.Canvas.Handle, orgPoint.X, orgPoint.Y, SRCPAINT);

第三种是任意形状的抓屏,其实所谓的任意形状并非真的是任意的。它是一个多边形,只不过它的边很多所以你看起来,就像是任意的一样。当你的鼠标在屏幕位图窗体上画线时,边些线的点就组成了一个多边形,然后要计算出这个多边形的外框,即与这个多边形相切的矩形。接着再用上面讲到的技术就可以实现一个任意形状的抓屏了。有了上面椭圆的讲解,我想,任意形的大概也能自己做出来了吧。其实是由于代码有些乱,不好放上来。
等一下我会做一个代码简单,但却很有意思的抓屏例子。请接着往下看吧。

三。当前工作窗口的抓屏:
当你想抓取当前正激活的窗口,你会怎么做呢,你可以按Ctrl+PrintScreenSysRp.即可以抓下这个口了。但我们要用程序来实现,怎么做呢,其实非常简单,就是获得这个活动窗口的句柄,再根据这个句柄到该窗口的设备描述表,这样就可以画出这个窗口了。那么要获得当前工作的窗口是要用到什么函数呢,主要是用到这样一个API:GetForegroundWindow(),它返回当前正在工作的窗口的句柄。好了,现在给出代码吧:
procedure TForm1.GetActiveWndImg(b:TBitmap);
var C:TCanvas; H:HDC; R:TRect; hand:THandle;
begin
   C:=TCanvas.Create;
   Hand:= GetForegroundWindow();
   if hand=0 then exit;
   H:=GetWindowDC(Hand);//取得这个窗口的句柄
   try
    GetWindowRect(hand,R);//取得这个窗口的大小,将其赋给位图对象
    B.Width:=R.Right-R.Left;
    B.Height:=R.Bottom-R.Top;
    C.Handle:=H;
    B.Canvas.CopyRect(Rect(0,0,B.Width,B.Height),C
    ,Rect(0,0,B.Width,B.Height));
   finally
    C.Free;
    ReleaseDC(Hand, H);
   end;
end;

上面已经讲解了抓屏的几种方式,只是一个引玉的作用,虽然没有详细的代码,我想思路应该是有了吧,再加上一本帮助你应该可以做出很不错的抓屏软件。

----------------------------------------------------
作为最后,我想出一个更有意思的抓屏方式,就是当你的鼠标指针指向屏幕的某一个地方,再按设定好的热键。就可以抓到鼠标指向的窗口(这个窗口也包括控件如按钮等)。这真的是不错,现实也并不是很难。主要有两个问题,这里一一作答吧,找到相应的API就行了:
一,热键问题,用到的API是RegisterHotKey和UnRegisterHotKey。这里不打算详细解说,可以自己看API帮助,当热键被按下时,会触发WM_HOTKEY消息,我们就在这个消息处理函数中抓鼠标位置的窗口位图。
二。光标位置的窗口,先用GetCurSorPos取得光标的位置,再用WindowFromPoint取得该位置的窗口句柄。

有了句柄,真是什么都好办呀。
以下是程序代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls;

type

  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
      hotkey:Integer;   
    procedure HotKeyDown(var Msg: Tmessage); message WM_HOTKEY;
    procedure GetActiveWndImg;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.GetActiveWndImg;
var C:TCanvas; b:TBitmap; H:HDC; R:TRect; hand:THandle;
   p:TPoint;
begin
   B:=TBitmap.Create;
   C:=TCanvas.Create;
   GetCurSorPos(P);
   Hand:= WindowFromPoint(P);
   if hand=0 then exit;
   H:=GetWindowDC(Hand);
   try
    GetWindowRect(hand,R);
    B.Width:=R.Right-R.Left;
    B.Height:=R.Bottom-R.Top;
    C.Handle:=H;
    B.Canvas.CopyRect(Rect(0,0,B.Width,B.Height),C
    ,Rect(0,0,B.Width,B.Height));
    Image1.Picture.Bitmap.Assign(B);
   finally
    C.Free;
    B.Free;
    ReleaseDC(Hand, H);
   end;
end;

procedure TForm1.HotKeyDown(var Msg: Tmessage);
begin
   if (Msg.LParamHi = VK_SPACE)and (Msg.LParamLo=MOD_CONTROL) then
       GetActiveWndImg;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   hotkey:=0;
  if not RegisterHotKey(Handle,hotkey,MOD_CONTROL ,VK_Space) then
    showmessage('can not register the hotkey');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   UnRegisterHotKey(handle, HotKey);
end;

end.

上面没有什么解释,真是抱歉,但如果看了上面的文字,我想也不难看得懂吧。把你的光标放在任何一个窗口上,按Ctrl+Space,看是不是把这个窗口抓下来了呢如果你将光标指在一个窗口内部的控件上,再按Ctrl+Space,这时候抓到的就是这个控件了。是不是很有意思呢。

其实,有了句柄,真的是好办,可以做好多的事情。

阅读全文
0 0

相关文章推荐

img
取 消
img