![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Странный зависон приложения :( [D7, XP]
b/@. © (2009-06-17 10:20:00)Сделал форму для показа информации о программе и выводе версии.
Эта форма имеет такие особенности:
BorderStyle = bsNone
FormStyle = fsStayOnTop
также имеется таймер, для закрытия формы по интервалу
procedure TAbout.TimerTimer(Sender: TObject);
begin
Button.Click();
end;
procedure TAbout.ButtonClick(Sender: TObject);
begin
Release();
end;
и так как форма не имеет заголовка, то сделан обработчик для того, чтобы форму можно было двигать
procedure TAbout.WMNCHitTest(var Message: TWMNCHitTest);
begin
Message.Result := HTCAPTION;
end;
Но вот в чём загвоздка, когда я вывожу формуTAboutпоShowModal();и ничего не нажимаю, или нажимаю только на кнопку, то всё отрабатывает нормально.
Но если после показа модальной формы я начинаю интенсивно таскать её мышкой по экрану, то получаю ексепшн
AV at address 00000000. Read of address 00000000.
и при этом главная форма висит и не принимает фокус, хотя часть сообщений, в часности WM_PAINT отрабатывает.
Складывается такое ощущение, что модальная форма исчезла с экрана, но тем не менее еще не закрыта.
Интуиция подсказала мне, что нужно применитьReleaseCapture();в обработчике таймера.
При этом AV исчезло, но может нужно использовать что-то другое ?
Нат (2009-06-17 17:18:00) [1]"Вычищен" - это что имеется ввиду?
Обниливайте указатель, перед обращением проверяйте на nil.
Игорь Шевченко (2009-06-17 17:17:00) [2]Да, Close вместо Release
AV никаких нет
unit about;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
procedure HitTest(var Message: TMessage); message WM_NCHITTEST;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
Timer1.Enabled := false;
Close;
end;
procedure TForm2.HitTest(var Message: TMessage);
begin
Message.Result := HTCAPTION;
end;
procedure TForm2.Timer1Timer(Sender: TObject);
begin
Button1.Click;
end;
end.
и вызывать по Create(Application) do
try
showmodal;
finally
free;
end;
b/@. (2009-06-17 16:59:00) [3]
> Игорь Шевченко © (17.06.09 16:47) [23]
> перед release вставь таймер.enabled := false
Это сделано еще вTimerTimer, просто не указал.
Таймер срабатывает только один раз, но даже если этого делатьTimer.Enabled := false;, то второй раз не успеет сработать - интервал=5 секундам, а AV возникает сразу.
b/@. (2009-06-17 16:48:00) [4]
> Нат © (17.06.09 16:37) [21]
> При перетаскивании нужно останавливать таймер.
> Вероятно, из-за перетаскивания окна в момент его уничтожения по таймеру, происходило обращение к свойствам объекта. И соот-но, AV.
Думаю немножко не так.
Я неправильно воспользовалсяRelease();. Получалось так что сначала выполнялся FormDestroy, и на момент выполненияCloseModalобъект был уничтожен и вычищен.
Игорь Шевченко (2009-06-17 16:47:00) [5]
> procedure TAbout.ButtonClick(Sender: TObject);
> begin
> Release();
> end;
перед release вставь таймер.enabled := false
b/@. (2009-06-17 16:40:00) [6]
> Ega23 © (17.06.09 16:29) [20]
> > 1. Форму нужно уничтожать принудительно.
> А где её не уничтожают?
В вашем варианте форма уничтожается здесь:
> frm := TForm5.Create(nil);
> try
> frm.ShowModal;
> finally
> frm.Free;
> end;
В моём же варианте, она уничтожается сама после закрытия.
Кстати Плохиш ©, вы были правы,Closeлучше.
Нат (2009-06-17 16:37:00) [7]При перетаскивании нужно останавливать таймер.
Вероятно, из-за перетаскивания окна в момент его уничтожения по таймеру, происходило обращение к свойствам объекта.
И соот-но, AV.
Ega23 (2009-06-17 16:29:00) [8]
> 1. Форму нужно уничтожать принудительно.
А где её не уничтожают?
b/@. (2009-06-17 16:25:00) [9]
> Ega23 © (17.06.09 15:47) [18]
У меня был точно такой же, но в этом коде два ньюанса:
1. Форму нужно уничтожать принудительно.
2. Форму можно таскать безконечно долго, сообщение от таймера прийдёт только только после окончания перетаскивания.
Благодаря совету Cobalt ©(17.06.09 15:03) [16] выяснил, что AV в моём коде происходило из-за слишком раннеговызоваRelease();и некорректом закрытии при этом модального окна.
AV вызывалось в методеTCustomForm.CloseModalв строчкеif CloseQuery then, причём в саму функциюCloseQueryдаже не заходило.
На данный момент, для предотвращения AV, можно использовать совет Ega23 ©(17.06.09 10:47) [2] одновременно с Нат ©(17.06.09 10:56) [5].
При этом остаётся лишь ньюанс №2, но этим можно и пожертвовать :)
Но самое интересное - что мой собственный вариант сReleaseCapture();приводит к точно такому же результату, но ньюанс №2 при этом не возникает - форма закрывается в любом случае, и во время перетаскивания тоже...
Ega23 (2009-06-17 15:47:00) [10]
> Давай.
Ну на.
procedure TForm1.Button8Click(Sender: TObject);
var
frm : TForm5;
begin
frm := TForm5.Create(nil);
try
frm.ShowModal;
finally
frm.Free;
end;
end;
unit Unit5;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm5 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form5: TForm5;
implementation
{$R *.dfm}
procedure TForm5.Button1Click(Sender: TObject);
begin
ModalResult := mrOk;
end;
procedure TForm5.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
ModalResult := mrOk;
end;
end.
b/@. (2009-06-17 15:21:00) [11]
> Ega23 © (17.06.09 14:57) [12]
> Ну что, код давать? :)
Давай.
Cobalt (2009-06-17 15:03:00) [12]А что говорит стек вызовов (CallStack)?
а еще скомпилировать с Debug dcu.
AV оно же ниоткуда не выскакивает просто так, кто-то где-то что-то забыл, или понадеялся на что-то.
Сергей М. (2009-06-17 15:00:00) [13]
> начинаю интенсивно таскать её
Что значит "интенсивно" ?
А если не "интенсивно" то что происходит ?
Ega23 (2009-06-17 15:00:00) [14]
> Присвоение ModalResult приводит к закрытию или сокрытию
> окна.
Только если оно модальное.
Нат (2009-06-17 14:58:00) [15]Присвоение ModalResult приводит к закрытию или сокрытию окна.
В зависимости от обрабочика OnClose
Use ModalResult to close the form when it is displayed modally.
By default, ModalResult is mrNone. Set ModalResult to any nonzero value to close the form. The value assigned to ModalResult becomes the return value of the ShowModal function call used to display the form.
Ega23 (2009-06-17 14:57:00) [16]
> А что, по-вашему, должно было произойти ?
Знаешь, я вот только что написал код. Создаёт форму с таймером и кнопкой, запускает её модально. Можно дёргать усиленно по экрану. Никаких AV. Использовал ModalResult.
Ну что, код давать? :)
b/@. (2009-06-17 14:40:00) [17]
> Ega23 © (17.06.09 12:41) [10]
> Сдаётся мне, ты гонишь. Либо не пробовал, либо пробовал, но через опу.
А что, по-вашему, должно было произойти ?
Ega23 (2009-06-17 12:41:00) [18]
> Точно такой же как и без него...
Сдаётся мне, ты гонишь. Либо не пробовал, либо пробовал, но через опу.
b/@. (2009-06-17 12:13:00) [19]
> KSergey © (17.06.09 11:48) [8]
> И каков результат?
Точно такой же как и без него...
KSergey (2009-06-17 11:48:00) [20]> b/@. © (17.06.09 10:52) [4]
> > ModalResult := mr....; // Например, mrOK
> > end;
>
> Эту штуку пробовал,
И каков результат?