Вы находитесь на странице: 1из 15

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

Berbagi

Laporkan Penyalahgunaan

Blog Berikut

Buat Blog

Masuk

POWERBUILDER
ALL ABO UT PRO GRAMMING

CA TE GO RIES

DO WNLOAD RINGTO NE S, WALLPAPER, GAMES

AJAX (4) Android (4) APACHE (1) Bind DNS (1) CENTOS (5) Database (6) datawindow (27) Graph (2) Iphone (1) Java (2) JQuery (1) MySQL (9) Netbeans (3) Oracle (6) PHP (18) powerbuider 11.2 (1) powerbuilder (34) Powerscript (38) recursive function (1) SEO (4) SQL (22) Squid Proxy (1) treeview (1) VB.NET (6) VirtualBox (1) VS FTP (1) WIN 32 API (12)

asikaja.com
R AB U, 30 JU LI 200 8

Auto Global Variables


OO purists say you should not have any global variables but as we all know you do not always have time to be pure. In most applications you normally have a few global declarations, usually some kind of an application manager or maybe an object request broker. Well if you export a PowerBuilder object an look at its source near the top of the code is a line that looks like:

SE AR CH

BOOKMARK

ARSIP BLOG

global type u_ken from userobject Mei 2012 (10) Which means that all objects created within the PowerBuilder painters have an automatic global variable of their type and name created. This is used by PowerBuilder to solve the references within your source objects but we can take advantage of this undocumented feature and just create an object of the correct type into this automatic global variable: u_ken = CREATE u_ken If you stop and think about it, PowerBuilder uses these variables itself at run time. For example when you say Open( w_mywindow ) the window w_mywindow is instantaited and its handle it stored in the global variable w_mywindow of type w_mywindow. This is how PowerBuilder knows the window is already open when you try to open it again using the same name, it also why you have to use a more complicated version of the Open command to open multiple copies, as there is only one global variable called w_mywindow in the application.
D I P OS K A N OL E H V I R T U E D I 08 : 31 L A BE L : P O W E R S C R I P T

April 2012 (9) Maret 2012 (11) Februari 2012 (11) Januari 2012 (4) Desember 2011 (2) Maret 2010 (1) Januari 2010 (1) Oktober 2009 (1) Agustus 2009 (1) Mei 2009 (3) November 2008 (3) Oktober 2008 (6) September 2008 (1) Agustus 2008 (17) Juli 2008 (41) Juni 2008 (72)

Large Random Numbers in powerbuilder


////////////////////////////////////////////////////////////////////////// // Function: f_BigRand // // Description: // This function uses 2 calls to Rand to generate Random numbers for large // ranges. It breaks the range into blocks of 32767 (max range for // RAND function) // The limit of the function is 32767 blocks of 32767. // It calls RAND to first determine which block, then calls RAND again to // determine the number in the // selected block. To ensure even probability over the range where // there are multiple blocks, // the same sub range is used for each block. // // Argument al_range // The upper limit of the range of random numbers you want returned. // The lower limit is always 1. The maximum value for the argument is // 1,073,676,289 or 32767*32767. // // Returns // A random number in the range 1 to al_range inclusive. // Or 0 if max range exceeded. // // Author: David Dennis ////////////////////////////////////////////////////////////////////////// // // Revision History

Mei 2008 (33)

MENGENAI S AY A VIRTUE L I H A T P R OFI L L E N G KA P K U

1 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

