Tuesday, March 30, 2010

Fixing a Report Designer Bug

A bug in the VFP Report Designer has always, ahem, bugged me: something seems to turn on the Printer Environment setting for a report. Unless you want a report to always use a certain printer, that setting should be off. Turning it on can make a report much slower to open (for example, if the printer saved with the report isn’t available on your system) and can cause other problems.

I don’t remember who discovered this (sorry) but the cause turned out to be clicking the font button in the Field or Label Properties dialogs, even if you then choose Cancel. But how would that affect the Printer Environment setting?

Tired of having to deal with this, I decided to track it down. Fortunately, the source code for the Report Designer dialogs is included with VFP (unzip HOME() + “TOOLS\XSource\XSource.ZIP” and look in the resulting VFPSource\ReportBuilder folder). After some digging, I found the culprit in the ChooseFont method of FRXFormatUtil (in FRXBuilder.VCX), which is called when you click the font button. That method checks whether the TAG memo field in the header record of the FRX is empty or not. If not, it uses SYS(1037, 3) to update TAG and TAG2 from the current printer environment (the code is actually in FRXCursor.PopPrintEnv, which ChooseFont calls). The idea is that if the report has a saved printer environment, that environment should be used since it may impact which fonts are available. However, here’s the bug: TAG may not be empty even when TAG2 (which contains the binary printer environment) is. I’ve seen a single CHR(8) in TAG when TAG2 is empty, which means there is no saved printer environment, but it passes the NOT EMPTY(TAG) check in ChooseFont so the printer environment of the report is overwritten.

The solution is simple: change the test in ChooseFont from IS NOT EMPTY(TAG) to IS NOT EMPTY(TAG2), then rebuild ReportBuilder.APP. I’ve already made this change in the upcoming Stonefield Query version 4.0.

Wednesday, March 17, 2010

Taking out the Slow Parts, Again

While looking up something else, I came across Brad Martinez’s article on extending the functionality of the TreeView control. One of his points about how to load the TreeView more quickly caught my eye:

Make sure the parent Node's Sorted property is set to False: If Sorted = True, the TreeView must sort every Node as it is added under the parent Node. Make Sorted = True after all child Nodes are added.

I wondered how much of an improvement it would make, so I changed some generic TreeView loading code I use in lots of places to follow his advice. Loading 1,329 nodes dropped from 4.128 to 0.533 seconds, which is almost eight times faster!

As I’ve said before, I love taking out the slow parts!