762 lines
36 KiB
Rexx
Executable File
762 lines
36 KiB
Rexx
Executable File
/*----------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (c) 2011-2014 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. */
|
|
/* */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* An example program showing how to work with the mouse wheel.
|
|
*
|
|
* The ooDialog programmer can capture mouse wheel event by using the
|
|
* connectEvent() method of the .Mouse class. The event handler for the
|
|
* connection will be invoked each time the user turns the scroll wheel on the
|
|
* mouse. The event handler can then use the arguments passed to it to do
|
|
* custom scrolling.
|
|
*
|
|
* Read throught the code comments to understand how this works.
|
|
*
|
|
* The dialog for this program contains a large multi-line edit control with a
|
|
* number of lines in it. For each turn of the mouse scroll wheel, the text in
|
|
* the edit control is scrolled 1 line. If the shift key is held down while
|
|
* turning the mouse scroll wheel, the text is scrolled 3 lines instead of 1.
|
|
* If the control key is down, the text is scrolled 1 page and if both the
|
|
* shift and control keys are down, the text is scrolled 3 pages.
|
|
*
|
|
* The Help button in the dialog displays text explaining the dialog. Use the
|
|
* help button to see the expected behavior of the dialog and compare the
|
|
* behavior with the implementing code in this file.
|
|
*/
|
|
|
|
-- First we locate the direcotry our source code is in. This allows us to
|
|
-- build complete path names to our resource files, which in turn allows this
|
|
-- program to be run from anywhwere on the computer. For instance the program
|
|
-- file can be dragged and dropped on ooDialog.exe and it will run correctly.
|
|
srcDir = locate()
|
|
|
|
-- When programmers wish to use symbolic resource IDs in their programs, as
|
|
-- this program does, it is much easier to use the global constant directory,
|
|
-- (.constDir,) rather than the constDir attribute of a dialog. Using the
|
|
-- .constDir Only is by far the most efficient way to use symbolic IDs.
|
|
--
|
|
-- The use of the global constant directory is controlled by the .Application
|
|
-- object. The .Application object is also used to set other application-wide
|
|
-- defaults or values. In this program, we also want to make the default for
|
|
-- automatic data detection to be off. Both of these requirements can be done
|
|
-- with one method call to the .Application object. As a convenience, the
|
|
-- setDefaults() method will also populate the .constDir with symbols.
|
|
--
|
|
-- In this invokcation, the application is set to use the .constDir only, "O",
|
|
-- symbols are loaded into the .constDir from the file: ContextMenu.h, and the
|
|
-- default for automatic data detection is set to off (.false.)
|
|
.application~setDefaults('O', srcDir'mouseWheel.h', .false)
|
|
|
|
dlg = .MouseDemo~new(srcDir"mouseWheel.rc", IDD_MOUSE_DLG)
|
|
|
|
if dlg~initCode <> 0 then do
|
|
msg = "Error initializing the Mouse Wheel Demonstration dialog." || '0d0a0d0a'x || -
|
|
"This example will have to quit."
|
|
j = MessageDialog(msg, 0, "Application Error", "OK", "ERROR")
|
|
return 99
|
|
end
|
|
|
|
dlg~execute("SHOWTOP")
|
|
return 0
|
|
|
|
::requires 'ooDialog.cls'
|
|
|
|
::class 'MouseDemo' subclass RcDialog
|
|
|
|
/** initDialog()
|
|
*
|
|
* The ooDialog framework automatically invokes the initDialog() method
|
|
* immediately after the underlying Windows dialog is created. This makes it
|
|
* the correct place to do any initialization that requires the underlying
|
|
* dialog and dialog controls to exist.
|
|
*
|
|
* This is a typical initDialog(), but take note of these points. The mouse
|
|
* wheel event notification is sent by the operating system to the window with
|
|
* the current input focus. If the window does not process the message, then
|
|
* the OS sends the message to the parent window of that window. This continues
|
|
* on up the parent / child window chain until either a window does process the
|
|
* notification or the top of the chain is reached.
|
|
*
|
|
* Multi-line edit controls *do* process the notification and normally handle
|
|
* their own scrolling. Because of this, we need to get two mouse objects. One
|
|
* for this dialog and one for the edit control. We then connect the mouse
|
|
* wheel event in both mouse objects to a method in this dialog.
|
|
*/
|
|
::method initDialog
|
|
expose eData pbOk eCommand process
|
|
|
|
-- Connect the help key event to our onHelp() method.
|
|
self~connectHelp(onHelp)
|
|
|
|
eData = self~newEdit(IDC_EDIT_DATA)
|
|
|
|
-- Get a mouse object for the edit control and connect the mouse wheel event.
|
|
-- There are several options of how to handle this. We could, using options
|
|
-- to connectEvent(), either have the edit control's mouse wheel events
|
|
-- connect to the same method as we connect the the dialog's mouse wheel
|
|
-- events to, or have them connect to a separate method.
|
|
--
|
|
-- In this case we choose the later, and specify the onEditMouseWheel()
|
|
-- method.
|
|
--
|
|
-- Note that onEditMouseWheel() method will only be invoked when the
|
|
-- IDC_EDIT_DATA edit control has the focus.
|
|
mouse = .Mouse~new(eData)
|
|
mouse~connectEvent('MOUSEWHEEL', onEditMouseWheel)
|
|
|
|
-- Connect all mouse wheel events that reach the dialog to a method in this
|
|
-- dialog. The default method name is onMouseWheel, so we omit the method
|
|
-- name arugment and name our method in this dialog: 'onMousWheel'.
|
|
--
|
|
-- Note that this onMouseWheel() method will never be invoked if the
|
|
-- IDC_EDIT_DATA edit control has the focus.
|
|
mouse = .Mouse~new(self)
|
|
mouse~connectEvent('MOUSEWHEEL')
|
|
|
|
-- Set up the radio buttons, connect a click event on any of them to our
|
|
-- single onRbSelect() method.
|
|
self~connectButtonEvent(IDC_RB_ANYWHERE , 'CLICKED', onRbSelect)
|
|
self~connectButtonEvent(IDC_RB_DIALOG , 'CLICKED', onRbSelect)
|
|
self~connectButtonEvent(IDC_RB_ON_EDIT_OK , 'CLICKED', onRbSelect)
|
|
self~connectButtonEvent(IDC_RB_FOCUSED_ANYWHERE, 'CLICKED', onRbSelect)
|
|
self~connectButtonEvent(IDC_RB_FOCUSED_DIALOG , 'CLICKED', onRbSelect)
|
|
self~connectButtonEvent(IDC_RB_FOCUSED_EDIT , 'CLICKED', onRbSelect)
|
|
|
|
-- Set the initial checked state to the 'Mouse is anywhere' radio button.
|
|
self~newRadioButton(IDC_RB_ANYWHERE)~check
|
|
process = "ANYWHERE"
|
|
|
|
-- Save a reference to the ok push button and the single-line edit control.
|
|
pbOk = self~newPushButton(IDOK)
|
|
eCommand = self~newEdit(IDC_EDIT_COMMAND)
|
|
|
|
-- Fill the edit control with data so we can see the scrolling.
|
|
text = ''
|
|
do i = 1 to 300
|
|
text ||= 'Line number' || '09'x || i || '09'x || 'Mouse Wheel Demonstation' || .endOfLine
|
|
end
|
|
eData~setText(text)
|
|
|
|
|
|
/** onMouseWheel()
|
|
*
|
|
* This is an event handler for the mouse wheel event. Three arguments are
|
|
* sent to the event handler by the ooDialog framework.
|
|
*
|
|
* @param state A list of keywords that indicate the keyboard and mouse button
|
|
* modifiers. The list of possible words is exactly:
|
|
*
|
|
* None Control lButton mButton rButton Shift xButton1 xButton2
|
|
*
|
|
* The none keyword will always be by itself, otherwise, the list
|
|
* can consist of one or more of the keywords.
|
|
*
|
|
* @param pos A .Point object that represents the position of the mouse
|
|
* pointer on the screen. This is in screen co-ordinates, in
|
|
* pixels.
|
|
*
|
|
* @param mouse The mouse object that connected this event. For our purposes
|
|
* we don't need the mouse so we just ignore this argument.
|
|
*
|
|
* @param delta A whole number that represents the amount the scroll wheel was
|
|
* turned. The number will always be a multiple of 120 because
|
|
* that is what the operating system sends. If the number is
|
|
* positive, the user turned the wheel away from herself and
|
|
* indicates to scroll up. When negative the user turned the
|
|
* wheel towards himself, and indicates to scroll down.
|
|
*
|
|
* At this point in time (c. 2011) the OS sends the event
|
|
* notification for each notch of the scroll wheel and so delta
|
|
* will always be 120 or -120.
|
|
*
|
|
* Because of the 2 mouse~connectEvent() calls in initDialog() the method will
|
|
* only be called when the dialog is the active window and the multi-line edit
|
|
* control does *not* have the focus. We simply delegate to the maybeScroll()
|
|
* method, passing on 3 of the arguments and .false to indicate the edit control
|
|
* does not have the focus.
|
|
*/
|
|
::method onMouseWheel unguarded
|
|
use arg state, pos, mouse, delta
|
|
|
|
return self~maybeScroll(delta, state, pos, .false)
|
|
|
|
|
|
/** onEditMouseWheel
|
|
*
|
|
* This is an event handler for the mouse wheel event. The arguments are
|
|
* explained in the comment header for onMouseWheel().
|
|
*
|
|
* Because of the 2 mouse~connectEvent() calls in initDialog() this method will
|
|
* *only* be called when the edit control has the focus.
|
|
*
|
|
* We simply delegate to the maybeScroll() method, passing on the 3 arguments
|
|
* and .true to indicate the edit control has the focus.
|
|
*/
|
|
::method onEditMouseWheel unguarded
|
|
use arg state, pos, mouse, delta
|
|
|
|
return self~maybeScroll(delta, state, pos, .true)
|
|
|
|
|
|
/** maybeScroll
|
|
* Based on the arguments, we determine whether to scroll or not.
|
|
*
|
|
* In all cases .true is returned, which is eventually returned by the
|
|
* event handler. This indicates that the event message was processed.
|
|
*/
|
|
::method maybeScroll private
|
|
expose process eData
|
|
use strict arg delta, state, pos, focused
|
|
|
|
-- Eliminate some easy stuff
|
|
if process~abbrev("FOCUSED"), \ focused then return 0
|
|
|
|
select
|
|
when process~right(8) == "ANYWHERE" then return self~scroll(delta, state)
|
|
when process~right(6) == "DIALOG" then return self~scrollOnDialog(delta, state, pos)
|
|
when process == "ON_EDIT_OK" then return self~scrollOnControls(delta, state, pos)
|
|
when process == "FOCUSED_EDIT", focused then return self~scrollOnEdit(delta, state, pos)
|
|
otherwise do
|
|
return .true
|
|
end
|
|
end
|
|
-- End select
|
|
|
|
|
|
/** scrollOnDialog()
|
|
*
|
|
* Determines if the position of the cursor (pos) is over the dialog window. If
|
|
* it is, we scroll, otherwise we do not scroll.
|
|
*
|
|
* In all cases .true is returned, which is eventually returned by the
|
|
* event handler. This indicates that the event message was processed.
|
|
*/
|
|
::method scrollOnDialog private
|
|
use strict arg delta, state, pos
|
|
|
|
if pos~inRect(self~windowRect) then return self~scroll(delta, state)
|
|
|
|
return .true
|
|
|
|
/** scrollOnEdit()
|
|
*
|
|
* Determines if the position of the cursor (pos) is over the multi-line edit
|
|
* control. If it is, we scroll, otherwise we do not scroll.
|
|
*
|
|
* In all cases .true is returned, which is eventually returned by the
|
|
* event handler. This indicates that the event message was processed.
|
|
*/
|
|
::method scrollOnEdit private
|
|
expose eData
|
|
use strict arg delta, state, pos
|
|
|
|
if pos~inRect(eData~windowRect) then return self~scroll(delta, state)
|
|
|
|
return .true
|
|
|
|
|
|
/** scrollOnControls()
|
|
*
|
|
* Determines if the position of the cursor (pos) is over one of the edit
|
|
* controls, or over the Ok button. If it is, we scroll, otherwise we do not
|
|
* scroll.
|
|
*
|
|
* In all cases .true is returned, which is eventually returned by the
|
|
* event handler. This indicates that the event message was processed.
|
|
*/
|
|
::method scrollOnControls private
|
|
expose eData pbOk eCommand
|
|
use strict arg delta, state, pos
|
|
|
|
if pos~inRect(eData~windowRect) | pos~inRect(eCommand~windowRect) | -
|
|
pos~inRect(pbOk~windowRect) then do
|
|
return self~scroll(delta, state)
|
|
end
|
|
|
|
return .true
|
|
|
|
|
|
/** scroll()
|
|
*
|
|
* This private method is where the scrolling is actually done. It is called
|
|
* by other methods that have determined the mouse is in the correct place for
|
|
* scrolling to happen. delta and state are the orignal arguments sent to the
|
|
* mouse wheel event handler. See onMouseWheel() and onEditMouseWheel() for
|
|
* the explanation of the arguments.
|
|
*
|
|
* Based on the arguments, we have the edit control scroll the appropriate
|
|
* amount. In all cases we return .true which is eventually returned by the
|
|
* event handler. This indicates that the event message was processed.
|
|
*/
|
|
::method scroll private
|
|
expose eData
|
|
use strict arg delta, state
|
|
|
|
if delta < 0 then do
|
|
select
|
|
when state == 'None' then eData~scrollCommand("DOWN")
|
|
|
|
when state~wordPos('Control') <> 0, state~wordPos('Shift') <> 0 then do
|
|
-- Scroll 3 pages down.
|
|
eData~scrollCommand('PAGEDOWN', 3)
|
|
end
|
|
|
|
when state~wordPos('Control') <> 0 then do
|
|
-- Scroll page down.
|
|
eData~scrollCommand('PAGEDOWN')
|
|
end
|
|
|
|
when state~wordPos('Shift') <> 0 then do
|
|
-- Scroll 3 lines down.
|
|
eData~scrollCommand('DOWN', 3)
|
|
end
|
|
|
|
otherwise do
|
|
-- Ignore all others and scroll 1 line.
|
|
eData~scrollCommand("DOWN")
|
|
end
|
|
end
|
|
-- End select
|
|
end
|
|
else do
|
|
-- Same as above, but scroll up.
|
|
select
|
|
when state == 'None' then eData~scrollCommand("UP")
|
|
|
|
when state~wordPos('Control') <> 0, state~wordPos('Shift') <> 0 then do
|
|
-- Scroll 3 pages down.
|
|
eData~scrollCommand('PAGEUP', 3)
|
|
end
|
|
|
|
when state~wordPos('Control') <> 0 then do
|
|
-- Scroll page down.
|
|
eData~scrollCommand('PAGEUP')
|
|
end
|
|
|
|
when state~wordPos('Shift') <> 0 then do
|
|
-- Scroll 3 lines down.
|
|
eData~scrollCommand('UP', 3)
|
|
end
|
|
|
|
otherwise do
|
|
-- Ignore all others and scroll 1 line.
|
|
eData~scrollCommand("UP")
|
|
end
|
|
end
|
|
-- End select
|
|
end
|
|
|
|
return .true
|
|
|
|
|
|
/** onRbSelect()
|
|
*
|
|
* This is the event handler for a button click on one of the radio buttons.
|
|
*
|
|
* With auto radio buttons, (which the radio buttons in this program are,) when
|
|
* a radio button is clicked, it is automatically set to the selected state.
|
|
*
|
|
* Each time a radio button becomes the selected button, we update the process
|
|
* variable. That way 'process' always reflects which radio button is currently
|
|
* selected.
|
|
*
|
|
* The event handler is sent five arguments. However the first two are left
|
|
* over from the old IBM ooDialog implementation and we ignore them. We only
|
|
* need the third 'id' argument, so we ignore the last two args also.
|
|
*/
|
|
::method onRbSelect
|
|
expose process
|
|
use arg , , id
|
|
|
|
select
|
|
when id == .ConstDir[IDC_RB_ANYWHERE ] then process = "ANYWHERE"
|
|
when id == .ConstDir[IDC_RB_DIALOG ] then process = "DIALOG"
|
|
when id == .ConstDir[IDC_RB_ON_EDIT_OK ] then process = "ON_EDIT_OK"
|
|
when id == .ConstDir[IDC_RB_FOCUSED_ANYWHERE] then process = "FOCUSED_ANYWHERE"
|
|
when id == .ConstDir[IDC_RB_FOCUSED_DIALOG ] then process = "FOCUSED_DIALOG"
|
|
when id == .ConstDir[IDC_RB_FOCUSED_EDIT ] then process = "FOCUSED_EDIT"
|
|
otherwise
|
|
nop
|
|
end
|
|
-- End select
|
|
|
|
|
|
/** help()
|
|
*
|
|
* This is the event handler for the IDHELP command. Any button or menu item
|
|
* with the resource ID of IDHELP will generate the HELP command event. The
|
|
* ooDialog framework automatically connects the IDOK, IDCANCEL, and IDHELP
|
|
* commands to the ok(), cancel(), and help() methods in the dialog object.
|
|
*
|
|
* The default help() method does nothing. To do something the programmer over-
|
|
* rides the method in her subclass. Here we simply invoke the onHelp() method
|
|
* to do the work.
|
|
*
|
|
* Do not confuse the HELP command event with the help key (F1) event.
|
|
*/
|
|
::method help
|
|
self~onHelp
|
|
|
|
/** onHelp()
|
|
*
|
|
* This is the event handler for the help key (F1) event. The event is
|
|
* generated when the user presses the F1 key.
|
|
*
|
|
* The programmer connects this event to a method in the Rexx dialog by using
|
|
* the connectHelp() method. Here in this event handler, we show a modal dialog
|
|
* with some help text.
|
|
*
|
|
* Do not confuse the help key (F1) event with the HELP command event.
|
|
*/
|
|
::method onHelp
|
|
.MouseDemoHelp~new(.application~srcDir'mouseWheel.rc', IDD_HELP)~execute("SHOWTOP")
|
|
|
|
|
|
/** class::MouseDemoHelp
|
|
*
|
|
* This is a very simple dialog subclass whose purpose is to display the help
|
|
* text for the Mouse Wheel Demonstration program.
|
|
*
|
|
* Note that we set up our own handlers for the mouse wheel event for the help
|
|
* text simply to provide more example code. There is really not much need to
|
|
* do this. The edit control by default handles the scrolling for the mouse
|
|
* wheel itself. There is not a compelling reason in this dialog to not simply
|
|
* let the edit control handle the scrolling for us. (Other than the reason
|
|
* mentioned, to provide more code example.)
|
|
*/
|
|
::class 'MouseDemoHelp' subclass RcDialog
|
|
|
|
::method initDialog
|
|
expose newFont e visibleLines
|
|
|
|
-- Connect the mouse wheel event to a method in this dialog. We don't specify
|
|
-- a method name, we'll just accept the default name of onMouseWheel.
|
|
.Mouse~new(self)~connectEvent('MOUSEWHEEL')
|
|
|
|
e = self~newEdit(IDC_HELP_TEXT)
|
|
|
|
-- In this case we have the edit control not process the mouse wheel, but
|
|
-- rather pass the message on to the dialog. The fourth optional parameter of
|
|
-- SENDTODLG is a keyword that causes the mouse wheel notfication to be
|
|
-- passed on up the parent / child window chain and not sent to the edit
|
|
-- control.
|
|
--
|
|
-- The effect of this is that the edit control never even sees the
|
|
-- notification, allowing our onMouseWheel() method to handle all mouse wheel
|
|
-- notifications, not matter where the mouse is over our dialog.
|
|
.Mouse~new(e)~connectEvent('MOUSEWHEEL', 'NOOP', , "SENDTODLG")
|
|
|
|
-- Create a mono-spaced font for the edit control that displays the help text.
|
|
newFont = self~createFontEx('Courier New', 9)
|
|
|
|
-- Set the font of the edit control to our custom font, set the text of the
|
|
-- edit control to our help text.
|
|
e~setFont(newFont)
|
|
e~setText(getHelpText())
|
|
|
|
-- visibleLines is the number of visible lines in the edit control. It is
|
|
-- only used if the user scrolls the help text using the mouse wheel. So, we
|
|
-- use lazy evaluation. It is only calculated if needed.
|
|
visibleLines = 0
|
|
|
|
|
|
/** onMouseWheel
|
|
*
|
|
* This is the event handler for the mouse wheel event. We connected the event
|
|
* to this method through the Mouse connectEvent() method in initDialog().
|
|
*
|
|
* The comment header for the onMouseWheel() event handler in the maid dialog
|
|
* explains the arguments in detail.
|
|
*
|
|
* The system-wide wheelScrollLines parameter is used to indicate how much to
|
|
* scroll for 1 notch of a turn of the mouse wheel. The system default is 3,
|
|
* but the user can set this to what they want.
|
|
*
|
|
* Microsoft says this about the wheel scroll lines parameter: it is the
|
|
* suggested number of lines to scroll when there are no modifier keys; if the
|
|
* value is 0, no scrolling should be done; if the value is greater than the
|
|
* number of visible lines, or its value is WHEEL_PAGESCROLL, it should be
|
|
* interpreted as clicking once in the page down or page up area of the scroll
|
|
* bar.
|
|
*/
|
|
::method onMouseWheel unguarded
|
|
expose e visibleLines
|
|
use arg state, pos, mouse, delta
|
|
|
|
if visibleLines == 0 then visibleLines = self~calcVisibleLines(e)
|
|
|
|
if delta > 0 then direction = 'up'
|
|
else direction = 'down'
|
|
|
|
scrollLines = .SPI~wheelScrollLines
|
|
|
|
-- scrollLines is only meant to indicate the number of lines to scroll when
|
|
-- there are no modifier keys or mouse buttons.
|
|
if state \== 'None' then do
|
|
select
|
|
when state~wordPos("Shift") <> 0, state~wordPos('Control') <> 0 then do
|
|
if direction == 'up' then e~scrollCommand('PAGEUP', 3)
|
|
else e~scrollCommand('PAGEDOWN', 3)
|
|
return .true
|
|
end
|
|
|
|
when state~wordPos('Shift') then do
|
|
if direction == 'up' then e~scrollCommand('UP', 3)
|
|
else e~scrollCommand('DOWN', 3)
|
|
return .true
|
|
end
|
|
|
|
when state~wordPos('Control') then do
|
|
if direction == 'up' then e~scrollCommand('PAGEUP')
|
|
else e~scrollCommand('PAGEDOWN')
|
|
return .true
|
|
end
|
|
|
|
otherwise do
|
|
-- Some other modifier, key or mouse, is active. There are a lot of
|
|
-- things we could do, but for simplicity we are going to just ignore
|
|
-- this.
|
|
return .false
|
|
end
|
|
end
|
|
-- End select
|
|
end
|
|
|
|
-- No modifiers, we use the system scroll lines value to decide how much to
|
|
-- scroll.
|
|
select
|
|
when scrollLines == 0 then do
|
|
-- Indicates to not scroll
|
|
end
|
|
|
|
when scrollLines == .SPI~WHEEL_PAGESCROLL then do
|
|
-- This setting indicates to scroll 1 page.
|
|
if direction == 'up' then e~scrollCommand('PAGEUP')
|
|
else e~scrollCommand('PAGEDOWN')
|
|
end
|
|
|
|
when scrollLines > visibleLines then do
|
|
-- Scroll 1 page.
|
|
if direction == 'up' then e~scrollCommand('PAGEUP')
|
|
else e~scrollCommand('PAGEDOWN')
|
|
end
|
|
|
|
otherwise do
|
|
-- Scroll the number of lines specified by wheel scroll lines parameter.
|
|
if direction == 'up' then e~scrollCommand('UP', scrollLines)
|
|
else e~scrollCommand('DOWN', scrollLines)
|
|
end
|
|
end
|
|
-- End select
|
|
|
|
return .true
|
|
|
|
|
|
/** caclVisibleLines()
|
|
*
|
|
* Calculates the number of visible lines in the edit control. This is done
|
|
* by gettting the size of the edit control formatting rectangle in pixels and
|
|
* the size of a string in the edit controls in pixels. The height of the
|
|
* formatting rectangle is then divided by the height of a line of text.
|
|
*
|
|
* When getting the height of a line in the edit control, any string can be used
|
|
* because we only need the height of the string. The length does not matter.
|
|
*
|
|
* On my first try at this, I used the client rect of the edit control for the
|
|
* calculation. But, it was off by 1. The proper way to calculate the height
|
|
* is to use the formatting rectangle. The edit control does all its drawing
|
|
* within that rectangle.
|
|
*/
|
|
::method calcVisibleLines private
|
|
use strict arg editCtrl
|
|
|
|
fRect = editCtrl~getRect
|
|
|
|
height = fRect~bottom - fRect~top
|
|
lineHeight = editCtrl~getTextSizePX("Any string will do for this")~height
|
|
|
|
-- Note that we return a whole number here, not a fraction. The number is
|
|
-- exactly the number of *whole* lines in the edit control. Quite often in a
|
|
-- dialog, a multi-line edit control will contain a partial line, (as does
|
|
-- this dialog.)
|
|
return height % lineHeight
|
|
|
|
/** leaving()
|
|
*
|
|
* The leaving method is invoked automatically by the ooDialog framework
|
|
* immediately before the dialog is destroyed.
|
|
*
|
|
* At this point, the underlying Windows dialog still exists. This makes the
|
|
* leaving method the proper place to do clean up. Especially if some of the
|
|
* clean up, as does deleteFont(), requires the underlying dialog to exist.
|
|
*
|
|
* Here we delete the mono-spaced font created for the help text display.
|
|
*/
|
|
::method leaving
|
|
expose newFont
|
|
|
|
self~deleteFont(newFont)
|
|
|
|
|
|
/** routine::getHelpText()
|
|
*
|
|
* This is convenience routine that returns the help text for the Mouse Wheel
|
|
* demonstration program. The help text is constructed here as a single string.
|
|
*
|
|
* The text could be contained in a file and read in when needed. To reduce the
|
|
* nubmer of files needed for the program, the text was just typed into the
|
|
* program file.
|
|
*/
|
|
::routine getHelpText
|
|
|
|
txt = -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' The Mouse Wheel Demonstration' || .endOfLine || -
|
|
' =============================' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' This demonstration program allows you to scroll the lines of text in the' || .endOfLine || -
|
|
' main edit control using the mouse wheel.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Scrolling' || .endOfLine || -
|
|
' =========' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' When the mouse wheel is rotated one notch, the text is scrolled one line.' || .endOfLine || -
|
|
' Rotating the mouse wheel away from yourself scrolls the text up, while' || .endOfLine || -
|
|
' rotating the wheel towards yourself scrolls the text down. When the text' || .endOfLine || -
|
|
' is scrolled to line 1, scrolling up stops. Likewise when the lines of' || .endOfLine || -
|
|
' text are scrolled all the way to the bottom, scrolling down stops.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Holding down the control and or the shift keys while rotating the mouse' || .endOfLine || -
|
|
' wheel changes the amount of text scrolled by rotating one notch of the' || .endOfLine || -
|
|
' mouse wheel. This is summarized in the following table:' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Notches Key Lines' || .endOfLine || -
|
|
' Rotated Down Scrolled' || .endOfLine || -
|
|
' =======================================' || .endOfLine || -
|
|
' 1 None 1' || .endOfLine || -
|
|
' ---------------------------------------' || .endOfLine || -
|
|
' 1 Shift 3' || .endOfLine || -
|
|
' ---------------------------------------' || .endOfLine || -
|
|
' 1 Control 1 page' || .endOfLine || -
|
|
' ---------------------------------------' || .endOfLine || -
|
|
' 1 Control' || .endOfLine || -
|
|
' & 3 pages' || .endOfLine || -
|
|
' Shift' || .endOfLine || -
|
|
' ---------------------------------------' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Radio Buttons' || .endOfLine || -
|
|
' =============' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' The radio buttons at the bottom of the dialog change how the position of' || .endOfLine || -
|
|
' the mouse pointer affects whether the text is scrolled, or not.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Text is never scrolled unless the dialog has the input focus. This' || .endOfLine || -
|
|
' essentially means when the dialog is the active window.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' The following table assigns a number to each radio button according to' || .endOfLine || -
|
|
' the text of the radio button. The next table uses the radio button' || .endOfLine || -
|
|
' number to describe its function.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Radio Radio' || .endOfLine || -
|
|
' Button Button' || .endOfLine || -
|
|
' # Text' || .endOfLine || -
|
|
' =========================================================================' || .endOfLine || -
|
|
' 1 Mouse is anywhere' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 2 Mouse is over dialog' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 3 Mouse over edit controls / Ok button' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 4 Multi-line edit focused / mouse anywhere' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 5 Multi-line edit focused / mouse over dialog' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 6 Multi-line edit focused / mouse over edit control' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Radio Text is' || .endOfLine || -
|
|
' Button scrolled' || .endOfLine || -
|
|
' # when:' || .endOfLine || -
|
|
' =========================================================================' || .endOfLine || -
|
|
' 1 The mouse pointer is anywhere on the screen. It does not have' || .endOfLine || -
|
|
' to be over the dialog at all.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 2 Only when the mouse pointer is over dialog. If the pointer is' || .endOfLine || -
|
|
' moved outside of the dialog, the scrolling stops.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 3 Only when the mouse pointer is directly over one of the two' || .endOfLine || -
|
|
' edit controls, or directly over the Ok button.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 4 First the multi-line edit control must have the focus. If any' || .endOfLine || -
|
|
' other control has the focus, text is not scrolled. The mouse' || .endOfLine || -
|
|
' pointer can be anywhere on the screen.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 5 The multi-line edit control must have the focus. The mouse' || .endOfLine || -
|
|
' pointer must be directly over the dialog.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
' 6 The multi-line edit control must have the focus. The mouse' || .endOfLine || -
|
|
' pointer must be directly over the multi-line edit control.' || .endOfLine || -
|
|
' -------------------------------------------------------------------------' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Edit Controls' || .endOfLine || -
|
|
' =============' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Large, top, edit control:' || .endOfLine || -
|
|
' -------------------------' || .endOfLine || -
|
|
' This contains the text that is scrolled. You can type into this control' || .endOfLine || -
|
|
' to add or remove lines.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Small, bottom, edit control labeled Command:' || .endOfLine || -
|
|
' --------------------------------------------' || .endOfLine || -
|
|
' This control serves no purpose, other than to take up real estate in the' || .endOfLine || -
|
|
' dialog. You can typ in this control, but it does nothing.' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Push Buttons' || .endOfLine || -
|
|
' ============' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Ok button -> Closes the dialog' || .endOfLine || -
|
|
'' || .endOfLine || -
|
|
' Help button -> Shows this help.' || .endOfLine
|
|
|
|
return txt
|