MSDN參考:
http://msdn.microsoft.com/zh-cn/library/ee502286
摘自:
http://blog.csdn.net/jjunjoe/article/details/6120601
作者:ARM-WinCE
WinCE系統中的控制台和Windows系統中的控制台原理是一樣的,裡面就是包含了一些應用程式。WinCE系統的控制台由Ctlpnl.exe,Control.exe和一些.cpl檔案組成,其中Ctlpnl.exe和Control.exe用于控制控制台的檔案夾顯示和架構,而.cpl檔案和控制台中的實際應用程式相對應。
WinCE的控制台中的每個應用程式都由兩部分組成:應用程式本身和所對應的.cpl檔案。實際上.cpl檔案就是一個dll,在該dll中會導出CPLApplet函數,該函數會處理來自控制台的消息(CPL_INIT, CPL_DBCLK, CPL_STOP等),然後根據相應的消息來調用應用程式。
先來看一下CPlApplet函數,如下:
LONG CPlApplet(HWND hwndCPl, UINT msg, LPARAM lParam1, LPARAM lParam2)
hwndCPl:控制台視窗的句柄
msg:發給控制面應用程式的消息
lParam1:消息參數1
lParam2:消息參數2
該函數會根據msg參數傳入的消息進行相應的處理,WinCE中所支援的控制台消息如下:
CPL_INIT:被首次加載的時候會收到該消息,也是第一個消息,用于初始化控制台應用程式,比如記憶體配置設定等。
CPL_GETCOUNT:第二個被收到的消息,該消息用于獲得該控制台應用程式中的元件數,因為.cpl檔案中可能包含多個Applet程式。
CPL_NEWINQUIRE:查詢元件資訊,如果該.cpl中包含多個元件,那麼lParam1表示元件号,lParam2是一個指向NEWCPLINFO結構的指針,其中NEWCPLINFO結構用于描述元件資訊。
CPL_DBCLK:使用者在控制台界面中輕按兩下某個應用時,會收到該消息,在該消息中執行對應的應用程式。如果包含多個元件,那麼lParam1表示組建号,lParam2為傳給應用程式的資料。
CPL_STOP:關閉控制面應用程式時,收到該消息,用于釋放資源。如果包含多個元件,那麼lParam1表示元件号,lParam2為傳給應用程式的資料。
CPL_EXIT:在CPL_STOP消息之後,控制台釋放該應用程式時,收到該消息。
在CPlApplet中收到CPL_NEWINQUIRE消息時,會初始化NEWCPLINFO結構來描述元件資訊,該結構定義如下:
typedef struct tagNEWCPLINFO {
DWORD dwSize;
DWORD dwFlags;
DWORD dwHelpContext;
LONG lData;
HICON hIcon;
TCHAR szName[32];
TCHAR szInfo[64];
TCHAR szHelpFile[128];
} NEWCPLINFO;
dwSize:該結構的資訊
dwFlags:忽略
dwHelpContext:忽略
lData:傳給組建程式的資料
hIcon:顯示在控制台中的圖示的句柄
szName:顯示在控制台中的元件的名字
szInfo:顯示在控制台中的描述資訊
szHelpFile:忽略
前面介紹了控制台的基礎知識,下面就開始添加應用程式到WinCE控制台中,步驟如下:
1. 建立一個WinCE的工程,然後添加一個應用程式:
首先要有一個WinCE的工程,然後點選File->New->Subproject,然後選擇WCE Application,然後可以選擇Hello World應用程式。
2. 為應用程式建立CPL工程:
同樣點選File->New->Subproject,然後選擇WCE Dynamic-Link Library,工程名為HelloCPL,然後點選Next,在Auto-generated subproject files頁面中選擇A Dll that exports some symbols,然後點選Finish完成。
3. 添加CPlApplet函數:
打開HelloCPL工程,并打開HelloCPL.cpp檔案,添加如下頭檔案:
#include <tchar.h>
#include “cpl.h”
然後添加如下代碼:
#define lengthof(exp) ((sizeof((exp)))/sizeof((*(exp))))
HMODULE g_hModule = NULL; // Handle to the DLL.
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
g_hModule = (HMODULE) hModule;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// The entry point to the Control Panel application.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C" HelloCPL_API LONG CALLBACK CPlApplet(HWND hwndCPL,
UINT message, LPARAM lParam1, LPARAM lParam2)
{
switch (message)
{
case CPL_INIT:
// Perform global initializations, especially memory
// allocations, here.
// Return 1 for success or 0 for failure.
// Control Panel does not load if failure is returned.
return 1;
case CPL_GETCOUNT:
// The number of actions supported by this Control
// Panel application.
return 1;
case CPL_NEWINQUIRE:
// This message is sent once for each dialog box, as
// determined by the value returned from CPL_GETCOUNT.
// lParam1 is the 0-based index of the dialog box.
// lParam2 is a pointer to the NEWCPLINFO structure.
{
ASSERT(0 == lParam1);
ASSERT(lParam2);
NEWCPLINFO* lpNewCplInfo = (NEWCPLINFO *) lParam2;
if (lpNewCplInfo)
{
lpNewCplInfo->dwSize = sizeof(NEWCPLINFO);
lpNewCplInfo->dwFlags = 0;
lpNewCplInfo->dwHelpContext = 0;
lpNewCplInfo->lData = IDI_HELLO;
// The large icon for this application. Do not free this
// HICON; it is freed by the Control Panel infrastructure.
lpNewCplInfo->hIcon = LoadIcon(g_hModule,
MAKEINTRESOURCE(IDI_HELLO));
LoadString(g_hModule, IDS_APP_TITLE, lpNewCplInfo->szName,
lengthof(lpNewCplInfo->szName));
LoadString(g_hModule, IDC_Hello, lpNewCplInfo->szInfo,
lengthof(lpNewCplInfo->szInfo));
_tcscpy(lpNewCplInfo->szHelpFile, _T(""));
return 0;
}
return 1; // Nonzero value means CPlApplet failed.
}
case CPL_DBLCLK:
{
// The user has double-clicked the icon for the
// dialog box in lParam1 (zero-based).
PROCESS_INFORMATION pi = {0};
if (CreateProcess(_T("//Windows//Hello.exe"), NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
return 1; // CPlApplet failed.
}
case CPL_STOP:
// Called once for each dialog box. Used for cleanup.
case CPL_EXIT:
// Called only once for the application. Used for cleanup.
default:
return 0;
}
return 1; // CPlApplet failed.
} // CPlApplet
具體不做解釋了,相信自己看一下都能看明白。在上面的代碼中,處理消息CPL_NEWINQUIRE的時候,加載了IDI_HELLO,IDS_APP_TITLE和IDC_Hello三個資源,分别是一個圖示和兩個字元串。為工程添加rc資源檔案和resource.h頭檔案,導入圖示資源和字元串資源。資源的導入和定義比較簡單,是以不介紹具體步驟了。
4. 修改HelloCPL工程配置:
打開HelloCPL.bib檔案,添加如下内容:
MODULES
HelloCPL.cpl $(_FLATRELEASEDIR)/HelloCPL.cpl NK
右擊HelloCPL工程,選擇Properities,選擇General頁面,在Custom Variables項中添加變量,變量名字為CPL,值為1。
再次右擊HelloCPL工程,選擇Properities,選擇C/C++頁面,确認Additional Macro Definitions的值為$(CDEFINES) -DHelloCPL_EXPORTS。設定DLL Entry Point項為DllMain。在Include Directories項中添加路徑$(_PROJECTROOT)/cesysgen/oak/inc。
5. 編譯Hello應用程式和HelloCPL工程:
編譯開始建立的Hello應用程式和HelloCPL工程,在WinCE6.0中,編譯完成後會自動Makeimg操作。
通過上面的步驟,可以把應用程式添加到WinCE系統的控制台中,最後編譯成功以後,就可以下載下傳運作了,在此我添加了一個Hello的應用程式,名字叫Hello application,運作結果如圖