// // ----------------------------------------------------------------------// VERSION CHANGE ID WHO WHEN WHAT/WHY // ----------------------------------------------------------------------// 6.30 8/4/00 Initial version. ////////////////////////////////////////////////////////////////////////// Long ll_Offset, ll_Return Integer li_Range, li_Blocks // Block size is set to 32767 as this is the maximum range // the RAND function can handle Integer li_BlockSize = 32767 IF al_range > 1073676289 THEN //Range is too big Return 0 END IF //Determine The number of blocks li_Blocks = Truncate(al_range/li_BlockSize,0) //Add an extra block to accommodate any remainder IF Mod(al_range, li_BlockSize) > 0 THEN li_Blocks = li_Blocks + 1 END IF // Improve efficiency for ranges less than Block Size // where there is only one block IF al_range < li_BlockSize THEN li_Range = al_range ELSE li_Range = li_BlockSize END IF ll_Return = 0 // Loop until the value is in range. // If the value is not in range, calculate the // Offset again to ensure even probability DO UNTIL (ll_Return > 0) And (ll_Return <= al_Range) // Calculate a Random Offset using the number // of blocks as the range. // Offsets will range from [0 to (li_Blocks - 1)*BlockSize] // in increments of BlockSize ll_Offset = (Rand(li_Blocks) - 1) * li_BlockSize //Main Calculation ll_Return = ll_Offset + Rand(li_Range) LOOP Return ll_Return
D I P OS KA N O L E H V I R TU E D I 08: 29 L A B E L : P OW E R S CR I P T

RABU, 09 JULI 2008

Move a Window Without a Titlebar in powerbuilder


In order to move any window with a mouse it must have a titlebar. Child, popup and response windows can have no title bar but what do you do if you want to simulate a title bar and allow the user to move the window. In the mouse down event of the window (pbm_lbuttondown) send the window the following message:
Send( Handle( this ), 274, 61458, 0 )
D I P OS KA N O L E H V I R TU E D I 08: 46 L A B E L : P OW E R S CR I P T

Last Position Function in powerbuilder


/*--------------------------------------------------------------

2 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

GF_LASTPOS: K.M. Howe 09-13-1995 (PUBLIC)

Function to find the last position of a string in a string.

long: position in string

as_string: string to look in as_value: string to match

--------------------------------------------------------------*/ Long ll_Pos, ll_OldPos

ll_Pos = Pos( as_String, as_Value ) IF ll_Pos = 0 THEN RETURN ll_Pos

DO WHILE ll_Pos <> 0 ll_OldPos = ll_Pos ll_Pos = Pos( as_String, as_Value, ll_Pos + 1 ) LOOP

RETURN ll_OldPos
D I P OS KA N O L E H V I R TU E D I 08: 44 L A B E L : P OW E R S CR I P T

JUMAT, 04 JUL I 2008

Converting keycodes to character strings


With most objects, you can trap the key strokes using user events. For example, on a datawindow object, you can create a user event using Event Id = pbm_dwnkey. In this event, you'll find a parameter of type keycode. This is a predefined enumerated data type with values such as KeyA!, KeyB!, etc. But if you want to convert this value to a string, you'll find your choices are limited. I searched for a method, but found none that did not involve a long extended CHOOSE statement. It looks something like this:

CHOOSE CASE a_key // for a..z, we convert to lower case at the end of the function. CASE keyA! ls_Key = 'A' CASE keyB! ls_Key = 'B' CASE keyC! ls_Key = 'C' CASE keyD! ls_Key = 'D' CASE keyE! ls_Key = 'E'

Just in case you need this, the source code is available here. What use is it you ask? Well, I used it on a datawindow to duplicate what you can do with an editable drop down datawindow. For example, it was a list of parts. If you pressed 'J', you went to the parts starting with 'J', etc.
D I P OS KA N O L E H V I R TU E D I 08: 54 L A B E L : P OW E R S CR I P T

SEL AS A, 0 1 JU LI 2 00 8

Faster Arithmetic
When doing arithmetic in PowerBuilder it is easy not to give any

3 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

consideration to the Datatypes you are performing arithmetic upon. I recently found out that although PowerBuilder allows you to perform arithmetic using all numeric Datatypes the internal engine will always use the largest internal Datatype for the calculation to reduce the risk of rounding and overflow. You may be wondering where this is leading but take for example the integer Datatype. PowerBuilder always converts this to a long before performing any math. This is useful in stopping overflow and rounding errors but means that whenever an integer is used it is always cast to a long before use. Consider the following Code: Integer li_I, li_J, li_K li_I = 4 li_J = 80 li_K = li_I + li_J li_K ++ The line li_K = li_I + li_J would execute as follows: cast li_I to long, cast li_J to long, perform addition, cast resulting long to integer, assign to li_K. The line li_K ++ would execute as follows: cast li_K to long, add one, cast resulting long to integer, assign to li_K. You can see that in each of these steps there is a lot of casting taking place. You may well argue that its the 90's machines are getting faster and a cast takes only a nanosecond to execute. But in timed tests even simple integer match like the above code when changed to use the long Datatype will run 20% faster than its integer counter part. I will let you draw your own conclusion!
D I P OS KA N O L E H V I R TU E D I 08: 56 L A B E L : P OW E R S CR I P T

