Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2021年11月13日] [更新 2021年11月14日] Delphi サンプルプログラム集
   
984_ウェブブラウザのアドレス欄の URL 取得と URL のセット
動作確認等 Windows 10 ビルド 19042 Pro 64 bit + Delphi XE5(UP2) Pro VCL-32
使用したウェブブラウザは本文参照.掲載画像は Microsott Edge
984_WebBrowser_AddressBar.zip [3.5 MB] 2021年11月14日版 (EXE 同梱)







ウェブブラウザのアドレス欄の URL 取得と URL のセット


ウェブブラウザのアドレス欄 (アドレスバー) の値を取得したり,アドレス欄に URL の値をセットしてその URL を表示させるサンプルです.ウェブブラウザのアプリに依存しない処理とするため,ショートカットキーを使用して操作する方法としています.
ウェブブラウザでは,以下のようなショートカットキーが利用可能です.



ショートカットキー 機能
[Alt] + [←] 戻る
[Alt] + [→] 進む
[Alt] + [Home] ホーム
[Home] ページの先頭へ
[End] ページの最後へ
[Alt] + [D] アドレスバーに移動して 全選択
[Ctrl] + [F] ページ内検索
ページ内検索中の次検索は [F3]
前検索は [Shift] + [F3]
[Ctrl] + [E] 検索窓を表示.閉じるのは [ESC]
[Ctrl] + [F4] 現在のタブを閉じる
[Ctrl] + [T] 新規タブ
[Ctrl] + [TAB] タブの移動 (右方向)
[Shift] + [Ctrl] + [T] 閉じた直後のタブを再表示
[F5] ページ更新
[Shift] + [F5] キャッシュを使用しないページ更新
[Ctrl] + [F5] ページのキャッシュをクリア
[Ctrl] + [U] ページのソースを新規タブで表示して,そのタブをアクティブにする
[F12] (要素の) 検証.開発者用.トグル
[Ctrl] + [+] 拡大表示
[Ctrl] + [-] 縮小表示
[Ctrl] + [0]] 等倍表示 (デフォルトの表示倍率)


本ページのサンプルは,以下のページからダウンロードしたファイルに含まれているショートカットキー送信操作用ユニットを使用しています.plSendShortCut.pas と plvkEnum.pas ファイルをライブラリパスの通った場所 (フォルダ) に置いて,uses に plSendShortCut を追加して使用します.



本ページでは,直前にアクティブだったアプリのウィンドウに対してショートカットキーを送信して操作します.起動中のウェブブラウザのウィンドウハンドルの取得や,ウェブブラウザの起動については以下の記事のサンプルを参考にしてください.
下図は,今回のテストに使用したウェブブラウザです.



図1
動作確認に使用したブラウザ




01_アドレス欄の URL を取得 - クリップボード使用


ウェブブラウザのアドレス欄の URL の値を取得するサンプルです.URL の値をクリップボードにコピーして,フォームの TEdit に貼り付けます.
URL が取得できれば,URLDownloadToFile 関数 (Winapi.UrlMon ユニット) で HTML ファイルをダウンロードしたり,TIdHTTP 等を使用してそのウェブページの HTML コードを取得することができます.


図2
実行例

リスト1
クリップボードを使用して,アドレス欄の URL を取得
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
 private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  Vcl.Clipbrd,
  plSendShortCut;

{$R *.dfm}




//=============================================================================
//  ブラウザのアドレスバーからに URL を取得
//  クリップボードを使用
//
//  動作確認方法
//  (1) ウェブブラウザを起動
//  (2) このプログラムの Button1 をクリック
//
//  uses に Vcl.Clipbrd, plSendShortCut が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  Edit1.Text := '';

  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Alt + D');
  SendShortCutKeyEx(LTargetWnd, 'Ctrl + C');

  Edit1.Text := Clipboard.AsText;
  SetForegroundWindow(Handle);
end;

end.




02_アドレス欄へ URL をセット - キー操作をエミュレート


ウェブブラウザのアドレス欄に URL の値としての文字列をセットするサンプルです.ショートカットキー送信操作用ユニット plSendShortCut の SendInputText 関数を使用して URL 欄に文字列を送信します.

