全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:7236
推到 Plurk!
推到 Facebook!

如何截取被看不见的视窗内容?

答題得分者是:wameng
dg822
一般會員


發表:14
回覆:38
積分:10
註冊:2004-12-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-01-20 17:28:46 IP:203.198.xxx.xxx 未訂閱
很简单,如下代码:
[code delphi]
procedure TForm1.Timer1Timer(Sender: TObject);
var HWND:THandle;
dc:HDC ;
rect:TRect ;

begin
Hide ;
HWND:=handle;
GetWindowRect(HWND,rect);
dc:=GetWindowDC(HWND);

try
BitBlt(Image1.Canvas.Handle,0,0,rect.Right-rect.Left,rect.Bottomrect.Top,dc,0,0,SRCCOPY );
Image1.Invalidate ;
finally
ReleaseDC(HWND,dc);
Timer1.Enabled :=false;
end;
end;
[/code]
结果,在Image1上显示的是原来Form1后面的图画。
如题,如果我想取看不见的视窗内容,应该怎么做?
編輯記錄
yckuo 重新編輯於 2007-12-25 13:01:45, 註解 套用程式碼高亮處理‧
yckuo 重新編輯於 2007-12-25 13:02:32, 註解 無‧
deity
尊榮會員


發表:90
回覆:876
積分:678
註冊:2003-05-09

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-01-21 10:57:44 IP:218.15.xxx.xxx 未訂閱
您好: 【發表】使用BitBlt進行某元件之畫面擷取並存檔或複製 http://delphi.ktop.com.tw/topic.php?topic_id=32388 【BCB】【轉貼】有關透明窗口的顯示  http://delphi.ktop.com.tw/topic.php?topic_id=26411 小弟没试过< > 参考看看< > ~~~静心养德~~~
jamests
初階會員


發表:0
回覆:43
積分:28
註冊:2005-01-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-01-21 15:31:06 IP:211.75.xxx.xxx 未訂閱
您好: 您想達到的目的似乎是抓取自己的Form底下的畫面. 所以先將自己Hide起來. 但這段Source的問題應該Handle是您的Form的. 所以不管怎麼抓都會是畫您自己Form的樣子. 也許應該改成抓取螢幕畫面才對吧? Form1.ClientToScreen與Form1.ScreenToClient可以將畫面座標與螢幕座標互轉. 取得Form1的螢幕座標位置後即可以ScreenShot抓下您的畫面. (當然自己的Form也要暫時Hide一下) 不知有沒幫助. 供參考.
dg822
一般會員


發表:14
回覆:38
積分:10
註冊:2004-12-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-01-21 17:51:39 IP:203.198.xxx.xxx 未訂閱
不,两位大大,请看一下标题:我是想知道如何截取隐藏了的视窗的内容。    代码里面的hide,只是将要截取的视窗(也就是form1.handle)隐藏,然后再截取,只是作示范作用而已。我真正的用途是想截取非本程式的的隐藏视窗内容。    从示范代码的结果是:视窗后面的内容,不过我想获得是视窗的内容! 该怎么做?
jamests
初階會員


發表:0
回覆:43
積分:28
註冊:2005-01-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-01-21 19:10:43 IP:211.75.xxx.xxx 未訂閱
抱歉誤會您的問題. 可以試試看Form1.GetFormImage 不過Hide時會少一些元件, 什麼原因就要問Borland了. 但很快的Show再抓取再Hide就沒問題. (比BitBlt抓到不是想要的. 或是配合Show/Hide做法要Delay一下還好一些些些...) 希望有所幫助.
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-01-21 20:21:16 IP:61.31.xxx.xxx 未訂閱
Delphi5 沒有GetFormImage方法。 不過可以仿效 DBCtrlGrid 作法。 利用 PaintTo(DC: HDC; X, Y: Integer)
dg822
一般會員


發表:14
回覆:38
積分:10
註冊:2004-12-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-01-21 22:44:34 IP:219.132.xxx.xxx 未訂閱
首先谢谢楼上大大的热心,可是我是想抓取其他程式的视窗影像, 如果真的由得我说show就show,hide就hide那该多好,可是控制权不在我,我不能主动干涉其他程式……… < >< >
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-01-21 22:58:23 IP:61.31.xxx.xxx 未訂閱
引言: 首先謝謝樓上大大的熱心,可是我是想抓取其他程式的視窗影像, 如果真的由得我說show就show,hide就hide那該多好,可是控制權不在我,我不能主動干涉其他程式……… < >< >
事實上,有些部分是共通的。 您可以利用 FindWindow 找到這個 Handle後。 將其設置SetForegroundWindow 在利用擷取螢幕畫面的方式。 或者傳送 WM_PAINT 訊息。 反之,若其他程式在隱藏狀態下 取得畫面是較為困難的
dg822
一般會員


