文档的使用, GDI(graphics device interface), 对话框的使用
2.双缓冲
1) 什么时候绘制 WM_PAINT
WM_PAINT –> OnPaint –> OnDraw
2) 在哪里绘制 DC
BeginPaint/EndPaint CPaintDC 绘制区域不超过无效区
GetDC/ReleaseDC CClientDC 绘制区域为整个客户区
GetWindowDC/ReleaseDC CWindowDC 绘制区域为整个窗口
CreateCompatibleDC CDC 内存DC,绘制区域为内存
实例:屏幕截图
BitBlt – 将一个DC中的图片拷贝到另一个DC中
光栅操作
CDC dcSreen;
dcSreen.CreateDC("DISPLAY", NULL, NULL, NULL);
CRect rcClient;
GetClientRect(&rcClient);
3) 如何绘制 – 双缓冲绘图法
响应消息:lbuttondown mousemove lbuttonup
绘制直线的api:MoveTo LineTo
鼠标移出窗口外仍然接受鼠标消息:SetCapture
不再接受窗口外的鼠标消息:ReleaseCapture
双缓冲的步骤:
- \1. 创建内存(兼容)DC
CreateCompatibleDC(pDC)
- 2.创建兼容位图
CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height())
- 3.将兼容位图选入内存DC
SelectObject(&bmp)
- 4.在内存DC中绘图
- 5.将内存DC中的图片拷贝到窗口
pDC->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY)
关于Cimage的截图,微软官方写的:
struct CaptureData
{
BOOL bCaptureFullScreen;
char szCapturePath[MAX_PATH]; // no unicode path support
char szCaptureFilename[MAX_PATH];
};
void WINAPI CaptureScreen(CaptureData* lpData)
{
ASSERT(lpData);
if (!lpData)
return;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
BOOL bStat;
CImage image;
CWnd *pWnd;
CRect rect;
if (lpData->bCaptureFullScreen) {
pWnd = CWnd::GetDesktopWindow();
}
else {
pWnd = CWnd::GetActiveWindow();
}
ASSERT(pWnd);
if (pWnd == NULL)
return;
CWindowDC winDC(pWnd);
pWnd->GetWindowRect(rect);
int nBPP = winDC.GetDeviceCaps(BITSPIXEL) * winDC.GetDeviceCaps(PLANES);
if (nBPP < 24)
nBPP = 24;
bStat = image.Create(rect.Width(), rect.Height(), nBPP); //创建图像
ASSERT(bStat);
if (!bStat)
return;
CImageDC imageDC(image);
//将图像绘制到imageDC 中
::BitBlt(imageDC, 0, 0, rect.Width(), rect.Height(), winDC, 0, 0, SRCCOPY);
CString strTempName = GetTempName(CString(lpData->szCapturePath)); //保存为指定格式和路径中
HRESULT hr = image.Save(strTempName);
if (FAILED(hr)) {
TRACE("Couldn't Save File: %s, %x\n", (LPCTSTR)strTempName, hr);
return;
}
strncpy_s(lpData->szCaptureFilename, MAX_PATH, CT2A(::PathFindFileName(strTempName)), _TRUNCATE);
}
//获取文件名和路径
static CString GetTempName(CString strPath)
{
const int nMin = 0;
const int nMax = 999;
const CString strBase(_T("ScreenCap"));
static int nLastKnown = nMin;
// count up sequentially to make sure we take the next available
// slot
if (strPath.Right(1) != "\\")
strPath += '\\';
bool bFound = false;
CString strPathName;
while (!bFound) {
if (nLastKnown > nMax)
break;
strPathName = strPath + strBase;
strPathName.AppendFormat(_T("%03.3d.png"), nLastKnown++);
HANDLE hFile = ::CreateFile(strPathName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
::CloseHandle(hFile);
bFound = TRUE;
}
}
if (!bFound)
strPathName.Empty();
return(strPathName);
}