YOUR FEEDBACK
Two great PDF creators
Michael Jahn wrote: related to the snapscan - are their an samples of the ...
SOA World Conference
Virtualization Conference
$50 Savings Expire May 23, 2008... – Register Today!


2007 West
GOLD SPONSORS:
Active Endpoints
Your SOA Needs BPEL for Orchestration
BEA
Virtualized SOA: Adaptive Infrastructure for Demanding Applications
Nexaweb
Overcoming Bandwidth Challenges with Nexaweb
TIBCO
What is Service Virtualization?
SILVER SPONSORS:
WSO2
Using Web Services Technologies and FOSS Solutions
Click For 2007 East
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


The PowerBuilder 9 IDE

Digg This!

Okay, I know you're already familiar with the PowerBuilder IDE. Yes, you're one of those people who knows where to find the system tree and how to turn it off.

And you already know what the clip window is for (if you don't, look at it, it's a pretty cool feature - we used it in our 7-year-old application to document who made changes or bug fixes). No, that's not what I'll be talking about today. I want to discuss the internals of the IDE, as it has improved a lot since PowerBuilder 7.

The Idea
Why should we take a closer look at the IDE? It works great, we like it, so everything's okay. I agree, but I miss having an autocomment tool, a tool that pastes a header like the following sample:

// Object : axisclient
// Method : open (event)
// Author : B. Hamboeck
// Date : 3/31/2003
//
// Argument(s): string commandline
// Returns: (none)
//
//
//********************************************
// Modification history:
// Date  Version  Author  Comment

This header displays a lot of information that we could get directly from the IDE; Figure 1 displays the script painter.

There are three dropdownlistboxes.
1.   The first one is used to select objects, functions, or declares. In Figure 1 it displays the object name (axisclient). In Figure 2 it's within a function [we know it's within an event if we see the object name and not the string "(Functions)"].
2.   The second one displays either the event name (see Figure 1) or the function name (see Figure 2), and the arguments with the corresponding datatype; don't forget the return value.
3.   The third one displays the name of the parent, if the object is inherited.

There's a lot of information that should be described within an object header. We'll have to do a lot of typing if we don't have a tool like the commenter. The commenter would read all these values and place a header (the default values should be stored within an ini file) that contains all the information within our script.

Windows, Messages, and Handles
To get information, we need to read the values from the dropdownlistboxes, but how? As PowerBuilder developers we already know that the Windows operating system is based heavily on messages. For example, when a user closes a window, the operating system sends the window a WM_CLOSE message. When the user types a key, the window with the focus receives a WM_CHAR message, and so on.

Messages can also be sent to a window or a control to affect its appearance or behavior or to retrieve the information it contains. For example, you can send the WM_SETTEXT message to most windows and controls to assign a string to their contents, and you can send the WM_GETTEXT message to read their current contents. Keep in mind that through these messages we can set or read the caption of a top-level window or set or read the text property of an edit control or dropdownlistboxes. This is exactly how we would like to get the information that's needed by commenter.

We know that PowerBuilder greatly simplifies the programming of Windows applications because it automatically translates most of these messages into properties, methods, and events. Instead of using WM_SETTEXT and WM_GETTEXT messages, we as PowerBuilder developers can reason in terms of title and text properties. We don't have to worry about trapping WM_CLOSE messages sent to a window, because the PowerBuilder runtime automatically translates them into the desired close event. More generally, control messages map to properties and methods, whereas notification messages map to events.

PowerBuilder helps us a lot here, but sometimes we don't have an event mapped to the object. For example, the WM_MOUSEMOVE messages don't fire per default on any PowerBuilder object. So what now? Well, try to create an event, give it the name ue_mousemove, and map the pbm_mousemove event to it. If it's not there by default, it doesn't mean we can't do it in PowerBuilder.

To sum it up, we can say that windows send messages to objects and the objects react to messages. This raises two questions: How do we send messages and where should we send them?

The main API function that we can use to send a message to a form or a control is SendMessage, whose declare statement is:

Function Long SendMessageA(Long hwnd, Long wMsg, Long wParam,
Ref String lParam) Library "user32"

