青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

幽幽
 
posts - 51,  comments - 28,  trackbacks - 0
一、 簡介

屏幕抓圖程序在處理圖形中應用廣泛。作為Windows XP及以后版本操作系統的圖形處理內核,GDI+在二維幾何圖形處理、圖像顯示與轉換和字符排版等方面簡直是傳統GDI程序員的一種解脫。但是,至少在目前情況下,GDI+尚不能完全代替GDI。與GDI相比,它至少還存在以下不足:

不支持從內存到屏幕的位傳輸操作;

不支持光柵“位運算”操作;

如果程序性能、速度要求比較嚴格,在圖片輸出方面的表現較差時,GDI往往能取代實現高性能的輸出。

本文通過對流行的屏幕抓圖程序工作原理的剖析,力圖向讀者闡明GDI+與GDI各自在圖形處理方面的優缺點,并給出相應的VC++ .NET代碼實現。

    二、 GDI在抓圖中的關鍵作用

    要實現屏幕抓圖,關鍵有兩點:一是獲取圖片所在窗口的窗口句柄,即在何處捕獲圖片;二是保存抓取的圖片,實現這一點正是GDI+的強項。

    對于問題一,可以利用SetCapture函數,它能夠追蹤鼠標指針的移動(包括在屏幕抓圖程序窗口之外的窗口)。在移動鼠標的過程中,它還可以根據鼠標的指針所在位置來判斷當前窗口的窗口句柄。我們還可以使用函數WindowFromPoint,這個函數能夠找出鼠標指針當前位置所對應的窗口句柄。

    使用過知名的抓圖軟件SnagIT的讀者都知道,在選擇抓圖窗口時,鼠標指針所在位置的窗口都會出現加粗的紅色邊框,以提醒目前所選擇的窗口,這個功能實現起來有些復雜。下面介紹在GDI中如何使這個紅色邊框出現。

    【注意】正是由于這個紅色邊框的實現,讀者才能發現GDI+在這方面的弱點。

在GDI中,一個最基本的概念就是設備環境(DC),每一個窗口都具有自己的DC。如果能夠找到窗口的DC,那么,用戶就能夠在該窗口的任何位置繪圖。然而,在屏幕抓圖程序中,由于用戶所選擇的窗口不固定,所以,要想得到鼠標指針所處窗口的DC并不容易。這一問題的答案在于GetDC函數。下面是GetDC的函數聲明:

HDC GetDC(HWND hWnd);

    這里,hWnd是DC對應的窗口句柄。注意,當hWnd為空時,該函數返回的是整個屏幕的設備環境句柄。這就意味著,開發人員可以在屏幕上的任何位置進行任意的繪圖操作。

    在鼠標指針所處的窗口繪圖時,繪圖的目的只是為了提醒用戶目前所選擇的窗口,所以,在繪圖時,必須保證不會破壞窗口原有的畫面。這時可將窗口的繪圖模式設為RS_NOTXORPEN,將畫筆顏色與屏幕顏色進行異或運算之后,再對屏幕顏色取反即可。RS_NOTXORPEN運算方式的特點在于:對同一像素進行兩次RS_NOTXORPEN運算后,像素值并不會發生變化。這樣,在同一個地方進行兩次繪圖后,窗口的畫面并不會發生任何變化。

    【注意】這些功能在GDI+中很難實現。

    三、 編碼實現

由上可知,屏幕抓圖至少分為3個步驟:

    (1) 啟用鼠標指針捕獲。

    (2) 在鼠標指針所在處的窗口進行繪圖,提示抓圖的目標。

    (3) 選定目標窗口時,將目標窗口的畫面保存為自定義的位圖并終止鼠標指針捕獲。

    以下是具體的編程步驟:

    (1)在Visual C++ .NET中按照GDI+程序的框架新建一個基于對話框的項目ScreenCapture,然后準備好一個外形為相機的光標文件(*.cur),將之引入資源管理器(IDC_CAMERA)。接著在CScreenCaptureDlg類中加入以下兩個全局變量:

HWND hwndCapture;

Crect rectCapture;

   (2)通過類向導加入對WM_MOUSEMOVE及WM_LBUTTONUP事件的響應函數,分別如下所示。

void CScreenCaptureDlg::OnMouseMove(UINT nFlags, CPoint point)

