{"id":1949,"date":"2011-01-26T16:25:02","date_gmt":"2011-01-26T16:25:02","guid":{"rendered":"http:\/\/www.amibroker.org\/userkb\/?p=1949"},"modified":"2011-02-09T22:42:15","modified_gmt":"2011-02-09T22:42:15","slug":"adding-help-tips-to-your-programs","status":"publish","type":"post","link":"http:\/\/www.amibroker.org\/editable_userkb\/2011\/01\/26\/adding-help-tips-to-your-programs\/","title":{"rendered":"Adding Help-Tips to your programs"},"content":{"rendered":"

If you write AmiBroker programs that are used by others you have undoubtedly found that documenting your program and answering hundreds of emails can be very time consuming. You can save yourself, and those who use your code, a lot of time by adding Help popups (Tips) to your programs. No longer will users have to search though manuals and\/or write emails to find basic instructions. Of course you will save time as well since you don’t have to answer all those emails :-) If you don’t program for others, read on, because there are some other applications that may interest you.<\/p>\n

When Tips are enabled they will display as a balloon when hovering the cursor over a defined object or area, no clicks are required. Here is a typical Tip:<\/p>\n

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

Tips can be used with gfx Control panels, trading dashboards, charts (function like the interpretation screen and now defunct ToolTip), tabular data, system status displays, gfx menus, caution and alert messages, etc. Your imagination sets the limits. Of course you can change the balloon size, colors, fonts, shape, etc. to your requirements. The code for the trading buttons shown is not provided in this post – that could be another topic.<\/p>\n

Tips can display real-time market and system information. In the above example the Last price and a cautionary warning that Transmit is turned ON reflect real-time status.<\/p>\n

In this post Tips are placed relative to the mouse’s cursor position. In chart applications you might want to use dynamically placed Tips that point to a critical event or condition on your chart. You would do this by converting price and bars to pixels and replace the MX and MY variables in the code with calculated values. For more on this see How to convert from bar-value to pixel coordinates<\/a> on the AmiBroker Knowledge Base.<\/p>\n

When I write button functions I add Tip information as the last argument to the function, this way the information is right where it is defined by the code. This is also helpful when reading the code. The actual Tip text can be repeated in your manual as a text box so that a clear association exists.<\/p>\n

The code in this post demonstrates how the balloon reorients itself depending on in which quadrant of the pane the cursor is located. This is done to keep tips within the pane area, even when hovering over an object close to the edge of the pane. Here is a short video to see how this works.<\/p>\n

\n<\/embed><\/object>\n<\/div>\n

If, on your computer, the Tip tracks the mouse cursor slower than in the video this is because I have enabled the higher refresh rate of 0.1 second. Tomasz explained this in post 151255<\/a> on the main AmiBroker list. Making errors while editing your Registry can cause serious computer problems, if you haven’t done this before, please seek professional help.<\/p>\n

All code in this post is solely intended to show you how to develop Tips. They serve no other purpose. To help you experiment I used Param() instead of hard-coding Tip properties:<\/p>\n

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

Have fun!<\/p>\n

\r<\/span>function <\/span>ShowTip<\/span>( <\/span>TipColor<\/span>, <\/span>TipOutlineColor<\/span>, <\/span>TipTextColor <\/span>)\r{\rglobal <\/span>MX<\/span>, <\/span>MY<\/span>, <\/span>PxWidth<\/span>, <\/span>PxHeight<\/span>, <\/span>TipWidth<\/span>, <\/span>TipHeight<\/span>, <\/span>TipsOn<\/span>, <\/span>TipFontName<\/span>, <\/span>TipFontSize<\/span>;\r<\/span>TipMsg <\/span>= <\/span>VarGetText<\/span>( <\/span>"TipMsg" <\/span>);\r\rif ( <\/span>TipsOn <\/span>AND <\/span>TipMsg <\/span>!= <\/span>"" <\/span>)\r{\r<\/span>Quadrant <\/span>= ( <\/span>MX <\/span>&<\/span>lt<\/span>; <\/span>pxwidth <\/span>\/ <\/span>2 <\/span>) + ( <\/span>MY <\/span>&<\/span>lt<\/span>; <\/span>pxheight <\/span>\/ <\/span>2 <\/span>) * <\/span>2<\/span>;\r<\/span>D\u00a0 <\/span>= <\/span>30<\/span>; <\/span>\/\/ Rounding Diameter\r\r<\/span>switch ( <\/span>Quadrant <\/span>)\r{\r\rcase <\/span>3<\/span>:\r<\/span>X1 <\/span>= <\/span>MX<\/span>;\r<\/span>Y1 <\/span>= <\/span>MY <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>X2 <\/span>= <\/span>MX <\/span>+ <\/span>TipWidth<\/span>;\r<\/span>Y2 <\/span>= <\/span>MY <\/span>+ <\/span>TipHeight <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>X3 <\/span>= <\/span>MX <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>Y3 <\/span>= <\/span>Y1<\/span>;\r<\/span>X4 <\/span>= <\/span>MX <\/span>+ <\/span>D <\/span>* <\/span>2<\/span>;\r<\/span>Y4 <\/span>= <\/span>Y1<\/span>;\r<\/span>X5 <\/span>= <\/span>MX<\/span>;\r<\/span>Y5 <\/span>= <\/span>MY<\/span>;\rbreak;\r\rcase <\/span>2<\/span>:\r<\/span>X1 <\/span>= <\/span>MX <\/span>- <\/span>TipWidth<\/span>;\r<\/span>Y1 <\/span>= <\/span>MY <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>X2 <\/span>= <\/span>MX<\/span>;\r<\/span>Y2 <\/span>= <\/span>MY <\/span>+ <\/span>TipHeight <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>X3 <\/span>= <\/span>MX <\/span>- <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>Y3 <\/span>= <\/span>Y1<\/span>;\r<\/span>X4 <\/span>= <\/span>MX <\/span>- <\/span>D <\/span>* <\/span>2<\/span>;\r<\/span>Y4 <\/span>= <\/span>Y1<\/span>;\r<\/span>X5 <\/span>= <\/span>MX<\/span>;\r<\/span>Y5 <\/span>= <\/span>MY<\/span>;\rbreak;\r\rcase <\/span>1<\/span>:\r<\/span>X1 <\/span>= <\/span>MX<\/span>;\r<\/span>Y1 <\/span>= <\/span>MY <\/span>- <\/span>TipHeight <\/span>- <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>X2 <\/span>= <\/span>X1 <\/span>+ <\/span>TipWidth<\/span>;\r<\/span>Y2 <\/span>= <\/span>Y1 <\/span>+ <\/span>TipHeight<\/span>;\r<\/span>X3 <\/span>= <\/span>MX <\/span>+ <\/span>2 <\/span>* <\/span>D<\/span>;\r<\/span>Y3 <\/span>= <\/span>Y2 <\/span>- <\/span>1<\/span>;\r<\/span>X4 <\/span>= <\/span>MX <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>Y4 <\/span>= <\/span>Y2 <\/span>- <\/span>1<\/span>;\r<\/span>X5 <\/span>= <\/span>MX<\/span>;\r<\/span>Y5 <\/span>= <\/span>y2 <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\rbreak;\r\rcase <\/span>0<\/span>:\r<\/span>X1 <\/span>= <\/span>MX <\/span>- <\/span>TipWidth<\/span>;\r<\/span>Y1 <\/span>= <\/span>MY <\/span>- <\/span>TipHeight <\/span>- <\/span>D <\/span>* <\/span>0.75<\/span>; <\/span>\/\/ Rectangle\r<\/span>X2 <\/span>= <\/span>X1 <\/span>+ <\/span>TipWidth<\/span>;\r<\/span>Y2 <\/span>= <\/span>Y1 <\/span>+ <\/span>TipHeight<\/span>;\r<\/span>X3 <\/span>= <\/span>X2 <\/span>- <\/span>2 <\/span>* <\/span>D<\/span>;\r<\/span>Y3 <\/span>= <\/span>Y2 <\/span>- <\/span>1<\/span>; <\/span>\/\/ Pointer\r<\/span>X4 <\/span>= <\/span>X2 <\/span>- <\/span>D <\/span>* <\/span>0.75<\/span>;\r<\/span>Y4 <\/span>= <\/span>Y2 <\/span>- <\/span>1<\/span>;\r<\/span>X5 <\/span>= <\/span>X2<\/span>;\r<\/span>Y5 <\/span>= <\/span>y2 <\/span>+ <\/span>D <\/span>* <\/span>0.75<\/span>;\rbreak;\r\rdefault:\r<\/span>x1 <\/span>= <\/span>x2 <\/span>= <\/span>x3 <\/span>= <\/span>x4 <\/span>= <\/span>x5 <\/span>= <\/span>y1 <\/span>= <\/span>y2 <\/span>= <\/span>y3 <\/span>= <\/span>y4 <\/span>= <\/span>y5 <\/span>= <\/span>0<\/span>;\r}\r\r<\/span>GfxSetBkMode<\/span>( <\/span>0 <\/span>);\r\r<\/span>GfxSelectPen<\/span>( <\/span>TipOutlineColor <\/span>);\r<\/span>GfxSetTextColor<\/span>( <\/span>TipTextColor <\/span>);\r<\/span>GfxSelectFont<\/span>( <\/span>TipFontname<\/span>, <\/span>TipFontSize <\/span>);\r<\/span>GfxSelectSolidBrush<\/span>( <\/span>TipColor <\/span>);\r<\/span>GfxRoundRect<\/span>( <\/span>X1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2<\/span>, <\/span>D<\/span>, <\/span>D <\/span>);\r<\/span>GfxPolygon<\/span>(<\/span>\u00a0\u00a0 X3<\/span>, <\/span>Y3 <\/span>, <\/span>X4 <\/span>, <\/span>Y4<\/span>, <\/span>X5<\/span>, <\/span>Y5 <\/span>);<\/span>\u00a0\u00a0\u00a0\u00a0 <\/span>\/\/ Pointer\r<\/span>GfxSelectPen<\/span>( <\/span>TipColor <\/span>); <\/span>\/\/ Hide line between RoundRect and Pointer\r<\/span>GfxMoveTo<\/span>( <\/span>X3<\/span>, <\/span>Y3 <\/span>);\r<\/span>GfxLineTo<\/span>( <\/span>X4<\/span>, <\/span>Y4 <\/span>);\r<\/span>GfxDrawText<\/span>( <\/span>TipMsg<\/span>, <\/span>x1 <\/span>+ <\/span>10<\/span>, <\/span>y1 <\/span>+ <\/span>3<\/span>, <\/span>x2 <\/span>- <\/span>10<\/span>, <\/span>y2 <\/span>- <\/span>5<\/span>, <\/span>16 <\/span>+ <\/span>65 <\/span>);\r}\r}\r\rfunction <\/span>TestObject<\/span>( <\/span>Label<\/span>, <\/span>X1<\/span>, <\/span>Y1<\/span>, <\/span>X2<\/span>, <\/span>Y2<\/span>, <\/span>Color <\/span>) <\/span>\/\/ Do-Nothing Demo function only\r<\/span>{\r<\/span>GfxSelectPen<\/span>( <\/span>colorBlack <\/span>);\r<\/span>GfxSelectSolidBrush<\/span>( <\/span>Color <\/span>);\r<\/span>GfxRectangle<\/span>( <\/span>X1<\/span>, <\/span>y1<\/span>, <\/span>x2<\/span>, <\/span>y2 <\/span>);\r<\/span>OverObject <\/span>= <\/span>MX <\/span>&<\/span>gt<\/span>; <\/span>x1 <\/span>AND <\/span>MX <\/span>&<\/span>lt<\/span>; <\/span>x2 <\/span>AND <\/span>MY <\/span>&<\/span>gt<\/span>; <\/span>y1 <\/span>AND <\/span>MY <\/span>&<\/span>lt<\/span>; <\/span>y2<\/span>;\r\rif ( <\/span>OverObject <\/span>)\r<\/span>VarSetText<\/span>( <\/span>"TipMsg"<\/span>, <\/span>"The cursor is now over the " <\/span>+ <\/span>Label <\/span>+\r<\/span>" quadrant and the shape of the Tip is adjusted accordingly." <\/span>);\r\rreturn <\/span>OverObject<\/span>;\r}\r\r<\/span>\/\/ Global variables and parameters can be hard-coded in the final application\r<\/span>global <\/span>MX<\/span>, <\/span>MY<\/span>, <\/span>PxWidth<\/span>, <\/span>PxHeight<\/span>, <\/span>TipWidth<\/span>, <\/span>TipHeight<\/span>, <\/span>TipsOn<\/span>, <\/span>FontName<\/span>, <\/span>FontSize<\/span>;\r<\/span>TipColor\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>ParamColor<\/span>( <\/span>"Tip Background Color"<\/span>, <\/span>colorWhite <\/span>);\r<\/span>TipOutlineColor <\/span>= <\/span>ParamColor<\/span>( <\/span>"Tip Outline Color"<\/span>, <\/span>colorBlack <\/span>);\r<\/span>TipTextColor\u00a0\u00a0 <\/span>= <\/span>ParamColor<\/span>( <\/span>"Tip Text Color"<\/span>, <\/span>colorBlack <\/span>);\r<\/span>TipsOn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>ParamToggle<\/span>( <\/span>"Tips On"<\/span>, <\/span>"OFF|ON"<\/span>, <\/span>1 <\/span>);\r<\/span>TipFontSize\u00a0\u00a0\u00a0 <\/span>= <\/span>Param<\/span>( <\/span>"Font Size"<\/span>, <\/span>9<\/span>, <\/span>0<\/span>, <\/span>24<\/span>, <\/span>1 <\/span>);\r<\/span>TipWidth\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>Param<\/span>( <\/span>"Tip Width"<\/span>, <\/span>220<\/span>, <\/span>50<\/span>, <\/span>500<\/span>, <\/span>10 <\/span>);\r<\/span>TipHeight\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>Param<\/span>( <\/span>"Tip Height"<\/span>, <\/span>80<\/span>, <\/span>50<\/span>, <\/span>500<\/span>, <\/span>10 <\/span>);\r<\/span>TipFontName\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>ParamStr<\/span>( <\/span>"Tip Font name"<\/span>, <\/span>"Lucida Console" <\/span>);\r\r<\/span>GfxSetBkMode<\/span>( <\/span>1 <\/span>);\r<\/span>GfxSetOverlayMode<\/span>( <\/span>0 <\/span>);\r<\/span>RequestTimedRefresh<\/span>( <\/span>0.1 <\/span>);\r<\/span>MX\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>GetCursorXPosition<\/span>( <\/span>1 <\/span>);\r<\/span>MY\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span>= <\/span>GetCursorYPosition<\/span>( <\/span>1 <\/span>);\r<\/span>PxWidth\u00a0\u00a0\u00a0 <\/span>= <\/span>Status<\/span>( <\/span>"pxwidth" <\/span>);\r<\/span>PxHeight\u00a0\u00a0\u00a0 <\/span>= <\/span>Status<\/span>( <\/span>"pxheight" <\/span>);\r\r<\/span>\/\/ In a real application each colored area could be s small button\r<\/span>TestObject<\/span>( <\/span>"UpperLeft"<\/span>, <\/span>0<\/span>, <\/span>0<\/span>, <\/span>pxwidth <\/span>\/ <\/span>2<\/span>, <\/span>pxheight <\/span>\/ <\/span>2<\/span>, <\/span>colorRed <\/span>);\r<\/span>TestObject<\/span>( <\/span>"UpperRight"<\/span>, <\/span>pxwidth <\/span>\/ <\/span>2<\/span>, <\/span>0<\/span>, <\/span>pxwidth<\/span>, <\/span>pxheight <\/span>\/ <\/span>2<\/span>, <\/span>colorBlue <\/span>);\r<\/span>TestObject<\/span>( <\/span>"LowerLeft"<\/span>, <\/span>0<\/span>, <\/span>pxheight <\/span>\/ <\/span>2<\/span>, <\/span>pxwidth <\/span>\/ <\/span>2<\/span>, <\/span>pxheight<\/span>, <\/span>colorYellow <\/span>);\r<\/span>TestObject<\/span>( <\/span>"Lowerright"<\/span>, <\/span>pxwidth <\/span>\/ <\/span>2<\/span>, <\/span>pxheight <\/span>\/ <\/span>2<\/span>, <\/span>pxwidth<\/span>, <\/span>pxheight<\/span>, <\/span>colorBrightGreen <\/span>);\r\r<\/span>ShowTip<\/span>( <\/span>TipColor<\/span>, <\/span>TipOutlineColor<\/span>, <\/span>TipTextColor <\/span>); <\/span>\/\/ Place this call at the very endo of your code\r<\/span><\/pre>\n","protected":false},"excerpt":{"rendered":"

If you write AmiBroker programs that are used by others you have undoubtedly found that documenting your program and answering hundreds of emails can be very time consuming. You can save yourself, and those who use your code, a lot of time by adding Help popups (Tips) to your programs. No longer will users have […]<\/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\/1949"}],"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=1949"}],"version-history":[{"count":52,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts\/1949\/revisions"}],"predecessor-version":[{"id":2005,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/posts\/1949\/revisions\/2005"}],"wp:attachment":[{"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/media?parent=1949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/categories?post=1949"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.amibroker.org\/editable_userkb\/wp-json\/wp\/v2\/tags?post=1949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}