抓圖軟件課程設計_第1頁
已閱讀1頁,還剩9頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p><b>  屏幕截圖軟件設計</b></p><p>  摘要: 本文闡述 VC++實現(xiàn)屏幕截圖功能的原理和具體設計步驟,所實現(xiàn)的這個抓圖軟件可以截取整個屏幕,截取指定的窗口,并將截取到的圖像以bmp文件形式保存到指定的路徑下。技術重點在鼠標在屏幕上的準確定位;如何獲取抓圖的窗口句柄;如何對抓到的圖片進行保存的問題。技術難點在如何將所抓取的屏幕窗口保存為磁盤BMP文件形式。

2、</p><p>  關鍵詞:屏幕截圖;BMP位圖;設備環(huán)境(DC)</p><p><b>  1 引言</b></p><p>  在我們的日常上網活動當中比如看電影、玩游戲、做圖等等會對一些畫面特別喜歡!但是卻沒有辦法將這些畫面以圖片形式保存下來,真是猶如“水中月,鏡中花”看得到卻得不到。由于QQ的出現(xiàn),曾改變了幾億人的交流生活方式,它的

3、里面嵌入的任意截圖功能,更是為人們的生活增添了無限的歡愉和快樂,通過截圖自己可以將最喜歡的游戲畫面,最喜歡的電影畫面,以圖片形式保存,可以及時的發(fā)給好友共享,給我們帶來了意想不到的幫助和驚喜。</p><p>  另外系統(tǒng)的功能強大的截圖軟件在社會建設的各個領域都到了施展空間,為人們的工作生活創(chuàng)造了極大的方便,解決了許多棘手難題??梢哉f呀抓圖軟件有很廣闊的應用前景,雖然它不算是很龐大的系統(tǒng)軟件,但是其它的大型的主

4、流系統(tǒng)軟件能夠嵌入抓圖的功能,必將受到極大的歡迎和青睞。</p><p>  所以在此次軟件課程設計當中,我選擇了用VC制作屏幕截圖的軟件,實現(xiàn)截取指定窗口,整個屏幕的功能,并且將截取的圖形以BMP文件形式存放在指定路徑的磁盤當中。本文將系統(tǒng)介紹截圖軟件的設計原理,設計步驟,設計方法,和運用的重點技術。</p><p>  2 實現(xiàn)基本原理和運用相關技術</p><p&

5、gt;  抓圖軟件基本原理就是把屏幕上所抓取的圖像復制到內存中,并最后將內存中的圖像內容以位圖文件形式保存到磁盤當中。在這此軟件設計當中,如果用戶將鼠標左鍵按住不放,則開始抓取圖片,此時隱藏程序窗口,以免影響在抓取時的“視野”,接著裝入“魔法棒”鼠標,開始追蹤鼠標的移動,然后獲得鼠標所在處的窗口句柄,取得屏幕的設備環(huán)境句柄,以便在屏幕的任何位置繪圖。接下來建立一紅色的畫筆,得到鼠標所在處的窗口的區(qū)域,在鼠標所在處的窗口四周畫一紅色的矩形

6、,做為選定時的提醒。當鼠標左鍵釋放的時候得到鼠標所在處的窗口的區(qū)域寬、高,然后建立一個屏幕設備環(huán)境句柄和與屏幕設備環(huán)境句柄兼容、與鼠標所在處的窗口的區(qū)域等大的位圖,把新位圖選到內存設備描述表中,最后把屏幕設備描述表拷貝到內存設備描述表中,終止鼠標捕獲,恢復窗口顯示模式。那么最后要作的工作就是寫一個位圖保存函數將內存當中的窗口圖片信息以位圖形式保存到指定磁盤當中。在整個程序當中要用到大量的函數:比如申請內存空間用于存放位圖文件 Glob

