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;
}