使用DirectX截屏
網上有很多關于DirectX截屏的文章,但大都是屏幕截圖,很少有窗口截圖,本文則兩者都涉及到,先講如何截取整個屏幕,再講如何截取某個窗口,其實二者的區別不大,只是某個參數的設置不同而已,最后我們還將擴展到任意區域的截圖。
首先看一下截屏用到的函數,最核心的當然是D3DXSaveSurfaceToFile,先看下函數原型
1?HRESULT?D3DXSaveSurfaceToFile(2???LPCTSTR?pDestFile,
3???D3DXIMAGE_FILEFORMAT?DestFormat,
4???LPDIRECT3DSURFACE9?pSrcSurface,
5???CONST?PALETTEENTRY?*?pSrcPalette,
6???CONST?RECT?*?pSrcRect
7?);
第一個參數是指向設備的指針,不多說啦
第二個參數是截圖文件的類型,支持的類型還不少,主要有下面這些
BMP,JPG,TGA,PNG,DDS,PPM,DIB,HDR,PFM
這里我們使用BMP-即位圖格式
第三個參數是指向Surface的指針,也就是保存了截圖數據的表面
第四個參數是Surface的調色板,這里不使用,設置為NULL
最后一個參數是Surface的矩形區域,也就是我們可以只截取Surface上某一矩形區域的數據,其實截取全屏和截取窗口的差別也就在這個參數的設置上
其他的函數在下面會逐一講解
現在來定義我們的截屏函數,首先我們需要一個設備指針,因為在DX中,任何操作都與設備密切相關,所以設備指針幾乎是每個DX函數都要用到的參數,我們這個函數也不例外,其次需要一個窗口句柄,當我們截取窗口時,把窗口句柄傳入,當我們截取整個屏幕時,直接傳入NULL。最后我們需要一個字符串參數來指定截圖對應的文件名,如下
1?BOOL?ScreenShot(LPDIRECT3DDEVICE9?lpDevice,?HWND?hWnd,?TCHAR*?fileName)詳細步驟:
首先我們需要獲取顯示模式,注意這里獲取的是顯卡的顯示模式,而不是設備的顯示模式,因為設備的顯示模式既有窗口模式,也有全屏模式,所以它的分辨率是不確定的,而顯卡的顯示模式返回的始終是最大分辨率,我們需要創建整個屏幕區域對應的Surface,當截取整個屏幕時,直接保存即可,當截取窗口時,我們將窗口所對應的區域保存即可
獲取顯卡顯示模式的代碼如下
1?HRESULT?hr;2?
3??//?Get?adapter?display?mode
4?D3DDISPLAYMODE?mode;
5?if?(FAILED(hr?=?lpDevice->GetDisplayMode(0,?&mode)))
6?????return?hr;
7?
下面開始創建表面,這個表面是對應整個屏幕的
Code接下來獲取屏幕對應的數據,這個函數實際上是將顯存中的數據拷貝到系統內存中
1?//?Get?the?screen?data2?if?(FAILED(hr?=?lpDevice->GetFrontBufferData(0,?surf)))
3?{
4?????surf->Release()?;
5?????return?hr?;
6?}
7?
接下來我們判斷是截取窗口還是截取屏幕,很簡單,只需判斷hWnd是否為NULL即可,如果是截取窗口則設置窗口對應的矩形區域即可
Code最后一步,保存截圖!
1?//?Save?the?screen?date?to?file2?hr?=?D3DXSaveSurfaceToFile(fileName,?D3DXIFF_BMP,?surf,?NULL,?rect);
3?
4?surf->Release()?;
5?
6?return?hr?;
7?
完整代碼
Code那么如何實現任意區域截屏呢,我想大家已經想到了,假設使用鼠標拖拽的方法截圖,記下鼠標按下和抬起時的坐標,構造一個RECT,然后傳遞給D3DXSaveSurfaceToFile函數就可以了,需要注意到是,由于鼠標拖拽到方向是任意的,所以在構造RECT的時候要注意right < left或者bottom < top 的情況,用下面的方法可以處理
Codehappy coding!
==THE END==
?
轉載自:http://www.cnblogs.com/graphics/archive/2009/11/25/1610914.html
轉載于:https://www.cnblogs.com/OrdinaryTravel/p/4326024.html
總結
以上是生活随笔為你收集整理的使用DirectX截屏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: struts2处理.do后缀的请求
- 下一篇: Hibernate学习笔记--第一个Hi