7、alAlloc(GHND,F(xiàn)ileLength); 位圖文件讀入所申請內存空間中LoadFileToMemory( mpBitsS</p><p>  屏幕抓圖程序的關鍵有兩點:一是應該知道鼠標在屏幕上有準確位置;二是應該知道欲抓圖的窗口句柄;三是如何對抓到的圖片進行保存的問題。對于問題一,很簡單,利用SetCapture函數便能夠追蹤鼠標的移動(包括在屏幕抓圖程序窗口之外的窗口)。對于問題二,這時會用到一個平時

8、我們不常用的函數:WindowFromPoint,其函數用法如下:HWND WindowFromPoint{ POINT Point; //坐標};這個函數能夠找出鼠標當前位置所對應的窗口句柄。具體用法可以參見MSDN,這里不做詳細敘述。在選擇抓圖窗口時,鼠標的在位置的窗口都會出現(xiàn)加粗的有色邊框,以提醒目前所選擇的窗口,這個功能實現(xiàn)起來有些復雜,它的代碼如下:</p><p>  POINT pt[5];

9、</p><p>  pt[0] = CPoint(rectCapture.left, rectCapture.top); </p><p>  pt[1] = CPoint(rectCapture.right,rectCapture.top); </p><p>  pt[2] = CPoint(rectCapture.right,rectCapture.bott

10、om); </p><p>  pt[3] = CPoint(rectCapture.left, rectCapture.bottom); </p><p>  pt[4] = CPoint(rectCapture.left, rectCapture.top);</p><p>  在GDI中,最常見的一個概念就設備環(huán)境(DC),每一個窗口都相應的具有自己的DC。如

11、果能夠調用到窗口的DC,那么,我們便能夠在窗口上的任何位置繪圖。然而,在屏幕抓圖程序中,由于用戶所選擇的窗口是不固定的,所以,要想得到鼠標所在處的窗口的DC,不是很容易。但是能夠隨心所欲地在屏幕上進行繪圖卻又不僅限于特定的窗口,GetDC能夠做到這點! GetDC的函數申明:HDC GetDC( HWND hWnd),hWnd是DC對應的窗口句柄,當hWnd為空時,該函數返回的是整個屏幕的設備環(huán)境句柄!這就意味著我們可以在屏幕上進行任意

12、繪圖。在鼠標所在處的窗口進行繪圖時,繪圖本身的目的只是為了提醒用戶目前所選擇的窗口,所以,在進行繪圖時,必須得保證不會破壞窗口原有的畫面。這點很好辦,將窗口的DC繪圖模式設為R2_NOTXORPEN(將畫筆顏色與屏幕顏色進行異或后,再將屏幕顏取反),這樣,在同一個地方進行兩次繪圖后(對同一像素進行兩次異或運算,像素值并不會發(fā)生變化),窗口的畫面并不會發(fā)生任何變化。以上就是此次截圖軟件設計當中運用的相關技術和設計實現(xiàn)原理。</p&g

13、t;<p><b>  3 軟件詳細設計</b></p><p>  3.1建立基于對話框的工程文件</p><p>  啟動Visual C++,生成一個基于對話框的工程,工程名為“Capture”. 然后準備好一個外形為細長矩形的光標文件(*.cur),將之引入資源管理器(IDC_CAMERA)。接著在CCaptureDlg類中加入兩個全局變量:HW

14、ND hwndCapture; CRect rectCapture; UINT nFlags;</p><p>  CPoint point;LPCTSTR lpFileName;HBITMAP hBitmap;</p><p>  3.2添加消息響應函數</p><p>  然后通過類向導加入對WM_MOUSEMOVE及WM_LBUTTONUP事件的響應函數,添加

15、WM_MOUSEMOVE事件的響應函數代碼該函數主要實現(xiàn)的功能:鼠標左鍵按住不放,則開始抓取圖片,此時隱藏程序窗口,以免影響在抓取時的“視野”,接著裝入“魔法棒”鼠標,開始追蹤鼠標的移動,然后獲得鼠標所在處的窗口句柄,取得屏幕的設備環(huán)境句柄,以便在屏幕的任何位置繪圖。接下來建立一紅色的畫筆,得到鼠標所在處的窗口的區(qū)域,在鼠標所在處的窗口四周畫一紅色的矩形,做為選定時的提醒。</p><p>  void CCap

16、tureDlg::OnMouseMove(UINT nFlags, CPoint point) </p><p><b>  {</b></p><p>  //如果用戶將鼠標左鍵按住不放,則開始抓取圖片 </p><p>  if(nFlags==MK_LBUTTON) </p><p><b>  { &l

17、t;/b></p><p>  //隱藏程序窗口,以免影響在抓取時的“視野” </p><p>  ShowWindow(SW_HIDE); </p><p>  //裝入“魔法棒”鼠標,開始追蹤鼠標的移動 </p><p>  HCURSOR cur=LoadCursor(AfxGetInstanceHandle(),MAKEINTR

18、ESOURCE(IDC_CAMERA )); </p><p>  SetCursor(cur); </p><p>  SetCapture(); </p><p>  //獲得鼠標所在處的窗口句柄 </p><p>  ClientToScreen(&point); </p><p>  hwndCaptu

19、re=(HWND)::WindowFromPoint(point); </p><p>  //取得屏幕的設備環(huán)境句柄,以便在屏幕的任何位置繪圖 </p><p>  HDC hDC=::GetDC(NULL); </p><p>  //建立一紅色的畫筆 </p><p>  HPEN hPen =CreatePen(PS_INSIDEFR

20、AME,6, RGB(255,0,0)); </p><p>  //將繪圖模式設為R2_NOTXORPEN,在繪圖時可以不破壞原有的背景 </p><p>  int nMode =SetROP2(hDC, R2_NOTXORPEN); </p><p>  HPEN hpenOld= (HPEN)SelectObject(hDC, hPen); </p&g

21、t;<p>  //得到鼠標所在處的窗口的區(qū)域 </p><p>  ::GetWindowRect(hwndCapture,&rectCapture); </p><p>  //在鼠標所在處的窗口四周畫一紅色的矩形,做為選定時的提醒 </p><p>  POINT pt[5]; </p><p>  pt[0] =

22、 CPoint(rectCapture.left, rectCapture.top); </p><p>  pt[1] = CPoint(rectCapture.right,rectCapture.top); </p><p>  pt[2] = CPoint(rectCapture.right,rectCapture.bottom); </p><p>  pt

23、[3] = CPoint(rectCapture.left, rectCapture.bottom); </p><p>  pt[4] = CPoint(rectCapture.left, rectCapture.top); </p><p>  ::Polyline(hDC,pt,5); </p><p>  //延時后再重繪紅色的矩形,這樣就不會破壞原有內容

24、 </p><p>  Sleep(100); </p><p>  ::Polyline(hDC,pt,5); </p><p>  ::SelectObject(hDC,hpenOld); </p><p>  ::ReleaseDC(NULL,hDC); </p><p><b>  } </b&

