Windows CE下开发控制面板应用程序

Windows CE控制面板为用户提供了一个设置系统参数和属性的小型应用程序运行中心。一个Windows CE操作系统可以包含标准的控制面板应用程序和用户自己开发的控制面板应用程序。

操作系统开发人员也可以通过修改标准控制面板应用程序来定制用户想要的控制面板应用程序。标准控制面板应用程序源代码存放在%_WINCEROOT%/PUBLIC /WCESHELLFE/ OAK/CTLPNL目录下。开发人员在开发控制面板应用程序时可以参考这此源代码。

在Windows CE操作系统下,控制面板由三个部分组成:Ctlpnl.exe、Control.exe和.CPL文件。Ctlpnl.exe和Control.exe是由操作系统来控制控制面板的文件视图和体系结构的。而“.CPL”文件则是用来实现控制面板功能的应用程序。要创建自己的控制面板应用程序,必须创建一个具有由Control.exe体系结构建立的必要的回调函数的“.CPL”文件。

    控制面板应用程序实际上是一个DLL,但是他的扩展名是“.CPL”,其接口函数CplApplet的句柄是CPL_INIT、CPL_GETCOUNT、CPL_NEWINQURE、CPL_STOP、CPL_EXIT。当用户打开控制面板的时候,操作系统搜索“/Windows”目录下的“.CPL”文件并组成控制面板应用程序。

开发一个Windows CE控制面板应用程序的步骤:

(1)       新建一个“Hello World”工程并加入到你的OS设置中。

(2)       新建一个控制面板工程并加入到OS设置中,并添加代码。

(3)       创建一个资源文件并添加必须的资源到你的控制面板应用程序中。

(4)       设置好连接属性。

(5)       连接并从新下载OS并测试你的控制面板应用程序。

步骤

注意:因本实验用Platform Builder 5.0编写,因此要求读者先用Platform Builder 5.0构建一个可以运行在MagicARM270实验箱上的操作系统。再进行本实验的以下步骤。

(1)       按照《PXA270&Windows CE实验教程》1.4小节的操作步骤,使用Platform Builder 5.0生成一个能运行于MagicARM270实验箱上的操作系统。

(2)       新建一个“Hello World”工程

a)             在Platform Build中单击File菜单, 选择New Project or File,在New Project or File窗口中,选择Projects签项,然后选择WCE Application,并在Project name框中输入工程名HelloWorld ,确认Workspace project单选框是选中状态。然后单击OK。如图1.8所示。

图 1.8 新建WCE Application工程

b)            在新建工程向导步骤1到步骤2,输入可选的信息后,单击Next。如图1.9所示。

图 1.9 输入可选信息

c)            在新建工程向导步骤2到步骤3,选择 A typical "Hello World" application 然后单击Finish。如图1.10所示。

图 1.10 选择A typeical”Hello World”applocation

HelloWorld工程出现在Platform Builder开发环境中。在工作区视图的FileView栏和OSDesignView栏可以看到。

d)            切换到FileView栏, 展开Projects,右击HelloWorld工程名然后单击Build Current Project如图 1.11所示。

图1.11 编译工程

编译无错后即可生成一个HelloWorld应用程序。

(3)       创建一个控制面板应用程序

a)         单击File菜单,选择New Project or File,在New Project or File对话框的Projects栏选择WCE Dynamic-Link Library。并在Project name栏输入工程名HelloCPL ,确认Workspaces project单选框被处于选中状态。然后单击OK。 如图 1.12所示。

图1.12 新建WCE Dynamic Link Library工程

b)        出现新建工程向导步骤1到步骤3。输入可选信息后单击NEXT。如图 1.13所示。

c)        确保工程名为HelloCPL。因为在后面系统生成的一些代码中会默认使用这个名字。

d)       注意:请不要在工程名后加“.cpl”扩展名,这将在以后设置工程时自动生成。

图1.13 输入控制面板应有程序的可选信息

e)         在新建工程向导中,选择A DLL that exports some symbols 然后单击Finish。如图 1.14所示。

图1.14  选择为A DLL that exports some symbols

