本文由BlueCoder編寫 轉載請說明出處:
http://blog.csdn.net/crocodile__/article/details/9769767
我的郵箱:[email protected] 歡迎大家和我交流編程心得
我的微博:BlueCoder_黎小華 歡迎光臨^_^
Win32學了一段時間了,跟着楊老師的腳步,準備學習MFC,因此最近幾天在複習C++,於是發現有將近一週沒寫博文了……
今天來寫一個較爲簡單、但是比較有意思的東西
不知大家在理髮店理髮的時候注意到一個奇觀沒:
理髮店一般都有兩面對立的鏡子,你仔細一看會發現,兩面鏡子裏面的成像逐漸縮小,並且居中排列,很有意思
盜夢空間中也有一個類似的場景,我截了一個圖:
yes,今天就來做一個這樣的效果,只不過是抓的屏幕
好吧,先來看看程序運行效果,來對比一下:
下面進入主題,剖析實現細節,主要分兩大步:
(1)要對屏幕"工作",在Win32中必須獲取屏幕的hdc。有兩種主要的方式:
1)GetDC(HWND), 傳遞參數NULL——GetDC(NULL)
2)CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
(2)貼圖
獲取環境hdc後,在hdc中會保存屏幕的狀態——相當於屏幕的截圖,只是用bmp保存的
今天貼圖用一個更好的函數StretchBlt,它有一個很好的功能——可以按比例縮放bmp位圖,然後顯示:
BOOL StretchBlt( HDC hdcDest, // handle to destination DC int nXOriginDest, // x-coord of destination upper-left corner int nYOriginDest, // y-coord of destination upper-left corner int nWidthDest, // width of destination rectangle int nHeightDest, // height of destination rectangle HDC hdcSrc, // handle to source DC int nXOriginSrc, // x-coord of source upper-left corner int nYOriginSrc, // y-coord of source upper-left corner int nWidthSrc, // width of source rectangle int nHeightSrc, // height of source rectangle DWORD dwRop // raster operation code );使用方法和BitBlt很類似,應該不用贅述了……
具體核心實現代碼如下:
int cxScreen, cyScreen;//全局變量——屏幕的長寬,用於窗口居中和縮放顯示bmp
hdcCli = BeginPaint(hwnd, &ps);
hdcScr = GetDC(NULL);
//循環3次
i = 0;
while(i<3)
{
//按比例顯示桌面截圖
StretchBlt(hdcCli, 0, 0, cxClient, cyClient, hdcScr, 0, 0, cxScreen, cyScreen, SRCCOPY);
i++;
}
DeleteDC(hdcScr);
EndPaint(hwnd, &ps);
這種方式很簡單,當然我肯定不會簡單用一下這個函數就了事了,這個沒什麼大不了的,下面我在介紹一種使用GDI映射模式+BitBlt來貼bmp位圖,實現效果和上面說的完全一樣
BitBlt函數沒有縮放功能,我就用映射模式來實現縮放功能,縮放的具體實現代碼如下:
hdcCli = BeginPaint(hwnd, &ps);
hdcScr = GetDC(NULL);
SetMapMode(hdcCli, MM_ANISOTROPIC);//設定x、y方向異性模式,就是說x、y方向可以不同
SetWindowExtEx(hdcCli, cxScreen, cyScreen, NULL);//設定窗口範圍
SetViewportExtEx(hdcCli, cxClient, cyClient, NULL);//設定視口範圍
//這樣就能將cxScreen * cyScreen的大小縮放爲cxClient * cyClient的大小,就是將屏幕大小縮小爲客戶區大小
//循環3次
i = 0;
while(i<3)
{
//由於已經在內存中縮放了屏幕bmp位圖,這裏就可直接貼圖
BitBlt(hdcCli, 0, 0, cxScreen, cyScreen, hdcScr, 0, 0, SRCCOPY);//直接顯示
i++;
}
DeleteDC(hdcScr);
EndPaint(hwnd, &ps);
這兩種方式實現的效果完全一樣,多一種方式,多一種思路,這樣才能提高能力……
源代碼下載