WinCE設(shè)備通常沒有臺式機那么多的內(nèi)存(通常PPC為32M),CE用戶可以調(diào)整存儲內(nèi)存和程序使用內(nèi)存的大小,當可用內(nèi)存容量小于一定水平時,操作系統(tǒng)自己會要求程序釋放內(nèi)存,甚至自動關(guān)閉程序。筆者見到一些商業(yè)化WinCE測圖軟件調(diào)入圖形文件時長達數(shù)分鐘,運行緩慢,測圖效率大打折扣。主要原因內(nèi)存小,主頻低,且PPC顯示屏小,筆者認為PPC不適合作為測圖硬件,或許手持PC(H/PC)更能勝任。
因此應(yīng)用程序必須是滿足低內(nèi)存要求,采用的對策主要有:
保持小尺寸的EXE文件
主要是減少資源文件(*.RC)中位圖、不用的字符串和加速鍵等。
集中分配所需內(nèi)存
盡可能采用LocalAlloc、HeapAlloc、VirtualAlloc等內(nèi)存分配函數(shù)一次性分配所需內(nèi)存。一般情況采用LocalAlloc函數(shù),當需要分配大內(nèi)存時考慮使用VirtualAlloc,當需要解決內(nèi)存碎片問題時采用HeapAlloc。
管理低內(nèi)存狀態(tài)
微軟建議PPC程序不設(shè)不設(shè)關(guān)閉按紐,當系統(tǒng)需要額外內(nèi)存是自動關(guān)閉它們。WinCE添加了WM_HIBERNATE消息,當內(nèi)存很少時發(fā)送到應(yīng)用程序,要求程序釋放內(nèi)存。測繪軟件應(yīng)該響應(yīng)此消息,保留有用數(shù)據(jù),提示用戶進行必要的處理等。
及時查詢內(nèi)存狀態(tài)
兩個有用的API 函數(shù)可查詢系統(tǒng)內(nèi)存:GetSystemInfo和GlobalMemoryStatus函數(shù)。如GlobalMemoryStatus(LPMEMORYSTATUS lpmst)的結(jié)構(gòu)MEMORYSTATUS中的兩個字段dwTotalPhys表示程序內(nèi)存總量和可用的空閑程序內(nèi)存。
采用內(nèi)存分配函數(shù)是一定要檢查返回值,如分配失敗作必要處理。
WinCE只支持Unicode字符集
Unicode字符集是一個世界范圍內(nèi)的字符編碼標準,采用Unicode字符集便于全球化的應(yīng)用程序,但對習慣Win9X的程序員帶來的一些不便。
解決的方法主要有:
采用TCHAR或CString類聲明所有字符串
采用TEXT、或_T宏表示程序中的文字:TEXT("abc")或_T("abc")
采用通用字符串函數(shù)或CString處理字符串:如wsprintf、 _tcslen等
實現(xiàn)ANSI和Unicode字符的轉(zhuǎn)換,可采用API函數(shù)WideCharToMultiByte和MultiByteToWideChar,也可采用ATL和MFC提供的轉(zhuǎn)換宏。下面提供一個函數(shù):
LPSTR UnicodeToANSI(const CString& str,int &len)
{
len = WideCharToMultiByte(CP_ACP,0,str,-1,NULL,NULL,NULL,NULL);
LPSTR buf = (LPSTR)LocalAlloc(LMEM_ZEROINIT,len);
VERIFY(WideCharToMultiByte(CP_ACP,0,str,-1,buf,len,NULL,NULL) == len);
return (buf);
}
目標系統(tǒng)處理
由于WinCE支持的目標設(shè)備多樣性,不同設(shè)備有不同版本的WinCE和SDK、不同的CPU、不同的顯示屏、不同的外設(shè),因此保持通用的代碼幾乎是不可能的。采用對策主要有:
eVC開發(fā)時需要針對不同設(shè)備編譯:IDE環(huán)境提供平臺選項,重新編譯即可。
添加檢測版本和平臺代碼:如#if UNDER_CE < 210 或#ifdef _PPC等。
對不同設(shè)備設(shè)計不同的用戶界面:如對H/PC(多為橫向顯示屏)、PPC(多為縱向顯示屏)分別設(shè)計對話框,檢測平臺后決定調(diào)用各自對話框。
運行時進行動態(tài)庫版本檢測區(qū)分不同目標系統(tǒng):如采用GetVersionEx、SystemParametersInfo、LoadLibrary等。
當然最好是在不同設(shè)備上進行測試。
用戶界面(UI)設(shè)計
WinCE的UI和Win32 UI主要區(qū)別有:不支持多文檔界面、位圖菜單、非客戶窗口繪制管理、消息鉤子、GDI中若干功能(坐標變換、MoveTo等API函數(shù)),其對輸入筆、語音、輸入面板、熱鍵輸入等確支持良好,在支持大多數(shù)Win32控件基礎(chǔ)上,WinCE提供了幾個特有控件。
輸入筆輸入消息可看作鼠標輸入的子集,響應(yīng)左鍵消息WM_L*和WM_MOUSEMOVE,編程方便。
輸入面板控制技術(shù)對無鍵盤的PPC尤為重要,如當光標落入編輯框時,自動升起輸入面板,反之收起面板;當輸入面板起落時,應(yīng)用軟件能適時調(diào)整窗口等,這些均體現(xiàn)了軟件用戶界面的友善性。實現(xiàn)不復雜,主要調(diào)用API函數(shù)SHSipInfo,可查閱微軟提供的幫助文檔(MSDN)中的例程。
對于使用PPC的測量員更希望有一個較大按鍵的輸入面板,WinCE系統(tǒng)不能滿足要求,有必要編寫一個,筆者在Douglas Boling(Window CE程序設(shè)計一書作者)的例程基礎(chǔ)上制作了一個“數(shù)字鍵盤”。對輸入方法編程主要利用了COM接口IIMCallback中兩個方法:SendVirtualKey和SendCharEvents。
對于不支持多文檔界面的WinCE,可以采用多種方法來模擬。筆者采用的一種方法是:在單文檔視(VIEW)的客戶區(qū),采用多個無模式對話框,達到了仿真效果。主要代碼如下:
class CLevelRecDlg : public CDialog
{
// Construction
public:
… … //成員變量定義
public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual void PostNcDestroy();
… … //其他函數(shù)定義
};
//WindowProc函數(shù)由于取消IDOK、IDCANCEL消息,防止對話框被錯誤關(guān)閉
LRESULT CLevelRecDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if ((message == WM_COMMAND) && (wParam <= 2))
return 1;
return CDialog::WindowProc(message, wParam, lParam);
}
同樣編寫其他對話框類。
在視類中添加以下代碼
class CLevelRecView : public CView
{
protected: // create from serialization only
CLevelRecView();
DECLARE_DYNCREATE(CLevelRecView)
… …
public:
CLevelRecDlg m_RecDlg; //添加無模式對話框成員變量
CBrowseDlg m_BrowseDlg;
BOOL m_bRecView; //顯示對話框的BOOL成員變量
BOOL m_bBrowseView;
… …
};
在視響應(yīng)WM_CREATE消息的函數(shù)內(nèi)創(chuàng)建對話框
int CLevelRecView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
m_RecDlg.Create(IDD_DIALOG_LEVELREC, this); //在此創(chuàng)建
… …
}
接著編寫一個視成員函數(shù)顯示指定對話框
void CLevelRecView::ChangeView()
{
if (m_bRecView)
{
m_RecDlg.ShowWindow(SW_SHOW);
m_BrowseDlg.ShowWindow(SW_HIDE);
m_RecDlg.UpdateWindow();
m_RecDlg.SetFocus();
}
……
}
當然,UI應(yīng)考慮本地化問題,由于eVC未提供自動支持中文界面的功能,筆者采用的方法是將資源文件(*.rc)采用文本編輯器打開,將其中涉及到代碼頁(code page)處用中文資源文件中相應(yīng)部分替換,將英文文字替換成中文即可。
WinCE下MFC編程
進行WinCE快速編程,最好的方法是采用MFC,所幸的是Microsoft將WinCE的MFC封裝的十分精巧,其和臺式機的MFC版本只有一些細微的差別,只要閱讀幫助文檔即可輕松的采用MFC進行WinCE的開發(fā),簡化了其他Win32系統(tǒng)下MFC程序的移植工作。WinCE的MFC對部分類作了輕微修改,如CString、CWnd、 CframeWnd等;少數(shù)類不支持,如MDI類、DAO類、ODBC類等;針對WinCE的特性增加了幾個類,如:CE的數(shù)據(jù)庫類CceDB*、CceSocket。值得一提的是CString類簡化了大量Unicode問題。
其他主題
WinCE的API是經(jīng)過仔細篩選Win32 API,保留了約1000個函數(shù);其MFC、ATL(不支持標準模板庫STL)、ADO可看作為臺式機版本的子集。 WinCE獨有的存儲方式是對象存儲,不過API和臺式機類似,同樣亦支持COM/DCOM(組件對象模型),不過一些C/C++運行庫、C++的異常處理不支持。WinCE通信方式很多,測繪軟件設(shè)計人員多關(guān)心其串行通信編程,遺憾的是Mircosoft沒有提供相應(yīng)的Activex控件,必須采用API實現(xiàn),在《測繪通報》上已有論文詳述。
筆者在開發(fā)過程中發(fā)現(xiàn)eVC可能存在一些Bug:如對話框中的只讀編輯框不能變灰(可通過處理WM_CTLCOLOR解決),浮點型變量不能比較大小(換成整型后解決)。