6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DelphiAdvent Calendar 2023

Day 12

SendMessageでメモ帳へ書き込んでみよう

Last updated at Posted at 2023-12-11

delphiから、メモ帳を起動してテキストを書き込みます

絵菜SendMessage0022.jpg

小ネタです。
delphiは、windows API や メッセージを処理することもできます。
こんなことをやります。

・ShellExecute で、メモ帳を起動します。
・FindWindowW で、起動中のメモ帳のウインドウハンドルを取ります
・FindWindowEx でメモ帳の中の編集領域のウインドハンドルを取ります
・SendMessage で書き込みます

画面を作ります

ファイル >> 新規作成 >> Windows VCLアプリケーション delphi と選択して、新規のアプリを作ります。
コンポーネントのパレットから
・memo1
・edit1
・button1
を貼りつけてください。
以上で画面作りは完了です。
C:(途中省略)\Embarcadero\Studio\Projects\ の下に適当なファイルフォルダーを作って保存してください。
ファイル >> すべて保存 を選択します。ファイル名やプロジェクトの名前はデフォルトのままで問題ありません。

プログラム

メモ帳を起動するには、ShellExecute というWindowsのAPIを使用します。delphiから使用するために、uses節に Winapi.ShellAPI を書き足してください。

ちっちゃいプログラムなので全文を掲載します。

unit Unit1;

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  lpClassName: Pchar;
  Hwnd_p, Hwnd_c: HWND;
begin
  //メモ帳のクラス名は'Notepad'。
  lpClassName:= Pchar('Notepad'); //Pchar型に変換('Notepad')

  //すでにメモ帳が起動しているか? いないか? 確認します
  //メモ帳のHandle:=FindWindowW(pChar型で'Notepad', ウインドウ名省略でnil)
  Hwnd_p := FindWindowW(PChar(lpClassName), nil);

  //FindWindowWの結果が0のときはメモ帳が起動していません
  if Hwnd_p = 0 then
    //ShellExecuteでメモ帳を起動します
    ShellExecuteA(Hwnd_p, '', 'notepad.exe', nil, nil, SW_SHOW);

  if Hwnd_p <> 0 then
  begin
    //親のハンドルでメモ帳のタイトルバーに書込
    SendMessage(Hwnd_p, WM_SETTEXT, 0, LPARAM(PChar(Edit1.Text)));

    //子のハンドル:=FindWindowEx(親のWindowHandle, 0, 入力部分の名は'Edit','')
    Hwnd_c :=FindWindowEx(Hwnd_p,0 ,PChar('EDIT'), '');

    //子のハンドルで編集画面に書込
    SendMessage(Hwnd_c, WM_SETTEXT, 0, LPARAM(PChar(memo1.Text)));
  end;
end;
end.

実験してみましょう

まず、メモ帳が起動していない状態で、上記のアプリを実行します。
button1をクリックします。
メモ帳が起動します。

そうしたら、edit1 と memo1 に何か適当にテキストを入力してから、
もう一度、button1 をクリックしてください。

sendmessage01.jpg

メモ帳に、文字列が転送されたら、成功です。
(なお、メモ帳のタイトルは、メモ帳にフォーカスを入れると、元に直されちゃいます)

説明

FindWindowWは、起動中のウインドウを探します。

起動していないときは、結果は0です。見つかったときは、起動中のウインドウのウインドウハンドルを返します。
Pcharに変換しているのは、Windows APIは、NULLで終わる文字列を使うためです。

Hwnd_p := FindWindowW( PChar( lpClassName ), nil ); の意味は、「クラス名またはウインドウのタイトル名から、起動中のウインドウのハンドルを探してください」です。

FindWindowWのパラメータは次のとおり

パラメータ 意味
1 lpClassName クラス名
2 lpWindowName ウインドウの名(タイトルバー)

※参考 FindWindowW 関数
 https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindoww

この記事では、メモ帳の名前は、Notepadだとわかっているため、クラス名から探しています。
ここで得られたウインドウハンドル宛てに、 後述の方法でメッセージを送ります。

ShellExecuteAは、アプリを起動します。

ShellExecuteAはアプリを起動して、ウインドウハンドルを返します。
notopadつまりメモ帳は、パスが通っているらしくて、フルパスを指定しなくても起動します。本当はフルパス指定みたいです。

ShellExecuteA(Hwnd_p, '', 'notepad.exe', nil, nil, SW_SHOW);

ShellExecuteAのパラメータは次のとおり

パラメータ 意味
1 hwnd ウインドウハンドル。起動したウインドウのハンドルを返します
2 lpOperation 編集や検索などの動作を指示。省略
3 lpFile ファイル名。notepad.exeを指定
4 lpParameters 起動時に渡すパラメーター。省略
5 lpDirectory 作業ディレクトリー。省略
6 nShowCmd 表示方法 SW_SHOW(ウィンドウをアクティブ化し、現在のサイズと位置で表示)を指定

※参考 ShellExecuteA 関数
 https://learn.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shellexecutea

FindWindowExは、子のウインドウを探します

FindWindowWが返すウインドウハンドルから直下の子のウインドウハンドルを返します。

メモ帳の編集領域のウインドウハンドル:= FindWindowEx(Hwnd_p,0 ,PChar('EDIT'), '');
です。メモ帳の編集領域を担当しているコントロールのクラス名は、ネットをさまよって調べた結果、'EDIT'という名前らしいです。

FindWindowExのパラメータは次のとおり

パラメータ 意味
1 hWndParent 親のウインドウハンドル
2 hWndChildAfter 子のウインドウハンドル。孫は探さないので 0を指定
3 lpszClass 探したい子のクラス名 'EDIT'
4 lpszWindow ウインドウの名前。省略

※参考 FindWindowExA 関数
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindowexa

SendMessageは、他のウインドウへお手紙を送信します。

Windowsはマウスを転がしても、かな漢字変換をしても、メッセージで処理しています。起動中の他のウインドウへお手紙を出すのが、Sendmessageです。

メモ帳のタイトルバーに書き込むのが、
SendMessage(Hwnd_p, WM_SETTEXT, 0, LPARAM(PChar(Edit1.Text)));
Hwnd_pの中身は、メモ帳のウインドウハンドルです。

メモ帳の中身、編集領域に書き込むのが、
SendMessage(Hwnd_c, WM_SETTEXT, 0, LPARAM(PChar(memo1.Text)));
Hwnd_cの中身は、メモ帳の子ウインドウの編集領域担当のコントロール'EDIT'です。

パラメータ 意味 SendMessageでWM_SETTEXTを送信のとき
1 hWnd 編集コントロールのウインドウハンドル
2 Msg システムに定義されているメッセージ。WM_SETTEXTを指定
3 wParam WM_SETTEXTでは使用しません
4 lParam 書込文字列。ゼロで終わる文字列。LPARAM( )で囲っているのは、NativeIntという「プラットフォームに依存する符号付き整数を定義したもの」です。Windowsには、32ビット環境と64ビット環境がありますから、ね。

※参考 SendMessage 関数
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-sendmessage

※参考 WM_SETTEXT メッセージ
https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-settext

※参考 NativeInt 
https://docwiki.embarcadero.com/Libraries/Athens/ja/System.NativeInt
delphiが、ネーティブコードを生成するコンパイラ言語なので、こんな機能があるんだと思いますけど、難しいね。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?