f)         到这里,新建的工程中自动创建了几个头文件、资源文件和源代码文件。你可以研究一下这些文件的内容和结构。请注意一下HelloCPL.h这个头文件的注释。它导出了一些宏给你的DLL使用。

g)        到此,这个控制面板应用程序只是一个简单的外壳,还没有具体的实现代码,下一步,我们将添加具体的代码到这个控制面板应用程序中。

(4)       添加具体的实现代码到控制面板工程中。

a)         在Workspace视图,切换到FileView标签,并展开HelloCPL files节点。再展开Source Files节点,双击HelloCPL.cpp打开源代码文件。这个文件包含了最基本的控制面板应用程序代码。将这个文件的所有代码替换成如程序清单1.3所示的代码。

程序清单 1.3 HelloCPL.cpp文件

//
// HelloCPL.cpp : Defines the entry point for the DLL
//
 
#include "stdafx.h"    // Auto-generated by wizard.
#include "HelloCPL.h"  // Auto-generated by wizard.
#include "resource.h"  // Auto-generated at compile time
 
#include <tchar.h>     // General text functions.
#include "cpl.h"       // Control Panel support.
 
// Returns the number of characters in an expression.
#define lengthof(exp) ((sizeof((exp)))/sizeof((*(exp))))
 
HMODULE g_hModule = NULL;   // Handle to the DLL.
 
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Main entry point for the Control Panel DLL.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C" BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved )
{
  switch (ul_reason_for_call)
  {
    case DLL_PROCESS_ATTACH:
    {
      g_hModule = (HMODULE) hModule;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
       break;
    }
    return TRUE;
}
 
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// The entry point to the Control Panel application.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C" HelloCPL_API LONG CALLBACK CPlApplet(HWND hwndCPL,
                  UINT message, LPARAM lParam1, LPARAM lParam2)
{
  switch (message)
  {
    case CPL_INIT:
      // Perform global initializations, especially memory
      // allocations, here.
      // Return 1 for success or 0 for failure.
      // Control Panel does not load if failure is returned.
      return 1;
 
    case CPL_GETCOUNT:
      // The number of actions supported by this Control
      // Panel application.
      return 1;
 
    case CPL_NEWINQUIRE:
      // This message is sent once for each dialog box, as
      // determined by the value returned from CPL_GETCOUNT.
      // lParam1 is the 0-based index of the dialog box.
      // lParam2 is a pointer to the NEWCPLINFO structure.
    {
      ASSERT(0 == lParam1);
      ASSERT(lParam2);
 
      NEWCPLINFO* lpNewCplInfo = (NEWCPLINFO *) lParam2;
      if (lpNewCplInfo)
      {
         lpNewCplInfo->dwSize = sizeof(NEWCPLINFO);
         lpNewCplInfo->dwFlags = 0;
         lpNewCplInfo->dwHelpContext = 0;
         lpNewCplInfo->lData = IDI_HELLOWORLD;
 
         // The large icon for this application. Do not free this 
         // HICON; it is freed by the Control Panel infrastructure.
         lpNewCplInfo->hIcon = LoadIcon(g_hModule,
          MAKEINTRESOURCE(IDI_HELLOWORLD));
 
          LoadString(g_hModule, IDS_APP_TITLE, lpNewCplInfo->szName,
              lengthof(lpNewCplInfo->szName));
          LoadString(g_hModule, IDS_HELLO, lpNewCplInfo->szInfo,
              lengthof(lpNewCplInfo->szInfo));
         LoadString(g_hModule, IDC_HelloWorld, lpNewCplInfo->szInfo,
              lengthof(lpNewCplInfo->szInfo));
          _tcscpy(lpNewCplInfo->szHelpFile, _T(""));
          return 0;
      }
      return 1;  // Nonzero value means CPlApplet failed.
    }
 
    case CPL_DBLCLK:
    {
      // The user has double-clicked the icon for the
      // dialog box in lParam1 (zero-based).
      PROCESS_INFORMATION pi = {0};
      if (CreateProcess(_T("//Windows//HelloWorld.exe"), NULL, NULL,
             NULL, FALSE, 0, NULL, NULL, NULL, &pi))
      {
           CloseHandle(pi.hThread);
           CloseHandle(pi.hProcess);
           return 0;
      }
      return 1;     // CPlApplet failed.
    }
 
    case CPL_STOP:
             // Called once for each dialog box. Used for cleanup.
    case CPL_EXIT:
             // Called only once for the application. Used for cleanup.
    default:
             return 0;
  }
 
  return 1;        // CPlApplet failed.
  }                    // CPlApplet