25、gt;</p><p>  CDialog::OnMouseMove(nFlags, point);</p><p><b>  }</b></p><p>  添加WM_LBUTTONUP事件的響應函數代碼:該函數主要實現(xiàn)當鼠標左鍵釋放的時候得到鼠標所在處的窗口的區(qū)域寬、高,然后建立一個屏幕設備環(huán)境句柄和與屏幕設備環(huán)境句柄兼容、與鼠標所在處的

26、窗口的區(qū)域等大的位圖,把新位圖選到內存設備描述表中,最后把屏幕設備描述表拷貝到內存設備描述表中,終止鼠標捕獲,恢復窗口顯示模式。</p><p>  void CCaptureDlg::OnLButtonUp(UINT nFlags, CPoint point) </p><p>  {//得到鼠標所在處的窗口的區(qū)域寬、高 </p><p>  int nWidt

27、h=rectCapture.Width(); </p><p>  int nHeight=rectCapture.Height(); </p><p>  HDC hdcScreen, hMemDC; </p><p>  HBITMAP hOldBitmap; </p><p>  //建立一個屏幕設備環(huán)境句柄 </p>

28、<p>  hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); </p><p>  hMemDC = CreateCompatibleDC(hdcScreen); </p><p>  //建立一個與屏幕設備環(huán)境句柄兼容、與鼠標所在處的窗口的區(qū)域等大的位圖 </p><p>  hB

