设为首页 收藏本站
查看: 601|回复: 0

[经验分享] ZZ Windows 控制面板编程

[复制链接]

尚未签到

发表于 2016-5-23 08:24:25 | 显示全部楼层 |阅读模式
  ZZ From: http://blog.csdn.net/tomcui/archive/2008/01/22/2058502.aspx
  
  
Windows 控制面板编程
  说明:本文章为本人在做项目时查阅相关文章而写成,如有不当之处,请指出。
  mail: tomcui60000520@163.com
  关键字:
  控制面板,控制面板应用程序,
  
  一、 什么是控制面板
  打开Windows的控制面板会看到类似的图像
  
  
图一
  双击其中的一个图标,会显示对话框,让用户来完成相应的软硬件设置工作。这就是我们看到的控制面板。那么如何开发控制面板程序呢?带着疑问在MSDN和google里搜索关键字“Control Panel”,就会找到相关的技术文章。这是我工作的方法:借鉴已有的资源。但实际情况是那样吗?我们可以跟着MSDN的讲述来一步一步深入下去。
  经过挖掘,发现并不是exe文件(Windows Vista下支持exe的控制面板应用程序,并且微软建议做成exe文件),而是有着cpl后缀名的文件,在windows->system32下可以找到这样的文件。如果借助工具,Dependency Walker for Win32 (x86) 或dumpbin等就可以看到该文件导出了一些函数。
  
  
  
图二
  多观察几个这样的文件,发现导出的函数虽有差异,但其中都有CPLApplet函数被导出。这些特征与DLL的特征吻合。去MSDN上查阅CPLApplet函数的说明证明我们的猜测是正确的。可以说控制面板应该程序就是以CPL为后缀名并且一定要导出CPLApplet函数的dll文件。
  对于具体的描述可以参考:
  http://msdn2.microsoft.com/en-us/library/bb776838(VS.85).aspx
  二、 明确几个概念
  l 控制面板管理程序:用于管理控制面板的程序,在桌面windows版本是CONTROL.EXE,在windows CE版本是CTLPNL.EXE,它们负责管理控制面板里的控制面板条目。简单的说,我们打开控制面板时,这些管理程序就在运行了。只不过我们看到的是挂上了Shell外观而已(注:这是我的猜测,还没有找到依据)。
  l 控制面板条目(Control Panel Item):在控制面板里看到的每个图标所对应的就是一个控制面板条目。
  l 控制面板应用程序(Control Panel Application):就是最终看到的CPL文件,一个控制面板应用程序可以实现几个控制面板条目。
  
  三、 控制面板应用程序的编写
  编写控制面板应用程序,就是编写dll文件,在该文件中实现控制所需要的功能。这就涉及到一个不得不说的函数,没有它就无法完成控制面板程序的实现。该函数为CPLApplet。下面就该函数的参数等知识做些介绍。
  函数:LONG CPLApplet(HWND hwndCPl,UINT msg, LPARAM lParam1, LPARAM lParam2)
  函数CPLApplet是控制面板应用程序(Control Panel application)的入口点,它被控制面板管理程序(control.exe 或Ctlpnl.exe)自动调用,它是个回调函数(Callback),注意:CPL文件一定要把函数CPLApplet导出,这样控制面板才能找到程序的入口点。
  当启动控制面板时,它会搜索Windows或System32或注册表的相应条目目录下的文件,并把以CPL作为扩展名的文件载入,它调用CPL文件的导出函数CPLApplet(),发送消息给该函数。所以,控制面板应用程序要处理控制面板发送过来的消息,即在函数CPLApplet中进行处理,该函数没有默认的行为。如果一个CPL文件中实现了多个控制面板程序,那么只会有一个CPLApplet函数,它负责所有的控制面板应用程序。
  参数说明:
  hwndCPl:控制面板管理程序或称为控制面板的窗口句柄,即为control.exe的窗口句柄。如果控制面板应用程序或其它窗口需要传递父窗口句柄,可以使用该参数。
  Msg:发送到控制面板应用程序的消息,由控制面板管理程序发送。
  lParam1:消息参数
  lParam2:消息参数
  函数的返回值依据消息的不同而不同。
  应用程序要使用该函数需要包含头文件:cpl.h
  
  
  消息名称
描述

