實現功能
- 將灰度圖內存數據畫到控件上
- 原始灰度圖的寬高與控件寬高不相同
- 在畫到控件上之前要在原始的灰度圖上做一些效果,如疊加文字、畫效果圖形等
上代碼
void ShowFrameOnCtl(HWND hWnd, unsigned char* frame, int w, int h)
{
HDC hdcPicControl;
// GetDC() need to be ReleaseDC
hdcPicControl = ::GetDC(hWnd);
RECT rcPic;
::GetClientRect(hWnd, &rcPic);
int nWidth = rcPic.right - rcPic.left;
int nHeight = rcPic.bottom - rcPic.top;
HDC hCompatibleDC = CreateCompatibleDC(hdcPicControl);
HBITMAP hCompatibleBitmap = CreateCompatibleBitmap(hdcPicControl, w, h);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hCompatibleDC, hCompatibleBitmap);
// 灰度圖
BITMAPINFOHEADER BitmapInfo;
BITMAPINFO *_BitmapInfo = (BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER) * 256 * sizeof(RGBQUAD)];
memset(_BitmapInfo, 0, sizeof(BITMAPINFOHEADER));
BitmapInfo.biSize = 40;
BitmapInfo.biPlanes = 1;
BitmapInfo.biBitCount = 8;
BitmapInfo.biClrImportant = 0;
BitmapInfo.biCompression = BI_RGB;
BitmapInfo.biXPelsPerMeter = 0;
BitmapInfo.biYPelsPerMeter = 0;
BitmapInfo.biClrUsed = 256;
BitmapInfo.biClrImportant = 0;
BitmapInfo.biWidth = 0;
BitmapInfo.biHeight = 0;
/*把BMP位圖信息頭中的數據讀取到位圖信息結構中去.*/
memcpy(_BitmapInfo, &BitmapInfo, sizeof(BITMAPINFOHEADER));
RGBQUAD *rgb = (RGBQUAD*)((BYTE*)_BitmapInfo + sizeof(BITMAPINFOHEADER));
for (int i = 0; i < 256; ++i) {
rgb[i].rgbBlue = rgb[i].rgbGreen = rgb[i].rgbRed = i;
}
_BitmapInfo->bmiHeader.biWidth = w;
_BitmapInfo->bmiHeader.biHeight = -1 * h;
_BitmapInfo->bmiHeader.biSizeImage = 0;
_BitmapInfo->bmiHeader.biBitCount = 8;
_BitmapInfo->bmiHeader.biClrUsed = 256;
SetStretchBltMode(hCompatibleDC, COLORONCOLOR);
StretchDIBits(hCompatibleDC,
0, 0, w, h,
0, 0, w, h,
frame, _BitmapInfo, DIB_RGB_COLORS, SRCCOPY);
//在內存DC上畫一些效果
if (!m_disableDraw)
drawView(hCompatibleDC, w, h);
delete _BitmapInfo;
SetStretchBltMode(hdcPicControl, COLORONCOLOR);
::StretchBlt(hdcPicControl, 0, 0, nWidth, nHeight, hCompatibleDC, 0, 0, w, h, SRCCOPY);
SelectObject(hCompatibleDC, hOldBitmap);
DeleteObject(hCompatibleBitmap);
DeleteDC(hCompatibleDC);
// ReleaseDC of hdcPicControl
ReleaseDC(hWnd, hdcPicControl);
}
小結
創建內存位圖
HBITMAP CreateCompatibleBitmap(HDC hdc,int nWidth,int nHeight)
nWidth 和 nHeight不一定要和hdc的大小一樣, 這樣可以讓創建的位置和原始圖像一致,最後內存DC拷貝到原始DC時,縮放一下即可
背景知識
什麼是DC
device context is a structure that defines a set of graphic objects and their associated attributes, as well as the graphic modes that affect output. The graphic objects include a pen for line drawing, a brush for painting and filling, a bitmap for copying or scrolling parts of the screen, a palette for defining the set of available colors, a region for clipping and other operations, and a path for painting and drawing operations. The remainder of this section is divided into the following three areas.
這是微軟官方的解釋,翻譯一下:
DC全稱Device Contexts, 意爲設備上下文,它是一個定義了一系列圖形對象及其屬性發生的數據結構,其他也包括一些影響顯示的圖形模式。 圖形對象包括畫筆(畫直線)、畫刷(填充)、位圖(拷貝或滾動屏幕的其他部分)、調色板(定義了一系列顏色)、裁剪區、路徑。
另外,設備上下文是設備無關的,DC主要是給用戶一致的繪圖體驗,它是用戶與真實設備驅動之間一個橋樑,用來屏蔽設備驅動等底層細節。
雙緩衝
雙緩衝是一種方法,它可以用來避免畫圖閃爍的問題。如果直接在畫布上畫圖,每次都要先擦除再繪製,這一過程需要時間,如果顯示的刷新頻率很快或繪製過程很慢(比較CPU性能差),就會讓用戶看到這一中間過程,造成閃爍現象。
Win32中雙緩衝的原理是先創建一個內存DC,畫圖繪製在內存DC上,繪製好後將內存DC直接拷貝到原始DC上,這樣就避免了閃爍。
就醬~