DoEasy. Steuerung (Teil 30): Animieren des ScrollBar-Steuerelements
Inhalt
- Konzept
- Verbesserung der Bibliotheksklassen
- Die Klasse des Erfassungsbereiches der ScrollBar
- Test
- Was kommt als Nächstes?
Konzept
Im vorherigen Artikel habe ich mit der Entwicklung des ScrollBar-Hilfssteuerelements begonnen. Im aktuellen Artikel werde ich die Interaktion der Steuerelemente mit der Maus implementieren. Die konstituierenden Elemente des WinForms ScrollBar-Objekts sind die Scroll-Schaltflächen und der Erfassungsbereich. Für die Bildlauftasten haben wir separate Klassen von Hilfsobjekten (Pfeiltasten), aber wir haben den Erfassungsbereich in Form einer einfachen Schaltfläche erstellt. Hier werde ich eine separate Klasse implementieren, die auf dem Button-Objekt basiert, um ein Objekt zur Bereichserfassung zu erstellen. Um die Ereignisse eines Schiebereglers korrekt zu behandeln, sollte das Objekt einen eigenen Typ haben. Daher wird es vom Schaltflächenobjekt abgeleitet - es erbt dessen Eigenschaften und wird ein unabhängiges Objekt mit einem eindeutigen Typ.
Zum größten Teil werde ich einige Vorbereitungen treffen, um Funktionen für die Größenänderung von Steuerelementen und die Handhabung von Mausinteraktionen mit Bildlaufleisten zu erstellen. Erweitern wir die Liste der Mauszustände und ihrer Ereignisse. All dies wird es mir ermöglichen, Kontrollen und ihre Funktionalität zu entwickeln, ohne durch Routinearbeiten in nachfolgenden Artikeln abgelenkt zu werden.
Verbesserung der Bibliotheksklassen
In \MQL5\Include\DoEasy\Defines.mqh fügen wir die Standardfarbkonstanten für die ScrollBar-Objektzustände hinzu:
#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
Jeder Bildlaufbereich hat eine Breite. Im Falle der vertikalen Bildlaufleiste ist dies die Breite des Objekts, im Falle der horizontalen Bildlaufleiste seine Höhe. Wir setzen den Standardwert 11 für diesen Parameter ein. Die Bildlaufleiste hat einen Rand, der sie von der Oberfläche trennt, wenn sie überlagert wird. Bei einem Breitenwert von 11 Pixeln beträgt der aktive Bereich der Bildlaufleiste 9 Pixel (ein Pixel pro Rand, oben, unten, links und rechts). Da die Pfeilschaltflächen und der Schieberegler auf der Bildlaufleiste aufgebaut werden sollen, sind 9 Pixel eine ausreichende ungerade Zahl, auf der das Pfeildreieck gleichmäßig und schön gezeichnet wird. Im Allgemeinen sollten wir bei der Größenänderung von Objekten, auf denen die Formen um ihre Mittelachse herum gezeichnet werden, immer versuchen, eine ungerade Anzahl von Pixeln zu verwenden, damit die Zeichnung gleichmäßig und ordentlich bleibt. Der Eckbereich ist ein Teil des Formulars, bei dem davon ausgegangen wird, dass sich der Cursor in der Ecke befindet. Befindet sich beispielsweise der Cursor bei der Größenänderung eines Objekts auf einer der vier Ecken, können wir zwei Parameter der Größe (Höhe und Breite) gleichzeitig ändern.
Hinzufügen neuer Werte zur Liste der möglichen Mauszustände in Bezug auf die Form. Die Größe von Objekten kann in acht Richtungen geändert werden:
- Wenn sich der Cursor auf der oberen Kante eines Objekts befindet, können wir seine Höhe ändern, indem wir die Kante nach oben verschieben.
- Wenn sich der Cursor auf der unteren Kante eines Objekts befindet, können wir seine Höhe ändern, indem wir die Kante nach unten verschieben.
- Wenn sich der Cursor auf dem linken Rand des Objekts befindet, können wir seine Breite ändern, indem wir den Rand nach links verschieben.
- Wenn sich der Cursor auf dem rechten Rand eines Objekts befindet, können wir seine Höhe ändern, indem wir den Rand nach rechts verschieben.
- Wenn sich der Cursor in der oberen linken Ecke des Objekts befindet, können wir seine Höhe und Breite ändern, indem wir ihn nach oben und nach links verschieben.
- Wenn sich der Cursor in der oberen rechten Ecke des Objekts befindet, können wir seine Höhe und Breite durch Verschieben nach oben und rechts ändern.
- Wenn sich der Cursor in der linken unteren Ecke des Objekts befindet, können wir die Höhe und Breite des Objekts ändern, indem wir es nach unten und nach links verschieben.
- Wenn sich der Cursor in der unteren rechten Ecke des Objekts befindet, können wir seine Höhe und Breite durch Verschieben nach unten und rechts ändern.
Der Container mit scrollbarem Inhalt wird rechts und unten mit Scrollbalken versehen. Wir müssen feststellen, auf welcher Bildlaufleiste sich der Cursor befindet - auf der rechten oder auf der unteren - und diese Zustände auf den Mausstatus setzen:
//+------------------------------------------------------------------+ //| 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 }; //+------------------------------------------------------------------+
Alle diese neuen Zustände werden als Zustand der Maus relativ zum Objekt definiert und aufgezeichnet.
Wenn ein Mausereignis in einem der vordefinierten Zustände registriert wird, wird das entsprechende Ereignis an die Bibliothek gesendet, wo die dem Ereignis entsprechenden Handler in jedem der Objekte, die Mausereignisse verarbeiten, aufgerufen werden.
Tragen wir neue Zustände in die Liste der möglichen Mausereignisse ein:
//+--------------------------------------------+ //| 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 //+------------------------------------------------------------------+
Der Liste der grafischen Elementtypen fügen wir einen neuen Elementtyp hinzu:
//+--------------------------------------------+ //| 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 }; //+------------------------------------------------------------------+
Dies wird das neue Hilfssteuerelement „Erfassungsbereich“ (Capture Area, Schieberegler) sein.
Hinzufügen von zwei neuen Eigenschaften in der Enumeration der ganzzahligen Eigenschaften eines grafischen Elements und Erhöhung ihrer Gesamtzahl von 138 auf 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 //+------------------------------------------------------------------+
Jedes der grafischen Elemente hat eine Markierung, die anzeigt, dass es mit der Maus in der Größe verändert werden kann. Die auf dem Element gezeichneten Pfeile (z. B. eine Schaltfläche mit einem Pfeil) haben die durch diesen Parameter festgelegten relativen Größen. Ein Pfeil mit einer Größe von 1 wird beispielsweise vom Mittelpunkt aus mit einem Scheitelpunkt-Einzug von 1 Pixel gezeichnet. Ein Pfeil mit einer Größe von 2 wird vom Mittelpunkt aus gezeichnet im Abstand von zwei Pixel usw.
Zum Beispiel, der Pfeil nach oben mit der Größe 1:
⊡⊠⊡ ⊠⊠⊠
Der Pfeil nach oben mit der Größe von 2:
⊡⊡⊠⊡⊡ ⊡⊠⊠⊠⊡ ⊠⊠⊠⊠⊠
Der Pfeil nach oben mit der Größe von 3:
⊡⊡⊡⊠⊡⊡⊡ ⊡⊡⊠⊠⊠⊡⊡ ⊡⊠⊠⊠⊠⊠⊡ ⊠⊠⊠⊠⊠⊠⊠
Wenn wir ein Pixel in der Mitte der Basis des Dreiecks als Mittelpunkt nehmen und die Anzahl der Pixel gleich der relativen Größe der Form zu jeder ihrer Seiten setzen, erhalten wir drei Eckpunkte des Dreiecks, entlang derer die Figur aufgebaut ist. Die Größe eines Dreiecks ist also die Anzahl der Pixel von der Mitte der Basis des Dreiecks nach oben, links und rechts, um die Koordinaten jedes Scheitelpunkts anzugeben.
Die Pfeile nach unten, links und rechts sind auf ähnliche Weise aufgebaut.
In \MQL5\Include\DoEasy\Data.mqh wurden neuen Nachrichtenindizes hinzugefügt:
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
und die Textnachrichten, die den neu hinzugefügten Indizes entsprechen:
{"Элемент управления \"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
Um die neue Typenbeschreibung des Objektes anzuzeigen, fügen wir in \MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh, und zwar in der Methode TypeElementDescription(), eine Zeichenfolge hinzu, die die Beschreibung des an die Methode übergebenen Objekttyps zurückgibt:
//+------------------------------------------------------------------+ //| 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" ); } //+------------------------------------------------------------------+
Jedes Mal, wenn eine neue Eigenschaft zur Enumeration der Eigenschaften eines grafischen Elements hinzugefügt wird, sollte sie der Objektstruktur hinzugefügt werden. Die Struktur eines grafischen Objekts wird verwendet, um die Eigenschaften von grafischen Elementen in einer Datei zu speichern und aus der Datei zu lesen. Dies ist notwendig, um die Objekte nach dem Neustart wiederherzustellen, sodass sie sich in demselben Zustand befinden wie vor dem Beenden. Bisher haben wir eine solche Funktion aufgrund der sich ständig ändernden Konstellation der Eigenschaften von grafischen Objekten nicht realisiert. Aber ich bin bereits dabei, eine solche Struktur für die Zukunft zu schaffen.
In \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh fügen wir die neue Eigenschaften zu der Objektstruktur hinzu:
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
Im öffentlichen Teil der Klasse deklarieren wir neue Methoden, die Flags für die Position des Cursors relativ zum grafischen Element zurückgeben:
//--- 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,
Im Methodenblock für den vereinfachten Zugriff auf die Objekteigenschaften setzen wir die Methoden, die die Koordinaten neuer Bereiche und grafischer Elementzonen zurückgeben, sowie die Methode, die das Flag für die Größenänderbarkeit zurückgibt:
//--- 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); }
Fügen wir der Methode, die das Flag für die Veränderbarkeit der Elementgröße zurückgibt hinzu:
//--- 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
Wir ändern die Deklaration der Pfeilzeichnungsmethoden:
//+------------------------------------------------------------------+ //| 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); }; //+------------------------------------------------------------------+
Jetzt erhalten die Methoden die Koordinaten des zentralen Punktes und die relative Pfeilgröße.
In der Methode zur Initialisierung der Objekteigenschaften setzen wir die Standardwerte für die Breite der Bereiche des oberen, unteren, linken und rechten Objektrandes auf zwei Pixel, um festzulegen, ob sich der Mauszeiger in diesen Bereichen befindet. Standardmäßig ist die Möglichkeit, die Größe des Objekts mit dem Mauszeiger zu ändern, deaktiviert, und die Größe des gezeichneten Pfeils beträgt 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 } //+------------------------------------------------------------------+
In der Methode, die die Struktur des Objekts erstellt, setzen wir die Werte der neuen Objekteigenschaften auf die neuen Strukturfelder:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
In der Methode, die ein Objekt aus einer Struktur erstellt, setzen wir die Werte der entsprechenden Strukturfelder auf die Werte der neuen Eigenschaften:
//+--------------------------------------------+ //| 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 } //+------------------------------------------------------------------+
Implementierung der Methoden, die die Cursorpositionsflags relativ zu den Bildlaufbereichen zurückgeben und die Größe des Elements ändern:
//+------------------------------------------------------------------+ //|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 | //+--------------------------------------------+
Abhängig von den Koordinaten der Cursorposition geben die Methoden das Flag zurück, ob sich der Cursor innerhalb des durch seine Werte umrissenen Bereichs befindet.
Die Methoden zum Zeichnen von Pfeilen zeichnen nun Dreiecke in Abhängigkeit von der Startkoordinate (Zentrum der Dreiecksbasis) und der angegebenen Pfeilgröße:
//+--------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Um die Koordinaten jedes Scheitelpunkts zu berechnen, addieren oder subtrahieren wir einfach die Größe des in den Parametern übergebenen Pfeils von den Koordinaten des zentralen Punkts.
Vergessen wir nicht, dass die Größe nur durch die untere Grenze (1), nicht aber durch die obere Grenze begrenzt ist. Hier müssen wir sicherstellen, dass der Pfeil in normaler Größe gezeichnet wird, da sich die tatsächliche Größe des Pfeils aus zwei angegebenen Größen + einem zentralen Pixel ergibt. Mit anderen Worten: Bei einer Größe von 1 ist die tatsächliche Größe 1+1+1. Bei einer Größe von 2 ist die tatsächliche Größe 2+1+2, bei einer Größe von 3: 3+1+3 usw.
Da wir nun neue Mauszustände in Bezug auf das Element und die entsprechenden Ereignisse haben, müssen diese in den Methoden zur Ereignisbehandlung des letzten Mausereignisses berücksichtigt werden.
Fügen wir in \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\Button.mqh die Liste der neuen Ereignisse zu der Methode hinzu:
//+--------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+
Hier werden all diese Ereignisse nicht behandelt, aber falls erforderlich, kann die Behandlung unter jedem Ereignis hinzugefügt werden.
Die gleichen Änderungen an der Methode wurden bereits in TabHeader.mqh, CheckBox.mqh und SplitContainer.mqh vorgenommen.
Um die Farbe des gezeichneten Pfeils in der Klasse der Pfeilschaltflächen festzulegen, haben wir die private Variable m_arrow_color verwendet. Die Verwendung dieser Variable ist überflüssig, da wir die Methode ForeColor() verwenden können, um die Farbe festzulegen, die auch die Farbe des gezeichneten Textes steuern kann. Daher entfernen wir in \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh die Variable und ihre Behandlungsmethoden:
//+------------------------------------------------------------------+ //| 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
Außerdem ersetzen wir den Aufruf von Remote-Methoden durch die Methoden zur Behandlung der Textfarbe:
//+--------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
In \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowRightButton.mqh, nämlich in den Klassenkonstruktoren, setzen wir die Größe des gezeichneten Pfeils auf 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); } //+------------------------------------------------------------------+
In der Methode, die den Pfeil zeichnet, ändern wir die Parameter, wenn wir die Methode zum Zeichnen des Pfeils aufrufen:
//+--------------------------------------------+ //| 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()); } //+------------------------------------------------------------------+
Als Mittelpunkt des Pfeils übergeben wir den Mittelpunkt des Objekts (horizontal um ein Pixel nach links verschieben) und geben die Größe des gezeichneten Pfeils in den Eigenschaften des Objekts an, seine Textfarbe und Deckkraft.
Ähnliche Änderungen wurden bereits in anderen Pfeiltasten-Objektklassen in ArrowLeftButton.mqh, ArrowDownButton.mqh und ArrowUpButton.mqh vorgenommen.
Zur vereinfachten Einstellung der Koordinaten und Größen der Bildlaufleistenbereiche fügen wir in der Datei \MQL5\Include\DoEasy\Objects\Graph\Form.mqh der Formularobjektklasse die öffentlichen Methoden hinzu:
//--- 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);
In der Methode, die den Zustand der Maus in Bezug auf das Formular festlegt und zurückgibt, überprüfen wir die Position des Mauszeigers, vergleichen sie mit den Koordinaten der verschiedenen Bereiche des Formulars und weisen die Flags dieser Zustände der Variablen zu. Ferner wird auf der Grundlage dieser Flags der allgemeine Zustand des Mauszeigers in Bezug auf das Objekt ermittelt. Fügen wir die Codeblöcke der Methode für die Verfolgung der Position des Cursors relativ zu den Bildlaufleisten und Rändern hinzu, in deren Bereich es möglich ist, den Rand des Objekts mit der Maus zu greifen und zu ziehen, um die Größe des Elements zu ändern:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Alle Codeblöcke sind ausführlich kommentiert, und in der Tat ist alles einfach in ihnen - wir überprüfen die Position des Cursors Koordinaten relativ zu den Koordinaten der Bereiche, zum Beispiel, Scrollen, und wenn der Cursor innerhalb des Bereichs ist, setzen wir die entsprechende Flag. Wenn nicht, entfernen wir das Flag. Als Ergebnis der Überprüfung und des Setzens der Flags haben wir eine Reihe von Flags, mit denen wir entscheiden, wo sich der Mauszeiger befindet. Wenn die Flags für seine Position auf der oberen und rechten Seite des Objekts gesetzt sind, bedeutet dies, dass sich der Cursor in der oberen rechten Ecke befindet. Daher müssen wir die Flags kombinieren, da die Bits im ushort-Wert nicht ausreichen, um jedes Flag einzeln zu zuzuweisen.
Ändern wir in der Ereignishandlung der Maus den Aufruf der Ereignisbehandlungsmethoden für das Auffinden des Cursors im Bildlaufbereich. Da wir zwei dieser Bereiche haben, haben wir den Namen des Mausstatus im Bildlaufbereich geändert. Jetzt zeigt der Status genau an, auf welchem der Rollbalken sich der Cursor befindet - auf dem rechten oder auf dem oberen Balken:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Fügen wir alle neuen Mausereignisse der letzten Mausereignishandlung hinzu:
//+--------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+
Wir korrigieren in der Methode, die die Ereignismeldung sendet, den Empfang des Basisobjekttyps:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Wenn ein erfolgreich abgerufenes Basisobjekt sein eigenes Basisobjekt hat, wird dessen Typ ermittelt. Andernfalls erhalten wir den Basisobjekttyp. Vor dieser Korrektur wurde das Programm mit einem kritischen Fehler beendet, wenn das Basisobjekt kein eigenes Basisobjekt hatte (z. B. wenn das Basisobjekt das Hauptobjekt war), weil der Zugriff auf das Objekt mit einem ungültigen Zeiger erfolgte. Jetzt ist das korrigiert.
Zuvor habe ich Anpassungen an der Position der Scrollbar-Objekte in der Resizing-Methode der WinForms-Basisobjektklasse vorgenommen. Wenn die Größe eines Objekts geändert wird, ändern sich die Koordinaten seiner Seiten. Da die Bildlaufleisten an die untere rechte Seite des Objekts gebunden sind, müssen ihre Koordinaten gegebenenfalls angepasst werden. Jetzt werden wir eine solche Anpassung in der Klasse der Container-Objekte vornehmen, denn nur Container-Objekte können angehängte Objekte enthalten, die möglicherweise einen Bildlauf erfordern, wenn sie nicht in den sichtbaren Bereich des Containers passen. Verschieben wir diese Verarbeitung in die Klasse des Containerobjekts. Dies ist der am besten geeignete Ort dafür.
In der Datei \MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqh der WinForms-Basisklasse entfernen wir aus der Methode zum Einstellen neuer Größen den Codeblock, der die Größe und die Koordinaten der Bildlaufleisten anpasst:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Dieser Codeblock wird vollständig in die Klasse des Containerobjekts verlagert.
In der Methode, die die Beschreibung der Ganzzahl-Eigenschaft des Elements zurückgibt, fügen wir den Codeblock für die Rückgabe der Beschreibungen neuer Eigenschaften hinzu:
//+------------------------------------------------------------------+ //| 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) ) : "" ); } //+------------------------------------------------------------------+
Die Klasse des Erfassungsbereiches der ScrollBar
Im letzten Artikel haben wir beim Erstellen des ScrollBar-Objekts die Button-Objektklasse für den Schieberegler verwendet. Dieses Objekt eignet sich tatsächlich für diese Funktion. Bei der Behandlung von Ereignissen sollten wir jedoch den Typ des zu verarbeitenden Objekts kennen, um den richtigen Handler aufrufen zu können. Es gibt einen solchen Handler für das Button-Objekt, aber er ist nicht für den Schieberegler geeignet. Der Schieberegler muss verschoben werden. Während der Verschiebung sollten die Koordinaten der Objekte, deren Sichtbarkeitsbereich von der Bildlaufleiste gesteuert wird, neu berechnet werden. Daher werde ich eine neue Klasse erstellen, die auf der Klasse des Schaltflächenobjekts basiert - der Klasse des Capture-Bereichsobjekts. In diesem Objekt können wir unseren eigenen Handler für die notwendigen Mausereignisse erstellen.
Im Verzeichnis \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ erstellen wir die neue Datei ScrollBarThumb.mqh der Klasse CScrollBarThumb.
Die Klasse sollte von der Klasse CCheckBox abgeleitet sein, und ihre Datei sollte in die eingebunden Klassendatei eingebunden werden:
//+------------------------------------------------------------------+ //| 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 { }
Im geschützten Abschnitt der Klasse deklarieren wir den geschützten Konstruktor und im öffentlichen Abschnitt den parametrischen Konstruktor:
//+--------------------------------------------+ //| 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); }; //+------------------------------------------------------------------+
Das ist im Moment alles, was wir von diesem Objekt brauchen. Sein Typ wird in den Klassenkonstruktoren festgelegt, und er ist eindeutig - das Objekt des Erfassungsbereichs.
Geschützter Konstruktor:
//+--------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Der Konstruktor erhält den Typ des erstellten Objekts, der an den Konstruktor der übergeordneten Klasse übergeben wird. Der grafische Elementtyp und der grafische Objekttyp der Bibliothek werden im Konstruktorkörper festgelegt. Außerdem werden alle Standardfarbwerte für verschiedene Objektzustände bei der Interaktion mit dem Mauszeiger festgelegt.
Der parametrische Konstruktor:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Hier ist alles ähnlich wie beim geschützten Konstruktor, mit der Ausnahme, dass der Objekttyp starr als Erfassungsbereich festgelegt ist.
Verfeinern wir die abstrakte Scrollbar-Objektklasse in \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBar.mqh.
Die Objektklassendatei des Erfassungsbereichs wird eingebunden. Im privaten Abschnitt deklarieren wir die Variable zum Speichern der Breite der Bildlaufleiste, während wir im geschützten Abschnitt die Methode zum Einstellen der Größe der Bildlauftasten deklarieren. Im öffentlichen Abschnitt deklarieren wir die Methoden für die Rückgabe des Capture-Bereichs-Objekts, um die Breite der Bildlaufleiste festzulegen und zurückzugeben, sowie die Methode, die die Größe der gezeichneten Pfeile auf den Schaltflächen der Bildlaufleiste festlegt:
//+------------------------------------------------------------------+ //| 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); }; //+------------------------------------------------------------------+
Fügen wir in der Initialisierungsmethode der Elementeigenschaften die Standardfarbwerte, die Breite der Bildlaufleiste sowie die Größe der Schaltflächen und Pfeile hinzu:
//+--------------------------------------------+ //| 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)); } //+------------------------------------------------------------------+
In der Methode zur Erstellung eines neuen grafischen Objekts implementieren wir den Codeblock zur Erstellung des Capture Area-Objekts:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Jetzt kann das Objekt zusätzlich zu den Pfeilschaltflächenobjekten auch den Schieberegler für die Erstellung der Steuerungsoberfläche erstellen.
Die Methode, die die Breite der Bildlaufleiste festlegt:
//+--------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+
Handelt es sich um eine vertikale Bildlaufleiste, wird die Breite des Objekts als die Breite der Leiste betrachtet. Handelt es sich um eine horizontale Bildlaufleiste, so entspricht die Objektbreite ihrer Höhe. Die Methode empfängt den Wert, der auf das Objekt gesetzt werden soll. Je nach Art der Bildlaufleiste wird entweder ihre Breite oder ihre Höhe festgelegt.
Die Methode, mit der die Größe der Bildlauftasten festgelegt wird:
//+--------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+
Die Schaltflächen des Scrollbar-Objekts haben gleiche Seiten. Die Größe wird an die Methode übergeben, und je nach Objekttyp erhalten wir die Zeiger auf die Schaltflächen links/rechts oder oben/unten und setzen die an die Methode übergebene Größe für sie - sowohl für die Breite als auch für die Höhe.
Die Methode, die die Größe der gezeichneten Pfeile auf den Bildlauftasten festlegt:
//+------------------------------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+
Je nach Art der Bildlaufleiste erhalten wir Zeiger auf die entsprechenden Schaltflächen, legen die Größe der gezeichneten Pfeile für sie fest und zeichnen das Objekt neu, um die Änderungen anzuzeigen.
Der Schieberegler für die Bildlaufleiste dient dazu, den Inhalt des Containers innerhalb seines Sichtbarkeitsbereichs zu verschieben. Wenn man den Schieberegler mit der Maus bewegen, sollte er nicht über die Bildlaufleiste hinausgehen - sein Bewegungsbereich sollte auf die Pfeiltasten beschränkt sein, die auch zum Scrollen verwendet werden. In \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBarVertical.mqh der vertikalen Bildlaufleisten-Objektklasse fügen wir die Objektklassendatei des Erfassungsbereichs ein. Im öffentlichen Abschnitt implementieren wir die Methoden, die die Zeiger auf die Pfeilschaltflächen zurückgeben, und deklarieren die Ereignisbehandlung:
//+------------------------------------------------------------------+ //| 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); }; //+------------------------------------------------------------------+
In der Methode, die die ArrowButton-Objekte erstellt, werden alle Schaltflächen und der Schieberegler erstellt, dann die Zeiger auf sie abgerufen und ihre Farben für verschiedene Mausinteraktionszustände festgelegt:
//+--------------------------------------------+ //| 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); } } //+------------------------------------------------------------------+
In der Ereignisbehandlung, beim Verschieben des Fortschrittsbalken-Schieberegler-Objekts, berechnen wir dessen Koordinaten, die durch die Schaltflächen an den Rändern der Bildlaufleiste begrenzt sein sollten:
//+--------------------------------------------+ //| 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()); } } } //+------------------------------------------------------------------+
Ähnliche Verbesserungen wurden an der Klasse des horizontalen Scrollbar-Objekts in der Datei ScrollBarHorisontal.mqh vorgenommen.
Seine Methode zur Erstellung von Schaltflächen- und Schiebereglerobjekten und der Ereignishandler unterscheiden sich von den obigen Methoden nur durch Zeiger auf andere Schaltflächentypen und durch die Beschränkung auf andere Achsen der Schiebereglerbewegung:
//+--------------------------------------------+ //| 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()); } } } //+------------------------------------------------------------------+
Verbessern wir die Container-Objektklasse in \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqh.
Im öffentlichen Abschnitt deklarieren wir die virtuelle Methode zum Ändern der Objektgröße:
//--- 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
Die Methode erhält den aus der WinForms-Basisobjektklasse entfernten Codeblock.
In den Klassenkonstruktoren legen wir die Größe der erstellten Bildlaufleisten fest, die standardmäßig in der Bibliothek implementiert sind, und bestimmen den Bereich für die untere Bildlaufleiste. Der Bereich für die rechte Bildlaufleiste wird noch nicht festgelegt, da zunächst die Funktion der unteren Leiste verfeinert werden muss. Dann werden die Ergebnisse in das rechte Bildlaufleistenobjekt verschoben:
//+--------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
In der Methode, die Parameter für das angehängte Objekt festlegt, schreiben wir den Codeblock zum Festlegen der Standardparameter für ein neu erstelltes Capture Area-Objekt:
//+--------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Für jedes der erstellten Objekte, die mit dem Container verbunden sind, gibt es hier einen Codeblock, der die für die Anzeige des Objekts erforderlichen Mindestparameter festlegt.
Da die Objekte im Container-Objekt automatisch in einer bestimmten Reihenfolge angeordnet werden können oder ihre Größe an die Größe des Containers angepasst werden kann, ist es notwendig, Bildlaufleisten von Objekten, die auf diese Weise behandelt werden, zu entfernen, da sie ein integraler Bestandteil des Container-Objekts und nicht seines Inhalts sind.
In einer Methode, die die Größe eines Elements an seinen inneren Inhalt anpasst, schließen wir die ScrollBar-Objekte von der Verarbeitung aus:
//+--------------------------------------------+ //| 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) ); } //+------------------------------------------------------------------+
Die Methode zum Festlegen der neuen Größe für das aktuelle Objekt:
//+--------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Diese virtuelle Methode ändert die Größe des Containerobjekts. Wir haben den Codeblock, der aus der Basisklasse von WinForms-Objekten entfernt wurde, in diese Klasse verschoben. Rufen wir zunächst die Methode zur Größenänderung von WinForms-Objekten auf. Wenn dies erfolgreich war, passen wir die Größe und die Koordinaten beider Bildlaufleisten an die neue Größe und die Koordinaten des Containers an.
Jetzt müssen wir die Kollektionsklasse der grafischen Elemente \MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqh verbessern.
Wir müssen der Bibliothek eine Nachricht über ihre Bewegung senden, wenn wir das Objekt des Erfassungsbereichs (den Schieberegler der Bildlaufleiste) bewegen, um seine Ereignisbehandlung aufzurufen. Wir haben bereits alles dafür - wir können den Separator im SplitContainer-Objekt bereits verschieben. Das bedeutet, dass wir die Bewegung und die Verarbeitung des Schiebereglers in die Codemethode aufnehmen müssen, in der die Bewegung des Trennzeichens verarbeitet wird.
Fügen wir eine Schieberegler-Behandlung in der Ereignisbehandlung des Separator-Handling-Blocks ein:
//--- 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); }
Ändern und fügen wir alle Ereignisbehandlungen hinzu, deren Namen von den Mausereignissen sich geändert haben:
//+---------------------------------------------------------------------------------------------+ //| '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); } //+---------------------------------------------------------------------------------------------+
Test
Um den Test durchzuführen, verwende ich den EA aus dem vorherigen Artikel und speichere ihn in \MQL5\Experts\TestDoEasy\Part130\ als TestDoEasy130.mq5.
Entkommentieren Sie einfach die Erstellung aller Objekte auf dem Panel und eine einzelne große Schaltfläche, um die Funktionen der Bildlaufleisten auf dem Panel zu testen.
//+--------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Kompilieren Sie den EA und starten Sie ihn auf einem Chart:
Wie wir sehen können, werden die Schieberegler durch die Pfeilschaltflächen ordnungsgemäß in der Bildlaufleiste eingegrenzt. Die Pfeiltasten reagieren auf Klicks, die Farben der Objekte ändern sich je nach Zustand des Objekts und des Cursors während der Interaktion.
Es gibt auch einen Nachteil: Der Rahmen der Bildlaufleiste, der sie von der Oberfläche trennt, verschwindet, wenn wir eines der Objekte auswählen. Dies geschieht durch das Neuzeichnen von Objekten und die Tatsache, dass die Bildlaufleisten unter anderen Objekten liegen, da sie früher erstellt wurden und keine Priorität haben. Es ist auch schwierig, eine Pfeilschaltfläche auf der Bildlaufleiste auszuwählen, um darauf zu klicken. Aus demselben Grund werden die Objekte zuerst erstellt und die später erstellten Objekte (große Schaltfläche) überlagern sie. Ich werde das alles später reparieren. Im Moment ist es wichtig, die Mängel zu erkennen, die Ursachen zu verstehen und zu wissen, was getan werden muss, um sie zu beseitigen.
Was kommt als Nächstes?
Im nächsten Artikel werde ich die Entwicklung des ScrollBar-Objekts fortsetzen.
*Vorherige Artikel in dieser Reihe:
DoEasy. Steuerung (Teil 26): Fertigstellung des ToolTip WinForms-Objekts und Weiterführung der ProgressBar-Entwicklung
DoEasy. Steuerung (Teil 27): Arbeiten am WinForms Objekt der ProgressBar
DoEasy. Steuerung (Teil 28): Balkenstile im ProgressBar-Steuerelement
DoEasy. Steuerung (Teil 29): ScrollBar-Hilfssteuerelement
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/11887
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.