The hWnd argument is the handle of the window to which you're sending the message, wMsg is the message number (usually expressed as a symbolic constant that you can find in the header file stored on your hard disc in the folder %Sybase%\Shared\PowerBuilder\cgen\h\nt\winuser.h), and the meanings of the wParam and lParam values depend on the particular message we're sending.

This should answer our two questions. Well, not really. We know how to send a message, but we still don't know where, or to which object and hWnd to send a message. Fortunately, there's a relatively simple way to determine what's going on with a program. We need spyxx.exe (also known as Spy++). In my opinion (a developer's point of view), the Spy++ tool is one of the most useful programs ever created for the Windows platform. It comes with Visual C++ and the Platform SDK, but you might also find it on the Web. The information it provides is invaluable for peeking into how an application is implemented.

I fired up Spy++ and started to look at several applications. Let's fire it up and look at PowerBuilder (use the spyglass and put it onto the PowerBuilder IDE by using drag-and-drop). Figure 3 provides a snapshot - you see the CPS_Combo object selected, and below are the three dropdownlistboxes displaying the information we would like to read. On the left side of every object is the handle for the object. This handle will look different on your snapshot; it's unambiguous on your system, but will change every time your program runs.

Let's Implement Commenter
We won't implement the complete application now; I'll just provide the necessary steps and show the way. You can download the commenter source code from www.sys-con.com/pbdj/sourcec.cfm or the author's Web site. I found commenter a long time ago on the Web and enhanced it for PowerBuilder 8 and now for PowerBuilder 9. There were some really good PowerBuilder gurus involved in writing it; you'll find their names in the headers of the different functions they wrote.

First we have to find the PowerBuilder 9 IDE. You can see in Listing 1 that we use two different of_findwindow functions. The first one is pretty short: return FindWindowA(as_classname, as_windowname).

The API FindWindow function retrieves the handle of the top-level window whose class name and window name match the specified strings. If it finds a top-level window of type PBFRAME90, we have our first handle.

The second of_findwindow call is a bit more complex. We call it when there's no window of type PBFRAME90 open. We use the GetDesktopWindow function, which returns the handle of the Windows desktop window. From there we're looking for a window of the type PBFRAME90 by walking through all open windows. If we don't find it by the type, we try it with part of the title. We look for "- PowerBuilder". This makes it possible to find and let commenter work for PowerBuilder 8 (the main IDE window is of type PBFRAME80) and, who knows, maybe for PowerBuilder 10. For the complete code see Listing 2.

