喫茶XRAYトップページ

[スレッド全体
]

[6382] Re4:Mouseメッセージの捕獲返信 削除
2012/9/19 (水) 18:12:06 おかぽん
▼ snail3さん
> マウスイベントですが、コンポーネント本体でクリックした時は
> 反応しますが、このコンポーネントに載せた子コンポーネントで
> クリックすると補足することができませんでした。子供でクリック
> した場合も横取りする方法はないでしょうか。


WM_PARENTNOTIFYをとっつかまえると、子コントロールのマウスダウンだけなら
補足できるようです。

手抜きかつDelphi5での記述ですが・・・
とりあえずTScrollBoxと位置を表示するためのTLabelを1個を配置。
それ以外は、TPanelとかTEdit,TConboBox,TListBox等を、TScrollBox上に適当に配置。

type
  TScrollBox=class(Forms.TScrollBox)
  private
    procedure WMParentNotify(var Message: TWMParentNotify); message WM_PARENTNOTIFY;
  public
    HintLabel        :TLabel;
  end;

  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    Label1: TLabel;
    //コンポーネントいろいろ
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

procedure TScrollBox.WMParentNotify(var Message: TWMParentNotify);
begin
  if HintLabel <> nil then begin
    case Message.Event of
      WM_LBUTTONDOWN: HintLabel.Caption := 'L: X=' + IntToStr(Message.XPos) + ' Y=' + IntToStr(Message.YPos);
      WM_MBUTTONDOWN: HintLabel.Caption := 'M: X=' + IntToStr(Message.XPos) + ' Y=' + IntToStr(Message.YPos);
      WM_RBUTTONDOWN: HintLabel.Caption := 'R: X=' + IntToStr(Message.XPos) + ' Y=' + IntToStr(Message.YPos);
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ScrollBox1.HintLabel := Label1;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ScrollBox1.HintLabel := nil;
end;

[6383] Re5:Mouseメッセージの捕獲返信 削除
2012/9/19 (水) 20:17:44 snail3
▼ おかぽんさん

ありがとうございました。色々とためになります。

これから試してみます。



[6384] Re5:Mouseメッセージの捕獲返信 削除
2012/9/19 (水) 20:33:14 Mr.XRAY
▼ おかぽんさん

すげぇ !! (みち子さんに『はしたなない』と言われてしまいそう)

WM_PARENTNOTIFY メッセージですか,
早速ググッてみました.なるほどです.
XPos と YPos から TWinControl はコントロールを判定できまからね.
これは使えますね.ありがとうごさいます.

>Delphi5での記述ですが・・・