Object Variables Should Always be Private


When attempting to encapsulate a class that will be inherited you would normally declare the variables as protected so that they can be accessed be derived classes but are protected from aggregate and associated relationships. The problem with this is that it generates a higher level of coupling between the ancestor and the descendant. The impact of changing the way a particular attribute is managed could potentially impact all operations on the object. If a class is badly designed allowing protected attributes to be directly accessed and modified by derived classes can cause the impact of a change to be very extensive. To minimize problems, it is better to make all class attributes private and not directly accessible by external or derived classes. This design convention has three main benefits; * Low Coupling: The way that the attribute is managed, the Datatype or the type of information it holds can be changed while still presenting a standard interface via function overloading. * Superclass: By providing get/set operations to the attributes it makes it possible for a derived class to override the operations. This means that other operations on the superclass would be unaware that they were actually invoking a completely different behavior than simply storing and retrieving the attributes value. * Attribute Extension: A derived class may want to extend the functionality of an attribute. This would be impossible as all ancestor functions and descendant functions changing the attribute would not make your derived class aware of the change without a design change to the original ancestor. To summarize all attributes should be private with protected methods for getting and setting the attributes. In my new framework the get and set methods are named the same as the attribute with function overloading:

4 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

ls_Var = is_SomeVar() is_SomeVar( "New Value" )


D I P OS KA N O L E H V I R TU E D I 08: 55 L A B E L : P OW E R S CR I P T

JUMAT, 27 JUNI 2008

Make a Window Stay On Top


Sometimes when developing applications you want your window to stay on top of all other windows. One way to achieve this is to declare an API call, but PowerBuilder has support for this built in. If at all possible it is best not to go directly to an API call as is makes your application platform specific. Anyway, there is a method of the window object, SetPosition() which takes an enumerated datatype of TopMost! or NoTopMost!. If you call the function with TopMost! then your window will always be on top of all other windows in the system. Calling the function with NoTopMost! will return the window back into the normal layering of windows.
D I P OS KA N O L E H V I R TU E D I 20: 36 L A B E L : P OW E R S CR I P T

SABTU, 21 JUNI 2008

Ancestry Check Function


This function will check if an object inherits from the past in class name. Submitted by Erik Toft. ///////////////////////////////////////////////////////////////////////// // // Global service function: f_is_a // // Purpose: Allows a program to check the ancestry of any // object to ensure that it is derived from an // expected ancestor, therefore having an // expected interface. // // Usefull in dynamic scripting, generic code, // and inspective/intorspective applications. // // Programmer: Erik Toft // Date: 03/24/2003 // ///////////////////////////////////////////////////////////////////////// boolean lb_ret = false classdefinition lcd_class_def if isnull(apo_to_check) then return false if not isvalid(apo_to_check) then return false if isnull(apo_to_check.classdefinition) then return false if not isvalid(apo_to_check.classdefinition) then return false lcd_class_def = apo_to_check.classdefinition do while not isnull(lcd_class_def) and isvalid(lcd_class_def) if upper(lcd_class_def.name) = upper(as_class_name) then lb_ret = true exit //the loop end if lcd_class_def = lcd_class_def.ancestor loop return lb_ret
D I P OS KA N O L E H V I R TU E D I 09: 20 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

Listview Custom Sort in powerbuilder


PBDelta uses a variety of controls for the UI and in the File Selection

5 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

