The first public showing of that demo did not include main thread protection. It originates from a session at the the 1995 Borland Developers Conference where Ray Konopka showed the below code from Bob Ainsbury.
Back in the .NET days, Delphi had an FINITEFLOAT compile option that came without a single-character shortcut.
It was about the handling of infinite float and other special float values in cases like overflow and underflow (including +Inf, -Inf and [Wayback] NaN).
At first – in the [Wayback] Delphi 8 (Octane) era of which few people want to be reminded off – it was the [Wayback] undocumented counterpart of the [Wayback] 8087 exception mask in x86 mode. Hallvard Vassbotn wrote an article about it and Chee Wee Chua documented it before it got documented in Delphi 2009 (that coincidentally dropped .NET support in the compiler – go figure):
Whereas the native Delphi compilers had exceptions turned on, Microsoft compilers (including .NET) had them turned off, hence the compiler option.
Like most new Delphi features in this century, FINITEFLOAT didn’t come without quirks. Often these are fleshed out in 2-3 product releases, but this one wasn’t:
The FINITEFLOAT compile option didn’t have a single-character shortcut. This made it impossible to use the {$IFOPT ...} construct as IFOPT only works for single-character compiler options.
For completeness some more information about exception masks in the native compiler:
In the past you could only set the exception mask as part of the full control word using [Wayback] Set8087CW, nowadays you can use [Wayback] SetExceptionMask.
Next to a precision mask, there are five exception masks you can set, see for instance this table from the [Wayback] Simply FPU Chap.1 Control Word section:
PM (bit 5) or Precision Mask UM (bit 4) or Underflow Mask OM (bit 3) or Overflow Mask ZM (bit 2) or Zero divide Mask DM (bit 1) or Denormalized operand Mask IM (bit 0) or Invalid operation Mask
Recently when printing the 3rd time and up, you get this error in many Delphi programs and the Delphi IDE:
Printer is not currently printing.
In the past this only occurred when you used a TPrinter and forgot to call BeginDoc.
But now it always occurs after reusing the same TPrinter instance for the 3rd time and up. Since the Delphi Galileo based IDEs (8 and higher; likely older ones as well: the source code printing hasn’t changed in a long time). The error actually occurs twice: after starting a source code print job, but also after cancelling the same failed source code print job.
The pattern there is using the Printer() function which has been the way the (un)official code examples have shown for ages (Delphi 2007 Printers.Printer Function [WayBack]; earlier examples like Delphi 7 [WayBack] usually in PDF files).
Like in the Delphi 7 “5-32 Developer’s Guide” page example:
procedure TForm1.Button1Click(Sender: TObject);
var
r: TRect;
i: Integer;
begin
with Printer do
begin
r := Rect(200,200,(Pagewidth - 200),(PageHeight - 200));
BeginDoc;
Canvas.Brush.Style := bsClear;
for i := 0 to Memo1.Lines.Count do
Canvas.TextOut(200,200 + (i * Canvas.TextHeight(Memo1.Lines.Strings[i])),
Memo1.Lines.Strings[i]);
Canvas.Brush.Color := clBlack;
Canvas.FrameRect(r);
EndDoc;
end;
end;
(Yes, that’s back in the D7 days when examples were still using with and not using try/finally statements for resource cleanup).
Actual cause and permanent fix
The printing problems are caused by various recent Windows updates part of MS16-098:
After you apply this security update and you print multiple documents in succession, the first two documents may print successfully. However, the third and subsequent documents may not print.
To resolve this issue, install update 3187022. For more information, click the following article number to view the article in the Microsoft Knowledge Base:
3187022 Print functionality is broken after any of the MS16-098 security updates are installed
This article describes printing issues that occur after any of the security updates that are described in Microsoft Security Bulletin MS16-098 are installed in Windows. You can fix these issues by installing the update that is described in this article. Before you install this update, check out the Prerequisites section.
This update applies to the following operating systems:
Windows Server 2012 R2
Windows 8.1
Windows RT 8.1
Windows Server 2012
Windows Server 2008 R2 Service Pack 1 (SP1)
Windows 7 SP1
Windows Server 2008 Service Pack 2 (SP2)
Windows Vista SP2
No solution for Windows 10 yet…
Until you install the fix: workarounds
For your own code (Thanks Remy Lebau for your answer), add this code for your BeginDoc call:
MyPrinter.Copies := MyPrinter.Copies;
You might want to keep including this in your code as you’re never sure when the end-users apply which Windows update.
For the Delphi IDE either:
Press the “Setup…” button in the “Print Selection” dialog when printing source code, then “OK” in the “Print Setup” dialog:
Print Selection dialog
“Print Setup” dialog.
Uninstall the security updated marked in blue (Security Update for Microsoft Windows (KB3177725):
A while ago, StackOverflow user Kobus Smit did some brilliant editorial work that – due to current state of StackOverflow – sort of fired backwards: his question got marked as duplicate before he could post his excellent answer. After that answer was posted, the oh-so pride SO-demi gods never took any energy to revisit to see which answers were best.
His simple question:
How can my Delphi app easily write to the Windows Event Log?What is the difference between TEventLogger and ReportEvent? How do I use the ReportEvent function?
Which somehow should be encompassed by this Delphi 5 question (apparently that 15+ year old Delphi version is still considered current by the SO demi-gods).
The answer summarises and extends existing answers spread out over StackOverflow and adds an EventLog git repository wrapping the ReportEventandRegisterEventSource (which somehow is always a pain: Delphi services for instance often forget that).
Lesson learned when doing editorial work:
prepare both the answer and question in markdown off-line
ensure you mention in the question that the answer is meant as collection of “best of” answers found elsewhere
post the question and answer in rapid succession
cross your fingers for the StackOverflow demi-gods being in a good mood
Since the table there is incomplete (even the Embarcadero documentation is wrong as some shortcuts can turn on and off a mode), here are the relevant shortcuts keys:
Ctrl + O + C
Turns on/offblockcolumn selection mode
Delphi 5 and up
Ctrl + O + K
Turns on/off block selection mode
Delphi 5 and up
Ctrl + O + L
Selects current line (and turns off block selection mode)
Delphi 5 and up
This is especially useful when the block selection is stuck (this happens every now and then: it’s a known bug).
Normal people would give Valentine presents today.
But 20 years ago, Borland thought it was a nice idea to release Delphi. Then a revolutionary new tool and lots of scepticism. Now – after 20 years – still going strong, despite all kinds of funny things that management at Borland, InPrise, etc did and the wild ride the market had.
Back then, the argument was that the designer needed to be restructured to do that. Now that it has – to accommodate FMX – and it is time, especially for the vast majority of Delphi users primarily using the designers to get work done.
So my wish, after 20+ years of Delphi use:
Please bring multi-level undo/redo functionality in the Delphi designer (form, datamodule, etc).