BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / soft-design / #25885同步于 2008/5/30
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖

有没有人知道怎样给控件截图?

NWN2
2008/5/30镜像同步14 回复
现在我知道这个控件的handle,但这个控件可能处于窗口或屏幕的不可见区域,我需要给这个控件截图。 有没有人知道应该怎么做? 目前假定是win32 C/C++的环境,如果能提供其它操作系统的实现方法,同样非常感谢
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
NWN2机器人#1 · 2008/5/30
【 在 flyingkisser 的大作中提到: 】 : 不是NE的MJ吧。。。 就等着猫哥了 基本没有做过win32编程 =v=!!
flyingkisser机器人#2 · 2008/5/30
你就是要对整个屏幕截图吧? 让MZ直接把代码贴出来,他写的木马肯定带这个功能,哈哈! 【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】 : 就等着猫哥了 : 基本没有做过win32编程 : =v=!! : ...................
NWN2机器人#3 · 2008/5/30
【 在 flyingkisser 的大作中提到: 】 : 你就是要对整个屏幕截图吧? : 让MZ直接把代码贴出来,他写的木马肯定带这个功能,哈哈! 非屏幕,而是某个控件,而且控件处于窗口或屏幕的不可见区域
flyingkisser机器人#4 · 2008/5/30
处于屏幕的不可见区域,win32k.sys不会对它进行绘制,如何截呢? 也就是说,我们看不到,windows也看不到,截毛。。。。。 另外,你知道有实现的先例吗?我感觉没法实现。 【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】 : 非屏幕,而是某个控件,而且控件处于窗口或屏幕的不可见区域
NWN2机器人#5 · 2008/5/30
【 在 flyingkisser 的大作中提到: 】 : 处于屏幕的不可见区域,win32k.sys不会对它进行绘制,如何截呢? : 也就是说,我们看不到,windows也看不到,截毛。。。。。 : 另外,你知道有实现的先例吗?我感觉没法实现。 有,我手头上有个dll能干这事 附件(56KB) SWTDesigner.dll 实现这个功能的函数应该是叫这个名字 Java_com_swtdesigner_test_TestShot_makeShot 无返回值,输入参数为(__int64 控件handle, __int64 图像数据输出handle, long)
flyingkisser机器人#6 · 2008/5/30
下了班逆向一下。 【 在 NWN2 (Neverwinter Nights 2) 的大作中提到: 】 : 有,我手头上有个dll能干这事 : [upload=1][/upload] : 实现这个功能的函数应该是叫这个名字 Java_com_swtdesigner_test_TestShot_makeShot : ...................
flyingkisser机器人#7 · 2008/5/30
这个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 (齐天大猫) 的大作中提到: 】 : 下了班逆向一下。
IchijyouSan机器人#8 · 2008/6/1
今天研究了一下,后面那部分代码是负责截图的 下面的代码实现了截图的功能 [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] 不过还有一个问题是,如果当控件不在可见范围之内时,就会失败,估计前面那段代码是用来处理这种情况的
IchijyouSan机器人#9 · 2008/6/1
BC了我,还有就是稍微被猫哥后面提供的代码迷惑了 直接就一个 SendMessageW(hWnd, WM_PRINT, hDC, PRF_CLIENT); 就ok了 =v=