<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      使用COM技術完成外殼擴展的屬性頁

      [摘要]當用戶在資源管理器中調用右鍵菜單時,會顯示一個"屬性"菜單項,點擊屬性菜單項會顯示一個屬性頁,用戶可以獲得甚至修改文件信息。我們可以定制屬性頁通過實現屬性頁擴展。如下圖所示,本文...
      當用戶在資源管理器中調用右鍵菜單時,會顯示一個"屬性"菜單項,點擊屬性菜單項會顯示一個屬性頁,用戶可以獲得甚至修改文件信息。我們可以定制屬性頁通過實現屬性頁擴展。如下圖所示,本文實現了一個顯示wave(波形)文件的信息如聲道數等信息的屬性頁擴展。

        屬性頁擴展通常是同某類文件相關聯的來實現同之相關的操作和信息顯示,另外可以同驅動器相關聯,我們還可以用屬性頁擴展來替換控制面板程序的屬性頁。象其他外殼擴展程序一樣,屬性頁擴展也是以動態連接庫形式實現的進程內COM對象。它除了IUnknown接口外還要實現IShellExtInit和IShellPropSheetExt接口。

        建立同文件關聯的屬性頁擴展

        首先,我們用命令File New...,創建一個ActiveX Library,然后新建一個COM Object,實現的接口為IShellExtInit和IShellPropSheetExt。

        同文件建立關聯需要注冊屬性頁,要在注冊表中同相應文件對應的表項下添加Shellex/PropertySheetHandlers子鍵,每增加一個頁面就需要注冊一個表項,最大可以添加的頁面數是24,我們可以用一個擴展實現多個頁面。這里我們通過從TComObjectFactory繼承類實現的UpdateRegistry實現了注冊。

        

        type

          TCXPropSheetFactory=class(TComObjectFactory)

         public

          procedure UpdateRegistry(Register: Boolean); override;

         end;

        procedure TCXPropSheetFactory.UpdateRegistry(Register: Boolean);var

          ClassID: string;

          Str,KeyName : string;begin

          inherited UpdateRegistry(Register);

        if Register then

        begin

          ClassID:=GUIDToString(Class_CXPropSheet);

          with TRegistry.Create do

          try

          RootKey:=HKEY_CLASSES_ROOT;

          OpenKey(’\.wav’,TRUE);

          KeyName := ReadString(’’);

         if Keyname = ’’ then

         begin

          WriteString(’’,’WaveFile’);

          OpenKey(’\.wav’,TRUE);

          KeyName := ReadString(’’);

         end;

          OpenKey(’\’+KeyName+’\shellex\Propert eetHandlers\Wav’,TRUE);

          WriteString(’’,Classid);

          finally

          Free;

        end;

        if(Win32Platform=VER_PLATFORM_WIN32_NT)then

        begin

          with TRegistry.Create do

          try

          RootKey:=HKEY_LOCAL_MACHINE;

          OpenKey(’SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions’, True);

          OpenKey(’Approved’, True);

          WriteString(ClassID, ’Wave File Property Sheet’);

          finally

          Free;

          end;

         end;

        end

        else

        刪除注冊表項....................... end;初始化擴展是通過IShellExtInit實現的,當外殼調用IShellExtInit.Initialize時,它傳遞一個數據對象包含來文件對應的目錄的PIDL標識符。Initialize方法需要從數據對象中提取文件名,并把文件名和PIDL標識符保存起來為了以后使用。

        

        function TCXPropSheet.SEIInitialize(pidlFolder: PItemIDList;

          lpdobj: IDataObject; hKeyProgID: HKEY): HResult;

        var

          StgMedium: TStgMedium;

          FormatEtc: TFormatEtc;

          szFile: array[0..MAX_PATH+1]of Char;

          filecount: integer;begin

          Result:=E_FAIL;

        if(lpdobj=nil)then

        begin

          Result:=E_INVALIDARG;

          messagebox(0, ’1’, ’錯誤’, mb_ok);

          Exit;

        end;

        with FormatEtc do

        begin

          cfFormat:=CF_HDROP;

          ptd:=nil;

          dwAspect:=DVASPECT_CONTENT;

          lindex:=-1;

          tymed:=TYMED_HGLOBAL;

        end;

        Result:=lpdobj.GetData(FormatEtc, StgMedium);

        if Failed(Result)then

        Exit;

        //如果只有一個文件被選中,獲得文件名并保存。

        filecount:=DragQueryFile(stgmedium.hGlobal, $FFFFFFFF, nil, 0);

        if filecount=1 then

        begin

          Result:=NOERROR;

          DragQueryFile(stgmedium.hGlobal, 0, szFile, SizeOf(szFile));

          FFilename:=strpas(szFile);

        end;

        ReleaseStgMedium(StgMedium);end;添加頁面的操作是通過IShellPropSheetExt接口來實現的。如果屬性頁是和文件相關聯,外殼會調用IShellPropSheetExt.AddPages給屬性頁添加一個頁面。如果屬性頁同控制面板程序相關聯,外殼調用IShellPropSheetExt.ReplacePage來替換頁面。

        IShellPropSheetExt.AddPages方法有兩個參數,lpfnAddPage是一個指向AddPropSheetPageProc回調函數的指針,回調函數用來提供要添加的頁面信息給外殼。lParam是一個用戶自定義的值,這里我們用它來返回給回調函數對象。

        一般的IShellPropSheetExt.AddPages方法實現步驟是:

        給PROPSHEETPAGE結構設定正確的值,特別是:

        把擴展的對象引用記數變量付值給pcRefParent成員,這可以防止頁面還在顯示時,擴展對象被卸載。

        實現PropSheetPageProc回調函數來處理頁面創建和銷毀的情況。

        調用CreatePropertySheetPage函數來創建頁面。

        調用lpfnAddPage指向的函數來來添加創建好的頁面。

        function TCXPropSheet.AddPages(lpfnAddPage: TFNADDPROPSHEETPAGE;

        lParam: LPARAM): HResult;var

        PSP: TPropSheetPage;

        HPSP: HPropSheetPage;begin

        result:=E_FAIL;

        try

        psp.dwSize:=SizeOf(psp);

        psp.dwFlags:=PSP_USEREFPARENT or PSP_USETITLE or PSP_USECALLBACK;

        psp.hInstance:=hInstance;

        //這里我們使用了事先儲存在wave.res中的對話框模板,模板是用delphi5自帶的

        //resource workshop編輯的,使用delphi5\bin\brcc32.exe編譯的。

        psp.pszTemplate:=MakeIntResource(100);

        //標題名

        psp.pszTitle:=’波文件信息’;

        //設定回調函數

        psp.pfnDlgProc:=@DialogProc;

        psp.pfnCallBack:=@PropCallback;

        //設定對象引用記數變量

        psp.pcRefParent:=@comserver.objectcount;

        //用lParam向回調函數傳遞對象

        psp.lParam:=integer(self);

        HPSP:=CreatePropertySheetPage(psp);

        if HPSP$#@60;$#@62;nil then begin

        if not lpfnAddPage(HPSP, lParam)then begin

        DestroyPropertySheetPage(HPSP);

        end else begin

        _addref;//增加引用記數,否則一脫離這個方法的作用域,delphi自動釋放對象。

        result:=S_OK;

        end

        end

        except

        on e: exception do begin

        e.message:=’添加頁面’+e.message;

        messagebox(0, pchar(e.message), ’錯誤’, mb_ok);

        end;

        end;end;

        function TCXPropSheet.ReplacePage(uPageID: UINT;

        lpfnReplaceWith: TFNADDPROPSHEETPAGE; lParam: LPARAM): HResult;begin

        Result:=E_NOTIMPL;//同文件關聯時,外殼不調用ReplacePage,所以不用實現end;回調函數處理屬性頁的消息,主要要響應WM_INITDIALOG消息來初始化頁面顯示信息,響應WM_COMMAND消息來處理用戶交互,響應WM_NOTIFY消息來處理頁面切換或關閉后處理操作結果。

        

        function DialogProc(hwndDlg: HWnd; Msg: UINT; wParam: wParam;

        lParam: LPARAM): Bool; stdcall;

        var

          PageObj: TCXPropSheet;

          filename: string;

          displayName : string;

          SheetHWnd: HWnd;

        begin

          result:=false;

          try

          if Msg=WM_INITDIALOG then begin//初始化界面

        //獲得lparam傳遞過來的對象

          pageObj:=TCXPropSheet(PPropSheetPage(lParam)^.lParam);

        //保存對象信息

          SetWindowLong(hwndDlg, DWL_USER, integer(pageObj));

        //設置界面顯示波文件信息

          SetDlgItemText(hwndDlg, 100, PChar(ExtractFileName(PageObj.FFileName)));

          OpenMedia(PageObj.FFileName);

        SetDlgItemText(hwndDlg, 101, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_AVGBYTESPERSEC))));

        SetDlgItemText(hwndDlg, 102, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_BITSPERSAMPLE))));

        SetDlgItemText(hwndDlg, 103, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_CHANNELS))));

        CloseMedia;

          SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);

          Result:=TRUE;

        end

        else if(Msg=WM_COMMAND)then begin

        if Lo(wParam)=110 then//用戶點擊了關于按鈕(id=110)

          MessageBox(0,’作者:hubdog’+#13#10+’email:hubdog@263.net’,’關于...’,MB_OK);

        end else if(msg=WM_NOTIFY)then begin

          sheetHwnd:=getparent(hwndDlg);//獲得屬性頁的窗口句柄

          case PNMHdr(lparam)^.code of

        //頁面失去焦點

          PSN_KILLACTIVE:

        begin

          SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);

          Result:=TRUE;

        end;

        end;

        end;

          except

          on e: exception do begin

          e.message:=’回調處理’+e.message;

          messagebox(0, pchar(e.message), ’錯誤’, mb_ok);

        end;

        end;

        end;

        

        建立同驅動器相關聯的屬性頁擴展用

        同上面講的有兩點不同:

        IShellExtInit.Initialize方法傳遞過來的數據對象包含的驅動器路徑可能是CFSTR_MOUNTEDVOLUME格式而不是CF_HDROP格式的。標準驅動器是CF_HDROP格式的,而在NTFS文件系統中映射的遠程設備則是CFSTR_MOUNTEDVOLUME格式的。

        注冊表項是HKEY_CLASSES_ROOT\Drive\Shellex\PropertySheetHandlers子鍵。

        建立控制面板屬性頁擴展

        同上面講的有兩點不同:

        控制面板程序調用IShellPropSheetExt.ReplacePage方法來替換頁面,它不調用IShellPropSheetExt。AddPages方法。

        注冊方式:子鍵可以在不同位置創建,這依賴于擴展是針對用戶還是針對機器的。對用戶方式子鍵是HKEY_CURRENT_USER\REGSTR_PATH_CONTROLPANEL,否則子鍵是HKEY_LOCAL_MACHINE\REGSTR_PATH_CONTROLSFOLDER。

        本程序在Delphi5,Win NT 4.0,K6-233系統下調試成功。例子程序可以到http://chaozhi.com/lgc去下載


      日韩精品一区二区三区高清