The next step is to get the current sheet. This would be the object with the handle 001c02ae and the caption axisclient (axisclient) (C:\d_drive\Articles\Axis\axisclient.pbl) inherited from application - Application. To compare the hex values displayed from Spyxx with the long values returned by the API functions, either write a function that converts long values to hex values, or you could use the calculator application that comes with Windows (change the view to scientific and you're able to switch from decimal to hex mode and vice versa).

IF of_getcurrentSheet(l_parenthandle,
l_handle, ls_caption) > 0 THEN
//OK
//MessageBox(ls_oops, "c,
CurrentSheet: " + String(l_handle))
ELSE
MessageBox(ls_oops, "Unable to get CurrentSheet...")
return
END IF

We need the client window within the current sheet (see Listing 3). This is the one with the class name of pbworkXX (XX could be any number chosen by the IDE).

Again we need the child below the object's handle that we already have. When I talk about a child, I mean a window that has the WS_CHILD style (look at the properties/styles in Spyxx) and is confined to the client area of its parent window. An application typically uses child windows to divide the client area of a parent window into functional areas. To get the object we want, the class type should be "CVS_Tiled" or "CPBWS_View", depending on which painter we are in.

l_handle = inv_extcalls.of_getwindow(l_handle, 5) //Child
ls_classn = Space(150)
inv_extcalls.of_getclassname(l_handle, ls_classn, 150)

DO WHILE ls_classn <> "CVS_Tiled" AND
ls_classn <> "CPBWS_View" AND
l_handle > 0
l_handle = inv_extcalls.of_getwindow(l_handle, 2) //Next
ls_classn = Space(150)
inv_extcalls.of_getclassname(l_handle, ls_classn, 150)
LOOP

This was straightforward. We only needed to walk through the tree, but now we could have different objects of the type "CVS_Tabbed", as you can see by using Spyxx. Only one is right; the other is the property view of our PowerBuilder object. The right object handle has a child of type wedit; the wrong one has another one (to be exact it's of type "PB_PropertyListClass90"). If we have the correct handle, we'd like to read the values from the dropdownlistbox. To do this, we send a message, as discussed earlier. In fact, we have to send two of them: CB_GETCURSEL (decimal 327) and CB_GETLBTEXT (decimal 328). The first one retrieves the index of the currently selected item; the second returns the text of the dropdownlistbox.

ll_index = SendMessage(hwnd, CB_GETCURSEL, 0, 0)

String lparam = SPACE(255)
as_objname = Space(255)

SendMessage(hwnd, CB_GETLBTEXT, ll_index, as_combos[1])

Another interesting object is the wedit control (handle 002E02CC). This is where we write the header and where we'll work with the WM_CHAR message. We send this message for every character we would like to see within the script painter. The syntax of the message is Send(a_hndl, WM_CHAR, code, 0), where a_hndl is the handle to the control, WM_CHAR is the code of the message (WM_CHAR = 258), and code is the ASCII value of the character to send (look at the Asc function in PowerBuilder).

Listing 4 shows a function that writes a complete string into the script painter.

Conclusion
We see that the PowerBuilder 9 development environment is "not more" than a standard windows application. It listens and responds to what's common in the Windows world: messages. With the information provided in this article, we're now able to send messages to other applications. You might apply what you have learned here to build applications that remotely control other applications. I wish you a happy (Windows) messaging!

About Berndt Hamboeck
Berndt Hamboeck is a senior consultant for BHITCON (www.bhitcon.net). He's a CSI, SCAPC8, EASAC, SCJP2, and started his Sybase development using PB5. You can reach him under admin@bhitcon.net.

PBDJ LATEST STORIES . . .
3rd International Virtualization Conference & Expo: Themes & Topics
From Application Virtualization to Xen, a round-up of the virtualization themes & topics being discussed in NYC June 23-24, 2008 by the world-class speaker faculty at the 3rd International Virtualization Conference & Expo being held by SYS-CON Events in The Roosevelt Hotel, in midtown
The PB Future: More on Graphs in PowerBuilder 11.5
Last week I posted a screen shot of the new 3D Rendering capabilities being added to some of the 3D graphs in PowerBuilder 11.5. It was met with mixed reviews on the PowerBuilder Futures newsgroup (forums.sybase.com) so I went back to the drawing board to see what I could come up with.
BluePhoenix Expands Modernization Collaboration with Microsoft
BluePhoenix announced that it has expanded its collaboration with Microsoft on legacy modernization projects. The collaboration provides customers moving their applications or databases to .NET-based environments the best in both modernization services and technical support. BluePhoeni
Sybase PowerBuilder Delivers AJAX and .NET Enhancements Enabling Rich Internet Application Development
Sybase announced that AJAX development capabilities and further Microsoft .NET enhancements have been added to the latest version of Sybase PowerBuilder 11, the premier 4GL rapid application development (RAD) tool. PowerBuilder 11.2 represents another milestone in the PowerBuilder road
PowerBuilder 11.2 Released: Sybase's Flagship IDE
Sybase has released the production version of its flagship .NET development tool - PowerBuilder version 11.2. This latest release of its premier IDE for RAD includes not only standard fixes but also a good list of new features. Here is the 'Coles Notes' version of these new features.
PowerBuilder Takes You To .NET
In June of 2007, Sybase released PowerBuilder 11. PowerBuilder developers can now deploy PowerBuilder components as .NET Assemblies or as .NET Web Services. A PowerBuilder developer can now create these .NET resources so that those who develop .NET solutions can benefit from PowerBuild
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
Sybase and Sun Set Guinness World Record for World's Largest Data Warehouse
Sybase, Inc. (NYSE:SY), the largest enterprise software and services company exclusively