CPL_INIT
控制面板应用程序收到的第一个消息,通常在此处理全局初始化和内存分配。成功返回非0,否则返回0,此时控制面板管理程序终止和该应用程序的通信,并释放相应的CPL文件。

CPL_GETCOUNT
该消息紧接在CPL_INIT消息之后被发送,它返回控制面板管理程序所能看到该CPL文件中所包含的控制面板组件的数目,即该CPL文件可以出现在控制面板中的图标的数目。

CPL_INQUIRE
于CPL_GETCOUNT之后被发送,为指定的控制面板条目提供信息。

CPL_NEWINQUIRE
于CPL_GETCOUNT之后被发送,与消息CPL_INQUIRE完成的功能类似,只不过其实现要求TNewCPLInfo结构指针,所包含的资源不提供缓存,所以控制面板启动的较慢,一般不建议处理该消息,除非特别必要,如要根据一定的条件动态的改变控制面板条目的图标、字符串等。

CPL_DBLCLK
表明用户选定了一个控制面板条目,程序应该显示相应的对话框以便用户完成相应的任务。成功返回0,否则,返回非0.

CPL_STOP
控制面板管理程序关闭时被发送,控制面板应用程序在此时处理内存释放等动作。成功处理,返回0.

CPL_SELECT
目前不被使用。只有Windows 95 和Microsoft Windows NT 4.0之前的系统使用。

CPL_STARTWPARMS
该消息与CPL_DBLCLK类似,但lParam2指向LPCTSTR,该消息在shell32.dll version 5.0 (Windows 2000 ,Windows Millennium Edition (Windows Me))及以后版本有效

CPL_EXIT
于CPL_STOP消息之后被发送,这是控制面板应用程序在释放资源的最后机会。成功处理返回0.

  
  CPL_INQUIRE:lParam1是以0为起点的整数,它是该CPL文件中所包含的控制面板条目的索引,lParam2参数要求一个CPLINFO结构的指针,用来填充所需的图标、字符串等信息。如果成功处理了该消息,应该返回0。
  CPL_NEWINQUIRE:该消息与CPL_INQUIRE都是CPL_GETCOUNT之后被发送的消息,但并没有明确的先后顺序。所以程序里不要依赖它们的顺序来处理不同的事务。
  编写控制面板应用程序的步骤:
  1 选择适当的开发工具(如:Visual Studio 2008),建立DLL项目;
  2 导出函数CPLApplet;
  3 在函数CPLApplet的消息处理过程中完成你需要的工作;
  一个简单的例子
  开发工具:Microsoft Visual Studio 2008
  操作系统:Windows XP SP2
  步骤:
  1 新建Win32 Project,工程名为CPLTest;
  
  
