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


Автор: Nic442 30.4.2006, 00:19
Вопрос довольно легкий, но я чего-то не досоображаю.

Код

procedure TIndex_Form.Reopen1_files(Sender: TObject);
var
   NewItem: TMenuItem;
   str:string;
begin
   NewItem:=(Sender as TMenuItem);
   //MessageDlg('1',mtWarning,[mbOk],0);    Но если я здесь ставлю вывод сообщения то работает нормально.
   Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));  // ОШИБКА
   Reopen1.Insert(0,NewItem);
   str:=StringReplace((Sender as TMenuItem).Caption,'&','',[rfReplaceAll]);
   File_Reopen(NIL, str);
end;


Этот код висит у меня на одной из кнопок mainmenu. Повесил его на Toolbar на одну из Toolbutton в свойство MenuItem. Так при щелчке на этом button и выборе пункта меню он выдаёт ошибку. (Хотя из mainmenu нормально работает). Я проверил Reopen1.IndexOf(Sender as TMenuItem)=-1 при вызове через Toolbar. Но весь прикол в том что если я добавляю MessageDlg('1',mtWarning,[mbOk],0); то все работает. Подскажите, пожалуйста, как исправить ошибку. 

Автор: seer 30.4.2006, 00:37
первое, что напрашивается.. это поставить задержку.. но это непонашенски..
Давай кидай более полную картину. А вообще у меня было нечто такое... в программе память зас%%л и проги выделывали странные штуки. Маловероятно, но бытьтакое может. 

Автор: Nic442 30.4.2006, 00:44
Я то кину. Но ошибка то точно в том коде который я написал сверху. Я даже знаю почему, но как исправить??? 
Ведь Reopen1.IndexOf(Sender as TMenuItem)=-1 А он не может удалить несуществующий пункт меню (Reopen1.Delete[-1]) Но как только я ставлю сообщение, то даже пр -1 всё делает правильно.


Код

procedure TIndex_Form.Reopen1_files(Sender: TObject);
var
   NewItem: TMenuItem;
   str:string;
begin
   NewItem:=(Sender as TMenuItem);
   MessageDlg('1',mtWarning,[mbOk],0);
   Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));
   Reopen1.Insert(0,NewItem);
   str:=StringReplace((Sender as TMenuItem).Caption,'&','',[rfReplaceAll]);
   File_Reopen(NIL, str);
end;

procedure TIndex_Form.File_Reopen(Sender: TObject; openfile: string);
var
   stroka: ShortString;
begin
try
  if tab_text1.PageCount<=199 then begin
    Screen.Cursor:= crHourGlass;
    File_NewExecute(File_Open);
    text_GL[tab_text1.ActivePageIndex].Lines.LoadFromFile(openfile);
    stroka:='';
    stroka:=ExtractFileName(openfile);
    if Length(stroka)>=22 then
       stroka:=copy(stroka, 1, 20)+'..'+ExtractFileExt(stroka);
    tab_text1.ActivePage.Caption:=stroka;
    text_GL[tab_text1.ActivePageIndex].Modified:=false;
    file_names.Items.Add(IntToStr(tab_text1.PageCount)+': '+openfile);
    file_names.ItemIndex:=tab_text1.PageCount-1;
    text_GL[tab_text1.ActivePageIndex].hint :='Дата обновления: '
                     +DateTimeToStr(FileDateToDateTime(FileAge(openfile)));
    tab_text1.ActivePage.ImageIndex:=1;
  end else
    MessageDlg('Ошибка! Нельзя одновременно открыть больше 200 окон.'+#10#13
               +'Закройте одно из окон и повторите попытку.',mtError, [mbOK],0);
except
     file_names.Items.Delete(tab_text1.PageCount);
     tab_text1.ActivePage.free;
     i:=i-1;
     MessageDlg('Ошибка при открытия файла "'+openfile+'".',mtError, [mbOK],0);
end; {try .. except}
Screen.Cursor:= crDefault;
Timer_textTimer(OpenDialog);

end;
 

Автор: Sunvas 30.4.2006, 00:48
Цитата(Nic442 @  30.4.2006,  00:19 Найти цитируемый пост)
 Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));  // ОШИБКА

Нужно так
Код

if (Sender is TMenuItem) then Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));


