WinCE開機即運行定製的Shell是很多系統的基本要求,有時還需要屏蔽WinCE內建的Shell。WinCE中程式的自啟動,一般有兩個實現方法,修改註冊表和添加自啟動捷徑。修改註冊表比較方便,如下:
[HKEY_LOCAL_MACHINE\init]
"Launch70"="MyApp.exe"
"Depend70"=hex:14,00,1e,00
只要將MyApp.exe打包到NK,並在platform.reg中加入上面的註冊表資訊,這樣WinCE啟動時便會自動運行該程式。但這時WinCE內建的Shell總是先出來,然後才運行MyApp.exe,為了避免這種情況,我們可以將註冊表設定修改如下:
[HKEY_LOCAL_MACHINE\init]
"Launch50"="MyApp.exe"
"Depend50"=hex:14,00,1e,00
即將原來啟動explorer.exe的值換為MyApp.exe。這樣WinCE啟動時直接進入定製的Shell,而不啟動explorer.exe。但這時有可能引入了新問題,如果定製的Shell是基於MFC編寫的,並且其中用到了如CFileDialog等類庫時,就會出現意想不到的情況,如所示:
是在不啟動Explorer.exe時,嘗試匯入註冊表檔案出現的狀況,而在啟動explorer.exe時是沒有問題的。這說明CFileDialog在某種程度上依賴於explorer.exe,具體細節沒研究。但說明不啟動explorer.exe,基於MFC的Shell運行時就可能會出問題。所以explorer.exe必須啟動,但又不能出現WinCE介面。要解決這個問題自然就想到修改explorer.exe了。WinCE5.0和WinCE6.0中,這一部分的代碼都是公開的,在WinCE6.0中Shell的相關代碼在C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN目錄下。
大致看了一下這一部分的代碼,發現只需修改如下兩個檔案,就應該能實現需求。
C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN\desktop.cpp
Code
bool CDesktopWnd::Create()
{
IShellFolder *pSHF;
FOLDERSETTINGS fs;
RECT rc;
HRESULT hr = E_FAIL;
// Get a shell folder for the desktop
hr = SHGetDesktopFolder(&pSHF);
if(hr || !pSHF)
goto Cleanup;
// create a shell view for it
hr = pSHF->CreateViewObject(NULL, IID_IShellView, (LPVOID *)&_psv);
if(hr || !_psv)
goto Cleanup;
fs.ViewMode = FVM_ICON;
fs.fFlags = FWF_DESKTOP | FWF_ALIGNLEFT | FWF_NOSCROLL;
//++changed by hjb
//將Desktop的視窗大小設為0
//SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN));
SetRect(&rc, 0, 0, 0, 0);
//--changed by hjb
// create the desktop's view window (no need to AddRef since CreateViewWindow does it)
hr = _psv->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rc, &_hWnd);
if(hr || !_hWnd)
{
Release();
goto Cleanup;
}
RegisterDesktop(_hWnd);
Cleanup:
if(pSHF)
pSHF->Release();
return (hr == S_OK);
}
C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN\explorer.cpp
Code
DWORD WINAPI CreateTaskBar(LPVOID pEvent)
{
HANDLE hSyncEvent = *((HANDLE *) pEvent);
CTaskBar *pTaskBar = NULL;
HWND hwndTB = NULL;
pTaskBar = new CTaskBar;
//++added by hjb
//在建立工作列時強制終止
if(pTaskBar)
{
delete pTaskBar;
SetEvent(hSyncEvent);
return 0;
}
//--added by hjb
if(!pTaskBar)
{
SetEvent(hSyncEvent);
return 0;
}
g_TaskBar = pTaskBar;
if(!pTaskBar->Register(g_hInstance))
{
g_TaskBar = NULL;
delete pTaskBar;
SetEvent(hSyncEvent);
return 0;
}
RegisterTaskBar(pTaskBar->GetWindow());
SetEvent(hSyncEvent);
DWORD dwRet = pTaskBar->MessageLoop();
delete pTaskBar;
return dwRet;
}
修改完這兩處後,先編譯該目錄,然後再重新編譯整個系統(執行Sysgen)應該就可以了。Explorer.exe依然啟動,依然可以聽到WinCE啟動的聲音,但WinCE的介面已經屏蔽掉了。此時,基於MFC的Shell也能正常工作,如所示:
在實際操作時,我沒有通過修改原始碼編譯來完成這個測試。因為在編譯C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN目錄時,發現它只產生了explorer.lib。考慮到重新編譯整個系統的時間太長,所以直接修改了工程目錄下的explorer.exe的檔案,MakeImg後測試的。這裡應該有快速編譯的方法,但目前不知怎麼弄。
修改後,在WinCE6.0的模擬器中測試,達到了預想的效果。這樣就大概解決了基於MFC的Shell和Explorer.exe之間的矛盾,是不是有隱患還不清楚,目前看來沒問題。
另外需要注意,修改public和private目錄下的檔案時,一定先做好備份,以免後患。
修改後的WinCE6.0的explorer.exe及示範視頻的:
http://files.cnblogs.com/we-hjb/WinCE_Shell.rar