window I use the Treeview and Listview objects. The combination gives an explorer style navigation for selecting files. I used the out of the box sort for the list view columns, however two of the columns where not "string" data but a size and a date column, when the out of the box sort was used it sorted them as string not as the original data type and was not particularly useful. I wanted to make the columns sort using their underlying data types, but I did not want to keep two copies of the data around and then sort the rows manually based on the seconds copy of the data, so I set about coding the "sort" event on the list view. The sort event works a little bit like a comparator on a list, it gets called by PB and asks you to tell PB if item a is before, after or identical item b. I coded this up and it worked just fine, however on a large list I noticed the performance when populating the list was slow. Even once populated the performance of the text columns was not as good as it was previously using the in built PB routines. Some testing revealed that the complete sort process was firing every time I added an item to the list, which makes sense but was a bit of a performance hit. As my data was loaded in the correct order in the first place I did not even need the sort! To improve matter I switched off the custom sort property so there was no sort by default and put a check in the columnclicked event to see which column was clicked, if it was a basic string data type I called the standard PB function as follows: this.Sort( Ascending!, column ) Then if it was a complex data type I called the custom routine: this.Sort( UserDefinedSort!, column ) Finally I added code to the sort event which used the 3 parameter version of the GetItem command. This version allows you to get the value from a list view column as follows: this.GetItem( index1, column, ls_Item1 ) this.GetItem( index2, column, ls_Item2 ) ls_Item1 now contains the string value of the column, I just convert that into the original data type and then can perform the comparison as normal: ll_Item1 = Long( ls_Item1 ) ll_Item2 = Long( ls_Item2 ) IF ll_Item1 > ll_Item2 THEN RETURN 1 IF ll_Item1 < ll_Item2 THEN RETURN -1
D I P OS KA N O L E H V I R TU E D I 09: 19 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

KAMIS, 19 JUNI 2008

Replacement for pfc_u_tv's of_FindItem


The following function was written to stand in place for pfc_u_tv's of_FindItem function. At least in 16-bit environments (not sure of 32-bit), PFC's of_FindItem gets a stack overflow and GPFs when it has to search more than 50 tree items. This function avoids the problem by searching the tree items in a loop instead of recursively. The parameters are the same as of_FindItem, except the parameter "ai_Level" is replaced by "ab_AllDescendants" -- I found the parameter switch made the function easier to use. Function: f_FindChild Purpose: Searches a TreeView Item's immediate children (or all its descendants) for the target value. In trying to match, it checks either the Label or Data attribute on each child TreeView item. Only expanded TreeView items are searched.

6 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

Parameters: in - as_Attribute The attribute of the TreeView item to search ("Label", or "Data") in - aa_Target A variable of type Any containg the search target. in - al_Begin The handle of the TreeView item to begin searching, if 0 entire tree will be searched. in - ab_AllDescendants True indicates all descendants to be searched (False for only immediate children). in - ab_RespectCase True - search is case sensitive, False - search is not case sensitive. Only used if the target is a string. in - ab_FullCompare True - Label or Data and Target must be equal False - Label or Data can contain Target (uses POS() function). Only used if the target is a string. Returns: Long >0: the handle of the item whose Label or Data matches the target 0: item not found -1: a serious error occurred String ls_Label, ls_Target Integer li_Level, li_ChildLevel Long ll_Handle, ll_Found, ll_Parent Long ll_MatchingItem = 0 TreeViewItem ltvi_Item // Get the first expanded child of the starting point ll_Handle = f_GetFirstExpandedChild(al_Begin) // Save the level for the child IF ll_Handle > 0 THEN IF This.GetItem(ll_Handle, ltvi_Item) = -1 Then Return -1 li_ChildLevel = ltvi_Item.Level li_level = ltvi_Item.Level END IF // Checking for this item and stop when we get to the level higher than // we're looking DO WHILE ll_Handle > 0 AND ll_MatchingItem = 0 AND li_level >= li_ChildLevel // only do comparison if we're at the correct level (i.e. immediate child // or checking all levels) IF li_Level = li_ChildLevel OR ab_AllDescendants THEN // Check if this item matches using pfc_u_tv function IF Trigger Event pfc_searchcompare(ll_Handle, as_Attribute, aa_Target, & ab_RespectCase, ab_FullCompare) Then ll_MatchingItem = ll_Handle END IF END IF // Get the next Tree Item, going deeper into tree if the caller requested it IF ab_AllDescendants THEN ll_Handle = FindItem(NextVisibleTreeItem!, ll_Handle) ELSE ll_Handle = FindItem(NextTreeItem!, ll_Handle) END IF IF ll_Handle > 0 THEN IF This.GetItem(ll_Handle, ltvi_Item) = -1 Then Return -1 li_level = ltvi_Item.Level END IF LOOP Return ll_MatchingItem This supporting function gets the first expanded child for a specified TreeView item, if any. Function: GetFirstExpandedChild (supports f_FindChild)

