Welcome!

PowerBuilder Authors: Chris Pollach, Yeshim Deniz, Jayaram Krishnaswamy, Kevin Benedict, Avi Rosenthal

Related Topics: PowerBuilder, Microsoft Cloud

PowerBuilder: Article

Using .NET in PowerBuilder.NET

Taking a list of image files and scaling their dimensions down based on a percentage of the original size

When the beta for PB.NET (PowerBuilder 12) started I was pretty excited to get my hands on it. This version comes with a whole new IDE and with it many new features. As a result, we now get to take advantage of things like better intellisense, script navigation functions, and a WPF editor for better UI design and development. Most important was the promise of being able to use the .NET Framework to its nearly full potential.

What I want to do with this article is walk you through the source code of an application I built; an application that uses some parts of .NET (see Figure 1). Its main purpose is to take a list of image files and scale their dimensions down based on a percentage of the original size. This will essentially reduce their size, allowing you to upload them to your favorite photo sharing site much quicker. In addition to scaling the images this solution will also allow you to rotate them. You can download the complete solution here.


Figure 1: Image Scaler written in PB.NET

Setting Up Our Environment
There are a few things we have to do in order to get started. First, get the beta version of PowerBuilder 12 if you don't already have it. Once you have the beta installed, click on the File\New menu option and create a new solution. The solution will be created and added to the Solution Explorer window. Right-click on the solution name and select the New menu. The New item dialog will open again. Expand the Target node and select WPF Window Application. Last, right-click on the new target in the Solution Explorer and select the New menu option. This time, select the WPF Window item under the PB Object tree node (see Figure 2).


Figure 2: PowerBuilder New Item Dialog

We now have our application started with a new window created. Just like we do in Classic PB, open the Application object and add some code to the Open event:

Open(w_window)

Our main window needs some controls added to it in order to make it useable. I decided to use the Grid as my layout object so I could have certain parts of the window size and others remain in a static position. See Listing 1 for the row definitions that I used. (Listings 1 - 5 can be downloaded here.) The first, third, fourth and fifth rows remain a static height and the second row sizes with the window. See the available source for the remaining XAML.

The last thing we need to do when setting up our new application is making sure that we have all the required references. Right-click on the References item in the solution explorer and select Add Reference. When the Add References window opens, find and add the following:

System.Data
System.Drawing
System.Windows.Forms
System.Xml
System.Xml.Linq

Using Some .NET
Now that we got the boring trivial stuff out of the way, let's look at something interesting. There are several parts of the application that require the use of .NET. To gain easy access to this functionality you need to add a few namespaces to the window object. Add the following by going to your window objects script window, select Declare from the first drop down and Namespace\Using from the second:

System
System.Collections.Generic
System.IO
System.Diagnostics
System.ComponentModel
System.Windows.Forms
System.Windows.Controls
System.Drawing.Drawing2D
System.Drawing.Imaging
System.Drawing

Of course, these are not needed but it will help make your code a lot less verbose.

The Add button on our window will open a FileOpen dialog that will allow you to select many image files. PowerBuilder has a built-in function for this but I thought it would be interesting to see how easy it would be to use the .NET version (see Listing 2). What we need to do is declare a new class called OpenFileDialog. This class has a few somewhat familiar properties and methods. The ShowDialog() method will display the Open File Dialog in a modal state. After it closes, we will have a list of files in the FileNames collection, assuming some were selected. We can then iterate over this collection, adding them to our DataWindow or ListBox.

After we add the images to our DataWindow it would be a good idea to display what the combined size of the images are. After all, the purpose of this tool is to reduce the size of the files so it would be best to show what the total size is starting off. To get the size of a file we can use the FileInfo class (see Listing 3). One thing you'll notice is that this class is being created with a parameterized constructor. This is new in PB.NET. Once FileInfo is created using the name of the file, we have access to all sorts of information about that file (e.g., created date, last write time, read only flag, etc.). We are interested in the length property. This will tell us how big the file is in bytes.

So far we've seen the OpenFileDialog and FileInfo classes. Before we get into the really cool stuff I wanted to point out the use of some other random .NET classes and methods that are being used. Take a look at the code for the Process button (clicked event of cb_5, yes I got lazy and didn't rename my controls) or refer to Listing 4. I'm using the .NET MessageBox, String and List classes (also note that the List class is using generics).

Using the .NET Image Class to Resize Our Files
We now get to the interesting part, looking at the code that is responsible for reading and creating new images. Take a look at the code in Listing 5 or the ScaleImage function in n_processimage within our sample application.

First, the function declares and creates a new image "object" using the name of an existing image. This is done using the static method FromImage in the Image class.

The next step is to create Rectangles that represent the dimensions of our existing image and what's to be our new image. The sourceRect variable will store the X,Y, Width and Height values that will be read from the source image (our existing image). In this case we want to "read" the full image so X and Y are both 0 and the Height and Width are set to the actual Height and Width of the image. If we wanted to crop the image, we can specify different values. The destRect variable will be set to the size of our new image. We determine the new width and height by using the percent that was entered by the user. If the current width and height of the image was 200 pixels and the user entered a percent of 50, the new image would have a width and height of 100 pixels.

After we've determined the dimensions of our current and new image we can start to transfer data from one to the other. We'll create a new Bitmap object using the height and width of our new image. After doing that, we can create a new Graphics class using the Bitmap object created one step earlier. After these classes have been created and initalized, we can call the DrawImage method in the Graphics class. This method accepts the current image, the dimensions of the new image, and the coordinates of the existing image.

The last thing to do is call the Save method on the Bitmap class. This method will take the name of the new file and the image type as parameters.

That's all there is to it. Really, it's pretty simple. You might be asking, how did you figure this out? This is the great thing about .NET. Someone else in the C# world came up with this solution. I was able to use the exact same code but change the syntax a bit to make it work with PowerScript.

Translating C# Code to PowerBuilder
As mentioned in the previous section, the image-scaling portion of the code came from a C# example. Going forward, this is going to happen a lot (or at least until we get enough PowerBuilder .NET samples out there). Keep one thing in mind when using code from a C# example: .NET is not C#. With that said, you should not expect C# sytanx styles and rules to work in PB. Here are some things to remember:

  1. You can not declare and create a class on the same line.
  2. You must use the CREATE PowerScript keyword when creating classes, not the C# new keyword.
  3. Enumerated types always end with a "!".
  4. You can not create a class in a method call (e.g., MyClass.DoSomething(CREATE AnotherClass()).
  5. Semi-colons are valid but not needed in PowerBuilder.
  6. Arrays still use a 1-based index and the .NET List class uses a 0-based index.

Conclusion
There is so much more we can do now that we have WPF and .NET at our disposal. Once PB.NET becomes more mature (i.e., post beta), we will be able to add more sophisticated tools to our image-processing application, such as a cropping tool. This would be similar to the one seen in the C# version of this application: www.werysoft.com/imagescaler.aspx (see Figure 3).


Figure 3: Cropping Tool

More Stories By Brad Wery

Brad Wery is the President of Werysoft Inc. (www.werysoft.com) and 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.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.