SendInputText 関数で文字列を送信した場合,受信側で日本語 IME が ON になっていると,かな漢字変換の未確定の状態になります.そこで,Button1 クリックのコードでは,日本語 IME を OFF にしてから文字列を送信します.Button2 クリックのコードでは,日本語 IME が ON の時は,文字列を送信した後に [Enter] キーを送信して確定状態にしています.

このサンプルは,Internet Explorer では動作しません.



図3
実行結果

リスト2
キー操作をエミュレートして,アドレス欄に URL をセット
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
 private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  function IsImeOnWnd(AWnd: HWND): Boolean;
  procedure ImeOnOffWnd(AWnd: HWND; IsOn: Boolean);

var
  Form1: TForm1;

implementation

uses
  Winapi.Imm,
  plSendShortCut;

{$R *.dfm}

const
  IMC_GETOPENSTATUS = $05;
  IMC_SETOPENSTATUS = $06;

//=============================================================================
//  ウェブブラウザのアドレスバーに URL セットしてその URL のページを表示
//  キー操作をエミュレート
//
//  動作確認方法
//  (1) ウェブブラウザを起動
//  (2) このプログラムの TButton をクリック
//
//  plSendShortCut (ショートカットキー送信操作用ユニット) の SendInputText 使用
//  SendInputText 手続きは Windows API の SendInput 関数を使用している
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Alt + D');
  SendShortCutKeyEx(LTargetWnd, 'Delete');

  // 日本語 IME を OFF にする
  ImeOnOffWnd(LTargetWnd, False);

  SendInputText(LTargetWnd, 'http://mrxray.on.coocan.jp/index.htm');
  SendShortCutKeyEx(LTargetWnd, 'Enter');
end;

//=============================================================================
//  ウェブブラウザのアドレスバーに URL セットしてその URL のページを表示
//
//  SendInputText で送信した文字列は IME が ON だと未確定の文字列になる
//  その場合は [Enter] キーを送信して確定する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Alt + D');
  SendShortCutKeyEx(LTargetWnd, 'Delete');

  SendInputText(LTargetWnd, 'http://mrxray.on.coocan.jp/index.htm');
  // 日本語 IME が ON だったら変換を確定する
  if IsImeOnWnd(LTargetWnd) then begin
    SendShortCutKeyEx(LTargetWnd, 'Enter');
  end;
  SendShortCutKeyEx(LTargetWnd, 'Enter');
end;

//-----------------------------------------------------------------------------
//  他のアプリの日本語 IME の ON / OFF を調べる
//  この関数は,自アプリにおける検出は不可
//  uses に Winapi.Imm が必要
//-----------------------------------------------------------------------------
function IsImeOnWnd(AWnd: HWND): Boolean;
var
  LhIMC : HIMC;
begin
  LhImc  := ImmGetDefaultIMEWnd(AWnd);
  Result := Boolean(SendMessage(LhImc, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0));
end;
//-----------------------------------------------------------------------------
//  他のアプリの日本語 IME の ON / OFF を切り換える
//  この手続きは,自アプリに対する操作は不可
//  uses に Winapi.Imm が必要
//-----------------------------------------------------------------------------
procedure ImeOnOffWnd(AWnd: HWND; IsOn: Boolean);
var
  LhIMC : HIMC;
begin
  LhImc := ImmGetDefaultIMEWnd(AWnd);
  SendMessage(LhImc, WM_IME_CONTROL, IMC_SETOPENSTATUS, LPARAM(IsOn));
end;

end.




03_アドレス欄へ URL をセット - クリップボード使用


文字列をクリップボードにコピーしてアドレス欄に貼り付ければ,日本語 IME の操作は必要ありません.そのサンプルです.
このサンプルは,Internet Explorer では動作しません.


リスト3
クリップボードを使用して,アドレス欄に URL をセットして URL をブラウザで表示
unit Unit1;

interface

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

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

var
  Form1: TForm1;

implementation

uses
  Vcl.Clipbrd,
  plSendShortCut;

{$R *.dfm}

//=============================================================================
//  ウェブブラウザのアドレスバーに URL セットしてその URL のページを表示
//  クリップボードを使用する方法
//
//  動作確認方法
//  (1) ウェブブラウザを起動
//  (2) このプログラムの Button1 をクリック
//
//  plSendShortCut (ショートカット送信操作用ユニット) を使用
//  uses に Vcl.Clipbrd が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Alt + D');
  SendShortCutKeyEx(LTargetWnd, 'Delete');

  Clipboard.AsText := 'http://mrxray.on.coocan.jp/index.htm';
  SendShortCutKeyEx(LTargetWnd, 'Ctrl + V');
  SendShortCutKeyEx(LTargetWnd, 'Enter');
