YOUR FEEDBACK
andy.mulholland wrote: intriguing !!! We have full scale 'Mashup Factories' in Chicago USA and Utrec...
AJAXWorld RIA Conference
Early Bird Savings Expire Friday Register Today and SAVE !..


2008 East
DIAMOND SPONSOR:
Data Direct
Frontiers in Data Access: The Coming Wave in Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
Intel
Virtualization – Path to Predictive Enterprise
Green Hills
IT Security in a Hostile World
JBoss / freedom oss
Practical SOA Approach
GOLD SPONSORS:
Software AG
The Art & Science of SOA: How Governance Enables Adoption
PlateSpin
Effective Planning for Virtual Infrastructure Growth
Fujitsu
Automated Business Process Discovery & Virtualization Service
Ceedo
Workspace Virtualization
Click For 2007 West
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
POWERBUILDER LINKS YOU MUST CLICK ON


Dockable Windows in PowerBuilder
Another PowerBuilder challenge

If you've read any of my past articles, you know that I love a good challenge, a challenge that really gets me thinking and ultimately ends up teaching me something. One thing I always wanted to do was create dockable windows using pure PowerScript. I held off from doing this for some time because of the almost overwhelming complexity that was inherent with this type of control. Seeing as this would be the perfect test of my skills, I motivated myself to do it.

The first thing I had to do before I started was investigate an existing control so that I could record proper behavior. To do this effectively I would need a really good example to analyze. Those of us using PowerBuilder 7 or higher know that the System Tree window in the IDE is as good an example as any.

Here is what I observed using the System Tree as an example:

  1. An outline appears when the windows title bar is clicked.
  2. The outline moves with the mouse clinging to the edges of the MDI window as a docked window would do.
  3. The outline disappears when the user lets go of the mouse button.
  4. The window moves to where the user last dragged the outline.
  5. Windows have a fixed position on the outer edges of the MDI frame.
  6. The window has a wide variety of resize capabilities.
After a little brainstorming I found that three main components were needed to accomplish our goal of making dockable windows.
  1. A non-visual object to manage all the open docked windows.
  2. An ancestor window from which all other docked windows will be inherited from.
  3. A window drag outline.
Due to the large amount of code produced for this example, it would be best to go to www.sys-con.com/pbdj to download the source provided so that you can follow along without having to sift through pages and pages of code within this article.

Once you have the source take a look at dockwindows.pbl. There are three objects that represent the three main components outlined above:

n_cst_dockwindowmanager
w_dockancestor
w_outline

n_cst_dockwindowmanager
This non-visual object is used to manage all open dockable windows; think of it as a layout manager. As windows are being opened, closed, or repositioned they need to be arranged in such a way that everything appears fixed and organized.

It's very important that this object be declared as a global variable like so: n_cst_dockwindowmanager gnv_dockmanager. The variable name in this case is very important; this is how it'll be referenced in the other objects.

There are a few key functions that you should be aware of that will help you interact with the docked windows. Review the code in each function for a better understanding of what's happening:

  • of_CloseWindow: This function closes a docked window. Pass as a string the name of the window you wish to close.

    gnv_dockmanager.of_CloseWindow("w_dockoutput")

  • of_GetWindow: Returns a reference to an open window. Pass as a string the name of the window you wish to get a reference to.

    w_dockoutput lw_output

    lw_output = gnv_dockmanger.of_GetWindow("w_dockoutput")

  • of_IsWindowOpen: Similar to PowerBuilder's IsValid function. Returns true if the specified window is open and false if otherwise.

    w_dockoutput lw_output

    IF of_IsWindowOpen("w_dockoutput")
         THEN
    lw_output = gnv_dockmanger.of_GetWindow("w_dockoutput")
    END IF

  • of_OpenWindow: This function opens a docked window in the position specified. Valid position values are left, right, top, and bottom. Alternatively, you can use the LEFT, RIGHT, TOP and BOTTOM constants as the second argument.

    gnv_dockmanager.of_OpenWindow("w_dockoutput", "bottom")

  • of_ResizeDockWindows: Positions and resizes all open docked windows and the MDI client area. Called in the resize event of the applications MDI window. An example and a better explanation will be provided closer to the end of the article.
  • of_SetClientArea: Called once in the MDI's open event to create a reference to the MDI client area.

    gnv_dockmanager.of_SetClientArea(THIS.MDI_1)

w_dockancestor
This window will be the ancestor of all your docked windows. Inherit one for every new window you require for your application. Once inherited and saved you will need to determine its position. Its position will dictate how you initially size the window. Windows docked to the left or right should have narrow widths. Windows docked to the top or bottom should have short heights. Take a look at w_dockpblselect and w_dockoutput for an example. W_dockpblselect docks to the left and w_dockoutput docks to the bottom.

Your new window should only have one control placed on it. Resizing and positioning of this control is done automatically. This is done by simply creating a reference to the fifth element in the control array within the open event of the window (i.e., ido_object). If more than one control is required, you must encapsulate everything into a custom visual user object and place that onto the window.

Take note of the windows event list. You will see two new user events: ResizeEnd and Resizing. Both are called from the Other event. Resizing is triggered before the Resize event and lets us know how the user is sizing the window (e.g., left edge, right edge, top edge, etc.). ResizeEnd is triggered once the user is finished sizing the window. The Resizing event is used to restrict the user in how they can size the docked window. If the window is docked to the left, you would only want them to resize by dragging the right edge, not the left, top, or bottom. If they are resizing from the wrong edge, the window stops drawing and is repositioned to its proper location. The ResizeEnd event will allow the window to start drawing if necessary.