Цитата(Nic442 @  30.4.2006,  00:19 Найти цитируемый пост)
Но весь прикол в том что если я добавляю MessageDlg('1',mtWarning,[mbOk],0);

Че-то я не совесем понял - куда добавишь?? 

Автор: Nic442 30.4.2006, 00:52
Sunvas, В коде на самом верху закоментарено куда,,, 

Ошибка не исправилась :-( 

Автор: Sunvas 30.4.2006, 00:59
Цитата(Nic442 @  30.4.2006,  00:52 Найти цитируемый пост)
Sunvas, В коде на самом верху закоментарено куда,,, 

Да. Не увидел..
Ну а с моим кодом-то работает? 

Автор: Nic442 30.4.2006, 01:02
Не, тоже самое. Вообще непонятно.
Ошибка не исправилась :-( 
 

Автор: Sunvas 30.4.2006, 01:14
Цитата(Nic442 @  30.4.2006,  00:44 Найти цитируемый пост)
едь Reopen1.IndexOf(Sender as TMenuItem)=-1 А он не может удалить несуществующий пункт меню (Reopen1.Delete[-1])

Ну так проверяй - если не равен -1 то удаляй.

Цитата(Nic442 @  30.4.2006,  00:44 Найти цитируемый пост)
Но как только я ставлю сообщение, то даже пр -1 всё делает правильно.

Видать глюк какой-то.. 

Автор: Nic442 30.4.2006, 01:19
Код

Ну так проверяй - если не равен -1 то удаляй. 

Не могу, иначе кнопка в баре будет не нужна.
Так дело в том что -1 идёт от ToolButton при нажатии на Toolbutton на любом пункте выдвигающегося меню. 

Автор: Демо 30.4.2006, 01:28
Что такое Reopen1? 

Автор: Nic442 30.4.2006, 01:33
Файл-->Reopen1-->NewItem
Reopen1 находится в меню, и включает в себя  Items 

Автор: Демо 30.4.2006, 01:47
Выполни вот это и исходи из того, что Sendere у тебя не TMenuItem:

Код

procedure TIndex_Form.Reopen1_files(Sender: TObject);    
var    
   NewItem: TMenuItem;    
   str:string;    
begin
  ShowMessage(Sender.ClassName);
 

Автор: Sunvas 30.4.2006, 01:52
Знаешь Nic442, я думаю это 1 из реальных глюков Борланда.. Попробуй другие компоненты поиспользовать или пойти другим путем..

ЗЫ. У меня даже банальный текст 
Код

showmessage(inttostr(n1.IndexOf(n2)));

на тулбаттоне показывает -1.

Добавлено @ 01:56 
Цитата(Демо @  30.4.2006,  01:47 Найти цитируемый пост)
Выполни вот это и исходи из того, что Sendere у тебя не TMenuItem:

Да нет! Именно Tmenuitem!

Цитата(Демо @  30.4.2006,  01:47 Найти цитируемый пост)
ShowMessage(Sender.ClassName);

Зачем это smile  

Автор: Nic442 30.4.2006, 02:00
ShowMessage(Sender.ClassName);

Имя класса я тоже решил поглядеть. При нажатии на ToolButton и выборе у него пункта меню выдаёт TMenuItem

Добавлено @ 02:07 
Я думаю такая фигня происходит. При нажатии на ToolButton и выборе у него пункта меню. Он посылает какое-то сообщение в меню. Но индекс остаётся -1  

Автор: Sunvas 30.4.2006, 02:13
Цитата(Nic442 @  30.4.2006,  02:00 Найти цитируемый пост)
Я думаю такая фигня происходит. При нажатии на ToolButton и выборе у него пункта меню. Он посылает какое-то сообщение в меню. Но индекс остаётся -1  

Токо меню ведь одно и тоже самое! Я проверял. 

Автор: Демо 30.4.2006, 02:13
Nic442
Ничего не понятно - как у тебя организовано. 

понял, чего ты навесил... 

Автор: Nic442 30.4.2006, 02:21
Объясняю: При открытии файла в Reopen1 добавляется путь к нему. При открытии его через Reopen1 этот пункт становится на первое место(удаляется со своего места и становится в на первое).
Код

procedure TIndex_Form.Reopen1_files(Sender: TObject);
var
   NewItem: TMenuItem;
   str:string;
begin
   NewItem:=(Sender as TMenuItem);
   ShowMessage(Sender.ClassName);
   Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));
   Reopen1.Insert(0,NewItem);
   str:=StringReplace((Sender as TMenuItem).Caption,'&','',[rfReplaceAll]);
   File_Reopen(NIL, str);
