Click here to Skip to main content
15,885,366 members
Articles / Desktop Programming / WTL
Article

Tab Controls And Splitters - Adding Some Dockable And Floating Sugar

Rate me:
Please Sign up or sign in to vote.
4.76/5 (39 votes)
6 Jan 20043 min read 212.6K   8.4K   104   44
Another implementation of dockable, floating, tabbing and splitting environment.

Tab Controls And Splitters - Adding Some Dockable And Floating Sugar

Introduction

In the previous article, I introduced SplitPane class that manages client view windows with splitters and tab panes and provides an interaction interface with the owner class. In this article, I would like to represent Frame class that extends SplitPane functionality with dockable and floating features. Also, I am going to consider that you know what dockable and floating windows are. Sure, the best example of those is Visual Studio .NET IDE. I guess you are also aware of an excellent job that has been done by Sergey Klimov and the further improvement by Daniel Bowen. This article is just an attempt to provide a simpler interface for the particular case, with a little bit different paradigm. I hope I have succeeded in it.

What it does

Briefly: Frame class provides dockable and floating environment for client views. There are three parts to this environment, the main pane, dock panes and float frames. All of them are owners of SplitPane, so you can split and tab all client views. Also, the client views are separated in two different groups, dockable views and document views. The difference is simple. The dockable views cannot be attached in the main pane but can be docked in one of the docked sides. The document views are unlike them, they can be attached in the main pane but cannot be docked. Both of them are able to become floating. That's the difference with Visual Studio .NET IDE. To prevent a floating window to get docked to any place, keep CTRL key pressed while dragging it.

Using the code

The use of Frame class can be as simple as the use of SplitPane class. It's also designed for SDI applications. I won't repeat all steps but a few points. With all include files mentioned in that, you will want to use DockTabFrame.h with the Frame class implementation. This is also in DockSplitTab namespace. There is a ClientView class that has all necessary properties for the client view windows. Frame class provides a communication interface for the interface with the owner or parent class. This is the FrameListener abstract class. clientDetached is the only function provided for this interface so far. Frame class calls it when a user closes a dock pane, a float frame or a tab. In other words, when he pushes a close button. There is a detachClientView function for Frame class that does the similar action but does not raise clientDetached event. Frame sends WM_CONTEXTMENU Windows message to the client views in appropriate cases. For instance, when you click a right mouse button on the tab.

Frame class

Public methods:

C++
// creates a new Split Pane window with parentWnd and rect parameters
HWND create( parentWnd, rect);

