1 HANDLE DDBtoDIB(HBITMAP bitmap,DWORD dwCompression,HPALETTE hPal,DWORD *sizeimage) 2 { 3 BITMAP bm; 4 BITMAPINFOHEADER bi; 5 LPBITMAPINFOHEADER lpbi; 6 DWORD dwLen; //颜色位图的大小 7 HANDLE hDib; 8 HANDLE handle; 9 HDC hdc; 10 11 //不支持BI_BITFIELDS类型 12 if( dwCompression == BI_BITFIELDS ) 13 return NULL; 14 15 //如果调色板为空,则用默认调色板 16 if (hPal==NULL) 17 hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE ); 18 19 //获取位图信息 20 GetObject(bitmap,sizeof(bm),(LPSTR)&bm); 21 22 //初始化位图信息头 23 bi.biSize = sizeof(BITMAPINFOHEADER); 24 bi.biWidth = bm.bmWidth; 25 bi.biHeight = bm.bmHeight; 26 bi.biPlanes = 1; 27 bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel; 28 bi.biCompression = dwCompression; 29 bi.biSizeImage = 0; 30 bi.biXPelsPerMeter = 0; 31 bi.biYPelsPerMeter = 0; 32 bi.biClrUsed = 0; 33 bi.biClrImportant = 0; 34 35 //计算信息头及颜色表大小 36 int ncolors = (1 << bi.biBitCount); //左移 37 if( ncolors> 256 ) 38 ncolors = 0; 39 dwLen = bi.biSize + ncolors * sizeof(RGBQUAD); //颜色表的大小 40 41 hdc = GetDC(NULL); 42 hPal = SelectPalette(hdc,hPal,FALSE); //将逻辑调色板(放在内存中的调色板)选入设备上下文中,第三个函数设为FALSE是为了不让逻辑设备调色板将物理调色板覆盖 43 RealizePalette(hdc); 44 45 //为信息头及颜色表分配内存 46 hDib = GlobalAlloc(GMEM_FIXED,dwLen); //分配指定的内存空间 47 48 if (!hDib){ 49 SelectPalette(hdc,hPal,FALSE); //如果失败,则需要恢复原先的调色板 50 ReleaseDC(NULL,hdc); 51 return NULL; 52 } 53 54 lpbi = (LPBITMAPINFOHEADER)hDib; 55 *lpbi = bi; 56 //调用 GetDIBits 计算图像大小 57 GetDIBits(hdc, bitmap, 0L, (DWORD)bi.biHeight, 58 (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS ); 59 60 bi = *lpbi; 61 //图像的每一行都对齐(32bit)边界 62 if (bi.biSizeImage == 0){ 63 bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 64 * bi.biHeight; 65 if (dwCompression != BI_RGB) 66 bi.biSizeImage = (bi.biSizeImage * 3) / 2; 67 } 68 69 //重新分配内存大小,以便放下所有数据 70 dwLen += bi.biSizeImage; 71 if (handle = GlobalReAlloc(hDib, dwLen, GMEM_MOVEABLE)) 72 hDib = handle; 73 else{ 74 GlobalFree(hDib); 75 76 //重选原始调色板 77 SelectPalette(hdc,hPal,FALSE); 78 ReleaseDC(NULL,hdc); 79 return NULL; 80 } 81 82 //获取位图数据 83 lpbi = (LPBITMAPINFOHEADER)hDib; 84 85 //最终获得的DIB 86 BOOL bgotbits = GetDIBits( hdc, bitmap, 87 0L, //扫描行起始处 88 (DWORD)bi.biHeight, //扫描行数 89 (LPBYTE)lpbi //位图数据地址 90 + (bi.biSize + ncolors * sizeof(RGBQUAD)), 91 (LPBITMAPINFO)lpbi, //位图信息地址 92 (DWORD)DIB_RGB_COLORS); //颜色板使用RGB 93 94 if( !bgotbits ) 95 { 96 GlobalFree(hDib); 97 98 SelectPalette(hdc,hPal,FALSE); 99 ReleaseDC(NULL,hdc); 100 return NULL; 101 } 102 103 SelectPalette(hdc,hPal,FALSE); 104 ReleaseDC(NULL,hdc); 105 *sizeimage=bi.biSizeImage; 106 return hDib; //得到设备无依赖位图 107 }
这是将依赖设备位图变为不依赖设备位图
1 BOOL CutScreen(LPTSTR FileName) 2 { 3 DWORD sizeimage; 4 HDC hdc=CreateDC("DISPLAY",NULL,NULL,NULL); 5 HDC CompatibleHDC= CreateCompatibleDC(hdc); 6 HBITMAP BmpScreen=CreateCompatibleBitmap(hdc,GetDeviceCaps(hdc,HORZSIZE),GetDeviceCaps(hdc,VERTSIZE)); 7 SelectObject(CompatibleHDC,BmpScreen); 8 BitBlt(CompatibleHDC,0,0,GetDeviceCaps(hdc,HORZSIZE),GetDeviceCaps(hdc,VERTSIZE),hdc,0,0,SRCCOPY); 9 10 HANDLE pbitmapwithoutfileh=DDBtoDIB(BmpScreen,BI_RGB,0,&sizeimage); 11 12 //设置位图信息头结构 13 BITMAPFILEHEADER bfh; 14 bfh.bfType=((WORD)('M'<<8)|'B'); //将单位设为MB 15 bfh.bfReserved1=0; 16 bfh.bfReserved2=0; 17 bfh.bfSize=54+sizeimage; 18 bfh.bfOffBits=54; 19 20 //创建位图文件 21 HANDLE hFile=CreateFile(FileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); 22 23 DWORD dwWrite; 24 // 写入位图文件头 25 WriteFile(hFile,&bfh,sizeof(BITMAPFILEHEADER),&dwWrite,NULL); 26 // 写入位图文件其余内容 27 WriteFile(hFile,pbitmapwithoutfileh,bfh.bfSize,&dwWrite,NULL); 28 DeleteDC(hdc); 29 30 CloseHandle(CompatibleHDC); 31 32 return TRUE; 33 34 }
得到位图
1 DWORD GetScreenProc(COMMAND command,SOCKET client) 2 { 3 char path[MAX_PATH]; 4 GetTempPath(MAX_PATH,path); // 得到保存在临时文件夹中的图片 5 strcat(path,"Screen.bmp"); //得到位图的完整路径 6 CutScreen(path); 7 8 COMMAND cmd; 9 FILEINFO fi; 10 memset((char*)&cmd,0,sizeof(cmd)); 11 memset((char*)&fi,0,sizeof(fi)); 12 13 cmd.ID=GetScreen; 14 15 CFile file; 16 int nChunkCount=0; 17 if(file.Open((char*)command.lparam ,CFile::modeRead | CFile::typeBinary) ) //打开文件 18 { 19 cout<<command.lparam<<endl; 20 int FileLen=(int)file.GetLength(); //获取文件长度 21 fi.FileLen=FileLen; 22 strcpy((char*)fi.FileName,file.GetFileName()) ; //获取文件名称 23 memcpy((char*)&cmd.lparam ,(char*)&fi,sizeof(fi)); 24 send(client,(char*)&cmd,sizeof(cmd),0); 25 nChunkCount=FileLen/CHUNK_SIZE; //计算文件发送次数 26 if(FileLen%CHUNK_SIZE!=0) 27 { 28 nChunkCount++; 29 } 30 char *date=new char [CHUNK_SIZE]; //创建数据缓存区 31 for(int i=0;i<nChunkCount;i++) 32 { 33 int nLeft; 34 if(i+1==nChunkCount) 35 { 36 nLeft=FileLen-CHUNK_SIZE*(nChunkCount-1); 37 } 38 else 39 { 40 nLeft=CHUNK_SIZE; 41 } 42 int idx=0; 43 file.Read(date,CHUNK_SIZE); //将内容保存到date中 44 while(nLeft>0) 45 { 46 int ret=send(client,&date[idx],nLeft,0); //发送文件 47 if(ret==SOCKET_ERROR) 48 { 49 cout<<"文件下载过程发生错误!"<<endl; 50 break; 51 } 52 nLeft-=ret; 53 idx+=ret; 54 } 55 } 56 cout<<"文件传输完成!"<<endl; 57 file.Close(); 58 delete []date; 59 } 60 return 0; 61 }
文件传输。