能把滚动视图保存为位图的sdk的方法 我想把自己客户区显示的图形保存为位图直接把客户区域显示的数据保存为位图时只能保存当前可见的从网上搜到的关于保存.打开位图资料的都没提到在sdk中滚动视图保存的问题怎样才能把整个客户区的全部保存(包括不可见的部分)谢谢大家了! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 既然是自己画的就好办了,使用双缓冲就可以数据先画到缓冲区上(位图),然后再bitblt拷贝到显示设备上。这样就能保存一个完整的图形了 谢谢回答阿。不过我还是不太明白。现在我把我写的代码贴出来吧,请大家帮着指点一下。这个代码只能保存可见部分的。BOOL DibSaveImage (PTSTR pstrFileName, HWND hwnd, int cxClient,int cyClient,int cxtotalSize){ BOOL bSuccess ; BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; DWORD dwBytesWritten1,dwBytesWritten2,dwBytesWritten3 ; HANDLE hFile ; HDC hdc, hdcMemBack; BITMAP btm; DWORD size; LPSTR lpData; HBITMAP hBitmapBack,hOld; HGDIOBJ hBrushFill=NULL; hdc=GetDC(hwnd); hdcMemBack=CreateCompatibleDC(hdc); hBitmapBack=CreateCompatibleBitmap(hdc,cxClient*cxtotalSize,cyClient); hOld=SelectObject (hdcMemBack, hBitmapBack) ; Rectangle(hdcMemBack,0,0,cxClient*cxtotalSize,cyClient); BitBlt(hdcMemBack,0, 0,cxClient*cxtotalSize, cyClient, hdc, 0, 0, SRCCOPY); SelectObject(hdcMemBack,hOld); //GetBitmap(&btm); GetObject (hBitmapBack, sizeof (BITMAP), &btm) ; size = btm.bmWidthBytes * btm.bmHeight; lpData = (LPSTR)GlobalAlloc(GPTR, size); bih.biBitCount = btm.bmBitsPixel; bih.biClrImportant = 0; bih.biCompression = 0; bih.biHeight = btm.bmHeight; bih.biPlanes = 1; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biSizeImage = size; bih.biWidth = btm.bmWidth; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; GetDIBits(hdcMemBack,hBitmapBack,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS); bfh.bfReserved1 = bfh.bfReserved2 = 0; bfh.bfType = ((WORD)('M'<< 8)|'B'); bfh.bfSize = 54 + size; bfh.bfOffBits = 54; ReleaseDC (hwnd, hdc) ; hFile = CreateFile (pstrFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ; if (hFile == INVALID_HANDLE_VALUE) return FALSE ; bSuccess = WriteFile (hFile, &bfh, 14, &dwBytesWritten1, NULL) ; WriteFile (hFile, &bih, bih.biSize, &dwBytesWritten2, NULL) ; WriteFile (hFile, lpData, size, &dwBytesWritten3, NULL) ; CloseHandle (hFile) ; GlobalFree(lpData); DeleteObject(hBitmapBack); if (!bSuccess &&(dwBytesWritten2 != bih.biSize)&&(dwBytesWritten3 != size)) { DeleteFile (pstrFileName) ; return FALSE ; } return TRUE ;} 这部分代码看不出什么问题,关键看你是怎么绘制到窗口DC上的。因为你拷贝位图是从窗口DC上拷贝的。如果你窗口DC本身就是只绘制了全部位图的一部分,那么你拷贝回来的也只是一部分了。你能把你WM_PAINT的处理部分贴出来么? 好的我现在把我的WM_PAINT消息部分和实现画图的函数贴出来。不过我的函数写得较乱,各位高人见笑了。谢谢大家。case WM_PAINT: // Clear the window //InvalidateRect (hwnd, NULL, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; si.cbSize = sizeof (si) ; si.fMask = SIF_POS ; GetScrollInfo (hwnd, SB_HORZ, &si) ; iHorzPos=si.nPos; Draw(hwnd,lParam,cxClient, cyClient,iShape,iHorzPos,ifHorzPos,cxChar,noLine,cyChar); ifHorzPos=iHorzPos; EndPaint (hwnd, &ps) ; return 0 ;下面是Draw()函数的具体内容void Draw(HWND hwnd,LPARAM lParam,int cxClient, int cyClient,int iShape,int iHs,int ifHs,int cw,int noLine,int ch){ HDC hdc; //HPEN hPen; hdc=GetDC(hwnd); SetIsotropic (hdc, cxClient, cyClient) ; switch(iShape) { case 0: //如果是电压 LineGraphYay( hdc,lParam ); LineGraphx(hdc,lParam,apt2,iHs,ifHs,cw,noLine); SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ; LinePointYa(hdc); DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; break; case 1: //如果是电流 LineGraphLiuy( hdc,lParam,ch ); LineGraphx(hdc,lParam,bpt2,iHs,ifHs,cw,noLine); SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ; LinePointLiu(hdc); DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; break; case 2: //如果是电阻 LineGraphZuy( hdc,lParam ); LineGraphx(hdc,lParam,dpt2,iHs,ifHs,cw,noLine); SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ; LinePointZu(hdc); DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; break; case 3: //如果是功率 LineGraphGongy( hdc,lParam ); LineGraphx(hdc,lParam,cpt2,iHs,ifHs,cw,noLine); SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ; LinePointGong(hdc); DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; break; } ReleaseDC(hwnd,hdc);} 果然,好像你的paint只是画了可视区域部分。 既然是这样,那没有理由不用双缓冲了。既能提高绘图效率又不用抓图。双缓冲这里有介绍,http://www.vckbase.com/document/viewdoc/?id=1612 同意booklove(纳海行云) 用双缓冲,既能提高效率,又能根据位图大小方便控制滚动条。 directshow播放 rmvb SoftWare Test 怎样才能捕获所有的键盘和鼠标,以及程序间传递的message vc++6.0写了一个基于CHtmlView 的程序,怎样才能使它在每次运行时不自动打开一个微软的MSDN的网页? 一个关于SelectObject的问题 p2p打洞可以1对多个远程IP么? 请问是不是通过一进程句柄获得应用程序窗口句柄的? 新手之VC第一个问题(关于添加变量到视图类的问题) 关于一个C++下载指定服务器目录文件的问题~ CBN_SELCHANGE的问题,急啊! 如何打开后缀名为“.ocx”的文件 如何在VB中调用这种类型的API函数???
数据先画到缓冲区上(位图),然后再bitblt拷贝到显示设备上。
这样就能保存一个完整的图形了
BOOL DibSaveImage (PTSTR pstrFileName, HWND hwnd, int cxClient,int cyClient,int cxtotalSize)
{
BOOL bSuccess ;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
DWORD dwBytesWritten1,dwBytesWritten2,dwBytesWritten3 ; HANDLE hFile ;
HDC hdc, hdcMemBack;
BITMAP btm;
DWORD size;
LPSTR lpData;
HBITMAP hBitmapBack,hOld;
HGDIOBJ hBrushFill=NULL; hdc=GetDC(hwnd);
hdcMemBack=CreateCompatibleDC(hdc);
hBitmapBack=CreateCompatibleBitmap(hdc,cxClient*cxtotalSize,cyClient);
hOld=SelectObject (hdcMemBack, hBitmapBack) ;
Rectangle(hdcMemBack,0,0,cxClient*cxtotalSize,cyClient);
BitBlt(hdcMemBack,0, 0,cxClient*cxtotalSize, cyClient, hdc, 0, 0, SRCCOPY);
SelectObject(hdcMemBack,hOld);
//GetBitmap(&btm);
GetObject (hBitmapBack, sizeof (BITMAP), &btm) ;
size = btm.bmWidthBytes * btm.bmHeight;
lpData = (LPSTR)GlobalAlloc(GPTR, size);
bih.biBitCount = btm.bmBitsPixel;
bih.biClrImportant = 0;
bih.biCompression = 0;
bih.biHeight = btm.bmHeight;
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = size;
bih.biWidth = btm.bmWidth;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
GetDIBits(hdcMemBack,hBitmapBack,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
bfh.bfReserved1 = bfh.bfReserved2 = 0;
bfh.bfType = ((WORD)('M'<< 8)|'B');
bfh.bfSize = 54 + size;
bfh.bfOffBits = 54;
ReleaseDC (hwnd, hdc) ;
hFile = CreateFile (pstrFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ; if (hFile == INVALID_HANDLE_VALUE)
return FALSE ; bSuccess = WriteFile (hFile, &bfh, 14, &dwBytesWritten1, NULL) ;
WriteFile (hFile, &bih, bih.biSize, &dwBytesWritten2, NULL) ;
WriteFile (hFile, lpData, size, &dwBytesWritten3, NULL) ;
CloseHandle (hFile) ;
GlobalFree(lpData);
DeleteObject(hBitmapBack);
if (!bSuccess &&(dwBytesWritten2 != bih.biSize)&&(dwBytesWritten3 != size))
{
DeleteFile (pstrFileName) ;
return FALSE ;
}
return TRUE ;
}
因为你拷贝位图是从窗口DC上拷贝的。如果你窗口DC本身就是只绘制了全部位图的一部分,那么你拷贝回来的也只是一部分了。你能把你WM_PAINT的处理部分贴出来么?
case WM_PAINT: // Clear the window
//InvalidateRect (hwnd, NULL, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
si.cbSize = sizeof (si) ;
si.fMask = SIF_POS ;
GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos=si.nPos;
Draw(hwnd,lParam,cxClient, cyClient,iShape,iHorzPos,ifHorzPos,cxChar,noLine,cyChar);
ifHorzPos=iHorzPos;
EndPaint (hwnd, &ps) ;
return 0 ;
下面是Draw()函数的具体内容
void Draw(HWND hwnd,LPARAM lParam,int cxClient, int cyClient,int iShape,int iHs,int ifHs,int cw,int noLine,int ch)
{ HDC hdc;
//HPEN hPen;
hdc=GetDC(hwnd);
SetIsotropic (hdc, cxClient, cyClient) ;
switch(iShape)
{
case 0: //如果是电压
LineGraphYay( hdc,lParam );
LineGraphx(hdc,lParam,apt2,iHs,ifHs,cw,noLine);
SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ;
LinePointYa(hdc);
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
break; case 1: //如果是电流
LineGraphLiuy( hdc,lParam,ch );
LineGraphx(hdc,lParam,bpt2,iHs,ifHs,cw,noLine);
SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ;
LinePointLiu(hdc);
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
break; case 2: //如果是电阻
LineGraphZuy( hdc,lParam );
LineGraphx(hdc,lParam,dpt2,iHs,ifHs,cw,noLine);
SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ;
LinePointZu(hdc);
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
break; case 3: //如果是功率
LineGraphGongy( hdc,lParam );
LineGraphx(hdc,lParam,cpt2,iHs,ifHs,cw,noLine);
SelectObject (hdc, CreatePen (PS_SOLID, 0, RGB (255, 0, 0))) ;
LinePointGong(hdc);
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
break;
}
ReleaseDC(hwnd,hdc);
}
双缓冲这里有介绍,http://www.vckbase.com/document/viewdoc/?id=1612
用双缓冲,既能提高效率,又能根据位图大小方便控制滚动条。