31 December 2012

Printing a listing on another printer

If you are running a Windows Vista or Windows 7 operating system, then the procedure to select different printers has changed from earlier versions of Windows. Starting with Windows Vista the "Printer ..." button is missing from the common dialog Page Setup dialog box. This is a consequence of the newer Windows operating systems. Now if you want to change printers or print drivers, you must change the default printer from the “Devices and Printers” window

How does this affect printing from GFA-BASIC 32?
To print a listing you can select Print in the File submenu. Depending on the presence of a text-selection, Gfa_Print will either print the entire listing or the current selection only. The text is printed immediately, without an option to select a different printer or to cancel the print job.

Initially, when you haven't printed before, the listing is sent to the default printer using default settings. At very first time, on my default printer, this produces lines in a vey hard to read small font size printed in the upper left corner of the paper.
Now I'm aware of this behavior, I make sure to set the printer page options before I  start printing for the first time.
The printer settings are available in the Printer Tab in the GFA-BASIC 32 Properties dialog box. The top two buttons are used to customize GB32's printing options.

GB32 Properties Printer

Selecting the top button labeled 'Page Setup' will bring up the Page Setup common dialog box. The Page Setup dialog box allows the user to set the paper size, source, orientation, and margins for printing. Starting with Windows Vista the common dialog box that pops up in GFA-BASIC 32 looks like this. The margin settings are initialized to zero, so it is logical that the listing is printed in the top-left corner of the paper.

GB32 PageSetup

After changing the page settings and selecting OK, GFA-BASIC 32 updates the top button in the Printer Tab with the name of the Printer (here Lexmark).

  • Due to a bug in the GFA-BASICs English string data the button text isn't shown properly. Rather than providing the printer name it only shows the word 'Printer'. (The first image shows a fixed version of the IDE.)

Applying new settings
The Page Setup values aren't applied before selecting the OK button in the GFA-BASIC Properties dialog box. The same is true for values from the other tabs (Editor and Compiler). 
The printer settings are applied to some global application variables and stored in 4 registry values in 'HCKU\Software\GFA\Basic' register sub keys:

Printer String containing DEVNAMES values
PrinterDMF Data containing relevant DEVMODE values
PrinterFont Compressed LOGFONT structure
PrinterPage Margins, MarginMetrics, Options. Used to initialize the Properties Print Page

At the next start the GFA-BASIC IDE reads back the "PrinterPage" values from the registry and assigns them to the global Printer Page variables. These values are used to initialize the controls of the Printer Properties Page (hence the name PrinterPage).

The "Printer" and "PrinterDMF" registry values contain device specific information. When the actual process of printing is started these values are used to create a printer device context. In case the values are missing or corrupted GFA-BASIC will obtain a device context for the default printer and starts printing without any user intervention.

How changes affect GB32
If you paid attention, you will have noticed that GFA-BASIC 32 supports the logic for using different printer than the default printer, but lacks the possibility to select one. How come? Well in all their wisdom Microsoft decided to change the Page Setup common dialog box starting with Windows Vista. Previously, until Windows XP, the Page Setup common dialog box contained a third button labeled 'Printer ...". It was this button that allowed the user to select a different printer from the Page Setup dialog box.

Workaround? Hardly!
When GFA-BASIC 32 was released it could not be known that MS would remove the "Printer ..." button. GB32's printer selection logic was build entirely around this button in the Page Setup dialog. That was - and still is - the only way to select a different printer. The only remaining option is to set another printer as the default printer from the Control Panel, although that wouldn't suffice. You should also remove the registry settings "Printer" and "PrinterDMF".

By providing this background information I'm hoping for some input as of how to get an actually working hotfix.

29 December 2012

Memory Leak with Form.Picture Object

When you assign an image to the Picture property of a Form Ocx, and don't release the Picture explicitly, a memory leak occurs when the Form is destroyed.

An image can be assigned using the Form-Editor Properties window in the sidebar. For a Form object the Properties window shows a Picture property that can be assigned an image (bitmap, icon, cursor, GIF, JPEG, and metafiles) by double clicking in the value column. Behind the scenes the LoadForm command - that is used to load a Form created with the Form-Editor - will create a COM Picture object on behalf of the Form. The dynamically allocated Picture COM object is then assigned to the Form.Picture property. 
However, a program may also set a Picture object to the Form.Picture property explicitly in code.

The memory leak occurs when the Form is closed. In the process of destroying all resources the Picture object is simply forgotten. The memory for the image is never released and the reference count on the COM object never reaches zero. Not only the memory necessary to store the image, but the memory allocated for the COM object will remain occupied. The memory used to store a bitmap can be of a considerable size and after some time you may even run out of memory. This most likely will present itself after RUNning a program multiple times within the IDE.

The best place to set the Picture Object to Nothing is within the Form_Destroy() event sub. A program cannot release the object when the Form has gone (==Nothing).

The leaked memory can never be reclaimed, because after the Form is destroyed the pointer to the Picture's COM Object is zeroed out. Selecting 'Cleanup Resources' from the Project menu will not work.