⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uwinhelpfiles.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:




{
SHG-FileFormat

... Picture Data ...
  see other sources

... Makro Data ...

  Always1             :Bytes = 1;
  NumberOfHotspots    :Word;
  SizeOfMacroData     :DWord;
  Hotspots            :array[1..NumberOfHotspots] of
                       record
                         id0: Byte;
                         id1: Byte;
                         id2: Byte;
                         Left, Top, Width, Height: Word;
                         HashOrMacroDataOffset: DWord
                       end;
  MacroData           :record
                       case Boolean of
                         False: (data: array[1..SizeOfMacroData] of Byte;)
                         True:  (macros: array[1..NumberOfMakros] of TMakro)
                       end;
  EditData            :array[1..NumberOfHotspots] of
                       record
                         HotspotName, TextInformation: StringZ;
                       end;

  StringZ is a 0-terminated string.

  EditData seems only to be used in editors for the SHG files, so ignored in
  here.

  MacroData contains data for any special link, i.e. not id0 in [$E0..$E7], in
  that case the HashOrMacroDataOffset is a byte-offset in MacroData to its
  entry, in the other case the hash value of the topic to link to.

  id0: set of TId0;
  TId0 = (id0JumpNotPopUp,
          id0JumpNotMakroA,
          id0InvisibleHotSpot,
          id0LinkToWindowOrFile,      //or: HashOrMacroDataOffset is an offset
          id0UnknownNotSet5,
          id0JumpNotMakroB,
          id0UnknownMustBeSet7,
          id0UnknownMustBeSet8);

  if id0InvisibleHotSpot is set than id1 is also 4 else 0.


  TMakro = record
  case Boolean of      //is a makro?
    False:         (ExtendedLink: TExtendedLink)
    True:          (Makro: StringZ;)
  end;

  TExtendedLink = record
    Info: set of (unknown, toWindow, toFile);
    TopicHash: DWord;
    case toWindow do
      window: StringZ;
    case toFile do
      file: StringZ;
  end;





{Creates a Segmented Hyper-Graphic file from a bitmap and a list of hot spots.
~param BMP         the bitmap of the SGH file or nil
~param BMPFileName name of the bitmap of the SGH file, if BMP is nil
~param HotSpots    the list of hot-spots to add to the bitmap;
                   the first 15 bytes of each entry are the binary data, the
                   remnant of the string the destination topic or macro
~param SHGFileName the name for the resulting SGH file }
procedure CreateSegmentedHyperGraphic(BMP: TBitmap; const BMPFileName: String;
                                      HotSpots: TStrings;
                                      const SHGFileName: String);

 {Writes a 31 bit value into the stream compressedly. Quite senseless because
  about 14 bytes are saved in a file of several kilo bytes, but well, its the
  specification.
 ~param AStream the stream to write the value into
 ~param Value   the value to write }
 procedure WriteCompressedDWord(AStream: TStream; Value: DWord);
 var       WriteWord  :Word;                 //buffer to write a word
 begin
  if (Value and $7FFF1000) = 0 then          //can be compressed?
   begin
    WriteWord := Value shl 1;                  //compress value
    AStream.WriteBuffer(WriteWord, SizeOf(WriteWord));   //and write it
   end
  else
   begin
    WriteWord := (Value shl 1) or 1;           //write both words
    AStream.WriteBuffer(WriteWord, SizeOf(WriteWord));
    WriteWord := (Value shr 15);
    AStream.WriteBuffer(WriteWord, SizeOf(WriteWord));
   end
 end;

 {Returns the makro data of links to other Windows Help files and/or windows.
 ~param Target the target of the link in format "topic[>window][@file.hlp]" }
 function CreateMakroText(Target: String): String;
 var      i              :Integer;          //index in the target string
          NewFile        :String;           //the new help file for the link
          Window         :String;           //the new windows for the link
 begin
  i := pos('@', Target);                    //search the help file
  if i <> 0 then                            //help file specified?
   begin                                      //extract it
    NewFile := Copy(Target, i + 1, High(Length(Target)));
    Delete(Target, i, High(Length(Target)));
   end
  else
   NewFile := '';

  i := pos('>', Target);                    //search the window
  if i <> 0 then                            //window specified?
   begin                                      //extract it
    Window := Copy(Target, i + 1, High(Length(Target)));
    Delete(Target, i, High(Length(Target)));
   end
  else
   Window := '';

  //set control byte, use bit 1 and 2 of first byte to select information
  Result := Char(Ord(NewFile <> '') shl 2 or Ord(Window <> '') shl 1) +
            GetTopicNameHashValue(Target);
  if Window <> '' then                            //add available information
   Result := Result + Window + #0;
  if NewFile <> '' then
   Result := Result + NewFile + #0;
 end;


var       Bitmap     :TBitmap;     //the bitmap to write into the shg file
          BMPContent :TMemoryStream;  //stream for compressed content of bitmap
          HSData     :TMemoryStream;  //stream for data of hot-spots
          SHGFile    :TFileStream;    //stream to write the SHG file
          i          :Integer;        //general counter or index
          WriteByte  :Byte;           //buffer to write the prefix byte
          S          :String;         //buffer to write data
          MacroData  :String;         //data of the hot spots
          WriteDWord :DWORD;          //buffer to write DWord-values
begin
 if Assigned(BMP) then
  Bitmap := BMP                       //use the image
 else
  Bitmap := TBitmap.Create;           //create object to load bitmap
 try
   if BMP <> Bitmap then              //need to load the image from a file
    Bitmap.LoadFromFile(BMPFileName);   //load the bitmap

{$IFNDEF LINUX}
   Bitmap.HandleType := bmDIB;        //we need a DIB
{$ENDIF}

   if Bitmap.PixelFormat < pf16bit then //we can't read palettes on Unix
    //so make sure this is an universal valid pixel format without one
{$IFNDEF LINUX}
    Bitmap.PixelFormat := pf16bit;
{$ELSE}
    //got some problems with Kylix, changing to 16bit actually set it to custom
    Bitmap.PixelFormat := pf32bit;
{$ENDIF}

{$IFNDEF LINUX}
   if Bitmap.PixelFormat in [pf24bit, pfCustom] then //bitmaps are written in
    Bitmap.PixelFormat := pf32bit;                     //32 bit, not 24
{$ENDIF}
   assert(Bitmap.PixelFormat in [pf16bit, pf32bit]);



   BMPContent := TMemoryStream.Create;  //create buffer for compressed bitmap
   try
     GetCompressedBitmapContent(Bitmap, BMPContent);   //get content of bitmap

     HSData := TMemoryStream.Create;        //create buffer for hot-spots
     try
       MacroData := '';                     //no data of macros so far
       for i := 0 to HotSpots.Count - 1 do  //for each hot-spot
        begin
         S := HotSpots[i];                    //get it
         if (S[1] < #$E0) or (S[1] >= #$E8) then //has further information?
          begin
           HSData.WriteBuffer(S[1], 11);           //write binary data
           //write index in data instead of hash value
           WriteDWord := Length(MacroData);
           HSData.WriteBuffer(WriteDWord, SizeOf(WriteDWord));
           if S[1] < #$E0 then                     //a real makro?
            //add the text of the macro to the data
            MacroData := MacroData + Copy(S, 16, High(Length(S))) + #0
           else
            //is a link to another window or in another help file
            MacroData := MacroData + CreateMakroText(Copy(S, 16,
                                                          High(Length(S))));
          end
         else
          HSData.WriteBuffer(S[1], 15);        //write its binary data
        end;

       if MacroData <> '' then               //some macros found?
        HSData.WriteBuffer(MacroData[1], Length(MacroData)); //write their data

       WriteByte := 0;                      //set byte to end name of hot-spot
       for i := 0 to HotSpots.Count - 1 do  //for each hot-spot
        begin
         HSData.WriteBuffer(WriteByte, 1);    //end the name (empty name)
         S := HotSpots[i];                    //get it
         Delete(S, 1, 15);                    //delete binary data
         HSData.WriteBuffer(S[1], Length(S) + 1);  //write target or macro
        end;


       //create the SHG file
       SHGFile := TFileStream.Create(SHGFileName, fmCreate);
       try
         S := 'lP'#01#00#08#00#00#00#06 +

              //Bit 0 = RunLength; Bit 1 = LZ77
{$IFDEF UseRunLength}
 {$IFDEF UseLZ77}
              #03
 {$ELSE}
              #01
 {$ENDIF}
{$ELSE}
 {$IFDEF UseLZ77}
              #02
 {$ELSE}
              #00
 {$ENDIF}
{$ENDIF}
               + #$C0#00#$C0#00#02;
         //compression:
         SHGFile.WriteBuffer(S[1], Length(S));      //write file header
         if Bitmap.PixelFormat = pf16bit then       //get bits per pixels
          WriteByte := 16 shl 1
         else
          WriteByte := 32 shl 1;
         SHGFile.WriteBuffer(WriteByte, 1);
         WriteCompressedDWord(SHGFile, Bitmap.Width);   //write size of bitmap
         WriteCompressedDWord(SHGFile, Bitmap.Height);
         S := #02#00#00#00;                             //color information
         SHGFile.WriteBuffer(S[1], Length(S));
         //write size of the compressed bitmap data
         WriteCompressedDWord(SHGFile, BMPContent.Position);
         //write size of the compressed hot-spot data
         WriteCompressedDWord(SHGFile, HSData.Position + 7);

         WriteDWord := SHGFile.Position + 12 - 8;      //write offset of bitmap
         SHGFile.WriteBuffer(WriteDWord, SizeOf(WriteDWord));
         inc(WriteDWord, BMPContent.Position);      //write offset of hot-spots
         SHGFile.WriteBuffer(WriteDWord, SizeOf(WriteDWord));
         WriteDWord := 0;                              //write not used color
         SHGFile.WriteBuffer(WriteDWord, SizeOf(WriteDWord));

         SHGFile.CopyFrom(BMPContent, 0);              //copy the bitmap data

         //write header of the list of hot-spots and their number
         S := #01 +
              Char(HotSpots.Count) + Char(HotSpots.Count shr 8);
         SHGFile.WriteBuffer(S[1], Length(S));
         WriteDWord := Length(MacroData);            //write size of macro data
         SHGFile.WriteBuffer(WriteDWord, SizeOf(WriteDWord));
         SHGFile.CopyFrom(HSData, 0);                  //copy the hot-spot data
       finally
        SHGFile.Free;                                //close the SHG file
       end;
     finally
      HSData.Free;                        //free buffer of data of hot-spots
     end;
   finally
    BMPContent.Free;                    //free buffer of data of the bitmap
   end;
 finally
  if BMP <> Bitmap then               //needs to be freed?
   Bitmap.Free;                         //free the bitmap
 end;
end;
















{Returns the SHG representation of a rectangle as a hot-spot (a link) in a
 SHG file.
~param Rect the rectangle to return in SHG format
~result the rectangle in SHG format }
function GetSHGRectString(Rect: TRect): String;
begin
 dec(Rect.Right, Rect.Left);          //calculate size of the rectangle
 dec(Rect.Bottom, Rect.Top);
 Result := Char(Rect.Left) + Char(Rect.Left shr 8) +    //just the four values
           Char(Rect.Top) + Char(Rect.Top shr 8) +      //as words
           Char(Rect.Right) + Char(Rect.Right shr 8) +
           Char(Rect.Bottom) + Char(Rect.Bottom shr 8);
end;


end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -