Продолжнение "Вызывает антирес и такой ишо разрез" Как можно осуществить событие для динамически созданного компонента? Проблема в том, что программа модульная и "процедура не описана как метод формы".
procedure MyOnClick(Sender: TObject); begin form1.Label1.Caption:=inttostr(form1.MainMenu1.Items.IndexOf(sender as TMenuItem)); end;
procedure CreateSubMenu(MainMenu: TMainMenu; p: TP); var i,j: integer; k: longint; N: TMenuItem; begin k:=3; //... SetLength(MenuItemArray, 2, k); for j:=0 to k-1 do for i:=0 to 1 do begin N:=TMenuItem.Create(MainMenu); n.Caption:=inttostr(i)+inttostr(j); n.OnClick:=MyOnClick; //вот здесь пишет Incompatible types: 'method pointer and regular procedure' MainMenu.Items[i+1].items[1].Insert(j,n); MenuItemArray[i][j]:=n; end; end;
Сама программа: VstupInfo.rar ( 275.13 килобайт )
Кол-во скачиваний: 528
Как можно осуществить событие для динамически созданного компонента?
Легко:
procedure CreateSubMenu(MainMenu: TMainMenu; p: TP); var // ... M: TMethod; // Делай раз !!! begin // ... // n.OnClick:=MyOnClick; // Это не нужно
M.Code := @MyOnClick; // Делай два !!! M.Data := n; n.OnClick := TNotifyEvent(M); // Всё, собственно, обработчик установлен
// ... end;
Работоспособность твоего кода не проверял, ибо не надо использовать нестандартных компонентов Не у всех они присутствуют.
Добавлено через 2 мин. Да, кстати, на предупреждения компилятора тоже обращай внимание, ладно? У тебя будет как минимум одно предупреждение, связанное с некорректной работой с переменными цикла (хоть проект и не открылся в Дельфи, но как текстовый файл я его просмотрел, это предупреждение видно невооруженным взглядом).
Итак, я нашел, что не давало открывать проект в D2009 - одно из свойств TIdHTTP уже отсутствует, поэтому проект не открывался. Открыл. Посмотрел... Могу подсказать, что надо будет сделать, чтобы оно заработало в 2009/2010, если тебя интересует (в том виде, в котором это сейчас - оно не очень-то работает, только при совпадении некоторых условий, а это плохой стиль программирования). Но это - не главное, что я хотел сказать. Главное - в другом.
У тебя парсинг сделан "в лоб". А зачем? Можно же воспользоваться средствами, которые тебе предоставляет Дельфи, и тогда вот это:
Цитата
procedure FindWreckersOnline(var Memo: TMemo;source: string); var prev,i: longint; s,n,m: string; poem: ansistring; begin // ... тут - получение строки Poem prev:=0; while PosEx('<tr><td>',poem,prev+1)<>0 do begin s:=''; prev:=PosEx('<tr><td>',poem,prev+1); for i:=prev to PosEx('</td></tr>',poem,prev) do s:=s+poem[i]; for i:=1 to 6 do delete(s,pos('<',s),pos('>',s)-pos('<',s)+1); n:=''; i:=1; while s[i] in Digits do begin n:=n+s[i]; inc(i); end; delete(s,1,length(n)); i:=1; while (s[i] in Letters)or (s[i]=' ') do inc(i); m:=''; while s[i] in Digits do begin m:=m+s[i]; inc(i); end; delete(s,pos('<',s)-length(m),length(s)-pos('<',s)+length(m)+1); Memo.Lines.Append(Format('%-5s',[n])+Format('%-7s',[m])+s); end; end;
Memo.Lines.BeginUpdate; for i := 0 to counter do begin Memo.Lines.Add(Format('%-5s%-7s %s', [SL.Strings[6*i + 0], StringReplace(SL.Strings[6*i + 1], '_', ' ', [rfReplaceAll]), SL.Strings[6*i + 2]])); end; Memo.Lines.EndUpdate;
finally SL.Free; end; end;
Ошибиться, как видишь, практически негде... Работает абсолютно так же, как твой код, только я один пробел (между фамилией и баллом, добавил, чтоб лучше смотрелось)
Да... А я то думал они есть и были у всех, кроме меня..Indy_9_00_17_src.zip ( 937.21 килобайт )
Кол-во скачиваний: 422
Я видел это предупреждение(это там где for i:=i to.., да?), но подумал, раз я его нигде не использую - то ничего страшного. А чем это может быть опасно?
А я думал, что у меня более новая версия (Indy 10), в которой НЕТ свойства MaxLineAction. Я что, должен теперь установить более старую версию?
Цитата
Как можно вручную открыть окно "Мessages"?
Нажать на Alt+F7 или Alt+F8 (переход к предыдущей/следующей ошибке), при этом должно появиться и окно Messages, если ошибки/предупреждения были, конечно.
Цитата
Я видел это предупреждение(это там где for i:=i to.., да?), но подумал, раз я его нигде не использую - то ничего страшного.
Ау.... Кто и чего где не использует? Ты получил предупреждение? Так вот тебе надо сделать так, чтоб твоя программа компилировалась без предупреждений. Чем опасно? Вот этим:
Notes The loop Variable value is not guaranteed by Delphi at loop end. So do not use it!
Теперь понимаешь, в чем проблема?
for i:=prev to PosEx('">',poem,prev)-1 do s:=s+poem[i];
// Вот тут чему равно i? Ты можешь гарантировать это? Source.Name:=s; s:=''; for i:=i+length('">') to PosEx('</td>',poem,i)-1 do // Здесь возникает предупреждение !!! s:=s+poem[i];
После окончания первого цикла у тебя i может быть не равно PosEx('">',poem,prev)-1 (на что ты рассчитываешь), тогда весь твой второй цикл улетит в тартарары... Будет незнамо где начинаться (и неизвестно где заканчиваться, потому как конечное значение второго цикла тоже вычисляется с учетом i). Дельфи гарантирует, что i будет принимать какое-то осмысленное значение ТОЛЬКО тогда, когда цикл закончился Break-ом, тогда то значение переменной, при котором произошел Break, сохранится и после цикла. У тебя Break отсутствует так что ничего определенного по поводу значения i сказать нельзя. Не зря во многих языках управляющая переменная цикла видима только внутри самого цикла, чтоб к ней потом нельзя было обратиться.
Могу подсказать, что надо будет сделать, чтобы оно заработало в 2009/2010, если тебя интересует (в том виде, в котором это сейчас - оно не очень-то работает, только при совпадении некоторых условий, а это плохой стиль программирования)
i, start, finish, counter: integer; SL: TStringList; begin srvReply := TStringStream.Create('', 1251); // Будем получать данные в кодировке 1251 Form1.IdHTTP1.Get(source, srvReply); Poem := srvReply.DataString; // Пересылаем в строку полученную информацию ...
... при этом работу по перекодировке из 1251 (или любой другой кодировки, которая указана в TStringStream.Create вторым параметром) возьмет на себя Дельфи.
Цитата
Ого, я тоже всегда считал, что если цикл завершился, то "loop variable" будет равна конечному параметру..
Очень плохо. Я тысячу раз говорил, что это не так, ни в Дельфи ни в Паскале, нигде это не должно подразумеваться, но никто ж не слушает... И в Турбо Паскале тоже нельзя было полагаться на подобное поведение, но на это тоже всем наплевать, здесь и сейчас работает и ладно.
Цитата
А что делать если в MyOnClick нужно еще передать дополнительные параметры?
Подумать, так ли они нужны на самом деле. Потому что обработчик события OnClick имеет строго определенную сигнатуру:
Цитата
type TNotifyEvent = procedure (Sender: TObject) of object;
, что явно не подразумевает передачу дополнительных параметров. Попробуй передать доп. параметры (а самое главное - обработать их в самОй процедуре), если обработчик - метод класса, то есть, без этих всяких ухищрений с TMethod... Получится у тебя это?
Все, конечно же, можно обойти, но так было бы чуть короче:
Код(Показать/Скрыть)
//...
procedure MyPathChange({Sender: TObject;}n: integer;var SourceVisual: TSourceVisual); var i: longint; begin for i:=3 to 5 do memo[i].Lines.Clear; if SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text) > -1 then begin FindWreckersOnline(Memo[n], source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Name); SourceVisual[n].Places.Caption := inttostr(source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Places); SourceVisual[n].Budget.Caption := inttostr(source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Budget); end; end;
procedure MyPathKeyPress({Sender: TObject;}n:integer; var Key: char;var SourceVisual: TSourceVisual); begin if (key = #13) then if SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text) > -1 then begin FindWreckersOnline(Memo[n], source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Name); SourceVisual[n].Places.Caption := inttostr(source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Places); SourceVisual[n].Budget.Caption := inttostr(source[SourceVisual[n].Path.Items.IndexOf(SourceVisual[n].Path.Text)].Budget); end else FindWreckersOnline(Memo[n], SourceVisual[n].Path.Text); end;
procedure TForm1.FormCreate(Sender: TObject); {var i: integer; M1, M2: TMethod; }begin //... { for i := 1 to 2 do begin M1.Code := @MyPathChange; M1.Data := SourceVisual[i].Path; SourceVisual[i].Path.OnChange := TNotifyEvent(M1); end; } //... end;
//А вот от этого в случае передачи параметров можно было бы отказаться
procedure TForm1.ComboBox1Change(Sender: TObject); begin MyPathChange(1,SourceVisual); end;
procedure TForm1.ComboBox2Change(Sender: TObject); begin MyPathChange(2,SourceVisual); end;
procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char); begin MyPathKeyPress(1,Key,SourceVisual); end;
procedure TForm1.ComboBox2KeyPress(Sender: TObject; var Key: Char); begin MyPathKeyPress(2,Key,SourceVisual); end;
end.
Ну и сам проэкт VstupInfo.rar ( 284.58 килобайт )
Кол-во скачиваний: 416
Могу подсказать, что надо будет сделать, чтобы оно заработало в 2009/2010
, если что:
Так что Дельфи 2009 обрабатывает совершенно нормально мой код (предупреждения о CharInSet - не в счет, я их пока не исправлял, и они выше по тексту)
Цитата
но так было бы чуть короче:
И сильно неправильнее, кстати. Я ж тебе сказал, какую сигнатуру имеет TNotifyEvent, а ты опять за свое. КАК ТЫ ОБЪЯСНИШЬ Дельфи, что функция с двумя параметрами должна втиснуться в то, что Дельфи с рождения знает, как TNotifyEvent - то есть, в функцию с одним параметром? Покажи мне, не как ты обходишь то, что наворотил, а как Дельфи принимает вместо одного параметра два, и как именно ты к этим параметрам обращаешься при выполнении кода. (Очень удачно ты сделал, да? Сначала выбрал неправильную структуру программы, потом обошел еще более неправильным костылем, и вроде бы даже и прав остался? Сейчас все работает, а потом - хоть потоп? Ну, разубеждать тебя не буду, дел у меня других нет что-ли... Потом сам придешь спрашивать. Я даже знаю, что именно. Но это уже, извини, без меня. Я больше на твои вопросы не отвечаю...)