网页游戏微端制作过程遇到的问题和知识点
最近接到个需求是制作我们游戏的微端,上头丢给我一个创建好的MFC程序,
包含一个主窗体MainFrm,一个内嵌窗体ChildView,
ChildView中初始化时创建控件CWebBrowser2,通过CWebBrowser2打开游戏网页,并装载引擎DLL。
目的是达到登录帐号并执行游戏的全过程。
第一个要点就是自绘制窗体:
因为系统创建的窗体的标题栏是肯定不能用的,就必须自己绘制整个客户区并取消系统的标题栏及附带的最小化、最大化、关闭等按钮。
参考:
游戏登陆页面Launcher的外框贴图需要镂空绘制
参考:
1 MFC 创建不规则窗体 这个方法效率高,可以在一秒内绘制出来
2 MFC 绘制不规则窗体 这个方法第一次绘制时会卡几秒甚至二十几秒,作为游戏微端,这个启动时间无法接受
然后就是各种按钮功能的具体实现,包括窗体不同状态下的大小绘制等问题
参考:
2 MFC GetWindowRect, GetClientRect和ScreenToClient
5 MFC 响应双击事件 用于双击自绘制标题栏响应最大化/恢复
6 关于WM_NCHITTEST消息 用于移动我们自绘制的无标题窗体
绘制最大化程序时遇到问题,因为需求是不覆盖任务栏的最大化,
所以使用了
CRect reWnd;
::SystemParametersInfo(SPI_GETWORKAREA,0,&rtWnd,0);
来获取桌面工作区域大小,但是自绘制的时候,右边和下面与任务栏连接处会有两条缝隙无法绘制到。
后来用 int frameSIze = ::GetSystemMetris(SM_CYFRAME);
获取了自身窗体的边框大小, 然后将上面获得的工作区的宽高分别补上frameSIze,才绘制了无缝贴合任务栏的窗体。
CWebbrowser2内嵌网页的输入框出现无法响应TAB、复制、粘贴等快捷操作的问题
最后找到了解决方案,是在ChildView中加入以下消息处理
BOOL CMyView::PreTranslateMessage(MSG* pMsg)
{
if (IsDialogMessage(pMsg))
return TRUE;
else
return CWnd::PreTranslateMessage(pMsg);
}
参考:
第二个要点就是程序的自更新下载:
我不想再写一个自更新程序,于是就将更新程序都集成在微端中,
主要思路是:
先到指定路径下下载一个版本文件,其中包含需要下载更新的文件名 和其对应最新版本的文件MD5码。
校验本地文件的MD5码和版本文件中是否相同,不同的则执行下载。
其中比较麻烦的是本身程序exe文件的更新,由于这个时候程序是启动的状态,无法修改对应exe文件。
对此,我采用的方式是先下载一份备份文件,重命名为XXX.update.exe,然后通过shell启动新的.update.exe并同时关闭原exe。
exe启动时判定是.update.exe启动还是原exe启动,
当.update.exe启动时,先删除原exe,拷贝一份.update.exe重命名为XXX.exe,然后重新启动原exe,关闭更新程序自身,
反之则删除XXX.update.exe,执行后面的逻辑。
参考:
2 CHttpConnection::OpenRequest
在Win7等系统下,由于有User Account Control(UAC)限制,
导致部分开启UAC功能的玩家由于XXX.exe无法启动下载的XXX.update.exe而导致更新过程失败。
参考:
1 MFC编程:Win7下支持弹出UAC对话框获取管理员权限
2 程序调用ShellExecuteEx打开其他程序(兼容UAC获取管理员权限)
后期维护中用到的知识:
使用ShellExecuteEx调用控制台程序(exe)并传入多个参数