上面的这段代码中,DLLMain 和 CPLApplet 都用了“extern “c”声明,这可以确保操作系统能够识别用C语言格式的函数调用。

控制面板应用程序目标代码被编译成动态连接库文件,也就是说,它将生成”.cpl”的目标文件。

当然,在前面的代码中我们也看到了,一个控制面板应用程序并不一定要在”CPL_DBLCLK”消息中处理要做的事,它可以把它要做的事交给另一个进程来完成。

这段代码还使用了一个叫“IDI_HELLOWORLD”的图标和三个名为“IDS_APP_TITLE”、“IDS_HTLLO”、和“IDC_HelloWorld”的字符串资源。在编译之前,你必须把这些资源添加到你的工程中。

(5)       添加资源文件到控制面板应用程序中

要正确编译这个控制面板应用程序,你必须添加以下图标和字符串资源到你的HelloCPL工程中。

l         字符串资源IDS_APP_TITLE、IDS_HELLO 和IDC_HelloWorld。

l         图标资源 IDI_HELLOWORLD。

注意,这些字符串和图标资源名必须跟HelloWorld应用程序的资源名相同。

添加一个资源文件到你的“HelloCPL”工程中。

a)         在“工作区”视图中, 切换到FileView标签栏。

b)        单击File菜单,选择New Project or File。出现New Project or File对话框。

c)        在New Project or File对话框中, 选择Files标签栏并选择Resource Script。在File name栏,输入新的资源文件名名字HelloCPL。确保Add to project复选框处于选中状态并且下面的文本框选择了HelloCPL,单击OK。如图1.15所示。

图1.15 输入文件名

d)        你的资源文件在一个新的窗口中打开。选择HelloCPL.rc窗口。如图1.16所示。

图 1.16 新建的资源文件

e)         创建资源文件后,你的下一步是添加一个字符串资源和一个图标资源到这个文件中,这个字符串用来显示你的控制面板应用程序名字,图标将显示在控制面板中。

(6)       添加一个字符串到你的资源文件中

a)         在“工作区”视图中,选择ResourceView标签,并选择HelloCPL resources。如图1.17所示。

图 1.17 选中HelloCPL Resources

b)        单击Project菜单,选择Insert,并选择Resource。出现Insert Resource对话框。如图 1.18所示。

图1.18 插入新资源对话框

c)        在Insert Resource对话框中,选择String Table然后单击New。

d)        出现字符串编辑窗口。如图1.19所示。

图1.19 字符串编辑窗口

e)         双击字符串窗口中的黑条。在出现的String Properties对话框的ID栏输入IDS_APP_TITLE。 在Caption框中,输入字符串Hello Control Panel。如图1.20所示。然后按回车键关闭对话框。

图1.20 设置IDS_APP_TITLE字符串属性

f)         从复步骤4到步骤6,添加IDS_HELLO和IDC_HelloWorld标识,并设定它们的值为A sample Control Panel application。如图1.21和图1.22所示。

图1.21设置IDS_HELLO字符串属性

图1.22设置IDS_HelloWorld字符串属性

g)        关闭字符串编辑窗口。

新建工程对话框并不会自动生成DLL程序图标,你必须自己给HelloCPL添加一个图标,它才能显示在控制面板中。

 

(7)       添加一个图标到资源文件中

a)         在“工作区”视图中,选择ResourceView标签。

b)        在ResourceView标签中,右击HelloCPL resources然后选择Import。如图1.23所示。

图1.23 导入资源文件

出现Import Resource对话框。如图 1.24所示。

图1.24 选择要导入的资源文件

c)        打开Hello World应用程序所在的目录。选择图标(.ico)文件,然后单击Import。如图1.25所示。

图1.25 找到HelloWorld工程的图标文件

d)        在ResourceView标签栏,你可以看到一个刚才导入的图标资源标识符。右击这个资源标识符,并选择Properties。如图 1.26所示。

