MFC繪圖總結-螢幕截屏,擷取DIB/DDB圖形Pixel,dibddb

來源:互聯網
上載者:User

MFC繪圖總結-螢幕截屏,擷取DIB/DDB圖形Pixel,dibddb
1.       對當前的Screen進行Copy螢幕,擷取BITMAP

對當前螢幕Copy,需要擷取當前螢幕的HDC,

一種是直接從螢幕DC抓原始圖。

一種是然後使用相容MemDC進行抓圖,然後可以附加圖形的相關處理,如調整大小,如把滑鼠繪製上去等。

(注:如果是對當前程式Copy螢幕的話,傳入GetDC參數使用 this->getsafehwnd())

(注:如果對指定視窗Copy螢幕的話,可以用Spy++擷取視窗HWND,然後傳入GetDC)

 

對於從程式抓原始圖的方式比式比較簡單,例如:

// 擷取當前螢幕HDCHDC hScreenDC = ::GetDC(NULL);// 直接擷取當前DC對應的BITMAPHBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);

對於使用相容DC抓圖的例子如下,例如:

// 擷取當前螢幕HDCHDC hScreenDC = ::GetDC(NULL);// 建立相容HDCHDC hMemDC = ::CreateCompatibleDC(hScreenDC)// 建立相容位元影像HBITMAP hbm = CreateCompatibleBitmap(hScreenDC, width, height);// 為MemDC選中相容為圖HBITMAP oldbm = (HBITMAP) SelectObject(hMemDC, hbm);// 複製圖片像素內容BitBlt(hMemDC, 0, 0, width, height, hScreenDC, left, top, SRCCOPY); // 如果需要繪製滑鼠資訊的話{//Draw the CursorICONINFO iconinfo ;BOOL ret;ret= GetIconInfo( hcur,  &iconinfo ); if (ret) {xPoint.x -= iconinfo.xHotspot;xPoint.y -= iconinfo.yHotspot;//need to delete the hbmMask and hbmColor bitmaps//otherwise the program will crash after a while after running out of resourceif (iconinfo.hbmMask) DeleteObject(iconinfo.hbmMask);if (iconinfo.hbmColor) DeleteObject(iconinfo.hbmColor);}::DrawIcon( hMemDC,  xPoint.x,  xPoint.y, hcur); }// 設定回原有的DC綁定位元影像SelectObject(hMemDC,oldbm);

 

2.       擷取DDB圖形Pixel

DDB-Device dependency bitmap裝置依賴圖形

因為當前Bitmap都是通過DC擷取的,所以都是DDB類型的圖形。

通過CBitmap的函數GetBitmapBits,擷取到相關bits內容,或者也可以使用GetBitmap擷取整個BITMAP結構資訊。

但擷取到的這個pixel資訊是和當前device相關的,例如device是24位色/32位色/自下而上繪製的/使用顏色掩碼,則擷取到的pixel也是這種的,

注: 此處CBitmap為DDB圖形,不能使用CImage進行CImage::GetBits擷取Pixel,詳見CImage:: IsDIBSection說明。同時,如果要儲存圖形的話,可以借用CImage:: Save來儲存圖形。

 

 例如:

// 綁定hbmpCBitmap bitmap;Bitmap.attach(hBmp);// 申請記憶體byte pBuffer = new [width * 4 * height];// 擷取bits資訊Bitmap. GetBitmapBits(pBuffer);

 

 

3.       擷取DIB圖形Pixel

DIB-Device Independency Bitmap裝置無關圖形

這類圖形,本身結構中具備了圖形顏色位元/顏色表/顏色掩碼說明相關的資訊,所以就可以不依賴於從社備中查詢這些資訊,也稱為裝置無關圖形。

從HBitmap擷取DIB圖形的函數常用GetDIBits。

GetDIBBits一方面可以用於查詢出當前裝置的結構資訊,填入DIB頭資訊BITMAPINFO說明中;