{

//如果用戶按隹鼠標左鍵不放,則開始抓取圖片

if(nFlags==MK_LBUTTON){

//隱藏程序窗口,以免影響在抓取時的“視野”

ShowWindow(SW_HIDE);

//載入“照相機”鼠標指針,開始追蹤鼠標指針的移動

HCURSOR cur=LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDC_CAMERA));

SetCursor(cur);

SetCapture();

//獲得鼠標指針所在窗口的句柄

this->ClientToScreen(&point);

hwndCapture=(HWND)::WindowFromPoint(point);

//取得屏幕的設備環境句柄,以便在屏幕的任何位置繪圖

HDC hDC=::GetDC(NULL);

//建立一個紅色的畫筆

HPEN hPen=CreatePen(PS_INSIDEFRAME,6,RGB(255,0,0));

//將繪圖模式設為R2_NOTXORPEN,在繪圖時可以不破壞原有的背景

int nMode=SetROP2(hDC,R2_NOTXORPEN);

HPEN hpenOld=(HPEN)SelectObject(hDC,hPen);

//得到鼠標指針所在窗口的區域

::GetWindowRect(hwndCapture,&rectCapture);

//在鼠標指針所在處的窗口四周畫一紅色的矩形,做為選定時的提示

POINT pt[5];

pt[0]=CPoint(rectCapture.left,rectCapture.top);

pt[1]=CPoint(rectCapture.right,rectCapture.top);

pt[2]=CPoint(rectCapture.right,rectCapture.bottom);

pt[3]=CPoint(rectCapture.left,rectCapture.bottom);

pt[4]=CPoint(rectCapture.left,rectCapture.top);

::Polyline(hDC,pt,5);

//延時后再重繪紅色矩形,這樣不會破壞原有的內容

Sleep(100);

::Polyline(hDC,pt,5);

::SelectObject(hDC,hpenOld);

::ReleaseDC(NULL,hDC);

}

CDialog::OnMouseMove(nFlags, point);

}

void CScreenCaptureDlg::OnLButtonUp(UINT nFlags, CPoint point)

{

// 得到鼠標指針所在窗口的區域寬、高

int nWidth=rectCapture.Width();

int nHeight=rectCapture.Height();

HDC hdcScreen,hMemDC;

HBITMAP hBitmap,hOldBitmap;

//建立一個屏幕設備環境句柄

hdcScreen=CreateDC("DISPLAY",NULL,NULL,NULL);

hMemDC=CreateCompatibleDC(hdcScreen);

//建立一個與屏幕設備環境句柄兼容、與鼠標指針所在窗口的區域等大的位圖

hBitmap=CreateCompatibleBitmap(hdcScreen,nWidth,nHeight);

//把新位圖選到內存設備描述表中

hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);

//把屏幕設備描述表拷貝到內存設備描述表中

BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,rectCapture.left,rectCapture.top,SRCCOPY);

DeleteDC(hdcScreen);

DeleteDC(hMemDC);

//返回位圖句柄

//打開剪貼板,并將位圖拷到剪貼板上

OpenClipboard();

EmptyClipboard();

SetClipboardData(CF_BITMAP,hBitmap);

//關閉剪貼板

CloseClipboard();

MessageBox("屏幕內容已經拷到剪貼板!");

ReleaseCapture();

//恢復窗口顯示模式

ShowWindow(SW_NORMAL);

CDialog::OnLButtonUp(nFlags, point);

}

    至此,一個具有專業效果的屏幕抓圖程序的核心已經搞定。

    四、 用GDI+實現畫面的保存

    經過上面兩步,如果用戶在對話框中按住鼠標左鍵不放,程序便開始“抓圖”。當選擇好抓圖的目標后,松開鼠標左鍵,抓圖的目標窗口的畫面就自動保存到剪貼板中了。但是,把畫面保存到文件中更為重要。如果用GDI的方式來操作,需要對各種類位圖的結構有詳盡的了解,極其麻煩。但如果用GDI+來實現之則極為容易。下面介紹如何將已經抓到的圖片保存到一個BMP文件中。

由上面知,抓圖程序已經得到了所捕獲的窗口的位圖句柄,接下來要將位圖句柄保存為相應的位圖文件。這一切歸功于GDI+的Bitmap類,詳見下列代碼。

