作者:zavier | 来源:互联网 | 2023-08-30 05:12
分别调用windows api函数及CVI自带函数,完成对GRAPH界面的截图
界面设计如下图,右侧为graph控件的位置信息,调用API函数是完成对于选择窗口的固定位置进行截图,调用CVI自带函数则是针对控件。
}//Windows API截图
int CVICALLBACK printByAPI (int panel, int control, int event,void *callbackData, int eventData1, int eventData2)
{char filePath[500];switch (event){case EVENT_COMMIT:FileSelectPopup ("c:\\Users\\Administrator\\Desktop", "*.bmp", "", "", VAL_SAVE_BUTTON, 0, 0, 1, 1, filePath);SetWaitCursor(1);Delay(0.1);CaptureImage (FindWindowA(NULL,"demo"),filePath);MessagePopup("","");SetWaitCursor(0);break;}return 0;
}/*** GDI 截取指定窗口* * 参数 hwnd 要截屏的窗口句柄* 参数 FilePath 截图存放目录**/
int CaptureImage(HWND hwnd, CHAR *FilePath)
{HDC hdcWindow;HDC hdcMemDC = NULL;HBITMAP hbmScreen = NULL;BITMAP bmpScreen;RECT rcClient;BITMAPFILEHEADER bmfHeader; BITMAPINFOHEADER bi;DWORD dwBmpSize;HANDLE hDIB;CHAR *lpbitmap;HANDLE hFile;DWORD dwSizeofDIB;DWORD dwBytesWritten;hdcWindow = GetWindowDC(hwnd); // 截图目标窗口DC
// hdcWindow = GetDC(hwnd); // 截图DC// 创建兼容内存DChdcMemDC = CreateCompatibleDC(hdcWindow); if(!hdcMemDC){MessagePopup("","CreateCompatibleDC has failed");goto done;}// 获取客户端区域用于计算大小GetClientRect(hwnd, &rcClient);// 设置延展模式SetStretchBltMode(hdcWindow, HALFTONE);// 来源 DC 是整个屏幕而目标 DC 是当前的窗口 (HWND)
/* if(!StretchBlt(hdcWindow, //-----------注释原因:不需要压缩位图,又不截取全屏0,0, rcClient.right, rcClient.bottom, hdcScreen, 0,0,GetSystemMetrics (SM_CXSCREEN),GetSystemMetrics (SM_CYSCREEN),SRCCOPY)){MessagePopup("","StretchBlt has failed");goto done;}
*/ // 通过窗口DC 创建一个兼容位图hbmScreen = CreateCompatibleBitmap(hdcWindow,400, 300//--位图宽高);if(!hbmScreen){MessagePopup("","CreateCompatibleBitmap Failed");goto done;}// 将位图块传送到我们兼容的内存DC中SelectObject(hdcMemDC,hbmScreen);/*---------------------------注释原因:截取软件部分界面,需要设定来源DC的坐标以及目标DC的宽高,保留原代码以观赏 if(!BitBlt(hdcMemDC, // 目的DC0,0, // 目的DC的 x,y 坐标rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, // 目的 DC 的宽高hdcWindow, // 来源DC0,0, // 来源DC的 宽高SRCCOPY)) // 粘贴方式{MessagePopup("","BitBlt has failed");goto done;}*/ if(!BitBlt(hdcMemDC, // 目的DC0,0, // 目的DC的 x,y 坐标400, 300, // 目的 DC 的宽高hdcWindow, // 来源DC50,50+26, // 来源DC的宽高SRCCOPY)) // 粘贴方式{MessagePopup("","BitBlt has failed");goto done;}// 获取位图信息并存放在 bmpScreen 中GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmpScreen.bmWidth; bi.biHeight = bmpScreen.bmHeight; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0;dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;// 在 32-bit Windows 系统上, GlobalAlloc 和 LocalAlloc 是由 HeapAlloc 封装来的// handle 指向进程默认的堆. 所以开销比 HeapAlloc 要大hDIB = GlobalAlloc(GHND,dwBmpSize); lpbitmap = (char *)GlobalLock(hDIB); // 获取兼容位图的位并且拷贝结果到一个 lpbitmap 中.GetDIBits(hdcWindow, // 设备环境句柄hbmScreen, // 位图句柄0, // 指定检索的第一个扫描线(UINT)bmpScreen.bmHeight, // 指定检索的扫描线数lpbitmap, // 指向用来检索位图数据的缓冲区的指针(BITMAPINFO *)&bi, // 该结构体保存位图的数据格式DIB_RGB_COLORS // 颜色表由红、绿、蓝(RGB)三个直接值构成);// 创建一个文件来保存文件截图hFile = CreateFile(FilePath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);// 将 图片头(headers)的大小, 加上位图的大小来获得整个文件的大小dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);// 设置 Offset 偏移至位图的位(bitmap bits)实际开始的地方bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); // 文件大小bmfHeader.bfSize = dwSizeofDIB; // 位图的 bfType 必须是字符串 "BM"bmfHeader.bfType = 0x4D42; //BM dwBytesWritten = 0;WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);// 解锁堆内存并释放GlobalUnlock(hDIB); GlobalFree(hDIB);// 关闭文件句柄CloseHandle(hFile);// 清理资源
done:DeleteObject(hbmScreen);DeleteObject(hdcMemDC);ReleaseDC(hwnd,hdcWindow);return 0;
}