DoEasy - コントロール(第30部):ScrollBarコントロールのアニメーション化
内容
概念
前回はScrollBar補助コントロールの開発に着手しました。今回は、マウスによるコントロール要素のインタラクションを実装してみます。WinForms ScrollBarオブジェクトの構成要素は、スクロールボタンとキャプチャ領域です。スクロールボタンについては、補助オブジェクト(矢印ボタン)のクラスを別に用意していますが、キャプチャ領域は単純なボタンの形で作りました。ここでは、キャプチャ領域オブジェクトを作成するために、ボタンオブジェクトをベースにした別のクラスを実装してみることにします。スクロールバースライダーのイベントを正しく処理するために、オブジェクトはそれ自身の型を持つ必要があります。したがって、ボタンオブジェクトから派生し、そのプロパティを継承して、独自の型を持つ独立したオブジェクトとなります。
大部分は、コントロールのサイズ変更とスクロールバーによるマウス操作の処理に関する機能を作成するための準備作業です。マウスの状態とそのイベントのリストを拡張してみましょう。これらにより、以降の記事でルーチンワークに気を取られることなく、コントロールとその機能の開発に取り組むことができます。
ライブラリクラスの改善
\MQL5\Include\DoEasy\Defines.mqhで、ScrollBarオブジェクトの状態に関するデフォルトの色定数を追加しました。
#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR (C'0xF0,0xF0,0xF0') // ScrollBar control background color #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR (C'0xFF,0xFF,0xFF') // ScrollBar control frame color #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR (C'0x60,0x60,0x60') // ScrollBar control text color #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_DOWN (C'0x00,0x00,0x00')// Color of ScrollBar control text when clicking on the control #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control text when hovering the mouse over the control #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR (C'0xCD,0xCD,0xCD') // ScrollBar control capture area color #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR (C'0xCD,0xCD,0xCD') // ScrollBar control capture area frame color #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN (C'0x60,0x60,0x60') // Color of ScrollBar control capture area when clicking on the control #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER (C'0xA6,0xA6,0xA6') // Color of ScrollBar control capture area when hovering over the control #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR (C'0x60,0x60,0x60') // ScrollBar control capture area text color #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN (C'0xFF,0xFF,0xFF')// Color of ScrollBar control capture area text when clicking on the control #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control capture area text when hovering the mouse over the control #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR (C'0xF0,0xF0,0xF0') // ScrollBar control button color #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_BORDER_COLOR (C'0xCD,0xCD,0xCD') // ScrollBar control button frame color #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN (C'0x60,0x60,0x60') // Color of ScrollBar control buttons when clicking on the control #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER (C'0xDA,0xDA,0xDA') // Color of ScrollBar control buttons when hovering the mouse over the control #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR (C'0x60,0x60,0x60') // ScrollBar control button text color #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN (C'0xFF,0xFF,0xFF')// Color of ScrollBar control button text when clicking on the control #define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control button text when hovering the mouse over the control #define DEF_CONTROL_SCROLL_BAR_WIDTH (11) // Default ScrollBar control width #define DEF_CONTROL_CORNER_AREA (4) // Number of pixels defining the corner area to resize #define DEF_CONTROL_LIST_MARGIN_X (1) // Gap between columns in ListBox controls #define DEF_CONTROL_LIST_MARGIN_Y (0) // Gap between rows in ListBox controls
各スクロール領域には幅があります。縦スクロールバーの場合はオブジェクトの幅、横スクロールバーの場合は高さです。このパラメータには、デフォルトの11を設定しましょう。スクロールバーには境界があり、インターフェイスに重ねたときにインターフェイスから分離されるようになっています。幅の値が11ピクセルの場合、スクロールバーのアクティブ領域は9ピクセル(上下左右の境界ごとに1ピクセル)になります。矢印ボタンとスライダーはスクロールバー上に作るので、矢印の三角形が均等に美しく描かれる9ピクセルが十分な奇数です。一般に、中心軸に沿った図形が描かれたオブジェクトのサイズを変更する場合、奇数のピクセル数を使用することで、均一できれいな描画を維持することができるようにする必要があります。角の領域とは、カーソルが角に位置しているとみなされるフォームの部分です。例えば、オブジェクトのサイズを変更する場合、カーソルが四隅のいずれかにあれば、そのサイズの2つのパラメータ(高さと幅)を一度に変更することができます。
形状に関連して可能なマウスの状態のリストに新しい値を追加します。オブジェクトの寸法は8方向にリサイズ可能です。
- カーソルがオブジェクトの上端 = 端を上にずらして高さを変更
- カーソルがオブジェクトの下端 = 端を下にずらして高さを変更
- カーソルがオブジェクトの左端 = 端を左にずらして高さを変更
- カーソルがオブジェクトの右端 = 端を右にずらして高さを変更
- カーソルがオブジェクトの左上 = 左と上にずらして高さと幅を変更
- カーソルがオブジェクトの右上 = 右と上にずらして高さと幅を変更
- カーソルがオブジェクトの左下 = 左と下にずらして高さと幅を変更
- カーソルがオブジェクトの右下 = 右と下にずらして高さと幅を変更
スクロール可能なコンテンツを持つコンテナの右側と下側にスクロールバーが表示されます。カーソルが右と下のどちらのスクロールバー上にあるかを判断し、それらの状態をマウスの状態に設定する必要があります。
//+------------------------------------------------------------------+ //| The list of possible mouse states relative to the form | //+------------------------------------------------------------------+ enum ENUM_MOUSE_FORM_STATE { MOUSE_FORM_STATE_NONE = 0, // Undefined state //--- Outside the form MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_FORM_STATE_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window header area MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area to the right MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED,// The cursor is within the window scrolling area to the right, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED, // The cursor is within the window scrolling area to the right, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL, // The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled //--- Within the window scrolling area at the bottom MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED,// The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED, // The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL, // The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled //--- Within the window resizing area at the top MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the top, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED, // The cursor is within the window resizing area at the top, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL, // The cursor is within the window resizing area at the top, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED, // The cursor is within the window resizing area at the bottom, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL, // The cursor is within the window resizing area at the bottom, the mouse wheel is being scrolled //--- Within the window resizing area to the left MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED, // The cursor is within the window resizing area to the left, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED, // The cursor is within the window resizing area to the left, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL, // The cursor is within the window resizing area to the left, the mouse wheel is being scrolled //--- Within the window resizing area to the right MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area to the right, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED, // The cursor is within the window resizing area to the right, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area to the right, the mouse wheel is being scrolled //--- Within the window resizing area to the top-left MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the top-left, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED, // The cursor is within the window resizing area at the top-left, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL, // The cursor is within the window resizing area at the top-left, the mouse wheel is being scrolled //--- Within the window resizing area to the top-right MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the top-right, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED, // The cursor is within the window resizing area at the top-right, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area at the top-right, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom left MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED, // The cursor is within the window resizing area at the bottom-left, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL, // The cursor is within the window resizing area at the bottom-left, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom-right MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED, // The cursor is within the window resizing area at the bottom-right, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area at the bottom-right, the mouse wheel is being scrolled //--- Within the control area MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED, // The cursor is within the control area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED, // The cursor is within the control area, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL, // The cursor is within the control area, the mouse wheel is being scrolled }; //+------------------------------------------------------------------+
これらの新しい状態はすべて、オブジェクトに対するマウスの相対的な状態として定義され、記録されることになります。
マウスが所定の状態にあるイベントが登録されると、そのイベントがライブラリに送られ、マウスイベントを処理する機能を持つ各オブジェクトで、そのイベントに対応するハンドラが呼び出されます。
可能なマウスイベントのリストに新しい状態を書き込んでみましょう。
//+--------------------------------------------+ //| List of possible mouse events | //+--------------------------------------------+ enum ENUM_MOUSE_EVENT { MOUSE_EVENT_NO_EVENT = CHART_OBJ_EVENTS_NEXT_CODE, // No event //--- MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_EVENT_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_EVENT_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_EVENT_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window active area MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area to the right MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED, // The cursor is within the window scrolling area to the right, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED, // The cursor is within the window scrolling area to the right, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL, // The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled //--- Within the window scrolling area at the bottom MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED, // The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED, // The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL, // The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled //--- Within the window resizing area at the top MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the top, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_PRESSED, // The cursor is within the window resizing area at the top, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_WHEEL, // The cursor is within the window resizing area at the top, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the bottom, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_PRESSED, // The cursor is within the window resizing area at the bottom, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_WHEEL, // The cursor is within the window resizing area at the bottom, the mouse wheel is being scrolled //--- Within the window resizing area to the left MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED, // The cursor is within the window resizing area to the left, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_PRESSED, // The cursor is within the window resizing area to the left, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_WHEEL, // The cursor is within the window resizing area to the left, the mouse wheel is being scrolled //--- Within the window resizing area to the right MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED, // The cursor is within the window resizing area to the right, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_PRESSED, // The cursor is within the window resizing area to the right, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area to the right, the mouse wheel is being scrolled //--- Within the window resizing area to the top-left MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the top-left, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED, // The cursor is within the window resizing area at the top-left, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL, // The cursor is within the window resizing area at the top-left, the mouse wheel is being scrolled //--- Within the window resizing area to the top-right MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the top-right, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED, // The cursor is within the window resizing area at the top-right, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area at the top-right, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom left MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL, // The cursor is within the window resizing area at the bottom-left, the mouse wheel is being scrolled //--- Within the window resizing area at the bottom-right MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area at the bottom-right, the mouse wheel is being scrolled //--- Within the control area MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED, // The cursor is within the control area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_CONTROL_AREA_PRESSED, // The cursor is within the control area, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL, // The cursor is within the control area, the mouse wheel is being scrolled }; #define MOUSE_EVENT_NEXT_CODE (MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL+1) // The code of the next event after the last mouse event code //+------------------------------------------------------------------+
グラフィック要素タイプのリストに新しい要素タイプを追加します。
//+--------------------------------------------+ //| The list of graphical element types | //+--------------------------------------------+ enum ENUM_GRAPH_ELEMENT_TYPE { GRAPH_ELEMENT_TYPE_STANDARD, // Standard graphical object GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED, // Extended standard graphical object GRAPH_ELEMENT_TYPE_SHADOW_OBJ, // Shadow object GRAPH_ELEMENT_TYPE_ELEMENT, // Element GRAPH_ELEMENT_TYPE_FORM, // Form GRAPH_ELEMENT_TYPE_WINDOW, // Window //--- WinForms GRAPH_ELEMENT_TYPE_WF_UNDERLAY, // Panel object underlay GRAPH_ELEMENT_TYPE_WF_BASE, // Windows Forms Base //--- 'Container' object types are to be set below GRAPH_ELEMENT_TYPE_WF_CONTAINER, // Windows Forms container base object GRAPH_ELEMENT_TYPE_WF_PANEL, // Windows Forms Panel GRAPH_ELEMENT_TYPE_WF_GROUPBOX, // Windows Forms GroupBox GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL, // Windows Forms TabControl GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER, // Windows Forms SplitContainer //--- 'Standard control' object types are to be set below GRAPH_ELEMENT_TYPE_WF_COMMON_BASE, // Windows Forms base standard control GRAPH_ELEMENT_TYPE_WF_LABEL, // Windows Forms Label GRAPH_ELEMENT_TYPE_WF_BUTTON, // Windows Forms Button GRAPH_ELEMENT_TYPE_WF_CHECKBOX, // Windows Forms CheckBox GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON, // Windows Forms RadioButton GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX, // Base list object of Windows Forms elements GRAPH_ELEMENT_TYPE_WF_LIST_BOX, // Windows Forms ListBox GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX, // Windows Forms CheckedListBox GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX, // Windows Forms ButtonListBox GRAPH_ELEMENT_TYPE_WF_TOOLTIP, // Windows Forms ToolTip GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR, // Windows Forms ProgressBar //--- Auxiliary elements of WinForms objects GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM, // Windows Forms ListBoxItem GRAPH_ELEMENT_TYPE_WF_TAB_HEADER, // Windows Forms TabHeader GRAPH_ELEMENT_TYPE_WF_TAB_FIELD, // Windows Forms TabField GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL, // Windows Forms SplitContainerPanel GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON, // Windows Forms ArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP, // Windows Forms UpArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN, // Windows Forms DownArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT, // Windows Forms LeftArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT, // Windows Forms RightArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX, // Windows Forms UpDownArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX, // Windows Forms LeftRightArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_SPLITTER, // Windows Forms Splitter GRAPH_ELEMENT_TYPE_WF_HINT_BASE, // Windows Forms HintBase GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT, // Windows Forms HintMoveLeft GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT, // Windows Forms HintMoveRight GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP, // Windows Forms HintMoveUp GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN, // Windows Forms HintMoveDown GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR, // Windows Forms BarProgressBar GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ, // Glare object GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB, // Windows Forms ScrollBarThumb GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR, // Windows Forms ScrollBar GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL, // Windows Forms ScrollBarHorisontal GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL, // Windows Forms ScrollBarVertical }; //+------------------------------------------------------------------+
これは、新しい「キャプチャ領域」ヘルパー(スクロールバースライダー)コントロールになります。
グラフィック要素の整数プロパティの列挙に2つの新しいプロパティを追加し、それらの合計数を138から140に増やしました。
//+------------------------------------------------------------------+ //| Integer properties of the graphical element on the canvas | //+------------------------------------------------------------------+ enum ENUM_CANV_ELEMENT_PROP_INTEGER { CANV_ELEMENT_PROP_ID = 0, // Element ID CANV_ELEMENT_PROP_TYPE, // Graphical element type //---... //---... CANV_ELEMENT_PROP_ZORDER, // Priority of a graphical object for receiving the event of clicking on a chart CANV_ELEMENT_PROP_ENABLED, // Element availability flag CANV_ELEMENT_PROP_RESIZABLE, // Resizable element flag CANV_ELEMENT_PROP_FORE_COLOR, // Default text color for all control objects CANV_ELEMENT_PROP_FORE_COLOR_OPACITY, // Default text color opacity for all control objects //---... //---... CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE, // Current ProgressBar value from Min to Max CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED, // Progress bar animation speed in case of Marquee style CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE, // Size of the arrow drawn on the button }; #define CANV_ELEMENT_PROP_INTEGER_TOTAL (140) // Total number of integer properties #define CANV_ELEMENT_PROP_INTEGER_SKIP (0) // Number of integer properties not used in sorting //+------------------------------------------------------------------+
各グラフィック要素には、マウスでサイズ変更が可能であることを示すフラグが表示されます。要素に描画される矢印(例えば、矢印付きボタン)は、このパラメータで指定された相対的な大きさを持つことになります。例えば、サイズ1の矢印は、中心点から1ピクセルのバーテックスインデントで描画されます。サイズ2の矢印は、中心点から2ピクセルずつインデントして描かれます。
例えば、サイズ1の上矢印の場合、次のようになります。
⊡⊠⊡ ⊠⊠⊠
サイズ2の上矢印は次のようになります。
⊡⊡⊠⊡⊡ ⊡⊠⊠⊠⊡ ⊠⊠⊠⊠⊠
サイズ3の上矢印は次のようになります。
⊡⊡⊡⊠⊡⊡⊡ ⊡⊡⊠⊠⊠⊡⊡ ⊡⊠⊠⊠⊠⊠⊡ ⊠⊠⊠⊠⊠⊠⊠
三角形の底面の中心を1ピクセルとし、その各辺に図形の相対的な大きさに等しいピクセル数を設定すると、三角形の3つの頂点が得られ、それに沿って図形が構築されることになります。したがって、三角形の大きさは、三角形の底面の中心から、各頂点の座標を示す上下左右のピクセル数となります。
下、左、右の矢印も同じように作られています。
\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します。
MSG_GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR, // ProgressBar control MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR, // ScrollBar control MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB, // ScrollBar control capture area MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL, // ScrollBarVertical control MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL, // ScrollBarHorisontal control
...
MSG_CANV_ELEMENT_PROP_DISPLAY_DURATION, // Control display duration MSG_CANV_ELEMENT_PROP_ENABLED, // Element availability flag MSG_CANV_ELEMENT_PROP_RESIZABLE, // Control size changeability flag MSG_CANV_ELEMENT_PROP_FORE_COLOR, // Default text color for all control objects MSG_CANV_ELEMENT_PROP_FORE_COLOR_OPACITY, // Default text color opacity for all control objects
...
MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE, // Current ProgressBar value from Min to Max MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,// Progress bar animation speed in case of Marquee style MSG_CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE, // Size of the arrow drawn on the button //--- Real properties of graphical elements //--- String properties of graphical elements
新しく追加したインデックスに対応するメッセージテキストも追加します。
{"Элемент управления \"ProgressBar\"","Control element \"ProgressBar\""}, {"Элемент управления \"ScrollBar\"","Control element \"ScrollBar\""}, {"Область захвата элемента управления \"ScrollBar\"","The grip area of the \"ScrollBar\" control"}, {"Элемент управления \"ScrollBarVertical\"","Control element \"ScrollBarVertical\""}, {"Элемент управления \"ScrollBarHorisontal\"","Control element \"ScrollBarHorisontal\""},
...
{"Продолжительность процесса отображения элемента управления","Duration of the process of displaying the control"}, {"Флаг доступности элемента","Element Availability flag"}, {"Флаг изменяемости размеров элемента","Element Resizable flag"}, {"Цвет текста по умолчанию для всех объектов элемента управления","Default text color for all objects in the control"}, {"Непрозрачность цвета текста по умолчанию для всех объектов элемента управления","Default text color opacity for all objects in the control"},
...
{"Текущее начение элемента ProgressBar в диапазоне от Min до Max","Current value of the ProgressBar in the range from Min to Max"}, {"Скорость анимации полосы прогресса при стиле Marquee","Marquee style progress bar animation speed"}, {"Размер стрелки, рисуемой на кнопке","Size of arrow drawn on the button"}, //--- String properties of graphical elements
新しいオブジェクトタイプの説明を表示するために\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqhのTypeElementDescription()メソッド内に、メソッドに渡されたオブジェクトタイプの説明を返す文字列を追加します。
//+------------------------------------------------------------------+ //| Return the description of the graphical element type | //+------------------------------------------------------------------+ string CGBaseObj::TypeElementDescription(const ENUM_GRAPH_ELEMENT_TYPE type) { return ( type==GRAPH_ELEMENT_TYPE_STANDARD ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD) : type==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED) : type==GRAPH_ELEMENT_TYPE_ELEMENT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_ELEMENT) : type==GRAPH_ELEMENT_TYPE_SHADOW_OBJ ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ) : type==GRAPH_ELEMENT_TYPE_FORM ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_FORM) : type==GRAPH_ELEMENT_TYPE_WINDOW ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WINDOW) : //--- WinForms type==GRAPH_ELEMENT_TYPE_WF_UNDERLAY ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_UNDERLAY) : type==GRAPH_ELEMENT_TYPE_WF_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BASE) : //--- Containers type==GRAPH_ELEMENT_TYPE_WF_CONTAINER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CONTAINER) : type==GRAPH_ELEMENT_TYPE_WF_GROUPBOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_GROUPBOX) : type==GRAPH_ELEMENT_TYPE_WF_PANEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_PANEL) : type==GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) : //--- Standard controls type==GRAPH_ELEMENT_TYPE_WF_COMMON_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_COMMON_BASE) : type==GRAPH_ELEMENT_TYPE_WF_LABEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LABEL) : type==GRAPH_ELEMENT_TYPE_WF_CHECKBOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKBOX) : type==GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON) : type==GRAPH_ELEMENT_TYPE_WF_BUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON) : type==GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM) : type==GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_TOOLTIP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP) : type==GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR) : //--- Auxiliary control objects type==GRAPH_ELEMENT_TYPE_WF_TAB_HEADER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER) : type==GRAPH_ELEMENT_TYPE_WF_TAB_FIELD ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_FIELD) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL) : type==GRAPH_ELEMENT_TYPE_WF_SPLITTER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLITTER) : type==GRAPH_ELEMENT_TYPE_WF_HINT_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_BASE) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN) : type==GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR) : type==GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ) : type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR) : type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL) : type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL) : type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB) : "Unknown" ); } //+------------------------------------------------------------------+
グラフィック要素のプロパティの列挙に新しいプロパティが追加されるたびに、オブジェクト構造体に追加する必要があります。グラフィカルオブジェクトの構造体を利用して、グラフィック要素のプロパティをファイルに保存したり、ファイルから読み込んだりすることができます。これは、再起動後にオブジェクトを復元し、終了前と同じ状態にするために必要です。これまで、グラフィカルオブジェクトのプロパティの構成が常に変化するため、そのような機能は作っていませんでしたが、すでに将来に向けてそのような仕組みを作っているのです。
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhで、オブジェクト構造体に新しい整数フィールドを追加します。
private: int m_shift_coord_x; // Offset of the X coordinate relative to the base object int m_shift_coord_y; // Offset of the Y coordinate relative to the base object struct SData { //--- Object integer properties int id; // Element ID int type; // Graphical element type //---... //---... long zorder; // Priority of a graphical object for receiving the event of clicking on a chart bool enabled; // Element availability flag bool resizable; // Size changeability flag color fore_color; // Default text color for all control objects uchar fore_color_opacity; // Default text color opacity for all control objects //---... //---... int progress_bar_value; // Current ProgressBar value from Min to Max int progress_bar_marquee_speed; // Progress bar animation speed in case of Marquee style uchar button_arrow_size; // Size of the arrow drawn on the button //--- ulong tooltip_initial_delay; // Tooltip display delay ulong tooltip_auto_pop_delay; // Tooltip display duration ulong tooltip_reshow_delay; // One element new tooltip display delay bool tooltip_show_always; // Display a tooltip in inactive window int tooltip_icon; // Icon displayed in a tooltip bool tooltip_is_balloon; // Tooltip in the form of a "cloud" bool tooltip_use_fading; // Fade when showing/hiding a tooltip //--- Object real properties //--- Object string properties uchar name_obj[64]; // Graphical element object name uchar name_res[64]; // Graphical resource name uchar text[256]; // Graphical element text uchar descript[256]; // Graphical element description uchar tooltip_title[256]; // Element tooltip title uchar tooltip_text[256]; // Element tooltip text }; SData m_struct_obj; // Object structure uchar m_uchar_array[]; // uchar array of the object structure
クラスのpublicセクションで、グラフィック要素に対するカーソル位置のフラグを返す新しいメソッドを宣言します。
//--- Return the cursor position relative to the (1) entire element, (2) visible part, (3) active area and (4) element control area bool CursorInsideElement(const int x,const int y); bool CursorInsideVisibleArea(const int x,const int y); bool CursorInsideActiveArea(const int x,const int y); bool CursorInsideControlArea(const int x,const int y); //--- Return the cursor position relative to the (1) right, (2) bottom element scroll area bool CursorInsideScrollRightArea(const int x,const int y); bool CursorInsideScrollBottomArea(const int x,const int y); //--- Return the cursor position relative to the (1) upper, (2) lower, (3) left and (4) right element resize area bool CursorInsideResizeTopArea(const int x,const int y); bool CursorInsideResizeBottomArea(const int x,const int y); bool CursorInsideResizeLeftArea(const int x,const int y); bool CursorInsideResizeRightArea(const int x,const int y); //--- Return the cursor position relative to the (1) top-left, (2) top-right, //--- (3) bottom-left, (4) bottom-right element resize area corner bool CursorInsideResizeTopLeftArea(const int x,const int y); bool CursorInsideResizeTopRightArea(const int x,const int y); bool CursorInsideResizeBottomLeftArea(const int x,const int y); bool CursorInsideResizeBottomRightArea(const int x,const int y); //--- Create the element bool Create(const long chart_id,
オブジェクトプロパティへのアクセスを簡略化するメソッドブロックに、新しい領域とグラフィック要素ゾーンの座標を返すメソッド、およびサイズ変更可能フラグを返すメソッドを設定します。
//--- Set (1) object movability, (2) activity, (3) interaction, //--- (4) element ID, (5) element index in the list, the flag of (6) availability, (7) changeable size, (8) shadow void SetMovable(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,flag); } void SetActive(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,flag); } void SetInteraction(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,flag); } void SetID(const int id) { this.SetProperty(CANV_ELEMENT_PROP_ID,id); } void SetNumber(const int number) { this.SetProperty(CANV_ELEMENT_PROP_NUM,number); } void SetEnabled(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_ENABLED,flag); } void SetResizable(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,flag); } void SetShadow(const bool flag) { this.m_shadow=flag; } //--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element control area void SetControlAreaX(const int value) { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,value); } void SetControlAreaY(const int value) { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,value); } void SetControlAreaWidth(const int value) { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,value); } void SetControlAreaHeight(const int value) { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,value); } //--- Return the shift (1) of the left, (2) right, (3) top and (4) bottom edge of the element active area int ActiveAreaLeftShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT); } int ActiveAreaRightShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT); } int ActiveAreaTopShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP); } int ActiveAreaBottomShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM); } //--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element active area int ActiveAreaLeft(void) const { return int(this.CoordX()+this.ActiveAreaLeftShift()); } int ActiveAreaRight(void) const { return int(this.RightEdge()-this.ActiveAreaRightShift()); } int ActiveAreaTop(void) const { return int(this.CoordY()+this.ActiveAreaTopShift()); } int ActiveAreaBottom(void) const { return int(this.BottomEdge()-this.ActiveAreaBottomShift()); } //--- Return the shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element control area int ControlAreaXShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X); } int ControlAreaYShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y); } int ControlAreaWidth(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH); } int ControlAreaHeight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT); } //--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ControlAreaLeft(void) const { return this.CoordX()+this.ControlAreaXShift(); } int ControlAreaRight(void) const { return this.ControlAreaLeft()+this.ControlAreaWidth(); } int ControlAreaTop(void) const { return this.CoordY()+this.ControlAreaYShift(); } int ControlAreaBottom(void) const { return this.ControlAreaTop()+this.ControlAreaHeight(); } //--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ControlAreaLeftRelative(void) const { return this.ControlAreaLeft()-this.CoordX(); } int ControlAreaRightRelative(void) const { return this.ControlAreaRight()-this.CoordX(); } int ControlAreaTopRelative(void) const { return this.ControlAreaTop()-this.CoordY(); } int ControlAreaBottomRelative(void) const { return this.ControlAreaBottom()-this.CoordY(); } //--- Return the shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element scroll area to the right int ScrollAreaRightXShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT); } int ScrollAreaRightYShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT); } int ScrollAreaRightWidth(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT); } int ScrollAreaRightHeight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT);} //--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ScrollAreaRightLeft(void) const { return this.CoordX()+this.ScrollAreaRightXShift(); } int ScrollAreaRightRight(void) const { return this.ScrollAreaRightLeft()+this.ScrollAreaRightWidth(); } int ScrollAreaRightTop(void) const { return this.CoordY()+this.ScrollAreaRightYShift(); } int ScrollAreaRightBottom(void) const { return this.ScrollAreaRightTop()+this.ScrollAreaRightHeight(); } //--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ScrollAreaRightLeftRelative(void) const { return this.ScrollAreaRightLeft()-this.CoordX(); } int ScrollAreaRightRightRelative(void) const { return this.ScrollAreaRightRight()-this.CoordX(); } int ScrollAreaRightTopRelative(void) const { return this.ScrollAreaRightTop()-this.CoordY(); } int ScrollAreaRightBottomRelative(void) const { return this.ScrollAreaRightBottom()-this.CoordY(); } //--- Return the shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element scroll area at the bottom int ScrollAreaBottomXShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM); } int ScrollAreaBottomYShift(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM); } int ScrollAreaBottomWidth(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM);} int ScrollAreaBottomHeight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM);} //--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ScrollAreaBottomLeft(void) const { return this.CoordX()+this.ScrollAreaBottomXShift(); } int ScrollAreaBottomRight(void) const { return this.ScrollAreaBottomLeft()+this.ScrollAreaBottomWidth(); } int ScrollAreaBottomTop(void) const { return this.CoordY()+this.ScrollAreaBottomYShift(); } int ScrollAreaBottomBottom(void) const { return this.ScrollAreaBottomTop()+this.ScrollAreaBottomHeight(); } //--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area int ScrollAreaBottomLeftRelative(void) const { return this.ScrollAreaBottomLeft()-this.CoordX(); } int ScrollAreaBottomRightRelative(void) const { return this.ScrollAreaBottomRight()-this.CoordX(); } int ScrollAreaBottomTopRelative(void) const { return this.ScrollAreaBottomTop()-this.CoordY(); } int ScrollAreaBottomBottomRelative(void)const { return this.ScrollAreaBottomBottom()-this.CoordY(); } //--- Return the width of the (1) left, (2) right, (3) upper and (4) lower element edge area int BorderResizeAreaLeft(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH); } int BorderResizeAreaRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH); } int BorderResizeAreaTop(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH); } int BorderResizeAreaBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH); }
要素サイズ変更可否フラグを返すメソッドを追加します。
//--- Return the (1) element movability, (2) activity, (3) interaction, (4) availability and (5) size changeability flag bool Movable(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_MOVABLE); } bool Active(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ACTIVE); } bool Interaction(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_INTERACTION); } bool Enabled(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED); } bool Resizable(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_RESIZABLE); } //--- Return (1) the object name, (2) the graphical resource name, (3) the chart ID and (4) the chart subwindow index
矢印描画メソッドの宣言を変更します。
//+------------------------------------------------------------------+ //| Methods for drawing predefined standard images | //+------------------------------------------------------------------+ //--- Draw the Info icon void DrawIconInfo(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the Warning icon void DrawIconWarning(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the Error icon void DrawIconError(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the left arrow void DrawArrowLeft(const int base_x,const int base_y,const int size,const color clr,const uchar opacity); //--- Draw the right arrow void DrawArrowRight(const int base_x,const int base_y,const int size,const color clr,const uchar opacity); //--- Draw the up arrow void DrawArrowUp(const int base_x,const int base_y,const int size,const color clr,const uchar opacity); //--- Draw the down arrow void DrawArrowDown(const int base_x,const int base_y,const int size,const color clr,const uchar opacity); }; //+------------------------------------------------------------------+
これで、メソッドは中心点の座標と相対的な矢印の大きさを受け取ることができます。
オブジェクトのプロパティを初期化するメソッドで、マウスカーソルがこれらの領域にあるかどうかを定義するために、オブジェクトの上下左右の端の領域の幅をデフォルト値として2ピクセルに設定します。デフォルトでは、マウスカーソルを使ってオブジェクトのサイズを変更する機能は無効になっており、描画される矢印のサイズは3になっています。
//+--------------------------------------------+ //| Initialize the properties | //+--------------------------------------------+ void CGCnvElement::Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id,const int element_num, const int x,const int y,const int w,const int h, const string descript,const bool movable,const bool activity) { this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,this.m_canvas.ResourceName()); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,CGBaseObj::ChartID()); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,CGBaseObj::SubWindow()); // Chart subwindow index this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,CGBaseObj::Name()); // Element object name this.SetProperty(CANV_ELEMENT_PROP_TYPE,element_type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_ID,element_id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_NUM,element_num); // Element index in the list this.SetProperty(CANV_ELEMENT_PROP_COORD_X,x); // Element's X coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_COORD_Y,y); // Element's Y coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_WIDTH,w); // Element width this.SetProperty(CANV_ELEMENT_PROP_HEIGHT,h); // Element height this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,0); // Active area offset from the left edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,0); // Active area offset from the upper edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,0); // Active area offset from the right edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,0); // Active area offset from the bottom edge of the element this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,movable); // Element moveability flag this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,activity); // Element activity flag this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false); // Flag of interaction with the outside environment this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true); // Element availability flag this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,false); // Element changeable size flag this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge()); // Element right border this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.BottomEdge()); // Element bottom border this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.ActiveAreaLeft()); // X coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.ActiveAreaTop()); // Y coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.ActiveAreaRight()); // Right border of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.ActiveAreaBottom()); // Bottom border of the element active area this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_X,0); // Visibility scope X coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_Y,0); // Visibility scope Y coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_WIDTH,w); // Visibility scope width this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT,h); // Visibility scope height this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,true); // Non-hidden control display flag this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_STATE,CANV_ELEMENT_DISPLAY_STATE_NORMAL);// Control display state this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_DURATION,DEF_CONTROL_PROCESS_DURATION); // Control display duration this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,0); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,0); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,0); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,0); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,0); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,0); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,0); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,0); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,0); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,0); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,2); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,2); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,2); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,2); // Top edge area width //--- this.SetProperty(CANV_ELEMENT_PROP_BELONG,ENUM_GRAPH_OBJ_BELONG::GRAPH_OBJ_BELONG_PROGRAM); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_ZORDER,0); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_BOLD_TYPE,FW_NORMAL); // Font width type this.SetProperty(CANV_ELEMENT_PROP_BORDER_STYLE,FRAME_STYLE_NONE); // Control frame style this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,0); // Control frame top size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,0); // Control frame bottom size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,0); // Control frame left size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,0); // Control frame right size this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR,this.BackgroundColor()); // Control frame color this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE,false); // Flag of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE,CANV_ELEMENT_AUTO_SIZE_MODE_GROW); // Mode of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL,false); // Auto scrollbar flag this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_W,0); // Width of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_H,0); // Height of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_DOCK_MODE,CANV_ELEMENT_DOCK_MODE_NONE); // Mode of binding control borders to the container this.SetProperty(CANV_ELEMENT_PROP_MARGIN_TOP,0); // Top margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_BOTTOM,0); // Bottom margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_LEFT,0); // Left margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_RIGHT,0); // Right margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_PADDING_TOP,0); // Top margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_BOTTOM,0); // Bottom margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_LEFT,0); // Left margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_RIGHT,0); // Right margin inside the control this.SetProperty(CANV_ELEMENT_PROP_TEXT_ALIGN,ANCHOR_LEFT_UPPER); // Text position within text label boundaries this.SetProperty(CANV_ELEMENT_PROP_CHECK_ALIGN,ANCHOR_LEFT_UPPER); // Position of the checkbox within control borders this.SetProperty(CANV_ELEMENT_PROP_CHECKED,false); // Control checkbox status this.SetProperty(CANV_ELEMENT_PROP_CHECK_STATE,CANV_ELEMENT_CHEK_STATE_UNCHECKED); // Status of a control having a checkbox this.SetProperty(CANV_ELEMENT_PROP_AUTOCHECK,true); // Auto change flag status when it is selected //--- //---... //---... this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,50); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,10); // Progress bar animation speed in case of Marquee style this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3); // Size of the arrow drawn on the button } //+------------------------------------------------------------------+
オブジェクトの構造を作成するメソッドで、新しいオブジェクトプロパティの値を新しい構造体フィールドに設定します。
//+--------------------------------------------+ //| Create the object structure | //+--------------------------------------------+ bool CGCnvElement::ObjectToStruct(void) { //--- Save integer properties this.m_struct_obj.id=(int)this.GetProperty(CANV_ELEMENT_PROP_ID); // Element ID this.m_struct_obj.type=(int)this.GetProperty(CANV_ELEMENT_PROP_TYPE); // Graphical element type //---... //---... this.m_struct_obj.zorder=this.GetProperty(CANV_ELEMENT_PROP_ZORDER); // Priority of a graphical object for receiving the on-chart mouse click event this.m_struct_obj.enabled=(bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED); // Element availability flag this.m_struct_obj.resizable=(bool)this.GetProperty(CANV_ELEMENT_PROP_RESIZABLE); // Element size changeability flag this.m_struct_obj.fore_color=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR); // Default text color for all control objects this.m_struct_obj.fore_color_opacity=(uchar)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY); // Opacity of the default text color for all control objects //---... //---... this.m_struct_obj.progress_bar_value=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE); // Current ProgressBar value from Min to Max this.m_struct_obj.progress_bar_marquee_speed=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED);// Progress bar animation speed in case of Marquee style this.m_struct_obj.button_arrow_size=(uchar)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE); // Size of the arrow drawn on the button //--- Save real properties //--- Save string properties ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_OBJ),this.m_struct_obj.name_obj); // Graphical element object name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_RES),this.m_struct_obj.name_res); // Graphical resource name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TEXT),this.m_struct_obj.text); // Graphical element text ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_DESCRIPTION),this.m_struct_obj.descript);// Graphical element description ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE),this.m_struct_obj.tooltip_title);// Tooltip title for the element ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT),this.m_struct_obj.tooltip_text); // Tooltip text for the element //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY,true); return false; } return true; } //+------------------------------------------------------------------+
構造体からオブジェクトを作成するメソッドで、適切な構造体フィールドの値をオブジェクトプロパティに設定します。
//+--------------------------------------------+ //| Create the object from the structure | //+--------------------------------------------+ void CGCnvElement::StructToObject(void) { //--- Save integer properties this.SetProperty(CANV_ELEMENT_PROP_ID,this.m_struct_obj.id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_TYPE,this.m_struct_obj.type); // Graphical element type //---... //---... this.SetProperty(CANV_ELEMENT_PROP_ZORDER,this.m_struct_obj.zorder); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_ENABLED,this.m_struct_obj.enabled); // Element availability flag this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,this.m_struct_obj.resizable); // Element size changeability flag this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR,this.m_struct_obj.fore_color); // Default text color for all control objects this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,this.m_struct_obj.fore_color_opacity); // Opacity of the default text color for all control objects //---... //---... this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,this.m_struct_obj.progress_bar_value); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,this.m_struct_obj.progress_bar_marquee_speed); // Progress bar animation speed in case of Marquee style this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,this.m_struct_obj.button_arrow_size); // Size of the arrow drawn on the button //--- Save real properties //--- Save string properties this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,::CharArrayToString(this.m_struct_obj.name_obj)); // Graphical element object name this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,::CharArrayToString(this.m_struct_obj.name_res)); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_TEXT,::CharArrayToString(this.m_struct_obj.text)); // Graphical element text this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,::CharArrayToString(this.m_struct_obj.descript));// Graphical element description this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,::CharArrayToString(this.m_struct_obj.tooltip_title));// Tooltip title for the element this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,::CharArrayToString(this.m_struct_obj.tooltip_text)); // Tooltip text for the element } //+------------------------------------------------------------------+
スクロール領域に対するカーソル位置フラグを返すメソッドと、要素のリサイズをおこなうメソッドを実装します。
//+------------------------------------------------------------------+ //|Return the cursor position relative to the element control area | //+------------------------------------------------------------------+ bool CGCnvElement::CursorInsideControlArea(const int x,const int y) { return(x>=this.ControlAreaLeft() && x<=this.ControlAreaRight() && y>=this.ControlAreaTop() && y<=this.ControlAreaBottom()); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element right scrolling area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideScrollRightArea(const int x,const int y) { return(x>=this.ScrollAreaRightLeft() && x<=this.ScrollAreaRightRight() && y>=this.ScrollAreaRightTop() && y<=this.ScrollAreaRightBottom()); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element bottom scrolling area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideScrollBottomArea(const int x,const int y) { return(x>=this.ScrollAreaBottomLeft() && x<=this.ScrollAreaBottomRight() && y>=this.ScrollAreaBottomTop() && y<=this.ScrollAreaBottomBottom()); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize upper area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeTopArea(const int x,const int y) { return(x>=this.CoordX()+DEF_CONTROL_CORNER_AREA && x<=this.RightEdge()-DEF_CONTROL_CORNER_AREA && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop()); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize lower area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeBottomArea(const int x,const int y) { return(x>=this.CoordX()+DEF_CONTROL_CORNER_AREA && x<=this.RightEdge()-DEF_CONTROL_CORNER_AREA && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge()); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize lower area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeLeftArea(const int x,const int y) { return(x>=this.CoordX() && x<=this.CoordX()+this.BorderResizeAreaLeft() && y>=this.CoordY()+DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()-DEF_CONTROL_CORNER_AREA); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize right area | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeRightArea(const int x,const int y) { return(x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>=this.CoordY()+DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()-DEF_CONTROL_CORNER_AREA); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize area upper left corner | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeTopLeftArea(const int x,const int y) { return ( (x>=this.CoordX() && x<this.CoordX()+DEF_CONTROL_CORNER_AREA && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop()) || (x>=this.CoordX() && x<=this.BorderResizeAreaLeft() && y>=this.CoordY() && y<=this.CoordY()+DEF_CONTROL_CORNER_AREA) ); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize area upper right corner | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeTopRightArea(const int x,const int y) { return ( (x>this.RightEdge()-DEF_CONTROL_CORNER_AREA && x<=this.RightEdge() && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop()) || (x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>=this.CoordY() && y<=this.CoordY()+DEF_CONTROL_CORNER_AREA) ); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize area lower left corner | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeBottomLeftArea(const int x,const int y) { return ( (x>=this.CoordX() && x<this.CoordX()+DEF_CONTROL_CORNER_AREA && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge()) || (x>=this.CoordX() && x<=this.CoordX()+this.BorderResizeAreaLeft() && y>this.BottomEdge()-DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()) ); } //+--------------------------------------------+ //| Return the cursor position relative to the | //| element resize area lower right corner | //+--------------------------------------------+ bool CGCnvElement::CursorInsideResizeBottomRightArea(const int x,const int y) { return ( (x>this.RightEdge()-DEF_CONTROL_CORNER_AREA && x<=this.RightEdge() && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge()) || (x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>this.BottomEdge()-DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()) ); } //+--------------------------------------------+ //| Update the coordinate elements | //+--------------------------------------------+
カーソルの位置の座標に応じて、メソッドはカーソルがその値で囲まれた領域内にあることを示すフラグを返します。
矢印を描画するメソッドは、開始座標(三角形の底辺中心)と指定された矢印のサイズに応じて三角形を描画するようになりました。
//+--------------------------------------------+ //| Draw the left arrow | //+--------------------------------------------+ void CGCnvElement::DrawArrowLeft(const int base_x,const int base_y,const int size,const color clr,const uchar opacity) { int x=base_x; int y=base_y; int s=(size<1 ? 1 : size); this.DrawTriangleFill(x-s,y,x,y-s,x,y+s,clr,opacity); this.DrawTriangleWu( x-s,y,x,y-s,x,y+s,clr,opacity); } //+--------------------------------------------+ //| Draw the right arrow | //+--------------------------------------------+ void CGCnvElement::DrawArrowRight(const int base_x,const int base_y,const int size,const color clr,const uchar opacity) { int x=base_x; int y=base_y; int s=(size<1 ? 1 : size); this.DrawTriangleFill(x+s,y,x,y+s,x,y-s,clr,opacity); this.DrawTriangleWu( x+s,y,x,y+s,x,y-s,clr,opacity); } //+--------------------------------------------+ //| Draw the up arrow | //+--------------------------------------------+ void CGCnvElement::DrawArrowUp(const int base_x,const int base_y,const int size,const color clr,const uchar opacity) { int x=base_x; int y=base_y; int s=(size<1 ? 1 : size); this.DrawTriangleFill(x,y-s,x+s,y,x-s,y,clr,opacity); this.DrawTriangleWu( x,y-s,x+s,y,x-s,y,clr,opacity); } //+--------------------------------------------+ //| Draw the down arrow | //+--------------------------------------------+ void CGCnvElement::DrawArrowDown(const int base_x,const int base_y,const int size,const color clr,const uchar opacity) { int x=base_x; int y=base_y; int s=(size<1 ? 1 : size); this.DrawTriangleFill(x,y+s,x-s,y,x+s,y,clr,opacity); this.DrawTriangleWu( x,y+s,x-s,y,x+s,y,clr,opacity); } //+------------------------------------------------------------------+
各頂点の座標を計算するには、中心点の座標にパラメータで渡された矢印の大きさを加減するだけです。
サイズは下限(1)のみで制限され、上限はないことに留意してください。ここで、矢印の実際の大きさは、指定された2つのサイズ+中央の1ピクセルとして得られるので、通常の大きさで描画されることを確認する必要があります。つまり、サイズが1の場合、実サイズは1+1+1になります。サイズが2の場合、実サイズは2+1+2、サイズが3の場合は3+1+3、などです。
要素に対する新しいマウスの状態とそれに対応するイベントができたので、それらを最後のマウスイベントのハンドラメソッドに反映させる必要があります。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\Button.mqhで、新しいイベントのリストをメソッドに追加します。
//+--------------------------------------------+ //| Last mouse event handler | //+--------------------------------------------+ void CButton::OnMouseEventPostProcessing(void) { if(!this.IsVisible() || !this.Enabled()) return; ENUM_MOUSE_FORM_STATE state=GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : if(this.MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED) { this.SetBackgroundColor(this.State() ? this.BackgroundStateOnColor() : this.BackgroundColorInit(),false); this.SetForeColor(this.State() ? this.ForeStateOnColor() : this.ForeColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); this.Redraw(false); } break; //--- The cursor is inside the form, the mouse buttons are not clicked //--- The cursor is inside the form, any mouse button is clicked //--- The cursor is inside the form, the mouse wheel is being scrolled //--- The cursor is inside the active area, the mouse buttons are not clicked //--- The cursor is inside the active area, any mouse button is clicked //--- The cursor is inside the active area, the mouse wheel is being scrolled //--- The cursor is inside the active area, left mouse button is released //--- The cursor is within the window scrolling area, the mouse buttons are not clicked //--- The cursor is within the window scrolling area, any mouse button is clicked //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window resizing area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window separator area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : //--- Within the active area case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : //--- Within the scrolling area at the bottom case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL : //--- Within the scrolling area to the right case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL : //--- Within the window resizing area at the top case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL : //--- Within the window resizing area at the bottom case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL : //--- Within the window resizing area to the left case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL : //--- Within the window resizing area to the right case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL : //--- Within the window resizing area to the top-left case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL : //--- Within the window resizing area to the top-right case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL : //--- Within the window resizing area at the bottom left case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL : //--- Within the window resizing area at the bottom-right case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL : //--- Within the control area case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
ここでは、これらのイベントはすべて処理されませんが、必要であれば、いつでも各イベントの下にその処理を追加することができます。
TabHeader.mqh、 CheckBox.mqh、SplitContainer.mqhで既に同様のメソッドの変更がおこなわれています。
矢印ボタンクラスで描画される矢印の色を指定するために、private変数m_arrow_colorを使用しました。ForeColor()メソッドで色を指定すれば、描画されるテキストの色も制御できるので、この変数の使用は余分なものです。そのため、\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqhの変数とその処理メソッドを削除します。
//+------------------------------------------------------------------+ //| Arrow Button object class of WForms controls | //+------------------------------------------------------------------+ class CArrowButton : public CButton { private: color m_arrow_color; // Arrow color protected: //--- Draw the arrow virtual void DrawArrow(void){return;} //--- Protected constructor with object type, chart ID and subwindow CArrowButton(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- (1) Set and (2) return the arrow color void SetArrowColor(const color clr) { this.m_arrow_color=clr; } color ArrowColor(void) const { return this.m_arrow_color; } //--- Constructor
また、リモートメソッドの呼び出しを、文字色を扱うメソッドに置き換えます。
//+--------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+--------------------------------------------+ CArrowButton::CArrowButton(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CButton(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and assign the library object type to the current object this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(1); this.SetForeColor(CLR_DEF_FORE_COLOR,true); } //+------------------------------------------------------------------+ //| Constructor indicating the main and base objects, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CArrowButton::CArrowButton(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CButton(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(1); this.SetForeColor(CLR_DEF_FORE_COLOR,true); } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowRightButton.mqhにあるクラスコンストラクタで、描画する矢印のサイズを 3に設定します。
//+--------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+--------------------------------------------+ CArrowRightButton::CArrowRightButton(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CArrowButton(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and the size of the drawn arrow to 3 this.SetTypeElement(type); this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3); } //+------------------------------------------------------------------+ //| Constructor indicating the main and base objects, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CArrowRightButton::CArrowRightButton(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CArrowButton(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT); this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3); } //+------------------------------------------------------------------+
矢印を描画するメソッドでは、呼び出す際のパラメータを変更します。
//+--------------------------------------------+ //| Draw the arrow | //+--------------------------------------------+ void CArrowRightButton::DrawArrow(void) { CGCnvElement::DrawArrowRight(this.Width()/2-1,this.Height()/2,(int)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE),this.ForeColor(),this.Opacity()); } //+------------------------------------------------------------------+
矢印の中心点として、オブジェクトの中心を渡し(水平方向に1ピクセル左にずらす)、オブジェクトのプロパティで設定した描画矢印のサイズ、その文字色と不透明度を指定します。
同様の変更は、他の矢印ボタンオブジェクトのクラスであるArrowLeftButton.mqh、ArrowDownButton.mqh、ArrowUpButton.mqhでも既におこなわれています。
スクロールバー領域の座標やサイズの設定を簡略化するために、フォームオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\Form.mqhファイルに、publicメソッドを追加します。
//--- Set the frame size (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides virtual void SetBorderSizeLeft(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,value); } virtual void SetBorderSizeTop(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,value); } virtual void SetBorderSizeRight(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,value); } virtual void SetBorderSizeBottom(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,value); } //--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element scrolling right area void SetScrollAreaRightX(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,value); } void SetScrollAreaRightY(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,value); } void SetScrollAreaRightWidth(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,value); } void SetScrollAreaRightHeight(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,value);} //--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element scrolling lower area void SetScrollAreaBottomX(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,value); } void SetScrollAreaBottomY(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,value); } void SetScrollAreaBottomWidth(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,value);} void SetScrollAreaBottomHeight(const int value){ this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,value);} //--- Update the coordinates (shift the canvas) virtual bool Move(const int x,const int y,const bool redraw=false);
フォームに対するマウスの状態を設定し返すメソッドでは、マウスカーソルの位置を確認し、フォームの各領域の座標と比較し、その状態のフラグを変数に設定します。さらに、これらのフラグを基に、オブジェクトに対するマウスカーソルの大まかな状態を形成します。メソッドにコードブロックを追加し、要素のサイズを変更するためにドラッグする際にマウスでオブジェクトの端をつかむことができる領域:で、スクロールバーと境界に対するカーソルの位置を追跡できるようにします。
//+------------------------------------------------------------------+ //| Set and get the mouse status relative to the form | //+------------------------------------------------------------------+ ENUM_MOUSE_FORM_STATE CForm::MouseFormState(const int id,const long lparam,const double dparam,const string sparam) { //--- Data location in the ushort value of the button status //--------------------------------------------------------------------------- // bit | byte | state | dec | hex | //--------------------------------------------------------------------------- // 0 | 0 | left mouse button | 1 | 1 | //--------------------------------------------------------------------------- // 1 | 0 | right mouse button | 2 | 2 | //--------------------------------------------------------------------------- // 2 | 0 | SHIFT key | 4 | 4 | //--------------------------------------------------------------------------- // 3 | 0 | CTRL key | 8 | 8 | //--------------------------------------------------------------------------- // 4 | 0 | middle mouse button | 16 | 10 | //--------------------------------------------------------------------------- // 5 | 0 | 1 add. mouse button | 32 | 20 | //--------------------------------------------------------------------------- // 6 | 0 | 2 add. mouse button | 64 | 40 | //--------------------------------------------------------------------------- // 7 | 0 | scrolling the wheel | 128 | 80 | //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // 0 | 1 | cursor inside the form | 256 | 100 | //--------------------------------------------------------------------------- // 1 | 1 | cursor inside active area | 512 | 200 | //--------------------------------------------------------------------------- // 2 | 1 | cursor in the control area | 1024 | 400 | //--------------------------------------------------------------------------- // 3 | 1 | cursor in the scrolling area| 2048 | 800 | //--------------------------------------------------------------------------- // 4 | 1 | cursor at the left edge | 4096 | 1000 | //--------------------------------------------------------------------------- // 5 | 1 | cursor at the bottom edge | 8192 | 2000 | //--------------------------------------------------------------------------- // 6 | 1 | cursor at the right edge | 16384 | 4000 | //--------------------------------------------------------------------------- // 7 | 1 | cursor at the top edge | 32768 | 8000 | //--------------------------------------------------------------------------- //--- Get the mouse status relative to the form, as well as the states of mouse buttons and Shift/Ctrl keys this.m_mouse_form_state=MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED; ENUM_MOUSE_BUTT_KEY_STATE state=this.m_mouse.ButtonKeyState(id,lparam,dparam,sparam); //--- Get the mouse status flags from the CMouseState class object and save them in the variable this.m_mouse_state_flags=this.m_mouse.GetMouseFlags(); //--- If the cursor is inside the form if(CGCnvElement::CursorInsideElement(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { //--- Set bit 8 responsible for the "cursor inside the form" flag this.m_mouse_state_flags |= (0x0001<<8); //--- If the cursor is inside the active area, set bit 9 "cursor inside the active area" if(CGCnvElement::CursorInsideActiveArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<9); //--- otherwise, release the bit "cursor inside the active area" else this.m_mouse_state_flags &=0xFDFF; //--- If the cursor is inside the control area, set bit 10 "cursor inside the control area", if(CGCnvElement::CursorInsideControlArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<10); //--- otherwise, remove the "cursor inside the control area" bit else this.m_mouse_state_flags &=0xFBFF; //--- If the cursor is inside the scroll area, set bit 11 "cursor inside the scroll area" if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()) || CGCnvElement::CursorInsideScrollBottomArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<11); //--- otherwise, remove the "cursor inside the scroll area" bit else this.m_mouse_state_flags &=0xF7FF; //--- If the cursor is on the upper left corner, set bit 15 "cursor on the upper side" and bit 12 "cursor on the left side" if(CGCnvElement::CursorInsideResizeTopLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { this.m_mouse_state_flags |= (0x0001<<15); this.m_mouse_state_flags |= (0x0001<<12); } //--- otherwise, check "cursor on the left face" and "cursor on the top face" separately else { //--- If the cursor is on the left side, set bit 12 "cursor on the left face" if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<12); //--- otherwise, remove the "cursor on the left face" bit else this.m_mouse_state_flags &=0xEFFF; //--- If the cursor is on the top edge, set bit 15 "cursor on the top face" if(CGCnvElement::CursorInsideResizeTopArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<15); //--- otherwise, remove the "cursor on the top face" bit else this.m_mouse_state_flags &=0x7FFF; } //--- If the cursor is on the upper left corner, set bit 15 "cursor on the upper face" and bit 12 "cursor on the left face" if(CGCnvElement::CursorInsideResizeTopRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { this.m_mouse_state_flags |= (0x0001<<15); this.m_mouse_state_flags |= (0x0001<<14); } //--- otherwise, check "cursor on the left face" and "cursor on the top face" separately else { //--- If the cursor is on the left side, set bit 12 "cursor on the right face" if(CGCnvElement::CursorInsideResizeRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<14); //--- otherwise, remove the "cursor on the right face" bit else this.m_mouse_state_flags &=0xBFFF; //--- If the cursor is on the top edge, set bit 15 "cursor on the top face" if(CGCnvElement::CursorInsideResizeTopArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<15); //--- otherwise, remove the "cursor on the top face" bit else this.m_mouse_state_flags &=0x7FFF; } //--- If the cursor is on the lower left corner, set bit 13 "cursor on the lower face" and bit 12 "cursor on the left face" if(CGCnvElement::CursorInsideResizeBottomLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { this.m_mouse_state_flags |= (0x0001<<13); this.m_mouse_state_flags |= (0x0001<<12); } //--- otherwise, check "cursor on the left face" and "cursor on the lower face" separately else { //--- If the cursor is on the left side, set bit 12 "cursor on the left face" if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<12); //--- otherwise, remove the "cursor on the left face" bit else this.m_mouse_state_flags &=0xEFFF; //--- If the cursor is on the lower side, set bit 13 "cursor on the lower face" if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<13); //--- otherwise, remove the "cursor on the lower face" bit else this.m_mouse_state_flags &=0xDFFF; } //--- If the cursor is on the lower right corner, set bit 13 "cursor on the lower face" and bit 14 "cursor on the right face" if(CGCnvElement::CursorInsideResizeBottomRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { this.m_mouse_state_flags |= (0x0001<<13); this.m_mouse_state_flags |= (0x0001<<14); } //--- otherwise, check "cursor on the right face" and "cursor on the lower face" separately else { //--- If the cursor is on the left side, set bit 12 "cursor on the right face" if(CGCnvElement::CursorInsideResizeRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<14); //--- otherwise, remove the "cursor on the right face" bit else this.m_mouse_state_flags &=0xBFFF; //--- If the cursor is on the lower side, set bit 13 "cursor on the lower face" if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<13); //--- otherwise, remove the "cursor on the lower face" bit else this.m_mouse_state_flags &=0xDFFF; } //--- If one of the three mouse buttons is pressed, check the location of the cursor in the form areas and //--- return the appropriate value of the pressed key if((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) { //--- If the cursor is inside the form if((this.m_mouse_state_flags & 0x0100)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_PRESSED; //--- If the cursor is inside the active area of the form if((this.m_mouse_state_flags & 0x0200)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED; //--- If the cursor is inside the form control area if((this.m_mouse_state_flags & 0x0400)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED; //--- If the cursor is inside the form scrolling area if((this.m_mouse_state_flags & 0x0800)!=0) { //--- If above the right area if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED; //--- otherwise, above the bottom one else this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED; } //--- If there are cursor flags on the top and left faces if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED; //--- Check the cursor flags on the top and left faces separately else { //--- If the cursor is on the top face if((this.m_mouse_state_flags & 0x8000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED; //--- If the cursor is on the left face if((this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED; } //--- If there are cursor flags on the top and right faces if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED; //--- Check the cursor flags on the top and right faces separately else { //--- If the cursor is on the top face if((this.m_mouse_state_flags & 0x8000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED; //--- If the cursor is on the right face if((this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED; } //--- If there are cursor flags on the bottom and left faces if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED; //--- Check the cursor flags on the bottom and left faces separately else { //--- If the cursor is on the bottom face if((this.m_mouse_state_flags & 0x2000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED; //--- If the cursor is on the left face if((this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED; } //--- If there are cursor flags on the bottom and right faces if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED; //--- Check the cursor flags on the bottom and right faces separately else { //--- If the cursor is on the bottom face if((this.m_mouse_state_flags & 0x2000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED; //--- If the cursor is on the right face if((this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED; } } //--- otherwise, if not a single mouse button is pressed else { //--- if the mouse wheel is scrolled, return the appropriate wheel scrolling value (in the active, control or form area) //--- If the cursor is inside the form if((this.m_mouse_state_flags & 0x0100)!=0) { //--- If the mouse wheel is being scrolled if((this.m_mouse_state_flags & 0x0080)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_WHEEL; else this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED; } //--- If the cursor is inside the active area of the form if((this.m_mouse_state_flags & 0x0200)!=0) { //--- If the mouse wheel is being scrolled if((this.m_mouse_state_flags & 0x0080)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL; else this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED; } //--- If the cursor is inside the form control area if((this.m_mouse_state_flags & 0x0400)!=0) { //--- If the mouse wheel is being scrolled if((this.m_mouse_state_flags & 0x0080)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL; else this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED; } //--- If the cursor is inside the form scrolling area if((this.m_mouse_state_flags & 0x0800)!=0) { //--- If above the right area if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED; //--- otherwise, above the bottom one else this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED; } //--- If there are cursor flags on the top and left faces if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED; //--- Check the cursor flags on the top and left faces separately else { //--- If the cursor is on the top face if((this.m_mouse_state_flags & 0x8000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED; //--- If the cursor is on the left face if((this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED; } //--- If there are cursor flags on the top and right faces if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED; //--- Check the cursor flags on the top and right faces separately else { //--- If the cursor is on the top face if((this.m_mouse_state_flags & 0x8000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED; //--- If the cursor is on the right face if((this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED; } //--- If there are cursor flags on the bottom and left faces if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED; //--- Check the cursor flags on the bottom and left faces separately else { //--- If the cursor is on the bottom face if((this.m_mouse_state_flags & 0x2000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED; //--- If the cursor is on the left face if((this.m_mouse_state_flags & 0x1000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED; } //--- If there are cursor flags on the bottom and right faces if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED; //--- Check the cursor flags on the bottom and right faces separately else { //--- If the cursor is on the bottom face if((this.m_mouse_state_flags & 0x2000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED; //--- If the cursor is on the right face if((this.m_mouse_state_flags & 0x4000)!=0) this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED; } } } //--- If the cursor is outside the form else { //--- return the appropriate button value in an inactive area this.m_mouse_form_state= ( ((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) ? MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED ); } return this.m_mouse_form_state; } //+------------------------------------------------------------------+
すべてのコードブロックは詳細にコメントされており、実際、その中ではすべてがシンプルです。たとえば、スクロールなどの領域の座標に対するカーソルの座標の位置を確認し、カーソルが領域内にあれば、適切なフラグを設定しています。そうでない場合は、フラグを削除します。フラグをチェックして設定した結果、マウスカーソルの位置を決定するために使用するフラグのセットが出来上がりました。オブジェクトの上面と右面に位置するフラグが設定されている場合、カーソルは右上にあることを示します。そのため、それぞれのフラグを別々に書き込むにはushort値のビットが足りないため、フラグを結合する必要があるのです。
マウスイベントハンドラで、スクロール領域内のカーソルを見つけるためのイベント処理メソッドの呼び出しを変更します。この領域は2つあるので、スクロール領域にあるマウスの状態の名前を変更しました。これで、カーソルが右と上のどちらのスクロールバー上にあるか、正確に表示されるようになりました。
//+--------------------------------------------+ //| Mouse event handler | //+--------------------------------------------+ void CForm::OnMouseEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { switch(id) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_WHEEL : break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED : this.MouseInsideNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_EVENT_INSIDE_FORM_PRESSED : this.MouseInsidePressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_FORM_WHEEL : this.MouseInsideWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED : this.MouseActiveAreaNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED : this.MouseActiveAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL : this.MouseActiveAreaWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED : this.MouseActiveAreaReleasedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area to the right, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED : this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam);break; //--- The cursor is within the window scrolling area to the right, the mouse button (any) is clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED : this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL : this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED: this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam);break; //--- The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED : this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL : this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the control area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED : this.MouseControlAreaNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the control area, the mouse button (any) is clicked case MOUSE_EVENT_INSIDE_CONTROL_AREA_PRESSED : this.MouseControlAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the control area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL : this.MouseControlAreaWhellHandler(id,lparam,dparam,sparam); break; //--- MOUSE_EVENT_NO_EVENT default: break; } this.m_mouse_event_last=(ENUM_MOUSE_EVENT)id; } //+------------------------------------------------------------------+
すべての新しいマウスイベントを最後のマウスイベントハンドラに追加します。
//+--------------------------------------------+ //| Last mouse event handler | //+--------------------------------------------+ void CForm::OnMouseEventPostProcessing(void) { if(!this.IsVisible() || !this.Enabled() || !this.Displayed()) return; ENUM_MOUSE_FORM_STATE state=this.GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : case MOUSE_FORM_STATE_NONE : if(this.MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_NO_EVENT) { this.SetBackgroundColor(this.BackgroundColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); } break; //--- The cursor is inside the form, the mouse buttons are not clicked //--- The cursor is inside the form, any mouse button is clicked //--- The cursor is inside the form, the mouse wheel is being scrolled //--- The cursor is inside the active area, the mouse buttons are not clicked //--- The cursor is inside the active area, any mouse button is clicked //--- The cursor is inside the active area, the mouse wheel is being scrolled //--- The cursor is inside the active area, left mouse button is released //--- The cursor is within the window scrolling area, the mouse buttons are not clicked //--- The cursor is within the window scrolling area, any mouse button is clicked //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window resizing area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window separator area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : //--- Within the active area case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : //--- Within the scrolling area at the bottom case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL : //--- Within the scrolling area to the right case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL : //--- Within the window resizing area at the top case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL : //--- Within the window resizing area at the bottom case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL : //--- Within the window resizing area to the left case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL : //--- Within the window resizing area to the right case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL : //--- Within the window resizing area to the top-left case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL : //--- Within the window resizing area to the top-right case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL : //--- Within the window resizing area at the bottom left case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL : //--- Within the window resizing area at the bottom-right case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL : //--- Within the control area case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
イベントメッセージを送信するメソッドで、基本オブジェクト型の受信を修正します。
//+--------------------------------------------+ //| Send a message about the event | //+--------------------------------------------+ bool CForm::SendEvent(const long chart_id,const ushort event_id) { //--- Create the event: //--- Get the base and main objects CGCnvElement *base=this.GetBase(); CGCnvElement *main=this.GetMain(); //--- find the names of the main and base objects string name_main=(main!=NULL ? main.Name() : this.IsMain() ? this.Name() : "Lost name of object"); string name_base=(base!=NULL ? base.Name() : "Lost name of object"); ENUM_GRAPH_ELEMENT_TYPE base_base_type=(base!=NULL ? (base.GetBase()!=NULL ? base.GetBase().TypeGraphElement() : base.TypeGraphElement()) : this.TypeGraphElement()); //--- pass the object ID in the event 'long' parameter //--- pass the object type in the event 'double' parameter //--- in the event 'string' parameter, pass the names of the main, base and current objects separated by ";" long lp=this.ID(); double dp=base_base_type; string sp=::StringSubstr(name_main,::StringLen(this.NamePrefix()))+";"+ ::StringSubstr(name_base,::StringLen(this.NamePrefix()))+";"+ ::StringSubstr(this.Name(),::StringLen(this.NamePrefix())); //--- Send the event of clicking on the control to the control program chart bool res=true; ::ResetLastError(); res=::EventChartCustom(chart_id,event_id,lp,dp,sp); if(res) return true; ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_ENQUEUE_EVENT),". ",CMessage::Text(MSG_LIB_SYS_ERROR),": ",CMessage::Text(::GetLastError())); return false; } //+------------------------------------------------------------------+
取得に成功した基本オブジェクトがそれ自身の基本オブジェクトを持っている場合、その型を取得します。それ以外の場合は、基本オブジェクトの型を取得します。この修正前は、基本オブジェクトが自身の基本オブジェクトを持っていない場合(例えば、基本オブジェクトがメインの場合)、無効なポインタでオブジェクトにアクセスしたため、プログラムがクリティカルエラーで終了していました。現在は修正されています。
前回は、WinFormsの基本オブジェクトクラスのサイズ変更メソッドで、スクロールバーオブジェクトの位置を調整しました。オブジェクトのサイズを変更すると、その辺の座標が変化します。スクロールバーはオブジェクトの右下に結合されているため、必要に応じて座標を調整する必要があります。なぜなら、コンテナオブジェクトだけが添付オブジェクトを含むことができ、コンテナの可視領域に収まらない場合はスクロールが必要になることがあるからです。このような処理は、コンテナオブジェクトのクラスに移しましょう。ここは、それに最も適した場所なのです。
基本WinFormsオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqhファイルにある、 "Setting new sizes "メソッドにある 新しいサイズを設定するメソッドで、スクロールバーのサイズと座標を調整するコードブロックを削除します。
//+--------------------------------------------+ //| Set the new size for the current object | //+--------------------------------------------+ bool CWinFormBase::Resize(const int w,const int h,const bool redraw) { //--- If the object width and height are equal to the passed ones, return 'true' if(this.Width()==w && this.Height()==h) return true; //--- Declare the variable with the property change result bool res=true; //--- Save the panel initial size int prev_w=this.Width(); int prev_h=this.Height(); //--- Set the property change result to the 'res' variable //--- (if the property value is not equal to the passed value) if(this.Width()!=w) res &=this.SetWidth(w); if(this.Height()!=h) res &=this.SetHeight(h); if(!res) return false; //--- Get the vertical scrollbar and CWinFormBase *scroll_v=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); if(scroll_v!=NULL) { //--- change the vertical size to the size of the container workspace scroll_v.Resize(scroll_v.Width(),this.Height()-this.BorderSizeTop()-this.BorderSizeBottom(),false); //--- Get a button object with the down arrow from the vertical scrollbar object CWinFormBase *arr_d=scroll_v.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); //--- If the button has been received if(arr_d!=NULL) { //--- Move it to the bottom edge of the vertical scrollbar if(arr_d.Move(arr_d.CoordX(),scroll_v.BottomEdge()-2*arr_d.Height())) { arr_d.SetCoordXRelative(arr_d.CoordX()-scroll_v.CoordX()); arr_d.SetCoordYRelative(arr_d.CoordY()-scroll_v.CoordY()); } } } //--- Get the horizontal scrollbar and CWinFormBase *scroll_h=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); if(scroll_h!=NULL) { //--- change the horizontal size to the size of the container workspace scroll_h.Resize(this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(),scroll_h.Height(),false); //--- Get a button object with the right arrow from the horizontal scrollbar object CWinFormBase *arr_r=scroll_h.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0); //--- If the button has been received if(arr_r!=NULL) { //--- Move it to the right edge of the horizontal scrollbar if(arr_r.Move(scroll_h.RightEdge()-2*arr_r.Width(),arr_r.CoordY())) { arr_r.SetCoordXRelative(arr_r.CoordX()-scroll_h.CoordX()); arr_r.SetCoordYRelative(arr_r.CoordY()-scroll_h.CoordY()); } } } //--- Calculate the value, by which the size should be changed int excess_w=this.Width()-prev_w; int excess_h=this.Height()-prev_h; //--- Get the "Shadow" object CShadowObj *shadow=this.GetShadowObj(); //--- If the object has a shadow and the "Shadow" object has been received, if(this.IsShadow() && shadow!=NULL) { //--- save shadow shifts by X and Y, int x=shadow.CoordXRelative(); int y=shadow.CoordYRelative(); //--- set the shadow new width and height res &=shadow.SetWidth(shadow.Width()+excess_w); res &=shadow.SetHeight(shadow.Height()+excess_h); //--- If the res variable contains 'false', //--- there was a resize error - return 'false' if(!res) return false; //--- If there is no need to redraw, remove the shadow if(!redraw) shadow.Erase(); //--- Save the previously set shadow shift values relative to the panel shadow.SetCoordXRelative(x); shadow.SetCoordYRelative(y); } //--- Redraw the entire element with new size if(redraw) this.Redraw(true); //--- All is successful - return 'true' return true; } //+------------------------------------------------------------------+
このコードブロックは、コンテナオブジェクトのクラスに完全に移動されます。
要素の整数プロパティの説明を返すメソッドに、新しいグラフィック要素のプロパティの説明を返すコードブロックを追加します。
//+------------------------------------------------------------------+ //| Return the description of the control integer property | //+------------------------------------------------------------------+ string CWinFormBase::GetPropertyDescription(ENUM_CANV_ELEMENT_PROP_INTEGER property,bool only_prop=false) { return ( property==CANV_ELEMENT_PROP_ID ? CMessage::Text(MSG_CANV_ELEMENT_PROP_ID)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TYPE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TYPE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.TypeElementDescription() ) : //---... //---... property==CANV_ELEMENT_PROP_ENABLED ? CMessage::Text(MSG_CANV_ELEMENT_PROP_ENABLED)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)(bool)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_RESIZABLE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_RESIZABLE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)(bool)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_FORE_COLOR ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : //---... //---... property==CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED ? CMessage::Text(MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : "" ); } //+------------------------------------------------------------------+
ScrollBarコントロールのキャプチャ領域クラス
前回は、ScrollBarオブジェクトを作成する際に、そのスライダーにボタンオブジェクトクラスを使用しました。実際、このオブジェクトはこのような用途に適しています。しかし、イベントを処理する場合、正しいハンドラを呼び出すために、処理されるオブジェクトの型を知っておく必要があります。ボタンオブジェクトにはそのようなハンドラがありますが、スライダーには適していません。スライダーはずらす必要があります。そのシフトの間、スクロールバーによって可視範囲が制御されているオブジェクトの座標は再計算される必要があります。そこで、ボタンオブジェクトのクラスを元に、新しいクラスを作成することにします。キャプチャ領域オブジェクトのクラスです。そのオブジェクトの中に、必要なマウスイベントのハンドラを自作することができます。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ライブラリフォルダで、CScrollBarThumbクラスのファイルScrollBarThumb.mqhを新規作成します。
クラスはボタンオブジェクトクラスから派生するので、そのファイルを作成されたクラスファイルにインクルードする必要があります。
//+------------------------------------------------------------------+ //| ScrollBarThumb.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+--------------------------------------------+ //| Include files | //+--------------------------------------------+ #include "..\Common Controls\Button.mqh" //+--------------------------------------------+ //| Label object class of WForms controls | //+--------------------------------------------+ class CScrollBarThumb : public CButton { }
クラスのprotectedセクションでprotectedコンストラクタを宣言し、publicセクションでパラメトリックコンストラクタを宣言します。
//+--------------------------------------------+ //| Label object class of WForms controls | //+--------------------------------------------+ class CScrollBarThumb : public CButton { private: protected: //--- Protected constructor with object type, chart ID and subwindow CScrollBarThumb(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- Constructor CScrollBarThumb(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); }; //+------------------------------------------------------------------+
今のところ、このオブジェクトに必要なのはそれだけです。その型はクラスのコンストラクタで設定され、キャプチャ領域オブジェクトというユニークなものになります。
以下はprotectedコンストラクタです。
//+--------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+--------------------------------------------+ CScrollBarThumb::CScrollBarThumb(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CButton(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and assign the library object type to the current object this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true); this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN); this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER); this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true); this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN); this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER); } //+------------------------------------------------------------------+
コンストラクタは、親クラスのコンストラクタに渡された生成オブジェクトの型を受け取ります。グラフィック要素タイプとライブラリグラフィカルオブジェクトタイプはコンストラクタ本体に設定されます。さらに、マウスカーソルで操作する際のさまざまなオブジェクトの状態に対するすべてのデフォルトの色値も設定されています。
以下は、パラメトリックコンストラクタです。
//+------------------------------------------------------------------+ //| Constructor indicating the main and base objects, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CScrollBarThumb::CScrollBarThumb(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CButton(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true); this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN); this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER); this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true); this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN); this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER); } //+------------------------------------------------------------------+
ここでは、 オブジェクトの型がキャプチャ領域として厳格に設定されることを除いて、すべてがprotectedコンストラクタと同様です。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBar.mqhにあるスクロールバーオブジェクトの抽象クラスを改善してみましょう。
キャプチャ領域オブジェクトクラスファイルをインクルードします。privateセクションで、スクロールバーの幅を格納する変数を宣言し、protectedセクションで、スクロールボタンの大きさを設定するメソッドを宣言します。publicセクションで、スクロールバーの幅を設定して返すために、キャプチャ領域オブジェクトを返すメソッドと、スクロールバーボタンに描かれる矢印の大きさを設定するメソッドを宣言します。
//+------------------------------------------------------------------+ //| ScrollBar.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+--------------------------------------------+ //| Include files | //+--------------------------------------------+ #include "..\WinFormBase.mqh" #include "ScrollBarThumb.mqh" #include "ArrowDownButton.mqh" #include "ArrowUpButton.mqh" #include "ArrowLeftButton.mqh" #include "ArrowRightButton.mqh" //+--------------------------------------------+ //| CScrollBar object class of WForms controls | //+--------------------------------------------+ class CScrollBar : public CWinFormBase { private: int m_thickness; // Scrollbar width (Width - vertical, Height - horizontal) //--- Create the ArrowButton objects virtual void CreateArrowButtons(const int width,const int height) { return; } //--- Create a new graphical object virtual CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int element_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity); //--- Calculate the capture area size virtual int CalculateThumbAreaSize(void); //--- Initialize the element properties void Initialize(void); protected: //--- Set the scroll buttons size void SetArrowButtonsSize(const int size); //--- Create the capture area object virtual void CreateThumbArea(void); //--- Protected constructor with object type, chart ID and subwindow CScrollBar(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- Supported object properties (1) integer, (2) real and (3) string ones virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property) { return true; } //--- Return the capture area object CScrollBarThumb *GetThumb(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,0); } //--- (1) Set and (2) return the scrollbar width virtual void SetThickness(const int value); int Thickness(void) const { return this.m_thickness; } //--- Set the size of drawn arrows on scroll buttons void SetArrowSize(const uchar size); //--- Constructor CScrollBar(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); //--- Timer virtual void OnTimer(void); }; //+------------------------------------------------------------------+
要素プロパティの初期化メソッドに、デフォルトの色値、スクロールバーの幅、ボタンと矢印のサイズの設定を追加します。
//+--------------------------------------------+ //| Initialize the element properties | //+--------------------------------------------+ void CScrollBar::Initialize(void) { this.SetBorderSizeAll(1); this.SetBorderStyle(FRAME_STYLE_SIMPLE); this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR,true); this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR); this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR); this.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true); this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_DOWN); this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_OVER); this.SetThickness(DEF_CONTROL_SCROLL_BAR_WIDTH); this.SetArrowButtonsSize(this.m_thickness); this.SetArrowSize(uchar(this.m_thickness<4 ? 1 : this.m_thickness<6 ? 2 : this.m_thickness<8 ? 3 : this.m_thickness<10 ? 4 : this.m_thickness<12 ? 5 : 6)); } //+------------------------------------------------------------------+
新しいグラフィックオブジェクトを作成するメソッドで、キャプチャ領域オブジェクトを作成するためのコードブロックを実装します。
//+--------------------------------------------+ //| Create a new graphical object | //+--------------------------------------------+ CGCnvElement *CScrollBar::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { CGCnvElement *element=NULL; switch(type) { case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB : element=new CScrollBarThumb(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN : element=new CArrowDownButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP : element=new CArrowUpButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT : element=new CArrowLeftButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT : element=new CArrowRightButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; default: break; } if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type)); return element; } //+------------------------------------------------------------------+
これで、オブジェクトは、矢印ボタンオブジェクトに加え、コントロールインターフェイスを作成するためのスライダーも作成できるようになります。
以下は、スクロールバーの幅を設定するメソッドです。
//+--------------------------------------------+ //| Set the scrollbar width | //+--------------------------------------------+ void CScrollBar::SetThickness(const int value) { //--- Depending on the type switch(this.TypeGraphElement()) { //--- For the vertical scrollbar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL : //--- set the width equal to the value passed to the method and write it as the width of the object this.m_thickness=value; this.SetWidth(this.m_thickness); this.Redraw(false); break; //--- For the horizontal scroll bar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: //--- set the width equal to the value passed to the method and write it as the height of the object this.m_thickness=value; this.SetHeight(this.m_thickness); this.Redraw(false); break; default: break; } } //+------------------------------------------------------------------+
垂直スクロールバーの場合、オブジェクトの幅はバーの幅とみなされます。水平スクロールバーの場合、オブジェクトの幅はその高さになります。このメソッドは、オブジェクトに設定される値を受け取ります。スクロールバーの種類によって、幅と高さのどちらかが設定されます。
以下は、スクロールボタンの大きさを設定するメソッドです。
//+--------------------------------------------+ //| Set the size of the scroll buttons | //+--------------------------------------------+ void CScrollBar::SetArrowButtonsSize(const int size) { //--- Declare the pointers to arrow buttons CArrowUpButton *bu=NULL; CArrowDownButton *bd=NULL; CArrowLeftButton *bl=NULL; CArrowRightButton *br=NULL; //--- Depending on the type switch(this.TypeGraphElement()) { //--- For the vertical scrollbar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL : //--- Get the pointer to the up arrow button and set its size equal to 'size' bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0); if(bu!=NULL) bu.Resize(size,size,false); //--- Get the pointer to the down arrow button and set its size equal to 'size' bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); if(bd!=NULL) bd.Resize(size,size,false); break; //--- For the horizontal scroll bar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: //--- Get the pointer to the left arrow button and set its size equal to 'size' bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0); if(bl!=NULL) bl.Resize(size,size,false); //--- Get the pointer to the right arrow button and set its size equal to 'size' br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0); if(br!=NULL) br.Resize(size,size,false); break; default: break; } } //+------------------------------------------------------------------+
スクロールバーオブジェクトのボタンは、同じ辺を持ちます。サイズはメソッドに渡され、オブジェクトの種類に応じて、左/右または上/下ボタンへのポインタを取得し、それらにメソッドに渡されたサイズを設定します(幅と高さの両方について)。
以下は、スクロールボタンに描画される矢印の大きさを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the size of drawn arrows on scroll buttons | //+------------------------------------------------------------------+ void CScrollBar::SetArrowSize(const uchar size) { //--- Declare the pointers to arrow buttons CArrowUpButton *bu=NULL; CArrowDownButton *bd=NULL; CArrowLeftButton *bl=NULL; CArrowRightButton *br=NULL; //--- Depending on the type switch(this.TypeGraphElement()) { //--- For the vertical scrollbar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL : //--- Get the pointer to the up arrow button and set its arrow size equal to 'size' bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0); if(bu!=NULL) { bu.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size); bu.Redraw(false); } //--- Get the pointer to the down arrow button and set its arrow size equal to 'size' bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); if(bd!=NULL) { bd.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size); bd.Redraw(false); } break; //--- For the horizontal scroll bar case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: //--- Get the pointer to the left arrow button and set its arrow size equal to 'size' bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0); if(bl!=NULL) { bl.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size); bl.Redraw(false); } //--- Get the pointer to the right arrow button and set its arrow size equal to 'size' br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0); if(br!=NULL) { br.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size); br.Redraw(false); } break; default: break; } } //+------------------------------------------------------------------+
スクロールバーの種類に応じて、対応するボタンへのポインタを取得し、それらに対応する描画された矢印のサイズを設定し、オブジェクトを再描画して変更を表示します。
スクロールバースライダーは、コンテナの可視範囲内でコンテナの内容をスクロールさせるために使用されます。マウスでスライダーを動かす場合、スクロールバーからはみ出さないように、移動範囲をスクロールにも使われる矢印ボタンに限定する必要があります。垂直スクロールバーオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBarVertical.mqhにキャプチャ領域オブジェクトクラスファイルを追加します。publicセクションで、矢印ボタンへのポインタを返すメソッドを実装し、イベントハンドラを宣言します。
//+------------------------------------------------------------------+ //| ScrollBarVertical.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+--------------------------------------------+ //| Include files | //+--------------------------------------------+ #include "ScrollBarThumb.mqh" #include "ArrowDownButton.mqh" #include "ArrowUpButton.mqh" #include "ScrollBar.mqh" //+------------------------------------------------------------------+ //| CScrollBarVertical object class of WForms controls | //+------------------------------------------------------------------+ class CScrollBarVertical : public CScrollBar { private: //--- Create the ArrowButton objects virtual void CreateArrowButtons(const int width,const int height); //--- Calculate the capture area size virtual int CalculateThumbAreaSize(void); protected: //--- Protected constructor with object type, chart ID and subwindow CScrollBarVertical(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- Supported object properties (1) integer, (2) real and (3) string ones virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property) { return true; } //--- Return the button with the (1) up, (2) down arrow CArrowUpButton *GetArrowButtonUp(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0); } CArrowDownButton *GetArrowButtonDown(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); } //--- Constructor CScrollBarVertical(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); //--- Timer virtual void OnTimer(void); //--- Event handler virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam); }; //+------------------------------------------------------------------+
ArrowButtonオブジェクトを作成するメソッドでは、すべてのボタンとスライダーを作成し、それらへのポインタを取得し、異なるマウス操作の状態に応じた色を設定しています。
//+--------------------------------------------+ //| Create the ArrowButton objects | //+--------------------------------------------+ void CScrollBarVertical::CreateArrowButtons(const int width,const int height) { //--- Set the size of the buttons equal to the width of the scrollbar without the size of its frame int size=this.Thickness()-this.BorderSizeLeft()-this.BorderSizeRight(); //--- Create the buttons with up and down arrows and the area capture object. The arrow size is set to 2 this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP, 0,0,size,size,this.BackgroundColor(),255,true,false); this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0,this.BottomEdge()-this.BorderSizeBottom()-2*size,size,size,this.BackgroundColor(),255,true,false); this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,0,this.Height()/2-height,size,30,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false); this.SetArrowSize(2); //--- Get the pointer to the up arrow button and set the colors of its various states for it CArrowUpButton *bu=this.GetArrowButtonUp(); if(bu!=NULL) { bu.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true); bu.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN); bu.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER); bu.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true); bu.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN); bu.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER); } //--- Get the pointer to the down arrow button and set the colors of its various states for it CArrowDownButton *bd=this.GetArrowButtonDown(); if(bd!=NULL) { bd.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true); bd.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN); bd.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER); bd.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true); bd.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN); bd.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER); } //--- Get the pointer to the capture area object and set the colors of its various states for it CScrollBarThumb *th=this.GetThumb(); if(th!=NULL) { th.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true); th.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true); th.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN); th.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER); th.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true); th.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN); th.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER); } } //+------------------------------------------------------------------+
イベントハンドラで、プログレスバースライダーオブジェクトを移動させるとき、スクロールバーの端にあるボタンで制限されるべき座標を計算します。
//+--------------------------------------------+ //| Event handler | //+--------------------------------------------+ void CScrollBarVertical::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Adjust subwindow Y shift CGCnvElement::OnChartEvent(id,lparam,dparam,sparam); //--- If the event ID is an object movement if(id==WF_CONTROL_EVENT_MOVING) { //--- Get the pointer to the capture area object CScrollBarThumb *thumb=this.GetThumb(); if(thumb==NULL) return; //--- Get the pointer to the button object with the up arrow CArrowUpButton *buttu=this.GetArrowButtonUp(); if(buttu==NULL) return; //--- Get the pointer to the button object with the down arrow CArrowDownButton *buttd=this.GetArrowButtonDown(); if(buttd==NULL) return; //--- Declare the variables for the coordinates of the capture area int x=(int)lparam; int y=(int)dparam; //--- Set the X coordinate equal to the X coordinate of the control element x=this.CoordX()+this.BorderSizeLeft(); //--- Adjust the Y coordinate so that the capture area does not go beyond the control, taking into account the arrow buttons if(y<buttu.BottomEdge()) y=buttu.BottomEdge(); if(y>buttd.CoordY()-thumb.Height()) y=buttd.CoordY()-thumb.Height(); //--- If the capture area object is shifted by the calculated coordinates if(thumb.Move(x,y,true)) { //--- set the object relative coordinates thumb.SetCoordXRelative(thumb.CoordX()-this.CoordX()); thumb.SetCoordYRelative(thumb.CoordY()-this.CoordY()); ::ChartRedraw(this.ChartID()); } } } //+------------------------------------------------------------------+
ScrollBarHorisontal.mqhファイルの水平スクロールバーオブジェクトのクラスにも同様の改良が施されています。
ボタンとスライダーのオブジェクトを作成する方法とイベントハンドラが上記の方法と異なるのは、他の種類のボタンへのポインタとスライダー移動の他の軸の制限だけです。
//+--------------------------------------------+ //| Create the ArrowButton objects | //+--------------------------------------------+ void CScrollBarHorisontal::CreateArrowButtons(const int width,const int height) { int size=this.Thickness()-this.BorderSizeTop()-this.BorderSizeBottom(); this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT, 0,0,size,size,this.BackgroundColor(),255,true,false); this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,this.RightEdge()-this.BorderSizeRight()-2*size,0,size,size,this.BackgroundColor(),255,true,false); this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,this.Width()/2-width,0,30,size,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false); this.SetArrowSize(2); CArrowLeftButton *bl=this.GetArrowButtonLeft(); if(bl!=NULL) { bl.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true); bl.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN); bl.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER); bl.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true); bl.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN); bl.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER); } CArrowRightButton *br=this.GetArrowButtonRight(); if(br!=NULL) { br.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true); br.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN); br.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER); br.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true); br.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN); br.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER); } CScrollBarThumb *th=this.GetThumb(); if(th!=NULL) { th.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true); th.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true); th.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN); th.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER); th.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true); th.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN); th.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER); } } //+------------------------------------------------------------------+ //+--------------------------------------------+ //| Event handler | //+--------------------------------------------+ void CScrollBarHorisontal::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Adjust subwindow Y shift CGCnvElement::OnChartEvent(id,lparam,dparam,sparam); //--- If the event ID is an object movement if(id==WF_CONTROL_EVENT_MOVING) { //--- Get the pointer to the capture area object CScrollBarThumb *thumb=this.GetThumb(); if(thumb==NULL) return; //--- Get the pointer to the button object with the left arrow CArrowLeftButton *buttl=this.GetArrowButtonLeft(); if(buttl==NULL) return; //--- Get the pointer to the button object with the right arrow CArrowRightButton *buttr=this.GetArrowButtonRight(); if(buttr==NULL) return; //--- Declare the variables for the coordinates of the capture area int x=(int)lparam; int y=(int)dparam; //--- Set the Y coordinate equal to the Y coordinate of the control element y=this.CoordY()+this.BorderSizeTop(); //--- Adjust the X coordinate so that the capture area does not go beyond the control, taking into account the arrow buttons if(x<buttl.RightEdge()) x=buttl.RightEdge(); if(x>buttr.CoordX()-thumb.Width()) x=buttr.CoordX()-thumb.Width(); //--- If the capture area object is shifted by the calculated coordinates if(thumb.Move(x,y,true)) { //--- set the object relative coordinates thumb.SetCoordXRelative(thumb.CoordX()-this.CoordX()); thumb.SetCoordYRelative(thumb.CoordY()-this.CoordY()); ::ChartRedraw(this.ChartID()); } } } //+------------------------------------------------------------------+
MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqhのパネルオブジェクトクラスを改善します。
publicセクションで、オブジェクトのサイズを変更するための仮想メソッドを宣言します。
//--- Set the (1) X, (2) Y coordinates, (3) element width and (4) height virtual bool SetCoordX(const int coord_x) { return CGCnvElement::SetCoordX(coord_x); } virtual bool SetCoordY(const int coord_y) { return CGCnvElement::SetCoordY(coord_y); } virtual bool SetWidth(const int width) { return CGCnvElement::SetWidth(width); } virtual bool SetHeight(const int height) { return CGCnvElement::SetHeight(height); } //--- Set the new size for the (1) current object and (2) the object specified by index virtual bool Resize(const int w,const int h,const bool redraw); //--- Create a new attached element
このメソッドは、ベースとなるWinFormsオブジェクトクラスから削除されたコードブロックを受け取ります。
クラスのコンストラクタで、ライブラリ用にデフォルトで実装されている作成済みスクロールバーのサイズを設定し、下部スクロールバーの領域を設定します。右スクロールバーの領域は、まず下のバーの機能を洗練させる必要があるので、設定しないことにしています。すると、結果は右のスクロールバーオブジェクトに移動します。
//+--------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+--------------------------------------------+ CContainer::CContainer(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CWinFormBase(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and assign the library object type to the current object this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER; this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetFontBoldType(FW_TYPE_NORMAL); this.SetMarginAll(3); this.SetPaddingAll(0); this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false); this.SetBorderStyle(FRAME_STYLE_NONE); this.SetAutoScroll(false,false); this.SetAutoScrollMarginAll(0); this.SetAutoSize(false,false); this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false); this.Initialize(); this.SetCoordXInit(x); this.SetCoordYInit(y); this.SetWidthInit(w); this.SetHeightInit(h); this.CreateScrollBars(DEF_CONTROL_SCROLL_BAR_WIDTH); this.SetScrollAreaBottomX(this.CoordX()); this.SetScrollAreaBottomY(this.BottomEdge()-DEF_CONTROL_SCROLL_BAR_WIDTH); this.SetScrollAreaBottomHeight(DEF_CONTROL_SCROLL_BAR_WIDTH); } //+------------------------------------------------------------------+ //| Constructor indicating the main and base objects, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CContainer::CContainer(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CWinFormBase(GRAPH_ELEMENT_TYPE_WF_CONTAINER,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CONTAINER); this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER; this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetFontBoldType(FW_TYPE_NORMAL); this.SetMarginAll(3); this.SetPaddingAll(0); this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false); this.SetBorderStyle(FRAME_STYLE_NONE); this.SetAutoScroll(false,false); this.SetAutoScrollMarginAll(0); this.SetAutoSize(false,false); this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false); this.Initialize(); this.SetCoordXInit(x); this.SetCoordYInit(y); this.SetWidthInit(w); this.SetHeightInit(h); this.CreateScrollBars(DEF_CONTROL_SCROLL_BAR_WIDTH); this.SetScrollAreaBottomX(this.CoordX()); this.SetScrollAreaBottomY(this.BottomEdge()-DEF_CONTROL_SCROLL_BAR_WIDTH); this.SetScrollAreaBottomHeight(DEF_CONTROL_SCROLL_BAR_WIDTH); } //+------------------------------------------------------------------+
添付されたオブジェクトにパラメータを設定するメソッドで、新しく作成されたキャプチャ領域オブジェクトのデフォルトパラメータを設定するコードブロックを記述します。
//+--------------------------------------------+ //| Set parameters for the attached object | //+--------------------------------------------+ void CContainer::SetObjParams(CWinFormBase *obj,const color colour) { //--- Set the text color of the object to be the same as that of the base container obj.SetForeColor(this.ForeColor(),true); //--- If the created object is not a container, set the same group for it as the one for its base object if(obj.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_CONTAINER || obj.TypeGraphElement()>GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) obj.SetGroup(this.Group()); //--- Depending on the object type switch(obj.TypeGraphElement()) { //--- For the Container, Panel and GroupBox WinForms objects case GRAPH_ELEMENT_TYPE_WF_CONTAINER : case GRAPH_ELEMENT_TYPE_WF_PANEL : case GRAPH_ELEMENT_TYPE_WF_GROUPBOX : obj.SetBorderColor(obj.BackgroundColor(),true); break; //--- For "Label", "CheckBox" and "RadioButton" WinForms objects case GRAPH_ELEMENT_TYPE_WF_LABEL : case GRAPH_ELEMENT_TYPE_WF_CHECKBOX : case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON : obj.SetForeColor(colour==clrNONE ? this.ForeColor() : colour,true); obj.SetBorderColor(obj.ForeColor(),true); obj.SetBackgroundColor(CLR_CANV_NULL,true); obj.SetOpacity(0,false); break; //--- For "Button", "TabHeader", TabField and "ListBoxItem" WinForms objects case GRAPH_ELEMENT_TYPE_WF_BUTTON : case GRAPH_ELEMENT_TYPE_WF_TAB_HEADER : case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD : case GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM : obj.SetForeColor(this.ForeColor(),true); obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_STD_BACK_COLOR : colour,true); obj.SetBorderColor(obj.ForeColor(),true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; //--- For "ListBox", "CheckedListBox" and "ButtonListBox" WinForms object case GRAPH_ELEMENT_TYPE_WF_LIST_BOX : case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX : case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX : obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_STD_BACK_COLOR : colour,true); obj.SetBorderColor(CLR_DEF_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); break; //--- For "TabControl" WinForms object case GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL : obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_TAB_BACK_COLOR : colour,true); obj.SetBorderColor(CLR_DEF_CONTROL_TAB_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(CLR_DEF_CONTROL_TAB_OPACITY); break; //--- For "SplitContainer" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER : obj.SetBackgroundColor(colour==clrNONE ? CLR_CANV_NULL : colour,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(0); break; //--- For "SplitContainerPanel" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL: obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_SPLIT_CONTAINER_BACK_COLOR : colour,true); obj.SetBorderColor(CLR_DEF_CONTROL_SPLIT_CONTAINER_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); break; //--- For "Splitter" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLITTER : obj.SetBackgroundColor(colour==clrNONE ? CLR_CANV_NULL : colour,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(0); obj.SetDisplayed(false); obj.Hide(); break; //--- For the "ArrowButton" WinForms object case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT : obj.SetBorderColor(CLR_DEF_CONTROL_TAB_HEAD_BORDER_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; //--- For "Hint" WinForms object case GRAPH_ELEMENT_TYPE_WF_HINT_BASE : obj.SetBackgroundColor(CLR_CANV_NULL,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_CANV_NULL,true); obj.SetOpacity(0,false); obj.SetBorderStyle(FRAME_STYLE_NONE); break; //--- For "HintMoveLeft", "HintMoveRight", "HintMoveUp" and "HintMoveDown" WinForms object case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT : case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT : case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : obj.SetBackgroundColor(CLR_CANV_NULL,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true); obj.SetOpacity(0,false); obj.SetBorderStyle(FRAME_STYLE_NONE); break; //--- For ToolTip WinForms object case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : obj.SetBackgroundColor(CLR_DEF_CONTROL_HINT_BACK_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_HINT_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); obj.SetOpacity(0,false); obj.SetDisplayed(false); obj.Hide(); break; //--- For BarProgressBar WinForms object case GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR : obj.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_NONE); break; //--- For ProgressBar WinForms object case GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR : obj.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; //--- For ScrollBar WinForms object case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR : case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL : obj.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true); obj.SetBorderSizeAll(1); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; //--- For the ScrollBarThumb WinForms object case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB : obj.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true); obj.SetBorderSizeAll(0); obj.SetBorderStyle(FRAME_STYLE_NONE); break; //--- For GlareObj WinForms object case GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ : obj.SetBackgroundColor(CLR_CANV_NULL,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_CANV_NULL,true); obj.SetBorderStyle(FRAME_STYLE_NONE); break; default: break; } obj.Crop(); } //+------------------------------------------------------------------+
コンテナに付属する作成された各オブジェクトについて、そのオブジェクトを表示するために必要な最低限のパラメータを設定するコードブロックがここにあります。
コンテナオブジェクト内のオブジェクトは、自動的に所定の順序で並べられたり、コンテナのサイズに合わせて大きさが調整されたりするため、このように扱われるオブジェクトは、コンテナオブジェクトと一体であり、その中身ではないため、スクロールバーを削除する必要があります。
要素のサイズを内側の内容に合わせて調整するメソッドでは、スクロールバーオブジェクトを処理対象から除外します。
//+--------------------------------------------+ //| Adjust the element size to fit its content | //+--------------------------------------------+ bool CContainer::AutoSizeProcess(const bool redraw) { //--- Get the list of bound objects with WinForms type basic and higher CArrayObj *list=this.GetListWinFormsObj(); int maxcX=0; int maxcY=0; //--- Calculate the maximum coordinate of the right and bottom edge from all bound objects for(int i=0;i<list.Total();i++) { CWinFormBase *obj=list.At(i); if(obj==NULL || obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR || obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL || obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL ) continue; if(obj.RightEdge()>maxcX) maxcX=obj.RightEdge(); if(obj.BottomEdge()>maxcY) maxcY=obj.BottomEdge(); } //--- Calculate the required width and height of the panel after adjusting its size to the content int w=maxcX-this.CoordX(); int h=maxcY-this.CoordY(); //--- Calculate the number of pixels, by which we need to resize the container in width and height int excess_x=w-this.WidthWorkspace()-this.BorderSizeRight()-1; int excess_y=h-this.HeightWorkspace()-this.BorderSizeBottom()-1; //--- If failed to change the container size, return 'true' if(excess_x==0 && excess_y==0) return true; //--- Return the result of resizing the container return ( //--- In case of size increase only this.AutoSizeMode()==CANV_ELEMENT_AUTO_SIZE_MODE_GROW ? this.Resize(this.Width()+(excess_x>0 ? excess_x : 0),this.Height()+(excess_y>0 ? excess_y : 0),redraw) : //--- if both increase and decrease this.Resize(this.Width()+(excess_x!=0 ? excess_x : 0),this.Height()+(excess_y!=0 ? excess_y : 0),redraw) ); } //+------------------------------------------------------------------+
以下は、現在のオブジェクトの新しいサイズを設定するメソッドです。
//+--------------------------------------------+ //| Set the new size for the current object | //+--------------------------------------------+ bool CContainer::Resize(const int w,const int h,const bool redraw) { //--- If it was not possible to change the size of the container, return 'false' if(!CWinFormBase::Resize(w,h,redraw)) return false; //--- Get the vertical scrollbar and CWinFormBase *scroll_v=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); if(scroll_v!=NULL) { //--- change the vertical size to the size of the container workspace scroll_v.Resize(scroll_v.Width(),this.HeightWorkspace(),false); //--- Move the vertical scrollbar to new coordinates if(scroll_v.Move(this.RightEdgeWorkspace()-scroll_v.Width(),this.CoordYWorkspace())) { scroll_v.SetCoordXRelative(scroll_v.CoordX()-this.CoordX()); scroll_v.SetCoordYRelative(scroll_v.CoordY()-this.CoordY()); } //--- Get a button object with the down arrow from the vertical scrollbar object CWinFormBase *arr_d=scroll_v.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); //--- If the button has been received if(arr_d!=NULL) { //--- Move it to the bottom edge of the vertical scrollbar if(arr_d.Move(arr_d.CoordX(),scroll_v.BottomEdge()-scroll_v.BorderSizeBottom()-2*arr_d.Height())) { arr_d.SetCoordXRelative(arr_d.CoordX()-scroll_v.CoordX()); arr_d.SetCoordYRelative(arr_d.CoordY()-scroll_v.CoordY()); } } } //--- Get the horizontal scrollbar and CWinFormBase *scroll_h=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); if(scroll_h!=NULL) { //--- change the horizontal size to the size of the container workspace scroll_h.Resize(this.WidthWorkspace(),scroll_h.Height(),false); //--- Move the horizontal scrollbar to new coordinates if(scroll_h.Move(this.CoordXWorkspace(),this.BottomEdgeWorkspace()-scroll_h.Height())) { scroll_h.SetCoordXRelative(scroll_h.CoordX()-this.CoordX()); scroll_h.SetCoordYRelative(scroll_h.CoordY()-this.CoordY()); } //--- Get a button object with the right arrow from the horizontal scrollbar object CWinFormBase *arr_r=scroll_h.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0); //--- If the button has been received if(arr_r!=NULL) { //--- Move it to the right edge of the horizontal scrollbar if(arr_r.Move(scroll_h.RightEdge()-BorderSizeRight()-2*arr_r.Width(),arr_r.CoordY())) { arr_r.SetCoordXRelative(arr_r.CoordX()-scroll_h.CoordX()); arr_r.SetCoordYRelative(arr_r.CoordY()-scroll_h.CoordY()); } } } return true; } //+------------------------------------------------------------------+
この仮想メソッドは、コンテナオブジェクトのサイズを変更します。WinFormsオブジェクトの基本クラスから削除されたコードのブロックをその中に移動させました。まず、WinFormsオブジェクトのリサイズメソッドを呼び出します。その後、成功すれば、両方のスクロールバーのサイズと座標をコンテナの新しいサイズと座標に調整します。
\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhのグラフィック要素のコレクションクラスを改善しましょう。
キャプチャ領域オブジェクト(スクロールバースライダー)を動かしたときに、そのイベントハンドラを呼び出すために、ライブラリにその動きをメッセージで伝える必要があります。SplitContainerオブジェクトでセパレータを移動させることができるのです。つまり、セパレータの移動が処理されるコードメソッドに、移動とスライダーの処理を追加する必要があるのです。
セパレータ処理ブロックのイベントハンドラでスライダー処理を追加します。
//--- In case of the mouse movement event if(id==CHARTEVENT_MOUSE_MOVE) { //--- If the cursor is above the form if(::CheckPointer(form)!=POINTER_INVALID) { //--- If the move flag is set if(move) { //--- calculate the cursor movement relative to the form coordinate origin int x=this.m_mouse.CoordX()-form.OffsetX(); int y=this.m_mouse.CoordY()-form.OffsetY(); //--- get the width and height of the chart the form is located at int chart_width=(int)::ChartGetInteger(form.ChartID(),CHART_WIDTH_IN_PIXELS,form.SubWindow()); int chart_height=(int)::ChartGetInteger(form.ChartID(),CHART_HEIGHT_IN_PIXELS,form.SubWindow()); //--- If the form is not within an extended standard graphical object if(form_index==WRONG_VALUE) { //--- If the form is a separator object, if(form.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SPLITTER || form.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB) { //--- get its base object CWinFormBase *base=form.GetBase(); if(base==NULL) return; //--- and send the "Object movement" event to the event handler of the base object const long lp=x; const double dp=y; base.OnChartEvent(WF_CONTROL_EVENT_MOVING,lp,dp,sparam); }
マウスイベント名が変更されたすべてのイベントハンドラを変更し、追加します。
//+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the active area, the left mouse button is clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED,lparam,dparam,sparam); } //+------------------------------------------------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area to the right, no mouse buttons are clicked' event handler | //+------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED,lparam,dparam,sparam); } //+------------------------------------------------------------------------------------------------------------+ //|'The cursor is inside the window scrolling area to the right, a mouse button is clicked (any)' event handler| //+------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED,lparam,dparam,sparam); } //+--------------------------------------------------------------------------------------------------------------+ //|'The cursor is inside the window scrolling area to the right, the mouse wheel is being scrolled' event handler| //+--------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL,lparam,dparam,sparam); } //+-------------------------------------------------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area at the bottom, no mouse buttons are clicked' event handler | //+-------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED,lparam,dparam,sparam); } //+-------------------------------------------------------------------------------------------------------------+ //|'The cursor is inside the window scrolling area at the bottom, a mouse button is clicked (any)' event handler| //+-------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------------------------+ //|'The cursor is inside the window scrolling area at the bottom, the mouse wheel is being scrolled' event handler| //+---------------------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the control area, no mouse buttons are clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+
検証
テストを実行するには、前の記事のEAを\MQL5\Experts\TestDoEasy\Part130\TestDoEasy130.mq5として保存します。
パネル上のすべてのオブジェクトの作成と、パネル上のスクロールバーの機能をテストするための大きなボタンを1つだけコメントアウトします。
//+--------------------------------------------+ //| Expert initialization function | //+--------------------------------------------+ int OnInit() { //--- Set EA global variables ArrayResize(array_clr,2); // Array of gradient filling colors array_clr[0]=C'26,100,128'; // Original ≈Dark-azure color array_clr[1]=C'35,133,169'; // Lightened original color //--- Create the array with the current symbol and set it to be used in the library string array[1]={Symbol()}; engine.SetUsedSymbols(array); //--- Create the timeseries object for the current symbol and period, and show its description in the journal engine.SeriesCreate(Symbol(),Period()); engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions //--- Create the required number of WinForms Panel objects CPanel *pnl=NULL; for(int i=0;i<FORMS_TOTAL;i++) { pnl=engine.CreateWFPanel("WinForms Panel"+(string)i,(i==0 ? 50 : 70),(i==0 ? 50 : 70),410,200,array_clr,200,true,true,false,-1,FRAME_STYLE_BEVEL,true,false); if(pnl!=NULL) { pnl.Hide(); //--- Set Padding to 4 pnl.SetPaddingAll(3); //--- Set the flags of relocation, auto resizing and auto changing mode from the inputs pnl.SetMovable(InpMovable); pnl.SetAutoSize(InpAutoSize,false); pnl.SetAutoSizeMode((ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)InpAutoSizeMode,false); //--- pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON,10,10,pnl.WidthWorkspace()-20,pnl.HeightWorkspace()-20,clrNONE,255,true,false); /* //--- Create TabControl pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false); CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); if(tc!=NULL) { tc.SetTabSizeMode((ENUM_CANV_ELEMENT_TAB_SIZE_MODE)InpTabPageSizeMode); tc.SetAlignment((ENUM_CANV_ELEMENT_ALIGNMENT)InpHeaderAlignment); tc.SetMultiline(InpTabCtrlMultiline); tc.SetHeaderPadding(6,0); tc.CreateTabPages(15,0,56,20,TextByLanguage("Вкладка","TabPage")); //--- Create Tooltip for the Left button tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false); CToolTip *tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0); if(tooltip!=NULL) { tooltip.SetDescription("Left Button Tooltip"); tooltip.SetIcon(InpTooltipIcon); tooltip.SetTitle(InpTooltipTitle); tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков вправо","Click to scroll headings to the right")); tc.AddTooltipToArrowLeftButton(tooltip); } //--- Create Tooltip for the Right button tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false); tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,1); if(tooltip!=NULL) { tooltip.SetDescription("Right Button Tooltip"); tooltip.SetIcon(ENUM_CANV_ELEMENT_TOOLTIP_ICON(InpTooltipIcon+1)); tooltip.SetTitle(InpTooltipTitle); tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков влево","Click to scroll headings to the left")); tc.AddTooltipToArrowRightButton(tooltip); } //--- Create a text label with a tab description on each tab for(int j=0;j<tc.TabPages();j++) { tc.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_LABEL,322,120,80,20,clrDodgerBlue,255,true,false); CLabel *label=tc.GetTabElementByType(j,GRAPH_ELEMENT_TYPE_WF_LABEL,0); if(label==NULL) continue; //--- If this is the very first tab, then there will be no text label.SetText(j<5 ? "" : "TabPage"+string(j+1)); } for(int n=0;n<5;n++) { //--- Create a SplitContainer control on each tab tc.CreateNewElement(n,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,10,10,tc.Width()-22,tc.GetTabField(0).Height()-22,clrNONE,255,true,false); //--- Get the SplitContainer control from each tab CSplitContainer *split_container=tc.GetTabElementByType(n,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0); if(split_container!=NULL) { //--- The separator will be vertical for each even tab and horizontal for each odd one split_container.SetSplitterOrientation(n%2==0 ? CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL,true); //--- The separator distance on each tab will be 50 pixels split_container.SetSplitterDistance(50,true); //--- The width of the separator on each subsequent tab will increase by 2 pixels split_container.SetSplitterWidth(6+2*n,false); //--- Make a fixed separator for the tab with index 2, and a movable one for the rest split_container.SetSplitterFixed(n==2 ? true : false); //--- For a tab with index 3, the second panel will be in a collapsed state (only the first one is visible) if(n==3) split_container.SetPanel2Collapsed(true); //--- For a tab with index 4, the first panel will be in a collapsed state (only the second one is visible) if(n==4) split_container.SetPanel1Collapsed(true); //--- On each of the control panels... for(int j=0;j<2;j++) { //--- Get the panel by loop index CSplitContainerPanel *panel=split_container.GetPanel(j); if(panel==NULL) continue; //--- set its description for the panel panel.SetDescription(TextByLanguage("Панель","Panel")+string(j+1)); //--- If this is the first tab and the second panel if(n==0 && j==1) { //--- Create the ProgressBar control on it if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,4,4,100,12,clrNONE,255,false,false)) { CProgressBar *progress_bar=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); if(progress_bar!=NULL) { //--- Set the style of the progress bar specified in the EA settings progress_bar.SetStyle((ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)InpProgressBarStyle); //--- Set the parameters for describing the progress bar progress_bar.SetBarDescriptionText("Progress Bar "); progress_bar.SetBarDescriptionColor(panel.BackgroundColor()); progress_bar.SetBarDescriptionOpacity(255); progress_bar.SetBarDescriptionY(-2); } } } //--- ...create a text label with the panel name if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_LABEL,4,4,panel.Width()-8,panel.Height()-8,clrDodgerBlue,255,true,false)) { CLabel *label=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_LABEL,0); if(label==NULL) continue; label.SetTextAlign(ANCHOR_CENTER); label.SetText(panel.Description()); } } } } } */ } } //--- Display and redraw all created panels for(int i=0;i<FORMS_TOTAL;i++) { //--- Get the panel object pnl=engine.GetWFPanel("WinForms Panel"+(string)i); if(pnl!=NULL) { //--- display and redraw the panel pnl.Show(); pnl.Redraw(true); //--- Get the pointer to the vertical scrollbar object of the main panel CScrollBarVertical *sbv=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); //--- Set the display flag for the object and show the scrollbar sbv.SetDisplayed(true); sbv.Show(); sbv.BringToTop(); sbv.Redraw(true); //--- Get the pointer to the horizontal scrollbar object of the main panel CScrollBarHorisontal *sbh=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); //--- Set the display flag for the object and show the scrollbar sbh.SetDisplayed(true); sbh.Show(); sbh.BringToTop(); sbh.Redraw(true); /* //--- Get the TabControl object from the panel CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); //--- Get the SplitContainer object from the first tab of the TabControl object CSplitContainer *sc=tc.GetTabElementByType(0,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0); //--- Get the second panel from the SplitContainer object CSplitContainerPanel *scp=sc.GetPanel(1); //--- Get the ProgressBar object from the received panel CProgressBar *pb=scp.GetElementByType(GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); //--- Waiting Sleep(1); //--- Get the width of the ProgressBar object int w=pb.Width(); //--- In the loop, increase the width of the ProgressBar by 180 pixels for(int n=0;n<180;n++) { //Sleep(1); pb.Resize(w+n,pb.Height(),true); } //--- Set the values for PerformStep of the ProgressBar object pb.SetValuesForProcessing(0,350,1,0); //--- Reset ProgressBar to minimum pb.ResetProgressBar(); //--- If the style of the progress bar is "Continuous line", display the progress bar description if(pb.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) pb.ShowBarDescription(); //--- Waiting Sleep(1); //--- If the style of the progress bar is not "Continuous scrolling" if(pb.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { //--- In the loop from the minimum to the maximum value of ProgressBar for(int n=0;n<=pb.Maximum();n++) { //--- call the method for increasing the progress bar by a given step with a wait of 1/5 second pb.PerformStep(); //--- Set the number of completed steps in the description of the progress bar pb.SetBarDescriptionText("Progress Bar, pass: "+(InpProgressBarPercent ? pb.ValuePercentDescription() : pb.ValueDescription())); Sleep(1); } } //--- Wait, set the description font type to Bold and write a completion message on the progress bar Sleep(1); pb.SetBarDescriptionFontFlags(FW_BOLD); pb.SetBarDescriptionText("Progress Bar: Done"); //--- Set the glare object type - rectangle, opacity 40, color - white pb.SetGlareStyle(CANV_ELEMENT_VISUAL_EFF_STYLE_RECTANGLE); pb.SetGlareOpacity(40); pb.SetGlareColor(clrWhite); */ } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
EAをコンパイルし、チャート上で起動します。
見ての通り、スライダーは矢印ボタンによってスクロールバー内で適切に拘束されています。矢印ボタンはクリックに反応し、オブジェクトの色はインタラクション中のオブジェクトとカーソルの状態に応じて変化します。
また、オブジェクトを選択すると、スクロールバーの枠が消えてしまうという欠点もあります。これは、オブジェクトの再描画と、スクロールバーが先に作成され優先順位がないため、他のオブジェクトより下にあることが原因で発生します。また、スクロールバー上の矢印ボタンをクリックして選択することも困難です。同じ理由で、先にオブジェクトが作成され、後から作成された他のオブジェクト(大きなボタン)が重なっています。これは後ですべて修正します。現時点では、欠点を見て、その原因を理解し、それを解消するために何をすべきかを考えることが重要です。
次の段階
次の記事では、フォームオブジェクトクラスの開発を続けます。
連載のこれまでの記事
DoEasy-コントロール(第26部):ToolTipWinFormsオブジェクトの最終確認とProgressBar開発の開始
DoEasy-コントロール(第27部):ProgressBarWinFormsオブジェクトでの作業
DoEasy-コントロール(第28部):ProgressBarコントロールのバースタイル
DoEasy - コントロール(第29部):ScrollBar補助コントロール
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/11887
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索