Potansif Logo
potansif.com Kurumsal Çözümler
Mühendislik Arşivi Yayın Tarihi: 30 Eylül 2019 • Yazar: Uğur Parlayan

TWebBrowser Lafınızı Dinlesin, HTML 5'ten Anlasın

#delphi #Programlama #HTML5 #TWebBrowser

Merhaba, Bu yazımızda TWebBrowser nesnesinde doğrudan HTML kodlarını nasıl çalıştıracağımızı, bir resmi, fotoğrafı disk işlemlerini kullanmadan doğrudan nasıl HTML koduna gömebileceğimizi, HTML5 ile birlikte gelen bazı yenilikleri nasıl kullanabileceğimizi, bu çerçevede bir vektör grafiği nasıl oluşturabileceğimizi inceleyeceğiz. Tüm bunları yapabilmek için önce TWebBrowser nesnesinde doğrudan nasıl HTML kodları çalıştırabileceğimizin alt yapısını kurmayı ve IE’nin HTML5 anlar hale nasıl getirileceği gibi sorunları nasıl aşabileceğimize bakacağız.

Makalemizdeki örnek kodların düzgün çalışabilmesi için XE2 ve üzeri bir Delphi sürümü kullanmanız gerekecek. Eğer daha eski Delphi sürümlerini kullanıyorsanız üzülmeyin, aşağıda paylaşacağım linklerde sizin sürümlere uyan örnek kodlar bulmanız da mümkün olabilir. Lazarus için henüz bir denemem olmadı. (Muhtemelen Lazarus’ta çalışmayacaktır)

Haydi başlayalım;

TWebBrowser’in HTML kodlarını doğrudan çalıştırabilmesi ve ekranda gösterebilmesi için IPersistStreamInit arabiriminden faydalanacağız. Kodların taşınabilirliğini arttırmak ve gereksiz WITH kullanımını önlemek adına biz bu kodları CLASS HELPER tekniğini kullanarak yazacağız. Gerekli açıklamalar kod içerisinde yer alacağı için ayrıca açıklama yapılmayacak. Şahsen yazılan kodun karmaşık olmasını sevmem ve tercih de etmem, ahengin basitlikte yattığına inanır ve o doğrultuda ilerlemeyi tercih ederim. Dolayısıyla kodlar olabildiğince sade ve basit tutulmaya çalışıldı.

...
...
interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.OleCtrls, SHDocVw, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    WebBrowser1: TWebBrowser;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  // BU KISMI AYRI BİR UNIT'E ALABİLİRSİNİZ...

  TWebBrowserHelper = class helper for TWebBrowser                         // Sınıf hizmetçisi
    public
      procedure RunHTML(aHTMLCode: String; aApplication: TApplication);    // Doğrudan HTML kodlarını çalıştıracak olan yordamımız
      function GetHTML: String;                                            // TWebBrowser nesnesindeki HTML kodu
      function GetTEXT: String;                                            // TWebBrowser nesnesinde gösterilen sayfadaki text (HTML kodu içermez, düz metindir...)
  end;
  TIEMode = (iemUnknown, iemIE7, iemIE8, iemIE9, iemIE10, iemIE11);
  function SetupIEMode(aAyarla: Boolean; IE_Kipi: TIEMode): LongInt;       // Internet Explorer'in hangi versiyon kipinde çalışacağını YÖNETİR
  function SetIEMode(Mode: TIEMode): boolean;                              // Internet Explorer'in hangi versiyon kipinde çalışacağını BELİRLER
  function GetIEMode: TIEMode;                                             // Internet Explorer'in hangi versiyon kipinde çalıştığını OKUR

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
    Winapi.ActiveX        //  IPersistStreamInit
  , MSHTML                //  IHTMLElement
  , System.Win.Registry   //  TRegistry
  ;

{ TWebBrowserHelper }

procedure TWebBrowserHelper.RunHTML(aHTMLCode: String; aApplication: TApplication);
var
  SS: TStringStream;                             // HTML KodlarımızıTWebBrowser'a aktarmak için kullanacağız
