实现远程桌面控制的功能。
我们需要思考传输速度的问题,它主要由三方面决定:
1.抓屏 2.压缩 3.网络传输
上一篇文章写了抓屏技术,压缩的话使用zlib压缩,现在主要总结一些传输的问题。
进行传输,首先获得位图信息。
//得到bmp结构的大小
ULONG BufferLength = 1 + m_ScreenSpy->GetBitmapInfoLength(); //大小
LPBYTE BufferData = (LPBYTE)VirtualAlloc(NULL, BufferLength, MEM_COMMIT, PAGE_READWRITE);
memcpy(BufferData + 1, m_ScreenSpy->GetBitmapInfo(), BufferLength - 1);
然后进行发送给服务器,服务器接收到消息后,继续发送。
首先是发送第一幅图像。
第一幅图,获得位图信息,构建数据包,发送就完事了。
This->SendFirstScreenData();
while (This->m_IsLoop)
{
//循环发送桌面数据
This->SendNextScreenData();
Sleep(10);
}
发送下一张的时候,我们在获得位图信息的时候,使用了差值算法,实际上就是节省了时间,所以我们在传输的时候,也是直接构建数据包完事。
以上是客户端做的事情,下面来看看服务器做了啥。
先初始化相关工具。
//DC设备描述符
m_WindowDCHandle = ::GetDC(m_hWnd);
m_WindowMemoryDCHandle = CreateCompatibleDC(m_WindowDCHandle);
m_BitmapHandle = CreateDIBSection(m_WindowDCHandle, m_BitmapInfo,
DIB_RGB_COLORS, &m_BitmapData, NULL, NULL); //创建应用程序可以直接写入的、与设备无关的位图
SelectObject(m_WindowMemoryDCHandle, m_BitmapHandle); //择一对象到指定的设备上下文环境
SetWindowPos(NULL, 0, 0, m_BitmapInfo->bmiHeader.biWidth / 2, m_BitmapInfo->bmiHeader.biHeight / 2, 0);
接收第一帧图像
第一帧图像,就正常接收,把数据拷贝到自己的DC当中,当然要进行解压缩。
接收下一帧图像
因为我们在客户端获取位图的时候,使用的差值截图,所以在接受的时候,也要注意,和前一帧的区别,然后再去更新鼠标位置。
(因为鼠标位置是不是从位图中获取的,所以我们要自己更新)。
//前一帧数据
LPVOID PreviousScreenData = m_BitmapData;
//获得当前帧数据
LPVOID CurrentScreenData = m_ContextObject->m_ReceiveDecompressedBufferData.GetArray(v1);
//获得当前帧长度
ULONG CurrentScreenLength = m_ContextObject->m_ReceiveDecompressedBufferData.GetArrayLength() - v1;
POINT PreviousClientCursorPosition;
memcpy(&PreviousClientCursorPosition, &m_CursorPosition, sizeof(POINT));
//更新光标位置
memcpy(&m_CursorPosition, m_ContextObject->m_ReceiveDecompressedBufferData.GetArray(2), sizeof(POINT));
if (memcmp(&PreviousClientCursorPosition, &m_CursorPosition, sizeof(POINT)) != 0)
{
//鼠标移动了
IsChange = TRUE;
}
if (CurrentScreenLength > 0)
{
//屏幕是否有变化
IsChange = TRUE;
}
//
CopyScreenData(PreviousScreenData, CurrentScreenData, CurrentScreenLength);
if (IsChange)
{
//如果有变化响应Paint消息
PostMessage(WM_PAINT);
}