2 应用程序类型选择DLL(CPL文件本质上是DLL);
  
  
  3 在项目中新增或导入一个图标文件和两个字符串资源,用于在控制面板管理程序中显示图标和提示;
  在Resource Files 上右键选择Add->Resource,然后选择Icon或String Table
  以下为resource.h 的部分内容
  #define IDI_ICON1 101 //图标标识
  #define IDS_STRING102 102 //字符串tom
  #define IDS_STRING103 103//字符串cui
  4 在dllmain.cpp文件中增加函数的导出CPLApplet;
  extern "C" __declspec(dllexport) LONG APIENTRY CPlApplet(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
  原则上可以按照上面的方式导出就可以了,但是请注意CPlApplet的调用方式是APIENTRY,通过这样方式导出的函数会被改名,通过多次实验也不可行。你可能会上去掉APIENTRY,但这样编出来的CPL文件无法运行,查阅了相关文档,在Windows Mobile Version 5.0 SDK的文档里指明了该函数的调用方式,windows CE 5.0 和Windows Shell and Controls没有指明这种调用方式。所以,只有加上APIENTRY。
  现在的问题是如何导出该函数?看来要通过DEF文件了,如果你的项目里没有产生DEF文件,可以通过Project->Properties->Linker->Module Definition File来指定或自己用记事本建立这样的文件,输入如下内容。
  ; CPLTest.def : Declares the module parameters for the DLL.
  
  LIBRARY "CPLTest"
  
  EXPORTS
  ; Explicit exports can go here
  CPlApplet
  5 在dllmain.cpp文件中增加函数CPLApplet的消息处理函数来完成指定的功能;
  在dllmain.cpp中包含以上两个头文件
  #include "resource.h" //资源标识
  #include <Cpl.h> //CPLApplet函数要求的头文件
  我的例子完成显示一个MessageBox的功能。
  dllmain.cpp的完整代码:
  // dllmain.cpp : Defines the entry point for the DLL application.
  #include "stdafx.h"
  #include "resource.h"
  #include <Cpl.h>
  
  LONG APIENTRY CPlApplet(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
  
  BOOL APIENTRY DllMain( HMODULE hModule,
  DWORD ul_reason_for_call,
  LPVOID lpReserved
  )
  {
  switch (ul_reason_for_call)
  {
  case DLL_PROCESS_ATTACH:
  case DLL_THREAD_ATTACH:
  case DLL_THREAD_DETACH:
  case DLL_PROCESS_DETACH:
  break;
  }
  return TRUE;
  }
  
  LONG APIENTRY CPlApplet(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
  {
  int i;
  LPCPLINFO lpCPlInfo;
  
  i = (int) lParam1;
  
  switch (uMsg) {
  case CPL_INIT: // first message, sent once
  return TRUE;
  
  case CPL_GETCOUNT: // second message, sent once
  return 1;
  break;
  
  case CPL_INQUIRE: // third message, sent once per application
  lpCPlInfo = (LPCPLINFO) lParam2;
  lpCPlInfo->lData = 0;
  lpCPlInfo->idIcon = IDI_ICON1;
  lpCPlInfo->idName = IDS_STRING102;
  lpCPlInfo->idInfo = IDS_STRING103;
  break;
  
  case CPL_DBLCLK: // application icon double-clicked
  MessageBox(NULL, TEXT("Tom66"), TEXT("Cuei666"), MB_OK);
  break;
  
  case CPL_STOP: // sent once per application before CPL_EXIT
  break;
  
  case CPL_EXIT: // sent once before FreeLibrary is called
  break;
  
  default:
  break;
  
  }
  return 0;
  }
  
  6 编译
  Project->Properties->Linker->Output File修改输出文件的后缀名为CPL,也可以不修改,到最后把dll改为cpl也可以的。
  
  
四、 控制面板应用程序的安装与运行
  l 将cpl文件拷贝到Windows(Windows CE)或Windows/system32(桌面版本Windows),可以在这里双击运行,也可以打开控制面板就可以看到该CPL文件所包含的控制面板条目,图标和文件就是你在CPLApplet里指定的,双击也可运行。
  2 在命令行下运行rundll32 shell32.dll,Control_RunDLL CPLTest.cpl(CPL文件名)@1(数字指定运行第几个控制面板条目,一个CPL文件可以包含几个控制面板条目)。在windows CE下,在命令行输入ctlpnl.exe /windows/cplmain.cpl,5,与桌面版本有些差异。
  3 在windows的注册表[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Control Panel/Cpls] 下新建字符串,并指定cpl所在的完整路径,然后就可以在控制面板里看到新增加的控制面板条目。通过写注册表的方式,是一些应用软件惯用的方式,安装时可以通过InstallShield等安装制作工具将其添加到注册表,卸载时,删除注册表中相关的项。
  
  
4 通过拷贝的方式,直接删除相应的CPL文件就可以了。至于有没有更好的方式,我还没有发现。
  
  五、参考资料:
  1 http://msdn2.microsoft.com/en-us/library/aa926276.aspx
  2 http://msdn2.microsoft.com/en-us/library/bb776392.aspx
  Add by myself
通过修改注册表的方式,来安装 控制面板应用程序(Control panel application),必须在CPlApplet中响应CPL_INQUIRE消息,并在其中加载图标。(LPCPLINFO->IdIcon),否则打开控制面板时,所安装应用程序的图标无法加载,无法显示。
而通过拷贝文件至System32目录,则可以响应CPL_INQUIRE或者CPL_NEWINQUIRE,可以在其中的任意一个响应函数中load图标。
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jtujtujtu/archive/2008/12/12/3503878.aspx

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-220511-1-1.html 上篇帖子: SQL Server 2008 – How To Build and Deploy AdventureWorks OLAP Cubes 下篇帖子: windows 下 php 环境配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表