RVOfficeCnv.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:19k
源码类别:

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       TRVOfficeConverter: component providing         }
  5. {       interface for Microsoft(R) Office               }
  6. {       Text Converters                                 }
  7. {       (registered on "RichView" page of               }
  8. {       the Component Palette)                          }
  9. {                                                       }
  10. {       Copyright (c) Sergey Tkachenko                  }
  11. {       svt@trichview.com                               }
  12. {       http://www.trichview.com                        }
  13. {                                                       }
  14. {*******************************************************}
  15. unit RVOfficeCnv;
  16. interface
  17. {$I RV_Defs.inc}
  18. uses Windows, Classes, SysUtils,
  19.      RVClasses, Forms, RichView;
  20.   {
  21.     Error codes for converters. They are assigned to converter.ErrorCode
  22.     after import/export operation.
  23.   }
  24. const
  25.   // errors running converter
  26.   rvceCnvLoadError   = 1;       // error loading converter's DLL
  27.   rvceFuncError      = 2;       // required function is not found in converter's DLL
  28.   rvceInitError      = 3;       // converter initialization failure
  29.   
  30.   // errors returned by converters; this is NOT an exhaustive list! 
  31.   rvceOpenInFileErr  = -1; // could not open input file
  32.   rvceReadErr      = -2; // error during read
  33.   rvceOpenConvErr    = -3; // error opening conversion file
  34.   rvceWriteErr      = -4; // error during write
  35.   rvceInvalidFile    = -5; // invalid data in conversion file
  36.   rvceOpenExceptErr  = -6; // error opening exception file
  37.   rvceWriteExceptErr = -7; // error writing exception file
  38.   rvceNoMemory      = -8; // out of memory
  39.   rvceInvalidDoc     = -9; // invalid document
  40.   rvceDiskFull      = -10; // out of space on output
  41.   rvceDocTooLarge    = -11; // conversion document too large for target
  42.   rvceOpenOutFileErr = -12; // could not open output file
  43.   rvceUserCancel     = -13;     // conversion cancelled by user
  44.   rvceWrongFileType  = -14;     // wrong file type for this converter
  45. type
  46.   TRVOfficeConverterInfo = class
  47.     public
  48.       Name, Path, Filter: String;
  49.   end;
  50.   TInitConverter32 = function(hwndWord: HWND; szModule: PChar): Integer; stdcall;
  51.   TUninitConverter = procedure; stdcall;
  52.   TForeignToRtf32Callback = function (cchBuff, nPercent: Integer): Integer; stdcall;
  53.   TRtfToForeign32Callback = function (rgfOptions, nReserved: Integer): Integer; stdcall;
  54.   TForeignToRtf32 = function (ghszFile: HGLOBAL; pstgForeign: Pointer; ghBuff,
  55.     ghszClass, ghszSubset: HGLOBAL; lpfnOut: TForeignToRtf32Callback): SmallInt; stdcall;
  56.   TRtfToForeign32 = function(ghszFile: HGLOBAL; pstgForeign: Pointer;
  57.     ghBuff, ghszClass: HGLOBAL; lpfnIn: TRtfToForeign32Callback): SmallInt; stdcall;
  58.   TRegisterApp = function(lFlags: Integer; lpRegApp: Pointer):HGLOBAL; stdcall;
  59.   TConvertingEvent = procedure (Sender:TObject; Percent: Integer) of object;
  60.   TRVOfficeConverter = class;
  61.   TRVOfficeCnvList = class (TRVList)
  62.     private
  63.       FOwner: TRVOfficeConverter;
  64.       hBuffer: HGLOBAL;
  65.       FOnConverting: TConvertingEvent;
  66.       FStream: TMemoryStream;
  67.       FStep, FStart, FSize: Integer;
  68.       procedure Put(Index: Integer; Value: TRVOfficeConverterInfo);
  69.       function Get(Index: Integer):TRVOfficeConverterInfo;
  70.       procedure LoadList(const RegPath: String; ExcludeHTML: Boolean);
  71.     public
  72.       constructor Create(const RegPath: String; Owner: TRVOfficeConverter;
  73.                          ExcludeHTML: Boolean);
  74.       function GetFilter(IncludeExtensions: Boolean): String;
  75.       procedure ImportRTF(const FileName: String; Index: Integer);
  76.       procedure ExportRTF(const FileName: String; Index: Integer);
  77.       property Items[Index: Integer]: TRVOfficeConverterInfo read Get write Put; default;
  78.   end;
  79.   TRVOfficeConverter = class (TComponent)
  80.     private
  81.       FImportConverters, FExportConverters: TRVOfficeCnvList;
  82.       FOnConverting: TConvertingEvent;
  83.       FStream: TMemoryStream;
  84.       FExcludeHTMLImportConverter: Boolean;
  85.       FExcludeHTMLExportConverter: Boolean;
  86.       FPreviewMode: Boolean;
  87.       FErrorCode: Integer;
  88.       FExtensionsInFilter: Boolean;
  89.       function GetExportConverters: TRVOfficeCnvList;
  90.       function GetImportConverters: TRVOfficeCnvList;
  91.     public
  92.       constructor Create(AOwner: TComponent); override;
  93.       destructor Destroy; override;
  94.       function ImportRTF(const FileName: String; ConverterIndex: Integer): Boolean;
  95.       function ExportRTF(const FileName: String; ConverterIndex: Integer): Boolean;
  96.       function ImportRV(const FileName: String; rv: TCustomRichView; ConverterIndex: Integer): Boolean;
  97.       function ExportRV(const FileName: String; rv: TCustomRichView; ConverterIndex: Integer): Boolean;
  98.       function GetImportFilter: String;
  99.       function GetExportFilter: String;
  100.       property ImportConverters: TRVOfficeCnvList read GetImportConverters;
  101.       property ExportConverters: TRVOfficeCnvList read GetExportConverters;
  102.       property Stream: TMemoryStream read FStream;
  103.       property ErrorCode: Integer read FErrorCode;
  104.     published
  105.       property ExcludeHTMLImportConverter: Boolean read FExcludeHTMLImportConverter write FExcludeHTMLImportConverter default False;
  106.       property ExcludeHTMLExportConverter: Boolean read FExcludeHTMLExportConverter write FExcludeHTMLExportConverter default False;
  107.       property PreviewMode: Boolean read FPreviewMode write FPreviewMode default False;
  108.       property ExtensionsInFilter: Boolean read FExtensionsInFilter write FExtensionsInFilter default False;
  109.       property OnConverting: TConvertingEvent read FOnConverting write FOnConverting;
  110.   end;
  111. implementation
  112. var Converters: TRVOfficeCnvList;
  113. {==============================================================================}
  114. function ForeignToRtf32Callback(cchBuff, nPercent: Integer): Integer; stdcall;
  115. var p: Pointer;
  116. begin
  117.   if Assigned(Converters.FOnConverting) then
  118.     Converters.FOnConverting(Converters.FOwner, nPercent);
  119.   if Assigned(Converters.FOnConverting) then
  120.     Converters.FOnConverting(Converters.FOwner, nPercent);
  121.   Result := 0;
  122.   if cchBuff=0 then
  123.     exit;
  124.   p := GlobalLock(Converters.hBuffer);
  125.   Converters.FStream.WriteBuffer(p^,cchBuff);
  126.   GlobalUnlock(Converters.hBuffer);
  127. end;
  128. {------------------------------------------------------------------------------}
  129. function RtfToForeign32Callback(rgfOptions, nReserved: Integer): Integer; stdcall;
  130. var p: Pointer;
  131. begin
  132.   Result := Converters.FStream.Size-Converters.FStream.Position;
  133.   if Result>Converters.FStep then
  134.     Result :=Converters.FStep;
  135.   if Result>0 then begin
  136.     p := GlobalLock(Converters.hBuffer);
  137.     Converters.FStream.ReadBuffer(p^, Result);
  138.     GlobalUnlock(Converters.hBuffer);
  139.   end;
  140.   if Assigned(Converters.FOnConverting) then
  141.     Converters.FOnConverting(Converters.FOwner,  (Converters.FStream.Position-Converters.FStart)*100 div Converters.FSize);
  142. end;
  143. {======================== TRVOfficeCnvList =================================}
  144. procedure TRVOfficeCnvList.Put(Index: Integer; Value: TRVOfficeConverterInfo);
  145. begin
  146.   inherited Put(Index, Value);
  147. end;
  148. {------------------------------------------------------------------------------}
  149. function TRVOfficeCnvList.Get(Index: Integer):TRVOfficeConverterInfo;
  150. begin
  151.   Result := TRVOfficeConverterInfo(inherited Get(Index));
  152. end;
  153. {------------------------------------------------------------------------------}
  154. constructor TRVOfficeCnvList.Create(const RegPath: String; Owner: TRVOfficeConverter; ExcludeHTML: Boolean);
  155. begin
  156.   inherited Create;
  157.   FOwner := Owner;
  158.   try
  159.     LoadList(RegPath, ExcludeHTML);
  160.   except
  161.   ;
  162.   end;
  163. end;
  164. {------------------------------------------------------------------------------}
  165. procedure TRVOfficeCnvList.LoadList(const RegPath: String; ExcludeHTML: Boolean);
  166. var key, subkey: HKEY;
  167.     KeyName, KeyBuf: String;
  168.     i: Integer;
  169.     Item: TRVOfficeConverterInfo;
  170.     {........................................}
  171.     function DecodeExt(s: String): String;
  172.     var p: Integer;
  173.         s1: String;
  174.     begin
  175.       Result := '';
  176.       while s<>'' do begin
  177.         p := Pos(' ',s);
  178.         if p=0 then begin
  179.           s1 := s;
  180.           s  := '';
  181.           end
  182.         else begin
  183.           s1 := Copy(s,1,p-1);
  184.           s  := Copy(s,p+1,Length(s));
  185.         end;
  186.         if Result<>'' then
  187.           Result := Result+';';
  188.         Result := Result+'*.'+s1;
  189.       end;
  190.     end;
  191.     {........................................}
  192.     function ReadString(Key: HKEY; const ValueName: String; var Value: String): Boolean;
  193.     var l: Integer;
  194.     begin
  195.       SetLength(Value, MAX_PATH);
  196.       l := MAX_PATH;
  197.       Result := RegQueryValueEx(Key, PChar(ValueName), nil, nil, PByte(Value), @l)=ERROR_SUCCESS;
  198.       if Result then
  199.         SetLength(Value, l-1);
  200.     end;
  201.     {........................................}
  202. begin
  203.    Clear;
  204.    SetLength(KeyBuf, MAX_PATH);
  205.    if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(RegPath), 0, KEY_READ, Key)<>ERROR_SUCCESS then
  206.      exit;
  207.    try
  208.      i := 0;
  209.      while RegEnumKey(Key, i, PChar(KeyBuf), MAX_PATH+1)=ERROR_SUCCESS do begin
  210.        KeyName := PChar(KeyBuf);
  211.        if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(RegPath+''+KeyName), 0, KEY_READ, SubKey)=ERROR_SUCCESS then
  212.          try
  213.            Item := TRVOfficeConverterInfo.Create;
  214.            if ReadString(SubKey, 'Name', Item.Name) and
  215.               ReadString(SubKey, 'Path', Item.Path) and
  216.               ReadString(SubKey, 'Extensions', Item.Filter) and
  217.               (not ExcludeHTML or (AnsiCompareText(ExtractFileName(Item.Path),'HTML32.CNV')<>0))
  218.                then begin
  219.              Item.Filter := DecodeExt(Item.Filter);
  220.              Add(Item)
  221.              end
  222.            else
  223.              Item.Free;
  224.          finally
  225.            RegCloseKey(SubKey);
  226.          end;
  227.        inc(i);
  228.      end;
  229.    finally
  230.      RegCloseKey(Key);   
  231.    end;
  232. end;
  233. {------------------------------------------------------------------------------}
  234. function TRVOfficeCnvList.GetFilter(IncludeExtensions: Boolean): String;
  235. var i: Integer;
  236. begin
  237.   Result := '';
  238.   for i := 0 to Count-1 do begin
  239.     if i>0 then
  240.       Result := Result + '|';
  241.     if IncludeExtensions then
  242.       Result := Result + Items[i].Name+' ('+Items[i].Filter+')|'+Items[i].Filter
  243.     else
  244.       Result := Result + Items[i].Name+'|'+Items[i].Filter;
  245.   end;
  246. end;
  247. {$A-}
  248. type TAppInfo = record
  249. cbStruct: SmallInt;
  250. cbSizeVer: Byte;
  251. opcodeVer: Byte;
  252. verMajor: SmallInt;
  253. verMinor: SmallInt;
  254.         cbSizeCharset: Byte;
  255.         opcodeCharset: Byte;
  256.         Charset:       Byte;
  257.      end;
  258. const AppInfo: TAppInfo =
  259.     (
  260. cbStruct: sizeof(TAppInfo);
  261. cbSizeVer: 1+1+2+2;
  262. opcodeVer: $01;
  263. verMajor: 10;
  264. verMinor: 0;
  265.         cbSizeCharset: 1+1+1;
  266.         opcodeCharset: $03;
  267.         Charset:       DEFAULT_CHARSET;
  268.     );
  269. {------------------------------------------------------------------------------}
  270. function GetFileNameHandle(const FileName: String): HGLOBAL;
  271. var pc: PChar;
  272. begin
  273.   Result := GlobalAlloc(GHND, Length(FileName)+1);
  274.   pc := GlobalLock(Result);
  275.   CharToOEM(PChar(FileName), pc);
  276.   GlobalUnlock(Result);
  277. end;
  278. {------------------------------------------------------------------------------}
  279. procedure TRVOfficeCnvList.ImportRTF(const FileName: String;
  280.   Index: Integer);
  281. var hLib : HMODULE;
  282.     ExeName: String;
  283.     InitConverter32:TInitConverter32;
  284.     UninitConverter:TUninitConverter;
  285.     ForeignToRtf32: TForeignToRtf32;
  286.     RegisterApp: TRegisterApp;
  287.     hFileName,hPref: HGLOBAL;
  288. begin
  289.    FStream.Clear;
  290.    Converters := Self;
  291.    SetLength(ExeName, Length(Application.ExeName));
  292.    CharToOEM(PChar(Application.ExeName), PChar(ExeName));
  293.    hFileName     :=  GetFileNameHandle(FileName);
  294.    hBuffer := GlobalAlloc(GHND, 4096);
  295.    hLib := LoadLibrary(PChar(Items[Index].Path));
  296.    if hLib=0 then begin
  297.      FOwner.FErrorCode := rvceCnvLoadError;
  298.      abort;
  299.    end;
  300.    try
  301.       InitConverter32 := GetProcAddress(hLib, 'InitConverter32');
  302.       if not Assigned(InitConverter32) then begin
  303.         FOwner.FErrorCode := rvceFuncError;
  304.         abort;
  305.       end;
  306.       if InitConverter32(Application.Handle, PChar(ExeName))=0 then begin
  307.         FOwner.FErrorCode := rvceInitError;
  308.         abort;
  309.       end;
  310.       RegisterApp := GetProcAddress(hLib, 'RegisterApp');
  311.       if Assigned(RegisterApp) then begin
  312.         if FOwner.PreviewMode then
  313.           hPref := RegisterApp(4,@AppInfo)
  314.         else
  315.           hPref := RegisterApp(0,@AppInfo);
  316.         if hPref<>0 then
  317.           GlobalFree(hPref);
  318.       end;
  319.       try
  320.         ForeignToRtf32 := GetProcAddress(hLib, 'ForeignToRtf32');
  321.         if not Assigned(ForeignToRtf32) then begin
  322.           FOwner.FErrorCode := rvceFuncError;
  323.           abort;
  324.         end;
  325.         FOwner.FErrorCode := ForeignToRtf32(hFileName,nil,hBuffer,0,0,ForeignToRtf32Callback);
  326.         if FOwner.FErrorCode<>0 then
  327.           abort;
  328.       finally
  329.         UninitConverter := GetProcAddress(hLib, 'UninitConverter');
  330.         if Assigned(UninitConverter) then
  331.           UninitConverter;
  332.       end;
  333.    finally
  334.      FreeLibrary(hLib);
  335.      GlobalFree(hBuffer);
  336.      GlobalFree(hFileName);
  337.    end;
  338. end;
  339. {------------------------------------------------------------------------------}
  340. procedure TRVOfficeCnvList.ExportRTF(const FileName: String;
  341.   Index: Integer);
  342. var hLib : HMODULE;
  343.     ExeName: String;
  344.     InitConverter32:TInitConverter32;
  345.     UninitConverter:TUninitConverter;
  346.     RtfToForeign32: TRtfToForeign32;
  347.     RegisterApp: TRegisterApp;
  348.     hFileName, hPref: HGLOBAL;
  349. begin
  350.    Converters := Self;
  351.    FStart := FStream.Position;
  352.    FSize  := FStream.Size-FStart;
  353.    if FSize=0 then
  354.      exit;
  355.    FStep := 4096;
  356.    if FStep>FSize then
  357.      FStep := FSize;
  358.    if Assigned(Converters.FOnConverting) then
  359.      Converters.FOnConverting(Self, 0);
  360.    SetLength(ExeName, Length(Application.ExeName));
  361.    CharToOEM(PChar(Application.ExeName), PChar(ExeName));
  362.    hFileName     :=  GetFileNameHandle(FileName);
  363.    hBuffer := GlobalAlloc(GHND, FStep);
  364.    hLib := LoadLibrary(PChar(Items[Index].Path));
  365.    if hLib=0 then begin
  366.      FOwner.FErrorCode := rvceCnvLoadError;
  367.      abort;
  368.    end;
  369.    try
  370.       InitConverter32 := GetProcAddress(hLib, 'InitConverter32');
  371.       if not Assigned(InitConverter32) then begin
  372.         FOwner.FErrorCode := rvceFuncError;
  373.         abort;
  374.       end;
  375.       if InitConverter32(Application.Handle, PChar(ExeName))=0 then begin
  376.         FOwner.FErrorCode := rvceInitError;
  377.         abort;
  378.       end;
  379.       RegisterApp := GetProcAddress(hLib, 'RegisterApp');
  380.       if Assigned(RegisterApp) then begin
  381.         hPref := RegisterApp(0,@AppInfo);
  382.         if hPref<>0 then
  383.           GlobalFree(hPref);
  384.       end;
  385.       try
  386.         RtfToForeign32 := GetProcAddress(hLib, 'RtfToForeign32');
  387.         if not Assigned(RtfToForeign32) then begin
  388.           FOwner.FErrorCode := rvceFuncError;
  389.           abort;
  390.         end;
  391.         FOwner.FErrorCode := RtfToForeign32(hFileName, nil, hBuffer,0,RtfToForeign32Callback);
  392.         if FOwner.FErrorCode<>0 then
  393.           abort;
  394.       finally
  395.         UninitConverter := GetProcAddress(hLib, 'UninitConverter');
  396.         if Assigned(UninitConverter) then
  397.           UninitConverter;
  398.       end;
  399.    finally
  400.      FreeLibrary(hLib);
  401.      GlobalFree(hBuffer);
  402.      GlobalFree(hFileName);
  403.    end;
  404. end;
  405. {============================ TRVOfficeConverter ==============================}
  406. constructor TRVOfficeConverter.Create(AOwner: TComponent);
  407. begin
  408.   inherited;
  409.   FStream := TMemoryStream.Create;
  410. end;
  411. {------------------------------------------------------------------------------}
  412. destructor TRVOfficeConverter.Destroy;
  413. begin
  414.   FExportConverters.Free;
  415.   FImportConverters.Free;
  416.   FStream.Free;
  417.   inherited;
  418. end;
  419. {------------------------------------------------------------------------------}
  420. function TRVOfficeConverter.GetExportConverters: TRVOfficeCnvList;
  421. begin
  422.    if FExportConverters=nil then
  423.      FExportConverters := TRVOfficeCnvList.Create('SOFTWAREMicrosoftShared ToolsText ConvertersExport', Self,
  424.        ExcludeHTMLExportConverter);
  425.    Result := FExportConverters;
  426. end;
  427. {------------------------------------------------------------------------------}
  428. function TRVOfficeConverter.GetImportConverters: TRVOfficeCnvList;
  429. begin
  430.    if FImportConverters=nil then
  431.      FImportConverters := TRVOfficeCnvList.Create('SOFTWAREMicrosoftShared ToolsText ConvertersImport', Self,
  432.        ExcludeHTMLImportConverter);
  433.    Result := FImportConverters;
  434. end;
  435. {------------------------------------------------------------------------------}
  436. function TRVOfficeConverter.GetImportFilter: String;
  437. begin
  438.   Result := ImportConverters.GetFilter(ExtensionsInFilter);
  439. end;
  440. {------------------------------------------------------------------------------}
  441. function TRVOfficeConverter.GetExportFilter: String;
  442. begin
  443.   Result := ExportConverters.GetFilter(ExtensionsInFilter);
  444. end;
  445. {------------------------------------------------------------------------------}
  446. function TRVOfficeConverter.ImportRTF(const FileName: String;
  447.   ConverterIndex: Integer): Boolean;
  448. begin
  449.   FErrorCode := 0;
  450.   ImportConverters.FStream := Stream;
  451.   FImportConverters.FOnConverting := OnConverting;
  452.   try
  453.     FImportConverters.ImportRTF(FileName, ConverterIndex);
  454.     Result := True;
  455.   except
  456.     Result := False;
  457.   end;
  458. end;
  459. {------------------------------------------------------------------------------}
  460. function TRVOfficeConverter.ExportRTF(const FileName: String;
  461.   ConverterIndex: Integer): Boolean;
  462. begin
  463.   FErrorCode := 0;
  464.   ExportConverters.FStream := Stream;
  465.   FExportConverters.FOnConverting := OnConverting;
  466.   try
  467.     FExportConverters.ExportRTF(FileName, ConverterIndex);
  468.     Result := True;
  469.   except
  470.     Result := False;
  471.   end;
  472. end;
  473. {------------------------------------------------------------------------------}
  474. function TRVOfficeConverter.ExportRV(const FileName: String; rv: TCustomRichView;
  475.   ConverterIndex: Integer): Boolean;
  476. begin
  477.   FErrorCode := 0;
  478.   Stream.Clear;
  479.   Result := rv.SaveRTFToStream(Stream,False);
  480.   if Result then begin
  481.     FStream.Position := 0;
  482.     Result := ExportRTF(FileName, ConverterIndex);
  483.   end;
  484.   Stream.Clear;
  485. end;
  486. {------------------------------------------------------------------------------}
  487. function TRVOfficeConverter.ImportRV(const FileName: String; rv: TCustomRichView;
  488.   ConverterIndex: Integer): Boolean;
  489. begin
  490.   FErrorCode := 0;
  491.   Result := ImportRTF(FileName, ConverterIndex);
  492.   FStream.Position := 0;
  493.   Result := rv.LoadRTFFromStream(Stream) and Result;
  494.   Stream.Clear;
  495. end;
  496. {------------------------------------------------------------------------------}
  497. end.