另一方面,可以指定BITMAPINFO/指定圖形格式,從Bitmap中轉換出指定格式的圖形資訊。

所以它的用法有兩種:

1.      一種是擷取Device中的格式,然後填入到BItmapInfo,然後基於該BitmapInfo,擷取Pixel資訊

2.      另一種是,直接指定Bitmapinfo,擷取基於指定格式轉換後Pixsel資訊

 

例如,我們兼或考慮這兩種,先擷取裝置BitmapInfo,然後對格式進行修改,再擷取修改格式後的圖形Pixel

// 初始化空白PBITMAPINFOLPBITMAPINFO lpBitmapInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD));memset(lpBitmapInfo, 0, sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD));lpBitmapInfo->bmiHeader.biSize = sizeof(lpBitmapInfo->bmiHeader);// lpvBits使用NULL查詢位元影像DIB資訊if (GetDIBits(hMemDC, hBmp, 0, 0, NULL, lpBitmapInfo, DIB_RGB_COLORS)){         // 修改格式,使用修改後的格式獲資料Pixel資料lpBitmapInfo->bmiHeader.biCompression = BI_RGB;         lpBitmapInfo->bmiHeader.biBitCount = 24;         // 查詢位元影像DIB資訊         GetDIBits(hMemDC, (HBITMAP)cBitmap.GetSafeHandle(), 0, nHeight, pBuffer, lpBitmapInfo, DIB_RGB_COLORS);}// 處理完畢刪除頭資訊delete lpBitmapInfo;


 


怎用MFC編寫一個程式,獲得整個螢幕的並儲存為bmp格式?

代碼 大概就是這樣 有幾個關鍵函數仔細一下,要是要完整代碼呢留言
CDC memDC;
CBitmap memBitmap,*pOldBitmap;
CWindowDC dc(GetDesktopWindow());
memDC.CreateCompatibleDC(&dc);
int nWidth,nHeight;
/* nWidth=GetSystemMetrics(SM_CXSCREEN);
nHeight=GetSystemMetrics(SM_CYSCREEN);*/
CRect rect;
GetDesktopWindow()->GetWindowRect(rect);
ClientToScreen(&rect);
nWidth=rect.Width();
nHeight=rect.Height();
memBitmap.CreateCompatibleBitmap(&dc,nWidth,nHeight);
pOldBitmap=memDC.SelectObject(&memBitmap);
// memDC.StretchBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,rect.Width(),rect.Height(),SRCCOPY);
memDC.BitBlt(0,0,nWidth,nHeight,&dc,0,0,SRCCOPY);

BITMAPFILEHEADER BMFhead;
BITMAPINFOHEADER BMIhead;
BMFhead.bfReserved1=0;
BMFhead.bfReserved2=0;
BMFhead.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BMFhead.bfSize=BMFhead.bfOffBits+nWidth*nHeight*4;
BMFhead.bfType=0x4d42;

BMIhead.biBitCount=32;
BMIhead.biClrImportant=0;
BMIhead.biClrUsed=0;
BMIhead.biSizeImage=0;
BMIhead.biXPelsPerMeter=0;
BMIhead.biYPelsPerMeter=0;
BMIhead.biCompression=BI_RGB;
BMIhead.biHeight=nHeight;
BMIhead.biPlanes=1;
BMIhead.biSize=sizeof(BITMAPINFOHEADER);
BMIhead.biWidth=nWidth;

DWORD dwSize=nWidth*nHeight*4;
BYTE *pData=new BYTE[dwSize];
GetDIBits(memDC.m_hDC,(HBITMAP)memBitmap.m_hObject,0,nHeight,pData,(LPBITMAPINFO)&BMIhead,DIB_RGB_COLORS);

CFile file;
file.Open("test.bmp",CFile::modeCreate | CFile::modeWrite);
file.Write(&BMFhead,sizeof(BITMAPFILEHEADER));
file.Writ......餘下全文>>
 