// sets the keyboard focus to the specified client view window
bool setFocusTo( clientViewWnd) {

// retrieves the client view window that receives the keyboard focus
HWND focusedClientView();

// toggles client view state and move
// the client view to an appropriate pane
bool toggleClientViewState( clientViewWnd, ClientView::State);

// retrieves client view properties with client view window handle
ClientView* getClientView( clientViewWnd);

// adds a new client view
bool addClientView( clientView);

// adds a new client view and attach it to the specified dock pane
bool dockClientView( dockSide, clientView);

// shows/hides the specified dock pane
bool showDockPane( dockSide, show);

// retrieves the visibility state of the specified dock pane
bool dockPaneVisible( dockSide);

// retrieves the existence state of the specified dock pane
bool dockPaneExists( dockSide);

// float frame iterator functions
POSITION floatFrameStart()
HWND floatFrameNext( &position);

// adds a new client view and attach it to a new float frame
// with the specified location
HWND floatClientView( rect, clientView);

// retrieves the visibility state of the specified float frame
bool showFloatFrame( floatFrameWnd, show);

// check if a float frame is visible
bool floatFrameVisible( floatFrameWnd)

// check if a float frame exists
bool checkFloatFrame( floatFrameWnd);

// reattach the client view. the function uses
// the last location object propertes
void attachClientView( clientView);

// detaches the client view window 
// This method changes the parent window of the client
// view window to the Frame's parent.
ClientView* detachClientView( clientViewWnd);

// retrieves the visibility state of the specified client view window handle
bool clientViewVisible( clientViewWnd);

// checks if client view window is attached.
bool clientViewAttached( clientViewWnd);

// set and get Image List
void setImageList( imgList);
HIMAGELIST getImageList();

Inside of Frame class

There are implementations of two very important classes for Frame class. These are DockPane class and FloatFrame class. Each of them has its own SplitPane member. So you can split and tab client views inside of each DockPane or FloatFrame instance. Frame class itself also owns SplitPane instance. An objective of this instance is to keep document views. Frame class communicates with the float frames, dock panes and main pane via FloatDockFrameListener interface class that extends CallBackListener interface.

class DockPane- contains docked client views.
class FloatFrame- contains floating client views.
class FloatDockFrameListener- communication interface between float frames, dock panes and their owner. (Frame class)
class SplitPaneWrapper

- encapsulates common data and methods for split pane containers.

Used by FloatFrame class and DockPane class.

class FloatFrameDragContext- stores drag and drop context. Inherited from RectTracker class.
class DropParcel-the result of drag and drop operations.
class LayoutManager- layout implementation for Frame class.

What's the next

Two things are left to do: Serialization and Auto hide panes.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCan't get latest code from www.katraev.ru Pin
liubl12-Mar-20 19:09
liubl12-Mar-20 19:09 
QuestionCompile error in VC++ 2005 Pin
feifeima20084-Jan-08 4:11
feifeima20084-Jan-08 4:11 
AnswerRe: Compile error in VC++ 2005 Pin
win32sdk5-Mar-09 23:08
win32sdk5-Mar-09 23:08 
GeneralWM_USER_DESTROY_PANE should be "Post" instead of "Send" Pin
Quynh Nguyen20-Sep-07 0:01
Quynh Nguyen20-Sep-07 0:01 
QuestionHow to change Tab caption? Pin
Quynh Nguyen19-Sep-07 18:36
Quynh Nguyen19-Sep-07 18:36 
GeneralProblem with using tab control between 2 panes in VC++ Pin
Shraddha Gautam14-Dec-06 19:50
Shraddha Gautam14-Dec-06 19:50 
Generalprint the focus tab Pin
ztkx2-Nov-06 2:52
ztkx2-Nov-06 2:52 
Questionit breaks in VC++ 8 Pin
2simple17-Sep-06 9:35
2simple17-Sep-06 9:35 
AnswerRe: it breaks in VC++ 8 Pin
fermil2-Jul-07 5:16
fermil2-Jul-07 5:16 
GeneralProblem with the code Pin
CornellDev22-Nov-05 8:23
CornellDev22-Nov-05 8:23 
GeneralError building project Pin
PaulaPaziani20-Oct-05 6:54
PaulaPaziani20-Oct-05 6:54 
AnswerRe: Error building project Pin
fermil2-Jul-07 5:31
fermil2-Jul-07 5:31 
GeneralMFC Pin
Pshemeksliwa6-Aug-05 11:11
Pshemeksliwa6-Aug-05 11:11 
GeneralI liked it Pin
sanjit_rath29-Nov-04 6:27
sanjit_rath29-Nov-04 6:27 
QuestionUpdate to match Daniel Bowen's? Pin
Erik Johnson18-Jul-04 4:58
Erik Johnson18-Jul-04 4:58 
Generaltabs not visible when created Pin
willyl18-Jun-04 23:34
willyl18-Jun-04 23:34 
GeneralRe: tabs not visible when created Pin
willyl20-Jun-04 5:01
willyl20-Jun-04 5:01 
QuestionHow to stop Main Pane Client View windows from being allowed to be dragged to float frames Pin
John Heenan22-Mar-04 19:28
John Heenan22-Mar-04 19:28 
GeneralFix for memory leak reported below Pin
John Heenan22-Mar-04 18:29
John Heenan22-Mar-04 18:29 
GeneralMemory Leak Pin
John Heenan19-Mar-04 23:25
John Heenan19-Mar-04 23:25 
GeneralIgor - Awesome! Pin
Hydra13-Feb-04 3:10
Hydra13-Feb-04 3:10 
GeneralRe: Igor - Awesome! Pin
Hydra13-Feb-04 4:43
Hydra13-Feb-04 4:43 
ok, so after playing with it for a bit, i realise i need to be able to at do the following things

1) save layouts
2) restore layouts
3) switch between layouts
4) auto hiding facilities - *I* can wait for this one, but maybe my users can't Wink | ;)

