On some of the XP-Theme product download pages it was stated that XP-Theme works with Clarion 5.5. This is not correct. When the source was moved up to Clarion 6.0 by PowerOffice there were quite a few modifications made to the code to make it thread safe in the new Clarion 6 threading model. Unfortunately this also made the code incompatible with Clarion 5.5.

Since it is seven and a half years since the last Clarion 5.5 build was released (May 29, 2002 according to my zip files) I will not be attempting to port the current product back to 5.5 compatibility.

I have updated the website and download information to reflect this and hopefully I found all the places it was mentioned. If you see somewhere that XP-Theme is compatible with Clarion 5.5, I would appreciate it if you would please let me know:)

Arnor Baldvinsson

One of my customer asked how he could hide and unhide a band on a PowerToolbar on the application frame from a PowerToolbar button on his MDI window.

In order to do this you need to set up the MDI client template on the MDI window. PowerToolbar uses a global instance of the POToolbarGlobalClass to control the appframe toolbar from other threads. You can take a look at some of the methods in the online documentation.

The code you need to toggle the visibility of a band looks like this:

If AppToolbar.GetBandVisible(TB1_TestWindowBand) = True
    AppToolbar.SetBandVisible(TB1_TestWindowBand, False)
Else
    AppToolbar.SetBandVisible(TB1_TestWindowBand, True)
End

That is pretty much all there is to it. This is exactly the same code as you would use on the appframe itself.

Arnor Baldvinsson

You may find that you need to dynamically change the text in a header or item. This is a bit tricky in the currently public release, but is made much simpler in the next release.

In the current release, 2.0.111, you need to add a few lines of code to make this work. First of all you need to declare a group in your procedure data embed:

TskI GROUP(POB:TaskInfo)
     End

This declares a group that you then need modify.

 TskI = Outlookbar1.GetTaskInfo(OutlookBar1.Outlookpanel,0)
 TskI.Title = 'Changed Outlookbar Title'
 Outlookbar1.SetTaskInfo(OutlookBar1.Outlookpanel,|
                         0,|
                         TskI)

The first line loads the local group, TaskInfo, with the data from the header or item. The second line sets the title in the group and the third line updates the the header or item. Since this is rather awkward we decided to simplify this down to:

OutlookBar1.SetTitle(OutlookBar1.Outlookpanel,|
                     0,|
                     'Changed Outlookbar Title')

To download version 2.0.112, which includes the new SetTitle method, please go to Download Icetips Outlookbar 2.0.112

Arnor Baldvinsson

Sometimes it is necessary to update and refresh controls on the toolbar. In order to do so you need to know the control IDs. You can find those in the templates (see the "ID" field in these screenshots) or you can open the source for the procedure in the embeditor (right click on procedure and select "Source" from the popup menu) and locate declaration of the toolbar class (search for "POToolbarClass"). The IDs will be declared rigth above it and the control IDs start in a number range of 10,000.

Here is an example on how to update couple of entry fields and a checkbox button:

 loc:query     = SEA:Terms
 MinAsk        = SEA:MinAsk
 MaxAsk        = SEA:MaxAsk
 Toolbar30.SetText    (ID30_SearchEntry, loc:Query)
 Toolbar30.SetText    (ID30_MnPrice,     MinAsk)
 Toolbar30.SetText    (ID30_MxPrice,     MaxAsk)
 Toolbar30.SetChecked (ID30_Haspic,      Sea:HasImage)
 Toolbar30.Refresh(True)

Note that in order to make sure that everything is updated correctly you need to use Refresh(True) rather than just Refresh()

Arnor Baldvinsson

How can you execute an action in XP Taskpanel in code?

This is actually very simple to do, but may not be obvious. The following code was tested in the XPTaskpanelDemo_C6.app in the OpenWindow event handler in the ToolboxMenu procedure:

TaskPanel1.ExecuteAction(TaskPanel1.Demos, |
                         TaskPanel1.Demos:Colors, |
                         MouseLeft, 0)

This opens the Color Demo window when the taskpanel window opens.

Arnor Baldvinsson

Clarion uses dialog units as screen position measurement unit when designing windows. This is fixed and cannot be changed at design time, but it can be changed at runtime. For window design we can use PROP:Pixels and to change to pixels it is a simple matter of setting PROP:Pixels to true for the window object, like:

 WindowLabel {PROP:Pixels} = True

Or:

 0 {PROP:Pixels} = True

Since 0 (zero) always refers to the structure of the current target object. To set the window back to using dialog units, simply set PROP:Pixels to false:

 0 {PROP:Pixels} = False

