|
|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SYS-CON.TV SYS-CON.TV WEBCASTS |
POWERBUILDER LINKS YOU MUST CLICK ON Messages
The PowerBuilder 9 IDE
By: Berndt Hamboeck
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
// Object : axisclient 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.
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 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, 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 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, 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 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) 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 PBDJ LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING POWERBUILDER / SYBASE NEWS
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||