end;

procedure TIndex_Form.File_Reopen(Sender: TObject; openfile: string);
var
   stroka: ShortString;
begin
try
  if tab_text1.PageCount<=199 then begin
    Screen.Cursor:= crHourGlass;
    File_NewExecute(File_Open);
    text_GL[tab_text1.ActivePageIndex].Lines.LoadFromFile(openfile);
    stroka:='';
    stroka:=ExtractFileName(openfile);
    if Length(stroka)>=22 then
       stroka:=copy(stroka, 1, 20)+'..'+ExtractFileExt(stroka);
    tab_text1.ActivePage.Caption:=stroka;
    text_GL[tab_text1.ActivePageIndex].Modified:=false;
    file_names.Items.Add(IntToStr(tab_text1.PageCount)+': '+openfile);
    file_names.ItemIndex:=tab_text1.PageCount-1;
    text_GL[tab_text1.ActivePageIndex].hint :='Дата обновления: '
                     +DateTimeToStr(FileDateToDateTime(FileAge(openfile)));
    tab_text1.ActivePage.ImageIndex:=1;
  end else
    MessageDlg('Ошибка! Нельзя одновременно открыть больше 200 окон.'+#10#13
               +'Закройте одно из окон и повторите попытку.',mtError, [mbOK],0);
except
     file_names.Items.Delete(tab_text1.PageCount);
     tab_text1.ActivePage.free;
     i:=i-1;
     MessageDlg('Ошибка при открытия файла "'+openfile+'".',mtError, [mbOK],0);
end; {try .. except}
Screen.Cursor:= crDefault;
Timer_textTimer(OpenDialog);

end;

procedure TIndex_Form.File_OpenExecute(Sender: TObject);      // Открыть
var
   c, vsego: byte;
   stroka, str: ShortString;
   NewItem: TMenuItem;
   col, l, FileHandle:integer;
begin
  if OpenDialog.Execute then begin
     if FileExists(OpenDialog.FileName)=false then begin
        FileHandle:=FileCreate(OpenDialog.FileName);
        FileClose(FileHandle);
     end;
     col:=OpenDialog.Files.Count;

     for l:=0 to (col-1) do begin
        try
           if tab_text1.PageCount<=199 then begin
              Screen.Cursor:= crHourGlass;
              File_NewExecute(File_Open);
              text_GL[tab_text1.ActivePageIndex].Lines.LoadFromFile(OpenDialog.Files[l]);
              stroka:='';
              stroka:=ExtractFileName(OpenDialog.Files[l]);
              if Length(stroka)>=22 then
                stroka:=copy(stroka, 1, 20)+'..'+ExtractFileExt(stroka);
              tab_text1.ActivePage.Caption:=stroka;
              text_GL[tab_text1.ActivePageIndex].Modified:=false;
              file_names.Items.Add(IntToStr(tab_text1.PageCount)+': '+OpenDialog.Files[l]);
              file_names.ItemIndex:=tab_text1.PageCount-1;
              text_GL[tab_text1.ActivePageIndex].hint :='Дата обновления: '
                 +DateTimeToStr(FileDateToDateTime(FileAge(OpenDialog.Files[l])));
              tab_text1.ActivePage.ImageIndex:=1;

              vsego := Reopen1.Count-1;
              for vsego := vsego downto 0 do begin
                 str:=StringReplace(Reopen1.items[vsego].Caption,'&','',[rfReplaceAll]);
                 if OpenDialog.Files[l] = str then begin
                    NewItem:=Reopen1.Items[vsego];
                    Reopen1.Delete(vsego);
                    Reopen1.Insert(0,NewItem);
                    break;
                 end;
              end;
              if OpenDialog.Files[l]<>str then begin
                 if Reopen1.Count=12 then Reopen1.Delete(11);
                 if Reopen1.Count<=11 then begin
                    NewItem := TMenuItem.Create(Reopen1);
                    NewItem.Caption := OpenDialog.Files[l];
                    Reopen1.Insert(0,NewItem);
                    Reopen1.Items[c].OnClick:=Reopen1_files;
                 end;
              end;
           end
           else
               MessageDlg('Ошибка! Нельзя одновременно открыть больше 200 окон.'
                           +#10#13+'Закройте одно из окон и повторите попытку.',
                          mtError, [mbOK],0);
        except
             file_names.Items.Delete(tab_text1.PageCount);
              tab_text1.ActivePage.free;
              i:=i-1;
              MessageDlg('Ошибка при открытия файла "'+OpenDialog.Files[l]+'".'
                         ,mtInformation, [mbOK],0);
        end;
    end;
  end;
  Screen.Cursor:= crDefault;
  Timer_textTimer(OpenDialog);
