本文共 13285 字,大约阅读时间需要 44 分钟。
示例代码:使用语法解决继承接口的命名冲突 |
TCCContextMenu = class(TComObject, IShellExtInit) private FFileList: TStringList; FGraphic: TGraphic; protected { IShellExtInit 接口 } function IShellExtInit.Initialize = SEInitialize; function SEInitialize(pidFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; stdcall; public procedure Initialize; override; destructor Destroy; override; |
示例代码:IShellExtInit.Initialize. 可以被任何实现IShellExtInit 的类所调用 |
function TCCContextMenu.SEInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; begin Result := GetFileListFromDataObject(lpdobj, FFileList); end; function GetFileListFromDataObject(lpdobj: IDataObject; sl: TStringList): HResult; var fe: FormatEtc; sm: StgMedium; i, iFileCount: Integer; FileName: array[0..MAX_PATH+1] of char; begin assert(lpdobj<>nil); assert(sl<>nil); sl.clear; with fe do begin cfFormat := CF_HDROP; ptd := nil; dwAspect := DVASPECT_CONTENT; lindex := -1; tymed := TYMED_HGLOBAL; end; with sm do begin tymed := TYMED_HGLOBAL; end; Result := lpdobj.GetData(fe, sm); if Failed(Result) then Exit; iFileCount := DragQueryFile(sm.hGlobal, $ffffffff, nil, 0); if iFileCount<=0 then begin ReleaseStgMedium(sm); Result := E_INVALIDARG; Exit; end; for i:=0 to iFileCount-1 do begin DragQueryFile(sm.hGlobal, i, FileName, sizeof(FileName)); sl.Add(FileName); end; ReleaseStgMedium(sm); Result := S_OK; end; |
示例代码: QueryContextMenu |
const // 菜单类型 mfString = MF_STRING or MF_BYPOSITION; mfOwnerDraw = MF_OWNERDRAW or MF_BYPOSITION; mfSeparator = MF_SEPARATOR or MF_BYPOSITION; // 菜单项 idCopyAnywhere = 0; // 复制(移动) idRegister = 5; // 注册ActiveX idUnregister = 6; // 取消注册ActiveX idImagePreview = 10; // 预览图片文件 idMenuRange = 90; // 在SDK 中是使用宏Make_HRESULT 实现的,Delphi 没有宏的概念,所以这里用函数 function Make_HResult(sev, fac, code: Word): DWord; begin Result := (sev shl 31) or (fac shl 16) or code; end; function TCCContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; var Added: UINT; begin if(uFlags and CMF_DEFAULTONLY)=CMF_DEFAULTONLY then begin Result := Make_HResult(SEVERITY_SUCCESS, FACILITY_NULL, 0); Exit; end; Added := 0; // 加入CopyAnywhere 菜单项 InsertMenu(Menu, indexMenu, mfSeparator, 0, nil); InsertMenu(Menu, indexMenu, mfString, idCmdFirst+idCopyAnywhere, PChar(sCopyAnywhere)); InsertMenu(Menu, indexMenu, mfSeparator, 0, nil); Inc(Added, 3); Result := Make_HResult(SEVERITY _SUCCESS, FACILITY_NULL, idMenuRange); end; |
示例代码: InvokeCommand |
function TCCContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; begin Result := E_INVALIDARG; if HiWord(Integer(lpici.lpVerb))<>0 then Exit; case LoWord(Integer(lpici.lpVerb)) of idCopyAnywhere: DoCopyAnywhere(lpici.hwnd, FFileList); end; Result := NOERROR; end; procedure DoCopyAnywhere(Wnd: HWND; sl: TStringList); var frm: TfrmCopyAnywhere; begin frm := TfrmCopyAnywhere.Create(Application); try frm.AddFiles(sl); frm.ShowModal; finally frm.Free; end; end; |
示例代码: GetCommandString |
function TCCContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult; var strTip: String; wstrTip: WideString; begin strTip := ‘‘; Result := E_INVALIDARG; if (uType and GCS_HELPTEXT)<> GCS_HELPTEXT then Exit; case idCmd of idCopyAnywhere: strTip := sCopyAnywhereTip; end; if strTip<>‘‘ then begin if (uType and GCS_UNICODE)=0 then //Anse begin lstrcpynA(pszName, PChar(strTip), cchMax); end else begin wstrTip := strTip; lstrcpynW(PWideChar(pszName), PWideChar(wstrTip), cchMax); end; Result := S_OK; end; end; |
示例代码:实现Context Menu Extension 的类工厂 |
procedure TCCContextMenuFactory.UpdateRegistry(Register: Boolean); procedure DeleteRegValue(const Path, ValueName: String; Root: DWord=HKEY_CLASSES_ROOT); var reg: TRegistry; begin reg := TRegistry.Create; with reg do begin try RootKey := Root; if OpenKey(Path, False) then begin if ValueExists(ValueName) then DeleteValue(ValueName); CloseKey; end; finally Free; end; end; end; const RegPath = ‘*\shellex\ContextMenuHandlers\CCShellExt’; ApprovedPath = ‘Software\Microsoft\Windows\CurrentVersion\ShellExtensions\Approved’; var strGUID: String; begin inherited; strGUID := GUIDToString(Class_CCContextMenu); if Register then begin CreateRegKey(RegPath, ‘‘, strGUID); CreateRegKey(ApprovedPath, strGUID, ‘CC 的外壳扩展’, HKEY_LOCAL_MACHINE); end else begin DeleteRegKey(RegPath); DeleteRegValue(ApprovedPath, strGUID, HKEY_LOCAL_MACHINE); end; end; |
示例代码: |
initialization TCCContextMenuFactory.Create(ComServer, TCCContextMenu, Class_CCContextMenu, '', '', ciMultiInstance, tmApartment); TTypedComObjectFactory.Create(ComServer, TCCContextMenu, Class_CCContextMenu, ciMultiInstance, tmApartment); |
示例代码: 实现注册/ 反注册功能。4 个方法:IsActiveLib ,RegisterActiveLib ,UnregisterActiveLib ,ReportWin32Error |
resourcestring sCopyAnywhere = ‘ 复制到... ‘; sCopyAnywhereTip = ‘ 将选定的文件复制到任何路径下’; sRegister = ‘ 注册...’; sRegisterTip = ‘ 注册ActiveX 库’; sUnregister = ‘ 取消注册...’; sUnregisterTip = ‘ 取消注册ActiveX 库’; sImagePreview = ‘ 预览图片文件’; sImagePreviewTip = ‘ 预览图片文件’; function IsActiveLib(const FileName: String): Boolean; var Ext: String; hLib: THandle; begin Result := False; Ext := UpperCase(ExtractFileExt(FileName)); if (Ext<>‘.EXE’) and (Ext<>‘.DLL’) and (Ext<>‘.OCX’) then Exit; hLib := LoadLibrary(PChar(FileName)); if hLib=0 then Exit; if GetProcAddress(hLib, ‘DllRegisterServer’)<>nil then Result := True; FreeLibrary(hLib); end; procedure RegisterActiveLib(Wnd: HWND; const FileName: String); var hLib: THandle; fn : TDllRegisterServer; hr: HResult; begin hLib := LoadLibrary(PChar(FileName)); if hLib=0 then begin ReportWin32Error(Wnd, ‘ 装载文件失败’, GetLastError); Exit; end; fn := TDllRegisterServer(GetProcAddress(hLib, ‘DllRegisterServer’)); if not Assigned(fn) then begin MessageBox(Wnd, ‘ 定位函数入口点DllRegisterServer 失败’, ‘ 错误’, MB_ICONEXCLAMATION); FreeLibrary(hLib); Exit; end; hr := fn(); if Failed(hr) then begin ReportWin32Error(Wnd, ‘ 注册动态库失败’, hr); FreeLibrary(hLib); Exit; end; MessageBox(Wnd, ‘ 注册成功’, ‘ 成功, MB_ICONINFORMATION); FreeLibrary(hLib); end; procedure UnregisterActiveLib(Wnd: HWND; const FileName: String); var hLib: THandle; fn : TDllRegisterServer; hr: HResult; begin hLib := LoadLibrary(PChar(FileName)); if hLib=0 then begin ReportWin32Error(Wnd, ‘ 装载文件失败’, GetLastError); Exit; end; fn := TDllUnregisterServer(GetProcAddress(hLib, ‘DllUnregisterServer’)); if not Assigned(fn) then begin MessageBox(Wnd, ‘ 定位函数入口点DllUnregisterServer’ 失败’, ‘ 错误’, MB_ICONEXCLAMATION); FreeLibrary(hLib); Exit; end; hr := fn(); if Failed(hr) then begin ReportWin32Error(Wnd, ‘ 取消注册动态库失败’, hr); FreeLibrary(hLib); Exit; end; MessageBox(Wnd, ‘ 取消注册成功’, ‘ 成功, MB_ICONINFORMATION); FreeLibrary(hLib); end; prcedure ReportWin32Error(Wnd: HWND; const Prefix: String; dwError: DWord); var szError: array[0..399] of char; str: String; begin FormatMessage(FROMAT_MESSAGE_FROM_SYSTEM, nil, dwError, Make_LangID(LANG_NEUTRAL, SUBLANG_DEFAULT), szError, sizeof(szError), nil); str := Format(‘%s:%s’, [Prefix, StrPas(szError)]); MessageBox(Wnd, PChar(str), ‘ 错误’, MB_ICONEXCLAMATION); end; |
示例代码:IContextMenu3.HandleMenuMsg2 |
function TCCContextMenu.HandleMenuMsg2(uMsg: UINT; wParam, lParam: Integer; var lpResult: Integer): HResult; var pmis: PMeasureItemStruct; pdis: PDrawItemStruct; begin Result := S_OK; case uMsg of WM_MEASUREITEM: begin pmis := PMeasureItemStruct(lParam); if not Assigned(FGraphic) then begin pmis.itemWidth := 120; pmis.itemHeight := 120; Exit; end; // 如果图片小于120*120 ,那么按照实际的显示,否则缩放到120*120 if (FGraphic.Width<=120) and (FGraphic.Height<=120) then begin pmis.itemWidth := 140; pmis.itemHeight := FGraphic.Height + 40; end else begin pmis.itemWidth := 140; pmis.itemHeight := 160; end; end; WM_DRAWITEM: begin pdis := PDrawItemStruct(lParam); DrawGraphic(pdis.hDC, pdis,rcItem, pdis.itemState, FGraphic); end; end; end; procedure DrawGraphic(adc: HDC; rc: TRect; State: Integer; Graphic: TGraphic); var rcImage, rcText, rcStretch: TRect; Canvas: TCanvas; nSaveDC: Integer; x, y: Integer; xScale, yScale, Scale: Double; xStretch, yStretch: Integer; begin with rcImage do begin Left := rc.Left + 10; Right := rc.Right – 10; Top := rc.Top + 10; Bottom := rc.Bottom – 30; end; with rcText do begin Left := rc.Left + 10; Right := rc.Right – 10; Top := rc.Top - 20; Bottom := rc.Bottom; end; Canvas := TCanvas.Create; nSaveDC := 0; try nSaveDC := SaveDC(adc); Canvas.Handle := adc; with Canvas do begin if not Assigned(Graphic) then begin Rectangle(rcImage); MoveTo(rcImage.Left, rcImage.Top); LineTo(rcImage.Right, rcImage.Bottom); MoveTo(rcImage. Right, rcImage.Top); LineTo(rcImage. Left, rcImage.Bottom); DrawText(Canvas.Handle, ‘ 未知图像’, -1, rcImage, DT_SINGLELINE or DT_CENTER or DT_VECNTER); end else begin if (Graphic.Width<rcImage.Right-rcImage.Left) and (Graphic.Height<rcImage.Bottom-rcImage.Top) then begin x := rcImage.Left + (rcImage.Right - rcImage.Left - Graphic.Width) div 2; y := rcImage. Top + (rcImage. Bottom - rcImage. Top - Graphic. Height) div 2; Canvas.Draw(x, y, Graphic); end else begin xScale := Graphic.Width / (rcImage.Right - rcImage.Left); yScale := Graphic.Height / (rcImage.Bottom - rcImage.Top); Scale := Max(xScale, yScale); xStretch := Trunc(Graphic.Width / Scale); yStretch := Trunc(Graphic. Height / Scale); x := rcImage.Left + (rcImage.Right - rcImage.Left - xStretch) div 2; y := rcImage. Top + (rcImage. Bottom - rcImage. Top - yStretch) div 2; rcStretch := Rect(x, y, x+xStretch, y+yStretch); Canvas.StretchDraw(rcStretch, Graphic); end; Windows.FillRect(Canvas.Handle, GetSysColor(COLOR_MENUTEXT)); SetBkColor(Canvas. Handle, PChar(ImageInfoToStr(Graphic)), -1, rcText, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; end; finally Canvas.Handle :=0; Canvas.Free; RestoreDC(adc, nSaveDC); end; end; function ImageInfoToStr(Graphic: TGraphic): String; begin Result := Format(‘%d * %d’, [Graphic.Width, Graphic.Height]); if Graphic is TIcon then Result := Result + ‘ 图标’; if Graphic is TBitmap then begin case TBitmap(Graphic).PixelFormat of pfDevice: Result := Result + ‘DDB’; pf1bit: Result := Result + ‘2 色; pf4bit: Result := Result + ‘16 色; pf8bit: Result := Result + ‘256 色; pf15bit, pf16bit: Result := Result + ‘16 位色; pf24bit: Result := Result + ‘24 位色; pf32bit: Result := Result + ‘32 位色; pfCustom: Result := Result + ‘ 自定义’; end; Result := Result + ‘ 位图’; end; if Graphic is TMetaFile then begin Result := Result + Format(‘(%d*%d) 元文件’, [TMetaFile(Graphic),MMWidth div 100, TMetaFile(Graphic).MMHeight div 100]) end; if Graphic is TJPEGImage then begin case TJPEGImage(Graphic).PixelFormat of jf24Bit: Result := Result + ‘24 位色JPEG’; jf8Bit: Result := Result + ‘8 位色JPEG’; end; end; end; |