7 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

Long ll_Handle TreeViewItem ltvi_Item // if whole tree is being searched, start looking from the first tree item IF al_Parent = 0 THEN ll_Handle = FindItem(RootTreeItem!, 0) ELSE IF This.GetItem(al_Parent, ltvi_Item) = -1 Then Return -1 // error getting TVI // If the specified tree item is not expanded, it will have no expanded children IF ltvi_Item.Expanded = False THEN ll_Handle = 0 // return not found ELSE // it's expanded, so get handle to first child ll_Handle = FindItem(ChildTreeItem!, al_Parent) END IF END IF Return ll_Handle
D I P OS KA N O L E H V I R TU E D I 09: 49 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

SENIN, 16 JUNI 2008

The Invisible MessageBox in Powerbuilder


The MessageBox may not display in the example below: SELECT cust_name INTO :ls_CustName FROM Customer WHERE cust_id = :ls_custid; MessageBox( "Warning!", "Customer: " + ls_CustName + & " does not have sufficient credit." ) If the customer is not found or if the customer name is Null, then no MessageBox will display. The reason: MessageBox displays nothing if an input parameter is Null (or evaluates to Null when concatenated). Having no MessageBox display could clearly result in both logic and business problems. Since the problem is essentially hidden, it might not be discovered for a long time. The solution: if you are using a framework (like PFC) and you should consistently use its Message (or "Error") service which should handle such a situation. Otherwise, create your own function like f_MessageBox (see sample code). As shown in the sample code, f_MessageBox explicitly checks for Null input. It can display an error and/or log the error when it receives Null input.
D I P OS KA N O L E H V I R TU E D I 10: 13 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

Setting Focus to the TabPage with the Control in powerbuilder


A common problem when using Tab objects is that you can set focus to a control (e.g. a DataWindow) on the tab but that control is not actually visible, since another Tab Page is selected. This may happen because another TabPage (e.g. TabPage 2) has focus when the save process starts and the DW on this Tabpage (e.g. TabPage 3) has an ItemChanged Error message to display. It is useful to create a general-purpose function that determines whether the control is on a Tab object and, if it is, sets focus to the Tab Page where the control is placed. The general-purpose function below was placed on the ancestor DataWindow object (u_dw in PFC) but it could be placed on any ancestor object.

8 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

Function Name: f_MakeTabPageCurrent Purpose: This function determines whether this control is on a Tab Object. If so, it makes the tab page that has this control current. If this object is not on a tabpage, then nothing happens. Parameters: None Returns: Long >0 Index of tabpage where object was placed (and focus was set) 0 the object was not placed on a tab object. -1 Error encountered integer li_Index boolean lb_TabParentFound = False boolean lb_TabPageFound = False long ll_RetCode u_tab lu_tab // u_tab is a standard visual user object of type "tab" powerobject lo_CurrentParent, lo_CurrentChild, lo_TabPage // Loop through control hierarchy until a Tab control or Window is found lo_CurrentParent = This.GetParent() DO WHILE (NOT lb_TabParentFound) AND (lo_CurrentParent.TypeOf() <> Window!) // we found tab control IF lo_CurrentParent.TypeOf() = Tab! THEN lu_tab = lo_CurrentParent // keep handle to Tab control lb_TabParentFound = True ELSE // if we're not at window yet, keep looking for a window or tab control IF lo_CurrentParent.TypeOf() <> Window! THEN lo_CurrentChild = lo_CurrentParent // keep handle for the Child object lo_CurrentParent = lo_CurrentParent.GetParent() // Get next parent END IF END IF LOOP // If a tab parent was found for this control, then make // the tab page containing our control current IF lb_TabParentFound THEN lo_TabPage = lo_CurrentChild // tabpage was second last object looked at li_Index = UpperBound(lu_Tab.Control[]) // Loop through child tabpages of Tab control looking for the tabpage DO WHILE NOT lb_TabPageFound and (li_Index > 0) IF lu_Tab.Control[li_Index] = lo_TabPage THEN // tab page found ... select it lu_tab.SelectTab(li_Index) lb_TabPageFound = True ELSE li_Index = li_Index - 1 END IF LOOP IF lb_TabPageFound THEN ll_RetCode = li_Index ELSE // TabPage not found -- maybe not in control array? (PB5 possibility) ll_RetCode = -1 END IF ELSE ll_RetCode = 0 END IF Return ll_RetCode
D I P OS KA N O L E H V I R TU E D I 10: 12 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

