代码改变世界

Windows Mobile控制面板程序

2009-06-22 21:23  王克伟  阅读(3903)  评论(12编辑  收藏  举报

什么是控制面板程序?看到下图就一目了然了。控制面板应用程序是一个以cpl为后缀的文件,其实是个dll文件(把项目生成的dll文件后缀改为cpl,或者从VS中修改配置直接生产cpl文件)。部署控制面板程序非常简单,直接把生产的cpl文件Copy到手机的Windows目录下即可。当你点击自己编写的控制面板程序的图标时,ctlpnl.exe进程会加载Windows目录下对应的cpl文件。

clip_image002clip_image002[5]clip_image002[8]

clip_image002[1]clip_image002[3]

其实系统自带的一些控制面板程序被集成在cplmain.cpl中(但是像无线管理器等并不是cpl文件,而是一个exe程序,这个可以从注册表中找到设置,微软这么设计的原因是因为无线管理器在很多地方都是需要的。),所以如果你需要在你的程序中打开这些面板的话会经常看到如下代码:

SHELLEXECUTEINFO info; 
TCHAR szControlPanelCmdLine[ 200 ];
swprintf( szControlPanelCmdLine, L\\windows\\cplmain.cpl,5);  //参数5代表调用about
info.cbSize = sizeof( info );
info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
info.lpVerb = NULL;
info.lpFile = TEXT("ctlpnl.exe");
info.lpParameters = szControlPanelCmdLine;
info.lpDirectory = NULL;
info.nShow = SW_SHOW;
info.hInstApp = NULL;
ShellExecuteEx( &info );

以下是更多对应关系:

ctlpnl.exe cplmain.cpl,1 - set password 
ctlpnl.exe cplmain.cpl,2 - set ownerinfo 
ctlpnl.exe cplmain.cpl,3 - battery status 
ctlpnl.exe cplmain.cpl,4 - memory status 
ctlpnl.exe cplmain.cpl,5 - about 
ctlpnl.exe cplmain.cpl,7 - align 
ctlpnl.exe cplmain.cpl,8 - keyboard settings 
ctlpnl.exe cplmain.cpl,9 - sound 
ctlpnl.exe cplmain.cpl,10 - remove programs 
ctlpnl.exe cplmain.cpl,11 - start menu 
ctlpnl.exe cplmain.cpl,12 - button assignments 
ctlpnl.exe cplmain.cpl,13 - today screen 
ctlpnl.exe cplmain.cpl,15 - beam settings 
ctlpnl.exe cplmain.cpl,16 - clock 
ctlpnl.exe cplmain.cpl,17 - network adapters 
ctlpnl.exe cplmain.cpl,18 - regional settings 
ctlpnl.exe cplmain.cpl,19 - connections 
ctlpnl.exe cplmain.cpl,20 - phone settings 
ctlpnl.exe cplmain.cpl,22 - manage certificates 
ctlpnl.exe cplmain.cpl,23 – bluetooth 

言归正传开始介绍cpl的编写

cpl文件中的回调函数CPlApplet为ctlpnl.exe进程进入你的cpl的入口点(需要导出,不管你在def文件里面,还是在函数前制定dllexport属性),一个cpl可以支持多个applets,见下面的代码中的注释。

LONG CPlApplet(
  HWND hwndCPl,  //Handle to the main window of the controlling application.
  UINT msg,  //Message being sent to the Control Panel application.
  LPARAM lParam1,
  LPARAM lParam2
);

msg有:

CPL_INIT
初始化,控制面板应用程序此时做一些全局的初始化工作,如内存分配。

CPL_GETCOUNT
获取控制面板应用程序支持的dialog boxes个数。

CPL_NEWINQUIRE
查询控制面板应用程序的dialog boxes的信息,信息包含在lParam2参数中,使用(LPNEWCPLINFO) lParam2获得指针。

typedef struct tagNEWCPLINFO { 
  DWORD dwSize; 
  DWORD dwFlags; 
  DWORD dwHelpContext; 
  LONG lData; 
  HICON hIcon;  //Handle to the icon that represents the dialog box.  
  TCHAR szName[32]; //The name is intended to be displayed below the icon.
  TCHAR szInfo[64]; //The description is intended to be displayed when the icon for the dialog                      box is selected.
  TCHAR szHelpFile[128]; //忽略。要想使用帮助,处理WM_NOTIFY消息,然后取得“lppsn = (LPPSHNOTIFY) lParam;”判断是否等于PSN_HELP,如果是即可调出帮助文档。
} NEWCPLINFO;

CPL_IDNAME
获得控制面板应用程序的名称,通过设置注册表键值[HKEY_LOCAL_MACHINE\ControlPanel\<ID name>]可以改变应用位于控制面板属性页的位置,主键值"Group"默认为dword类型1,也就是说当你不指定位置时,默认放在系统这个tab中。另外还有如下值可以选择:

0                    Personal 
1 (default value)    System 
2                    Connections

CPL_DBLCLK
当用户双击控制面板上的icon时,系统会发送这个消息给你的控制面部应用程序,此时你可以弹出一个dialog box。处理完这个消息之后返回0表示你成功处理这个消息了(其它消息也一样),非0表示其它。

CPL_STOP
关闭控制面部应用程序之前那一刻发送这个消息给你的控制面板应用程序。

CPL_EXIT
释放DLL文件之前那一刻发送这个消息给你的控制面板应用程序。

////////////////////////////////////////////////////////
//	This is the entry point called by ctlpnl.exe
//  
////////////////////////////////////////////////////////
extern "C"
__declspec(dllexport)
LONG WINAPI CPlApplet(HWND hwndCPL, UINT uMsg, LONG lParam1, LONG lParam2)
{
	static int		iInitCount = 0;
	int				iApplet;

    switch (uMsg)
	{
		// First message sent. It is sent only once to
		// allow the dll to initialize it's applet(s)
		case CPL_INIT:
			if (!iInitCount)
			{
				if (!InitApplet(hwndCPL))
					return FALSE;
			}
			iInitCount++;
			return TRUE;
			
		// Second message sent. Return the count of applets supported
		// by this dll
		case CPL_GETCOUNT:
			// Return the number of applets we support
			return (LONG)((sizeof(SystemApplets))/(sizeof(SystemApplets[0])));

		// Third message sent. Sent once for each applet supported by this dll.
		// The lParam1 contains the number that indicates which applet this is
		// for, from 0 to 1 less than the count of applets.
		// lParam2 is a NEWCPLINFO that should be filled with information about
		// this applet before returning
		case CPL_NEWINQUIRE:
			{
				LPNEWCPLINFO	lpNewCPlInfo;

				lpNewCPlInfo = (LPNEWCPLINFO)lParam2;
				iApplet = (int)lParam1;
				lpNewCPlInfo->dwSize = (DWORD)sizeof(NEWCPLINFO);
				lpNewCPlInfo->dwFlags = 0;
				lpNewCPlInfo->dwHelpContext	= 0;
				lpNewCPlInfo->lData = SystemApplets[iApplet].icon;
				lpNewCPlInfo->hIcon = LoadIcon(g_hInstance, (LPCTSTR)MAKEINTRESOURCE(SystemApplets[iApplet].icon));
				lpNewCPlInfo->szHelpFile[0] = '\0';

				LoadString(g_hInstance,SystemApplets[iApplet].namestring, lpNewCPlInfo->szName,32);
				LoadString(g_hInstance,SystemApplets[iApplet].descstring, lpNewCPlInfo->szInfo,64);
			}

			break;

		// This is sent whenever the user clicks an icon in Settings for one of
		// the applets supported by this dll. lParam1 contains the number indicating
		// which applet. Return 0 if applet successfully launched, non-zero otherwise
		case CPL_DBLCLK:
			iApplet = (UINT)lParam1;
			if (!CreatePropertySheet(hwndCPL,iApplet))
				return 1;
			break;
			
		// Sent once per applet, before CPL_EXIT
		case CPL_STOP:
			break;
			
		// Sent once before the dll is unloaded
		case CPL_EXIT:
			iInitCount--;
			if (!iInitCount)
				TermApplet();
			break;
			
		default:
			break;
    }

    return 0;
}

更详细的代码请见例子\Samples\PocketPC\CPP\win32\myBackLight,或者点这里下载。

关于任何调试cpl代码,请参照下面的文章。