![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как из Thread обращ. к объектам на активной MDI-дочерней форме? [D7, WinXP]
Billis © (2006-06-15 15:40:00)Помогите, пож. Есть дочерняя MDI-приложения, на каждой дочерней форме есть кнопка, запускающая процесс. Эти процессы должны заполнять дочернюю форму. Однако, любой из этих процессов заполняет последнюю открытую дочернюю форму, а не ту, с которой был запущен. Как быть?
Процедура процесса:
procedure TMyThread.FullGrid;
VAR i: integer;
begin
CashCardForm.ADOQuery1.Active:=false;
CashCardForm.ADOQuery1.SQL.Text:=''+
'SELECT DISTINCT Children.ID, Children.Family, Children.Name, Children.HomeID, Home.Title '+
'FROM Home INNER JOIN (Children INNER JOIN (Cash INNER JOIN CashForChildren ON Cash.ID = CashForChildren.IDCash) ON Children.ID = CashForChildren.IDChildren) ON Home.ID=Children.HomeID '+
'WHERE Children.ID NOT IN '+
'(SELECT Children.ID '+
'FROM Home INNER JOIN (Children INNER JOIN (Cash INNER JOIN CashForChildren ON Cash.ID = CashForChildren.IDCash) ON Children.ID = CashForChildren.IDChildren) ON Home.ID=Children.HomeID '+
'WHERE YearCash='+MyMDIForm.cxTextEdit06.Text+') '+
'UNION '+
'SELECT Children.ID, Children.Family, Children.Name, Children.HomeID, Home.Title '+
'FROM Home INNER JOIN Children ON Home.ID=Children.HomeID '+
'WHERE Children.ID NOT IN '+
'(SELECT DISTINCT CashForChildren.IDChildren '+
'FROM CashForChildren)';
CashCardForm.ADOQuery1.Active:=true;
CashCardForm.ProgressBar1.Position:=10;
If CashCardForm.ADOQuery1.RecordCount>0 then
begin
CashCardForm.ADOQuery1.First;
CashCardForm.ADOQuery1.Sort:='ID';
For i:=1 to CashCardForm.ADOQuery1.RecordCount do
begin
CashCardForm.StringGrid1.Cells[0,i]:=CashCardForm.ADOQuery1.FieldValues['ID'];
CashCardForm.StringGrid1.Cells[1,i]:=CashCardForm.ADOQuery1.FieldValues['Family' ];
CashCardForm.StringGrid1.Cells[2,i]:=CashCardForm.ADOQuery1.FieldValues['Name'];
CashCardForm.StringGrid1.Cells[3,i]:=CashCardForm.ADOQuery1.FieldValues['HomeID' ];
CashCardForm.StringGrid1.Cells[4,i]:=CashCardForm.ADOQuery1.FieldValues['Title'] ;
CashCardForm.ADOQuery1.Next;
If i<CashCardForm.ADOQuery1.RecordCount then CashCardForm.StringGrid1.RowCount:=CashCardForm.StringGrid1.RowCount+1;
CashCardForm.ProgressBar1.Position:=10+(90 div CashCardForm.ADOQuery1.RecordCount)*i;
end;
end;
T1.Terminate;
end;
Сергей М. (2006-06-15 17:07:00) [1]Отладчик тебе в руки.
Billis (2006-06-15 17:05:00) [2]по [19] сделал - таже ерунда, заполняется только последняя дочерняя форма
evvcom (2006-06-15 16:49:00) [3]
procedure TMyMDIForm.FormCreate(Sender: TObject);
begin
FMyThread := TMyThread.Create(Self);
end;
constructor TMyThread.Create(AOwner: TMyMDIForm);
begin
FMyMDIForm := AOwner;
inherited Create(False);
end;
Джо (2006-06-15 16:49:00) [4]> [18] Billis (15.06.06 16:37)
> Как ввести ссылку на экземпля формы и передать ее?
Например, так:
// Твой потомок TThread
// со свойством
TMyThread = class (TThread)
private
FMyForm: TMyMDIForm;
public
property MyForm: TMyMDIForm read FMyForm write FMyForm;
end;
// Ну, и создание и запуск потока в таком роде:
with TMyThread.Create(True) do
begin
FreeOnTerminate := True
MyForm := <ссылка на активную MDI-форму>
....
Resume
end;
Billis (2006-06-15 16:37:00) [5]Как ввести ссылку на экземпля формы и передать ее?
Джо (2006-06-15 16:33:00) [6]> [15] Billis (15.06.06 16:21)
> А как определить какой номер у активной дочерней?
А не лучше ли, как уже, кажется, советовали, запоминать не номер, а ссылку на сам экземпляр формы? Зачем вводить лишние сущности и условности?
Billis (2006-06-15 16:31:00) [7]Спасибо
Billis (2006-06-15 16:21:00) [8]А как определить какой номер у активной дочерней?
Джо (2006-06-15 16:16:00) [9]> [12] Billis (15.06.06 16:10)
> да нет же,
> перед запуском потока (по нажатию кнопки на дочерней форме)
>
> необходимо определить номер активной дочерней формы, записать
> его в глобальную i и обращаться в потоке именно к нужной
> дочерней так MainForm.MDIChildren[i].
> Так наверное нужно сделать?
Зачем в глобальную? Заведи у своего потока свойство, в него и записывай ту форму, которая активна на момент создания экз. потока.
evvcom (2006-06-15 16:14:00) [10]> [8] Сергей М. ©
Да. Надо было смайлик поставить.
> [9] Billis
например в конструкторе. Только передавать тогда уж не номер, а сразу указатель на объект. Воспользуйся лучше советом [7]
> [12] Billis
нет, не так. Использование глобальных переменных для передачи локальных параметров чревато.
Billis (2006-06-15 16:10:00) [11]да нет же,
перед запуском потока (по нажатию кнопки на дочерней форме)
необходимо определить номер активной дочерней формы, записать его в глобальную i и обращаться в потоке именно к нужной дочерней так MainForm.MDIChildren[i].
Так наверное нужно сделать?
evvcom (2006-06-15 16:08:00) [12]> CashCardForm.ADOQuery1.Sort:='ID';
Почему бы это в SQL не вынести?
Нафига строить динамический запрос, если гораздо нагляднее он в статике в design-time?
Нафига StringGrid заполнять, если можно DBGrid использовать?
> CashCardForm.ADOQuery1.RecordCount
Пока не выполнен метод Last, значению RecordCount доверять нельзя.
Сергей М. (2006-06-15 16:05:00) [13]
> необходимо передать в поток номер активной дочернейформы
Не забывай, что пока поток работает, активной может стать другая форма.
Billis (2006-06-15 16:03:00) [14]для evvcom
необходимо передать в поток номер активной дочернейформы, чтобы обращаться к ней MDIChildren[i] , но как это сделать?
Сергей М. (2006-06-15 16:03:00) [15]
> evvcom © (15.06.06 16:01) [6]
Судя по изложению проблемы - не похоже.
Сергей М. (2006-06-15 16:02:00) [16]
> Billis (15.06.06 16:00) [5]
На то есть демо-проект threads.dpr.
Разберись как он работает и поймешь, что все гениальное проще пареной репы.
evvcom (2006-06-15 16:01:00) [17]> [3] Сергей М. ©
А может он его (TMyThread.FullGrid) через Synchronize вызывает?
Billis (2006-06-15 16:00:00) [18]Как же тогда быть, если выполнение запроса + заполнение дочерней формы очень длительный процес и зависания на пару минут приложения до заполнения формы недопустимо?
evvcom (2006-06-15 15:59:00) [19]> Однако, любой из этих процессов заполняет последнюю открытую
> дочернюю форму
Ты ж используешь глобальную переменную CashCardForm! Ясен пень. И эту переменную наверняка переписываешь всякий раз, когда создаешь новую MDI-форму. А теперь подумай, что у тебя происходит, и что же (как же) тебе надо бы сделать.
Сергей М. (2006-06-15 15:57:00) [20]Ну тады следует самым серьезным образом отнестись к тому, что обращение в визуальным (и не только) VCL-объектам в контексте доп.потоков НЕдопустимо.