螢幕監控 mirror?

電腦螢幕映像的截取在螢幕的錄製、電腦遠端控制以及多媒體教學軟體中都是關鍵術,基於Windows作業系統有多種截屏方法,研究的重點集中在如何快速有效截取DBI(Device-Independent Bitmap)格式的螢幕圖形資料。現在商業軟體流行的截屏技術主要採取的Api Hook技術,但這種技術一次截屏仍有較大的時間消耗,這樣就對運行軟體的硬體仍有較多的限制,而且是一種非標準的技術,不為微軟公司所推薦。

1截屏技術

1.1使用api hook技術

使用api hook技術截屏基於一下的原理;多數螢幕圖形的繪製都是通過調用使用者態gdi32.dll中的繪圖函數實現的,如果利用api hook技術攔截系統中所有對這些函數的調用,就可以得到螢幕圖形重新整理或變化的地區座標;然後使用api函數bitblt將重新整理或者變化後的螢幕地區的ddb格式的位元影像拷貝到記憶體中,接著使用函數getbits將ddb位元影像轉換為dbi位元影像,最後壓縮、儲存或者傳輸。

這種方案只有捕捉到變化,才進行截屏。這樣每次截屏都是有效操作。每次(第一次除外)僅截取了栓新或變化部分,從根本上解決了資料量大的問題。但是這種技術仍然有一下缺點:1實際截屏採用的api函數,截取的是ddb位元影像,要經過一次格式轉換,耗時較大。2如果螢幕變化地區矩形的座標r1、r2、……rn相繼到達,為了不是螢幕變化的資訊丟失,通常不是逐個截取,而是將矩形座標合并,這樣就可以截取並未變化的地區,不經增加截屏的時間消耗,而且產生冗餘資料。3該技術不支援directdraw技術,由於應用程式可能使用directdraw驅動程式進行直接操縱顯示記憶體、硬體位塊轉移,硬體重疊和交換表面等圖形操作,而不必進行gdi調用,所以此時api hook技術將失去效用,不能捕捉螢幕變化。4api hook技術在螢幕取詞,遠端控制和多媒體教學中都有實際的應用,但是這種技術是一種非標準的技術,微軟公司並不推薦使用。

1.2 使用圖形驅動技術

該技術的原理:應用程式調用win32 gdi 函數進行圖形輸出請求,這個請求通過核心模式gdi發送。核心模式gdi把這些請求發送到相應的圖形驅動程式。如,顯示器驅動程式,通訊流。現將該技術詳細解釋如下:

(1)顯示器驅動輸出一系列裝置驅動程式介面DDI(Device Driver Interface)函數供GDI調用。資訊通過這些進入點的輸入/輸出參數在GDI和驅動程式之間傳遞。

(2) 在顯示器驅動載入時,GDI調用顯示器驅動程式函數DrvEnableDriver,在這裡我們向GDI提供顯示器驅動支援的,可供GDI調用的DDI函數進入點,其中部分時將要Hook的圖形輸出函數。

(3) 在GDI調用函數DrvEnableDriver成功返回後,GDI調用顯示器驅動的DrvEnablePDEV函數,在這裡可以設定顯示器的顯示模式,然後建立一個PDEV結構,PDEV結構是物理顯示器的邏輯表示。

(4) 在成功建立PDEV結構之後,顯示驅動為視頻硬體建立一個表面,該表面可以是標準的DIB位元影像管理表面,然後驅動程式使該表面與一個PDEV結構相關聯,這樣顯示驅動支援的所有繪畫操作都將在該DIB位元影像表面上進行。

(5) 當應用程式調用使用者態GDI32.DLL中的繪圖函數發出圖形請求時,該請求將圖形引擎通過相應的DDI函數發送到顯示驅動,顯示驅動程式將這次圖形變化事件通知應用程式。

(6) ......餘下全文>>
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.