游戏用的是DirectDraw, 我的截屏是这样做的: 1.hook了DirectDrawCreate获取了LPDIRECTDRAW 2.hook了CreateSurface, 将主表面地址保存起来 3.创建一个离屏surface,将主表面copy到这个离屏表面上,然后输出到文件
现在问题是这个截屏后,若游戏窗口被遮挡,则被遮挡部分无法获取. 这个是什么原因呢? 是这种截图方式不支持遮挡部分截屏呢? 还是说跟游戏主表面的创建有关,有点诡异,游戏窗口大小是800*600,却创建了一个1400*900(显示器大小)的主表面. 还请高手指点下:)
找到原因了,直接取主表面,copy一份到离屏表面,然后打印,那个结果就是遮挡的还是遮挡. 解决方法就是对主表面的blt函数hook,当主表面更新数据时,即调用blt时,此时传入的src表面是未遮挡的,就是麻烦点,那个src表面就是离屏表面,而且是多个拼凑的... 顺便还做了个小测试,在主表面的blt函数中加了个sleep(50),这个cpu占用率就降低了 哈哈哈
现在问题是这个截屏后,若游戏窗口被遮挡,则被遮挡部分无法获取. 这个是什么原因呢? 是这种截图方式不支持遮挡部分截屏呢? 还是说跟游戏主表面的创建有关,有点诡异,游戏窗口大小是800*600,却创建了一个1400*900(显示器大小)的主表面. 还请高手指点下:)
//创建后台表面 if (g_lpDirectDrawCopySurface == NULL) { LPDIRECTDRAW lpDD = NULL; //创建DirectDraw if (FAILED( DirectDrawCreate(NULL,&lpDD,NULL))) { MyTrace(L_ERROR, "Couldn't create DirectDraw object."); return E_FAIL; } if (FAILED(lpDD->SetCooperativeLevel(hwnd/*NULL*/, DDSCL_NORMAL))) { MyTrace(L_ERROR, "SetCooperativeLevel failed."); lpDD->Release(); return E_FAIL; } //创建后台表面 RECT rc; GetClientRect(hwnd, &rc); DDSURFACEDESC desc; ZeroMemory(&desc,sizeof(desc)); desc.dwSize=sizeof(desc); desc.dwFlags= DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS; desc.dwWidth=/*::GetSystemMetrics(SM_CXSCREEN); */ /*primedesc.dwWidth*/ /*800*/ rc.right - rc.left; desc.dwHeight=/*::GetSystemMetrics(SM_CYSCREEN); */ /*primedesc.dwHeight*/ /*600*/ rc.bottom - rc.top; desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; if (FAILED(hr = lpDD->CreateSurface(&desc, &g_lpDirectDrawCopySurface, NULL))) { MyTrace(L_ERROR, "CreateSurface copysurface failed.err=0x%x", hr); lpDD->Release(); return E_FAIL; } } RECT rc; //GetWindowRect(hwnd, &rc); GetClientRect(hwnd, &rc); MyTrace(L_DEBUG, "GetClientRect: %d,%d,%d,%d", rc.left, rc.right, rc.top, rc.bottom); DDSURFACEDESC desc; ZeroMemory(&desc,sizeof(desc)); desc.dwSize = sizeof(desc); if (FAILED(hr = g_lpDirectDrawCopySurface->GetSurfaceDesc(&desc))) { MyTrace(L_ERROR, "copysurface GetSurfaceDesc failed.err=0x%x", hr); return E_FAIL; } else { MyTrace(L_DEBUG, "copysurface GetSurfaceDesc successfully, nWidth=%d, nHeight=%d", desc.dwWidth, desc.dwHeight); } if (FAILED(hr = g_lpDirectDrawCopySurface->BltFast(0,0,g_lpDirectDrawPrimeSurface,&rc,DDBLTFAST_NOCOLORKEY| DDBLTFAST_WAIT))) { MyTrace(L_ERROR, "BltFast failed.err=0x%x", hr); return E_FAIL; } if (FAILED(hr = g_lpDirectDrawCopySurface->Lock(NULL, &desc, DDLOCK_WAIT|DDLOCK_NOSYSLOCK,NULL))) { MyTrace(L_ERROR, "Lock failed.err=0x%x", hr); return E_FAIL; } //save to bmp if(SaveToBitmapFile(&desc, pszFilePath) != S_OK) { g_lpDirectDrawCopySurface->Unlock(NULL); MyTrace(L_ERROR, "SaveToBitmapFile failed."); return E_FAIL; } else { g_lpDirectDrawCopySurface->Unlock(NULL); MyTrace(L_DEBUG, "SaveToBitmapFile successfully."); }
找到原因了,直接取主表面,copy一份到离屏表面,然后打印,那个结果就是遮挡的还是遮挡. 解决方法就是对主表面的blt函数hook,当主表面更新数据时,即调用blt时,此时传入的src表面是未遮挡的,就是麻烦点,那个src表面就是离屏表面,而且是多个拼凑的... 顺便还做了个小测试,在主表面的blt函数中加了个sleep(50),这个cpu占用率就降低了 哈哈哈
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2305
- 用户1336
- 访客11455538
每日一句
Talent without working hard is nothing.
没有努力,天份不代表什么。
没有努力,天份不代表什么。
MySQL 数据库优化
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
免ROOT实现模拟点击任意位置
Mobaxterm终端神器
CreateProcessW要注意的细节问题
Autonomous NAT Traversal
【教程】win10 彻底卸载edge浏览器
eclipse工程基于Xposed的一个简单Hook
排名前5的开源在线机器学习
Mac OS最简单及(Karabiner)快捷键设置
发一款C++编写的麻将
VMware NAT端口映射外网访问虚拟机linux
独家发布最新可用My-AutoPost——wordpress 采集器
新会员