Windows Mobile的远程控制

diskonline 2008-04-10 05:20:46

程序代码

介绍:
这里描述的是一个Windows Mobile 的桌面远程控制程序。用这个程序,你可以通过键盘和鼠标远程控制你的Windows Mobile设备。
背景:
代码实在我以前的文章类曾经提到的:一个远程的Windows Mobile屏幕截取工具。除了调用RAPI,该软件可以通过一个RAPI服务流,允许桌面程序建立设备之间不间断的连接。当然,在该程序中。我放弃了GAPI和DirectDraw的屏幕截取方式,使用了一个简单的基于GDI屏幕截取方式。为了曾强通信能力,代码在连接两端使用了ZLIB的压缩库。
桌面代码:
请在解压该程序前建立一个CeRemoteClient的目录来保存桌面项目。
桌面程序代码的大部分包含在CeRemoteClientView.h中,事实上WTL 8.0框架子窗口实现了所有桌面客户端的功能。
设备的连接通过Connect() 和 Disconnect()方法实现。在菜单和工具条中可以使用该命令,这些都包含在主框架窗口类中(MainFrm.h)。当桌面成功的连接到设备,一个200微秒的时钟被建立,用来压缩屏幕位图。
屏幕设备是由GetScreen()方法控制的。它先关掉计时器,然后发送信息到服务设备请求当前屏幕图象:
KillTimer(SCREEN_TIMER);
hr = Write(RCM_GETSCREEN);


服务设备返回一个信息包含同样的信息代码,屏幕缓冲的压缩大小,然后解压流数据。在读取类三个字大小的数据后,代码判断压缩和解压缓冲的空间是否够用,然后读取压缩的数据流:

//读取压缩缓冲区
hr = m_pStream->Read(m_pZipBuf, cbZipBuf, &ulRead);

如果一切顺利,压缩缓冲将被解压,结果DIB是位图的大小。如果大小不一样则再来一次,当非常接近时,屏幕设备将被刷新,这样整个窗口被清空:
zr = uncompress(m_pScrBuf, &nDestLen, m_pZipBuf, cbZipBuf);
if(zr == Z_OK)
{
DIBINFO* pDibInfo = (DIBINFO*)m_pScrBuf;
BYTE* pBmpData = (BYTE*)(m_pScrBuf + sizeof(DIBINFO));
BOOL bErase = FALSE;

if(m_xDevScr != pDibInfo->bmiHeader.biWidth ||
m_yDevScr != pDibInfo->bmiHeader.biHeight)
{
m_xDevScr = pDibInfo->bmiHeader.biWidth;
m_yDevScr = pDibInfo->bmiHeader.biHeight;

SetScrollSize(m_xDevScr, m_yDevScr);

bErase = TRUE;
}

m_dib.SetBitmap((BITMAPINFO*)pDibInfo, pBmpData);

InvalidateRect(NULL, bErase);
UpdateWindow();
}
在强制窗口更新后,计时器重新启动,这样我们就可以获得下一张屏幕图象。
发送输入:
发送键盘和鼠标的输入信息非常简单:处理相应的窗口信息,将其数据转化为INPUT结构,将其发送到服务端处理。以下是对WM_KEYDOWN的处理:
LRESULT OnKeyDown(TCHAR vk, UINT cRepeat, UINT flags)
{
HRESULT hr;
INPUT input;

if(!m_bConnected)
return 0;

input.type = INPUT_KEYBOARD;
input.ki.wVk = MapKey(vk);
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;

hr = Write(RCM_SETINPUT);
if(SUCCEEDED(hr))
{
hr = Write(&input, sizeof(input));
if(SUCCEEDED(hr))
GetScreen();
}

return 0;
}
MapKey()函数在桌面和键盘设备之间进行基本的安键索引。用F1键用来控制左,F2用来控制右。F3和F4自然的做为数字键。
LRESULT OnLButtonDown(UINT Flags, CPoint pt)
{
HRESULT hr;
INPUT input;

if(!m_bConnected)
return 0;

m_bLeftBtn = true;
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE |
MOUSEEVENTF_LEFTDOWN;
input.mi.dx = pt.x * 65536 / m_xDevScr;
input.mi.dy = pt.y * 65536 / m_yDevScr;
input.mi.mouseData = 0;
input.mi.time = 0;
input.mi.dwExtraInfo = 0;

hr = Write(RCM_SETINPUT);
if(SUCCEEDED(hr))
{
hr = Write(&input, sizeof(input));
if(SUCCEEDED(hr))
hr = GetScreen();
}

return 0;
}
注意鼠标的屏幕坐标是可以被屏幕做参照的,SendInput API在服务器上使用的原因。
现在注意,让我们进一步看一下服务器设备的代码。
设备代码:
请建立设备项目的CeRemSrv路径。
大部分设备代码是CRemoteControl类中执行的。所有由桌面客户发送的信息在循环运行的方法中被处理。
设备屏幕可以被SendScreen方法扑捉。它有一个和桌面副本很相似的结构。看一下屏幕设备是怎么被方便的扑捉的:
hDC = GetWindowDC(NULL);

当获得了设备屏幕的HDC后,你可以非常容易的拷贝到一个位图文件中并和桌面联系。这里不需要在怀念 GAPI或DirectDraw技术:
memcpy(m_pScrBuf + i, m_dib.GetBitmapInfo(), sizeof(DIBINFO));
i += sizeof(DIBINFO);

memcpy(m_pScrBuf + i, m_dib.GetDIBits(), m_dib.GetImageSize());
i += m_dib.GetImageSize();

ULONG len = m_cbZipBuf;
int zr = compress(m_pZipBuf, &len, m_pScrBuf, cbNew);

if(zr != Z_OK)
len = 0;

hr = m_pStream->Write(&dwMsg, sizeof(DWORD), &ulWritten);
hr = m_pStream->Write(&len, sizeof(ULONG), &ulWritten);
hr = m_pStream->Write(&cbNew, sizeof(DWORD), &ulWritten);
hr = m_pStream->Write(m_pZipBuf, len, &ulWritten);

Handling input from the desktop is even simpler:

HRESULT CRemoteControl::GetInput()
{
INPUT input;
HRESULT hr;
DWORD dwRead;

hr = m_pStream->Read(&input, sizeof(input), &dwRead);
if(FAILED(hr))
return hr;

if(dwRead != sizeof(input))
return E_FAIL;

SendInput(1, &input, sizeof(input));

return S_OK;
}

一个非常简单的方式。
感兴趣的几点:
这里有两件事比较有趣:这样模拟鼠标的双击事件,为什么代码不会在WM5和WM6设备上工作?
双击必须发送消息到设备。这样是因为窗口将合并四个鼠标事件(down - up - down - up)到一个单一的信息WM_LBUTTONDBLCLK中。如果你看了我的代码,你就回知道这是怎样失败的。
在WM5和WM6设备中,你可能必须用RAPI的连续性,以便服务设备DLL响应客户端。我一次写了一个简单的设备工具以解决着类复杂问题。你在这就能找到,拷贝EXE文件到设备上然后运行它。
...全文
204 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
jikun6666 2008-05-02
  • 打赏
  • 举报
回复
knowledge_Is_Life 2008-05-01
  • 打赏
  • 举报
回复
这个简单啊,网上搜一下就得到答案了.

7,655

社区成员

发帖
与我相关
我的任务
社区描述
Windows Phone是微软发布的一款手机操作系统,它将微软旗下的Xbox LIVE游戏、Zune音乐与独特的视频体验整合至手机中。
社区管理员
  • Windows客户端开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