喫茶XRAYトップページ


[478] PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/29 (土) 22:10:15 OK牧場
パスワードつきアプリケーション(Form1)をつくります。
Edit1、Button1を貼り付けEdit1に数字を入力してButton1を押す。
正解するとアプリケーションが先に進む。

Form2のアプリから
PostMessageでEdit1に数字を送る、
Sleepでちょっと間をおいて
SendMessageでButton1をクリックしたようにする。
違う場合はPostする数字を1づつたしていく。

こうやって数字を増やされてくといつかあたりそうなんで防ぐ方法を
考えてみたんですけど思い浮かびませんでした。
実際は正解の数字を20桁ぐらいにしてしまえば問題ないと思うんですが
手で打った文字とPostされた文字の違いを見分ける方法があるのか
興味をもったので書かせていただきました。
引き続き自分でも考えてみようと思うので、よろしくお願いします。

[479] Re:PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/30 (日) 00:28:37 Mr.XRAY
▼ OK牧場さん

> こうやって数字を増やされてくといつかあたりそうなんで防ぐ方法を
> 考えてみたんですけど思い浮かびませんでした。


これはパス.ゴメン!!

> 手で打った文字とPostされた文字の違いを見分ける方法があるのか

具体的なコードは今すぐというわけにはいきませんが,
Messaggeを送る時に,ユーザ定義のメッセージにして,受取る側は,その
メッセージの時に処理すれば可能かも知れません.
WM_USER+100とか...


[480] Re2:PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/30 (日) 12:26:19 Mr.XRAY
 ▼ OK牧場さん

失礼しました.

>Form2のアプリから

別のアプリなんですね.WM_USER+は使用できませんね.

考えてみれば,文字列のメッセージを受取ったという場合でも,フラグか
何かで判断する必要があるので,逆に,Form1のキーイベント(OnKeyPress等)
内でフラグを立てて,例えばこのフラグがTrueならキー入力と判断する方法は
使えませんか.


[481] Re3:PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/30 (日) 20:59:36 OK牧場
▼ Mr.XRAYさん
>  ▼ OK牧場さん
>
> 失礼しました.
>
> >Form2のアプリから
>
> 別のアプリなんですね.WM_USER+は使用できませんね.
>
> 考えてみれば,文字列のメッセージを受取ったという場合でも,フラグか
> 何かで判断する必要があるので,逆に,Form1のキーイベント(OnKeyPress等)
> 内でフラグを立てて,例えばこのフラグがTrueならキー入力と判断する方法は
> 使えませんか.


フラグで判断とはどんな感じなんでしょうか。
keypressの使い方がまだわかりませんが試してみました。

何か手で打つとshowmessageで一文字ごと知らせる。
2文字打つと2回showmessageがでます。

postmessageで2回(2文字)送信すると2回showmessageがでたので
自分の考えてる判別方法だとうまくいきませんでした。


[482] Re4:PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/31 (月) 00:22:55 Mr.XRAY
▼ OK牧場さん

> postmessageで2回(2文字)送信すると2回showmessageがでたので
> 自分の考えてる判別方法だとうまくいきませんでした。


う〜む,そうですか.
目的の動作を実現する方法は,いつくか考えられますが.これはやはりEdit1
のサプクラス化が早いかも知れません.

(1)送る側のアプリ
   TForm2でTButtonが一つ(Button1)

//====================================================================
//  文字列を送る側のButton1のクリックイベント
//  受取る側のEdit1は判断しやすいようにID値を1000にしてある
//====================================================================
procedure TForm2.Button1Click(Sender: TObject);
var
     hWindow    : HWND;
     EditHandle : HWND;
     GetText    : PChar;
     SendText   : String;
begin
     //まず目的のEdit1があるTForm1のウィンドウハンドルを取得
     //次にそのウィンドウ内のIDが1000のコントロールのハンドルを取得
     //そこにWM_SETTEXTで文字列を送る
     //ここでは既に入力済みの文字列を取得しているが
     //受取った側で処理する方法も考えられる
     hWindow:=FindWindow('TForm1',nil);
     if hWindow<>0 then begin
       EditHandle:=GetDlgItem(hWindow,1000);
       SendMessage(EditHandle,WM_GETTEXT,256,LPARAM(GetText));
       SendText:=GetText+'567';
       SendMessage(EditHandle,WM_SETTEXT,0,LPARAM(PChar(SendText)));
     end;
end;


