SplitCon consists of the following components:
- a demo form, splitcon.scx
- The demo form illustrates how to use the SplitCon classes.
- a class library, splitcon.vcx
- This library contains the core SplitCon class definitions that can be used
by any application to support splitters.
To launch the SplitCon demo application (built from form splitcon.scx) just
issue the following VFP command line:
splitcon()
This will bring up a tabbed dialog with 4 tabbed pages, labeled 2X1, 1X2,
3X4, and Nested. SplitCon allows for a 2-dimensional array
of sub-containers, separated by vertical and horizontal "splitter"
lines, which can be dragged to resize the containers between them. Each
page shows an example for the indicated number of rows and columns. The
last tabbed page illustrates a simple case of nested split containers, where a
1X2 split container contains a 2X1 split container. It's a humble demo
because the sub-containers are empty, but if you put controls into these
containers and add logic to support the Resize event, things get a lot more
interesting.
The SplitCon class library, splitcon.vcx, contains the following class
definitions:
- splitcontainer: foundation splittable container class, with no
sub-containers.
The following subclasses are used by the demo form, but not required for
other applications, although they can be convenient:
- splitcon_1_2: 1 row and 2 columns.
- splitcon_2_1: 2 rows and 1 column.
- splitcon_3_4: 3 rows and 4 columns.
- splitterbar: foundation class for all splitter bar shapes.
- splitterbarh: horizontal splitter bar subclass.
- splitterbarv: vertical splitter bar subclass.
- splittercover: invisible cover shape class used while dragging a splitter.
Based on VFP's Container class, the SplitContainer class has logic in its
Init and Resize event methods, and the following custom properties:
- splcp_barabove
- Property containing an object reference to the top-bounding splitter bar for this container. Null if there is none. Used for automatic resizing.
- splcp_barbelow
- Property containing an object reference to the bottom-bounding splitter bar for this container. Null if there is none. Used for automatic resizing.
- splcp_barleft
- Property containing an object reference to the left-bounding splitter bar for this container. Null if there is none. Used for automatic resizing.
- splcp_barright
- Property containing an object reference to the right-bounding splitter bar for this container. Null if there is none. Used for automatic resizing.
- splcp_coordx
- Property for holding on to the X-position of the mouse pointer while a splitter is being dragged. This is set in the target's OLEDragOver event method, and used in the splitter's OLEGiveFeedback event method.
- splcp_coordy
- Property for holding on to the Y-position of the mouse pointer while a splitter is being dragged. This is set in the target's OLEDragOver event method, and used in the splitter's OLEGiveFeedback event method.
- splcp_ncols
- Property containing the number of colums of sub-containers into which this outer container is divided. 0 means none, i.e. there is no array of
sub-containers.
- splcp_nrows
- Property containing the number of rows of sub-containers into which this outer container is divided. 0 means none, i.e. there is no array of
sub-containers.
- splcp_resizecontinuously
- Flag (i.e. boolean) property indicating whether to resize continuously as the splitter bar is dragged, or just when the drag completes.
- Init Event Method
- The Init logic loops over the array of sub-containers (if there are any)
and connects them to their bounding splitter bars by saving splitters object
references in each sub-container's splcp_barabove, splcp_barbelow, splcp_barleft,
and splcp_barright properties. Within the same loops the splitter bars
are also threaded to their neighbors, using a similar set of splitterbar
properties, so that dragging can be properly
restricted to prevent crossing these boundaries.
This initialization logic does the work for predefined subclasses of various
row and column dimensions, but it requires that a strict naming convention be followed in order to initialize various internally used object references.
(Other methods, however, should make no assumption about naming conventions for sub-containers and splitter bars, but instead use the appropriate linking properties. This will facilitate support
of dynamic splitters, where rows and columns can be added and removed on the
fly.)
- Resize Event Method
- For terminal containers, i.e. those with property splcp_nrows = 0, this is
a no-op. Otherwise, for split containers, the Resize logic adjusts the
dimensions of the splitter's cover (whose member name is Splittercover1)
and loops over all controls in the
container, propagating resizing effects to the child splitter bars and
sub-containers.
Included in the splitcon.vcx class library are subclasses of the SplitContainer
class, some of which are used by the demo form, splitcon.scx. Note that
the foundation SplitContainer class is actually the degenerate case of a
terminal split container, which has no splitter or sub-containers. The
subclasses, splitcon_1_2, splitcon_2_1, splitcon_3_4, and so on are examples of
non-trivial split containers that actually contain splitters and sub-containers.
The names of these subclasses follow a consistent convention with the first
number being the count of sub-container rows and the second number being the
count of sub-container columns. These simple subclasses may be of general
utility, but one is not required to use them, and you can compose your own such
subclasses or member objects within a form, with your own naming conventions.
Note however that while the name of a top-level split container class or
member object can be whatever you choose, the naming conventions for the child
members within such a class or member object have greater significance. By
following the standard naming conventions, one gets the additional benefit of
automatic initialization of internal object references that are required for
proper operation, handled by the default SplitContainer.Init
method. Unless you are prepared to perform the equivalent initialization
logic to support your own member object naming conventions, you should follow
these standard naming conventions:
- sub-containers have member names of the form subcon_n_m
where n is the row # and m is the column number. Each sub-container
is based on the SplitContainer class or one of
its subclasses.
- splitter bars have names of the form splith_n or splitv_m
where n is the row # above a horizontal splitter, and m is the
column # to the left of a vertical splitter. Each splitter is based on
a SplitterBar subclass.
- the cover is a member object named Splittercover1
There is at most one such member, of class SplitterCover,
in a split container object. If a split container has a non-zero value
in its splcp_nrows property, it must contain a
splitter cover member object with the name Splittercover1.
The SplitterBar foundation class, based on VFP's Shape, is
subclassed into SplitterBarH and SplitterBarV, which are the classes actually
used for horizontal and vertical splitter bars. The subclasses
SplitterBarH and SplitterBarV have no additional method code, and they differ
only in their Height, Width, and MousePointer properties. These classes
also have the following custom properties:
- splbp_barabove
- Property containing an object reference to the top-bounding splitter bar for this
splitter. Null if there is none. Used to restrict against dragging over
neighboring splitters.
- splbp_barbelow
- Property containing an object reference to the bottom-bounding splitter bar for this
splitter. Null if there is none. Used to restrict against dragging over
neighboring splitters.
- splbp_barleft
- Property containing an object reference to the left-bounding splitter bar for this
splitter. Null if there is none. Used to restrict against dragging over
neighboring splitters.
- splbp_barright
- Property containing an object reference to the right-bounding splitter bar for this
splitter. Null if there is none. Used to restrict against dragging over
neighboring splitters.
- splbp_horizontal
- Flag (boolean) property to easily distinguish vertical and horizontal splitter
bar cases.
The following SplitterBar event methods have have code:
- OLEStartDrag Event Method
- Triggered when the users starts to drag a splitter, this brings the active splitter
and the splitter cover forward and makes the cover trap all available OLE drag & drop target locations
by setting its OLEDropMode property to 1.
- OLEGiveFeedback Event Method
- This method is triggered after every OLEDragOver event. The logic
handles displaying a double-headed mouse pointer, movement of the splitter
bar (within limits), and triggering a Resize on the parent split container if its splcp_resizecontinuously
property is .T.
- OLECompleteDrag Event Method
- Triggered when the users finishes dragging a splitter, this hides the splitter cover and disables its trapping of OLE drag and drop
events, i.e. sets its OLEDropMode property to 0. If the parent split
container's splcp_resizecontinuously property is set to .T., the parent's
Resize event is also triggered at this point.
The SplitterCover class, based on VFP's Shape, is a transparent member
of a split container, used only during the process of dragging a splitter
bar. It has code for the following event method:
- OLEDragOver Event Method
- This event is triggered in the splitter cover as the splitter bar is
dragged over it, when the cover's OLEDropMode property is set to 1
(Enabled). By bouncing back and forth between the splitter cover's OLEDragOver
and the splitter bar's OLEGiveFeedback events, both the drop target and the
drop source have a channel of communication.
The logic for SplitterCover holds on to the mouse coordinates in the splcp_CoordX
and splcp_CoordY properties of the parent SplitContainer, using VFP's
AMOUSEOBJ() to get mouse coordinates relative to the parent container.
Also, this method makes the necessary OLEDrop property settings to inform
VFP that it's OK to drop to this location (OLEDropHasData = 1), and enable Move onto this target
(OLEDropEffects = 2).
Copyright © 2000 - 2002, SpaceTime Systems