用mfc很容易把當前螢幕擷取,並顯示在自己程式的ui上。以對話方塊為例,在執行繪製的單元(比如onpaint)中呼叫下面這個函式就能做到:
bool csrnshotdlg::getmyscreen(
cdc *pdc//
目標dc
)
接下來改造一下,把螢幕截圖先轉換為灰度(gray scale)圖,再顯示出來。轉換灰度圖的公式是,對乙個rgb值,r、g、b分別是其3色分量,計算:
gray = r * 0.299 + g *0.587 + b * 0.114
然後將gray分別替換掉原來的3色分量。到這個地方,很自然想到用setpixel/getpixel來實現。因為要對dc進行操作,當然就不能直接在上面getmyscreen裡邊的dc直接操作了,為此對getmyscreen進行一下改造,並且,為了程式的可讀性,增加乙個converttogray函式負責轉換(與上面**不同的地方用紅色區分):
void converttogray (cdc * pdc)
}
bool csrnshotdlg::getmyscreen(
cdc *pdc//
目標dc
)
效果出來了,但是並不完美。實際上我用setpixelv代替了setpixel,但顯示的速度還是很慢,cpu使用率也很高。如何提高效率呢?直接改dc上附著的點陣圖資料似乎是個好辦法。下面就轉而對cbitmap類物件進行操作。
因為是直接截圖,所以需要先用cdc::getdevicecaps帶bitspixel引數獲得螢幕色深,因為不同色深的點陣圖的儲存方式不同。簡要說明一下:16位色位圖,每個象素佔2位元組;24位色,每個象素佔3位元組;32位色,每個象素佔4位元組儲存空間。我們可以用cbitmap::getbitmapbits函式來獲得位圖資料,這其實是乙個byte陣列。這個陣列的結構,最簡單的是24位色的情況。前面說過了每個象素佔3個位元組,按陣列下標從低到高分別是b、g、r這3色分量,而32位色的情況跟24位色類似,4個位元組只不過多了乙個alpha值。下面就是處理24位色深的converttogray24。
#define bits24(int)(1024 * 768 * 3)
void converttogray24(cbitmap *pbmp)
pbmp->setbitmapbits(bits24, lpbits);
delete lpbits;
}
當getdevicecaps(bitspixel)返回16的時候,又有兩種情況:16位色和15位色。16位色的情況下,位圖陣列使用2位元組儲存資料,其中從高位往低位分別是b、g、r這3色分量按位5:6:5占用。需要用位操作來獲得每個分量的色值:
#define getrvaluex(rgb)((byte)(rgb) & 0x1f)
#define getgvaluex(rgb)((byte)(((rgb) & 0x07e0) >> 5))
#define getbvaluex(rgb)((byte)(((rgb) & 0xf800) >> 11))
#define rgbx(r,g,b) /
((word)(((byte)(r)|((word)((byte)(g))<<5))|(((word)(byte)(b))<<11)))
要注意的是因為綠色分量占用了6bit,其儲存精度是其它兩個分量的2倍,所以在進行後繼的計算的時候公式的因數會有所改變。(另外,使用15位色的介面卡比較少,其儲存規則也是占用2位元組,但是最高位無意義,其餘15位按5:5:5分配,這裡不詳細討論了。)
#define bits16(int)(1024 * 768 * 2)
void converttogray16(cbitmap *pbmp)
pbmp->setbitmapbits(bits16, lpbits);
delete lpbits;
}
最後,第三次改造getmyscreen:
bool csrnshotdlg::getmyscreen(
cdc *pdc//
目標dc
)
pbmp->create***patiblebitmap(&dc, clientrect.width(),clientrect.height());
pmemdc->selectobject(pbmp);
showwindow(sw_hide);
pmemdc->bitblt(0, 0,
clientrect.width(), clientrect.height(),
&dc, 0, 0, srccopy);
switch(pmemdc->getdevicecaps(bitspixel))
pdc->bitblt(0, 0, //
起始位置
clientrect.width(),clientrect.height(),//
寬高 pmemdc, //
源cdc
物件 0, 0,
// 源位置
srccopy//
複製方法
);
pbmp->deleteobject();
pmemdc->deletedc();
delete pbmp;
delete pmemdc;
dc.deletedc();
return true;
}
附,感謝puhuofeie的幫助
Linux下截圖方法!
一 最便捷的方法 1 按下印螢幕鍵,擷取整個桌面 2 按下alt 螢幕鍵,擷取當前視窗 二 命令列截圖 1 import screenshot.jpg 你將可以使用滑鼠選取乙個矩形框。在你放下滑鼠左鍵的那一刻,乙個該矩形框的截圖會以import後面 跟的檔名儲存在當前目錄下。2 scrot d 4 ...
雙屏 多顯示器截圖
截圖程式的原始碼網上到處都有,但是基本都不支援多顯示器。這讓我一度以為支援多顯示器是一件很困難的事情。demo 包含多顯示器支援,視窗高亮,十字放大等 其實多顯示的截圖跟主顯示器的截圖區別並不大,甚至根本不需要enumdisplaymonitors 之類的呼叫。只是因為網上有了原始碼,我們就懶得想了...
Windows Mobile下快速截圖的一種方法
wince下截圖的方法有很多種,這裡介紹一種利用gapi實現的方法。gapi是game api的縮寫,它提供了一系列函式,可以直接對螢幕緩衝區進行讀 寫訪問。雖然現在逐漸被directx mobile取代,但自從2000年首次應用在ppc上後,幾乎所有的移動裝置上都能看見它。gapi主要應用於遊戲開...