关于屏幕截取,发送的问题,高手进来 我在客户端截取屏幕之后,取得是DDB位图,是否需要转换成DIB位图,才能发到服务器?服务器端收到DIB位图之后,是不是可以直接显示DIB位图,要不要转换成DDB格式? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如果能正常收到的话,就可以直接显示DIB 是啊,在转化为DIB的时候压缩的,是压缩的DIB。 一般采用先jpg压缩,再传输,解压,显示 #define MAXXCount 10 //屏幕X方向最多分割块数#define MAXYCount 5 //... Y................#define DestNum 1000 //每块的偏移检测点最大个数COLORREF Colors[MAXXCount][MAXYCount][DestNum];COLORREF BakColors[MAXXCount]{MAXYCount][DestNum];TPoint Dests[DestNum];int Sw;int Sh;int xCount;int yCount;int ItemWidth;int ItemHeight;int Dnum;int Qlity;//得到消息后执行://另外:接收到的数据包中分析出 Dnum ,Qlity//Dnum:偏移观测点数量//Qlity:图象要求质量__fastcall TForm1::CopyScreen(int DNum,int Qlity){ItemWidth=Sw/xCount;ItemHeight=Sh/yCount;Sw=Screen->Width;Sh=Screen->Height;xCount=(Sw>1000)?8:6;yCount=(Sh>1000)?3:2;for (int num1=0;num1 Dests[num1].x=random(ItemWidth);Dests[num1].y=random(ItemHeight);}CatchScreen(DNum,Qlity);}//收到刷屏消息后只执行:CatchScreen(DNum,Qlity);__fastcall TForm1::CatchScreen(int DNum,int Qlity){//函数功能:扫描改变的屏幕区域,并切经过优化处理,最后发送这些区域数据//DNum: 偏移量 Qlity:图象质量HDC dc=GetDC(GetDesktopWindow());Graphics::TBitmap *bm=new Graphics::TBitmap;bm->Width=Sw;bm->Height=Sh;BitBlt(bm->Canvas->Handle,0,0,Sw-1,Sh-1,dc,0,0);int num1,num2,num3;int nowx,nowy;bool Change;bool ItemChange[MAXXCount][MAXYCount];for (num1=0;num1 nowx=ItemWidth*num1;for (num2=0;num2 nowy=ItemHeight*num2;Change=false;for (num3=0;num3 Colors[num1][num2][num3]=bm->Canvas->Pixels[nowx+Dests[num3].x][nowy+Dests[num3].y];if (Colors[num1][num2][num3]!=BakColors[num1][num2][num3]){BakColors[num1][num2][num3]=Colors[num1][num2][num3];ItemChange[num1][num2]=true;}}}}int CNum,MaxCNum;int ChangedNum=0;TRect *Rect;int num4;int MinSize=10000;int m;TRect MinRect;Graphics::TBitmap *bt2=new Graphics::TBitmap;TJPEGImage *j=new TJPEGImage;//************************j->Quality=Qlity;//************************CopyScreenUint CopyScreen;CopyScreenItemUint CopyScreenItem;TMemoryStream *ms=new TMemoryStream;ms->Write(&TcpMsg,sizeof(TcpMsgUint));ms->Write(&CopyScreen,sizeof(CopyScreenUint));do{for (num1=0;num1 for (num2=0;num2 for (num3=num1+1;num3<=xCount;num3++){MaxCNum=0;for (num4=num2+1;num4<=yCount;num4++){ //遍历所有矩形CNum=GetChangedNum(TRect(num1,num2,num3,num4));if (CNum>MaxCNum) MaxCNum=CNum;m=(num3-num1)*(num4-num2);if (2*m-CNum MinSize=2*m-CNum;MinRect=TRect(num1,num2,num3,num4);}}}TMemoryStream *ms;BitBlt(bt2->Canvas->Handle,0,0,ItemWidth-1,ItemHeight-1,bt->Canvas->Handle,0,0);j->Assign(bt2);j->SaveToStream(ms2);CopyScreenItem.Rect=TRect(num1,num2,num3,num4);CopyScreenItem.FileType=JPEGFILE; //JPEGFILE 定义为:#define JPEGFILE 1ms2->Position=0;CopyScreenItem.Length=ms2->Size;ms->Write(&CopyScreenItem,sizeof(ScreenItemUint));ms->CopyFrom(ms2,ms2->Size);ChangedNum++;}while(MaxCNum>0);TcpMsg.Type=MsgCopyScreen;ms->Position=0;TcpMsg.Length=ms->Size-sizeof(TcpMsgUint);CopyScreen.Count=ChangedNum;ms->Write(&TcpMsg,sizeof(TcpMsgUint));ms->Write(&CopyScreen,sizeof(CopyScreenUInt));ms->Position=0;sock->SendStream(ms);} 这个程序把屏幕画面切分为了多个部分,并存储画面为JPG格式,这样压缩率就变的十分的高了。通过这种方法压缩处理过的数据,变得十分小,甚至在屏幕没有改变的情况下,传送的数据量为0,你可以仔细看看 //图形转换HANDLE DDBtoDIB( HBITMAP bitmap) { BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; DWORD dwLen; HANDLE hDib; HANDLE handle; HDC hdc; HPALETTE hPal; 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 = 4; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; int ncolors = (1 << bi.biBitCount); if( ncolors> 256 ) ncolors = 0; dwLen = bi.biSize + ncolors * sizeof(RGBQUAD); hdc = GetDC(NULL); hPal = SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); hDib = GlobalAlloc(GMEM_FIXED,dwLen); if (!hDib){ SelectPalette(hdc,hPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } lpbi = (LPBITMAPINFOHEADER)hDib; *lpbi = bi; GetDIBits(hdc, bitmap, 0L, (DWORD)bi.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS ); bi = *lpbi; if (bi.biSizeImage == 0) { bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight; } dwLen += bi.biSizeImage; if (handle = GlobalReAlloc(hDib, dwLen, GMEM_MOVEABLE)) hDib = handle; else { GlobalFree(hDib); SelectPalette(hdc,hPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } lpbi = (LPBITMAPINFOHEADER)hDib; BOOL bgotbits = GetDIBits( hdc, bitmap, 0L, (DWORD)bi.biHeight, (LPBYTE)lpbi + (bi.biSize + ncolors * sizeof(RGBQUAD)), (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); if( !bgotbits ) { GlobalFree(hDib); SelectPalette(hdc,hPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } SelectPalette(hdc,hPal,FALSE); ReleaseDC(NULL,hdc); return hDib;} //获得桌面图形HBITMAP GetSrcBit(DWORD BitWidth,DWORD BitHeight){ HDC hdcmy,hbufferdc; HBITMAP hBit,hOldBitmap; hdcmy = CreateDC("DISPLAY",NULL,NULL,NULL); hbufferdc = CreateCompatibleDC(hdcmy); hBit = CreateCompatibleBitmap(hdcmy, BitWidth, BitHeight); hOldBitmap = (HBITMAP)SelectObject(hbufferdc, hBit); StretchBlt(hbufferdc, 0, 0, BitWidth, BitHeight, hdcmy, 0, 0,SysWidth,SysHeight, SRCCOPY); hBit = (HBITMAP)SelectObject(hbufferdc, hOldBitmap); DeleteObject(hOldBitmap); ReleaseDC(NULL,hdcmy); ReleaseDC(NULL,hbufferdc); return hBit;}//---------------------------------------------------------------//发送桌面屏幕void SendDesktop() { int BitMsg; LPBYTE plmagePoint; HANDLE hDib; HBITMAP hBit; int BitHeight,BitWidth; //获得桌面宽度和高度 recv(NewSock,(char*)&BitWidth,sizeof(BitWidth)+1,0); recv(NewSock,(char*)&BitHeight,sizeof(BitHeight)+1,0); if (BitWidth > SysWidth) BitWidth = SysWidth; if (BitHeight > SysHeight) BitHeight = SysHeight; //转换为位图形式 hBit = GetSrcBit(BitWidth,BitHeight); hDib = DDBtoDIB(hBit); DWORD bitSize = GlobalSize(hDib); send(NewSock,(char*)&bitSize,sizeof(bitSize)+1,MSG_OOB); recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0); plmagePoint = (LPBYTE)hDib; for(WORD i=0;i<bitSize/US_MAXSIZE;i++) { send(NewSock,(char*)plmagePoint,sizeof(BYTE)*US_MAXSIZE,MSG_OOB); plmagePoint = plmagePoint + US_MAXSIZE; recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0); } if (bitSize%US_MAXSIZE) { send(NewSock,(char*)plmagePoint,sizeof(BYTE)*GlobalSize(hDib)%US_MAXSIZE,MSG_OOB); recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0); } DeleteObject(hBit); GlobalFree(hDib);} 今天编译8个小时没解决的一个未定义编译错误 如何获取COM 组件的路径 ADO是否支持远程数据库访问? 如何安全地杀死线程? 关于continue在while中的问题~~~~~~~~~~!!!!!!!!! vc.net哪里能真正删掉.h和.cpp文件??(至少使得它们在项目中无效) HANDLE hFile 是如何捕获的?我使用FILE打开文件,如何捕获? 问一个简单的对话框问题。。。 再问一次了,关于树控件刷新后要恢复成原来的展开状况的问题,谢谢! 装VC++6.0需要注意点什么吗? 学vc 的郁闷 彪悍的中国人的一天
#define MAXYCount 5 //... Y................
#define DestNum 1000 //每块的偏移检测点最大个数
COLORREF Colors[MAXXCount][MAXYCount][DestNum];
COLORREF BakColors[MAXXCount]{MAXYCount][DestNum];
TPoint Dests[DestNum];
int Sw;
int Sh;
int xCount;
int yCount;
int ItemWidth;
int ItemHeight;
int Dnum;
int Qlity;
//得到消息后执行:
//另外:接收到的数据包中分析出 Dnum ,Qlity
//Dnum:偏移观测点数量
//Qlity:图象要求质量
__fastcall TForm1::CopyScreen(int DNum,int Qlity){
ItemWidth=Sw/xCount;
ItemHeight=Sh/yCount;
Sw=Screen->Width;
Sh=Screen->Height;
xCount=(Sw>1000)?8:6;
yCount=(Sh>1000)?3:2;
for (int num1=0;num1 Dests[num1].x=random(ItemWidth);
Dests[num1].y=random(ItemHeight);
}
CatchScreen(DNum,Qlity);
}
//收到刷屏消息后只执行:
CatchScreen(DNum,Qlity);
__fastcall TForm1::CatchScreen(int DNum,int Qlity){
//函数功能:扫描改变的屏幕区域,并切经过优化处理,最后发送这些区域数据
//DNum: 偏移量 Qlity:图象质量
HDC dc=GetDC(GetDesktopWindow());
Graphics::TBitmap *bm=new Graphics::TBitmap;
bm->Width=Sw;
bm->Height=Sh;
BitBlt(bm->Canvas->Handle,0,0,Sw-1,Sh-1,dc,0,0);
int num1,num2,num3;
int nowx,nowy;
bool Change;
bool ItemChange[MAXXCount][MAXYCount];
for (num1=0;num1 nowx=ItemWidth*num1;
for (num2=0;num2 nowy=ItemHeight*num2;
Change=false;
for (num3=0;num3 Colors[num1][num2][num3]=bm->Canvas->Pixels[nowx+Dests[num3].x][nowy+Dests[num3].y];
if (Colors[num1][num2][num3]!=BakColors[num1][num2][num3]){
BakColors[num1][num2][num3]=Colors[num1][num2][num3];
ItemChange[num1][num2]=true;
}
}
}
}
int CNum,MaxCNum;
int ChangedNum=0;
TRect *Rect;
int num4;
int MinSize=10000;
int m;
TRect MinRect;
Graphics::TBitmap *bt2=new Graphics::TBitmap;
TJPEGImage *j=new TJPEGImage;
//************************
j->Quality=Qlity;
//************************
CopyScreenUint CopyScreen;
CopyScreenItemUint CopyScreenItem;
TMemoryStream *ms=new TMemoryStream;
ms->Write(&TcpMsg,sizeof(TcpMsgUint));
ms->Write(&CopyScreen,sizeof(CopyScreenUint));
do{
for (num1=0;num1 for (num2=0;num2 for (num3=num1+1;num3<=xCount;num3++){
MaxCNum=0;
for (num4=num2+1;num4<=yCount;num4++){ //遍历所有矩形
CNum=GetChangedNum(TRect(num1,num2,num3,num4));
if (CNum>MaxCNum) MaxCNum=CNum;
m=(num3-num1)*(num4-num2);
if (2*m-CNum MinSize=2*m-CNum;
MinRect=TRect(num1,num2,num3,num4);
}
}
}
TMemoryStream *ms;
BitBlt(bt2->Canvas->Handle,0,0,ItemWidth-1,ItemHeight-1,bt->Canvas->Handle,0,0);
j->Assign(bt2);
j->SaveToStream(ms2);
CopyScreenItem.Rect=TRect(num1,num2,num3,num4);
CopyScreenItem.FileType=JPEGFILE; //JPEGFILE 定义为:#define JPEGFILE 1
ms2->Position=0;
CopyScreenItem.Length=ms2->Size;
ms->Write(&CopyScreenItem,sizeof(ScreenItemUint));
ms->CopyFrom(ms2,ms2->Size);
ChangedNum++;
}while(MaxCNum>0);
TcpMsg.Type=MsgCopyScreen;
ms->Position=0;
TcpMsg.Length=ms->Size-sizeof(TcpMsgUint);
CopyScreen.Count=ChangedNum;
ms->Write(&TcpMsg,sizeof(TcpMsgUint));
ms->Write(&CopyScreen,sizeof(CopyScreenUInt));
ms->Position=0;
sock->SendStream(ms);
} 这个程序把屏幕画面切分为了多个部分,并存储画面为JPG格式,这样压缩率就变的十分的高了。通过这种方法压缩处理过的数据,变得十分小,甚至在屏幕没有改变的情况下,传送的数据量为0,你可以仔细看看
HANDLE DDBtoDIB( HBITMAP bitmap)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDib;
HANDLE handle;
HDC hdc;
HPALETTE hPal; 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 = 4;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0; int ncolors = (1 << bi.biBitCount);
if( ncolors> 256 )
ncolors = 0;
dwLen = bi.biSize + ncolors * sizeof(RGBQUAD); hdc = GetDC(NULL);
hPal = SelectPalette(hdc,hPal,FALSE);
RealizePalette(hdc); hDib = GlobalAlloc(GMEM_FIXED,dwLen); if (!hDib){
SelectPalette(hdc,hPal,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
} lpbi = (LPBITMAPINFOHEADER)hDib; *lpbi = bi; GetDIBits(hdc, bitmap, 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS ); bi = *lpbi; if (bi.biSizeImage == 0)
{
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;
} dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDib, dwLen, GMEM_MOVEABLE))
hDib = handle;
else
{
GlobalFree(hDib); SelectPalette(hdc,hPal,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
} lpbi = (LPBITMAPINFOHEADER)hDib; BOOL bgotbits = GetDIBits( hdc, bitmap,
0L,
(DWORD)bi.biHeight,
(LPBYTE)lpbi
+ (bi.biSize + ncolors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi,
(DWORD)DIB_RGB_COLORS); if( !bgotbits )
{
GlobalFree(hDib);
SelectPalette(hdc,hPal,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
} SelectPalette(hdc,hPal,FALSE);
ReleaseDC(NULL,hdc); return hDib;
}
HBITMAP GetSrcBit(DWORD BitWidth,DWORD BitHeight)
{
HDC hdcmy,hbufferdc;
HBITMAP hBit,hOldBitmap; hdcmy = CreateDC("DISPLAY",NULL,NULL,NULL);
hbufferdc = CreateCompatibleDC(hdcmy); hBit = CreateCompatibleBitmap(hdcmy, BitWidth, BitHeight); hOldBitmap = (HBITMAP)SelectObject(hbufferdc, hBit);
StretchBlt(hbufferdc, 0, 0, BitWidth, BitHeight,
hdcmy, 0, 0,SysWidth,SysHeight, SRCCOPY); hBit = (HBITMAP)SelectObject(hbufferdc, hOldBitmap);
DeleteObject(hOldBitmap);
ReleaseDC(NULL,hdcmy);
ReleaseDC(NULL,hbufferdc); return hBit;
}//---------------------------------------------------------------
//发送桌面屏幕
void SendDesktop()
{
int BitMsg;
LPBYTE plmagePoint;
HANDLE hDib;
HBITMAP hBit;
int BitHeight,BitWidth; //获得桌面宽度和高度
recv(NewSock,(char*)&BitWidth,sizeof(BitWidth)+1,0);
recv(NewSock,(char*)&BitHeight,sizeof(BitHeight)+1,0);
if (BitWidth > SysWidth)
BitWidth = SysWidth;
if (BitHeight > SysHeight)
BitHeight = SysHeight; //转换为位图形式
hBit = GetSrcBit(BitWidth,BitHeight); hDib = DDBtoDIB(hBit);
DWORD bitSize = GlobalSize(hDib);
send(NewSock,(char*)&bitSize,sizeof(bitSize)+1,MSG_OOB);
recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0); plmagePoint = (LPBYTE)hDib;
for(WORD i=0;i<bitSize/US_MAXSIZE;i++)
{
send(NewSock,(char*)plmagePoint,sizeof(BYTE)*US_MAXSIZE,MSG_OOB);
plmagePoint = plmagePoint + US_MAXSIZE;
recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0);
}
if (bitSize%US_MAXSIZE)
{
send(NewSock,(char*)plmagePoint,sizeof(BYTE)*GlobalSize(hDib)%US_MAXSIZE,MSG_OOB);
recv(NewSock,(char*)&BitMsg,sizeof(BitMsg)+1,0);
} DeleteObject(hBit);
GlobalFree(hDib);
}