end;

end.


ウェブブラウザのアドレス欄は,ウェブ検索のキーワード入力にも利用できます.その例です.
このサンプルは,Internet Explorer では動作しません.



図4
検索を実行

procedure TForm1.Button1Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Alt + D');
  SendShortCutKeyEx(LTargetWnd, 'Delete');

  Clipboard.AsText := 'delphi ショートカットキー 送信';
  SendShortCutKeyEx(LTargetWnd, 'Ctrl + V');
  SendShortCutKeyEx(LTargetWnd, 'Enter');
end;


ここまでのサンプルでは,[Alt] + [D] と [Ctrl] + [Delete] のキー操作後に,アドレス欄に URL 等の文字列トをセットしました.文字列は,入力フォーカスがあるコントロールにセットすることができます.
次のコードは,対象のウィンドウの入力コントロール内をマウスでクリックした後,そのコントロールに文字列をセットします.



procedure TForm1.Button2Click(Sender: TObject);
var
  LTargetWnd : HWND;
begin
  // このフォームを表示する前にアクティブだったウィンドウのハンドルを取得
  LTargetWnd := GetNextWindow(Handle, GW_HWNDNEXT);
  while not IsWindowVisible(LTargetWnd) do begin
    LTargetWnd := GetNextWindow(LTargetWnd, GW_HWNDNEXT);
  end;


  SendShortCutKeyEx(LTargetWnd, 'Ctrl + A');
  SendShortCutKeyEx(LTargetWnd, 'Delete');

  Clipboard.AsText := 'ショートカットキー 送信';
  SendShortCutKeyEx(LTargetWnd, 'Ctrl + V');
end;




04_ショートカットキー操作によるページのソースコード取得


ウェブブラウザのショートカットキーに [Ctrl] + [U] があります.これは,新規にタブを表示してページのソースコードを表示します.そのコードをコピーすれば,原理的にはページのソースコードが取得可能ということになります.ページのソースコードの表示と,コートを選択してコピーする処理にはタイムラグがあります.
コピー処理のタイムラグは,クリップボードを監視することで回避てきます.ここでは中村拓男氏作のクリップボード監視用のコンポーネントを使用しています.

このサンプルは,Internet Explorer では動作しません.筆者の環境の FireFox でば取得できませんでした.ページのソースコードは,HTML ファイルをダウンロードするか,TIdHTTP コンポーネントを使用して取得する方が確実です.



図5
実行例

リスト4
ショートカットキー操作によるページのソースコード取得
  function QueryFullProcessImageNameW(Process: THandle; Flags: DWORD; Buffer: PChar;
    Size: PDWORD): DWORD; stdcall; external 'kernel32.dll';
  function EnumTopWindowExeName(hWindow: HWND; lPar: LPARAM): BOOL; stdcall;

var
  Form1: TForm1;

implementation

uses
  Vcl.Clipbrd,
  Winapi.Dwmapi,
  System.StrUtils,
  plSendShortCut;

{$R *.dfm}

var
  FTargetWnd : HWND;

//=============================================================================
//  ウェブブラウザで表示中のページのソースコードを取得
//  ウェブブラウザのショートカットキー操作を使用する例
//
//  FireFox, IE 11 では動作しない
//  FireFox は [Ctrl] + [A] の操作でブラウザがハングアップ
//  全て選択状態にして [Ctrl] + [C] を送信してもハングアップする
//  IE 11 は管理者への昇格ダイアログが表示され,別ウィンドウ表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LExeName : string;
  LArgName : string;
begin
  Clipboard.Clear;
  Memo1.Lines.Clear;
  Self.FormStyle := fsStayOnTop;


  // 対象のブラウザの EXE 名
  // LExeName := 'chrome.exe';
  LExeName := 'MSEdge.exe';

  // 起動しているかをチェック
  LArgName := LExeName;
  EnumWindows(@EnumTopWindowExeName, LPARAM(@LArgName));

  FTargetWnd := StrToIntDef(LArgName, 0);
  if FTargetWnd = 0 then Exit;


  // ソースコード表示と全選択・コピーの処理はタイムラグがある 
  SendShortCutKeyEx(FTargetWnd, 'Ctrl + U');
  Sleep(100);
  SendShortCutKeyEx('Ctrl + A');
  SendShortCutKeyEx('Ctrl + C');
