控制面板程序是用户用于配置Windows环境的一些特殊动态连接库(DLL)。Windows已经为我们提供了一些标准的控制面板程序,如字体、键盘、鼠标设置等;如图1所示。我们也可以根据实际的需要创建自己的控制面板程序,以便让用户来查看或者修改特定软硬件的参数设置。
控制面板的功能和 *** 作方式
控制面板程序的主要功能是显示一个对话框让用户完成特定的任务。但是,与其它应用程序不同的是,控制面板程序并不是一个独立的应用程序,它不提供标准菜单或者其它方法让用户直接去 *** 作这些对话框,而是在其他应用程序(如控制面板)的控制下 *** 作和显示它们的对话框的。
控制面板程序通常是由一个Windows的系统工具(即控制面板)所控制,从而让用户来运行的。但是,其它应用程序只要发送控制面板程序所需要的消息并且处理它们的返回值同样可以加载并且管理这些控制面板程序,为了陈述简单,下文中我们将这类程序统称为控制面板。
大多数的控制面板程序仅显示并且维护一个对话框让用户来控制系统某一个部件的参数设置以及 *** 作方式,但事实上控制面板程序可以提供多个对话框来控制多个系统部件(这些单个的对话框通常被称为Applet小程序)。为了区分这些对话框,控制面板程序通常为每个对话框提供一个图标。控制面板则把这些图标显示出来,供用户选择不同的对话框进行配置。
程序入口函数
前面提到,控制面板程序是特殊的动态连接库(DLL),在每一个控制面板程序中必须提供一个标准的函数入口 CPlApplet ,控制面板程序通过这个函数来接收控制面板发送的消息,从而执行相应的功能,如初始化程序、显示并且管理对话框以及关闭程序等。
当控制面板首次加载控制面板程序时取得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应该释放与给定对话框相关联的内存资源。
消息处理
回调函数CPlApplet处理所有由控制面板发送给控制面板程序的上述消息,这些消息是按照特定的顺序来发送并且处理的。
当控制面板首次加载控制面板程序的动态连接库时,CPlApplet收到CPL_INIT消息。CPlAppet在处理该消息的程序中应该执行一些初始化的工作,如分配内存等,并且返回非0值;如果CPlApplet初始化失败,则应该返回0,控制面板将停止向CPlApplet发送消息并且释放已经加载的动态连接库DLL。
当CPL_INIT消息处理成功之后,CPlApplet函数将收到CPL_GETCOUNT消息,CPlApplet函数必须返回该控制面板程序所支持的对话框的数目。
对应控制面板所支持的每一个对话框,CPlApplet函数收到由控制面板发送的一条CPL_INQUIRE消息和一条CPL_NEWINQUIRE消息。函数需要用控制面板程序的信息填充CPLINFO或者NEWCPLINFO结构体,如名称、图标以及描述字符串等。多数控制面板程序仅需处理CPL_INQUIRE消息而将CPL_NEWINQUIRE消息忽略。CPL_INQUIRE通过一个控制面板能够缓存的结构存放信息从而提高性能。CPL_NEWINQUIRE仅当您需要根据计算机的状态来改变控制面板程序的图标和显示字符串时有用。
当用户在控制面板中双击某个对话框所对应的图标时, CPlApplet函数将收到一条CPL_DBLCLK消息,CPlApplet函数可以收到该消息多次。该消息包含了对话框的标志和一个lData数据,CPlApplet函数应该显示相应的对话框并且处理用户的输入。
当控制面板关闭时,对应控制面板程序支持的每一个对话框, CPlApplet函数将收到一条CPL_STOP消息。该消息包含了对话框的标志以及lData数据,CPlApplet函数应该释放此对话框所占用的资源。
在最后一条CPL_STOP消息之后, CPlApplet将收到一条CPL_EXIT消息。此时应该释放此控制面板程序所占用的所有资源。在该消息返回之后,控制面板将调用FreeLibrary 来释放控制面板程序动态连接库。
控制面板程序的安装
在编译连接输出文件名选项中将输出文件扩展名改为.CPL,编译连接成功后将其拷贝到windows的SYSTEM目录即可。
示例程序:
该示例程序将显示一个对话框,并且根据用户的输入改变系统注册表中相应的数据.按上小节所述的安装方法安装控制面板示例程序后,再次启动控制面板,在控制面板中将出现示例程序的图标,双击该图标后将d出一个对话框。如图2所示。
该程序使用Visual C++开发,从File菜单选择New,再选择MFC AppWizard,工程名称为CPL,如图3所示。单击OK之后再选择MFC Extention DLL,如图4所示。这样,Visual C++将为我们创建一个包含资源文件,DEF文件的动态连接库工程。
在Visual C++ AppWizard为我们创建的工程中,加入一个图标资源和字符串资源,ID分别为ID_ICON1和ID_STRING1,然后再加入一个图2所示对话框,其中有一个CheckBox,ID为ID_CHECK1。并且将工程的输出文件名改为CDAUTO.CPL,方法是选择Project菜单的Settings...项,如图5所示。以下是程序的清单。
程序清单:
// CPL.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include <afxdllx.h>
#include <CPL.h>
#include <winreg.h>
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__
#endif
static AFX_EXTENSION_MODULE CPLDLL = { NULL, NULL }
HINSTANCE hinst = NULL
BOOL FAR PASCAL CPLDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
file://控制面板接口函数CPlApplet
extern "C" int APIENTRY CPlApplet(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved)
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("CPL.DLL Initializing!\n")
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(CPLDLL, hInstance))
return 0
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(CPLDLL)
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("CPL.DLL Terminating!\n")
// Terminate the library before destructors are called
AfxTermExtensionModule(CPLDLL)
}
hinst = hInstance
return 1// ok
}
int 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_STRING1
lpCPlInfo->idInfo = IDS_STRING1
break
case CPL_DBLCLK: // application icon double-clicked
FARPROC lpProcDlg
lpProcDlg = (FARPROC)MakeProcInstance(CPLDlg,hinst)
DialogBox(hinst,MAKEINTRESOURCE(IDD_DIALOG1),hwndCPL,(DLGPROC)lpProcDlg)
FreeProcInstance(lpProcDlg)
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
}
BOOL FAR PASCAL CPLDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD dataType
BYTE data[100]
DWORD reserved
DWORD size
HKEY hKey = HKEY_CURRENT_USER
char ValueName[]="Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoDriveTypeAutoRun"
switch(message)
{
case WM_INITDIALOG:
size = 4
if(RegQueryValueEx(HKEY_CURRENT_USER,ValueName,&reserved,&dataType,data,&size)
== ERROR_SUCCESS )
{
if( data[0] == 0x95 )
SendDlgItemMessage(hDlg,IDC_CHECK1,BM_SETCHECK,1,0L)
else
SendDlgItemMessage(hDlg,IDC_CHECK1,BM_SETCHECK,0,0L)
}
return TRUE
case WM_COMMAND:
switch(wParam)
{
case IDOK:
if(SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0L) == BST_CHECKED)
data[0] = 0x95
else
data[0] = 0xb5
data[1] =data[2] = data[3] = 0
size =4
reserved = 0
dataType = REG_BINARY
RegSetValueEx(HKEY_CURRENT_USER,ValueName,reserved,dataType,(BYTE*)data,size)
EndDialog(hDlg,TRUE)
break
case IDCANCEL:
EndDialog(hDlg,FALSE)
break
}
break
}
return FALSE
}
C语言的原型ALGOL 60语言。(也称为A语言)1963年,剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)语言。1967年,剑桥大学的Matin Richards 对CPL语言进行了简化,于是产生了BCPL语言。1970年,美国贝尔实验室的Ken Thompson将BCPL进行了修改,并为它起了一个有趣的名字“B语言”。意思是将CPL语言煮干,提炼出它的精华。并且他用B语言写了第一个UNIX *** 作系统。而在1973年,B语言也给人“煮”了一下,美国贝尔实验室的D.M.RITCHIE在B语言的基础上最终设计出了一种新的语言,他取了BCPL的第二个字母作为这种语言的名字,这就是C语言。为了使UNIX *** 作系统推广,1977年Dennis M.Ritchie 发表了不依赖于具体机器系统的C语言编译文本《可移植的C语言编译程序》。即是著名的ANSI C。1978年Brian W.Kernighian和Dennis M.Ritchie出版了名著《C语言程序》(The C Programming Language),从而使C语言成为当时世界上流行最广泛的高级程序设计语言。1988年,随着微型计算机的日益普及, C语言出现了许多版本。由于没有统一的标准,使得这些C语言之间出现了一些不一致的地方。为了改变这种情况,美国国家标准研究所(ANSI)为C语言制定了一套ANSI标准, 成为现行的C语言标准3.C语言的主要特点 。C语言发展迅速, 而且成为最受欢迎的语言之一, 主要因为它具有强大的功能。许多著名的系统软件, 如DBASE Ⅲ PLUS、DBASE Ⅳ 都是由C 语言编写的。用C语言加上一些汇编语言子程序, 就更能显示C语言的优势了,象PC- DOS 、WORDSTAR等就是用这种方法编写的。ORG 0000HSJMP START
ORG 000BH
SJMP CTCS
START: MOV SP,#40H 设置堆栈指针
MOV TMOD,#01H CTC初始化,定时计数器0工作模式为1
MOV TL0,#0D2H 设置定时计数器0的时长初值:00DCH
MOV TH0,#0FFH
SETB TR0 启动定时计数器0
SETB ET0 允许定时计数器0中断
SETB EA 允许总中断
WAIT:NOP
SJMP WAIT
CTCS: PUSH PSW CTC定时器 中断程序
MOV TL0,#0D2H 重置时长初值
MOV TH0,#0FFH
CPL P1.0 *** 作点亮或关灭灯
CT1:POP PSW
RETI
END
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)