本文轉載自微軟嵌入式中文社群
www.msembed.com和以往一樣我開始充滿激情地研究WinCE的新版本:Windows Embedded Compact 7,尤其是作業系統的新功能。我用我們的參考平台Alioth(一個基于Marvel PXA 300的參考設計)BSP來研究WEC7的功能。我用到了WEC7(ie)的重要功能Silverlight Shell。Wow!!!微軟為WEC7設計了新的圖形界面。我為我的平台生成了新的OSDesign。我加入了"sample Home Screen Silverlight for Windows Embedded (SYSGEN_XRSHELL)"元件以及其它一些必要的元件,成功地編譯出OS的鏡像。
将鏡像下載下傳到目标闆後,我有點失望,因為我沒看到XRShell,取而代之的是一個灰色的空螢幕,如下圖所示。
而與此同時,我的經理和其他一些Windows CE團隊的成員卻得到了成功的結果。我的腦袋又開始發熱了。我開始收集他們的OSDesign,進行對比并找出在OSDesign的元件清單中的差異。我試着加入和移除我的OSDesign中的某些元件,最後終于找到了罪魁禍首。讓XRShell不能運作的元件是"ActiveSync"。我找到了解決問題的線索。
我開始看XRShell的源代碼,它們在WINCE700/public/ shell/ oak/ XRshell/ src/ CXRShell.cpp中。同時我也在觀察ActiveSync在啟動過程中的活動。起初我懷疑可能是ActiveSync中用到的SH_Shell API沒有被實作。在檢查CXRShell.cpp過程中我發現他們的确沒有實作這個API,但是他們用一個"MissingAPI()"給所有的SH_Shell API設定一個占位函數,并在CXRShell::Execute()方法中對這個占位API進行初始化。
CXRShell::Execute()方法中shell生成桌面、場景等,包括對SH_Shell API進行初始化。用這個API的占位API,XRShell可以使其它需要用到SH_Shell API的應用程式得以運作。但我們的情況不同。這裡XRShell被ActiveSync阻塞了。是以SH_Shell API的占位不是問題所在。
下一個被懷疑的活動是ActiveSync會在工作列中顯示提示圖示,但不幸的是目前的XRShell中沒有實作工作列。最後我終于發現原來是ActiveSync在一直找工作列,是以阻塞了XRShell的啟動。
解決方案
我生成了一個起占位作用的空工作列,并與XRShell相關聯。太棒了!現在XRShell可以帶着ActiveSync一起啟動了。
下面我将解釋如何生成一個占位用工作列。我們可以從已有的标準shell的源代碼中輕松地生成一個工作列。如果你浏覽了以下的檔案,你可以輕松地生成一個占位工作列。
• /Wince700/public/shell/oak/hpc/explorer/inc/taskbar.hxx
• /Wince700/public/shell/oak/hpc/explorer /taskbar.cpp
• /Wince700/public/shell/oak/hpc/explorer /main.cpp
以下是我生成工作列的源代碼。
//以下的宏定義取自taskbar.hxx檔案。
#define HHTASKBARDATA 8
#define HHTASKBARCLASSNAME TEXT(“HHTaskBar”)
#define HHTASKBARID 0
#define HHTASKBARSTATE 4
//為工作列設立的一個啞WndProc
LRESULT CALLBACK XRshellTaskBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
//以下代碼通過參考taskbar.cpp中的CTaskBar::Register()方法而生成。
//函數XShellTaskBar()-用于生成一個占位工作列。
void XShellTaskBar(HINSTANCE hInstance)
RETAILMSG(1,(TEXT(“XRshell TaskBar ++/r/n”)));
HWND hwndTaskBar;
WNDCLASS wc;
wc.style = /*CS_HREDRAW | CS_VREDRAW | */CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)XRshellTaskBarWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = HHTASKBARDATA;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = HHTASKBARCLASSNAME;
RegisterClass(&wc);
//為工作列生成一個視窗。參考自taskbar.cpp中的CtaskBar::Create()。
hwndTaskBar= CreateWindowEx(0,HHTASKBARCLASSNAME, L”", WS_POPUP, 0, 0,
10, 10, NULL, NULL, hInstance, NULL);
//在成功生成視窗後,用RegisterTaskbar() API将此視窗注冊為工作列。參考自explorer.cpp中的WINAPI CreateTaskBar()方法。該函數調用了CTaskbar::Register和 RegisterTaskBar() API。
if( hwndTaskBar)
if (RegisterTaskBar(hwndTaskBar))
RETAILMSG(1,(TEXT(“XRShellTaskBar: RegisterTaskBar success/r/n”)));
else
RETAILMSG(1,(TEXT(“XRShellTaskBar: RegisterTaskBar failed/r/n”)));
RETAILMSG(1,(TEXT(“XRShellTaskBar: Unable to create Taskbar window/r/n”)));
RETAILMSG(1,(TEXT(“Xshell TaskBar –/r/n”)));
}
占位工作列已經準備好了,現在我們要将它加入到XRShell中。這部分比較簡單,你可以将上面的代碼加到CXRShell.cpp的開始部分然後在CXRShell::Execute()中調用XShellTaskBar()函數,就像下面做的這樣。
unsigned long CXRShell::Execute(int nCmdShow)
/*已有的代碼*/
…..
InitializeAPI();
XShellTaskbar(m_hInstance); //我們為XRShell準備的黑色工作列
CHR( ShowShell()); //這是個阻塞調用