リアルタイム系EAでLabel Object をクリックしたら、数字を変える。

今日は、「Label Object をクリックしたら、数字を変える」の最終回です。
昨日に引き続き、一般向けの便利ツール公開はありませんので、この種のプログラムに興味のない人は読み飛ばし推奨です..。今日も、WindowsAPI を使って何か作りたい初心者な人向けの解説だけです...。


昨日作成した、RTMouse_EA.mq4 を複数のチャートに貼り付けて、チャートを重ね合わせて動かすと、非アクティブなチャートでもマウスに反応しています。これでは、背後に隠れたチャートでも気づかないうちにクリックしてしまう...という悲惨な事態を招きかねません。


…という訳で、EAの動作しているチャートがアクティブになっているかどうかの判定を加えます。
アクティブ判定の方法はいくつか考えられますが、簡単なところで以下のAPIを使用します。

#import "user32.dll"
int GetForegroundWindow();
int GetParent(int HWND);
int GetTopWindow(int HWND);
int GetAncestor(int HWND,int flag);
#import

これらのAPIについては、以下に資料があります。
GetForegroundWindow
http://msdn.microsoft.com/ja-jp/library/cc364732.aspx
GetParent
http://msdn.microsoft.com/ja-jp/library/cc364718.aspx
GetTopWindow
http://msdn.microsoft.com/ja-jp/library/cc364754.aspx
GetAncestor
http://msdn.microsoft.com/ja-jp/library/cc364581.aspx


まず、EAの動いているMetaTrader 自身が最前面にあるかどうか判定します。

int hwnd = WindowHandle( Symbol(),0 );
int AppTop = GetAncestor( hwnd, 2 );
int WinTop = GetForegroundWindow();
if( AppTop != WinTop ) { 最前面デハナイ }

AppTop は、MT4 本体のウィンドウハンドルで、WinTop は、デスクトップ上の最前面のウィンドウハンドルなので、両者が一致しなければ、MT4 が最前面ではない..と分かります。


次に、1つのMT4 のウィンドウの中にある複数のチャートの中で最前面(アクティブ)になっているかどうかを判定します。

int hwnd = WindowHandle( Symbol(),0 );
int MDITop = GetTopWindow( GetParent(GetParent(hwnd)) );
int MyMDI = GetParent( hwnd );
if( MDITop != MyMDI ) { 最前面デハナイ }

これはWindowの階層構造とMDIについて知らないと説明が難しいのですが、複数のチャート(=MDI子ウィンドウ)の中で最前面になっているウィンドウのハンドル MDITop を求め、それがEAの動いているチャートのウィンドウハンドル MyMDI と比較することで判定しています。


これで、必要なAPIの知識は揃いましたので、ぐちゃっっとまとめてEA化したのが、RTMouse5_EA.mq4 です。
時計と数字をクリックすると、数字が増減してゆきます。


マウスクリックの判定部分は、

int status = CheckMouse("MEC",Corner,125,30,prev_click_MEC);
if( status == 1 ) ObjectSet("MEC" ,OBJPROP_COLOR, Yellow);
if( status >= 2 ) ObjectSet("MEC" ,OBJPROP_COLOR, Red);
if( status == 3 ) count++;

で、

int prev_click_MEC = 0;//static or grobal

という状態保存用の変数をループ外にラベルオブジェクトごとに個別に宣言してから、

CheckMouse( オブジェクト名 , コーナー(0or1) , 横幅 , 高さ , 状態保存変数 );

を呼び出しています。返り値は0〜3でマウスの位置関係と状態が分かります。
状態保存変数は、初回のマウス押下げと、継続的な押下げを区別する為に使用しています。
ラベルオブジェクトの横幅と高さを手作業で測定して指定する必要があるのが不便ですが、大きさを知る手段が無いのでどうしようもないです。



とりあえず、これで目的は達成できるかしらん・・・^^;