Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Вопрос по алгоритмике


Автор: DonPager 4.10.2007, 14:07
Сначала хотел запостить в алгоритмах но думаю что здесь уместнее
Вопрос такой есть код:
Код

  TCustomStation = class(TGroupBox)
  private
...
     FStatePSH :boolean;
...
     FbtnPSH :TCheckBox;
...
     procedure SetPSH(const Value :boolean);
....
  protected
     procedure OnPSHClick(Sender:TObject);
...
  public
     property StatePSH :boolean  read FStatePSH    write SetPSH;
...
  end;
...
implementation
...
procedure TCustomStation.SetPSH(const Value: boolean);
begin
 FStatePSH := Value;
 if FbtnPSH <> nil then begin
   FbtnPSH.Checked := FStatePSH;
   if FbtnPSH.Checked then FbtnPSH.Font.Color := clRed else FbtnPSH.ParentFont := true;
 end;
end;
...
procedure TCustomStation.OnPSHClick(Sender: TObject);
begin
  StatePSH := not FStatePSH;
  if FStatePSH then SendCommand(CODE_PSH,#$00) else SendCommand(CODE_PSH,#$FF);
end;
...

В ответ на эту команду приходит STATUS исполнения его я и обрабатываю
Код
if STATUS=OTKA3 then StatePSH = false
 эта команда вызывает рекурсивное зацикливание - так вот как бы мне изменить условия
чтобы всё работало и при этом если чекбокс чекнутый то он становилсябы красным?

Автор: Rennigth 4.10.2007, 14:54
Код

  TCustomStation = class(TGroupBox)
  private
     FLockChecked: Boolean;
     FStatePSH :boolean;
     FbtnPSH :TCheckBox;
     procedure SetPSH(const Value :boolean);
  protected
     procedure OnPSHClick(Sender:TObject);
  public
     property StatePSH :boolean  read FStatePSH    write SetPSH;
  end;

implementation

procedure TCustomStation.SetPSH(const Value: boolean);
begin
  FLockChecked  := True;
  try  
     FStatePSH := Value;
     if FbtnPSH <> nil then 
     begin
       FbtnPSH.Checked := FStatePSH;
       if FbtnPSH.Checked then 
         FbtnPSH.Font.Color := clRed else FbtnPSH.ParentFont := true;
      end;
  finally
    FLockChecked  := False;
  end;
end;

procedure TCustomStation.OnPSHClick(Sender: TObject);
begin
  if not FLockChecked then
  begin
    StatePSH := not FStatePSH;
    if FStatePSH then SendCommand(CODE_PSH,#$00) else SendCommand
(CODE_PSH,#$FF);
  end;
end;



Примерно так, если я правильно понял проблему.

Добавлено @ 15:06
А еще лутше так:
Код


procedure TCustomStation.SetPSH(const Value: boolean);
begin
  if FLockChecked then
    Exit;

  FLockChecked  := True;
  try
     FStatePSH := Value;
     if FbtnPSH <> nil then
     begin
       if FStatePSH then
       begin
         FbtnPSH.Checked := FStatePSH;
         SendCommand(CODE_PSH,#$00)
       end
       else
       begin
         FbtnPSH.Checked := False;
         SendCommand(CODE_PSH,#$FF);
       end;

       if FbtnPSH.Checked then
         FbtnPSH.Font.Color := clRed
       else
         FbtnPSH.ParentFont := True;
      end;
  finally
    FLockChecked  := False;
  end;
end;

procedure TCustomStation.OnPSHClick(Sender: TObject);
begin
  StatePSH := not FStatePSH;
end;

Автор: DonPager 4.10.2007, 15:21
т.е. добавить флажок на время выполнения процедуры присвоения, чтобы запретить рекурсию? smile 
всёрно спасибо  smile 
 smile ... а может как нить покрасивше? чтобы вообще рекурсии не возникало

Автор: Rennigth 4.10.2007, 16:09
DonPager, так уж в VCL-ом CheckBox-е сделано. 
Вот код который вызывается при клике:
Код

  if FState <> Value then
  begin
    FState := Value;
    if HandleAllocated then
      SendMessage(Handle, BM_SETCHECK, Integer(FState), 0);
    if not ClicksDisabled then Click;
  end;

т.е. Click будет вызываться если не установлен флаг ClicksDisabled, а он находиться в области видимости protected. Как вариант, можно этой проперте увеличить область видимости, примерно так, (прописать вначале модуля):
Код

  TCheckBox = class(StdCtrls.TCheckBox)
  public
    property ClicksDisabled;
  end;

И при необходимости устанавливать ее.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)