It may not be immediately obvious, but you can also use a few other measurement units when dealing with windows at runtime. There are 3 more measurement units that can be used: PROP:Thous, PROP:mm and PROP:Points. If you set the properties to false Clarion goes back to dialog units. Normally we would only think of using PROP:Thous, PROP:mm and PROP:Points on reports, but they work equally well on windows!

The smallest unit you can use with PROP:Thous is 1 which equals 0.0254mm. Point is 1/72" equal to about 0.353mm. With millimeters, the smallest unit is 2 (or at least it used to be) or 100 times bigger than the smallest unit with PROP:Thous, which makes it pretty much useless for any precision placements. If I need to set sizes in metric units I convert to 1/1000" It may not always be perfect but for most things I think it is close enough.

If you have a control on a report, for example a fixed width textbox and you want the user of your software to be able to format the contents on a window so that it will look exactly as it will print, you can get the measurement from the report and use it to set the size of the textbox on a window. Let

There has been some discussion about the fact that Microsoft no longer allows you to customize the start menu in Windows 7 to have the "classic" look. I have to admit that I have been using the Classic menu on both XP and Vista for many years and miss it when I started messing with Windows 7.

After some snooping around I found this article that describes how to set up a new toolbar which acts as a start button menu. Not quite the same, but close enough to get those of us who are suffering from withdrawal symptoms to relax:)

-- Arnor Baldvinsson

1

Two months ago I implemented the Clarion PDF generation templates in a client project. I was pretty horrified by the results as characters were chopped and spaced very strangely. After posting about this on the Clarion newsgroups, Lee White suggested that this was because I was running Large Fonts on my system.

Since I have had to deal with Large Font issues before simply because I use high resolution and need to be able to seeB) I decided to take a closer look at this and see what was going on.

Sure enough the problem stems from code in the ABPRPDF.CLW file where the width of the characters is calculated. To fix this I made some changes to the files.

This involves adding a single method to the PDFGeneratorClass class in ABPRPDF.INC and ABPRPDF.CLW:

Add to class declaration in ABPRPDF.INC (I put it in at the top of the
method list, around line 195):

AdjustDPIValues   PROCEDURE(Long pValue),Long 
!! AB 2009-02-19  Adjusts DPI values

In the classfile, ABPRPDF.clw, I added this:

PDFGeneratorClass.AdjustDPIValues   PROCEDURE(Long pValue)!!,Long 
!! AB 2009-02-19  Adjusts DPI values
HDcScreen  UNSIGNED
IDPI       Long
R          Real
L          Long
 Code
 R = 1
 HDcScreen = GetDC(0)
 If HDcScreen <> 0
   IDPI = GetDeviceCaps(HDcScreen, 88)
   L = ReleaseDC(0, HDcScreen)
   R = IDPI/96
 End
 Return (pValue / R)

In PDFGeneratorClass.AddFontDescriptor method, you have code like this:

!SET the fonts Width
LOOP LOC:I=SELF.FontsNames.FirstChar TO SELF.FontsNames.LastChar
   LOC:CharToTest=CHR(LOC:I)
   IF GetTextExtentPoint32(LOC:DC,LOC:CharToTest, 1,LOC:CharSize)<>0 THEN
      IF LOC:Subclasing THEN
         IF SELF.FontsNames.CharWidth[LOC:I] THEN
            SELF.FontsNames.CharWidth[LOC:I] = LOC:CharSize.eW
         END
      ELSE
         SELF.FontsNames.CharWidth[LOC:I] = LOC:CharSize.eW
      END
   END
END

I changed both of the assignments to the CharWidth to:

SELF.FontsNames.CharWidth[LOC:I] = |
           SELF.AdjustDPIValues(LOC:CharSize.eW)

In PDFGeneratorClass.GetTextWidth method, you have code like this:

 IF SelectObject(LOC:DC, LOC:HFont) THEN
    RV = GetTextExtentPoint32(LOC:DC,pText, LEN(pText),LOC:CharSize)
    LOC:OLDMAPMODE=SetMapMode(LOC:DC,LOC:OLDMAPMODE)
    DeleteObject(LOC:HFont)
    RETURN LOC:CharSize.eW + (LOC:CharSize.eW/20)
 END

I changed the RETURN to adjust the value:

RETURN SELF.AdjustDPIValues(LOC:CharSize.eW + (LOC:CharSize.eW/20))

This takes care of the font sizing problem in any DPI combination that I
threw at it:)

Arnor Baldvinsson

2

I stumbled on a really good deal on a HP LaserJet CP1215 color laser printer I had been looking at it at OfficeDepot and they had it for $199. I was looking it up on the HP website and they had it for a $99 special deal and free shipping so I jumped on it.