發表:14
回覆:38
積分:10
註冊:2004-12-16

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-01-22 10:11:47 IP:203.198.xxx.xxx 未訂閱
反之,若其他程式在隱藏狀態下 取得畫面是較為困難的......
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-02-27 21:15:36 IP:125.225.xxx.xxx 未訂閱
SphereXP執行畫面 http://www.spheresite.com/screenshots.html
雖然畫面很好看但實際試用的時候就出問題了
將視窗拉到螢幕外面,這軟體就抓不到完整的畫面
http://img246.imageshack.us/img246/6739/68861905nr1.gif

發現了一個神奇的軟體TopDesk
官方網站http://www.otakusoftware.com/topdesk/
在試用的時候將視窗拉出螢幕外,軟體也能正確完整的視窗畫面抓出來
不僅如此連被其他程式所壓到的視窗也能抓出來
我用bcb的tdump去剖析topdesk.dll發現SetWindowsHook
或許又是API HOOK了

類似問題
http://delphi.ktop.com.tw/board.php?cid=30&fid=69&tid=79161
Kingron
中階會員


發表:1
回覆:51
積分:60
註冊:2005-09-14

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-03-03 04:42:31 IP:125.89.xxx.xxx 訂閱
这个问题的确不是普通的方式可以做到。

由于没有使用这个软件,也无法具体分析。

估计可以用这种方法:Hook目标窗口,给目标窗口发送WM_PAINT消息,处理绘画并存储。

另外用下面的代码可以抓被遮住窗口的内容,例如被Notepad窗口遮住的窗口的内容:
[code delphi]
const
WS_EX_LAYERED = $00080000;

var
DC: HDC;
FStyle: Longint;
FCanvas: TCanvas;
bmpScreen : TBitmap;
FHwnd: HWND;
R : TRect;

begin
FHwnd := FindWindow('Notepad', nil);
GetWindowRect(FHwnd, R);
FStyle := GetWindowLong(FHwnd, GWL_EXSTYLE);
FStyle := FStyle or WS_EX_LAYERED;
SetWindowLong(FHwnd, GWL_EXSTYLE, FStyle);
Sleep(500);
bmpScreen := TBitmap.Create;
bmpScreen.Width := R.Right - R.Left;
bmpScreen.Height := R.Bottom - R.Top;
bmpScreen.Canvas.Lock;
DC := GetDC(0);
with bmpScreen do
Bitblt(Canvas.Handle, 0, 0,
bmpScreen.Width, bmpScreen.Height,
DC, R.Left, R.Top, SRCCOPY);
ReleaseDC(0, DC);
bmpScreen.Canvas.UnLock;
Image1.Picture.Assign(bmpScreen);
FStyle := GetWindowLong(FHwnd, GWL_EXSTYLE);
FStyle := FStyle and (not WS_EX_LAYERED);
SetWindowLong(FHwnd, GWL_EXSTYLE, FStyle);
end;
[/code]


关注。



===================引 用 文 章===================

SphereXP執行畫面 http://www.spheresite.com/screenshots.html

雖然畫面很好看但實際試用的時候就出問題了

將視窗拉到螢幕外面,這軟體就抓不到完整的畫面

http://img246.imageshack.us/img246/6739/68861905nr1.gif



發現了一個神奇的軟體TopDesk

官方網站http://www.otakusoftware.com/topdesk/

在試用的時候將視窗拉出螢幕外,軟體也能正確完整的視窗畫面抓出來

不僅如此連被其他程式所壓到的視窗也能抓出來

我用bcb的tdump去剖析topdesk.dll發現SetWindowsHook

或許又是API HOOK了



類似問題

http://delphi.ktop.com.tw/board.php?cid=30&fid=69&tid=79161
------
超级猛料:http://kingron.delphibbs.com
編輯記錄
yckuo 重新編輯於 2007-12-25 12:54:58, 註解 套用程式碼高亮處理‧
yckuo 重新編輯於 2007-12-25 12:57:37, 註解 刪除程式碼那多餘換行‧
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-04-22 17:42:12 IP:125.224.xxx.xxx 未訂閱
後來我注意到一個軟體也有類似功能TaskSwitchXP
PChome介紹http://toget.pchome.com.tw/intro/utility_system/utility_system_Optimize/22902.html
官網執行畫面http://www.ntwind.com/software/taskswitchxp/screenshots.html
最重要的是有原始碼可以下載,經過一個月的研究終於發現windows XP以上的版本就有提供這個功能的API
原來TopDesk和TaskSwitchXP只能限定在XP以上的作業系統才能執行原因就是如此
範例執行檔下載http://delphi.ktop.com.tw/download.php?download=upload/462b2d3ecd83c_Project1.exe
執行後會自行開啟記事本而視窗位置在螢幕外,但按下抓圖按鈕後仍可抓到完整的視窗畫面

sunweb
一般會員


發表:11
回覆:9
積分:4
註冊:2006-07-06