MINGGU , 15 J UNI 20 08

How to store your error messages with powerbuilder

9 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

If you have an application which uses the PFC error message service (n_cst_error), you might have given some thought to distributing your application with the messages stored in a table. At first, the error message table looked very attractive. And it is, for most situations, especially those which access a central database. However, if your application is deployed to many different locations and each location contains a database, the table approach can become a nightmare. As with many technical problems, a alternative approach came to me right after implementing a valid solution. At present, I'm storing this data within a database table which is immediately cached as soon as the application starts. I'm going to change the approach so that the datawindow contains the data all the time via the Rows/Data method. The specific problem I'm trying to solve is the updating of the messages table as used by the PFC error service. At present, the options provided with PFC are limited to sourcing the messages from a file or from the database. I want a third source: the datawindow, unretrieved. I'm going to extend the error object via the PFE and add a third version of of_SetPredefinedSource. When a new message is to be added to the list, I'll do it directly within the datawindow painter via Rows/Data. If I was continue maintaining the data within the table, then I would need to distribute updates to that table when new messages were added. Somehow these would be loaded into the database if they hadn't already been loaded. I think the PFC extension approach leaves less room for error. The application will always have the error messages associated with that version of the application.
D I P OS KA N O L E H V I R TU E D I 08: 35 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

Using the Resize and Preference service together in powerbuilder


The resize service (n_cst_resize) is useful for windows which contain controls which can be resized. The preference service (n_cst_preferences) is great for users. It allows windows to remember their last position and size. However, unless you use these services in the correct order, you can get into strife. For example, if you don't set the resize service and register your controls before the ancestor's open script completes, you may have wind up with controls that have not been resized properly. Below are two screens. The first has not resized correctly but the second one has correctly resized. The difference between the two windows is the following script in the pfc_preopen event. This script will be executed before the open event of pfc_w_master which is where the preferences are reset. You'll note that of_SetOrigSize() is commented out. I've never actually found a situation where this is needed or useful. But that doesn't mean it isn't useful. Somewhere...out there. this.of_SetResize(TRUE) //this.inv_Resize.of_SetOrigSize(this.width, this.height) this.inv_Resize.of_Register(dw_1, "ScaleToRight&Bottom")

resize1.gif (49186 bytes) Incorrect resizing resize2.gif (36495 bytes) Correct resizing
D I P OS KA N O L E H V I R TU E D I 08: 32 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

JUMAT, 13 JUNI 2008

ItemChanged Event in powerbuilder


This event occurs whenever the data is changed and the current field looses its focus (clicking on other field or other control, pressing tab, etc.). Use this event to validate the data and trigger ItemError event, whenever there is an error in the data. This

10 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

