分享
 
 
 

[FY] 截取屏幕的3种实现

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

本文地址 : http://www.codeproject.com/dialog/screencap.asp

有时候我们需要在程序中截取屏幕,下面我将解释如何来实现。其中最直接的方式是使用 GDI 或者 DX,除此之外,还可以考虑 Windows Media API。 在这里我们会分别介绍他们的实现方法。

GDI 方式:

如果不考虑效果或者仅是随便的截图,我们可以考虑GDI。他的机制是利用了桌面也是一个窗口,因此都会有窗口句柄以及设备环境(DC)

如果我们获取了该DC,只需要把他的内容 blit 到我们的程序DC中即可,而知道了窗口句柄后,DC则是探囊取物。桌面的窗口句柄可以通过函数 GetDesktopWindow() 获取。

因此所涉及的步骤有:

1. 通过XX 函数获得窗口句柄

2. 通过句柄获得设备环境

3. 为桌面DC创建一个兼容DC以及创建兼容位图到该DC。可以使用CreateCompatibleDC() 和 CreateCompatibleBitmap();SelectObject()实现

4. 准备好了? OK, 把桌面DC BLIT 到 刚创建的兼容DC中 就搞定了(刚才创建的位图便是当前的桌面了)

5 记得释放内存。

Example

Void CaptureScreen()

{

int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);

int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

HWND hDesktopWnd = GetDesktopWindow();

HDC hDesktopDC = GetDC(hDesktopWnd);

HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);

HBITMAP hCaptureBitmap =CreateCompatibleBitmap(hDesktopDC,

nScreenWidth, nScreenHeight);

SelectObject(hCaptureDC,hCaptureBitmap);

BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight,hDesktopDC,0,0,SRCCOPY);

SaveCapturedBitmap(hCaptureBitmap); //Place holder - Put your code

//here to save the captured image to disk

ReleaseDC(hDesktopWnd,hDesktopDC);

DeleteDC(hCaptureDC);

DeleteObject(hCaptureBitmap);

}

上面的代码段中,函数GetSystemMetrics() 使用参数SM_CXSCREEN 返回屏幕宽,SM_CYSCREEN返回屏幕高。 至于如何保存所获取的位图以及如何发送到

粘贴板,没什么好说的 HOHO。

DX :

通过DX截取屏幕是一件非常简单的事情。

每个 DX 应用程序都有一个缓冲来存放本程序相关的显存,也叫做背面缓冲。有些可能不止一个背面缓冲。还有另外一个可以直接存取的

缓冲——前台缓冲,他包含了于桌面相关的显存——实际上就是桌面的图片。

通过读取前台缓冲,我们便可以截取桌面了,而DX的内部机制可以确保得到优化的效果——至少比GDI强。

通过DX我们可以很轻松的对前台缓冲进行操作,接口 IDirect3DDevice8 提供了函数 GetFrontBuffer() ,带一个参数(IDirect3DSurface8),

该参数用于获得前台缓冲的内容。而 IDirect3DSurface8 对象可以通过函数 CreateImageSurface() 创建,一旦屏幕被截取到 surface 中,我们可以

用 D3DXSaveSurfaceFile() 把 surface 保存为位图格式,下面是截图代码:

extern IDirect3DDevice8* g_pd3dDevice;

Void CaptureScreen()

{

IDirect3DSurface8 * pSurface;

g_pd3dDeviceàCreateImageSurface(ScreenWidth,ScreenHeight,

D3DFMT_A8R8G8B8,&pSurface);

g_pd3dDevice->GetFrontBuffer(pSurface);

D3DXSaveSurfaceToFile("Desktop.bmp",D3DXIFF_BMP,pSurface,

NULL,NULL);

pSurface->Release();

}

g_pd3dDevice 是IDirect3DDevice的对象,并假设已经被初始化。 上面的代码是直接保存图片到本地磁盘,如果我们只是想对图片的象素进行操作,我们

可以使用 IDirect3DSurface8::LockRect(), 他让一个指针指向所截取图片的内存单元,我们可以把他拷贝到我们的程序定义的内存并进行操作,下面是

实现拷贝操作的代码段:

extern void* pBits;

extern IDirect3DDevice8* g_pd3dDevice;

IDirect3DSurface8 * pSurface;

g_pd3dDeviceàCreateImageSurface(ScreenWidth,ScreenHeight,

D3DFMT_A8R8G8B8,&pSurface);

g_pd3dDevice->GetFrontBuffer(pSurface);

D3DLOCKED_RECT lockedRect;

pSurfaceàLockRect(&lockedRect,NULL,

D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|

D3DLOCK_READONLY)));

for( int i=0 ; i < ScreenHeight ; i++)

{

memcpy( (BYTE*) pBits + i * ScreenWidth * BITSPERPIXEL / 8 ,

(BYTE*) lockedRect.pBits + i* lockedRect.Pitch ,

ScreenWidth * BITSPERPIXEL / 8);

}

g_pSurface->UnlockRect();

pSurface->Release();

上面的 pBits 是一个 void 指针,在拷贝之前要却被他有足够的内存。 BITSPERPIXEL 典型的值是每个象素32位,但他可能因显示器的设置而改变。

这里特别需要注意的是,surface 的宽度并不等同于截取的屏幕图片的宽度。 由于内存对齐处理(以字对齐的方式存取快于非对齐内存),surface 可能会在每行的后面进行多余的填充。 不过 lockedRect.Pitch 确切的告诉我们两行之间的位数,也就是说我们可以通过 pitch 而非 width 获得正确的结果。

字对齐。

下面的代码段是以反序拷贝 surface :

当你想反转一个位图时可以使用。

for( int i=0 ; i < ScreenHeight ; i++)

{

memcpy((BYTE*) pBits +( ScreenHeight - i - 1) *

ScreenWidth * BITSPERPIXEL/8 ,

(BYTE*) lockedRect.pBits + i* lockedRect.Pitch ,

ScreenWidth* BITSPERPIXEL/8);

}

在 DX8 中, LockRect 是唯一的方式可以对截取的图片进行存取操作,而在 DX9 中,可以使用 GetDC() 来获得该图片的GDI兼容设备环境,

这样问题又回归到了第一种方式……

最后一点废话(文档的注意信息):GetFrontBuffer() 被设计为一个较慢的操作,在性能较差的机器的应用程序中不与考虑。

独子饿了! ……

有错误的理解请指正!谢谢

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有