cpl (控制面板应用程序) 编写及调试 (以dialog 为例)
控制面板程序是用户用于配置Windows环境的一些特殊动态连接库(DLL)。Windows已经为我们提供了一些标准的控制面板程序,如字体、键盘、鼠标设置等。我们也可以根据实际的需要创建自己的控制面板程序,以便让用户来查看或者修改特定软硬件的参数设置。
控制面板的功能和操作方式
控制面板程序的主要功能是显示一个对话框让用户完成特定的任务。但是,与其它应用程序不同的是,控制面板程序并不是一个独立的应用程序,它不提供标准菜单或者其它方法让用户直接去操作这些对话框,而是在其他应用程序(如控制面板)的控制下操作和显示它们的对话框的。
控制面板程序通常是由一个Windows的系统工具(即控制面板)所控制,从而让用户来运行的。但是,其它应用程序只要发送控制面板程序所需要的消息并且处理它们的返回值同样可以加载并且管理这些控制面板程序,为了陈述简单,下文中我们将这类程序统称为控制面板。
大多数的控制面板程序仅显示并且维护一个对话框让用户来控制系统某一个部件的参数设置以及操作方式,但事实上控制面板程序可以提供多个对话框来控制多个系统部件(这些单个的对话框通常被称为Applet小程序)。为了区分这些对话框,控制面板程序通常为每个对话框提供一个图标。控制面板则把这些图标显示出来,供用户选择不同的对话框进行配置。
程序入口函数
前面提到,控制面板程序是特殊的动态连接库(DLL),在每一个控制面板程序中必须提供一个标准的函数入口PlApplet ,控制面板程序通过这个函数来接收控制面板发送的消息,从而执行相应的功能,如初始化程序、显示并且管理对话框以及关闭程序等。
当控制面板首次加载控制面板程序时取得CPlApplet函数的地址,通过该地址去调用控制面板程序的函数以及给它发送消息。
控制面板可以向控制面板程序发送的消息名称及其意义如下表所示:
消息名称 含义
CPL_DBLCLK 该消息通知CPlApplet函数用户双击了某对话框相关联的图标。CPlApplet应该显示相应的对话框并且完成用户指定的任务。
CPL_EXIT 该消息在最后一条CPL_STOP消息之后,并且控制面板调用FreeLibrary 函数释放包含控制面板程序的动态连接库DLL 之前调用。CPlApplet应该释放所用资源准备关闭。
CPL_GETCOUNT 该消息在发送了CPL_INIT消息之后发送,CPlApplet应该返回一个整数指明它支持多少个对话框。
CPL_INIT 该消息在控制面板动态连接库DLL程序首次加载时调用, CPlApplet在此可以执行一些初始化过程,包括内存的分配。
CPL_INQUIRE 该消息在CPL_GETCOUNT消息之后发送,让CPlApplet提供特定对话框的信息。CPlApplet的lParam2参数指向一个CPLINFO结构。
CPL_NEWINQUIRE 该消息在CPL_GETCOUNT消息之后发送,让CPlApplet提供指定对话框的信息。参数lParam2是指向NEWCPLINFO结构的指针,在Windows 95 and Windows NT version 4.0,为了提高性能,控制面板程序应该处理CPL_INQUIRE消息,而不是CPL_NEWINQUIRE消息。
CPL_STOP 在控制面板关闭前向每一个对话框发送该消息。CPlApplet应该释放与给定对话框相关联的内存资源。
编写
1, 建立一个MFC DLL project —— CPL_Test
2, 将 controlpanelapp.h contorlpanelapp.cpp 拷贝到当前工程,并添加到project中
3, 将 CPL_Testapp 的基类由 CWinapp 改为 CControlPanelApp
4, 在 CPL_Testapp 中override 函数 OnInit()
BOOL CPL_Testapp::OnInit()
{
AddApplet(new CCPApplet(IDI_LOGO, RUNTIME_CLASS(CMainControlDlg), TRUE));
return CControlPanelApp::OnInit();
}
其中 IDI_LOGO 为出现在控制面板中的Icon, CMainControlDlg为启动的主界面类(这里以CDialog为例)
5, 在def文件中exports函数 CPlApplet
在启动控制面板或者调试时,会调用此函数发送消息至CControlPanelApp
6, 确认CMainControlDlg支持DYNAMIC_CREATE
CMainControlDlg.h 中 DECLARE_DYNCREATE(CMainControlDlg)
CMainControlDlg.cpp 中 IMPLEMENT_DYNCREATE(CMainControlDlg, CDialog)
7, 在resource中的string table增加一项 IDI_LOGO – “Test Logo”,此字符串会出现在控制面板中的Logo下方,作为Item的描述。
调试
1, 将 "Porject > Properties > Debugging" 的 "Command" 设为 {System Folder}/rundll32.exe
2, 将 "Porject > Properties > Debugging" 的 "Command Arguments" 设为 {System Folder}/shell32.dll,Control_RunDLL “{yourcpl}”
{System Folder} : 系统system32目录
{yourcpl} : 控制面板应用程序的路径。注意,这里必须是全路径。
3, 通过 F5 进行调试。
上述contorlpanelapp中包括 class CCPApplet : public CCmdTarget, class CControlPanelApp : public CWinApp
具体可以搜索CControlPanelApp
其中的CPL注册即如何使他出现在控制面板中,不同的系统有不同的方法, 具体可以参考较早时间的一篇文章.