PrintWindow是公开的函数,XP以上系统才有。以下摘自MSDN。PrintWindow The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC.BOOL PrintWindow( HWND hwnd, // Window to copy HDC hdcBlt, // HDC to print into UINT nFlags // Optional flags );Parameters hwnd Handle to the window that will be copied. hdcBlt Handle to the device context. nFlags Specifies the drawing options. It can be one of the following values. Value Meaning PW_CLIENTONLY Only the client area of the window is copied to hdcBlt. By default, the entire window is copied. Return Values If the function succeeds, it returns a nonzero value.If the function fails, it returns zero.
The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC.BOOL PrintWindow(
HWND hwnd, // Window to copy
HDC hdcBlt, // HDC to print into
UINT nFlags // Optional flags
);Parameters
hwnd
Handle to the window that will be copied.
hdcBlt
Handle to the device context.
nFlags
Specifies the drawing options. It can be one of the following values. Value Meaning
PW_CLIENTONLY Only the client area of the window is copied to hdcBlt. By default, the entire window is copied.
Return Values
If the function succeeds, it returns a nonzero value.If the function fails, it returns zero.
按照这种思路实现时,的确可以成功截图,但是会产生严重的窗口闪烁现象。
有没有人遇到过这种情况?
怎么能防止自己的窗口被PrintWindow截取呢?
2、pUnknow->QueryInterface(IID_IViewObject2,(void**)&pViewObj);
3、创建兼容DC dcCompatible,CRect vRt;
4、pViewObj->Draw(DVASPECT_CONTENT,-1,NULL,NULL,0,m_dcCompatible,&vRt,0,NULL,0);如果IID_IViewObject2 不行就试下 ID_IViewObject
不建议,"闪"啊另外LZ"怎么能防止自己的窗口被PrintWindow截取呢",这个要处理得好那就是你的专利了, 现在电子章用到的技术大概就是这个
VISTA以后的系统引入了DWM,所有的窗口都是画到了directx的一个surface上,所以VISTA任务栏上可以随时显示窗口缩略图。
在启动截图的时候,
查找所有可视窗口,在截图对话框中LISTBOX显示,
用户可随意将被挡住窗口设置为顶部(在切换的过程中会闪一下),
之后就很正常了.
其原理很简单,就是先调整窗口,然后截图窗口再次截取全屏幕,并在截图窗口重新绘制.
2.创建目标兼容BITMAP hBitmap
3.SelectObject(hDC, hBitmap)
4.SendMessage(hWndTarget, WM_PAINT, hDc, 0)
5.ok
http://topic.csdn.net/t/20061109/11/5144676.html>>>>>>
如果在应用层做,你应该先找到DirectDraw的COM对象,比如可以通过
Hook DriectDraw的创建函数xxxCreate(),得到DirectDraw之后,想
Hook DreictDraw的那个函数都很容易。
<<<<<<
1>因为Hook了DirectDrawCreate这个API, 因此其它进程调用DirectDrawCreate时转入了咱们的XXXDirectDrawCreate。
2>在XXXDirectDrawCreate中,通过XXX_get_vfuncaddr_createsurface获得IDirectDraw::CreateSurface方法的函数地址。
3>此时可以Hook IDirectDraw::CreateSurface这个函数。
4>在其它进程调用IDirectDraw::CreateSurface时,转入咱们的XXXIDirectDraw_CreateSurface、
5>此时通过XXX_get_vfuncaddr_blt获得IDirectDrawSurface::Blt的函数地址。
6>此时Hook IDirectDrawSurface::Blt这个函数。
7>在咱们的XXXIDirectDrawSurface_Blt()函数中进行截屏。这里Blt是虚函数,没法通过NULL对象获得其函数地址,所以过程搞得复杂了点。
//获取IDirectDraw接口的CreateSurface方法的实际函数地址。
long XXX_get_vfuncaddr_createsurface(LPDIRECTDRAW pDD)
{
if( !g_apiinited ) {
g_apiinited = true;
memset(&g_apicreatesurface,0,sizeof(XXXHookApi));
memset(&g_apiblt,0,sizeof(XXXHookApi));
} if( g_apicreatesurface.name.function) { return 0;}
long * vtblDD = ( (long *)(* (long*)pDD) );
memset(&g_apicreatesurface,0,sizeof(g_apicreatesurface));
g_apicreatesurface.name.function = vtblDD[6];
strcpy(g_apicreatesurface.name.olddll,"ddraw.dll");
strcpy(g_apicreatesurface.name.newdll,"XXX.dll");
strcpy(g_apicreatesurface.name.newname, "XXXIDirectDraw_CreateSurface");
XXXHook hook;
hook.InitApi(&g_apicreatesurface);
hook.InstallApi(&g_apicreatesurface); return 0;
}
//获取IDirectDrawSurface接口的Blt方法的实际函数地址。
long XXX_get_vfuncaddr_blt(LPDIRECTDRAWSURFACE pDS)
{
if( g_apiblt.name.function) { return 0;}
long * vtbl = ( (long *)(* (long*)pDS) ); memset(&g_apiblt,0,sizeof(g_apiblt));
g_apiblt.name.function = vtbl[5];
strcpy(g_apiblt.name.olddll,"ddraw.dll");
strcpy(g_apiblt.name.newdll,"XXX.dll");
strcpy(g_apiblt.name.newname, "XXXIDirectDrawSurface_Blt");
XXXHook hook;
hook.InitApi(&g_apiblt);
hook.InstallApi(&g_apiblt); return 0;
}
//被替换的IDirectDraw::CreateSurface方法
extern "C" HRESULT __stdcall XXXIDirectDraw_CreateSurface( LPDIRECTDRAW p0, LPDDSURFACEDESC p1, LPDIRECTDRAWSURFACE FAR * p2, IUnknown FAR * p3)
{
XXXHook hook;
hook.UninstallApi(&g_apicreatesurface);
XXX_log_trace("XXXIDirectDrawSurface_Blt called.\n"); if( ( DDSCAPS_OFFSCREENPLAIN & p1->ddsCaps.dwCaps) == DDSCAPS_OFFSCREENPLAIN ) {
p1->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
p1->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
p1->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
} HRESULT hr = p0->CreateSurface(p1,p2,p3);
hook.InstallApi(&g_apicreatesurface); XXX_get_vfuncaddr_blt( *p2);
return hr;
}
//被替换的IDirectDrawSurface::Blt方法。
//窗口截屏在这里进行。
extern "C" HRESULT __stdcall XXXIDirectDrawSurface_Blt( LPDIRECTDRAWSURFACE p0, LPRECT p1,LPDIRECTDRAWSURFACE p2, LPRECT p3,DWORD p4, LPDDBLTFX p5)
{
XXXHook hook;
hook.UninstallApi(&g_apiblt);
//XXX_log_trace("XXXIDirectDrawSurface_Blt called.\n");
HRESULT hr = p0->Blt(p1,p2,p3,p4,p5);
hook.InstallApi(&g_apiblt); ///////////COPY BITMAP DATA//////// if( p3->right-p3->left > 800 && p3->bottom-p3->top>600 ) {
g_sc.CaptureSurface(p0, p2 );
}
return hr;}//被替换的DirectDrawCreate函数。
extern "C" HRESULT WINAPI XXXDirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter )
{
XXXAutoHook hook("DirectDrawCreate","ddraw.dll");
XXX_log_trace("DirectDrawCreate called.\n");
HRESULT hr = DirectDrawCreate(lpGUID, lplpDD, pUnkOuter);
if(FAILED(hr)) { return hr;} XXX_get_vfuncaddr_createsurface( *lplpDD );
return hr;
}
我有见到过一些数据安全产品防止键盘截图的,但是没见过防止这个API截图的。
有人提供一些思路么?HOOK?驱动?还是。?
我觉得那些将窗口置前,截图,再置后的做法不可取,这样的变化太明显了,修改其他窗口的属性更是不应该的。LZ和二楼那位大侠说的PrintWindow就能很好的完成功能,学习了