29、itmap = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight); </p><p>  // 把新位圖選到內存設備描述表中 </p><p>  hOldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap); </p><p>  // 把屏幕設備描述表拷貝到內存設備描述表

30、中 </p><p>  BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,rectCapture.left,rectCapture.top,SRCCOPY); </p><p>  //取回鼠標所在處的窗口屏幕位圖的句柄 </p><p>  hBitmap =(HBITMAP)SelectObject(hMemDC, hOld

31、Bitmap); </p><p>  DeleteDC(hdcScreen); </p><p>  DeleteDC(hMemDC); </p><p>  MessageBox("屏幕內容已經剪切獲得,請單擊對話框菜單按紐保存為BMP文件!"); </p><p><b>  //終止鼠標捕獲 </b

32、></p><p>  ReleaseCapture(); </p><p>  //恢復窗口顯示模式 </p><p>  ShowWindow(SW_NORMAL); </p><p>  CDialog::OnLButtonUp(nFlags, point);</p><p><b>  }<

33、;/b></p><p>  3.3將抓取的窗口圖片保存為位圖文件存取</p><p>  設計保存函數SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpFileName),并且在前面對話框類里面進行函數聲明。此函數是整個軟件設計當中的技術難點,要特別對BMP位圖文件非常熟悉,BMP文件由文件頭、位圖信息頭、顏色信息和圖形數據四部分組成。BMP

34、文件頭數據結構含有BMP文件的類型、文件大小和位圖起始位置等信息。位圖文件的類型,必須為BM位圖文件的大小,以字節(jié)為單位,位圖文件保留字,必須為0位圖數據的起始位置,以相對于位圖文件頭的偏移量表示,以字節(jié)為單位。BMP位圖信息頭數據用于說明位圖的尺寸等信息。在typedef struct tagBITMAPINFOHEADER結構當中DWORD biSize表示本結構所占用字節(jié)數;LONGbiWidth表示位圖的寬度;以像素為單位LON

35、GbiHeight表示位圖的高度,以像素為單位WORD biPlanes表示目標設備的級別,必須為1;WORD biBitCount表示每個像素所需的位數,必須是1(雙色),4(16色),8(256色)或24(真彩色)之一;DWORD biCompression; </p><p>  {BITMAPINFOHEADER bmiHeader; // 位圖信息頭RGBQUAD bmiColors[1]; //

36、顏色表} BITMAPINFO;位圖數據記錄了位圖的每一個像素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。位圖的一個像素值所占的字節(jié)數: 當biBitCount=1時,8個像素占1個字節(jié);當biBitCount=4時,2個像素占1個字節(jié);當biBitCount=8時,1個像素占1個字節(jié);當biBitCount=24時,1個像素占3個字節(jié);Windows規(guī)定一個掃描行所占的字節(jié)數必須是 4的倍數(即以long為單位),不

37、足的以0填充, 一個掃描行所占的字節(jié)數計算方法: DataSizePerLine= (biWidth* biBitCount+31)/8表示一個掃描行所占的字節(jié)數; DataSizePerLine= DataSizePerLine/4*4表示字節(jié)數必須是4的倍數 ,位圖數據的大小(不壓縮情況下):DataSize= DataSizePerLine* biHeight; 在SaveBitmapToFile()當中首先<