is one of the frequently used events in the DataWindow control. This event gives access to the old data (which is retrieved from the database), as well as the new data (the data changed by the user). Let's write some validation code in the event. For example, let's display an error message, if the user enters an existing product_no, while entering a new record. Actually, database gives an error message if duplicate product_no is entered, because, product_no is a primary key for the product_master table. The reason we would like to validate here is, to display the error message as soon as the user enters a duplicate product_no, instead of waiting till the whole record is entered and sent to the database. Which means that we need to check for the existence of the product_no, as soon as the user presses the tab key in the new record. This check can be done by using embedded SQL or with a hidden DataWindow control. We didn't teach embedded SQL yet, so, let's go with the second method. Place a new DataWindow control in the window and name it as dw_product_check. Go to the properties dialog box for this DataWindow control and assign d_display_product DataWindow object to this control. In case you don't remember, d_display_product takes an argument product_no and brings the data for the given product_no. If you don't get any results for the given product_no, it means that the product_no is not existing. We find no reason to display dw_product_check DataWindow control to the user, so, turn off its Visible property. Do you remember what we should do before we do any database operation on this DataWindow control? I am sure you guessed it by this time! We need to set the transaction object. Write the following code:

// Object: Window w_product_master // Event: Open // Append the following line to the existing code. dw_product_check.SetTransObject( SQLCA ) Write the following code in the ItemChanged event for the dw_product DataWindow.

// Object: dw_product in w_product_master Window // Event: ItemChanged If This.GetColumnName() = "product_no" And &

11 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

( This.GetItemStatus( Row, 0, Primary! ) = New! Or & This.GetItemStatus( Row, 0, Primary! ) = & NewModified! ) Then dw_product_check.Retrieve( Integer( Data ) ) If dw_product_check.RowCount() = 1 Then MessageBox( "Error", "Product No: '" + Data + & " ->" + & dw_product_check.GetItemString(Row, & "product_description") +& "' already exists.", StopSign!, OK!,1) Return 1 End If End If This code works fine here, because, product_description column is defined as NOT NULL in the database, meaning product_description column always contain something and it is never null. If the column allows NULL value, and if the content of the product_description for that product is NULL, then the MessageBox() will never display, because you are sending a NULL value as the parameter to the MessageBox(). If you want to learn about how the MessageBox() function behaves when the message text is NULL value, Place a CommandButton in w_script_practice and write string ls_null; MessageBox( "Test", ls_null), run that window and click on that button. You will never see that message box being popped up.) If that is the case, call GetItemString() on a separate line and check for the NULL value, substitute with appropriate message and then display it. For ex:

