最初に計画しておきたいこと
前回の記事の続きになります。
今回は機能からGUIが生えてきました。
最初はGUIなんて作る予定もなく思い付きで作り始めたため、何をどこまで作り込むか全然計画を立てていなかったためとても苦労しました。
もしこの記事を見た後に作成する方は最初にざっくりでいいので「必要な機能の洗い出し」と「GUIの設計」をすることをお勧めします。
必要な機能の洗い出し
1度情報をするべくざっくり大枠でほしいと思った機能が以下の通り
- 通常注文機能
- 特殊注文機能(主にこれを作りたかった)
- ポジション管理機能
- ロット・リスク管理
機能の詳細はまた別記事で解説します。
GUIの設計・作成
Excelで設計図を作成
今回やらかした大きなことは作りながら考える、考えながら作る、あれもこれも作りたい・・・。
最初に形を考えずに欲しい機能欲しい機能と付けていったらあとから配置を変えるのが一苦労でした。
そのため一度スタートに戻って形から決めていきます。
いろんな描画ソフトで使いやすいものを試そうと思いましたが、調べたり覚えたり書いたりテストしたり全部自分でやっているためなかなか面倒です。
この時点で思った以上に大規模なプロジェクトになってまいりました。
そのため一番手軽に利用できそうなExcelをチョイス。
図形をセルに張り付く設定にして、ボタン類の配置を考えていきます。
またどのボタンがどのような挙動をするのかという洗い出しが必要になります。
オンオフトグルで切り替わるのか、押すと何かが変わるのか等・・・
理想でいうのならば「オブジェクトの種類」「変数名」「オブジェクトの挙動」「オブジェクトに与えられる機能」あたりも洗い出しておくと後々管理が楽でしょう。
実装してテストをしていくうちに使いやすい形が出てくると思うので最初はざっくり決めました。
GUIの作り方
大きく分けて通常のオブジェクトと標準ライブラリのDialogというものがあるようです。
もともと通常のオブジェクトとして作っていましたが、作り直しを考えている段階で標準機能としてGUIを作る事ができることに気づく。
試しに作ってみるが、慣れていないことと利用方法がイマイチ理解できず。
通常オブジェクトの場合は関数化して必要な値を与えることでボタン等が作成できるために工数が違いすぎる。
関数化できそうな事に気づくも構造体変数structの受け渡しが上手くできずに頓挫。
ネット上にもMT4でGUIを作るような資料は少なかったため後回しへ。
まだ全然理解できていませんがこのような感じで記述する必要がありそうです。
Create_LabelSymbolのほうが一般的にネット上で公開されている書式、Create_BtnTrapRepeatのほうが簡略化するために試行錯誤をしている形。
class CPanelDialog : public CAppDialog
{
private:
CLabel m_LabelSymbol;
CButton m_BtnTrapRepeat;
public:
CPanelDialog(void);
~CPanelDialog(void);
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
protected:
bool Create_LabelSymbol(void);
bool Create_BtnTrapRepeat(string name1, string name2, string text, double x1, double y1, double x2,double y2);
};
bool CPanelDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
{
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2)) return(false);
if( !Create_LabelSymbol())return (false);
if(!Create_BtnTrapRepeat(
"m_BtnTrapRepeat", "__BtnTrapRepeat", "Trap",
indent_left,
indent_top+full_height+controls_gap_y,
indent_left+full_width,
indent_top+full_height+controls_gap_y+full_height
)) return(false);
return(true);
}
CPanelDialog AppWindow;
bool CPanelDialog::Create_LabelSymbol(void)
{
int x1=indent_left;
int y1=indent_top;
int x2=x1+full_width;
int y2=y1+full_height;
if( !m_LabelSymbol.Create( m_chart_id, m_name + "m_LabelSymbol", m_subwin, x1, y1, x2, y2 ) ) return false;
if( !m_LabelSymbol.Text( StringConcatenate(Symbol()," ",PERIOD_CURRENT)) ) return false;
if( !Add( m_LabelSymbol ) ) return false;
return true;
}
bool CPanelDialog::Create_BtnTrapRepeat(string name1, string name2, string text, double x1, double y1, double x2,double y2)
{
if(!m_BtnTrapRepeat.Create(0,name2,0,x1,y1,x2,y2)) return(false);
if(!m_BtnTrapRepeat.Text(text)) return(false);
if(!Add(m_BtnTrapRepeat)) return(false);
return(true);
}
これについては力技で並べていくか、記述する行数が違いすぎるためもう少し効率的なやり方が必要に思えます。
オブジェクト(ボタンやラベル)の作り方
苦労の末簡単な解決策はすぐに見つからなそうだったので、オブジェクトとして作成していくことに。
もともと途中まではオブジェクトで作成していったためつぎ足す形です。
最終的な配置については利用しながら使いやすさを考えていきます。
こういう感じで関数を作っておくとあとは必要な値を引数として渡すだけで作成ができます。
void CreateButton(string name, string label, int x, int y, int width, int height,
color bgColor = C'236,233,216', color textColor = clrBlack, int anchor = CORNER_RIGHT_UPPER)
{
ObjectCreate(name, OBJ_BUTTON, 0, 0, 0);
ObjectSet(name,OBJPROP_XDISTANCE,x+width);
ObjectSet(name,OBJPROP_YDISTANCE,y);
ObjectSet(name,OBJPROP_WIDTH,x);
ObjectSet(name,OBJPROP_XSIZE,width);
ObjectSet(name,OBJPROP_YSIZE,height);
ObjectSet(name, OBJPROP_CORNER, anchor);
ObjectSet(name, OBJPROP_BGCOLOR, bgColor);
ObjectSet(name, OBJPROP_COLOR, textColor);
ObjectSet(name, OBJPROP_ZORDER, 100);
ObjectSetText(name, label, FontSize);
}
void CreateLabel(string name, string label, int x, int y, int width, int height,
color bgColor = C'236,233,216', color textColor = clrBlack, int anchor = CORNER_RIGHT_UPPER)
{
ObjectCreate(name, OBJ_LABEL, 0, 0, 0);
ObjectSet(name,OBJPROP_XDISTANCE,x+width);
ObjectSet(name,OBJPROP_YDISTANCE,y);
ObjectSet(name,OBJPROP_WIDTH,x);
ObjectSet(name,OBJPROP_XSIZE,width);
ObjectSet(name,OBJPROP_YSIZE,height);
ObjectSet(name, OBJPROP_CORNER, anchor);
ObjectSet(name, OBJPROP_BGCOLOR, bgColor);
ObjectSet(name, OBJPROP_COLOR, textColor);
ObjectSet(name, OBJPROP_ZORDER, 100);
ObjectSetText(name, label, FontSize);
}
今回のまとめ
最初にも書きましたが機能の洗い出しとGUIの設計は必ず最初にやろうです。
後からGUIの配置を変えることは想像を絶するくらいに苦痛です。
また次回に続きます。