這裡有一些抓屏的技巧匯總,是本人平時編程積累下來的。在這裡寫出來,希望對大家有用。其實其技巧也不難,只要知道幾個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,這時候抓到的就是這個控件了。是不是很有意思呢。
其實,有了句柄,真的是好辦,可以做好多的事情。