String l_desc1 l_desc1 = dw_product_check.GetItemString( Row, & "product_description" ) if IsNull( l_desc1 ) Then l_desc1 = "Not Defined." MessageBox( "Error", "Product No: '" + l_desc1 + & "' already exists, StopSign!, OK!,1) The first IF statement is checking for two things. One, whether the user is tabbing out of product_no column or any other column. We are interested in it only if the user is leaving product_no column. GetColumnName() returns the current column name. Just FYI, GetColumn() returns the column number. As you have learned in the "DataWindow Buffers" section, a row can be in one of the four

12 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

statuses. New!, NewModified!, NotModified!, DataModified!. Typically, user might enter the product_no, since it is the first column in the DataWindow. When the row is inserted, it is in the New! status and remains in the New! status till the user presses the tab and the ItemChanged event completes the script execution successfully. That's why we check for the New! status. Sometimes, user might enter data in the new record and navigate to other records and come back to change the product_no. For that reason, we need to check for the NewModified! status. GetItemStatus() gives the status of the specified column, in the specified buffer. If you specify the column number as 0 (zero), it returns the row status, instead of the column status. The third argument is the buffer name. Here, we are interested in the Primary buffer. PowerBuilder sends the data entered by the user as parameters to this event in the Data variable. Remember that it is always in the string format. We need to convert into appropriate formats. The next line is bringing data from the database. Observe the datatype conversion of the Retrieve() function parameter. RowCount() function returns the number of rows in the specified DataWindow. If the row count is greater than zero, it means that the given product is existing in the product_master. (Here, we are checking for 1 because, the product_no in product_master table is unique, meaning product_master would never have multiple records for a given product_no. Checking for >0 instead of = 1 will also serve the purpose; It is useful when you are expecting one or more rows.) Then we are displaying the error information by using the MessageBox() function. The last line Return 1 is very important. This statement tells PowerBuilder, what it has to do after completing the script execution.
D I P OS KA N O L E H V I R TU E D I 22: 00 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

PrintPage Event in powerbuilder


This event occurs for each page printed (just before the page gets printed. Please note that, RetrieveRow event occurs after the row is retrieved by PowerBuilder, but before it displays on the screen). This event gets PageNumber that will be printed as well as the number of the copy, Copy as parameters to this event.

// Object: DataWindow dw_product in w_product_master window // Event: PrintPage w_mdi_frame.SetMicroHelp( "Printing Page # " + & String( PageNumber) ) In fact, you need not code the

13 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

above script, because, when you call DataWindow's Print() function with TRUE as an argument, PowerBuilder automatically displays the page number being printed and also allows you to cancel if needed. If you want to skip printing a particular page, return 1 as the return value from this event
D I P OS KA N O L E H V I R TU E D I 21: 59 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

PrintStart Event in powerbuilder


This event occurs as soon as PowerBuilder starts printing. The total number of pages that are going to print, PagesMax, is passed as parameter to this event. You might want to ask the user whether the printer has that many papers in the tray or not. However, you cant stop printing from this event programmatically, instead you need to code in the PrintPage event.

// Object: DataWindow dw_product in w_product_master window // Event: PrintStart w_mdi_frame.SetMicroHelp( "Starting to Print" )
D I P OS KA N O L E H V I R TU E D I 21: 57 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

KAMIS, 12 JUNI 2008

RetrieveEnd Event in Powerbuilder


This event triggers as soon as the last row of the result set is retrieved. The total number of retrieved rows is passed to this event as a event parameter, RowCount.

// Object: DataWindow "dw_query" in w_product_master window // Event: RetrieveEnd w_mdi_frame.SetMicroHelp( "Rows Retrieved: " + & String( RowCount ) + & ". Query execution complete.")
D I P OS KA N O L E H V I R TU E D I 09: 37 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

RetrieveRow Event in Powerbuilder


This event triggers immediately after retrieving each row and before displaying it on the screen. This is the right place to write the code, if you want to do some process on the row, before the user sees the row on the screen. Writing code in this event and setting the Asynchronous option of the transaction object to TRUE, makes PowerBuilder to display the row on the screen, as soon as the code in this event is executed. For example, say the result set of a query has 10,000 rows.

14 dari 15

06/08/2012 11:16

powerbuilder: Powerscript

http://belajar-powerbuilder.blogspot.com/search/label/Powerscript

User will see the data on the screen only when PowerBuilder completes retrieving 10,000 first row is received by PowerBuilder (of course, code for this event is executed before it is displayed on the screen). By writing code or comment increases the total time required to retrieve the result set. To reduce the time, you might want to write the code in the RetrieveEnd (explained later), which is executed after retrieving all the rows in the result set. Writing code for the RetrieveRow or RetrieveEnd depends on the application requirement. * There is an exception to this behavior. If RetrieveAsNeeded option is set, PowerBuilder displays data as soon it completes retrieving one screen full of data. Whenever user tries to scroll down the screen, another screen full of data will be retrieved. PowerBuilder, depending on the DataWindow control size at run-time determines the number of rows that fit on a single screen. Another exception is, you should not use aggregate functionssuch as Sum(), Avg(), Min(), Max(), Count()etc in the DataWindow and should not set the sort criteria in the DataWindow. In this situation, PowerBuilder needs the full result set in order to calculate the aggregate functions or to sort the data. The following code displays the number rows retrieved on the status bar like a counter.
th

row*. By writing code in this event (even a

single line comment), user will see the data on the screen as soon as the

// Object: DataWindow dw_query in w_product_master window // Event: RetrieveRow w_mdi_frame.SetMicroHelp( "Rows Retrieved: " + & String( row ) )
D I P OS KA N O L E H V I R TU E D I 09: 36 L A B E L : P OW E R S CR I P T TI D A K A D A K OM E N T A R : L I N K K E P OS T I N G I N I

Beranda Langganan: Entri (Atom)

Posting Lama

15 dari 15

06/08/2012 11:16

Вам также может понравиться