So I have a working solution, but why it works is beyond me.
Instead of writing a callback, as cdbc suggested, I tried to put the processmessages call inside the inner loop. This resulted in the same result: at the halfway point of the outer loop the progress bar instantly goes from min to max. Then I thought, following cdbc's lead, I should somehow factor in inner loop counter in the increment of the progress bar.
From this:
Form2.ProgressBar1.Position:= trunc(j/jMax*100);
To this:
Form2.ProgressBar1.Position:= trunc(j*i/jMax*100);
This admittedly worked, but it slowed things down. I'll just divide it by some reasonable number,I thought, resulting in this:
Form2.ProgressBar1.Position:= trunc(j*i/i/jMax*100);
It worked! Ok, time for bed.
Woke up this morning, looked at that line of code, and thought: "What were you thinking? the i's just cancel out", and promptly erased them both... (so now I'm back at the original version that didn't work.) Recompiled it, and it worked!?
I must have made a mistake of some sort, I thought. But no. I rewrote the whole procedure with the original progress bar line. Compiled it... no go. Added the "trunc(j*i/i/jMax*100)" part, recompiled it. Works, but slow. Edited out the inner loop counters. Recompiled it, and it works just fine. Weird.
It works, I'm happy. Here's one for the X-Files.😎
Thanks to TRon and cdbc, for your help.