среда, 13 августа 2008 г.

Как добавить обработчик для типа файла (и пример)

К примеру, надо добавить thumbnail provider для flv файла:
  • сначала надо в HKEY_CLASSES_ROOT найти нужное расширение файла (.flv)
  • если нашли - читаем значение по умолчанию для ветки (KMPlayer например после добавления воспроизведения flv файлов на себя обозвал такие файлы как flv_auto_file)? если нет - создаем ветку и придумываем название для такого типа файлов, записывая его в значение по умолчанию для ветки
  • теперь надо открыть (или создать) в HKEY_CLASSES_ROOT ветку, значение которой прочитали (flv_auto_file), и
  1. проверить, есть ли в ней ветка Shell (потому что если ее нет, то даже если все остальное правильно, все равно ничего работать не будет... по крайней мере для эскизов я точно об этом знаю)
  2. в ветке ShellEx добавить ветку с guid-ом нужного обработчика (например для обработчика эскизов - {E357FCCD-A995-4576-B01F-234630154E96}), и записать в значение по умолчанию guid сом-обьекта, который собственно и будет создавать эскизы
  • для красоты можно записать в ветку flv_auto_file ключик Treatment - в висте он будет дорисовывать рамочку вокруг эскиза; например рамка в виде кадра кинопленки - значение 3.
  • вообще говоря не относится к регистрации особо, но - если провайдер эскизов реализует интерфейс IInitializeWithFile, то в HKEY_CLASSES_ROOT\CLSID\provider_guid надо добавить ключик DisableProcessIsolation со значением 1

Простенький проект, который будет рисовать эскизы в проводнике для flv файлов (ахтунг, для висты! в хр используется другой интерфейс для показа эскизов):
library vista_thumb;

uses
  ComServ,
  thumbProvider_impl in 'thumbProvider_impl.pas';

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.RES}

begin
end.

unit thumbProvider_impl;

interface

uses
  windows, graphics, sysutils, 
  ActiveX, ComObj, registry, propsys;

const
  CLSID_ThumbProvider: TGUID = '{C8F39152-17CA-42F9-9FC0-4499C6D74C92}';

type
  TThumbProvider2 = class (TComObject, IInitializeWithFile, IThumbnailProvider)
  public
    function IInitializeWithFile.Initialize = Initialize1;
    function Initialize1 (pszFilePath: LPCWSTR; grfMode: DWORD): HRESULT; stdcall;
    function GetThumbnail(cx: Cardinal; out phbmp: HBITMAP; out pdwAlpha: Cardinal): HRESULT; stdcall;
  end;

implementation

uses
  ComServ, ShlObj;

type
  TThumbProviderFactory = class (TComObjectFactory)
    procedure UpdateRegistry (Register: Boolean); override;
  end;

{ TThumbProviderFactory }

procedure TThumbProviderFactory.UpdateRegistry(Register: Boolean);
const
  shell_path = 'Shell';
  shellex_thumbnail = 'ShellEx\{E357FCCD-A995-4576-B01F-234630154E96}';
var
  reg: TRegistry;
  base_path: string;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_CLASSES_ROOT;
    if Register then
    begin
      inherited UpdateRegistry (Register);
      reg.OpenKey ('.flv', true);
      try
        if reg.ValueExists ( '' ) then
          base_path := reg.ReadString ( '' )
        else
          base_path := 'flv_auto_file';
      finally
        reg.CloseKey;
      end;

      reg.OpenKey ( base_path, true );
      try
        if not reg.KeyExists ( shell_path ) then
          reg.CreateKey ( shell_path );
      finally
        reg.CloseKey;
      end;

      reg.OpenKey ( base_path, false );
      try
        reg.WriteInteger ('Treatment', 3);
      finally
        reg.CloseKey;
      end;

      if reg.OpenKey (base_path + '\' + shellex_thumbnail, true) then
      try
        reg.WriteString ('', GUIDToString (CLSID_FlashFilesThumbProvider));
      finally
        reg.CloseKey;
      end;

      if reg.OpenKey ( 'CLSID\' + GUIDToString (CLSID_FlashFilesThumbProvider), false ) then
      try
        reg.WriteInteger ('DisableProcessIsolation', 1);
      finally
        reg.CloseKey;
      end;

    end else begin
      reg.DeleteKey (base_path + '\' + shellex_thumbnail);
      inherited UpdateRegistry (Register);
    end;

    SHChangeNotify ( SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil );
  finally
    reg.Free;
  end;
end;

{ TThumbProvider2 }

function TThumbProvider2.GetThumbnail(cx: Cardinal; out phbmp: HBITMAP; out pdwAlpha: Cardinal): HRESULT;
var
  bmp: TBitmap;
begin
  Result := E_FAIL;

  bmp := TBitmap.Create;
  try
    bmp.Width := cx; bmp.Height := cx div 2;
    bmp.PixelFormat := pf32bit;

    with bmp.Canvas do
    begin
      Brush.Color := clFuchsia;
      FillRect (ClipRect);
      TextOut (5, 5, format ('%d', [cx]));
      TextOut (5, 25, 'fuck U!');
    end;

    phbmp := bmp.Handle;
    bmp.ReleaseHandle;
    pdwAlpha := WTSAT_RGB;

    Result := S_OK;
  finally                                          
    bmp.free;
  end;
end;

function TThumbProvider2.Initialize1 (pszFilePath: LPCWSTR; grfMode: DWORD): HRESULT;
begin
  Result := S_OK;
end;

initialization
  TThumbProviderFactory.Create (ComServer, TThumbProvider2,
      CLSID_ThumbProvider, 'Thumbnail provider for Flash files',
      '', ciMultiInstance, tmApartment);


end.

2 комментария: