/*----------------------------------------------------------------------------*/ /* */ /* Copyright (c) 2012-2021 Rexx Language Association. All rights reserved. */ /* */ /* This program and the accompanying materials are made available under */ /* the terms of the Common Public License v1.0 which accompanies this */ /* distribution. A copy is also available at the following address: */ /* https://www.oorexx.org/license.html */ /* */ /* Redistribution and use in source and binary forms, with or */ /* without modification, are permitted provided that the following */ /* conditions are met: */ /* */ /* Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in */ /* the documentation and/or other materials provided with the distribution. */ /* */ /* Neither the name of Rexx Language Association nor the names */ /* of its contributors may be used to endorse or promote products */ /* derived from this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */ /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* */ /*----------------------------------------------------------------------------*/ /** * ToolTip control example. * * This example demonstrates some fundemental use of the TooTip control. It * creates a tool tip for each push button in the dialog and tool tips for some * rectangular areas in the dialog itself. * * There is a 'Test' push button in the dialog. When this button is pushed, * several short demonstrations are executed that show some of the additional * ToolTip methods at work. These demonstrations print to the screen using say * statements. Therefore it is best to run this example program from a standard * console window so that the output can be seen. * */ -- Set this application to use the global .constDir Only. Then add our -- symbolic IDs to the .constDir. .application~setDefaults('O', , .false) .constDir[IDC_TT_MAIN ] = 500 .constDir[IDC_TT_OK] = 501 .constDir[IDC_TT_CANCEL] = 502 .constDir[IDC_TT_TEST] = 503 .constDir[IDTOOL_DLG_RECT1] = 774 .constDir[IDTOOL_DLG_RECT2] = 775 .constDir[IDTOOL_DLG_RECT3] = 776 .constDir[IDTOOL_DLG_RECT4] = 777 .constDir[IDC_PB_TEST] = 600 -- Instantiate our dialog and execute it. dlg = .ToolTipDialog~new dlg~execute("SHOWTOP", IDI_DLG_OOREXX) return 0 ::requires "ooDialog.cls" ::class 'ToolTipDialog' subclass UserDialog /** init() * * Usual init() method for a UserDialog subclass. We initialize the super class * and then create the dialog frame to get things started. * * We also use this method to create an icon image. This image is used for the * balloon ToolTip. */ ::method init expose icon forward class (super) continue -- Locate our icon file srcDir = locate() icon = .Image~getImage(srcDir"musicNote.ico", ICON, .size~new(16, 16)) self~create(30, 30, 257, 123, "ToolTip Example Dialog", "CENTER") /** defineDialog() * * Usual defineDialog() method. We add 3 push buttons to the dialog template. */ ::method defineDialog self~createPushButton(IDC_PB_TEST, 10, 99, 50, 14, , "Test", onTest) self~createPushButton(IDOK, 142, 99, 50, 14, "DEFAULT", "Ok") self~createPushButton(IDCANCEL, 197, 99, 50, 14, , "Cancel") /** initDialog() * * Usual initDialog() method. * * However, note that ToolTip controls can not be added to the dialog template. * They *have* to be created *after* the underlying dialog exists. Typically, * ToolTips would always be created in the initDialog() method. */ ::method initDialog unguarded expose icon pbTest count ttTest -- The main tool tip is set up in a private method, so that the code for it -- can be inspected without distraction. self~createMainToolTip -- Creat a somewhat fancy balloon tool tip for the Ok button. ttOk = self~createToolTip(IDC_TT_OK, 'BALLOON CLOSE') ttOk~setTitle("Important Message", icon) text = 'Push the'.endOfLine'Ok button'.endOfLine'to end this'.endOfLine'foolishness' ttOk~addTool(self~newPushButton(IDOK), text) -- Create a simple multiline tool tip for the Cancel push button. The tool -- tip is turned into a multiline tool tip by seeting the max tool tip -- width. ttEsc = self~createToolTip(IDC_TT_CANCEL) ttEsc~addTool(self~newPushButton(IDCANCEL), 'Press Cancel to end the dialog') margins = 2 * 4 s = self~getTextSizePX('Press Cancel') ttEsc~setMaxTipWidth(s~width + margins) -- Create a tool tip for the Test push button. pbTest = self~newPushButton(IDC_PB_TEST) ttTest = self~createToolTip(IDC_TT_TEST) ttTest~addTool(pbTest) self~connectToolTipEvent(IDC_TT_TEST, 'NEEDTEXT') count = 0 /** createMainToolTip() * * This is a private method we use to set up the main ToolTip. We do the set * up here so that the code for the set up can be studied without any other * distractions. */ ::method createMainToolTip private expose tt clRect1 clRect2 clRect3 clRect4 tt = self~createToolTip(IDC_TT_MAIN) -- We divide the client area of the dialog into 4 quadrants and then add a -- tool for each quandrant to the main tool tip. clRect = self~clientRect hMidpoint = trunc((clRect~right - clRect~left) / 2) + clRect~left vMidpoint = trunc((clRect~bottom - clRect~top) / 2) + clRect~top clRect1 = .Rect~new(clRect~left, clRect~top, hMidpoint, vMidpoint) clRect2 = .Rect~new(hMidpoint + 1, clRect~top, clRect~right, vMidpoint + 1) clRect3 = .Rect~new(clRect~left, vMidpoint + 1, hMidpoint + 1, clRect~bottom) clRect4 = .Rect~new(hMidpoint + 1, vMidpoint + 1, clRect~right, clRect~bottom) ret = tt~addToolRect(self, IDTOOL_DLG_RECT1, clRect1, 'Over main dialog, top left quadrant', 'TRANSPARENT') ret = tt~addToolRect(self, IDTOOL_DLG_RECT2, clRect2, 'Over main dialog, top right quadrant', 'TRANSPARENT') ret = tt~addToolRect(self, IDTOOL_DLG_RECT3, clRect3, 'Over main dialog, bottom left quadrant', 'TRANSPARENT') ret = tt~addToolRect(self, IDTOOL_DLG_RECT4, clRect4, 'Over main dialog, bottom right quadrant', 'TRANSPARENT') -- Connect the SHOW event so that we can position the tool tip text where -- we want it. The SHOW notification is sent right before the tool tip is -- going to display its window. self~connectToolTipEvent(IDC_TT_MAIN, 'SHOW') /** onShow() * * This is the event handler for the ToolTip SHOW event. It is invoked right * before the ToolTip is about to show its display window. * * One of the uses for this event is to customize the position of the window. * To customize the window position, the programmer calculates where he wants * the window to be position and then uses the setWindowPos() method to place * the window. When the position is set by the programmer, the event handler * needs to return .true to inform the ToolTip not to position the window in its * default position. If .false is returned, then the ToolTip positions its * window where it normally would. * * We use this event handler to place the text for each tool in the main ToolTip * at the top left-hand corner of its rectangle. */ ::method onShow unguarded expose clRect1 clRect2 clRect3 clRect4 use arg toolID, toolTip -- Determine the position for the tool about to be displayed: select when toolID == .constDir[IDTOOL_DLG_RECT1] then pos = .Point~new(clRect1~left, clRect1~top) when toolID == .constDir[IDTOOL_DLG_RECT2] then pos = .Point~new(clRect2~left, clRect2~top) when toolID == .constDir[IDTOOL_DLG_RECT3] then pos = .Point~new(clRect3~left, clRect3~top) when toolID == .constDir[IDTOOL_DLG_RECT4] then pos = .Point~new(clRect4~left, clRect4~top) otherwise pos = .Point~new end -- End select -- Position the ToolTip window where we want it: self~client2screen(pos) toolTip~setWindowPos(TOPMOST, pos, .Size~new(0, 0), "NOACTIVATE NOSIZE NOZORDER") -- Return .true so that the ToolTip knows not to position the window itself. return .true /** onNeedText() * * This is the event handler for the ToolTip NEEDTEXT event. It is invoked when * a ToolTip control needs the text to display in its window. * * The notification is generated when there is no text assigned to a tool, of if * the special string: "TextCallBack" is assigned as the text of a tool. * * The event handler must return .true or .false. It .true is returned, that * tells the ToolTip to store the returned text and not ask for it again. If * .false is returned, then the ToolTip will ask for the text each time the * window is about to be displayed. * * The text itself is returned in the info object. This is a .Directory object. * The returned text is placed at the TEXT index. */ ::method onNeedText unguarded use arg id, toolTip, info info~text = 'Press Test to execute a ToolTip test' return .true /** onTest() * * This is the event handler for the button CLICK event. It is invoked when the * 'Test' push button is pressed or clicked. * * We use this to demonstrate some of the methods of the ToolTip class. */ ::method onTest unguarded expose tt ttTest pbTest count reply 0 count += 1 select when count == 1 then do do i = 1 to tt~getToolCount toolInfo = tt~enumTools(i) say 'Tool info hwnd: ' toolInfo~rexxHwnd say 'Tool info id: ' toolInfo~rexxID say 'Tool info text: ' toolInfo~text say 'Tool info flags: ' toolInfo~flags say 'Tool info rect: ' toolInfo~rect say 'Tool info userData:' toolInfo~userData say 'Tool info resource:' toolInfo~resource say end end when count == 2 then do time = tt~getDelayTime say 'Time for autopop:' time say time = tt~getDelayTime('AUTOPOP') say 'Time for autopop:' time say time = tt~getDelayTime('INITIAL') say 'Time for initial:' time say time = tt~getDelayTime('RESHOW') say 'Time for reshow:' time say end when count == 3 then do mouse = .Mouse~new(self) pos = mouse~getCursorPos pbTest~screen2client(pos) hitTool = .ToolInfo~forHitTest(pbTest) if ttTest~hitTestInfo(hitTool, pos) then do say 'Got hit' say 'Tool info hwnd: ' hitTool~rexxHwnd say 'Tool info id: ' hitTool~rexxID say 'Tool info text: ' hitTool~text say 'Tool info flags: ' hitTool~flags say 'Tool info rect: ' hitTool~rect say 'Tool info userData:' hitTool~userData say 'Tool info resource:' hitTool~resource say end else do say 'NO hit' say 'Tool info hwnd: ' hitTool~rexxHwnd~hwnd say 'Test push button hwnd:' pbTest~hwnd say end end otherwise do count = 0 say 'No test for this push. Going to recycle.' say end end -- End select return