38、/p><p>  3.4軟件界面設計和其它相關功能設計</p><p>  由于本軟件是基于對話框的工程,其界面相對比較單一簡單,那么為了使得界面比較漂亮美觀,我特別進行了對話框的漸變色設計,使界面有夢幻般的感覺。對話框的漸變色效果是在OnPaint()函數中實現(xiàn)的 ,具體實現(xiàn)細節(jié)在這里不多做描述了。在軟件設計的最后收尾階段,實現(xiàn)文件的退出菜單功能設計。圖1是該抓圖軟件的運行界面圖形。<

39、/p><p><b>  (圖1)</b></p><p>  3.5軟件運行功能測試圖</p><p>  啟動工程執(zhí)行程序,出現(xiàn)圖1程序界面時,用鼠標按下左鍵,程序界面便隱藏,于是拖動鼠標開始屏幕抓圖。當鼠標左鍵釋放后,程序會彈出一個MessageBox對話框來提醒您已經抓取了指定窗口的圖片請單擊對話框菜單按鈕保存為指定磁盤路徑的BMP文件,接

40、下來程序窗口出現(xiàn),最后點擊菜單按鈕保存抓取的窗口圖片。</p><p>  圖2就是抓取的全屏位圖。 </p><p><b> ?。▓D2)</b></p><p>  此抓圖軟件不僅僅可以抓取全屏圖案,還可以抓取任意指定窗口的圖形。圖3是 抓取指定小窗口的BMP圖片。</p&g

41、t;<p><b> ?。▓D3)</b></p><p>  當抓圖結束后,可以單擊界面上的菜單退出按鈕安全退出,此時程序又會彈出一個MessageBox對話框提醒您是否確定要退出程序。通過大量的調試和運行,該抓圖軟件運行穩(wěn)定,抓取保存速度比較快,整體性能比較理想。完成了任意指定窗口的界面截取功能及保存功能。</p><p>  4 存在問題和改進意見&

42、lt;/p><p>  在此次屏幕截圖軟件設計當中主要面對三個問題,一是如何知道鼠標在屏幕上的準確位置;二是如何知道欲抓圖的窗口句柄;三是如何對抓到的圖片進行保存的問題。對于問題一,很簡單,利用SetCapture函數便能夠追蹤鼠標的移動,包括在屏幕抓圖程序窗口之外的窗口。應該注意的是,SetCapture的具體功能并不像MSDN中所說的那樣:調用SetCapture一次直到使用ReleaseCapture終止鼠標捕

43、獲前都會起到對鼠標的捕獲作用,實際上,在使用過程中,就會發(fā)現(xiàn),在進行了一次鼠標捕獲之后,SetCapture便失去了作用,這可能是SetCapture函數的一個Bug。所以,在編程時,要不斷地調用SetCapture函數,以保證SetCapture能夠對鼠標進行正確無誤的捕獲。對于問題二,這時會用到一個平時我們不常用的函數:WindowFromPoint,這個函數能夠找出鼠標當前位置所對應的窗口句柄。</p><p&

44、gt;  問題最多當要屬問題三:如何對抓到的圖片進行保存且保存為指定位置的bmp文件,這個是整個程序設計當中的難點也是最麻煩的出了很多棘手的問題,由于需要設計一個這樣的保存函數,限于自身水平就參考了網上同仁編寫的這種功能的函數,于是拿到自己的程序中調用此函數便陷入了尷尬的境地,首先是出現(xiàn)了二三十處語法錯誤經過耐心修改全部搞定,但是執(zhí)行程序,單擊保存按鈕卻無法進行保存,一運行會發(fā)出錯誤報告然后自動退出,經過確定是程序邏輯錯誤,后經過調試是

45、應為在寫這個函數的時候,一個參數有問題,是因為該參數是在前面的一個函數中定義過且為私有變量,后面的函數需要調用這個參數,來獲取屏幕位圖窗口句柄,那么這個參數就需要設置為全局變量,在這里我就犯了這個低級錯誤。接著執(zhí)行程序抓圖保存,但是令人驚訝的是機子接近崩潰的邊緣,運行比“蝸?!边€慢,等大約6-7分鐘后,一切才恢復正常,最后到保存的指定文件中去查看所保存的抓取圖片,讓人吃驚的是保存的圖片大小為655M,怪不得執(zhí)行程序后會那么慢,經過分析問

