我的问题有2个都不是大问题,希望能按序号解答,再次感谢
1.我的截图很小只截取了屏幕左上角一小块。我希望能截取整个屏幕,查了半天也不知道是哪没设置好,贴上代码求解
2.我最后释放HANDLE老是报错说指定了一个无效的句柄,忽略也不会有问题我的原理是客户端自己截取屏幕然后存在临时文件夹中,然后客户端下载文件显示出来,目前下载文件部分代码不存在问题已经测试过,问题不知是出在客户端显示上还是服务端截取上?下面附客户端和服务端相关函数
有些长,麻烦大家了
问题2出错的代码是CloseHandle(pbitmapwithoutfileh);
下面是服务端接收到客户端命令后调入的函数,下面3个函数一个调一个,功能都有注释
DWORD GetScreenProc(COMMAND command,SOCKET client)//屏幕监视
{
char Path[MAX_PATH];
GetTempPath(MAX_PATH,Path);
strcat(Path,"远程屏幕.bmp");
CapScreen(Path);//保存图像到指定路径
COMMAND cmd;
FILEINFO fi;
memset((char*)&cmd,0,sizeof(cmd));
memset((char*)&fi,0,sizeof(fi));
cmd.ID=GetScreen;
CFile file;
int nChunkCount=0;//传输次数
int nLeft;//剩余数据块
if(file.Open((char*)command.lparam,CFile::modeRead|CFile::typeBinary))//typeBinary二进制方式打开
{
int FileLen=file.GetLength();
fi.FileLen=FileLen;//文件长度
strcpy((char*)&fi.FileName,file.GetFileName());//文件名
memcpy((char*)&cmd.lparam,(char*)&fi,sizeof(fi));
send(client,(char*)&cmd,sizeof(cmd),0);
nChunkCount=FileLen/CHUNK_SIZE;
if(FileLen%CHUNK_SIZE!=0)
{
nChunkCount++;
}
char* data=new char[CHUNK_SIZE];//缓存区
for(int i=0;i<nChunkCount;i++)//传输文件
{
if(i+1==nChunkCount)
{
nLeft=FileLen-CHUNK_SIZE*(nChunkCount-1);
}
else
{
nLeft=CHUNK_SIZE;
}
int idx=0;
file.Read(data,nLeft);//读出一块数据
while(nLeft>0)
{
int ret=send(client,&data[idx],nLeft,0);//已传输的字节数
if(ret==SOCKET_ERROR)
{
cout<<"文件传输过程中发生错误!\n";
}
nLeft=nLeft-ret;//剩余字节数
idx=idx+ret;//下次起始地址
}
}
file.Close();
delete[] data;
}
return TRUE;
}
BOOL CapScreen(LPTSTR FileName)//保存图像到指定路径
{
DWORD sizeimage;
HDC hdc=CreateDC("DISPLAY",NULL,NULL,NULL);//创建设备环境
HDC CompatibleHDC=CreateCompatibleDC(hdc);//映射到内存减少读取时间
HBITMAP BmpScreen=CreateCompatibleBitmap(hdc,GetDeviceCaps(hdc,HORZSIZE),GetDeviceCaps(hdc,VERTSIZE));//创建位图
SelectObject(CompatibleHDC,BmpScreen);//将位图映射到设备环境
BitBlt(CompatibleHDC,0,0,GetDeviceCaps(hdc,HORZSIZE),GetDeviceCaps(hdc,VERTSIZE),hdc,0,0,SRCCOPY);//对设备环境区域中的像素进行转换,传送到内存环境
HANDLE pbitmapwithoutfileh=DDBtoDIB(BmpScreen,BI_RGB,0,&sizeimage);//依赖设备位图转化为不依赖设备位图
BITMAPFILEHEADER bfh;//DIB的头文件信息
bfh.bfType=((WORD)('M'<<8|'B'));
bfh.bfSize=sizeimage+54;//54是BITMAPFILEHEADER大小
bfh.bfReserved1=0;
bfh.bfReserved2=0;
bfh.bfOffBits=54;//偏移位数,因为有头文件
HANDLE hFile=CreateFile(FileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);//创建一个位图文件
DWORD dwWrite;
WriteFile(hFile,&bfh,sizeof(BITMAPFILEHEADER),&dwWrite,NULL);//写入头文件
WriteFile(hFile,pbitmapwithoutfileh,bfh.bfSize,&dwWrite,NULL);//写入文件内容
DeleteDC(hdc);
CloseHandle(hFile);
CloseHandle(pbitmapwithoutfileh);
return TRUE;
}
HANDLE DDBtoDIB(HBITMAP bitmap,DWORD dwcompression,HPALETTE hpal,DWORD* sizeimage)//依赖设备位图转化为不依赖设备位图
{
BITMAP bm;
BITMAPINFOHEADER bi;//DIB信息
LPBITMAPINFOHEADER lpbi;
DWORD dwlen;//位图大小
HANDLE hDib;
HANDLE handle;
HDC hdc;
if(hpal==0)
{
hpal=(HPALETTE)GetStockObject(DEFAULT_PALETTE);//得到调色板句柄
}
GetObject(bitmap,sizeof(bm),(LPSTR)&bm);//获得图形的信息
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=bm.bmWidth;
bi.biHeight=bm.bmHeight;
bi.biPlanes=1;//目标设备层数
bi.biBitCount=bm.bmPlanes*bm.bmBitsPixel;//像素位数
bi.biCompression=dwcompression;//压缩方式
bi.biSizeImage=0;//压缩方式决定
bi.biXPelsPerMeter=0;//水平分辨路
bi.biYPelsPerMeter=0;//垂直分辨率
bi.biClrUsed=0;//使用所有的颜色
bi.biClrImportant=0;//使用重要的颜色也是用所有颜色 int ncolors=(1<<bi.biBitCount);//1左移
if(ncolors>256)//256色以上无颜色表
ncolors=0;
dwlen=bi.biSize+ncolors*sizeof(RGBQUAD);//位图大小=信息头+RGBQUAD颜色表
hdc=GetDC(NULL);//得到整个屏幕设备环境句柄
hpal=SelectPalette(hdc,hpal,FALSE);//逻辑调色板加入设备环境
RealizePalette(hdc);//逻辑调色板到系统调色板
hDib=GlobalAlloc(GMEM_FIXED,dwlen);//分配内存空间
if(hDib==NULL)
{
SelectPalette(hdc,hpal,FALSE);//调色板恢复到原先的设备环境
ReleaseDC(NULL,hdc);//释放设备环境
return NULL;
}
lpbi=(LPBITMAPINFOHEADER)hDib;
*lpbi=bi;//DIB信息存储在已分配空间内
GetDIBits(hdc,bitmap,0L,(DWORD)bi.biHeight,NULL,(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);//检取位图的信息,复制到一个缓冲区中
bi=*lpbi;
if(bi.biSizeImage==0)
{
bi.biSizeImage=(((bi.biWidth*bi.biBitCount)+31)&(~31)>>3)*bi.biHeight;//大小必须是4字节的倍数
}
dwlen=dwlen+bi.biSizeImage;
handle=GlobalReAlloc(hDib,dwlen,GMEM_MOVEABLE);
if(handle==NULL)
{
GlobalFree(handle);
SelectPalette(hdc,hpal,FALSE);//调色板恢复到原先的设备环境
ReleaseDC(NULL,hdc);//释放设备环境
return NULL;
}
hDib=handle;
lpbi=(LPBITMAPINFOHEADER)hDib;
int Scannum=GetDIBits(hdc,bitmap,0L,(DWORD)bi.biHeight,(LPBYTE)lpbi+bi.biSize+ncolors*sizeof(RGBQUAD),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);//写入到缓冲区
if(Scannum==0)
{
GlobalFree(hDib);
SelectPalette(hdc,hpal,FALSE);//调色板恢复到原先的设备环境
ReleaseDC(NULL,hdc);//释放设备环境
return NULL;
}
SelectPalette(hdc,hpal,FALSE);//转换后恢复原先设备环境
ReleaseDC(NULL,hdc);//释放设备环境
*sizeimage=bi.biSizeImage;
return hDib;
}客户端显示已下载的图片的函数为
void CSCREENDLG::OnBnClickedScreen1()//显示屏幕
{
// TODO: 在此添加控件通知处理程序代码
char path[MAX_PATH];//保存地址
GetTempPath(MAX_PATH,path);//得到临时文件夹地址
strcat(path,"远程屏幕.bmp");
hwnd=GetDlgItem(IDC_SCREEN);//显示屏幕的句柄
hDesDC=hwnd->GetDC()->m_hDC;//得到环境变量中用于输出的环境变量
hSrcDC=CreateCompatibleDC(hDesDC);//映射到内存减少读取时间
hbitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),path,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);//读入一个独立且不依赖于设备的位图
GetObject(hbitmap,sizeof(BITMAP),&bm);
SelectObject(hSrcDC,hbitmap);//导入到环境变量
hwnd->GetClientRect(&rect);//得到客户区坐标
BitBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,0,0,SRCCOPY);//图像从内存设备环境映射回实际设备环境:直接拷贝SRCCOPY
}