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时,缩放一下即可
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上,这样就避免了闪烁。
就酱~