でも基本は同じですからね.(^^;

[6385] Re6:Mouseメッセージの捕獲返信 削除
2012/9/19 (水) 20:53:36 Mr.XRAY
> WM_PARENTNOTIFY メッセージですか,

考えてみたら,サンプルプログラム集の中で,サブクラス化でやっている
ものの,いくつかは,このメッセージで済みますね.

サブクラスのサンプルだと思えばいいか... ?

[6386] Re6:Mouseメッセージの捕獲返信 削除
2012/9/19 (水) 23:42:26 snail3
▼ Mr.XRAYさん

> XPos と YPos から TWinControl はコントロールを判定できまからね.


これって簡単に取り出す関数無いですよね。
知っていたら教えて下さい。



[6387] Re7:Mouseメッセージの捕獲返信 削除
2012/9/20 (木) 09:56:56 Mr.XRAY
> > XPos と YPos から TWinControl はコントロールを判定できまからね.

ウィンドウハンドルを持つコントロール(TWinControl)だけですと,
こんな関数でしょうか.

 FindVCLWindow
http://docwiki.embarcadero.com/Libraries/ja/Vcl.Controls.FindVCLWindow

WindowFromPoin と FindControl の組み合わせ
http://msdn.microsoft.com/ja-jp/library/cc364874.aspx
http://docwiki.embarcadero.com/Libraries/ja/Vcl.Controls.FindControl

TGraphicControl だと,
フォーム(Self)に直接乗っているTControlの場合

  GetCursorPos(CurPos);
  Windows.ScreenToClient(Handle, CurPos);

  for i := 0 to Self.ControlCount - 1 do begin
    AControl := Controls[i];
    ARect    := AControl.BoundsRect;
    if PtInRect(ARect, CurPos) then begin
      //
      break;
    end;
  end;

な感じで検索するしかないような気がします.
更に高級な技 (^^;
[06_マウスカーソル下のオブジェクトの情報]
http://mrxray.on.coocan.jp/Delphi/plSamples/678_IAccessibleInterface.htm#06



[6388] Re7:Mouseメッセージの捕獲返信 削除
2012/9/20 (木) 11:47:48 おかぽん
▼ snail3さん
> これって簡単に取り出す関数無いですよね。
> 知っていたら教えて下さい。

すでにマスターからレスがありますが、FindVCLWindowは、ウインドウハンドルを
持っているコンポーネントしか拾うことができないようなので、
直接の子コントロールしか返してくれないけど、ウインドウハンドルなしでもOKな
ControlAtPosを使ってみると、こんな感じですかね。

上記のWMParentNotify内で行うなら
var
  ctrlPos: TPoint;
  control1, control2: TControl;

    ctrlPos := Point(Message.XPos, Message.YPos);
    control1 := ControlAtPos(ctrlPos, True, True);
    while control1 <> nil do begin
      control2 := control1;
      if control2 is TwinControl then begin
        //子コントロールの座標に変更
        ctrlPos := Point(ctrlPos.X - TwinControl(control2).Left,
                         ctrlPos.Y - TwinControl(control2).Top);
        //子コントロール内のコントロールを検索
        control1 := TwinControl(control2).ControlAtPos(ctrlPos, True, True);
      end
      else begin
        control1 := nil;
      end;
    end;
  {ここで control2 がマウス下のコンポーネント
  今更ながら、WMParentNotifyは ウィンドウハンドルのないコントロールからは
  届かないので、TScrollBoxに直接貼ったTLabelとかだと、ここではつかまえることが
  できないですね。}

[6389] Re8:Mouseメッセージの捕獲返信 削除
2012/9/20 (木) 13:10:52 Mr.XRAY
▼ おかぽんさん

これで出揃った感じですね.
ControlAtPos がありました.
これ便利ですよね.無効化したのも,子コントロールも検出しますから.

[6390] Re8:Mouseメッセージの捕獲返信 削除
2012/9/20 (木) 20:22:35 snail3
▼ おかぽんさん

最初 GetCursorPos 使ったいたんですが、キャレットが残ってしまって
うまくいきませんでした。

  control1 := ControlAtPos(ctrlPos, True, True);

今試していますが ControlAtPos を使うと、再度

WM_LBUTTONDOWN イベントが発生してしまいます。


>   今更ながら、WMParentNotifyは ウィンドウハンドルのないコントロールからは
>   届かないので、TScrollBoxに直接貼ったTLabelとかだと、ここではつかまえることが
>   できないですね。}


ユーザーは普通 Tedit なんかをクリックするので
これはあまり問題にならないと思います。


[6401] Re9:Mouseメッセージの捕獲返信 削除
2012/9/22 (土) 22:50:09 おかぽん
▼ snail3さん
> 今試していますが ControlAtPos を使うと、再度
>
> WM_LBUTTONDOWN イベントが発生してしまいます。


残念ながら、うちのDelphi5では発生しないです。
先に示したサンプル内の話ですけど。

使いどころによっては発生するんですかね?


[6402] Re10:Mouseメッセージの捕獲返信 削除
2012/9/23 (日) 12:50:26 snail3
▼ おかぽんさん
> ▼ snail3さん
> > 今試していますが ControlAtPos を使うと、再度
> >
> > WM_LBUTTONDOWN イベントが発生してしまいます。
>
> 残念ながら、うちのDelphi5では発生しないです。
> 先に示したサンプル内の話ですけど。
>
> 使いどころによっては発生するんですかね?


試しに おかぽんさん 提供のソースでそのまま実行したところ
確かに発生しませんね。

もう少し調べてみます。

[6403] Re11:Mouseメッセージの捕獲返信 削除
2012/9/23 (日) 13:49:34 snail3
▼ snail3さん

原因がわかりました。
色々と触っているときに

Application.ProcessMessages;

これを入れちゃていました。

余計なお手間をおかけしてすみませんでした。


[6404] Re12:Mouseメッセージの捕獲返信 削除
2012/9/23 (日) 14:19:10 Mr.XRAY
▼ snail3さん

> Application.ProcessMessages;
>
> これを入れちゃていました。


Application.ProcessMessages の使い方って,結構難しいですよね.
これを入れないと,処理が飛ぶこともありますが.
一方で,挙動がおかしくなることがあります.
具体的な処理の内容によりますね.

今回の場合は,キューにたまっているのを処理してくれた,
ということでしょう.Windows さんがまじめにやった,というこで...
お許しください.

[6407] Re13:Mouseメッセージの捕獲返信 削除
2012/9/24 (月) 00:27:20 snail3
▼ Mr.XRAYさん
 
> Application.ProcessMessages の使い方って,結構難しいですよね.
> これを入れないと,処理が飛ぶこともありますが.
> 一方で,挙動がおかしくなることがあります.
> 具体的な処理の内容によりますね.
>
> 今回の場合は,キューにたまっているのを処理してくれた,
> ということでしょう.Windows さんがまじめにやった,というこで...
> お許しください.


一件落着と思ったら、複雑怪奇。ゾンビのごとく復活してきます。
メインルーチンの ProcessMessages で WMParentNotify
が呼び出されてしまいます。(;_;)

[6408] Re14:Mouseメッセージの捕獲返信 削除
2012/9/24 (月) 01:06:03 snail3
▼ snail3さん

BlockInput 関数で囲んだらいい感じ。


http://mrxray.on.coocan.jp/Delphi/plSamples/840_CancellLockDisable.htm

ためになります。


[6410] Re15:Mouseメッセージの捕獲返信 削除
2012/9/24 (月) 07:41:00 Mr.XRAY
▼ snail3さん

「勝てば官軍,動けば正義」ということにしますか.

TApplication.ProcessMessages は,例えば,キーやフックで,処理コード
内でループしで処理すると,おかしな動作をしてしまうことがあります.
また,ファイルの一覧を取得する時に使用する,findfirst, findNext
のループで使用しても同様に,シェルの項目識別子を使用したファイル
情報取得のループ内でも同じですね.

TApplication.ProcessMessages はあくまでも,I/O 処理待ち用です.
Sleep(1) とか Sleep(10) なんてのもよく使用しますが,

あっ,思い出した.Sleep で,TApplication.ProcessMessagesとは違いますが
最近こんのながありました.
これは,Label の文字描画が終了しない内に,Sleep の処理に入って
しまうために,文字が描画更新されない,というものです.

http://www.freeml.com/delphi-users/2732/latest




[6438] Re16:Mouseメッセージの捕獲返信 削除
2012/10/4 (木) 20:03:22 snail3
▼ Mr.XRAYさん
▼ おかぽんさん

あれからもメインルーチンにある

 Application.ProcessMessages

で時々ゾンビが発生していまして、困っていました。

意味は全然わかっていないのですが

    Message.Value :=  0;  // ←これでイベントのループが消える?

を入れることで解決したようです。


[6439] Re17:Mouseメッセージの捕獲返信 削除
2012/10/5 (金) 10:23:52 Mr.XRAY
▼ snail3さん

苦労していますね.お疲れ様です.

>    Message.Value :=  0;  // ←これでイベントのループが消える?

これはメッセージなしにすることですね.なるほど,その手がありましたか.
これで何とか落ち着くといいですね.
無事を祈っています (^^;


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82