end;
 

Автор: Демо 30.4.2006, 02:22
Вот такой код у меня возвращает не -1:

Код

procedure TForm1.ToolButton1Click(Sender: TObject);
var
  NewItem: TMenuItem;
begin
  NewItem:=(Sender as TMenuItem);
  ShowMessage(IntToStr(N21.IndexOf(Sender as TMenuItem)));


Похоже, что без конкретных данных не разобрать, что происходит... 

Автор: Sunvas 30.4.2006, 02:24
Демо, вот смотри:
1. Бросаешь на форму tmainmenu и ttoolbar
2. В tmainmenu создаешь 2 tmenuitem (воторое - субменю первого) - n1 и n2, а на toolbar-e создаешь кнопочку.
3. В свойсте кнопки tmenuitem ставишь n1
4. В онклике n2 пишешь
Код

showmessage(inttostr(n1.IndexOf(n2)));


Теперь парадокс - если мы кликаем по n2 с меню то получаем сообщение 0, а если с кнопки, то сообщение -1.. 

Автор: Nic442 30.4.2006, 02:26
N21 Включает в себя подпункты??
Теперь совсем непонятно становится.... 

Автор: Sunvas 30.4.2006, 02:28
Цитата(Демо @  30.4.2006,  02:22 Найти цитируемый пост)
ToolButton1Click

а нужно Reopen1Click или, как у меня n2click 

Автор: Nic442 30.4.2006, 02:32
Еще раз как у меня

Код

Reopen1.Items[c].OnClick:=Reopen1_files;
..............

procedure TIndex_Form.Reopen1_files(Sender: TObject);    
var    
   NewItem: TMenuItem;    
   str:string;    
begin    
   NewItem:=(Sender as TMenuItem);    
   Reopen1.Delete(Reopen1.IndexOf(Sender as TMenuItem));    
   Reopen1.Insert(0,NewItem);    
   str:=StringReplace((Sender as TMenuItem).Caption,'&','',[rfReplaceAll]);    
   File_Reopen(NIL, str);    
end;

 

Автор: Демо 30.4.2006, 02:33
Вот проект, который именно так себя и ведет, как я написал: 

Автор: Sunvas 30.4.2006, 02:34
Цитата(Nic442 @  30.4.2006,  02:26 Найти цитируемый пост)
N21 Включает в себя подпункты??
Теперь совсем непонятно становится.... 


Вот проект для понятливости: 

Автор: Демо 30.4.2006, 02:34
Цитата(Sunvas @  30.4.2006,  02:28 Найти цитируемый пост)
а нужно Reopen1Click или, как у меня n2click 


Это только название осталось такое. 

Автор: Sunvas 30.4.2006, 02:42
Демо, посмотри, чего мой реализ не работает 

Автор: Демо 30.4.2006, 02:43
Вопрос дополнительно:
На ToolButton навешено меню с подменю, или же только один пункт меню

Автор: Nic442 30.4.2006, 02:44
Чего-то не кочаются примеры... 

Автор: Демо 30.4.2006, 02:45
Цитата(Sunvas @  30.4.2006,  02:42 Найти цитируемый пост)
посмотри, чего мой реализ не работает 


По разному навешены пункты меню, и связка не та, что нужно. По поводу уточнения вот автор скажет  - посмотрим... 

Автор: Sunvas 30.4.2006, 02:45
Цитата(Демо @  30.4.2006,  02:43 Найти цитируемый пост)
На ToolButton навешено меню с подменю, или же только один пункт меню?