begin
  Navigate('about:blank');                       // TWebBrowser nesnesine temiz bir sayfa açıyoruz.
  try
    while (ReadyState  nil) do E := E.parentElement;
      Result := E.outerHTML;
  end;
end;

function TWebBrowserHelper.GetTEXT: String;
var
  Bodi : IHTMLElement;
begin
  Result := '';
  if  (Assigned(Document) = TRUE)
  then Result := (Document as IHTMLDocument2).body.innerText;
end;

TWebBrowser nesnemize doğrudan HTML kodlarını çalıştırma yeteneği kazandırmış olduk. Fakat IE varsayılan olarak HTML5 diyalektiğini kullanmaya ayarlanmadığı için HTML5 kodlarını çalıştırmak istediğinizde boş bir sayfa ile karşılaşabilir veya HTML5 komutlarının gözardı edildiğini görebilirsiniz. Bu sorunu aşmak için ise Registry’de bir ayarlama yapmamız gerekir. Bunu yapsak bile bu ayarı TWebBrowser nesnesini barındıran formun SHOW edilmeden önce gerçekleştirilmesi işletim sistemi tarafından beklenir… Dolayısıyla aşağıda yer alan örnek kodları kullanmak için formun create edildiği fakat henüz show edilmediği bir noktada bu kodları çağırmanız gerekecektir. Esasen bu kodların tüm uygulama yaşam döngüsü boyunca sadece 1 defa çalıştırılması yeterli olacaktır.

function SetupIEMode(aAyarla: Boolean; IE_Kipi: TIEMode): LongInt;
const
  REG_KEY = 'Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION';
var
  Reg     : TRegistry;
  Value   : LongInt;
  I       : LongInt;
  Uygulama: String;
begin

  Result := 0;
  if  (aAyarla = TRUE )
  and ( IE_Kipi = iemUnknown ) then Exit;                     // IE'nin bilinmeyen (muhtemelen daha yeni) bir sürümüyse çık...

  Uygulama := ExtractFileName(ParamStr(0));                   // Kendi uygulamamızın EXE adı (Mesela "Project1.exe" gibi...)

  Value := 0;
  if (aAyarla = TRUE ) then begin                             // Aşağıdaki kısım ile ilgili olarak şu linki incelemenizi tavsiye ederim;
                                                              // http://www.ahmetaltay.com.tr/2016/02/delphi-twebbrowser-emulasyonu/
     case IE_Kipi of                                          // IE'nin ne şekilde çalışacağını seçiyoruz...
          iemIE7 : Value := 7000;
          iemIE8 : Value := 8888;                             // IE 8  + DOCTYPE spesifikasyonunu destekler
          iemIE9 : Value := 9999;                             // IE 9  + DOCTYPE spesifikasyonunu destekler
          iemIE10: Value := 10001;                            // IE 10 + DOCTYPE spesifikasyonunu destekler
          iemIE11: Value := 11001;                            // IE 11 + DOCTYPE spesifikasyonunu destekler
          else     Value := 11001;                            // IE 11 ve üzeriise IE11 + DOCTYPE spesifikasyonunu destekler
      end;
  end;

  Reg := nil;
  try
    // Bu noktada uygulamamız için REGISTRY'de bir ayarlama yapıyoruz
    // Bu ayarlama uygulamamızın hangi IE sürümüyle çalışacağını
    // İşletim sistemine söylemiş olacak...
    Reg := TRegistry.Create();
    Reg.RootKey := HKEY_CURRENT_USER;
    if (Reg.OpenKey(REG_KEY, True) ) then begin
        if (aAyarla = TRUE) then begin
            Reg.WriteInteger(Uygulama, Value);
            Result := Value;
        end else begin
            Value := Reg.ReadInteger( Uygulama );
        end;
        Reg.CloseKey;
    end;
  except;
    // Herhangi bir hata mesajı görmek istemiyoruz...
  end;

  if (Assigned(Reg) = TRUE) then FreeAndNil(Reg);             // REG nesnesinin Temizliği...

  if (aAyarla = FALSE) and (Value > 0) then begin
      I := Value div 1000;
      if (I >= 7) and (I = 12) then Result := Byte(iemIE11);
          end;
      end;
  end;