46、題出在,設置保存為BMP文件得時候,抓取窗口得長寬大小在函數SaveBitmapToFile()中并沒有獲得,那么程序運行得時候就</p><p>  為所抓取的圖片數據沒有獲得,用DEBUG設置斷點調試明顯顯示GetDIBits()的數據值為0,但是始終搞不清楚為什么所獲得的位圖數據值是零,龍滿生老師細心的幫我分析,最后才確定出罪魁禍首是DeleteDC(hDC);該函數用錯了位置,它在GetDIBits()函

47、數調用之前便調用了那么當然獲取的位圖數據為零了,于是調整DeleteDC(hDC)為在GetDIBits()函數調用之后調用,終于解決了這個問題。那么到最后該軟件就算大功告成了。</p><p>  該軟件特別要改經的地方那就是能夠像QQ抓圖那樣任意拖動鼠標,截取任意大小的圖片,并且所見即所抓,不管它是什么東東,游戲畫面也好,電影畫面也好,F(xiàn)LANSH,靜態(tài)圖片等等,像怎么抓就怎么抓。但是限于自身能力有限還有時間

48、的關系,這些更棒功能等以后再實現(xiàn)吧</p><p><b>  5 結束語</b></p><p>  在此論文當中主要介紹 VC++實現(xiàn)屏幕截圖功能的實現(xiàn)基本原理和運用的相關技術詳細介紹了軟件的具體設計步驟,所實現(xiàn)的這個抓圖軟件可以截取整個屏幕,截取指定的窗口,并將截取到的圖像以bmp文件形式保存到指定的路徑下。技術重點在鼠標在屏幕上的準確定位;如何獲取抓圖的窗口句

49、柄;如何對抓到的圖片進行保存的問題。技術難點在如何將所抓取的屏幕窗口保存為磁盤BMP文件形式。</p><p>  在整個設計當中要運用大量的圖形操作函數,特別是在設計保存功能的時候,要對位圖文件結構有相當深刻的了解,通過此次設計自己掌握了很多技術如:追蹤鼠標的移動,如何獲得鼠標所在處的窗口句柄,如何取得屏幕的設備環(huán)境句柄得到鼠標所在處的窗口的區(qū)域寬、高,如何建立一個屏幕設備環(huán)境句柄和與屏幕設備環(huán)境句柄兼容、與鼠

50、標所在處的窗口的區(qū)域等大的位圖,如何把新位圖選到內存設備描述表中,如何把屏幕設備描述表拷貝到內存設備描述表中等等。</p><p>  最后要特別感謝龍滿生老師,在這兩個禮拜的軟件設計當中,龍滿生老師作為我的導師給予了我巨大的幫助和指導,自己在這個過程當中學會了很多很多東西,比如如何分析程序出錯的原因,如何解決問題的方法,特別是我感受到了要想作為一名好的編程人員所應具備的素質,通過老師的指導我還領會了DEBUG斷

51、點調試的妙用,從這里我更深入的理解了程序運行的機制和參數數據間的傳遞以及函數的相互調用。同時增強了自己的編程能力和一些作為編程人員所因具有的耐性和仔細,體會到了溝通協(xié)作的重要性,總之在這兩個禮拜的軟件課程設計當中自己學到了很多很多。</p><p><b>  參考文獻</b></p><p>  1.何東健. 數字圖像處理. 西安:西安電子科技大學出版社,2003&

52、lt;/p><p>  2.楊永國.Visual C++ 6.0實用教程. 北京:清華大學出版社,2004</p><p>  3.張力. Visual C++高級編程. 北京:人民郵電出版社,2002</p><p>  4.《電腦編程技巧與維護》雜志社,Visual C/C++編程精選集錦(數據庫和圖形圖像分冊).北京:科學出版社,2003</p>

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論