(2)受取る側のアプリ
   TForm1でTEditを一つ配置(Edit1)

var
   EditFlag: Boolean;
   OriginalProc: Pointer;

//====================================================================
//   Edit1のサブクラス化関数
//====================================================================
function Edit1Proc(AWnd: HWND; uMsg: UINT; wParam:WPARAM;
  lParam: LPARAM):LRESULT; stdcall;
begin
     case uMsg of
     WM_SETTEXT:
       begin
         EditFlag:=False;
         //他からEditに文字列が入力された時の処理
       end;
     WM_KEYDOWN:
       begin
         EditFlag:=True;
         //Edit1にキーボードからタイプした時の処理
         //もちろんOnKeyPress,OnKeyDownに書いてもよい
       end;
     end;

     //通常の処理を継続
     Result:=CallWindowProc(OriginalProc,AWnd,uMsg,wParam,lParam);
end;
//====================================================================
//   送る側でEdit1を判定しやすい様にID=1000とする
//====================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
     SetWindowLong(Edit1.Handle,GWL_ID,1000);
     //Edit1のサブクラス化
     OriginalProc:=Pointer(SetWindowLong(Edit1.Handle,GWL_WNDPROC,
                           LongInt(Addr(Edit1Proc))));
end;

end.

サブクラス化というのは,ここではEdit1に対してですが.
TEditのヘルプを見て下さい.このプロパティにWindowProcというのがあります.
これで,TEditがメッセージを処理する関数を指定しています.この関数の処理
内容を変更する,つまり関数のサブ関数という意味で「サブクラス」といっています.
(または元のEdit1の(とは違う)サブクラスの動作仕様という意味)
(これはコールバック(呼び戻し)関数と言われるものの仲間でもあります)

このサプクラス関数の名前は任意ですが,引数の型と順序は指定されています.
このサブクラス関数の中で,Edit1のメッセージを処理しようというわけです.
詳しい説明は,Halbow資料館などにもありますで,後で調べて下さい.

取敢えず,上記のコードの動作が目的の動作を実現するために利用可能だけを
確認して下さい.

もしかしたら,未知の世界のコードや命令があると思いますが,いつかは
通らなければならない道です.頑張って下さい.


[483] Re5:PostMessageと手打ち(タイピング)の見分け方返信 削除
2005/10/31 (月) 19:35:40 Mr.XRAY
▼ OK牧場さん

> TEditのヘルプを見て下さい.このプロパティにWindowProcというのがあります.
> これで,TEditがメッセージを処理する関数を指定しています.この関数の処理


ということなので,以下のコードの方がわかりやすいかも知れません.
これなら,Edit1SubClassProcはクラスメソッドとなりますので,
EditFlag,OriginalProcをクラス変数(Private等の)にできます.
EditFlagは,必要な処理をこのメソッド内で行えば不要でしょう.

var
   EditFlag: Boolean;
   OriginalProc: TWndMethod;

//====================================================================
//   Edit1のサブクラス化関数
//====================================================================
procedure TForm1.Edit1SubClassProc(var Message: TMessage);
begin
     OriginalProc(Message);
     case Message.Msg of
     WM_SETTEXT:
       begin
         EditFlag:=False;
         Panel1.Caption:='WM_SETTEXT';
         //他からEditに文字列が入力された時の処理
       end;
     WM_KEYDOWN:
       begin
         EditFlag:=True;
         Panel1.Caption:='KeyDown';
         //Edit1にキーボードからタイプした時の処理
       end;
     end;
end;
//====================================================================
//   送る側でEdit1を判定しやすい様にID=1000とする
//====================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
     SetWindowLong(Edit1.Handle,GWL_ID,1000);
     //Edit1のサブクラス化
     OriginalProc:=Edit1.WindowProc;
     Edit1.WindowProc:=Edit1SubClassProc;
end;

end.

[484] Re6:PostMessageと手打ち(タイピング)の見分け方 (解決)返信 削除
2005/10/31 (月) 22:22:52 OK牧場
わざわざ2種類ものソースありがとうございます。
こちらのサンプル集でサブクラス化を勉強させていただいてたのに
知識としてあっても使うときに出てこなかった・・。
ウィンドウメッセージとあわせて使うのうまいです。
あらためてソースをみると、なるほど納得です。
単語を知ってても話ができない英語みたい・・。
ソースを読むだけじゃなくて書く機会をふやさねば。
今回はありがとございました。


INCM/CMT
Cyclamen v3.82