end;

//=============================================================================
//  TNkClipDetector の OnClipChange イベント
//  TNkClipDetector は中村拓男氏作のクリップボード監視用コンポーネント
//
//  ソースコード取得操作前に Clipboard.Clear を実行しておく
//=============================================================================
procedure TForm1.NkClipDetector1ClipChange(Sender: TObject);
begin
  if Clipboard.HasFormat(CF_TEXT) then begin
    SendShortCutKeyEx(FTargetWnd, 'Ctrl + F4');
    Sleep(50);
    Memo1.Lines.Text := Clipboard.AsText;
    SetForegroundWindow(Handle);
    Self.FormStyle := fsNormal;
  end;
end;

//-----------------------------------------------------------------------------
//  EnumWindows のコールバック関数
//  引数 (lPar) と同じ EXE 名の EXE が起動しているかを検出
//  検出したらウィンドウハンドルの値を文字列にして引数 lPar に返す
//
//  Microsoft Edge の EXE 名は Chromium 版と非 Chromium 版とでは異なる
//   非 Chromium 版では microsoftedge.exe
//   Chromium 版では MSEdge.exe
//-----------------------------------------------------------------------------
function EnumTopWindowExeName(hWindow: HWND; lPar: LPARAM): BOOL; stdcall;
const
  PROCESS_QUERY_LIMITED_INFORMATION = $1000;
  DWMWA_CLOAKED = 14;
var
  LExeName    : string;
  LCloaked    : BOOL;
  LProcessID  : DWORD;
  LhProcess   : THandle;
  LBuffer     : array [0..MAX_PATH - 1] of Char;
  LSTR_SIZE   : DWORD;
  LAppPath    : string;
begin
  Result := True;
  LExeName := LowerCase(PString(lPar)^);

  if GetWindow(hWindow, GW_OWNER) <> 0 then exit;
  if not IsWindowVisible(hWindow) then exit;

  // 待機中またはバックグラウンドのウィンドウは対象外
  DwmGetWindowAttribute(hWindow, DWMWA_CLOAKED, @LCloaked, SizeOf(LCloaked));
  if LCloaked then Exit;


  // プロセス ID を取得.その値からプロセスのハンドル取得
  GetWindowThreadProcessId(hWindow, Addr(LProcessID));
  LhProcess := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, LProcessID);
  try
    // プロセスのハンドルから EXE のフルパスを取得
    FillChar(LBuffer, SizeOf(LBuffer), #0);
    LSTR_SIZE := Length(LBuffer);
    if QueryFullProcessImageNameW(LhProcess,
                                  0,
                                  @LBuffer[0],
                                  @LSTR_SIZE) = 0 then Exit;
    LAppPath := LBuffer;
    LAppPath := ExtractFileName(LAppPath);

    if RightStr(LExeName, 4) <> '.exe' then LExeName := LExeName + '.exe';
    if SameText(LAppPath, LExeName) then begin
      PString(lPar)^ := IntToStr(hWindow);
      Result := False;
    end;
  finally
    CloseHandle(LhProcess);
  end;
end;


[備考]
一般的に,デスクトップアプリのウィンドウはそのウィンドウのクラス名で判定できますが,Coogle Chromw と Microsoft Edge はクラス名では判定できません.どらちのクラス名も同じ Chrome_WidgetWin_1 です.そのため,上のコードでは EnumWindows 関数を使用して,EXE 名で判定しています.





05_IE 11 ( Internet Explorer ) における動作


IE 11 (Internet Explorer) では動作しないサンプルがありますが,これは Internet Explorer の特性によるもの
です.IE 11 で同様の機能を実現するには,InternetExplorer オブジェクトのインスタンスを取得または生成して操作します.



[備考]
Windows 11 では,単体のアプリとしての IE 11 (Internet Explorer) は提供されなくなりました.
代替えとして,Microsoft Edge に IE モードが実装されています.