返回信息流现在我知道这个控件的handle,但这个控件可能处于窗口或屏幕的不可见区域,我需要给这个控件截图。
有没有人知道应该怎么做?
目前假定是win32 C/C++的环境,如果能提供其它操作系统的实现方法,同样非常感谢
这是一条镜像帖。来源:北邮人论坛 / soft-design / #25885同步于 2008/5/30
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖
有没有人知道怎样给控件截图?
NWN2
2008/5/30镜像同步14 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
你就是要对整个屏幕截图吧?
让MZ直接把代码贴出来,他写的木马肯定带这个功能,哈哈!
【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】
: 就等着猫哥了
: 基本没有做过win32编程
: =v=!!
: ...................
【 在 flyingkisser 的大作中提到: 】
: 你就是要对整个屏幕截图吧?
: 让MZ直接把代码贴出来,他写的木马肯定带这个功能,哈哈!
非屏幕,而是某个控件,而且控件处于窗口或屏幕的不可见区域
处于屏幕的不可见区域,win32k.sys不会对它进行绘制,如何截呢?
也就是说,我们看不到,windows也看不到,截毛。。。。。
另外,你知道有实现的先例吗?我感觉没法实现。
【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】
: 非屏幕,而是某个控件,而且控件处于窗口或屏幕的不可见区域
【 在 flyingkisser 的大作中提到: 】
: 处于屏幕的不可见区域,win32k.sys不会对它进行绘制,如何截呢?
: 也就是说,我们看不到,windows也看不到,截毛。。。。。
: 另外,你知道有实现的先例吗?我感觉没法实现。
有,我手头上有个dll能干这事
附件(56KB) SWTDesigner.dll
实现这个功能的函数应该是叫这个名字 Java_com_swtdesigner_test_TestShot_makeShot
无返回值,输入参数为(__int64 控件handle, __int64 图像数据输出handle, long)
下了班逆向一下。
【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】
: 有,我手头上有个dll能干这事
: [upload=1][/upload]
: 实现这个功能的函数应该是叫这个名字 Java_com_swtdesigner_test_TestShot_makeShot
: ...................
这个DLL主要导出了2个函数:
1。
__int64 __stdcall Java_com_swtdesigner_test_TestShot_makeShot(int a1, int a2, HWND hWnd, int a4, WPARAM wParam, int a6, int a7)
{
if ( a7 )
SendMessageW(hWnd, 0x317u, wParam, 30);
return 0i64;
}
2.__int64 __stdcall Java_com_swtdesigner_test_TestShot_fetchPopupMenuVisualData(int a1, int a2, HWND a3, int a4, HMENU a5, int a6, int a7)
{
__int64 result; // qax@2
DWORD v8; // eax@1
HHOOK v9; // eax@1
int v10; // esi@3
int v11; // eax@3
int v13; // edi@3
hWnd = a3;
hhk = 0;
dword_1000C7FC = 0;
dword_1000C800 = 0;
dword_1000C804 = 0;
dword_1000C7E8 = 0;
lpPrevWndFunc = 0;
byte_1000C80C = 0;
hMenu = a5;
v8 = GetCurrentThreadId();
v9 = SetWindowsHookExW(4, fn, 0, v8);
hhk = v9;
if ( v9 )
{
v10 = a1;
v11 = (*(int (__stdcall **)(int, int))(*(_DWORD *)a1 + 684))(a1, a7);
_ECX = 0;
v13 = v11;
v11 *= 4;
__asm { seto cl }
Memory = (void *)operator new(v11 | -_ECX);
SetForegroundWindow(hWnd);
TrackPopupMenuEx(hMenu, 0x4000u, 100, 100, hWnd, 0);
(*(int (__stdcall **)(int, int, _DWORD, int, void *))(*(_DWORD *)v10 + 844))(v10, a7, 0, v13, Memory);
UnhookWindowsHookEx(hhk);
hhk = 0;
if ( dword_1000C800 )
ReleaseDC(0, dword_1000C800);
if ( dword_1000C804 )
DeleteDC(dword_1000C804);
j__free(Memory);
result = dword_1000C7E8;
}
else
{
result = 0i64;
}
return result;
}
你说的那个用来截图的函数,通过
SendMessageW(hWnd, 0x317u, wParam, 30);
给一个窗口发0x317消息,窗口句柄是由接口指定的,
找到这个DLL的内部消息处理函数如下:
LRESULT __stdcall sub_10001006(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
int v4; // ebx@4
UINT v5; // edi@4
int v6; // esi@6
LPARAM v7; // esi@10
int v8; // ebx@11
int v9; // edi@11
HDC v10; // eax@13
HBITMAP v11; // eax@15
LRESULT result; // eax@17
char *v13; // eax@8
int v14; // esi@11
HDC v15; // eax@14
struct tagRECT rcItem; // [sp+Ch] [bp-20h]@4
int v17; // [sp+1Ch] [bp-10h]@7
int v18; // [sp+20h] [bp-Ch]@8
int v19; // [sp+24h] [bp-8h]@8
int v20; // [sp+28h] [bp-4h]@8
if ( Msg == 70 )
{
if ( byte_1000C80C )
{
*(_DWORD *)(lParam + 8) += 10000;
if ( dword_1000C804 )
{
if ( dword_1000C7E8 )
PostMessageW(hWnd, 0x317u, (WPARAM)dword_1000C804, 30);
}
PostMessageW(hWnd, 0x81DEu, 0, 0);
PostMessageW(hWnd, 0x10u, 0, 0);
byte_1000C80C = 0;
}
return CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
}
if ( Msg != 131 )
{
if ( Msg == 33246 )
{
v4 = GetMenuItemCount(hMenu);
v5 = 0;
if ( GetMenuItemRect(hWnd, hMenu, 0, &rcItem) )
{
if ( v4 > 0 )
{
v6 = 0;
do
{
if ( !GetMenuItemRect(hWnd, hMenu, v5, (struct tagRECT *)&v17) )
break;
v13 = (char *)Memory + v6;
*(_DWORD *)((char *)Memory + v6) = v17 - rcItem.left + 2;
v6 += 16;
*((_DWORD *)v13 + 1) = v18 - rcItem.top + 2;
*((_DWORD *)v13 + 2) = v19 - v17;
++v5;
*((_DWORD *)v13 + 3) = v20 - v18;
}
while ( (signed int)v5 < v4 );
}
}
}
return CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
}
v7 = lParam;
hWnd = (HWND)CallWindowProcW(lpPrevWndFunc, hWnd, 0x83u, wParam, lParam);
if ( wParam == 1 )
{
v14 = *(_DWORD *)(v7 + 48);
v9 = *(_DWORD *)(v14 + 16);
v8 = *(_DWORD *)(v14 + 20);
}
else
{
v9 = *(_DWORD *)(v7 + 8) - *(_DWORD *)v7;
v8 = *(_DWORD *)(v7 + 12) - *(_DWORD *)(v7 + 4);
}
v10 = GetDC(0);
dword_1000C800 = v10;
if ( v10 )
{
v15 = CreateCompatibleDC(v10);
dword_1000C804 = v15;
if ( v15 )
{
v11 = CreateCompatibleBitmap(dword_1000C800, v9, v8);
dword_1000C7E8 = (int)v11;
if ( v11 )
SelectObject(dword_1000C804, v11);
}
}
result = (LRESULT)hWnd;
byte_1000C80C = 1;
return result;
}
看样子最后几行和这个截图有点关系,对DC进行的操作。
所以,如果你那边有能跑的程序用这个DLL截图的,再动态分析一下就知道怎么回事了。
【 在 flyingkisser (齐天大猫) 的大作中提到: 】
: 下了班逆向一下。
今天研究了一下,后面那部分代码是负责截图的
下面的代码实现了截图的功能
[quote]HWIND source = hWnd;
HDC sDC, tDC;
int width, height;
HBITMAP bitmap;
sDC = GetDC(source);
if (sDC) {
tDC = CreateCompatibleDC(sDC);
width = GetDeviceCaps(sDC, HORZRES);
height = GetDeviceCaps(sDC, VERTRES);
if (tDC) {
bitmap = CreateCompatibleBitmap(sDC, width, height);
if (bitmap) {
SelectObject(tDC, bitmap);
if (!BitBlt(tDC, 0, 0, width, height, sDC, 0, 0, SRCCOPY)) {
// Error
}
}
}
ReleaseDC(source, sDC);
}
[/quote]
不过还有一个问题是,如果当控件不在可见范围之内时,就会失败,估计前面那段代码是用来处理这种情况的
BC了我,还有就是稍微被猫哥后面提供的代码迷惑了
直接就一个
SendMessageW(hWnd, WM_PRINT, hDC, PRF_CLIENT);
就ok了
=v=