i guess saving a layout is a case of iterating through the dockable areas, making a note of what is where and what it's split with (and so on..), a bit tricky though

ability to get a pane's object type from a pane specific LPARAM or something is required too.

For example - to describing a layout such as this one...

+--------------+----+
|              |    |
|=5============|    |
+-----+--------+    |
|     |=10:11==|    |
|     |        |    |
|=1===|        |    |
+-----+        |    |
|     |        |    |
|     |        |    |
|     +--------|    |
|=2===|=12=====|    |
+-----+        |    |
|     |        |=6==|
|     +--------+----+
|     |             |
|=3:4=|=7:8:9=======|
+-----+-------------+


we need to check each docking area, see what it contains and how it's docked to the areas above/below or left/right of it (depending on wether it's vertical or horizontal, respectively) and if it contains a group of frames, and what those frames are and which one is active.

we also need to be able to retreive (and later set) the floating x,y,w,h values for each frame.

I'm going to start with the left area, (panes 1 thu 4) in the figure above.

left area (areas 1 to 4), split horizontally into 2 panes, docked below top area, docked with bottom area, splitter position is 33%
--> pane 1, (area 1) contains one frame
----> frame 1, (area 1) object is: info panel
--> pane 2, (areas 2 and 3:4) split horizontally into 2 panes, splitter position is 50%
----> pane 1, (area 2) contains one frame
------> frame 1, (area 2) object is: server list
----> pane 2, (area 3 & 4) grouped pane container
------> group contains two frames, active frame is the second frame.
--------> frame 1, (area 3) object is: global user list
--------> frame 2, (area 4) object is: friends list

top area (area 5), contains 1 frame, docked with left window edge, docked with right area
--> frame 1 (area 5) object is: channel monitor

right area (area 6), contains 1 frame, docked with top window edge, docked with bottom area
--> frame 1 (area 6) object is: some other view

bottom area (area 7 to 9), contains group pane container, docked with left area, docked with right windowedge
--> grouped pane container, group contains two frames, active frame is the first frame.
----> frame 1 (area 7) object is: transfer panel
----> frame 1 (area 8) object is: event log panel
----> frame 1 (area 9) object is: output panel

and so on...

restoring a layout currently looks like it might not be possible as i don't see functions like dockTo(), groupWith() and splitWith().

to restore the above layout, we would add the views in the same order, calling dockTo(), groupWith(), and splitWith()

dockto() would take a frame and dock it with another frame so that it appears in the same split pane with tabs below it. dockto() also needs a parameter so that you can decide to leave make the frame active or leave the old frame you're docking with active.

groupwith() would take a frame and then dock another frame to it.

splitWith() would take a new frame object and split the area of the frame you're docking to in half (or preferably, a percentage of the area as a parameter) and show the new frame object in the other pane, you must also be able to specify that the new pane appears above/left or below/right of the existing frame.

thinking about it, we'd probably need three createframe() functions too, one to create one in a docked area (left, right, etc), one to create one split with another frame, and one to create one grouped with another frame()

Additonally, it would be nice to have the floating windows appear as app windows, i.e. they would appear on the taskbar.

i think that saving and restoring layouts should be left to the application that uses the layout tools and not done like sergey's docking windows are done. why? 1) sergey's saving/loading routines sometimes caused crashes, requiring the user to remove registry keys before the app could be run again, 2) different apps require different layout saving methods. my app really wants to save and restore layouts to/from XML files and not the registry.

with the above two functions it should be easy enough for any coder to simply remember where things are positioned and put them back in the same place.

Ok, comments?
GeneralRe: Igor - Awesome! Pin
Igor Katrayev13-Feb-04 4:48
Igor Katrayev13-Feb-04 4:48 
Generalrookie questions Pin
Dr.Rugelj12-Feb-04 7:53
Dr.Rugelj12-Feb-04 7:53 
GeneralRe: rookie questions Pin
Igor Katrayev13-Feb-04 4:31
Igor Katrayev13-Feb-04 4:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.