The printer arrived it last Saturday and tonight I finally got some time set it up. It was easy to set up. I connected it to my Vista 64 machine and there were no issues or problems and it prints just beautifully! I checked it couple of days after I bought it and it was back up to $299 and I see that they are now out of stock;)

It is rated 12ppm in Black only and 8ppm in color. We are starting to send out printed letters to our customers since we get close to 40% of our emails back with errors of one sort or the other, mostly because people have changed email addresses. So it is getting very difficult for us to keep in direct touch with our customers.

We have already sent out one mailing, about 3 weeks ago, and we got pretty good response so we are definitely going to be using this more and more in the future.

I have two excellent Epson photo printers, an older Epson 2200 workhorse and a more recent R-340. After comparing prices for ink and toner I realized that the difference wasn't much - if any - and the laser is faster and does a pretty good job - images and graphics look crips and details are excellent. Besides I would like to use my photo printers to print photos, which is what they were made for!

I will keep you updated on how this printer works in the long run, but so far it looks pretty impressive!

-- Arnor Baldvinsson

Why duplicate symbol error?

In Clarion 6.3 build 9058, Softvelocity added a bunch of new API function information to the WIN32.LIB and WININET.LIB library files. This caused a conflict with some other LIB files that included two shared function names, DLLInstall and DLLGetVersion.

There has been a fair amount of discussion about this, some confusion about who should fix this problem and even what exactly the problem is.

The problem

The problem, in a nutshell, is that two or more LIB files include the same function name and are both or all included into the same Clarion project or application. This results in the Clarion linker throwing a "Duplicate Symbol" error when it attempts to link in the second LIB file with the duplicate function name.

Can't we change the label and use NAME() to fix it?

No. That only takes care of issues with duplicate labels in Clarion. This is duplicate symbol which means that there are two libs that contain the same API function - in this case DLLGetVersion, DLLInstall.

This could be prototyped in two different places like this:

Module('IcetipsWhatever.lib')
  IT_DLLGetVersion  ...,NAME('DLLGetVersion')
  IT_DLLInstall     ...,NAME('DLLInstall')
END
MODULE('ABWHatever.Lib')
  AB_DLLGetVersion ...,NAME('DLLGetVersion')
  AB_DLLInstall    ...,NAME('DLLInstall')
END

This will give you two different (Clarion) labels for the functions, but they will still generate a "Duplicate Symbol" errors on IcetipsWhatever.Lib and ABWhatever.Lib which both include those two symbols. So this does not solve this particular problem. However it does solve the problem of possibly duplicate labels for the same (or different) API functions prototyped by different vendors.

This is kind of like the mail man trying to delive a letter to an address only to discover that there are two houses on the same street with the same number.

So, how CAN we fix it?

There are only two ways to fix this as far as I know.

  1. Find the offending LIB(s) and remove these two entries using LibMaker and then PLEASE report it to the producer of the LIB
  2. Dynamically load the DLLs and skip the LIBs altogether. This is what I use in our Iceitps Utilities for apis that are not included in the OLD Win32.lib and from now on I will use that as a base so anything that was not in the old win32.lib will be loaded dynamically. We also use this method in our Build Automator to load plugin dlls.

Finding the LIB files - what tools can we use?

The problem is finding the offending LIB files. Many search utilities won't search inside binary files. The version of the excellent Clarion Source Search that I have does not do it. I highly reccommend it for searching Clarion source though! The search in Total Commander DOES find it - one more reason to get that fantastic program!

I did find one freeware tool that does search binaries (or at least the Clarion LIB files!) without problems, called GrepWin. Very easy to use, supports both straight text search and regular expressions and it is FREE;

How do we fix the LIB files?

  1. Search for the DLLInstall or DLLGetVersion in your Clarion\3rdParty\LIB folder and any other LIB folders you can find.
  2. When you find the LIB, first MAKE A BACKUP of it in case you make a mistake and need to start over. Do not skip this step!
  3. Load the LIB file into the Clarion LibMaker (located in the Clarion\Bin folder - there should be a link in the Startup menu as well) and carefully locate the function name and select it in the list.
  4. Hit the Delete button to delete the function from the list
  5. Save the file back to the same LIB file.
  6. Repeat for the other function name.

Recompile your app to check if the error is gone. Repeat as necessary.

What about dynamically loading the functions?

While changing the LIB files can be done by the "end-user" developer, the dynamic loading has to be coded into the product or tool that makes use of the tool and is not reasonable for the end-user to deal with. In 2007 I posted an example application and classes that demonstrate how to do this. If you are interested in loading dlls dynamically at runtime, you can download this small, simple example and try it out yourself.

Hopefully this can help some people who are struggling with the "Duplicate symbol" error in Clarion 6.3 builds 9058 or 9059:)

-- Arnor Baldvinsson