开源软件《M8围棋谱》v0.8.8 首次登陆魅族软件中心,免费发布,技术总结

  今日(2010/7/22),本人(liigo)开发的C/C++开源软件《M8围棋谱》v0.8.8 首次登陆魅族软件中心,免费发布。本文主要针对“如何满足魅族软件中心对软件的各项要求”作一些技术总结。

  众所周知,魅族对发布在软件中心的软件有详细的要求、严格的审核,工作人员甚至帮你测试寻找BUG,细致入微,热心而且周到,工作效率也挺高,周六都在加班工作。在《M8围棋谱(v0.8.8)》申请进入魅族软件中心之前,我逐条对照《魅族手机应用软件审核标准1.2》,自我审核并修改了部分内容,后来有几经周折按照魅族软件中心工作人员的反馈,修改了另外部分内容。总结一下,此次为登陆魅族软件中心,大概修改了一下内容:

  软件必须单实例运行;

  必须设置标题栏文本;

  软件在系统任务管理器中的显示文本必须与软件名称一致;

  通过USB连接电脑时软件必须退出,且不弹出任何提示;

  软件启动、退出、切换窗口时必须有动画效果;

  软件在英文系统下运行不能有中文乱码;

  如果软件有播放声音的功能,必须允许用户通过音量键(物理按键)调节声音,必须有选项可以关闭声音;

总体来说,它的审核有点过分琐碎、过分严格,有些细节在编码实现上有过分复杂(这是SDK设计不够友好)。

  软件必须单实例运行,我是通过创建系统全局Event对象实现的,与官方示例代码稍有区别:

//应MStore要求,必须单实例运行 m_eventHandle = CreateEvent(NULL, FALSE, FALSE, L"Global//M8WeiqiPu_by_liigo"); if(m_eventHandle && GetLastError() == ERROR_ALREADY_EXISTS) { HWND hWnd = FindWindowW(NULL, M8_WEIQIPU); if(hWnd) { SetForegroundWindow(hWnd); SetActiveWindow(hWnd); ::ShowWindow(hWnd, SW_SHOWNORMAL); ::UpdateWindow(hWnd); } PostQuitMessage(0); return FALSE; } else SetWindowText(M8_WEIQIPU);

  上面的代码中,首先创建全局Event对象,如果发现同名对象已存在,说明本软件已经有一个实例在运行,通过WinCE API函数FindWindow()找到主窗口并激活它,然后退出当前进程。

  软件在系统任务管理器中的显示文本必须与软件名称一致。文档中似乎没有提到系统任务管理器中的显示文本取自何处,我总结得知,如果通过WinCE API函数SetWindowText()设置了主窗口标题栏文本,则显示该文本,否则显示软件EXE文件名(无路径)。所以要满足此条要求,只需设置标题栏文本为软件中文名称即可。

  通过USB连接电脑时软件必须退出,且不弹出任何提示。这个实现起来稍微有一点麻烦,但是也简单,SDK文档有相关说明。首先要定义一个类成员 int m_usbNotifyMsg,在窗口初始化时(OnInitDialog)对其赋值:m_usbNotifyMsg = RegisterUsbNotifyMsg();,即通过调用MZ SDK 函数RegisterUsbNotifyMsg()获取“USB连接相关的”消息值。然后,在CMzWnd::MzDefWndProc()方法中处理USB连接消息,主要代码如下:

