Can a TFrame be made to float outside the main form, i.e. make the desktop its parent? I tried setting Parent to nil and ParentWindow to the GetDesktopWindow but it remains invisible. Is this related to TFrame not being the same as a TForm? I've never quite understood the difference..

Comments

  1. Is there a reason why you cannot place the TFrame on a borderless form? Would that not give you the same behaviour without having to resort to more complicated solutions?

    ReplyDelete
  2. I use frames because it works better when their parent is the main form. When dragging on/off the main form (making them "float") I'd need to dynamically add/remove the form. It's possible, but I prefer to avoid it if there is an easy answer to my question. You say the solution is complicated, does that mean you know why setting the ParentWindow does not work?

    ReplyDelete
  3. For me, reframing requires setting Owner as well as Parent - does that help?

    ReplyDelete
  4. On second thought - that alone won't help at all. You would need to create a new form and your frame on that form.

    ReplyDelete
  5. Yeah, that works (but now I cannot drag the frame any more). I guess this is one of those areas where a form and frame differ a lot. Thanks.

    ReplyDelete
  6. Thanks Lars Fosdal , please note I have no issue doing this with forms, the question was if I can do it with frames without using a form (and break existing functionality).

    ReplyDelete
  7. I do not specifically know why it does not work, save to say that a TFrame ultimately is designed to be used in conjunction with a form or another frame. This leads me to consider that without being placed on a parent form or frame it may not paint its controls as one would expect. Perhaps tracing through your code and into the library code would help you determine why it is not painting.

    I guess what I am saying is that to make it work, you could well face a steep learning curve, so my suggestion was see if you could consider another option.

    ReplyDelete
  8. On facebook you just drop a thank you video into the comment and you're done. On G+ I need to post a public video to youtube first, and then link to it here.
    youtube.com - VidBlasterX 170220142649

    ReplyDelete
  9. Looks good. Glad to hear you found a way to make it work.

    ReplyDelete
  10. Mike Versteeg Or share it here directly from YouTube.

    ReplyDelete
  11. When I create the form you see a brief flash. I cannot seem to find a way to create the form and position it correctly without making it visible first, which draws it at (0,0). So in slomo you would see the empty form appear in the top-left corner, then it moves to the right position, and then the frame is painted over it. Works fine, looks less pro. Any ideas how to avoid the flash?

    ReplyDelete
  12. Mike Versteeg Would it be possible to override the paint routine for the form and disable paint until it is in the right position? You would probably have to do some extra message trickery to handle borders and tool bar painting (non-client area).

    ReplyDelete
  13. You can't make a frame be a top level window. It needs to be parented.

    ReplyDelete
  14. David Heffernan Should that read "parented"?

    ReplyDelete
  15. Lars Fosdal I would think keeping it invisible would do that, but apparently that disables everything. I'll look into your suggestion, thanks.

    ReplyDelete
  16. I tried locking the form's canvas, Perform(WM_SETREDRAW..) and SendMessage(..WM_SETREDRAW..), none of those help. Only solution that sort of works is LockWindowUpdate() as it does delay any drawing until the frame is reparented and ready to be painted on the right spot, but it causes my entire main window to flash (repaint) when I unlock.
    LockWindowUpdate is the most promising, but unfortunately it only postpones all paints, it does not prevent the ones I want to skip.

    ReplyDelete
  17. Possibly something you have already thought about, but does changing the double buffering setting for the different controls make any difference?

    ReplyDelete
  18. It's not the flashing of controls on the form that is the problem, but the creation of the form and the fact you cannot position it before it is made visible. So when you create it, it is first drawn at 0,0 before you can position it correctly. No doubt there'llbe some issues after that, but at least they would be in-place, not somewhere else.

    ReplyDelete
  19. I am using Delphi 10.1 and if I create a standard VCL forms project, two forms (Unit2 and Unit3, TForm2 and TForm3 respectively, TForm2 being the main form), If I create a single button on TForm2 with the following event code, it works for me with no flicker.

    procedure TForm2.Button1Click(Sender: TObject);
    var
      f: TForm3;
    begin
      f := TForm3.Create(Self);
      DoubleBuffered := True;
      f.DoubleBuffered := True;
      f.Parent := Self;
      f.Show;
      f.top := random(100);
      f.left := random(100);
      SetFocus;
    end;

    The initial DoubleBuffererd := True should be in the form create, but I just put it here for speed. What happens if you do the same?

    ReplyDelete
  20. Your form will be painted at 0,0 when you call Show, then move to a random position. You may not notice it as this is a very light app and probably happen too fast, but it does happen. Setting DoubleBuffered has no effect on this problem.

    ReplyDelete
  21. You may well be right. I have not observed any repainting and without doublebuffered being set I did see the repainting that you mention.

    ReplyDelete
  22. It's really quite odd you cannot set left & top when the form isn't yet visible. Not sure if that is by design or some bug.

    ReplyDelete
  23. You can. I have done some tracing. It looks as though a TForm's default show code will attempt to reposition and resize the form depending on the properties set for Position and DefaultMonitor. Try setting the DefaultMonitor to dmDesktop and Position to poDefaultSizeOnly. Then resize the form after the show. Ensure that the child form is also double buffered. I have tried this with around 50 controls on the child form, including a large image and it certainly appears to be OK for me.

    The alternative would be to create your own TForm descendent that overrides this awkward behaviour and sets the properties correctly and at the right time.

    ReplyDelete
  24. Indeed, that fixes the issue! Thank you!

    ReplyDelete

Post a Comment