unit viewer_thtmlcomp; {$mode delphi} interface uses Classes, SysUtils, // browserviewer, // HtmlMisc, HTMLsubs, Htmlview, HTMLun2; type { THtmlCompViewer } THtmlCompViewer = class(TBrowserViewer) private Viewer: THTMLViewer; FoundObject: TImageObj; procedure ViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure ViewerProgress(Sender: TObject; Stage: TProgressStage; PercentDone: Integer); procedure ViewerPrintHTMLFooter(Sender: TObject; HFViewer: THTMLViewer; NumPage: Integer; LastPage: Boolean; var XL, XR: Integer; var StopPrinting: Boolean); procedure ViewerPrintHTMLHeader(Sender: TObject; HFViewer: THTMLViewer; NumPage: Integer; LastPage: Boolean; var XL, XR: Integer; var StopPrinting: Boolean); procedure HotSpotChange(Sender: TObject; const URL: string); procedure HotSpotClick(Sender: TObject; const URL: string; var Handled: boolean); procedure RightClick(Sender: TObject; Parameters: TRightClickParameters); procedure ViewerImageRequest(Sender: TObject; const SRC: string; var Stream: TMemoryStream); public procedure CreateViewer(AParent, AOwner: TWinControl); override; procedure LoadFromFile(AFilename: string); override; // procedure LoadFromURL(AURL: string); override; function GetDocumentTitle: string; override; procedure SetShowImages(AValue: Boolean); override; procedure HandlePageLoaderTerminated(Sender: TObject); override; procedure Reload; override; end; implementation { THtmlCompViewer } procedure THtmlCompViewer.ViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var TitleStr: string; begin if not Timer1.Enabled and Assigned(ActiveControl) and ActiveControl.Focused then {9.25} begin TitleStr := Viewer.TitleAttr; if TitleStr = '' then OldTitle := '' else if TitleStr <> OldTitle then begin TimerCount := 0; Timer1.Enabled := True; OldTitle := TitleStr; end; end; end; procedure THtmlCompViewer.ViewerProgress(Sender: TObject; Stage: TProgressStage; PercentDone: Integer); begin ProgressBar.Position := PercentDone; case Stage of psStarting: ProgressBar.Visible := True; psRunning:; psEnding: ProgressBar.Visible := False; end; ProgressBar.Update; end; procedure THtmlCompViewer.ViewerPrintHTMLFooter(Sender: TObject; HFViewer: THTMLViewer; NumPage: Integer; LastPage: Boolean; var XL, XR: Integer; var StopPrinting: Boolean); var S: string; begin S := ReplaceStr(HFText, '#left', Viewer.DocumentTitle); S := ReplaceStr(S, '#right', Viewer.CurrentFile); HFViewer.LoadFromString(S); end; procedure THtmlCompViewer.ViewerPrintHTMLHeader(Sender: TObject; HFViewer: THTMLViewer; NumPage: Integer; LastPage: Boolean; var XL, XR: Integer; var StopPrinting: Boolean); var S: string; begin S := ReplaceStr(HFText, '#left', DateToStr(Date)); S := ReplaceStr(S, '#right', 'Page '+IntToStr(NumPage)); HFViewer.LoadFromString(S); end; procedure THtmlCompViewer.HotSpotChange(Sender: TObject; const URL: string); {mouse moved over or away from a hot spot. Change the status line} var Caption: string; begin Caption := ''; if URL <> '' then Caption := Caption+'URL: '+URL+' '; if Viewer.TitleAttr <> '' then Caption := Caption+'Title: '+Viewer.TitleAttr; panelBottom.Caption := Caption; end; {This routine handles what happens when a hot spot is clicked. The assumption is made that DOS filenames are being used. .EXE, .WAV, .MID, and .AVI files are handled here, but other file types could be easily added. If the URL is handled here, set Handled to True. If not handled here, set it to False and ThtmlViewer will handle it.} procedure THtmlCompViewer.HotSpotClick(Sender: TObject; const URL: string; var Handled: boolean); const snd_Async = $0001; { play asynchronously } var PC: array[0..255] of char; {$IFDEF LCL} PC2: array[0..255] of char; {$ENDIF} S, Params: string[255]; Ext: string[5]; ID: string; AbsURL: string; I, J, K: integer; begin Handled := False; {The following looks for a link of the form, "IDExpand_XXX". This is interpreted as meaning a block with an ID="XXXPlus" or ID="XXXMinus" attribute should have its Display property toggled. } I := Pos('IDEXPAND_', Uppercase(URL)); if I=1 then begin ID := Copy(URL, 10, Length(URL)-9); Viewer.IDDisplay[ID+'Plus'] := not Viewer.IDDisplay[ID+'Plus']; Viewer.IDDisplay[ID+'Minus'] := not Viewer.IDDisplay[ID+'Minus']; Viewer.Reformat; Handled := True; Exit; end; AbsURL := MyPageLoader.URLToAbsoluteURL(URL); J := Pos('HTTP:', UpperCase(AbsURL)); if (J > 0) then begin LoadURL(AbsURL); Handled := True; Exit; end; I := Pos(':', URL); J := Pos('FILE:', UpperCase(URL)); if (I <= 2) or (J > 0) then begin {apparently the URL is a filename} S := URL; K := Pos(' ', S); {look for parameters} if K = 0 then K := Pos('?', S); {could be '?x,y' , etc} if K > 0 then begin Params := Copy(S, K+1, 255); {save any parameters} S[0] := chr(K-1); {truncate S} end else Params := ''; S := Viewer.HTMLExpandFileName(S); Ext := Uppercase(ExtractFileExt(S)); if Ext = '.WAV' then begin Handled := True; {$IFNDEF LCL} sndPlaySound(StrPCopy(PC, S), snd_ASync); {$ENDIF} end else if Ext = '.EXE' then begin Handled := True; {$IFNDEF LCL} WinExec(StrPCopy(PC, S+' '+Params), sw_Show); {$ELSE} {$IFDEF MSWINDOWS} ShellExecute(Handle, nil, StrPCopy(PC, S), StrPCopy(PC2, Params), nil, SW_SHOWNORMAL); {$ELSE} //Not sure if this makes any sense since executable won't have .exe. {$IFDEF DARWIN} Shell('open -n "' + S + '" --args "' + Params + '"'); {$ELSE} Shell('"' + S + '" "' + Params + '"'); {$ENDIF} {$ENDIF} {$ENDIF} end else if (Ext = '.MID') or (Ext = '.AVI') then begin Handled := True; {$IFNDEF LCL} WinExec(StrPCopy(PC, 'MPlayer.exe /play /close '+S), sw_Show); {$ELSE} {$IFDEF MSWINDOWS} ShellExecute(Handle, nil, 'MPlayer.exe', '/play /close', nil, SW_SHOWNORMAL); {$ELSE} //No equivalent to MPlayer? {$ENDIF} {$ENDIF} end; {else ignore other extensions} editURL.Text := URL; Exit; end; I := Pos('MAILTO:', UpperCase(URL)); if (I > 0) then begin {$IFDEF MSWINDOWS} ShellExecute(0, nil, pchar(URL), nil, nil, SW_SHOWNORMAL); {$ELSE} {$IFDEF DARWIN} Shell('open "' + URL + '"'); {$ELSE} Shell('"' + URL + '"'); //use LCL's OpenURL? {$ENDIF} {$ENDIF} Handled := True; Exit; end; editURL.Text := URL; {other protocall} end; procedure THtmlCompViewer.RightClick(Sender: TObject; Parameters: TRightClickParameters); var Pt: TPoint; S, Dest: string; I: integer; HintWindow: THintWindow; ARect: TRect; begin with Parameters do begin FoundObject := Image; ViewImage.Enabled := (FoundObject <> Nil) and (FoundObject.Bitmap <> Nil); CopyImageToClipboard.Enabled := (FoundObject <> Nil) and (FoundObject.Bitmap <> Nil); if URL <> '' then begin S := URL; I := Pos('#', S); if I >= 1 then begin Dest := System.Copy(S, I, 255); {local destination} S := System.Copy(S, 1, I-1); {the file name} end else Dest := ''; {no local destination} if S = '' then S := Viewer.CurrentFile else S := Viewer.HTMLExpandFileName(S); NewWindowFile := S+Dest; OpenInNewWindow.Enabled := FileExists(S); end else OpenInNewWindow.Enabled := False; GetCursorPos(Pt); if Length(CLickWord) > 0 then begin HintWindow := THintWindow.Create(Self); try ARect := Rect(0,0,0,0); DrawTextW(HintWindow.Canvas.Handle, @ClickWord[1], Length(ClickWord), ARect, DT_CALCRECT); with ARect do HintWindow.ActivateHint(Rect(Pt.X+20, Pt.Y-(Bottom-Top)-15, Pt.x+30+Right, Pt.Y-15), ClickWord); PopupMenu.Popup(Pt.X, Pt.Y); finally HintWindow.Free; end; end else PopupMenu.Popup(Pt.X, Pt.Y); end; end; { In this event we should provide images for the html component } procedure THtmlCompViewer.ViewerImageRequest(Sender: TObject; const SRC: string; var Stream: TMemoryStream); var J: Integer; URL: string; begin URL := MyPageLoader.URLToAbsoluteURL(SRC); J := Pos('http:', LowerCase(URL)); if (J > 0) then begin MyPageLoader.LoadBinaryResource(URL, Stream); Exit; end; end; procedure THtmlCompViewer.CreateViewer(AParent, AOwner: TWinControl); begin ViewerName := 'THTMLComp written in Pascal'; Viewer := THTMLViewer.Create(AOwner); Viewer.Left := 1; Viewer.Height := 358; Viewer.Top := 1; Viewer.Width := 611; Viewer.OnHotSpotCovered := HotSpotChange; Viewer.OnHotSpotClick := HotSpotClick; Viewer.OnImageRequest := ViewerImageRequest; Viewer.OnFormSubmit := SubmitEvent; Viewer.OnHistoryChange := HistoryChange; Viewer.OnProgress := ViewerProgress; Viewer.TabStop := True; Viewer.TabOrder := 0; Viewer.Align := alClient; Viewer.DefBackground := clWindow; Viewer.BorderStyle := htFocused; Viewer.HistoryMaxCount := 6; Viewer.DefFontName := 'Times New Roman'; Viewer.DefPreFontName := 'Courier New'; Viewer.DefFontColor := clWindowText; Viewer.DefOverLinkColor := clFuchsia; Viewer.ImageCacheCount := 6; Viewer.NoSelect := False; Viewer.CharSet := DEFAULT_CHARSET; Viewer.PrintMarginLeft := 2; Viewer.PrintMarginRight := 2; Viewer.PrintMarginTop := 2; Viewer.PrintMarginBottom := 2; Viewer.PrintScale := 1; Viewer.OnMouseMove := ViewerMouseMove; Viewer.OnProcessing := ProcessingHandler; Viewer.OnPrintHTMLHeader := ViewerPrintHTMLHeader; Viewer.OnPrintHTMLFooter := ViewerPrintHTMLFooter; Viewer.OnInclude := ViewerInclude; //Viewer.OnSoundRequest := SoundRequest; Viewer.OnMetaRefresh := MetaRefreshEvent; Viewer.OnObjectClick := ObjectClick; Viewer.OnRightClick := RightClick; Viewer.Parent := AParent; // ShowImages.Checked := Viewer.ViewImages; Viewer.HistoryMaxCount := MaxHistories; {defines size of history list} end; procedure THtmlCompViewer.LoadFromFile(AFilename: string); begin Viewer.LoadFromFile(HtmlToDos(Trim(AFilename))); end; function THtmlCompViewer.GetDocumentTitle: string; begin Result := Viewer.DocumentTitle; end; procedure THtmlCompViewer.SetShowImages(AValue: Boolean); begin Viewer.ViewImages := AValue; end; procedure THtmlCompViewer.HandlePageLoaderTerminated(Sender: TObject); begin inherited HandlePageLoaderTerminated(Sender); Viewer.LoadFromString(MyPageLoader.Contents); Caption := Viewer.DocumentTitle; end; procedure THtmlCompViewer.Reload; begin Viewer.ReLoad; Viewer.SetFocus; end; initialization SetBrowserViewerClass(THtmlCompViewer); end.