Link to home
Start Free TrialLog in
Avatar of toreot
toreot

asked on

How to force immediate repaint of child forms?

My application draws mathematical patterns in child forms filling one quarter of the screen. The parameters for the patterns come from DialogForm (see code below). When DialogForm closes, the child windows already created need repainting. This is done by blitting a copy of the finished pattern to the child window in the FormPaint method of TChildForm.However,this takes place only after the pattern has been drawn in the new child, and as the drawing takes many seconds, the screen doesn't look good with partially blank child windows.
Why does not this code work? I would think that the repaint messages to the child windows would be processed when ProsessMessages is encountered, but evidently the last two lines are processed before the repainting takes place.(Update or Refresh instead of Repaint has no effect).


procedure TMainForm.MenuClick(Sender: TObject);
...
   DialogForm.ShowModal;
    if MDIChildCount >0 then
       for i:= 0 to MDIChildCount-1  do
          MDIChildren[i].Repaint;
    Application.ProcessMessages;
    Child:=TChildForm.Create(Self);
    Child.DrawPattern;
   {only now the repainting is done!}
end;

How can I achieve what I want?
ASKER CERTIFIED SOLUTION
Avatar of 98113772
98113772

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of toreot
toreot

ASKER

Sorry, the addition of Update did not make any difference. The child windows already on the screen still are not painted until the loop in my procedure DrawPattern in the newly created child form has finished, leaving gaping white holes in the earlier windows for many seconds. There must be a way of repainting them before the loop starts, or...?
Funny!
Well the place I use it in is very fast, so I guess this is why I don't have holes.

Have you tried to give the windows focus? Something (untested) like this:

...
if MDIChildCount >0 then
  for i:= 0 to MDIChildCount-1 do Begin
    MDIChildren[i].SetFocus;
    MDIChildren[i].Repaint;
    MDIChildren[i].Update;
    Application.ProcessMessages;
  End;
....

I can't try it from this machine, but maybe it will work


Avatar of toreot

ASKER

Still no luck! I have also tried moving the repainting code to the onclose and ondestroy event handler of DialogForm, with no result.
I had a similar problem when DrawPattern procedure call was associated with the OKButton handler on DialogForm, after the DialogForm.Close command. Then DialogForm wouldn't close until after the pattern had been drawn. Moving the code after DialogForm.ShowModal solved that. However, I have no place to move the DrawPattern code now! Associating it with a menu or a button would be too inelegant, I want it drawn immediately after DialogForm closes with no further user intervention. Could you perhaps introduce some delaying loop in your own code to see if your windows are repainted before or after the drawing of a new window? (Have tried both D1 and D2).
How about trying refresh instead of repaint?

Well, it seems to be exactely the same problem as you have. If I make a delay, it will repaint the new window before the old ones are painted.

After I have tested that, I got a new idea. Try this one:

if MDIChildCount >0 then
  for i:= 0 to MDIChildCount-1 do Begin
    MDIChildren[i].SetFocus;
    Application.ProcessMessages;
    MDIChildren[i].Invalidate;
    MDIChildren[i].Update;
    Application.ProcessMessages;
  End;

I did not test it myself (short of time right now)

Avatar of toreot

ASKER

As mentioned in my original question, neither refresh, repaint or update works. To me it looks like you can't force Delphi to update a window until an event handler has finished, even with a ProcessMessages inside the handler. Is this correct? If it is, can anybody think of a way to solve my problem?
Avatar of toreot

ASKER

Since my last comment, I have in fact solved the problem myself. The following code does what I want:

    Child:=TChildForm.Create(Self);
    if MDIChildCount >1 then
      for i:= 1 to MDIChildCount-1  do    
      begin
        MDIChildren[i].SetFocus;
        MDIChildren[i].Update;
        Application.ProcessMessages;
      end;
    Child.DrawPattern;
    Child.SetFocus;    {must be here, not before DrawPattern !}

In the process I discovered that the last created child has index 0 (Delphi doc. says otherwise).
Thanks for suggesting that SetFocus might be important.
toreot@hellerud.vgs.no