图1.26 设置图标的属性

出现Properties对话框。

e)         将资源标识符的ID改为“IDI_HELLOWORLD”然后按回车键关闭对话框。如图1.27所示。

图1.27 输入图标属性的ID值

Platform Builder将在编译时处理这个资源文件并且创建一个Resources.h文件到你的工程目录中。

在HelloCPL.cpp中使用#include “resource.h”即可将这此资源标识符包含到你的代码中。

虽然你在工程中添加了一个资源文件,但Resource.h头文件并没有被添加在工程的头文件夹中,所以它并不会出现在工程的头文件夹下。因些,需在HelloCPL.cpp中使用#include “resource.h”命令把资源标识符包含到你的代码中。

(8)       编译一个控制面板应用程序

要让操作系统将一个DLL文件当作一个控制面板应用程序来处理,这个文件必须连接成一个扩展名为(.cpl)的文件。

在控制面板中,.cpl文件必须放在/Windows目录下,操作系统才会把它当作一个控制面板应用程序来对待。不过这是编译器默认的行为,因此,我们不需要作其它的设置。

注意:以下的步骤描述了怎么设置一个工程为控制面板工程,然而,由于上下文的关系,你也可以将它设置成不同的值以应用在你自己的工程中。但你必须完成以下所有的步骤。

a)             在“工作区”视图中,选择FileView标签。

b)            单击“Build OS”菜单,选择“Set Active Configuration”。出现Active Configuration对话框。如图 1.28所示。

图1.28 设置活动配置对话框

c)            在Set Active Configuration对话框中,选择编译目标代码为release 。单击OK  关闭对话框。

虽然你只配置好了一个工程,但是你的其它工程也将被设置成相同的配置,你可以检查一下是否在IDE中打开的编译工具条。

(9)       将输出文件扩展名由dll改为cpl.

a)             在“工作区”视图中,选择FileView标签。

b)            右击HelloCPL 工程并选择Settings。出现设置工程对话框。如图1.29所示。

图1.29 设置工程对话框

c)        选择General标签栏,在Custom Variables域中,单击“... ”按钮打开Custom Variables对话框。如图1.30所示。

图1.30 Custom Variables对话框

d)        单击New按钮。在Environment Variable对话框中,在Variable name文本框中输入“CPL”,并在Variable value中输入“1”,单击OK关闭Environment Variable对话框。再次单击OK关闭Custom Variables对话框。如图1.31所示。

图1.31 新建环境变量对话框

这将强制HelloCPL应用程序名字为.cpl扩展名而不是.dll扩展名。

e)         在工程设置对话框中单击C/C++标签栏,将应用程序头文件包含进来。在Include Directories域,输入“$(_PROJECTROOT)/cesysgen/oak/inc ”。如图1.32所示。

图1.32 设置编译预处理目录

单击OK关闭工程设置对话框。

f)         在文件视图中,定位到HelloCPL/Parameter 文件节点并双击HelloCPL.bib文件,将它的内容替换成如程序清单1.4所示的内容。

程序清单 1.4 HelloCPL.bib文件

         MODULES

HelloCPL.cpl $(_FLATRELEASEDIR)/HelloCPL.cpl           NK

g)        设置DLL Entry Point域为DllMain。如图1.33所示。

图1.33 设置DLL 入口函数

h)        单击OK关闭工程设置对话框。

(10)   编译生成HelloCPL工程。

a)             在“工作区”中选择FileView标签栏,并选择HelloCPL 工程。

b)            要编译HelloCPL工程,在Build Project菜单中,确保以下选项是选中的。如图1.34所示。

l         Clean Before Building

l         Make Run-Time Image Before Build

图1.34 检查编译选项

c)        单击Build Project菜单中的Build Current Project。如图1.35所示。

图1.35 编译工程

编译连接完成后,将生成新的NK.NB0文件。

d)        下载新的NK.NB0文件到目标系统中,打开设置,控制面板,即可看到HelloCPL控制面板应用程序,如图 1.36所示。双击运行即可看到Hello World!。如图1.37所示。


Hello Control Panel 控制面板应用程序



图1.36 出现在控制面板中的Hello Control Panel程序

图1.37 HelloCPL程序的运行结果