發送簡訊給我
#13 引用回覆 回覆 發表時間:2007-10-26 12:59:03 IP:218.170.xxx.xxx 訂閱
不知道,xp是提供哪各api有這功能捏
大大可否告知呢?
找了很久就是找不到捏!謝謝...
===================引 用 bugmans 文 章===================
後來我注意到一個軟體也有類似功能TaskSwitchXP
PChome介紹http://toget.pchome.com.tw/intro/utility_system/utility_system_Optimize/22902.html
官網執行畫面http://www.ntwind.com/software/taskswitchxp/screenshots.html
最重要的是有原始碼可以下載,經過一個月的研究終於發現windows XP以上的版本就有提供這個功能的API
原來TopDesk和TaskSwitchXP只能限定在XP以上的作業系統才能執行原因就是如此
範例執行檔下載http://delphi.ktop.com.tw/download.php?download=upload/462b2d3ecd83c_Project1.exe
執行後會自行開啟記事本而視窗位置在螢幕外,但按下抓圖按鈕後仍可抓到完整的視窗畫面

bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#14 引用回覆 回覆 發表時間:2007-10-29 20:01:56 IP:125.224.xxx.xxx 未訂閱
你好,我是範例程式的作者
我當初花了很多時間讀TaskSwitchXP原始碼,也才逐漸了解其中的原理,所以才沒有提供原始碼
但答案很簡單就是一個WinXP以上才提供的API而已,提示在TaskSwitchXP原始碼的generic.cpp裡面
你可以用Visual Studio 2005逐步執行看看哪段程式是跟視窗畫面有關的,再到MSDN找各參數的意義
Kingron
中階會員


發表:1
回覆:51
積分:60
註冊:2005-09-14

發送簡訊給我
#15 引用回覆 回覆 發表時間:2007-10-29 23:08:27 IP:125.89.xxx.xxx 訂閱
------
超级猛料:http://kingron.delphibbs.com
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#16 引用回覆 回覆 發表時間:2007-10-30 05:32:55 IP:125.225.xxx.xxx 未訂閱
Kingron給了正確答案,那我也公佈範例的原始碼,就只是呼叫PrintWindow而已

[code vb]
VERSION 5.00
Begin VB.Form Form1
AutoRedraw = -1 'True
Caption = "Form1"
ClientHeight = 7515
ClientLeft = 1650
ClientTop = 1530
ClientWidth = 10605
LinkTopic = "Form1"
ScaleHeight = 7515
ScaleWidth = 10605
Begin VB.CommandButton Command1
Caption = "抓圖"
Height = 495
Left = 240
TabIndex = 0
Top = 6720
Width = 1095
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Function PrintWindow Lib "user32" (ByVal hwnd As Long, ByVal hdcBlt As Long, ByVal nFlags As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Private Const VER_PLATFORM_WIN32s = 0
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32_NT = 2
Dim mWnd As Long
Private Sub Command1_Click()
Dim info As OSVERSIONINFO
info.dwOSVersionInfoSize = Len(info)
GetVersionEx info
If (info.dwPlatformId = VER_PLATFORM_WIN32_NT And info.dwMajorVersion >= 5 And info.dwMinorVersion >= 1) Then
Me.Cls
PrintWindow mWnd, Me.hDC, 0
Me.Refresh
Else
MsgBox "要Windows XP以上的版本才支援"
End If
End Sub
Private Sub Form_Load()
Shell "notepad.exe", vbNormalNoFocus
mWnd = FindWindow("Notepad", vbNullString)
If mWnd = 0 Then MsgBox "失敗"
MoveWindow mWnd, -300, 200, 500, 200, 0
'Me.AutoRedraw = True
End Sub

[/code]
sunweb
一般會員


發表:11
回覆:9
積分:4
註冊:2006-07-06

發送簡訊給我
#17 引用回覆 回覆 發表時間:2007-11-21 10:50:10 IP:60.249.xxx.xxx 訂閱
謝謝...kingron及bugmans兩位大大的無私,小弟以測試成功啦!
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#18 引用回覆 回覆 發表時間:2007-11-25 08:12:36 IP:125.225.xxx.xxx 未訂閱
再補充PrintWindow的應用軟體WinFlip
http://winflip.stylekings.de/

bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#19 引用回覆 回覆 發表時間:2008-01-24 08:19:34 IP:125.225.xxx.xxx 未訂閱
http://forums.microsoft.com/msdn-cht/showpost.aspx?postid=2711456&siteid=14&mode=1&sb=0&d=1&at=7&ft=11&tf=0&pageid=1
假如視窗已經縮到工具列裡,PrintWindow就取不到畫面了,這篇討論提供了可行的作法
出自Capturing Minimized Window: A kid’s trick
http://www.codeproject.com/KB/cs/CapturingMinimizedWindow.aspx
系統時間:2024-04-24 23:49:29
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!