Delphi: ссылка на элемент управления из потока в кадре - PullRequest
2 голосов
/ 04 августа 2011

Существует FRAME (не форма) и поток. Как ссылаться на элемент управления Frame из потока? Например, я хочу отключить кнопку из потока. Но у меня нет указателя на кнопку, нет глобальных переменных в кадре.

Спасибо!

Ответы [ 2 ]

7 голосов
/ 04 августа 2011

На самом деле вы не должны вызывать какой-либо метод или изменять какие-либо свойства элемента управления VCL вообще или что-либо видимое пользователю (пользовательский интерфейс вашего приложения, что означает, что элементы управления VCL обычно в Delphi, будь то в кадре или нет) прямо из фоновой темы.

Однако вы можете отправить событие или уведомление в основной поток, используя PostMessage, или TThread.Synchronize, или TThread.Queue.

Вместо того, чтобы ссылаться на фрейм или элемент управления в вашем объекте потока, может быть лучше просто передать дескриптор формы, содержащей ваш фрейм или другие элементы управления, в поток и использовать сообщение пользователя ( WM_USER + 10001) как this.

Я предпочитаю PostMessage для TTHread.Synchronize или Queue, потому что это действительно просто и прекрасно работает. Это не совсем кроссплатформенный метод, поскольку он привязан к Win32 API.

Вы должны вызвать синхронизацию следующим образом:

  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;
2 голосов
/ 05 августа 2011

Как совершенно справедливо указано, вы не можете вызывать какие-либо элементы любого визуального компонента в фоновом потоке.

Чтобы отключить кнопку изнутри кода потока, вы должны иметь ссылку на кнопку ИЛИ ссылкусобытию, которому вы можете назначить объект потока - вы можете запустить поток внутри очереди или синхронизированной процедуры, например так: -

    type
      test=class(tthread)
         ondisablebutton:tnotifyevent;

{...}

затем, когда в процедуре, которую вы инкапсулируете с помощью tthread.synchronizeВы можете вызвать событие, не забывая проверить, назначено ли оно ....

procedure test.synchronisedprocedure;
begin
  if assigned(ondisablebutton) then
    ondisablebuttone(self);
end;

Когда вы создаете созданный вами объект потока, вам нужно назначить кнопку ondisable для процедуры в формесодержащий кнопку, которая выглядит следующим образом: -

procedure form1.threadwantstodisablebutton(sender:tobject);
begin
  button1.enabled:=false;
end;

для создания вашего потока необходима дополнительная строка: -

  mythread:=test.create;
  test.ondisablebutton:=form1.threadwantstodisablebutton;

примерно так, очевидно, вы должны иметь доступ к форме1 (илиформа, содержащая кнопку), где вы определяете и создаете свою ветку, что не обязательно является хорошим дизайном, но оно работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...