急!!^_^★★★★★MFC实现视屏捕捉,传输显示的相关技术 学期末的一个MFC项目,想做一个软件:描述:局域网内,在一台机器上用行该软件,实现捕捉当前屏幕,然后传输到其他机器上在另一个辅助软件上显示。我想了解一下其中用到的技术,希望可以得到比较具体的介绍!形势比较急,希望大家可以帮忙!不胜感激!!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 涉及到WinSock套接字编程,图像传输。获取当前桌面并保存为bitmap结构。网上搜索“局域网监控软件”的代码。 www.codeproject.com上面找找。记得有一个这样的软件,只不过里面用的大部分是SDK。功能比楼主要求的还多。 谢谢KevinJHoo,英文网站,找起来困难啊,大家帮帮忙! bo2000,很强的,有源码,我放到csdn下载资源里面了,还有几个类似的,你去下载看看。 http://download.csdn.net/hicsdn/sxcong在这里,前三个都是类似的 谢谢 sxcong 非常感谢,大家再帮忙提供些资源!^_^ 谢谢! 我的blog里面有一个捕捉屏幕的函数1捕捉屏幕图像2压缩3传输4解压5显示 要代码么 我帖:(我自己的啊 呵呵)/* * 发送和接收图像数据的函数 */BOOL SendData(SOCKET *ptalk,BYTE * pdata,int datalen,BYTE * tempdata,int templen,int w,int h){ ZeroMemory(tempdata,templen); if(templen < datalen) return FALSE; //先压缩 int ret = compress2(tempdata,(unsigned long *)&templen,pdata,datalen,Z_BEST_SPEED); if(templen > datalen) //无用就是看看 AfxMessageBox("压缩后变大了"); if(ret != Z_OK) return FALSE; myhead head; head.w = w; head.h = h; head.datalen = datalen; head.clen = templen; ret = ::send(*ptalk,(char *)&head,sizeof(head),0); //发送头 if(ret <= 0) return FALSE; int left = templen; int pos = 0; while(left > 0) { ret = ::send(*ptalk,(char *)tempdata+pos,left,0); //发送数据 if(ret < 0) return FALSE; pos += ret; left -= ret; } CString temp; temp.Format("send byte %d",pos); OutputDebugString(temp); return TRUE;}BOOL RecvData(SOCKET *ptalk,BYTE *pdata,int *pdatalen,BYTE * tempdata,int templen,int *w,int *h){ ZeroMemory(tempdata,templen); myhead head; int ret = ::recv(*ptalk,(char *)&head,sizeof(head),0); //先接收头部 if(ret <= 0) return FALSE; *w = head.w; //得到图的长和宽 *h = head.h; int left = head.clen; int pos = 0; while(left > 0) { ret = ::recv(*ptalk,(char *)tempdata+pos,left,0); //接收数据部分 if(ret <= 0) return FALSE; pos += ret; left -= ret; } if(pos != head.clen) { CString temp; temp.Format("pos = %d,head.clen = %d",pos,head.clen); OutputDebugString(temp); return FALSE; } ret = uncompress(pdata,(unsigned long *)pdatalen,tempdata,head.clen); if(ret != Z_OK) return FALSE; return TRUE;}//执行操作的函数BOOL XOR(char *a,char *b,char *res,int len) //对数据进行抑或{ for(int i = 0;i < len;i++) res[i] = a[i]^b[i]; return TRUE;}BOOL GetScreenCaps(int *x,int *y) //得到屏幕的分辨率{ HDC hScrDC; hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); *x = GetDeviceCaps(hScrDC, HORZRES); *y = GetDeviceCaps(hScrDC, VERTRES); DeleteObject(hScrDC); return TRUE;}/*将鼠标光标画到指定的地方去*/BOOL DrawMouse(HDC hdc,HCURSOR hcursor){ POINT CursorPos; ICONINFO IconInfo;// hcursor = ::GetCursor(); // If the mouse cursor handle is invalid then forget it if (hcursor == NULL) return FALSE; // Get the cursor position if (!GetCursorPos(&CursorPos)) return FALSE; // Translate position for hotspot if (GetIconInfo(hcursor, &IconInfo)) { CursorPos.x -= ((int) IconInfo.xHotspot); CursorPos.y -= ((int) IconInfo.yHotspot); if (IconInfo.hbmMask != NULL) DeleteObject(IconInfo.hbmMask); if (IconInfo.hbmColor != NULL) DeleteObject(IconInfo.hbmColor); } // Draw the cursor DrawIconEx( hdc, // handle to device context CursorPos.x, CursorPos.y, // hcursor, // handle to icon to draw 0,0, // width of the icon 0, // index of frame in animated cursor NULL, // handle to background brush DI_NORMAL | DI_COMPAT // icon-drawing flags ); return TRUE;}//取屏幕数据,lpRect指定取屏幕的范围,len指定buf的大小//// 当buf不为NULL且长度足够拷贝数据时,返回图片数据大小// 当buf为NULL或者长度不够拷贝数据时,返回图片数据大小// 当执行失败时返回0unsigned GetScrnData(LPRECT lpRect, unsigned char * buf, unsigned len){ HDC hScrDC, hMemDC; // 屏幕和内存设备描 述表 HBITMAP hBitmap, hOldBitmap; // 位图句柄 // 位图宽度和高度 int iWidth, iHeight; iWidth = lpRect->right- lpRect->left; iHeight = lpRect->bottom - lpRect->top; //为屏幕创建设备描述表 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); // 获得屏幕分辨率 int xScrn, yScrn; xScrn = GetDeviceCaps(hScrDC, HORZRES); yScrn = GetDeviceCaps(hScrDC, VERTRES); //为屏幕设备描述表创建兼容的内存设备描述表 hMemDC = CreateCompatibleDC(hScrDC); hBitmap = CreateCompatibleBitmap(hScrDC, iWidth,iHeight); hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); StretchBlt(hMemDC, 0, 0, iWidth, iHeight, hScrDC, 0, 0, xScrn,yScrn, SRCCOPY); /*这里把鼠标的图标画到图像中去*/ if(buf && len) { // DrawMouse(hMemDC); HCURSOR cur = ::GetCursor(); POINT curPos; GetCursorPos(&curPos); DrawIcon(hMemDC,curPos.x,curPos.y,cur); } // 创建位图头 BITMAPINFO bmpInfo; ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = iWidth; bmpInfo.bmiHeader.biHeight = iHeight; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 24; bmpInfo.bmiHeader.biCompression = BI_RGB; //图片信息 if (0 == GetDIBits(hMemDC, hBitmap, 0, iHeight, NULL, &bmpInfo, DIB_RGB_COLORS)) { MessageBox(NULL,"GetDIBits Fail !","ERROR",MB_OK); return 0; } //当接收缓冲为空或者,长度不够时返回需要的长度 if (NULL == buf || len < bmpInfo.bmiHeader.biSizeImage) { // return bmpInfo.bmiHeader.biSizeImage; goto hah; } //把图片数据拷至缓冲中去 GetDIBits(hMemDC, hBitmap, 0, iHeight, buf, &bmpInfo, DIB_RGB_COLORS); hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);hah: int erro = DeleteObject(hBitmap); erro = DeleteDC(hScrDC); erro = DeleteDC(hMemDC); // DeleteObject(hBitmap); // 返回位图句柄 return bmpInfo.bmiHeader.biSizeImage;}void DisplayPicture(HDC hdc,char *pdata,int datalen,int s_w,int s_h,int w,int h) //显示图像{ BITMAPINFO bmpInfo; ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = 0; bmpInfo.bmiHeader.biHeight = 0; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 24; bmpInfo.bmiHeader.biCompression = BI_RGB; bmpInfo.bmiHeader.biSizeImage = datalen; bmpInfo.bmiHeader.biWidth = w; bmpInfo.bmiHeader.biHeight = h; StretchDIBits(hdc,0,0,s_w,s_h, 0,0,w,h,pdata,&bmpInfo, DIB_RGB_COLORS,SRCCOPY);}BOOL DisposeFun(CServerDlg *pdlg){ SOCKET *ptalk = &pdlg->m_talk; int w,h; GetScreenCaps(&w,&h); RECT rect; rect.left = 0; rect.top = 0; rect.right = 1024; rect.bottom = 768; int datalen = BITMAPSIZE; BYTE *pdata = new BYTE[datalen]; ZeroMemory(pdata,datalen); int templen = BITMAPSIZE; BYTE *tempdata = new BYTE[templen]; ZeroMemory(tempdata,templen); int xorlen = BITMAPSIZE; BYTE *xordata = new BYTE[xorlen]; ZeroMemory(xordata,xorlen); int sorlen = BITMAPSIZE; BYTE *sordata = new BYTE[sorlen]; ZeroMemory(sordata,sorlen); int reallen; reallen = GetScrnData(&rect,NULL,0); if(datalen < reallen) return FALSE; GetScrnData(&rect,pdata,datalen); memcpy(sordata,pdata,reallen); int ret = SendData(ptalk,pdata,reallen,tempdata,templen,rect.right,rect.bottom); DWORD newtime,oldtime,count; while(pdlg->m_bisSubWork) { oldtime = GetTickCount(); GetScrnData(&rect,pdata,datalen); XOR((char *)sordata,(char *)pdata,(char *)xordata,reallen); memcpy(sordata,pdata,reallen); ret = SendData(ptalk,xordata,reallen,tempdata,templen,rect.right,rect.bottom); if(!ret) break; newtime = GetTickCount(); count = oldtime - newtime; if(count < 100) Sleep(100 - count); } pdlg->m_bisSubWork = FALSE; ::closesocket(*ptalk); delete []pdata; delete []tempdata; delete []xordata; delete []sordata; return TRUE;}要给分啊 我不容易啊 我的图像传输是这样:先抓 1张图 发送 然后抓下一张 与第一张进行疑惑 把疑惑的结果发过去(发送之前都是要压缩的,我用的是zip压缩算法) 然后将这张图保存为第一张图 以后 都这样处理 虽然可能处理上耗费些时间 但是网络的负担小很多 ADO 执行 插入 出错 怎么像任务管理器一样,得到当前的网络使用情况呢? 关于拖动程序的问题 ★★★★求一简单编程题★★★★ 从网上下了些代码,控件如何有效更快速的使用? 为什么我无法改变字体的颜色? 如何用shgetfileinfo取得某种类型的图标? 在执行CoUninitialize()时出错,该怎样解决? 一个函数 等差数列的第m项为n,n项为m,m+n项的值是多少? 如何向IHTMLInputElement发送模拟键盘消息? 谁能把ProcessExplorer里面的各种进程内存信息解释清楚?
网上搜索“局域网监控软件”的代码。
在这里,前三个都是类似的
1捕捉屏幕图像
2压缩
3传输
4解压
5显示
/*
* 发送和接收图像数据的函数
*/
BOOL SendData(SOCKET *ptalk,BYTE * pdata,int datalen,BYTE * tempdata,int templen,int w,int h)
{
ZeroMemory(tempdata,templen); if(templen < datalen)
return FALSE;
//先压缩
int ret = compress2(tempdata,(unsigned long *)&templen,pdata,datalen,Z_BEST_SPEED);
if(templen > datalen) //无用就是看看
AfxMessageBox("压缩后变大了");
if(ret != Z_OK)
return FALSE;
myhead head;
head.w = w;
head.h = h;
head.datalen = datalen;
head.clen = templen;
ret = ::send(*ptalk,(char *)&head,sizeof(head),0); //发送头
if(ret <= 0)
return FALSE;
int left = templen;
int pos = 0;
while(left > 0)
{
ret = ::send(*ptalk,(char *)tempdata+pos,left,0); //发送数据
if(ret < 0)
return FALSE;
pos += ret;
left -= ret;
}
CString temp;
temp.Format("send byte %d",pos);
OutputDebugString(temp);
return TRUE;
}BOOL RecvData(SOCKET *ptalk,BYTE *pdata,int *pdatalen,BYTE * tempdata,int templen,int *w,int *h)
{
ZeroMemory(tempdata,templen); myhead head;
int ret = ::recv(*ptalk,(char *)&head,sizeof(head),0); //先接收头部
if(ret <= 0)
return FALSE; *w = head.w; //得到图的长和宽
*h = head.h; int left = head.clen;
int pos = 0;
while(left > 0)
{
ret = ::recv(*ptalk,(char *)tempdata+pos,left,0); //接收数据部分
if(ret <= 0)
return FALSE;
pos += ret;
left -= ret;
}
if(pos != head.clen)
{
CString temp;
temp.Format("pos = %d,head.clen = %d",pos,head.clen);
OutputDebugString(temp);
return FALSE;
}
ret = uncompress(pdata,(unsigned long *)pdatalen,tempdata,head.clen);
if(ret != Z_OK)
return FALSE; return TRUE;
}//执行操作的函数BOOL XOR(char *a,char *b,char *res,int len) //对数据进行抑或
{
for(int i = 0;i < len;i++)
res[i] = a[i]^b[i];
return TRUE;
}
BOOL GetScreenCaps(int *x,int *y) //得到屏幕的分辨率
{
HDC hScrDC;
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
*x = GetDeviceCaps(hScrDC, HORZRES);
*y = GetDeviceCaps(hScrDC, VERTRES);
DeleteObject(hScrDC); return TRUE;
}
/*将鼠标光标画到指定的地方去*/
BOOL DrawMouse(HDC hdc,HCURSOR hcursor)
{
POINT CursorPos;
ICONINFO IconInfo;// hcursor = ::GetCursor();
// If the mouse cursor handle is invalid then forget it
if (hcursor == NULL)
return FALSE;
// Get the cursor position
if (!GetCursorPos(&CursorPos))
return FALSE;
// Translate position for hotspot
if (GetIconInfo(hcursor, &IconInfo))
{
CursorPos.x -= ((int) IconInfo.xHotspot);
CursorPos.y -= ((int) IconInfo.yHotspot);
if (IconInfo.hbmMask != NULL)
DeleteObject(IconInfo.hbmMask);
if (IconInfo.hbmColor != NULL)
DeleteObject(IconInfo.hbmColor);
}
// Draw the cursor
DrawIconEx(
hdc, // handle to device context
CursorPos.x, CursorPos.y, //
hcursor, // handle to icon to draw
0,0, // width of the icon
0, // index of frame in animated cursor
NULL, // handle to background brush
DI_NORMAL | DI_COMPAT // icon-drawing flags
); return TRUE;
}
//取屏幕数据,lpRect指定取屏幕的范围,len指定buf的大小
//
// 当buf不为NULL且长度足够拷贝数据时,返回图片数据大小
// 当buf为NULL或者长度不够拷贝数据时,返回图片数据大小
// 当执行失败时返回0
unsigned GetScrnData(LPRECT lpRect, unsigned char * buf, unsigned len)
{
HDC hScrDC, hMemDC; // 屏幕和内存设备描 述表
HBITMAP hBitmap, hOldBitmap; // 位图句柄
// 位图宽度和高度
int iWidth, iHeight;
iWidth = lpRect->right- lpRect->left;
iHeight = lpRect->bottom - lpRect->top;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
// 获得屏幕分辨率
int xScrn, yScrn;
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
hBitmap = CreateCompatibleBitmap(hScrDC, iWidth,iHeight);
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
StretchBlt(hMemDC, 0, 0, iWidth, iHeight, hScrDC, 0, 0, xScrn,yScrn, SRCCOPY);
/*这里把鼠标的图标画到图像中去*/
if(buf && len)
{
// DrawMouse(hMemDC);
HCURSOR cur = ::GetCursor();
POINT curPos;
GetCursorPos(&curPos);
DrawIcon(hMemDC,curPos.x,curPos.y,cur);
}
// 创建位图头
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = iWidth;
bmpInfo.bmiHeader.biHeight = iHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = BI_RGB;
//图片信息
if (0 == GetDIBits(hMemDC, hBitmap, 0, iHeight, NULL, &bmpInfo, DIB_RGB_COLORS))
{
MessageBox(NULL,"GetDIBits Fail !","ERROR",MB_OK);
return 0;
}
//当接收缓冲为空或者,长度不够时返回需要的长度
if (NULL == buf || len < bmpInfo.bmiHeader.biSizeImage)
{
// return bmpInfo.bmiHeader.biSizeImage;
goto hah;
}
//把图片数据拷至缓冲中去
GetDIBits(hMemDC, hBitmap, 0, iHeight, buf, &bmpInfo, DIB_RGB_COLORS);
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
hah:
int erro = DeleteObject(hBitmap);
erro = DeleteDC(hScrDC);
erro = DeleteDC(hMemDC);
// DeleteObject(hBitmap);
// 返回位图句柄
return bmpInfo.bmiHeader.biSizeImage;
}void DisplayPicture(HDC hdc,char *pdata,int datalen,int s_w,int s_h,int w,int h) //显示图像
{
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = 0;
bmpInfo.bmiHeader.biHeight = 0;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = datalen;
bmpInfo.bmiHeader.biWidth = w;
bmpInfo.bmiHeader.biHeight = h; StretchDIBits(hdc,0,0,s_w,s_h,
0,0,w,h,pdata,&bmpInfo,
DIB_RGB_COLORS,SRCCOPY);
}BOOL DisposeFun(CServerDlg *pdlg)
{
SOCKET *ptalk = &pdlg->m_talk;
int w,h;
GetScreenCaps(&w,&h);
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = 1024;
rect.bottom = 768; int datalen = BITMAPSIZE;
BYTE *pdata = new BYTE[datalen];
ZeroMemory(pdata,datalen); int templen = BITMAPSIZE;
BYTE *tempdata = new BYTE[templen];
ZeroMemory(tempdata,templen);
int xorlen = BITMAPSIZE;
BYTE *xordata = new BYTE[xorlen];
ZeroMemory(xordata,xorlen); int sorlen = BITMAPSIZE;
BYTE *sordata = new BYTE[sorlen];
ZeroMemory(sordata,sorlen); int reallen;
reallen = GetScrnData(&rect,NULL,0);
if(datalen < reallen)
return FALSE; GetScrnData(&rect,pdata,datalen);
memcpy(sordata,pdata,reallen);
int ret = SendData(ptalk,pdata,reallen,tempdata,templen,rect.right,rect.bottom);
DWORD newtime,oldtime,count; while(pdlg->m_bisSubWork)
{
oldtime = GetTickCount();
GetScrnData(&rect,pdata,datalen);
XOR((char *)sordata,(char *)pdata,(char *)xordata,reallen);
memcpy(sordata,pdata,reallen);
ret = SendData(ptalk,xordata,reallen,tempdata,templen,rect.right,rect.bottom);
if(!ret)
break;
newtime = GetTickCount(); count = oldtime - newtime;
if(count < 100)
Sleep(100 - count); }
pdlg->m_bisSubWork = FALSE;
::closesocket(*ptalk);
delete []pdata;
delete []tempdata;
delete []xordata;
delete []sordata;
return TRUE;
}要给分啊 我不容易啊