[FMX]ユーザー定義のWindowsメッセージを受信するには?


K  2016-04-07 20:49:53  No: 48149

お世話になっています。

今、行いたい事は FMXアプリケーションで、WM_USER+n ユーザーメッセージ番号を定義して
自フォームからPostMessageを行い、自フォームで受信して、それに応じた処理を行いないたいのですが、
VCL(Windows)とは勝手が違う様で、以下のコードでは受信できません。

[コード]
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit,
  FMX.Controls.Presentation, FMX.StdCtrls,
  FMX.Platform.Win,
  Winapi.Windows, Winapi.Messages;

const
  WM_HOGEHOGE = WM_USER + 100;

type
  TForm1 = class(TForm)
    Button1 : TButton;
    Edit1   : TEdit;
    procedure Button1Click( Sender : TObject );
    procedure Message_WM_HOGEHOGE( var Msg : TMessage ); Message WM_HOGEHOGE;
  private
    { private 宣言 }
  public
    { public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click( Sender : TObject );

var
  WindowHandle : TWinWindowHandle;

begin
  WindowHandle := WindowHandleToPlatform( Form1.Handle );
  Winapi.Windows.PostMessage( WindowHandle.Wnd, WM_HOGEHOGE, WPARAM( 0 ), LPARAM( 0 ) );
end;

procedure TForm1.Message_WM_HOGEHOGE( var Msg : TMessage );

begin
  Form1.Edit1.Text := 'HOGEHOGE受信';
end;
end.

ウインドウハンドルを取得する WindowHandleToPlatform処理 で WindowHandle を取得し、
WindowHandle.Wnd には正しいウインドウハンドルが入っている事を確認しました。
しかし、エディットのTextプロパティに 'HOGEHOGE受信' を格納する所に
ブレークポイントを張ってもブレークしてくれません。
メッセージをトラップするやり方が間違っているのか、
そもそもこの様なやり方が、FireMonkeyとして間違っているのかもわかりません。

FMXの本も少なく、Googleでも散々検索してみましたが良くわからず、
質問させて頂きました。


K  2016-04-07 20:52:53  No: 48150

環境を書くのを忘れていました。

CPU:i5プロセッサ
メモリ:4GB
OS:Windows7 Professional(32Bit)
Delphi:DelphiXE8 Professional(General Update1適用済み)

どうぞよろしくお願いします。


take  2016-04-07 23:38:44  No: 48151

> VCL(Windows)とは勝手が違う様で、以下のコードでは受信できません。
VCLでは動いているコードという解釈で良いですかね?

試しに独自ウインドウハンドルを介して
メッセージをやりとりした場合はどうですかね?

// 宣言部
  private
    { Private 宣言 }
    FHandle: HWND;                           // ウインドウハンドル
    procedure WndProc(var Msg: TMessage);

implementation

constructor TForm1.Create();
begin
  FHandle := Classes.AllocateHWnd(WndProc);        // 独自ウインドウハンドルを生成
end;

destructor TForm1.Destroy;
begin
  Classes.DeallocateHWND(FHandle);               // 独自ウインドウハンドルを破棄
end;

procedure TForm1.WndProc(var Msg: TMessage);
begin
  if Msg.Msg = WM_HOGEHOGE then begin              // 自作ウインドウメッセージ通知の場合
    exit;
  end;
  if Msg.Msg <> WM_HOGEHOGE then begin             //  自作ウインドウメッセージ通知では無い場合は処理を返す
    Msg.Result:=DefWindowProc(FHandle,Msg.Msg,
                              Msg.wParam,Msg.lParam);
    exit;
  end;
end;


通りすがり  2016-04-08 00:13:05  No: 48152

本当にWindowsのメッセージメカニズムをFMX上で使用したいのですか?そうでなければこの話が参考になるかもしれません。

TMessageManagerってこんなの。 - 全力わはー
http://d.hatena.ne.jp/tales/20130622/1371894728


K  2016-04-08 18:20:28  No: 48153

take様、返信有難う御座います。

>> VCL(Windows)とは勝手が違う様で、以下のコードでは受信できません。
> VCLでは動いているコードという解釈で良いですかね?
はい、その通りです。
次のVCLコードは正常に受信できています。

[VCLコード]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  WM_HOGEHOGE = WM_USER + 100;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click( Sender : TObject );

begin
  PostMessage( Form1.Handle, WM_HOGEHOGE, WPARAM( 0 ), LPARAM( 0 ) );
end;

procedure TForm1.Message_WM_HOGEHOGE( var Msg : TMessage );

begin
  Form1.Edit1.Text := 'HOGEHOGE受信';
end;

end.

VCLコード異なる点は、フォームハンドルの取得方法だけです。
FMXでは、Form1.Handle が Wnd から TWindowHandleに変更されている為、
WindowHandleToPlatform処理で取得しています。

take様のコードをFMXに組み込んでみましたが、WndProc関数に飛んで来ていないのです(申し訳ないです;;)
もしかして、受信側ではなくメッセージを投げる方に問題が!?と思い始めて来ました。

[FMXコード]
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit,
  FMX.Controls.Presentation, FMX.StdCtrls,
  FMX.Platform.Win,
  Winapi.Windows, Winapi.Messages;

const
  WM_HOGEHOGE = WM_USER + 100;

type
  TForm1 = class( TForm )

    Button1 : TButton;
    Edit1   : TEdit;
    procedure Button1Click( Sender : TObject );
  private
    { private 宣言 }
    FHandle: HWND;                               // ウインドウハンドル
    procedure WndProc( var Msg : TMessage );
  public
    { public 宣言 }
    constructor Create;
    destructor  Destroy;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

constructor TForm1.Create;

begin
  FHandle := AllocateHWnd( WndProc );            // 独自ウインドウハンドルを生成
end;

destructor TForm1.Destroy;

begin
  DeallocateHWND( FHandle );                     // 独自ウインドウハンドルを破棄
end;

procedure TForm1.Button1Click( Sender : TObject );

var
  WindowHandle : TWinWindowHandle;

begin
  WindowHandle := WindowHandleToPlatform( Form1.Handle );
  Winapi.Windows.PostMessage( WindowHandle.Wnd, WM_HOGEHOGE, WPARAM( 0 ), LPARAM( 0 ) );
end;

procedure TForm1.WndProc( var Msg : TMessage );

begin
  if Msg.Msg = WM_HOGEHOGE then                  // 自作ウインドウメッセージ通知の場合
  begin
    Form1.Edit1.Text := 'HOGEHOGE受信';
    Exit;
  end;
  if Msg.Msg <> WM_HOGEHOGE then                 //  自作ウインドウメッセージ通知では無い場合は処理を返す
  begin
    Msg.Result := DefWindowProc( FHandle,Msg.Msg,
                                 Msg.wParam, Msg.lParam );
    Exit;
  end;
end;

end.

/////

通りすがり様、返信有難う御座います。

FMX内のメッセージング機構というのがあったんですね。
理解を進める為にじっくり読んでみます。

新しい Delphi は、複数のOS上での動作をサポートしていますが、
今の所、私のプログラムは Windows上での動作を前提に置いています。
Windowsメッセージに拘っているのは、他のアプリケーション(過去のVCLプログラム)との連携が今後必要であるかも知れないからです。
とりあえず簡単なメッセージ処理をするプログラムを組んでみようとしていた所、動作できなかったので質問に至った次第です。

何か判明した点があればまた書き込みをさせて頂きます。


take  2016-04-08 22:04:48  No: 48154

気になったのですが

> const
>   WM_HOGEHOGE = WM_USER + 100;

これ

WM_HOGEHOGE = WM_USER+0x0100

こうじゃないですかね?

0x0100以上を使わないと駄目なはずですよ


tor  2016-04-08 22:56:14  No: 48155

そんなこと気にするくらいならサクッとラペチミミ使っちゃおうぜ!
それはさておき、ラミが結び付いているのは自分のフォームじゃなくてダミーで作ったウィンドウなので、メッセージの送り先もそっちにしないといけないんじゃないですか?
×ヲサミヘィヲサラネョラ
○ヲサミヘィヲサニネ
スススススススススススススススススススススススススススススススススススススススス
ニコ ヒ
トコ イーアカッーエッークィ金ゥ アエコイカコエオ  書込者ノト:ロ 「・ヲ」。 ン

様、様、失礼しました。

様の仰られた通りに、アカ進数の、アーーに変更しました。

ヲサヲサラペネマヌナネマヌナヲサスヲサラペユモナメヲサォヲサ、ーアーーサ

様の仰られた通りに、対象のハンドルが間違っていたのを修正しました。
あの間違えてたコードでは、独自ハンドルを生成した意味がありませんでした。

ヲサヲサラョラョモヘィヲサニネャヲサラペネマヌナネマヌナャヲサラミチメチヘィヲサーヲサゥャヲサフミチメチヘィヲサーヲサゥサ

しかしながら、現状でも受信ない状態は変わらずでした。
もう少し調べてみます。有難う御座います。
スススススススススススススススススススススススススススススススススススススススス
ニコ 通りすがり
トコ イーアカッーエッーケィ土ゥ アキコエカコエイ  書込者ノト:ロ ァ。。 ン

山本さんのこちらの記事をどうぞ。

ニヘアプリケーションでユーザー定義のラメッセージを受信するには?ヲサヲサ」クイアアサヲサ山本隆の開発日誌
コッッョョッッソスキウカキ
スススススススススススススススススススススススススススススススススススススススス
ニコ ヒ
トコ イーアカッーエッアアィ月ゥ ーケコオオコイー  書込者ノト:ロ 「・ヲ」。 ン
モコ 

通りすがり様、情報有難う御座います。

あれから、メラヘ関数による方法はどうか?とか
ヤヘ&トヘ関数による方法はどうか?等、かなり迷走していました(汗

山本隆様のサイトを参考に組み込んでみた所、
自アプリ送信&自アプリ受信を行う事が出来る様になりました。感謝!
他のアプリに対しての確認はまた機会のある時に行ってみます。

まだ提示して頂いたコードを理解していないのですが、これで解決とさせて頂きます。
有難う御座いました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加