end;

function SetIEMode(Mode: TIEMode): boolean;
begin
  Result := ( SetupIEMode(TRUE, Mode) > 0 );
end;

function GetIEMode: TIEMode;
begin
  Result := TIEMode( Byte( SetupIEMode(FALSE, iemUnknown) ) );
end;

Bu noktadan sonra uygulamanızın ana formunun en alt satırını şu şekilde düzenlemeniz HTML5 kodlarını TWebBrowser üzerinde çalıştırmanıza imkan tanıyacaktır.

initialization
  SetIEMode( iemIE11);
end.

Örnek uygulama için boş bir VCL Projesi oluşturup form üzerine bir adet TWEBBROWSER ve bir adet TButton nesnesi ekleyin. Button1 nesnesinin onclick olayına aşağıdaki kodu yazıp çalıştırın. Butona bastığınzıda WebBrowser1’de yazdığınız HTML kodlarının derlendiğini göreceksiniz.

Kod bütünlüğünün bozulmaması adına .pas ve .dfm dosya içeriğini aşağıda paylaşıyorum;

unit Ana_;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.OleCtrls, SHDocVw, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    WebBrowser1: TWebBrowser;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  // BU KISMI AYRI BİR UNIT'E ALABİLİRSİNİZ...

  TWebBrowserHelper = class helper for TWebBrowser                         // Sınıf hizmetçisi
    public
      procedure RunHTML(aHTMLCode: String; aApplication: TApplication);    // Doğrudan HTML kodlarını çalıştıracak olan yordamımız
      function GetHTML: String;                                            // TWebBrowser nesnesindeki HTML kodu
      function GetTEXT: String;                                            // TWebBrowser nesnesinde gösterilen sayfadaki text (HTML kodu içermez, düz metindir...)
  end;
  TIEMode = (iemUnknown, iemIE7, iemIE8, iemIE9, iemIE10, iemIE11);
  function SetupIEMode(aAyarla: Boolean; IE_Kipi: TIEMode): LongInt;       // Internet Explorer'in hangi versiyon kipinde çalışacağını YÖNETİR
  function SetIEMode(Mode: TIEMode): boolean;                              // Internet Explorer'in hangi versiyon kipinde çalışacağını BELİRLER
  function GetIEMode: TIEMode;                                             // Internet Explorer'in hangi versiyon kipinde çalıştığını OKUR

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
    Winapi.ActiveX        //  IPersistStreamInit
  , MSHTML                //  IHTMLElement
  , System.Win.Registry   //  TRegistry
  ;

procedure TForm1.Button1Click(Sender: TObject);
begin
  WebBrowser1
  .RunHTML( ''    // -> HTML5
          + ''
          + ''
          + ''    // Bir vektörel Grafik (SVG)
          + '  '
          + '    '
          + '      '
          + '      '
          + '    '
          + '  '
          + '  '        // Dikdörtgen (Vektör bazlıdır...)
          + '  '     // Elips
          + '  Uğur PARLAYAN'       // metin
          + '  Maalesef, tarayıcınız satır içi SVG desteklemiyor.'
          + ''
          + ''            // Canvas bir dikdörtgen (pixel bazlıdır...)
          + '![32x32 Rubicube Logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdF)'
          + ''
          + ''
          , Application
          );
end;

{ TWebBrowserHelper }

procedure TWebBrowserHelper.RunHTML(aHTMLCode: String; aApplication: TApplication);
var
  SS: TStringStream;                             // HTML KodlarımızıTWebBrowser'a aktarmak için kullanacağız
begin
  Navigate('about:blank');                       // TWebBrowser nesnesine temiz bir sayfa açıyoruz.
  try
    while (ReadyState  nil) do E := E.parentElement;
      Result := E.outerHTML;
  end;
