Win32 and Direct2D in 2026

Seventeen days ago I made the first commit of PDF Side Viewer. Today the program is at 0.9.0, it’s about fourteen thousand eight hundred lines of C++ across thirty-nine files, and since this morning it can show three documents side by side instead of two.

The question I’d ask if I were reading this from outside is why on earth, in 2026, anyone would write a desktop application in plain Win32 with Direct2D for drawing, C++20, and the PDF rendering library compiled into the executable. There’s no framework, no runtime to install, no web layer anywhere.

The honest technical reason is that this program does one thing and does it while the user scrolls. Two or three document views that must stay aligned as you move them are a latency problem, and latency is far easier to control when there is nothing between your call and the drawing surface. The second reason is that what I hand over is an executable you open and use, with no prerequisites, which for a desk accessory matters more than people admit.

The third reason is that I enjoy it, and I’ll say that without dressing it up.

I pay for this in things that come free elsewhere. I have no control library: every toolbar, every context menu, every side panel is my own code. I don’t have a unit test suite either, which is a debatable choice I made deliberately: almost everything worth verifying here concerns window behaviour, not a pure function. So verification runs from the outside, driving the executable with Windows messages from a PowerShell script that opens real documents, scrolls, couples the two panes and checks where they ended up. It’s end-to-end testing of a graphical object, and for this program it’s the only thing that measures anything real.

Then there are two decisions that have nothing to do with performance and everything to do with caution, and they’re the ones I’m proudest of.

First. The viewer talks to the text editor: from a formula in the PDF I jump to the source line that generated it, and back again. To make the backward jump it has to launch a command, and the template for that command lives in a configuration file any ordinary user process can rewrite. If the viewer were running elevated, honouring that file would mean executing a command written by anyone at high integrity. So if it detects that it is elevated, it simply refuses. And it refuses when it can’t establish with certainty whether it is.

Second. The Explorer context menu integration is registered for the current user only, in a branch that by construction cannot make the program the default PDF handler. An accessory that grabs the double-click on every PDF on the system is a rude accessory, and I’ve installed enough of those to know how much it grates.

For the third pane, on the other hand, there’s no architectural justification. I have three editions of the same book, Italian, English and Hungarian, and last week I noticed I kept opening and closing the same pair in order to look at the third. The code was already ready to generalise, because synchronisation works on a chain of correspondences rather than a special pair, so the real work was all in the interface.

It’s funny to trace the chain back. I returned to university for a degree, out of the degree came a book, out of the book came three editions, and out of the three editions came a PDF viewer with three panes. None of these steps was planned, and I’m solely responsible for all of them.


Last modified on 2026-07-27