WEB开发网
开发学院软件开发VC 编写控制面板程序的一个例子 阅读

编写控制面板程序的一个例子

 2009-10-24 20:31:26 来源:WEB开发网   
核心提示:例子程序的实现代码很象典型的MFC文档/视图应用,所不同的是它的APP类派生于CControlPanelApp,编写控制面板程序的一个例子(2),而不是CWinApp, 并且不用改写InitInstance来添加文档模板,Windows发送CPL_DBLCK消息, 这个消息被映射到CCPApplet::OnLaunch

例子程序的实现代码很象典型的MFC文档/视图应用,所不同的是它的APP类派生于CControlPanelApp,而不是CWinApp, 并且不用改写InitInstance来添加文档模板,它用一个名为OnInit函数创建控制面板应用,OnInit创建了两个面板程序:

BOOL CMyControlPanelApp::OnInit()
{
   AddApplet(new CCPApplet(IDR_MYAPPLET1,
   RUNTIME_CLASS(CMyDialog)));
   AddApplet(new CCPApplet(IDR_MYAPPLET2,
   RUNTIME_CLASS(CMyPropSheet)));
   return CControlPanelApp::OnInit();
}

CCPApplet是个很通用的类 ,在例子程序中使用它时都不必再派生新类,其运行机制也很透明。真正需要自己编写代码的部分是对话框本身。MyCtrlPanel实现一个对话框CMyDialog和一个属性页CMyPropSheet。不管你相不相信,就这么简单, 创建一个对话框,并象上述那样重载CControlPanelApp::OnInit,剩下的事情都交给迷你框架来做。

到这里我们只完成了一部分工作,下面我们要描述由框架负责的那部分工作,比如:在哪里获取图标以及描述性信息、CPlApplet函数 的实现在哪里?CPL消息的处理例程等等。所有这些工作都由CControlPanelApp 和 CCPApplet来完成。CPanel.cpp中有一个CPlApplet函数负责将CPL消息转换成虚拟函数调用。当控制面板以消息CPL_INIT 调用 CPlApplet时,CPlApplet再调用CControlPanelApp::OnCplMsg,然后依次将控制传到CControlPanelApp::OnInit。OnCplMsg是CWnd::WindowProc的模拟,OnInit 类似于消息处理函数,如OnCreate。有些CPL消息如CPL_INQUIRE、CPL_DBLCLK等都有面板程序号(索引),用lParam1进行传递,这些消息被传到索引指示的程序。(记住:单个控制面板扩展 可以实现一个以上的图标或应用)。此时CControlPanelApp::OnCplMsg将消息处理路由到CCPApplet类的某个虚拟函数,而非CControlPanelApp。

以上我们介绍了一大堆的类代码运行逻辑,将底层的DLL调用和消息代码映射到较高级C++雷和虚拟函数。可光有逻辑是不行的,要实现这个逻辑才有价值。CControlPanelApp 和 CCPApplet 便是最终的结果。它们根据给定的静态信息实现了需要的处理。当你创建一个新的控制面板应用时,只要给构造函数一个资源ID和一个MFC运行时类:

AddApplet(new CCPApplet(IDR_MYAPPLET2,
RUNTIME_CLASS(CMyPropSheet)));

这就是框架实现控制面板应用时需要的全部信息。AddApplet将应用添加到m_lsApplets列表。默认的CPL_GETCOUNT消息处理函数可以返回列表中 应用的个数。当控制面板发送CPL_INQUIRE 或 CPL_NEWINQUIRE消息时,CCPApplet使用资源ID来获得应用的图标、名字和描述。名字和描述被解析为主资源串中的子串。

STRINGTABLE PRELOAD DISCARDABLE?
BEGIN
IDR_MYAPPLET3 "Intergalactic\n
Intergalactic settings for space cadets\n\n"
END

这类似于MFC使用IDR_MAINFRAME处理串资源情况,如应用程序名、文当类型、COM ProgID等。只要按规范定义图标和资源串,就不必再实现OnInqure 或者 OnNewInqure,调用默认的实现即可。另外,这里要对CPL_INQUIRE 和 CPL_NEWINQUIRE消息的处理要做一点说明,CPL_NEWINQUIRE是新增的消息。一般说来,一个应用只要实现OnInqure就可以了,但如果 面板应用程序的信息从一个SESSION到另一个SESSION的过程中是可变的(似乎有点不可思议),那么就只需实现OnNewInquire,如果是这样,应将CCPApplet::m_bDynamic赋值为TRUE; 以便告诉框架旁路掉对CPL_INQUIRE消息的处理,也就是让它返回FALIED,从而让控制面板程序去处理CPL_NEWINQUIRE消息。 是不是有点神奇啊!就是为什么你能忽略所有的那些细节,仅仅使用资源串就能搞掂的缘故。

当用户双击控制面板中的应用图标时,Windows发送CPL_DBLCK消息。 这个消息被映射到CCPApplet::OnLaunch,此函数用对话框或者属性页的运行时类来创建一个实例,并调用DoModal:

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;
   }
}

Tags:编写 控制 面板

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接