Цитата(Демо @  30.4.2006,  02:43 Найти цитируемый пост)
один пункт меню

 

Автор: Nic442 30.4.2006, 02:47
РИСУЮ

ФАЙЛ--> REOPEN1--> ЕГО ПОДМЕНЮ
                                           |
TOLLBUTTON--------->Показывается подменю 

Автор: Демо 30.4.2006, 02:47
Цитата(Sunvas @  30.4.2006,  02:45 Найти цитируемый пост)
один пункт меню


Тогда понятно.

Вот возьми обратно исправленный проект:

Добавлено @ 02:48 
Цитата(Nic442 @  30.4.2006,  02:47 Найти цитируемый пост)
TOLLBUTTON--------->Показывается подменю 


Ясно, у тебя другая ситуация. Минут через 5 попробую решить такую же задачку. 

Автор: Sunvas 30.4.2006, 02:49
Цитата(Nic442 @  30.4.2006,  02:47 Найти цитируемый пост)
РИСУЮ

Ясно, ясно! У меня просто и ща мозги кипят от чего же так..

Добавлено @ 02:50 
Цитата(Nic442 @  30.4.2006,  02:44 Найти цитируемый пост)
Чего-то не кочаются примеры... 

а ты правой кнопкой мыши и "сохранить объект как.."

Цитата(Демо @  30.4.2006,  02:45 Найти цитируемый пост)
По разному навешены пункты меню, и связка не та, что нужно.

Сможешь исправить?

Добавлено @ 02:53 
Демо, в моем коде добавить onclick это немного не то... 

Автор: Nic442 30.4.2006, 03:02
Да вот  
Да это я файл хотел прикрепить. Чего-то не прикрепился. 
Но в общем так как у тебя только при нажатии на toolbutton показывается submenu1 и   submenu2 

Автор: Sunvas 30.4.2006, 03:04
Цитата(Nic442 @  30.4.2006,  03:02 Найти цитируемый пост)
Да вот  

Это к чему? 

Автор: Демо 30.4.2006, 03:08
Nic442
У тебя OnClick на подпункты меню навешен?

Добавлено @ 03:10 
Уже понял.. 

Автор: Nic442 30.4.2006, 03:10
Конечно, ведь они через меню работают.

Reopen1.Items[c].OnClick:=Reopen1_files;
 

Автор: Sunvas 30.4.2006, 03:14
Цитата(Nic442 @  30.4.2006,  03:02 Найти цитируемый пост)
Но в общем так как у тебя только при нажатии на toolbutton показывается submenu1 и   submenu2

Но мой глюк так и остался глюком.. 

Автор: Nic442 30.4.2006, 03:17
Да и глюк такой же.  smile 
Я ещё пробовал через Toolbutton.MenuItem.IndexOf..... Но так тоже не катит

Добавлено @ 03:23 
Демо  Так попробовал или как?? Какие результаты? 

Автор: Демо 30.4.2006, 03:23
Вот работающий вариант на OnClick:
Неохота разбираться, глюк это Delphi или так и должно работать...

Код

var
  m: TMenuItem;
begin
  m := Sender as TMenuItem;
  showmessage(inttostr(m.Parent.IndexOf(m)));
 

Автор: Nic442 30.4.2006, 03:34
Можешь написать работающий вариант, чтобы он удалял пункт и всталял в начало без message 

Автор: Демо 30.4.2006, 03:37
Цитата(Nic442 @  30.4.2006,  03:34 Найти цитируемый пост)
Можешь написать работающий вариант, чтобы он удалял пункт и всталял в начало без message 

Так сейчас IndexOf не -1 возвращает...

Добавлено @ 03:39 
Код

var
  m: TMenuItem;
  ParentItem: TMenuItem;
begin
  m := Sender as TMenuItem;
  ParentItem := m.Parent;
  ParentItem.Delete(ParentItem.IndexOf(m));
  ParentItem.Insert(0,m);

 

Автор: Nic442 30.4.2006, 03:44
ВООООООООООООООООООООООООООООООООо !!!!!!!!!!!!!!!! ЗАРАБОТАЛО КАЖИСЬ... smile 
СПАСИБО ВАМ ОБОИМ. Я уже хотел сдаваться и спать....

Добавлено @ 03:49 
ТЕМУ ПОМЕЧАЮ :-) 

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