While looking at the event list you may have noticed two other user events: PositionChanging and PositionChanged. PositionChanging is called before a window is repositioned by the user. You can prevent the window from being repositioned by returning 1 from this event. PositionChanged is called after the window's position has changed. Arguments in both events are integers that are represented by the LEFT, RIGHT, TOP, and BOTTOM constants found in n_cst_dockwindowmanager. Both user events are triggered from the of_SetPosition function.

The drag outline appears when a user clicks on the window's title bar and starts dragging. Refer to of_DragWindow to see exactly how this is managed. The SetCapture and ReleaseCapture Windows API functions are used to direct all mouse activity to the window title bar. By doing this, the mouse can leave the window and still trigger the MouseMove event of the title bar, which in turn makes a call to of_DragWindow.

One other thing to make note of is the visual appearance of the windows title bar. The title bar comprises of the following images; feel free to change them to suite the overall look of your application:
barhorizontal.bmp
barvertical.bmp
barclosehorizontal.bmp
barclosevertical.bmp

w_outline
Of all the components needed, this is by far the simplest. W_outline is used to display the outline of the docked window as it's being dragged within the MDI frame. The outline is just a rectangle object on a popup window. The fill color of the rectangle is set to Aqua, which is the color that will be converted to transparent.

The open event of the window uses an API call to change the windows style to be layered so that transparency can be added.

SetWindowLong(Handle(THIS), GWL_EXSTYLE, WS_EX_LAYERED)

Another API call is triggered to convert the Aqua color to transparent.

SetLayeredWindowAttributes(Handle
    (THIS), RGB(0,255,255), char(0),
    LWA_COLORKEY)

That's it; we now have an outline (see Figure 1). To change the color of the outline you would just change the line color of the rectangle.

Putting It Together
Now that we have all our logic encapsulated into the above objects, implementing this functionality is very simple. To add docked windows to your application, simply do the following:

//Declare Global Variable
n_cst_dockwindowmanager gnv_dockmanager

//Open Event of Application Object
gnv_dockmanager = CREATE n_cst_dockwindowmanager
//Open Event of your MDI Window
gnv_dockmanager.of_SetClientArea
(THIS.MDI_1)

gnv_dockmanager.of_OpenWindow("w_dockpblselect", "left")

//Resize Event of your MDI Window
gnv_dockmanager.of_ResizeDock
Windows(0, gnv_toolbar.of_
GetToolbarHeight(), THIS.
WorkSpaceWidth(), THIS.WorkSpace Height() - MDI_1.MicroHelpHeight)

Pay attention to the call to of_ResizeDockWindows in the frames resize event. You can see that the size and position is being set based on having your own homemade toolbars implemented (http://pbdj.syscon.com/read/140739.htm). If you're using the built-in PowerBuilder toolbars, then you will need to set the size and position in a different way. The first argument should be 100 x the number of toolbars visible and the last argument should be the work space height - micro-help height + (100 x the number of toolbars visible).

Conclusion
While our example isn't a perfect solution, it is an acceptable one. The next time you see a control in another application that isn't available in PowerBuilder, challenge yourself to create it. Trust me; it's a fun and exciting way to learn the full capabilities of this great development tool (see Figure 2).

About Brad Wery
Brad Wery is the creator of www.PowerToTheBuilder.com, a site dedicated to helping PowerBuilder developers create visually appealing user interfaces. He has been a member of TeamSybase since 2006 and is an active participant in the PowerBuilder Newsgroups.

YOUR FEEDBACK
PBDJ News Desk wrote: If you've read any of my past articles, you know that I love a good challenge, a challenge that really gets me thinking and ultimately ends up teaching me something. One thing I always wanted to do was create dockable windows using pure PowerScript. I held off from doing this for some time because of the almost overwhelming complexity that was inherent with this type of control. Seeing as this would be the perfect test of my skills, I motivated myself to do it.
PBDJ LATEST STORIES . . .
Virtualization is actively being used by Sybase IT to help solve power/cooling issues as well as transform the datacenter into an environment that brings greater benefits to their customers, especially the engineering organization. Average CPU utilization was very low on physical serve...
Must have at least 5 years of recent experience (within the last 7 years) in building, testing, and supporting complex (multiple interfaces with database(s) and other applications) and mission-critical Windows applications using PowerBuilder. Must have at least 5 years of experience wr...
Join Scott Guthrie as he discusses Microsoft’s commitment to web standards development, Rich Internet Applications and how Microsoft is contributing to help move the web forward. Join Adobe’s Kevin Lynch as he demonstrates how Flash and HTML come together to make the most engaging,...
Particularly in a means of moving PowerBuilder applications to the web. What I’m looking for doesn’t require a server license or the installation of unmanaged code to the web server, and works well across different browsers (not just Internet Explorer). The WPF DataWindow will help...
"The rise of Enterprise Architecture is proof that organizations need to manage the impact of changes in competition, technology and regulations across their enterprise," said Dan Lahl, director of Intelligent Enterprise for Sybase. "PowerDesigner 15's unique Link and Synch technology ...
With PowerBuilder 11 Sybase gave developers what we have long hoped for – the possibility of taking an application created in a client/server architecture and turning it into a Web application, almost without having to move the code; and it's better if you don't use a server applicat...
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE
BREAKING POWERBUILDER / SYBASE NEWS
Medmatics, LLC, a leading vendor of on-demand, anticoagulation software for private practices and ho...