void CScreenCaptureDlg::OnLButtonUp(UINT nFlags, CPoint point)

{

//……省略

if(GetSaveFileName(&ofn))

{

CLSID pngClsid;

Bitmap bmp(hBitmap,NULL);

//獲取BMP文件的編碼方式

GetEncoderClsid(L"image/bmp",&pngClsid);//幫助函數

CString tmp(ofn.lpstrFile);

CStringW filename((LPCSTR)tmp);

//保存所截取的屏幕圖片

bmp.Save(filename,&pngClsid);

}

ReleaseCapture();

MessageBox("屏幕內容已經保存到文件中!");

//恢復窗口顯示模式

ShowWindow(SW_NORMAL);

CDialog::OnLButtonUp(nFlags, point);

}

    五、 小結

    本文通過一個專業的屏幕抓圖程序的核心實現,對比分析了GDI與GDI+各自的優缺點。但我們相信,GDI+作為新一代圖形引擎,隨著版本的不斷升級,其遲早要淘汰掉GDI。本人拙見,不足處還望讀者指正。

另外,本文源碼在Windows 2000/VC++.NET 2003環境中調試通過。調試過程中注意:

確保工程對GDI+庫的正確引用:在頭文件stdafx.h中要加入相應引用;在應用程序類的InitInstance成員函數前后及其析構函數中加適當的操作;工程編譯時要加入對gdiplus.lib的引用(“項目”|“添加現有項”,我的機器上是在C:\Program Files\Microsoft Visual Studio.NET\vc7\platformSDK\lib下找到庫文件)。

 

posted on 2008-08-13 23:02 幽幽 閱讀(2039) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理



<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

常用鏈接

留言簿(6)

隨筆分類(35)

隨筆檔案(51)

文章分類(3)

文章檔案(3)

相冊

