编写控制面板程序的一个例子
2009-10-24 20:31:26 来源:WEB开发网一定要用DECLARE_DYNCREATE来声明对话框类和属性页类。如果不这样做Create会调用失败,而且可能还会有MFC的TRACE诊断错。除此之外,还要记住重 写对话框和属性页的OnPostNcDestroy函数,加入代码“delete this”。这是因为,通常创建对话框是在栈(stack)上进行的,代码如下:
CMyDialog dlg;
dlg.DoModal();
这种情况不用关心delete。而CPApplet是在堆(heap)上创建的对话框和属性页,在对话框和属性页被destroy掉以后,必须要进行delete操作,否则造成内存溢出。
综上所述,我们可以看到,使用CControlPanelApp 和 CCPApplet编写控制面扩展易如反掌。为了添加普通对话框或者基于属性页的面板应用,只需要重写CControlPanelApp::OnInit即可,然后实现相应的对话框代码和属性页代码。 表一概括地总结了框架处理各种CPL消息的方法和注释。
表一:控制面板消息和控制面板应用框架
CPlApplet 消息 | 框架 class::function | 是否需要改写? |
CPL_INIT | CControlPanelApp::OnInit | 是,每个控制面板程序都调用 AddApplet 添加 |
CPL_GETCOUNT | 没有 | 否,CControlPanelApp 决定控制面板程序数量 |
CPL_INQUIRE | CCPApplet:: OnInquire | 很少用 |
CPL_NEWINQUIRE | CCPApplet::OnNewInquire | 很少用 |
CPL_DBLCLK | CCPApplet::OnLaunch | 很少用,仅用于没有对话框和属性页界面的情况 |
CPL_SELECT (已废掉) | CCPApplet::OnSelect | 否 |
CPL_STOP | CCPApplet::OnStop | 很少用,除非控制面板程序都进行垃圾收集,但这种情况最好在程序的析构函数中进行 |
CPL_EXIT | CControlPanelApp::OnExit | 很少用,用 ExitInstance 代替 |
CPL_STARTWPARAMS (Windows 98 或者Windows NT 4.0) |
CCPApplet::OnLaunch | 很少用,仅用于没有对话框和属性页界面的情况 |
下面是编写控制面板程序需要注意的几件事情:首先是生成控制面板扩展后,它是一个*.dll文件,不要忘了把它的扩展名改为*.cpl。其次,运行*.cpl之前,必须将它拷贝到Windows的系统目录中,如C:\\Winnt\\System32,或者C:\\Windows\\System,根据你的操作系统安装目录决定。你可以通过“Project”=>“Setting”菜单将这一步添加到Post-Build步骤中。如果你想在自己的目录中保存一份DLL文件,那么可以通过安装程序在Windows的CONTROL.INI文件的[MMCPL]
段添加一行内容:
[MMCPL]
MyCtrlPanel=c:\utils\MyCtrlPanel\MyCtrlPanel.cpl
第三要注意的事情是当你生成控制面板程序时,可能会遇到下面的情况:如增加另一个面板应用、改变名字或者图标——而这些更改在控制面板中反映不出来。这是因为控制面板读取(CPL_INQUIRE)信息时,需要第一次与你的DLL见面后, 它才能将信息缓冲到磁盘。让控制面板重读新信息的一种比较保险的方法是改DLL名字。你也可以试一下在控制面板中按F5(Refresh),但这个方法不一定每次都奏效。在开发期间,你可以将CCPApplet::m_bDynamic 设置为 TRUE,让它告诉框架使用CPL_NEWINQUIRE(不缓冲信息)代替 CPL_INQUIRE (缓冲信息)。当你完成调试准备发行正式版时,再将CCPApplet::m_bDynamic置回(缺省值)FALSE。
说到调试,下面介绍两种调试控制面板应用程序的方法:一种是在调试器中启动控制面板程序;如果你觉得那太麻烦,那么还有另外一种方法是使用rundll32:
rundll32 shell32.dll,Control_RunDLL MyCtrlPanel.cpl
你可以在命令行上面的命令,也可以在VC++的Debug Settings菜单中进行设置。
相信很多人都没像这样用过 rundll32.exe 程序,它可以从命令行调用某个DLL中的某个函数。Control_RunDLL是shell32.dll中的一个特别的函数, 顾名思义,它运行一个控制面板程序;为了运行DLL中一个特定的控制面板程序,敲入:
rundll32 shell32.dll,Control_RunDLL MyCtrlPanel.cpl,@n
这里 n 是基于零的应用程序索引。如果你在末尾加一个串,它被传递到CPL_STARTWPARAMS,就象一个常规的Windows应用程序命令行一样。通常,这个串被用于启动一个基于属性页的控制面板应用, 并且定位到特定的属性页上。例如:为了调出显示器的“设置”属性页标签,敲入:
rundll32 shell32.dll,Control_RunDLL desk.cpl,,3
如果你以前不知道有些应用程序是怎么启动特定的控制面板应用的,现在你应该知道了。如果你使用本文提供的迷你框架,自己就不必写任何代码来解析这个参数;对于一个基于属性页的面板,CCPApplet自动将相关参数解释为一个属性页号。
LRESULT CCPApplet::OnLaunch(CWnd* pWndCpl, LPCSTR lpCmdLine)
{
CWnd* pw = (CWnd*)m_pDialogClass->CreateObject();
if (pw) {
if (pw->IsKindOf(RUNTIME_CLASS(CPropertySheet))) {
CPropertySheet* ps = (CPropertySheet*)pw;
ps->SetActivePage(lpCmdLine ? atoi(lpCmdLine) : 0);
ps->DoModal();
} else if (pw->IsKindOf(RUNTIME_CLASS(CDialog))) {
CDialog* pd = (CDialog*)pw;
pd->DoModal();
}
}
return pw==NULL;
}
最后,如果你不知道如何卸载控制面板程序,这里告诉你一个笨方法:重启机器,只要你不运行控制面板,Windows就不会加载那些.cpl文件,所以你可以直接到Windows系统目录 (比如c:\windows\sysytem或者c:\winnt\system32)下删除相应的.cpl文件。注意这样做的风险是——万一你删错了文件, 那么对应的控制面板程序图标将从控制面板中消失。所以删除文件的时候一定要小心。如果哪位有更好的办法,请告诉我。
希望本文的介绍和例子对大家开发控制面板程序有所帮助
更多精彩
赞助商链接