end;

function TWebBrowserHelper.GetTEXT: String;
var
  Bodi : IHTMLElement;
begin
  Result := '';
  if  (Assigned(Document) = TRUE)
  then Result := (Document as IHTMLDocument2).body.innerText;
end;

function SetupIEMode(aAyarla: Boolean; IE_Kipi: TIEMode): LongInt;
const
  REG_KEY = 'Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION';
var
  Reg     : TRegistry;
  Value   : LongInt;
  I       : LongInt;
  Uygulama: String;
begin

  Result := 0;
  if  (aAyarla = TRUE )
  and ( IE_Kipi = iemUnknown ) then Exit;                     // IE'nin bilinmeyen (muhtemelen daha yeni) bir sürümüyse çık...

  Uygulama := ExtractFileName(ParamStr(0));                    // Kendi uygulamamızın EXE adı (Mesela "Project1.exe" gibi...)

  Value := 0;
  if (aAyarla = TRUE ) then begin                             // Aşağıdaki kısım ile ilgili olarak şu linki incelemenizi tavsiye ederim;
                                                              // http://www.ahmetaltay.com.tr/2016/02/delphi-twebbrowser-emulasyonu/
     case IE_Kipi of                                          // IE'nin ne şekilde çalışacağını seçiyoruz...
          iemIE7 : Value := 7000;
          iemIE8 : Value := 8888;                             // IE 8  + DOCTYPE spesifikasyonunu destekler
          iemIE9 : Value := 9999;                             // IE 9  + DOCTYPE spesifikasyonunu destekler
          iemIE10: Value := 10001;                            // IE 10 + DOCTYPE spesifikasyonunu destekler
          iemIE11: Value := 11001;                            // IE 11 + DOCTYPE spesifikasyonunu destekler
          else     Value := 11001;                            // IE 11 ve üzeriise IE11 + DOCTYPE spesifikasyonunu destekler
      end;
  end;

  Reg := nil;
  try
    // Bu noktada uygulamamız için REGISTRY'de bir ayarlama yapıyoruz
    // Bu ayarlama uygulamamızın hangi IE sürümüyle çalışacağını
    // İşletim sistemine söylemiş olacak...
    Reg := TRegistry.Create();
    Reg.RootKey := HKEY_CURRENT_USER;
    if (Reg.OpenKey(REG_KEY, True) ) then begin
        if (aAyarla = TRUE) then begin
            Reg.WriteInteger(Uygulama, Value);
            Result := Value;
        end else begin
            Value := Reg.ReadInteger( Uygulama );
        end;
        Reg.CloseKey;
    end;
  except;
    // Herhangi bir hata mesajı görmek istemiyoruz...
  end;

  if (Assigned(Reg) = TRUE) then FreeAndNil(Reg);             // REG nesnesinin Temizliği...

  if (aAyarla = FALSE) and (Value > 0) then begin
      I := Value div 1000;
      if (I >= 7) and (I = 12) then Result := Byte(iemIE11);
          end;
      end;
  end;
end;

function SetIEMode(Mode: TIEMode): boolean;
begin
  Result := ( SetupIEMode(TRUE, Mode) > 0 );
end;

function GetIEMode: TIEMode;
begin
  Result := TIEMode( Byte( SetupIEMode(FALSE, iemUnknown) ) );
end;

initialization
  SetIEMode( iemIE11);

end.

Bu da DFM dosyasıdır…

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  DesignSize = (
    635
    299)
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 8
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object WebBrowser1: TWebBrowser
    Left = 8
    Top = 39
    Width = 619
    Height = 252
    Anchors =
    TabOrder = 1
    ControlData = {
      4C000000FA3F00000C1A00000000000000000000000000000000000000000000
      000000004C000000000000000000000001000000E0D057007335CF11AE690800
      2B2E126208000000000000004C0000000114020000000000C000000000000046
      8000000000000000000000000000000000000000000000000000000000000000
      00000000000000000100000000000000000000000000000000000000}
  end
end