{"id":1544,"date":"2008-02-18T14:16:36","date_gmt":"2008-02-18T14:16:36","guid":{"rendered":"http:\/\/www.amibroker.org\/userkb\/2008\/02\/18\/moving-low-level-graphics-gfx-objects-on-your-charts\/"},"modified":"2011-02-28T11:17:31","modified_gmt":"2011-02-28T11:17:31","slug":"moving-low-level-graphics-gfx-objects-on-your-charts","status":"publish","type":"post","link":"http:\/\/www.amibroker.org\/editable_userkb\/2008\/02\/18\/moving-low-level-graphics-gfx-objects-on-your-charts\/","title":{"rendered":"Moving Low Level Graphics (GFX) Objects on your Charts"},"content":{"rendered":"

When drawing gfx objects on your charts, you can move them around by applying an X and Y offset to the coordinates of the object. The following code shows a simple example of how you can move a square object around your chart.<\/p>\n

<\/span>function <\/span>DrawButton<\/span>( <\/span>Text<\/span>, <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>BackColor <\/span>)\r{\r    <\/span>GfxSetOverlayMode<\/span>( <\/span>0 <\/span>);\r    <\/span>GfxSelectFont<\/span>( <\/span>"Tahoma"<\/span>, <\/span>12<\/span>, <\/span>800 <\/span>);\r    <\/span>GfxSelectPen<\/span>( <\/span>colorBlack <\/span>);\r    <\/span>GfxSetBkMode<\/span>( <\/span>1 <\/span>);\r    <\/span>GfxSelectSolidBrush<\/span>( <\/span>BackColor <\/span>);\r    <\/span>GfxSetBkColor<\/span>( <\/span>BackColor <\/span>);\r    <\/span>GfxSetTextColor<\/span>( <\/span>1 <\/span>);\r    <\/span>GfxRectangle<\/span>( <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2 <\/span>);\r    <\/span>GfxDrawText<\/span>( <\/span>Text<\/span>, <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>32 <\/span>| <\/span>1 <\/span>| <\/span>4 <\/span>);\r}\r \r<\/span>Yoffset <\/span>= <\/span>Param<\/span>( <\/span>"Button Row Offset (px)"<\/span>, <\/span>50<\/span>, <\/span>0<\/span>, <\/span>2000<\/span>, <\/span>5 <\/span>);\r<\/span>Xoffset    <\/span>= <\/span>Param<\/span>( <\/span>"Button Column Offset (px)"<\/span>, <\/span>50<\/span>, <\/span>0<\/span>, <\/span>2000<\/span>, <\/span>5 <\/span>);\r<\/span>CellHeight <\/span>= <\/span>Param<\/span>(<\/span>"Cell Height"<\/span>,<\/span>20<\/span>,<\/span>5<\/span>,<\/span>200<\/span>,<\/span>5<\/span>);   \r<\/span>CellWidth <\/span>= <\/span>Param<\/span>(<\/span>"Cell Width"<\/span>,<\/span>120<\/span>,<\/span>5<\/span>,<\/span>200<\/span>,<\/span>5<\/span>);  \r<\/span>DrawButton<\/span>( <\/span>"TEST"<\/span>, <\/span>Xoffset<\/span>, <\/span>yoffset<\/span>, <\/span>Xoffset <\/span>+ <\/span>CellWidth<\/span>, <\/span>yOffset <\/span>+ <\/span>CellHeight<\/span>, <\/span>colorBlue <\/span>);<\/span><\/pre>\n

If you only need to adjust the position of your object once in awhile, this simple method may serve best. However, when you want to move an object on the fly, without having to open the Param window each time, you can do this by registering the coordinates of your first click on the object and then move the object to the location of your next mouse click. The program below shows how to do this. It also shows you how to detect whether your click is within the object area (see the CursorInField variable). <\/p>\n

To facilitate readability, the code has not been optimized. You can see in the captures below the code only adds about 4 microseconds to your execution time. It is doubtful that code optimization will have much effect on the overall execution time of your code. To test this code you Apply it to an indicator. At First Apply, it will display the Yellow Square with the word TEST in it:<\/p>\n

\"clip_image002\"<\/a><\/p>\n

When you click within the yellow square with your Left mouse button, it will turn Red:<\/p>\n

\"clip_image004\"<\/a><\/p>\n

The red color indicates that a move is in progress and that the next click will determine the location to which the object will be moved. After the move is completed, the object will return to its default yellow color:<\/p>\n

\"clip_image006\"<\/a><\/p>\n

In a real application, you may want to add some protective code that disables other mouse click activated actions while a move is in progress. Such code would be disabled while the object is Red and the variable MoveInProgress is true.<\/p>\n

While the code could be (and initially was) written to move the object by holding down the Left Mouse button and dragging the object in the conventional way, the one-second minimum chart refresh rate makes this extremely awkward and slow to work with. For diagnostic purposes, a Reset button in provided in the Param window. Clicking this button will move the yellow square to its default coordinates. <\/p>\n

<\/span>function <\/span>DrawButton<\/span>( <\/span>Text<\/span>, <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>BackColor <\/span>)\r{\r    <\/span>GfxSetOverlayMode<\/span>( <\/span>0 <\/span>);\r    <\/span>GfxSelectFont<\/span>( <\/span>"Tahoma"<\/span>, <\/span>12<\/span>, <\/span>800 <\/span>);\r    <\/span>GfxSelectPen<\/span>( <\/span>colorBlack <\/span>);\r    <\/span>GfxSetBkMode<\/span>( <\/span>1 <\/span>);\r    <\/span>GfxSelectSolidBrush<\/span>( <\/span>BackColor <\/span>);\r    <\/span>GfxSetBkColor<\/span>( <\/span>BackColor <\/span>);\r    <\/span>GfxSetTextColor<\/span>( <\/span>1 <\/span>);\r    <\/span>GfxRectangle<\/span>( <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2 <\/span>);\r    <\/span>GfxDrawText<\/span>( <\/span>Text<\/span>, <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>32 <\/span>| <\/span>1 <\/span>| <\/span>4 <\/span>);\r}\r\r\r<\/span>ParamSqrSize    <\/span>= <\/span>100<\/span>;\r<\/span>Reset <\/span>= <\/span>ParamTrigger<\/span>( <\/span>"Reset Coordinates"<\/span>, <\/span>"RESET" <\/span>);\r<\/span>xOffset  <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"xOffset" <\/span>);\r<\/span>YOffset  <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"YOffset" <\/span>);\r\rif ( <\/span>IsNull<\/span>( <\/span>xOffset <\/span>) OR <\/span>IsNull<\/span>( <\/span>yOffset <\/span>) OR <\/span>Reset <\/span>)\r{\r    <\/span>StaticVarSet<\/span>( <\/span>"xOffset"<\/span>, <\/span>20 <\/span>);\r    <\/span>StaticVarSet<\/span>( <\/span>"yOffset"<\/span>, <\/span>20 <\/span>);\r    <\/span>X1 <\/span>= <\/span>XOffset<\/span>;\r    <\/span>Y1 <\/span>= <\/span>YOffset<\/span>;\r    <\/span>X2 <\/span>= <\/span>XOffset <\/span>+ <\/span>ParamSqrSize<\/span>;\r    <\/span>Y2 <\/span>= <\/span>YOffset <\/span>+ <\/span>ParamSqrSize<\/span>;\r    <\/span>StaticVarSet<\/span>( <\/span>"X1"<\/span>, <\/span>X1 <\/span>);\r    <\/span>StaticVarSet<\/span>( <\/span>"X2"<\/span>, <\/span>X2 <\/span>);\r    <\/span>StaticVarSet<\/span>( <\/span>"Y1"<\/span>, <\/span>Y1 <\/span>);\r    <\/span>StaticVarSet<\/span>( <\/span>"Y2"<\/span>, <\/span>Y2 <\/span>);\r    <\/span>StaticVarSet<\/span>( <\/span>"MoveinProgress"<\/span>, <\/span>False <\/span>);\r}\r\r<\/span>X1 <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"X1" <\/span>) );\r\r<\/span>X2 <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"X2" <\/span>) );\r<\/span>Y1 <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"Y1" <\/span>) );\r<\/span>Y2 <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"Y2" <\/span>) );\r<\/span>LButtonTrigger    <\/span>= <\/span>GetCursorMouseButtons<\/span>() == <\/span>9<\/span>;\r<\/span>MousePx  <\/span>= <\/span>Nz<\/span>( <\/span>GetCursorXPosition<\/span>( <\/span>1 <\/span>) );\r<\/span>MousePy  <\/span>= <\/span>Nz<\/span>( <\/span>GetCursorYPosition<\/span>( <\/span>1 <\/span>) );\r\r<\/span>CursorInField <\/span>= <\/span>MousePx <\/span>> <\/span>X1 <\/span>AND <\/span>MousePx <\/span>< <\/span>X2 <\/span>AND <\/span>MousePy <\/span>> <\/span>Y1 <\/span>AND <\/span>MousePy <\/span>< <\/span>Y2<\/span>;\r\r<\/span>MoveInProgress <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"MoveInProgress" <\/span>) );\r\r<\/span>BackColor <\/span>= <\/span>colorYellow<\/span>;\r\rif ( <\/span>NOT MoveInProgress <\/span>)\r{\r    if ( <\/span>LButtonTrigger <\/span>AND <\/span>CursorInField <\/span>)\r    {\r        <\/span>StaticVarSet<\/span>( <\/span>"BackColor"<\/span>, <\/span>colorRed <\/span>);\r        <\/span>StaticVarSet<\/span>( <\/span>"DownPx1"<\/span>, <\/span>MousePx <\/span>);\r        <\/span>StaticVarSet<\/span>( <\/span>"DownPy1"<\/span>, <\/span>MousePy <\/span>);\r        <\/span>StaticVarSet<\/span>( <\/span>"MoveinProgress"<\/span>, <\/span>True <\/span>);\r\r    }\r}\relse\r    if ( <\/span>LButtonTrigger <\/span>)\r    {\r        <\/span>StaticVarSet<\/span>( <\/span>"BackColor"<\/span>, <\/span>colorYellow <\/span>);\r        <\/span>DownPx1 <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"DownPx1" <\/span>);\r        <\/span>DownPy1 <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"DownPy1" <\/span>);\r        <\/span>xMove <\/span>= <\/span>MousePx <\/span>- <\/span>DownPx1<\/span>;\r        <\/span>yMove <\/span>= <\/span>MousePy <\/span>- <\/span>downPy1<\/span>;\r        <\/span>PrevxOffset <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"xOffset" <\/span>);\r        <\/span>PrevYOffset <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"YOffset" <\/span>);\r        <\/span>xOffset <\/span>= <\/span>PrevxOffset <\/span>+ <\/span>xMove<\/span>;\r        <\/span>yOffset <\/span>= <\/span>PrevYOffset <\/span>+ <\/span>yMove<\/span>;\r        <\/span>StaticVarSet<\/span>( <\/span>"xOffset"<\/span>, <\/span>xOffset <\/span>);\r        <\/span>StaticVarSet<\/span>( <\/span>"yOffset"<\/span>, <\/span>yOffset <\/span>);\r        <\/span>StaticVarSet<\/span>( <\/span>"MoveinProgress"<\/span>, <\/span>False <\/span>);\r    }\r\r\r<\/span>BackColor <\/span>= <\/span>Nz<\/span>( <\/span>StaticVarGet<\/span>( <\/span>"BackColor" <\/span>), <\/span>colorYellow <\/span>);\r\r<\/span>xOffset <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"xOffset" <\/span>);\r<\/span>YOffset <\/span>= <\/span>StaticVarGet<\/span>( <\/span>"YOffset" <\/span>);\r<\/span>X1 <\/span>= <\/span>XOffset<\/span>;\r<\/span>Y1 <\/span>= <\/span>YOffset<\/span>;\r<\/span>X2 <\/span>= <\/span>XOffset <\/span>+ <\/span>ParamSqrSize<\/span>;\r<\/span>Y2 <\/span>= <\/span>YOffset <\/span>+ <\/span>ParamSqrSize<\/span>;\r<\/span>StaticVarSet<\/span>( <\/span>"X1"<\/span>, <\/span>X1 <\/span>);\r<\/span>StaticVarSet<\/span>( <\/span>"X2"<\/span>, <\/span>X2 <\/span>);\r<\/span>StaticVarSet<\/span>( <\/span>"Y1"<\/span>, <\/span>Y1 <\/span>);\r<\/span>StaticVarSet<\/span>( <\/span>"Y2"<\/span>, <\/span>Y2 <\/span>);\r<\/span>DrawButton<\/span>( <\/span>"TEST"<\/span>, <\/span>x1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>BackColor <\/span>);<\/span><\/pre>\n

Edited by Al Venosa.<\/p>\n","protected":false},"excerpt":{"rendered":"

When drawing gfx objects on your charts, you can move them around by applying an X and Y offset to the coordinates of the object. The following code shows a simple example of how you can move a square object around your chart. function DrawButton( Text, x1, y1, x2, y2, BackColor ) {     GfxSetOverlayMode( 0 );     GfxSelectFont( "Tahoma", 12, 800 );     GfxSelectPen( colorBlack );     GfxSetBkMode( 1 );     GfxSelectSolidBrush( BackColor );     GfxSetBkColor( BackColor );     GfxSetTextColor( 1 );     GfxRectangle( x1, y1, x2, y2 );     GfxDrawText( Text, x1, y1, x2, y2, 32 | 1 | 4 ); } […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[138],"tags":[],"_links":{"self":[{"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts\/1544"}],"collection":[{"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/comments?post=1544"}],"version-history":[{"count":2,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts\/1544\/revisions"}],"predecessor-version":[{"id":2320,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts\/1544\/revisions\/2320"}],"wp:attachment":[{"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/media?parent=1544"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/categories?post=1544"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/tags?post=1544"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}