virtual LRESULT MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam) { if( message == m_usbNotifyMsg) //应MStore要求:USB连接时静默退出程序 { if(wParam == USB_MASSSTORAGE_ATTACH) { Quit(); } } …………

  软件启动、退出、切换窗口时必须有动画效果。主要是CMzWnd::AnimateWindow(MZ_ANIMTYPE_ZOOM_IN, true) 此类代码调用,SDK文档中有示例代码,简单。

  软件在英文系统下运行不能有中文乱码。M8围棋谱软件需要读取GB编码的SGF棋谱文件,我(liigo)自行开发的SGF解析器解析出来的文本都是GB编码(char*),而软件本身是UNICODE的,中间需要进行编码转换。我原来使用C库函数 mbstowcs() 转换编码,后来被魅族软件中心测试人员发现,在软件运行在英文系统下时,此举会造成中文显示乱码。我分析后估计是locale的原因,事先调用C库函数setlocale()设置为中文locale应该就能解决吧?然后又发现WinCE下的C运行库似乎没有setlocale()函数。于是放弃这个思路,改用WinCE API函数MultiByteToWideChar()进行编码转换(GB2312->UCS2LE),主要代码如下:

//确保在英文系统下也能转换SGF文件中的中文字符到Unicode static int cncharsToWChar(const char* cnchars, WCHAR* wchars_buffer, int wchar_buffer_size) { if(wchars_buffer == NULL) return MultiByteToWideChar(936 /*gb2312*/, 0, cnchars, -1, NULL, 0); else return MultiByteToWideChar(936 /*gb2312*/, 0, cnchars, -1, wchars_buffer, wchar_buffer_size); }

  如果软件有播放声音的功能,必须允许用户通过音量键(物理按键)调节声音,必须有选项可以关闭声音。我原来是调用WinCE API函数PlaySound()播放WAVE文件的,如此一来不好处理音量大小的控制。后来选择调用MZ SDK提供的COM接口IPlayerCore_Play,首先是相关COM对象的初始化(基本上是引用SDK文档中的示例代码,相当繁琐):

#include <IMzSysFile.h> #include <IPlayerCore.h> #include <IPlayerCore_IID.h> #include <PlayerCore_GUID.h> IPlayerCore_Play* m_pPlayCore; IMzSysFile* m_pSysFile; //初始化声音播放组件 m_pSysFile = NULL; m_pPlayCore = NULL; if(SUCCEEDED( CoCreateInstance(CLSID_PlayerCore, NULL, CLSCTX_INPROC_SERVER, IID_MZ_SysFile, (void **)&m_pSysFile))) { m_pSysFile->SetParentWnd(m_hWnd); if( !SUCCEEDED(m_pSysFile->QueryInterface( IID_PlayerCore_Play, (void**)&m_pPlayCore)) ) { m_pSysFile->Release(); m_pSysFile = NULL; } //m_pPlayCore->SetNotify(m_hWnd, WM_USER + 15); }

  欲播放音乐文件时,先调用 m_pSysFile->SetName(m_luoziSoundFile),然后调用 m_pPlayCore->OpenFile(),然后调用 m_pPlayCore->Play(),当然,Play()之前可以调用 m_pPlayCore->SetVolume(m_soundVolume) 设置音量:

m_pSysFile->SetName(m_luoziSoundFile); m_pPlayCore->OpenFile(); m_pPlayCore->SetVolume(m_soundVolume); m_pPlayCore->Play();

  接下来要处理用户按下音乐键(物理按键)的消息了,以便增减音量。方法与处理USB连接事件大致相同(代码之繁琐有过之而无不及):

int m_allkeyEventMsg; int m_soundVolume; RegisterShellMessage(m_hWnd, WM_MZSH_ALL_KEY_EVENT); m_allkeyEventMsg = GetShellNotifyMsg_AllKeyEvent(); virtual LRESULT MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message == m_allkeyEventMsg) //应MStore要求:音量键调节声音 { int key = LOWORD(wParam); //WPARAM_KEY_EVENT_*** if(key == WPARAM_KEY_EVENT_CLICK_VOLUP) { m_soundVolume += 7; //与按下音量键时的系统音量变化幅度保持基本一致 if(m_soundVolume > 100) m_soundVolume = 100; m_skin.SetSoundVolume(m_soundVolume); } else if(key == WPARAM_KEY_EVENT_CLICK_VOLDOWN) { m_soundVolume -= 7; if(m_soundVolume < 0) m_soundVolume = 0; m_skin.SetSoundVolume(m_soundVolume); } } …………

  实现响应音乐键调节音量的过程中,有个细节我处理的不够理想,即,没有找到获取当前音量的方法。用户按“上音量键”我增加音量,用户按“下音量键”我减小音量,可是音量的初始值是什么呢?一直没找到方法读取,只好暂时以当前系统来电铃声音量替代。目前的效果不是很好:用户按音乐键时,系统会自动弹出一个音量调节进度显示框,而它显示的值有时明显不能跟我软件中的音量一致起来。归根结底还是没有取得音量初始值。郁闷。如果系统改进一下接口,在用户按下音乐键时,直接返回给我音量值多好。

  总体的感觉,MZ SDK 的 API 接口设计不是非常友好,有些地方使用起来相当繁琐。是不是我易语言代码写多了,再不愿写又臭又长的代码?我倒是很期待Android SDK,想象中Google设计的API应该相当OK吧?无论如何,《M8围棋谱》进入魅族软件中心,还是值得庆祝的。顺便也祝愿魅族软件中心发展的越来越好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值