我的鏈接

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品久久久久中文字幕欢迎你| 欧美午夜精品| 最新成人av网站| 欧美高清视频一区二区| 亚洲大胆人体视频| 亚洲电影激情视频网站| 欧美黄色成人网| 一本色道久久加勒比精品| 一区二区三区久久| 欧美一区二粉嫩精品国产一线天| 99re这里只有精品6| 在线亚洲+欧美+日本专区| 午夜精品理论片| 久久夜色精品国产欧美乱| 欧美激情综合在线| 国产欧美日韩三区| 亚洲三级电影全部在线观看高清| 亚洲大片免费看| 在线亚洲自拍| 久久精品中文字幕一区| 亚洲激情国产精品| 午夜精品久久久| 欧美国产日韩精品| 国产欧美日韩一区| 亚洲人成网站色ww在线| 久久激情久久| 最新国产成人av网站网址麻豆 | 国内精品久久久久久久影视麻豆 | 久久中文字幕一区| 欧美午夜无遮挡| 激情校园亚洲| 亚洲欧美另类久久久精品2019| 狠狠色丁香婷综合久久| 日韩一二三在线视频播| 欧美在线黄色| 9l国产精品久久久久麻豆| 久久亚洲图片| 国产美女诱惑一区二区| 一区二区电影免费观看| 欧美电影免费观看高清| 欧美亚洲自偷自偷| 国产精品久久久久久久久免费| 国产精品丝袜91| 在线综合亚洲欧美在线视频| 欧美激情综合| 久久久青草青青国产亚洲免观| 欧美日本在线一区| 亚洲欧洲一区二区三区久久| 久久亚洲一区二区三区四区| 亚洲欧美综合精品久久成人| 欧美性色综合| 亚洲曰本av电影| 亚洲美女91| 欧美午夜www高清视频| 亚洲一区二区av电影| 亚洲三级影片| 欧美人与性动交α欧美精品济南到 | 亚洲欧洲精品天堂一级| 久热精品在线视频| 欧美一区二区视频在线观看2020| 欧美日韩亚洲网| 中文精品视频| 99视频在线精品国自产拍免费观看 | 亚洲国产日韩欧美一区二区三区| 午夜激情久久久| 亚洲午夜性刺激影院| 国产精品国产一区二区| 亚洲免费网址| 欧美一区综合| 一区二区三区在线观看欧美| 欧美高清免费| 欧美日韩在线观看一区二区| 亚洲欧美成人| 欧美综合77777色婷婷| 在线精品视频免费观看| 欧美国产第一页| 欧美精品日韩综合在线| 亚洲自拍偷拍网址| 久久成人18免费观看| 亚洲国产欧美在线人成| 亚洲美女视频| 国产日韩一区欧美| 亚洲第一精品久久忘忧草社区| 蜜臀av在线播放一区二区三区| 亚洲欧洲视频在线| 亚洲一区二区三区激情| 性18欧美另类| 亚洲嫩草精品久久| 欧美日韩免费观看一区三区| 欧美华人在线视频| 亚洲国产一区二区三区在线播| 久久精品成人| 欧美成人嫩草网站| 午夜亚洲一区| 美女网站久久| 欧美亚洲一区| 欧美激情 亚洲a∨综合| 欧美中文在线字幕| 欧美大片免费观看| 久久精品国产77777蜜臀| 欧美黄色免费网站| 久久琪琪电影院| 国产精品99一区二区| 欧美国产精品一区| 国产精品亚洲а∨天堂免在线| 久久国产福利国产秒拍| 欧美成人性生活| 久久久久国产精品www| 欧美日韩国产在线看| 狂野欧美性猛交xxxx巴西| 国产精品a久久久久| 欧美黄色一区二区| 国产一区二区三区免费不卡| 亚洲日本欧美天堂| 亚洲国产三级在线| 欧美在线观看一区| 午夜精品视频在线| 欧美午夜精品理论片a级按摩| 久久精品二区| 国产精品久久久一区二区三区| 久久人人爽人人| 国产欧美日韩三级| 亚洲免费在线电影| 亚洲一区三区视频在线观看| 欧美成人首页| 亚洲高清视频中文字幕| 国产一区清纯| 午夜视频在线观看一区二区三区| 99精品热6080yy久久| 美脚丝袜一区二区三区在线观看 | 国产精品久久久久久久久久尿| 欧美二区在线| 在线日本欧美| 久久久亚洲国产美女国产盗摄| 亚洲欧美日韩精品久久奇米色影视 | 欧美专区福利在线| 国产精品视频精品| 亚洲欧美日韩视频一区| 亚洲欧美成人| 国产嫩草影院久久久久| 欧美在线观看你懂的| 久久人人爽人人爽| 在线观看91精品国产入口| 久久最新视频| 亚洲巨乳在线| 午夜精品三级视频福利| 国产人久久人人人人爽| 欧美一二三视频| 欧美成人精品h版在线观看| 一区二区欧美国产| 国产精品午夜在线观看| 亚洲在线1234| 久久精品国产一区二区三| 国产精品剧情在线亚洲| 欧美一区网站| 欧美成人午夜77777| 一区二区三区.www| 国产欧亚日韩视频| 久久久www成人免费毛片麻豆| 久久成人资源| 亚洲国产激情| 国产精品成人免费精品自在线观看| 99xxxx成人网| 久久aⅴ国产欧美74aaa| 在线看国产一区| 欧美视频在线观看视频极品| 亚洲欧美电影在线观看| 免费成人av在线| 亚洲视频在线观看网站| 国产嫩草一区二区三区在线观看 | 久久国产精品第一页| 欧美国产视频日韩| 亚洲午夜久久久久久久久电影院 | 男人的天堂亚洲| 亚洲午夜女主播在线直播| 老色鬼久久亚洲一区二区| 亚洲天堂网站在线观看视频| 激情五月综合色婷婷一区二区| 欧美激情视频网站| 欧美一区1区三区3区公司| 亚洲国产一区在线| 久久精品视频网| 亚洲一区尤物| 亚洲激情一区二区| 国产精品色婷婷久久58| 欧美精品一区二区在线播放| 久久精品成人一区二区三区| 亚洲天堂免费观看| 亚洲人成人77777线观看| 久久久精品久久久久| 亚洲午夜激情| 最近中文字幕mv在线一区二区三区四区| 欧美极品在线播放| 久久精品国产亚洲高清剧情介绍| 亚洲伦理在线免费看| 欧美电影美腿模特1979在线看| 欧美在线视频观看| 午夜在线一区| 亚洲免费在线视频一区 二区| 亚洲国产清纯|