Search code examples
delphipointerstframerefer

Delphi: refer to control from thread in frame


There is a FRAME (not a form) and a thread. How to refer to Frame's control from the thread? For example I want to disable a button from a thread. But I don't have a pointer to the button, no global variables in the frame.

Thanks!


Solution

  • You should not in fact, call any method or modify any property of an VCL control at all, or anything visible to the user (the User interface of your application, which means VCL controls normally in Delphi, whether in a frame or not) directly from a background thread.

    You can however send an event or notification to the main thread, either using PostMessage, or TThread.Synchronize or TThread.Queue.

    Rather than having a reference to the frame or the control in your thread object, it might be better to just pass the handle of the form that contains your frame or other controls, to the thread, and use a user-message (WM_USER+10001) like this.

    I prefer PostMessage to TTHread.Synchronize or Queue, because it's really simple and it works great. It's not exactly a cross-platform-friendly technique since it's tied to the Win32 API.

    You should call synchronize like this:

      TMyThread = class(TThread)
      private
        FFrame: TFrame;
        ...
      public
        constructor Create(AFrame: TFrame); 
        ...
      end;
    
      constructor TMyThread.Create(AFrame: TFrame);
      begin
        FFrame := AFrame;
        inherited Create;
      end;
    
      // do not call directly, only using Synchronize
      procedure TMyThread.AMethodWithNoParameters; 
      begin
         FFrame.Button1.Enabled := not FBusy;
      end;
    
      procedure TMyThread.DoWork; // called from Execute.
      begin
        FBusy := true; 
        Synchronize(AMethodWithNoParameters);
        Sleep(100); //dummy;
        FBusy := false; 
        Synchronize(AMethodWithNoParameters);
      end;