程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 控制面板的編程

控制面板的編程

編輯:Delphi

  大家應該都非常熟悉控制面板吧,大家也都有操作過控制面板吧,但如何使用Delphi對控制面板進行編程呢?
  一、控制面板的原理
  下面我就來講講控制面板的原理:控制面板在Windows中的system目錄下,其中所有以CPL為擴展名的,就都是我們的控制面板。要想對控制面板進行編程,就要對CPlApplet這個函數非常熟悉,它是構成CPL文件的核心,原型如下:
  function CPlAPPTet(
  hwndCPL:HWND;
  uMsg:UINT;
  lParam1:LPARAM;
  lParam2:LPARAM
  ):LongInt;stdcall;
  參數說明:
  hwndCPL:激活控制面板組件的應用程序窗口handle。
  uMsg:由外界傳入的控制消息。
  lParam1:根據消息種類而定的參數1。
  lParam2:根據消息種類而定的參數2。
  返回值:根據消息種類而定。
  當我們想編程激活某個CPL文件時,就會加載此CPL文件,取得CPlApplet函數地址然後調用它。而CPlApplet函數的任務是,根據uMsg消息參數得知外界的請求並做出適當響應。可以傳入的消息種類如下表所示:
   
  CPL_INIT CPL文件加載後 供CPL文件有機會進行各控制面板組件的數據結構、變量及配置內存等初始化及前置工作
  CPL_GETCOUNT 緊接在CPL_INIT消息後 取得CPL文件提供的控制面板組件數目
  CPL_INQUIRE 緊接在CPL_GETCOUNT消息後 取得個別控制面板的信息
  CPL_NEWINQUIRE 緊接在CPL_INQUIRE消息後 取得個別控制面板的信息,作用與消息CPL_INQUIRE相同,但應用場合不同,組件通常只須選擇二者之一支持即可
  CPL_DBLCLK 激活個別組件前 激活某一控制面板組件,通常的響應都是顯示Modal對話框供用戶設置
  CPL_STOP 激活個別組件後 激活中的控制面板組件關閉後,控制面板程序會送出此消息進行個別組件的善後工作
  CPL_EXIT 釋放CPL文件前 控制面板程序要釋放此CPL文件前會送出此消息,提供資源釋放或其它善後工作的機會
  二、CPlApplet函數的詳解
  現在我就來講講,以上列表中各個消息的詳細作用:
  1、CPL_INIT:lParam1、lParam2:均未使用。返回值:成功返回非零值;失敗返回零。
  CPL程序第一個收到的消息一定是CPL_INIT,這時我們可以利用此機會初始化所有控制面板組件共享的數據結構及變量。若初始化失敗,返回零,這會使得控制面板不繼續傳送其它消息給此CPL文件,而這個CPL包含的控制面板的組件就不會出現在控制面板內。
  2、CPL_GETCOUNT:lParam1、lParam2:均未使用。返回值:返回此CPL文件所支持的控制面板組件數目。
  繼CPL_INIT消息後,緊接著會收到CPL_GETCOUNT消息,此時必須返回CPL文件所支持的控制面板組件數目。
  3、CPL_INQUIRE:lParam1:組件編號,值為0~(CPL_GETCOUNT返回數目-1)。lParam2:指向TCPLInfo結構的指針。返回值:成功返回零,失敗返回非零。
  CPL_INQUIRE是編程中最重要的消息,控制面板就是利用這個消息來取得每個組件的確良名稱、描述及圖標。參數一傳入組件編號,我們必須根據組件編號將對應的組件信息填入參數2指向的TCPLInfo結構中。
  TCPLInfo結構定義如下:
  TCPLInfo=pccked record
  idIcon:integer;//指向組件圖標
  idName:integer;//指向組件名稱
  idInfo:integer;//指向組件描述CPL_DBLCLKCPL_STOP
  lData:Longint;//用戶自定義參數
  end;
  idIcon、idName、idInfo這三個字段是存放組件圖標、名稱、描述的,我們要調用LoadString及LoadIcon API函數,從CPL文件中取得實際字符串及圖標的。
  lData字段的類型為Longint,長度為4個字節的無符號整數,不過也可改為指針變量來使用,lData中的值會在控制面板程序下次傳送CPL_DBLCLK、CPL_STOP消息時由lParam2參數返回供組件使用,你可以自由決定它的功能。
  4、CPL_NEWINQUIRE:lParam1:組件編號,值為0~(CPL_GETCOUNT返回數目-1)。lParam2:指向TNewCPLInfo結構的指針。返回值:成功返回零,失敗返回非零。TNewCPLInfo結構比TCPLInfo結構稍微復雜,定義如下:
  TNewCPLInfo=pccked record
  dwSize:DWord;//結構占用長度
  dwFlags:DWord;//目前未使用
  dwHelpContext:DWord;//說明頁編號,目前未使用
  lData:Longint;//用戶自定義參數
  hIcon:HICON;//組件圖示
  szName:array[0..31] of char;//組件名稱
  szInfo:array[0..63] of char;

  szHelpFile:array[0..127] of char;//說明文件名,目前未使用
  end;
  szName、szInfo 、hIcon、lData這4個字段與上一個CPLInfo結構中對應的4個字段作用完全相同,只不過szName、szInfo 、hIcon字段變成為字符串及HICN類型了。這使得CPL程序可以動態地根據情況來產生及返回組件的名稱、描述及圖標。
  5、CPL_DBLCLK:lParam1:組件編號,值為0~(CPL_GETCOUNT返回數目-1)。lParam2:指向TCPLInfo或TNewCPLInfo結構的返回的lData字段值。返回值:成功返回零,失敗返回非零。
  當我們雙擊控制面板中的組件圖標時,就會觸發CPL_DBLCLK消息。這個就是我們用來打開控制面板,打開相應的對話框,然後來設置用的。
  6、CPL_STOP:lParam1:組件編號,值為0~(CPL_GETCOUNT返回數目-1)。lParam2:指向TCPLInfo或TNewCPLInfo結構的返回的lData字段值。返回值:成功返回零,失敗返回非零。
  這個消息提供機會讓個別組件進行善後工作,例如釋放GDI或核心對象等等。如果一切無誤,返回零。
  7、CPL_EXIT:lParam1、lParam2:均未使用。返回值:成功返回零;失敗返回非零值。就是退出啦。
  好了,關於控制面板的研究,到此就告一段落了,若想對它進行深入的編程,可轉入到實例中進行練習練習。三、我的控制面板的制作
  大家一定用過Windows優化大師吧,它裡面有個控制面板,可以把我們電腦裡的控制面板都顯示出來,我們經過了前面的學習,是否可以也編一個類似的程序呢?回答是肯定的。下面我們就來編個看看吧!
  經過我們觀察,決定用TlistVIEw控件 。
  為了美觀,TlistView控件做如下設置:Checkboxes設為True;Columnclick設為False;FlatScrollBar設為True;SortType設為stText;VIEwStyle設為vsReport;單擊Columns,加上三個數值:項目名稱、項目說明、項目作用。在USES中加入聲明:CPL。
  編程代碼:
  procedure TForm1.FormCreate(Sender: TObject);
  procedure newvIEw(ANode: TListItem);
  var
  hLib : THandle;
  CPLProc : TCPLApplet;//指向 CPlApplet 函數的指針
  iCount, I : Integer; // 用來取得控制面板的結構
  cplInfo : TCPLInfo;

  // 記錄元件的名稱、描述及圖標
  sName, sInfo: array[0..255] of char;
  hAppIcon : hIcon;
  begin
  
  hLib := LoadLibrary(PChar(ANode.Caption));
  if hLib = 0 then
  begin
  ANode.SubItems.Add(' - 無法加載!!');
  Exit;
  end;
  try
  
  CPLProc := TCPLApplet(GetProcAddress(hLib, 'CPlApplet'));
  if @CPLProc = nil then Exit;
  if CPLProc(Handle, CPL_INIT, 0, 0) = 0 then Exit;
  
  iCount := CPLProc(Handle, CPL_GETCOUNT, 0, 0);
  for I := 0 to iCount - 1 do
  begin
  
  FillChar(cplInfo, sizeof(TCPLInfo), 0);
  CPLProc(Handle, CPL_INQUIRE, I, LongInt(@cplInfo));
  
  LoadString(hLib, cplInfo.idName, @sName, 255);
  LoadString(hLib, cplInfo.idInfo, @sInfo, 255);
  hAppIcon := LoadIcon(hLib,MAKEINTRESOURCE(cplInfo.idIcon));
  
  ANode.SubItems.Add(sName);
  ANode.SubItems.Add(sInfo);
  
  end;
  CPLProc(Handle, CPL_EXIT, 0, 0);
  finally
  FreeLibrary(hLib);

  end;
  end;
  var
  sSysdir:array[0..255] of char;
  SearchRec:TSearchRec;
  J: Integer;
  NewItem: TListItem;
  begin
  GetsystemDirectory(sSysdir,255);//取得系統目錄
  J:=FindFirst(sSysdir+'*.cpl',faAnyFile,SearchRec);//開始尋找系統目錄下的CPL文件
  while J=0 do
  begin

  NewItem:=ListVIEw1.Items.add;
  NewItem.caption:=AnsiLowerCase(searchRec.name);
  NewView(NewItem);//調用自定義函數NewVIEw
  J:=FindNext(searchRec);//尋找下一個CPL文件
  end;
  FindClose(searchRec);
  end;
  若想雙擊進行運行選中的控制面板,代碼如下:
  procedure TForm1.ListVIEw1DblClick(Sender: TObject);
  var
  hLib : THandle;
  CPLProc: TCPLApplet;
  NewItem: TListItem;
  cplInfo: TCPLInfo;

  begin
  NewItem:=ListVIEw1.Selected;
  if (not Assigned(NewItem)) then Exit;
  hLib := LoadLibrary(PChar(NewItem.Caption));//加載CPL文件, CPL文件名就是項目名
  
  if hLib = 0 then
  begin
  MessageDlg('無法運行' + NewItem.Caption,
  mtError,[mbOK], 0);
  Exit;
  end;
  
  CPLProc := TCPLApplet(GetProcAddress(hLib, 'CPlApplet'));
  if @CPLProc <> nil then
  begin
  CPLProc(Handle, CPL_INIT, 0, 0);//運行面板
  FillChar(cplInfo, sizeof(TCPLInfo), 0);
  CPLProc(Handle, CPL_INQUIRE, NewItem.Index, LongInt(@cplInfo));
  CPLProc(Handle, CPL_DBLCLK, NewItem.Index, cplInfo.lData);
  CPLProc(Handle, CPL_STOP, NewItem.Index, cplInfo.lData);
  CPLProc(Handle, CPL_EXIT, 0, 0);
  end;
  FreeLibrary(hLib);//釋放CPL文件
  end;
  好了,編程完畢。程序在Windows98+Delphi5下調試通過。
  如果大家不想麻煩編寫這麼多代碼的話,可以寫信向本人索取源代碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved