Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   MainMenu и выход из программы (http://forum.oszone.net/showthread.php?t=253553)

novashdima 09-02-2013 05:25 2086105

MainMenu и выход из программы
 
Добрый день. В проге имеется главное меню, и конечно же стандартная менюшка "Выход", все, что надо сделать при нажатии на эту клавишу, это выполнить Form.Close, но вот в чем проблема, если прописать в обработчике нажатия Close или Form.Close, то компилятор ругается, будто нет соответствующей процедуры и если запустить прогу вывалится AV.
Создавать же обработчик и в нем писать одну единственную команду Close бред... Как быть?

lxa85 09-02-2013 09:44 2086144

Цитата:

Цитата novashdima
Как быть? »

Начать приводить примеры кода и ошибок компилятора.
А вообще, не Form.Close, а Form1.Close (если имя формы не менялось)
что то я сейчас ленюсь теорию с практикой на пальцах объяснять

LilLoco 09-02-2013 16:08 2086352

Цитата:

Цитата novashdima
Создавать же обработчик и в нем писать одну единственную команду Close бред... Как быть? »

А как вообще вы хотите выполнить "действие", не создавая обработчик?

novashdima 09-02-2013 16:33 2086367

Цитата:

Цитата lxa85
если имя формы не менялось »

Имя формы менялось, поэтому Form.Close я привел для примера.

Цитата:

Цитата lxa85
Начать приводить примеры кода и ошибок компилятора. »

Я итак вроде бы понятно написать, что имеется на форме компонент MainMenu, в этом MainMenu есть Item, при событии OnClick по которому надо делать Close. Если написать в обработчик Close то компилятор говорит, мол не найдена процедура обработки Close, удалить описание? Я говорю нет, и тогда при запуске программы вылетает AV (Access Violation), что логично.

Цитата:

Цитата LilLoco
А как вообще вы хотите выполнить "действие", не создавая обработчик? »

Можно создать свою процедуру и повесить ее на обработку любых событий нескольких компонентов, почему тогда нельзя на обработку повесить вызов не своей процедуры, а вызов обработчика формы?

lxa85 09-02-2013 18:37 2086463

Меня поражает нежелание людей приводить кусочек исходного текста. Я же не весь код прошу, а только проблемный участок. Может там синтаксическая ошибка, может логическая, нам как угадывать?
Вот сложно привести небольшой фрагмент описания формы, и вызов процедуры MainMenu?
Цитата:

Цитата novashdima
Можно создать свою процедуру и повесить ее на обработку любых событий нескольких компонентов, почему тогда нельзя на обработку повесить вызов не своей процедуры, а вызов обработчика формы? »

Три раза перечитал, три раза не понял. Наверно из-за нарушений принципов ООП.
---
Еще раз прошу привести фрагмент проблемного кода.

LilLoco 09-02-2013 18:48 2086467

Цитата:

Цитата lxa85
Три раза перечитал, три раза не понял. »

А я после прочтения второй раз, думаю, что автор пытается запихать не в код обработчика метод Close, а в имя обработчика.
Что то типа этого:
вместо
Код:

procedure TForm1.НажатиеПунктаМеню(Sender: TObject);
begin
  Form.Close;
end

это
Код:

ПунктМеню.OnClick:=Form.Close;
Цитата:

Цитата novashdima
Я итак вроде бы понятно написать »

Но никто не понять, увы...

novashdima 09-02-2013 19:44 2086507

Цитата:

Цитата LilLoco
А я после прочтения второй раз, думаю, что автор пытается запихать не в код обработчика метод Close, а в имя обработчика. »

Да, все верно
Цитата:

Цитата LilLoco
ПунктМеню.OnClick:=Form.Close; »

Так сделать реально?

Iska 09-02-2013 21:22 2086561

Цитата:

Цитата novashdima
Так сделать реально? »

А в документации почитать — реально или нет — нельзя?!

novashdima 09-02-2013 23:02 2086652

Цитата:

Цитата Iska
А в документации почитать — реально или нет — нельзя?! »

Вот все, что есть в документации

lxa85 10-02-2013 00:01 2086698

novashdima, это нарушение принципов ООП. Я завтра картинку нарисую для наглядности. Некорректное взаимодействие объектов.

novashdima 10-02-2013 00:05 2086700

Цитата:

Цитата lxa85
ovashdima, это нарушение принципов ООП. Я завтра картинку нарисую для наглядности. Некорректное взаимодействие объектов. »

Спасибо за ответ, значит нельзя. А вот картинка, почему нарушает очень не помешает.

Iska 10-02-2013 01:24 2086759

Цитата:

Цитата novashdima
Вот все, что есть в документации »

А так: Vcl.Menus.TMenuItem.OnClick - XE3 API Documentation?

novashdima 10-02-2013 01:46 2086780

Цитата:

Цитата Iska
А так: Vcl.Menus.TMenuItem.OnClick - XE3 API Documentation? »

Эм... то есть вместо процедуры обработки я могу ввести WM_COMMAND?

Iska 10-02-2013 02:03 2086792

Я постарался выделить существенную часть:
Цитата:

Delphi

property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored;


novashdima 10-02-2013 02:44 2086809

Цитата:

Цитата Iska
Я постарался выделить существенную часть: »

Ага, то есть свойство OnClick-а TNotifyEvent, что являет собой строку-название обработчика, но получается, что Form.Close - функция, но тогда вопрос, почему я могу указать имя произвольной функции в качестве TNotifyEvent, а другую функцию, которая по идее TNotifyEvent - не могу???

Iska 10-02-2013 05:24 2086831

Procedural Types (Delphi) - RAD Studio XE3
Events Are Properties - RAD Studio XE3

Во всяком случае — имя, не строку. Почему «по идее»? Как определили? Каков код?

novashdima, я пробовал Delphi один раз, в третьей версии, лет пятнадцать назад ;). Не стесняйтесь излагать подробно и приводить код, на форуме достаточно просвещённого народа, чтобы помочь.

novashdima 10-02-2013 06:08 2086840

Цитата:

Цитата Iska
Во всяком случае — имя, не строку »

Я думал имя это строка...
Цитата:

Цитата Iska
Почему «по идее»? »

Эм... свойство у event у нас получается типа TNotifyEvent , которая является именем обработчика (функции). При этом свойством одного event указать функцию-обработчик другого event у меня не получилось, может попробовать свойством event назначить свойство другого компонента, то есть свойство OnClick у MainMenu назначить Form.OnClose?

Раз так просите привожу конкретный пример:
Код:

Есть ExitFileItem: TMenuItem
ExitFileItem.OnClick = ExitProgram

procedure TMainForm.ExitProgram(Sender: TObject);
begin
  Close;
end;

Все, что надо, это значение свойства ExitFileItem.OnClick присвоить в Object Inspector MainForm.Close|MainForm.CloseQuery|Exit|Application.Terminate|Halt|WM_Close|WM_Quit... может еще какие способы закрыть приложение есть, я все что знал сказал)
п.с. при этом все, что меня интересует, так это то, почему я значением свойства могу указать MyFunction
Код:

type
  TMainForm = class(TForm)
      procedure MyFunction(Sender: TObject);

То есть процедура у нас MainForm.MyFunction(Sender) и все отлично, а вот указать MainForm.Close(Sender) я не могу, вопрос - почему?

Цитата:

Цитата Iska
Не стесняйтесь излагать подробно и приводить код, на форуме достаточно просвещённого народа, чтобы помочь. »

Русскоязычные форумы отличаются тем, что в процессе обсуждения проблемы сначала все скажут, какой ТС лох, что он тут забыл, ему в раздел новички или вообще с этого форума, через постов 15-20 начнут обсуждать суть темы и или окажется, что никто не знает, что делать или подскажут вариантов 5 минимум решения проблемы) На англоязычных форумах/чатах если задашь вопрос, то тебе сразу прямо ответят, дадут линк, объяснят что к чему и пожелают удачи)

Iska 10-02-2013 09:56 2086887

Цитата:

Цитата novashdima
Русскоязычные форумы отличаются тем, … »

Что делать ;), «у каждого свои недостатки». Впрочем, я лично видел всякое.


Цитата:

Цитата novashdima
а вот указать MainForm.Close(Sender) я не могу, вопрос - почему? »

Возможно, не тот тип? Впрочем, как я писал выше, мои знания давно устарели. Подождём более опытных коллег.

Любезный 10-02-2013 12:12 2086941

Так... ТС, напиши в обработчике нажатия на пункт меню команду Application.Terminate, и всё. Только так, а не всякими Form1.Close, можно корректно завершить работу всего приложения.

А если нужно просто закрывать текущую форму, надо приучаться писать Self.Close, ибо если в будущем планируешь стать программистом, тебе, возможно, придётся создавать большое количество идентичных форм с разными именами, поэтому ты никакими FormXXX.Close не отделаешься.

Цитата:

На англоязычных форумах/чатах если задашь вопрос, то тебе сразу прямо ответят, дадут линк, объяснят что к чему и пожелают удачи)
Ты бы лучше вместо чтения англоязычных форумов почитал бы Help к Delphi и хорошие книжки по ней. Да и английский бы заодно выучил, прежде чем дезинформировать нас таким высказыванием.

novashdima 10-02-2013 16:54 2087128

Цитата:

Цитата Любезный
ТС, напиши в обработчике нажатия на пункт меню команду Application.Terminate, и всё »

---------------------------
Error
---------------------------
'Application.Terminate' is not a valid identifier.
---------------------------
OK Help
---------------------------
Цитата:

Цитата Любезный
FormXXX.Close »

У меня в программах не бывает 100 форм, я обхожусь 5-10 и всегда использовал FormXXX.Close или FormXXX.Hide и все было нормально.
Цитата:

Цитата Любезный
Self.Close »

Что дает Self передавая его в качестве параметра Sender и в таком варианте?

Цитата:

Цитата Любезный
Ты бы лучше вместо чтения англоязычных форумов почитал бы Help к Delphi »

Все, что было написано в хелпе я приложил, и теперь расскажите, где там написано о том, что можно писать Application.Terminate или о чем еще надо.

Цитата:

Цитата Любезный
хорошие книжки »

Читал я две книжки, там и про ООП написано и про сами языки, но нигде не написано, что именно можно указывать значением свойства Event

Цитата:

Цитата Любезный
Да и английский бы заодно выучил, прежде чем дезинформировать нас таким высказыванием. »

У меня среднее знание английского, понять пойму, рассказать - посложнее будет, да и вообще какое ваше дело?
Никто не дезинформирует, это чистейшая правда, пройдитесь по форумам, к нас чтобы выяснить какую-то мелочь надо будет пол часа доказывать, что ты не верблюд.

Любезный 10-02-2013 17:10 2087142

Цитата:

Цитата novashdima
У меня в программах не бывает 100 форм, я обхожусь 5-10 и всегда использовал FormXXX.Close или FormXXX.Hide и все было нормально. »

Я же написал: если хочешь стать программистом.

Цитата:

Цитата novashdima
Что дает Self передавая его в качестве параметра Sender и в таком варианте? »

Sender тут ни при чём, его роль обычно служебная и состоит в том, чтобы передать в обработчик информацию о любом объекте для дальнейшей обработки в коде, которая производится отнюдь не всегда. А в таком варианте Self позволяет закрыть именно тот экземпляр TForm, из которого вызывается метод.

Цитата:

Цитата novashdima
Application.Terminate' is not a valid identifier. »

Точку с запятой в конце строки не поставил?
Если поставил - посмотри, что у тебя в списке модулей (uses). Наверняка там нет модуля Forms, в котором прописан идентификатор Application.

novashdima 10-02-2013 17:24 2087150

Цитата:

Цитата Любезный
Я же написал: если хочешь стать программистом. »

Ок, ТС лох и опозорился и не хочу я стать программистом, довольны?
Цитата:

Цитата Любезный
А в таком варианте Self позволяет закрыть именно тот экземпляр TForm, из которого вызывается метод. »

Тогда Self.Close ничем не отличается от Close, так?
Цитата:

Цитата Любезный
Точку с запятой в конце строки не поставил? »

ЧТО??? Точка с запятой??? Это где вы видели, чтобы имя обработчика указывалось с точкой с запятой? Для уверенности, попробовал поставить точку с запятой, получил выщеуказанное мною сообщение об ошибке.
Цитата:

Цитата Любезный
Если поставил - посмотри, что у тебя в списке модулей (uses). Наверняка там нет модуля Forms, в котором прописан идентификатор Application. »

На чем основаны ваши предположения? На том, что ТС нуб?
1. Если бы в uses не было Forms, то компилятор бы ругался даже на объявление моей формы.
2. Компилятор сам добавляет недостающие модули в uses.
3. Если бы модуля не было, то я получил бы Undeclared Identifier "Application.Terminate", а я получил "is not valid identifier" (для знатоков английского - не верный идентификатор)

Любезный 10-02-2013 17:25 2087151

Цитата:

Цитата novashdima
Все, что было написано в хелпе я приложил, и теперь расскажите, где там написано о том, что можно писать Application.Terminate или о чем еще надо. »

Плохо приложил.

Цитата:

Forms.TApplication.Terminate
From RAD Studio VCL Reference
Delphi Information
From Forms.pas
procedure Terminate;
Unit: Forms
Type: method
Visibility: public
Member Of: TApplication
Description
Ends application execution.
Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion. Terminate calls the Windows API PostQuitMessage function to perform an orderly shutdown of the application. Terminate is not immediate. Terminate is called automatically on a WM_QUIT message and when the main form closes.
Цитата:

Цитата novashdima
Ок, ТС лох и опозорился и не хочу я стать программистом, довольны? »

Зачем хамишь? Лучше бы прислушался и вник.

Цитата:

Цитата novashdima
Тогда Self.Close ничем не отличается от Close, так? »

Можно сказать и так. Но лучше приучаться писать именно Self.Close. Причин много. Есть, например, блоки with Object do begin...end, в которых могут быть объекты со своими методами Close.

Цитата:

Цитата novashdima
ЧТО??? Точка с запятой??? Это где вы видели, чтобы имя обработчика указывалось с точкой с запятой? Для уверенности, попробовал поставить точку с запятой, получил выщеуказанное мною сообщение об ошибке. »

Кто тебе сказал, что Application.Terminate - это имя обработчика? Это код, который нужно вставить в обработчик. Для чего, по твоему, в конце строки добавляют точку с запятой?

Цитата:

Цитата novashdima
1. Если бы в uses не было Forms, то компилятор бы ругался даже на объявление моей формы. »

Не факт.

Цитата:

Цитата novashdima
2. Компилятор сам добавляет недостающие модули в uses. »

Ничего подобного. Компилятор сам не добавляет ничего - это дело среды.

Цитата:

Цитата novashdima
3. Если бы модуля не было, то я получил бы Undeclared Identifier "Application.Terminate", а я получил "is not valid identifier" (для знатоков английского - не верный идентификатор) »

Ну так прочитай в хелпе описание этой ошибки и сделай выводы.

novashdima 10-02-2013 17:37 2087160

Цитата:

Цитата Любезный
Плохо приложил. »

Расскажите теперь о категориях оценки хорошо/плохо приложил, а что что-то я таких не знаю.
Цитата:

Цитата Любезный
Forms.TApplication.Terminate
From RAD Studio VCL Reference
Delphi Information
From Forms.pas
procedure Terminate;
Unit: Forms
Type: method
Visibility: public
Member Of: TApplication
Description
Ends application execution.
Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion. Terminate calls the Windows API PostQuitMessage function to perform an orderly shutdown of the application. Terminate is not immediate. Terminate is called automatically on a WM_QUIT message and when the main form closes. »

Я итак знал, что данная процедура находится в модуле Forms из Forms.pas и то, что она завершает приложение. Узнал, что данная процедура вызывает WinApi функцию PostQuitMessage. То, что WM_QUIT и закрытие главной формы вызывает Terminate я подозревал, как думаю терминейт вызывает и WM_EXIT|Halt. Но! как данная справка поможет мне в решении проблемы?

Цитата:

Цитата Любезный
Зачем хамишь? Лучше бы прислушался и вник. »

Потому что каждый вновь прибывший уверенно говорит, что я полный лох и не могу одну строку кода написать.
К тому же, к чему я должен по вашему прислушиваться? как оказалось вы даже не поняли, что я хочу сделать! К тому же я до сих пор обращаюсь в кам на Вы, что вы почему то не делаете, видимо воспитание такое.
П.С. Спасибо за все новое, что я узнал в этой теме, а это пока из 24 комментов то, какую WinApi функцию вызывает terminate и какой вызывается он сам.
Цитата:

Цитата Любезный
Кто тебе сказал, что Application.Terminate - это имя обработчика? Это код, который нужно вставить в обработчик. Для чего, по твоему, в конце строки добавляют точку с запятой? »

О БОГИ!!! Вы меня совсем не слушали? Я не спрашивал, как создать свой обработчик и написать туда одну из множества команд завершения приложения, я спрашивал, как можно вместо имени обработчика указать саму процедуру выхода из приложения (надеюсь теперь все поймут меня)
Цитата:

Цитата Любезный
Не факт. »

Ну расскажите мне тогда, как без использования определенного модуля компилятор вытащит исходник и будет знать, что за функцию я написал?
Цитата:

Цитата Любезный
Ничего подобного. Компилятор сам не добавляет ничего - это дело среды. »

Да, согласен, тут лоханулся, я хотел сказать, не компилятор добавляет, а среда добавляет автоматически (с версии 2009 вроде бы среда это делает)
Цитата:

Цитата Любезный
Ну так прочитай в хелпе описание этой ошибки и сделай выводы. »

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

<IDname> is not a valid identifierFrom RAD Studio XE2
Go Up to Error Messages Index




The identifier name is invalid. Ensure that the first character is a letter or an underscore (_). The characters that follow must be letters, digits, or underscores, and there cannot be any spaces in the identifier.

Retrieved from "http://docwiki.embarcadero.com/RADStudio/en/IDname_is_not_a_valid_identifier"


Любезный 10-02-2013 17:58 2087185

Хорошо, процитируем топик.

Цитата:

Цитата novashdima
Создавать же обработчик и в нем писать одну единственную команду Close бред... Как быть? »

Обоснуй, почему бред.

Цитата:

Цитата novashdima
я спрашивал, как можно вместо имени обработчика указать саму процедуру выхода из приложения (надеюсь теперь все поймут меня) »

Здесь проще ответить вопросом: а зачем?

Цитата:

Цитата novashdima
если прописать в обработчике нажатия Close или Form.Close, то компилятор ругается, будто нет соответствующей процедуры и если запустить прогу вывалится AV. »

Мне интересно, что значит "нет соответствующей процедуры". В норме такого быть не должно.
Ну раз у тебя ХЕ2, задам такой вопрос: приложение, которое ты делаешь - VCL или FireMonkey?

novashdima 10-02-2013 18:05 2087191

Цитата:

Цитата Любезный
Обоснуй, почему бред. »

Я написал в следующем посте, что создавать обработчик и писать в нем всего одну команду имхо бред.
Цитата:

Цитата Любезный
Здесь проще ответить вопросом: а зачем? »

Я немного не так себя процитировал, я спрашивал, можно ли вместо имени обработчика указать процедуру или нет, если да, то как, если нет, то почему.
Цитата:

Цитата Любезный
Мне интересно, что значит "нет соответствующей процедуры". В норме такого быть не должно.
Ну раз у тебя ХЕ2, задам такой вопрос: приложение, которое ты делаешь - VCL или FireMonkey? »

Что значит? Да очень просто, в имени обработчика пишите "qwertyui" и не объявляйте и не создавайте такую процедуру в коде, как результат объявление есть, а самой процедуры обработки нет.
VCL

Любезный 10-02-2013 18:22 2087200

Цитата:

Цитата novashdima
Что значит? Да очень просто, в имени обработчика пишите "qwertyui" и не объявляйте и не создавайте такую процедуру в коде, как результат объявление есть, а самой процедуры обработки нет. »

Даже комментировать не хочется.

Если бы вместо пункта меню была, например, кнопка, у неё есть свойство ModalResult, установив которое, можно задать закрытие формы по щелчку. Но у пунктов меню такого свойства нет. Так что... пиши обработчик с одной командой, хотя бы в ввиде, приведённом в верхнем коде поста:
http://forum.oszone.net/post-2086467-6.html

novashdima 10-02-2013 18:28 2087207

Цитата:

Цитата Любезный
Даже комментировать не хочется. »

Почему?
Цитата:

Цитата Любезный
Так что... пиши обработчик с одной командой »

Да так у меня давно уже написано, просто перебираю код, пытаюсь избавиться от говнокода.

Кстати вопрос не по теме, но не знаешь какой-то компонент или dll для работы с 7zip архивами?

Любезный 10-02-2013 18:42 2087220

Цитата:

Цитата novashdima
Почему? »

Мне просто стало понятно, что ты пытался написать Form.Close в инспекторе объектов. В нём можно писать только названия уже объявленных в описании класса формы обработчиков событий. Для чужих процедур и методов он не предназначен.

Цитата:

Цитата novashdima
Да так у меня давно уже написано, просто перебираю код, пытаюсь избавиться от говнокода. »

В этом никакого говнокода нет. Но многие начинающие злоупотребляют такими обработчиками, помещая их на одну форму по нескольку штук. Вот от чего нужно избавляться. Вместо этого достаточно присвоить один обработчик нескольким пунктам/кнопкам и.т.п. через тот же инспектор объектов

cookie_monster 10-02-2013 18:42 2087222

Цитата:

Цитата novashdima
Кстати вопрос не по теме, но не знаешь какой-то компонент или dll для работы с 7zip архивами? »

Честно, прочитывая эту тему поймал себя на мысли, что вы, не умеете пользоваться поиском.

http://www.7-zip.org/links.html
http://stackoverflow.com/questions/7...ip-from-delphi
http://www.angusj.com/delphi/

Без обид.

novashdima 10-02-2013 18:49 2087234

Цитата:

Цитата Любезный
В этом никакого говнокода нет. Но многие начинающие злоупотребляют такими обработчиками, помещая их на одну форму по нескольку штук. Вот от чего нужно избавляться. Вместо этого достаточно присвоить один обработчик нескольким пунктам/кнопкам и.т.п. через тот же инспектор объектов »

В смысле создать одну поцедуру обработки и назначить ее обрабатывать событие нескольких компонентов? если да, то я так и делаю, и тогда давно интересовавший вопрос, как сделать так... хм... в общем есть множество компонентов Met1 Met2.... и вот допустим одна процедура обоработки, как ее переделать, чтобы можно было использовать для нескольких компонентов?
Код:

procedure TMainForm.Met11Change(Sender: TObject);
begin
 try
  if (IsNan(Met11.Value) = False) and (Met11.Value <> 0)
      and (Met11.Value < Met11.MaxValue)
  then UpdateMetProduction
  else if (IsNan(Met11.Value) = True) or (Met11.Value = 0)
        then begin
              MetLabel11.Caption := '';
              MetLabel.Caption := '';
            end
        else Met11.Value := Met11.MaxValue - 1;
 except
    on E:EConvertError do
    Met11.Clear;
 end;
end;

Цитата:

Цитата cookie_monster
Честно, прочитывая эту тему поймал себя на мысли, что вы, не умеете пользоваться поиском.
http://www.7-zip.org/links.html
http://stackoverflow.com/questions/7...ip-from-delphi
http://www.angusj.com/delphi/
Без обид. »

Конечно не обижаюсь)
Я пробовал много вариантов, с сайта 7zip скачивал порт для делфи, но что-то было не так, то ли функционал то ли что. Находил так же другие компоненты, пытался их использовать, один был очень даже неплох, сжимал нормально, а вто с расжатием одна проблема была, при сжатии если нужный файл находился мне допустим в C:\Windows\"много всяких папок"\notepad.exe, то архив будет такой:
папка Windows -> много всяких папок -> нужный файл
Насчет JclCompression - я вроде бы в нем разобраться не смог( Со стандартной библиотекой System.Zip тоже какие-то траблы были

Любезный 10-02-2013 19:50 2087280

Цитата:

Цитата novashdima
В смысле создать одну поцедуру обработки и назначить ее обрабатывать событие нескольких компонентов? если да, то я так и делаю, и тогда давно интересовавший вопрос, как сделать так... хм... в общем есть множество компонентов Met1 Met2.... и вот допустим одна процедура обоработки, как ее переделать, чтобы можно было использовать для нескольких компонентов? »

Здесь важно, какого типа этот Met11. Пусть для примера это будет TMyType.
Возьмём тот же код и слегка переделаем, используя Sender.
Код:

procedure TMainForm.Met11Change(Sender: TObject);
begin
 if not (Sender is TMyType) then exit;
 try
  if (IsNan((Sender as TMyType).Value) = False)
  and ((Sender as TMyType).Value <> 0)
      and ((Sender as TMyType).Value < (Sender as TMyType).MaxValue))
  then UpdateMetProduction
  else if (IsNan((Sender as TMyType).Value) = True) or ((Sender as TMyType).Value = 0)
        then begin
              MetLabel11.Caption := '';
              MetLabel.Caption := '';
            end
        else (Sender as TMyType).Value := (Sender as TMyType).MaxValue- 1;
 except
    on E:EConvertError do
    (Sender as TMyType).Clear;
 end;
end;

Переделка слегка грубовата - надо проверить на предмет скобок. Из движка форума это неудобно.

novashdima 10-02-2013 20:04 2087291

Цитата:

Цитата Любезный
Переделка слегка грубовата - надо проверить на предмет скобок. Из движка форума это неудобно. »

Я примерно так и думал, но вот еще в чем дело, эти самые Met1,Met2... это TSpinEdit, при изменении MetX изменяется также MetLabelX и так для каждого компонента, поэтому надо еще как-то привязаться к номеру этого самого MetX
Надеюсь понятно написал.

Любезный 10-02-2013 20:12 2087299

Начиная с D2010, можно решить и этот вопрос. Но тут уже посложнее. Привязка будет не к номеру, а к имени.

У любого компонента есть свойство Name. Все компоненты формы можно обойти в цикле и найти нужные, с нужными именами. Пример:
Код:

var lab: TLabel;
with Self
 do for I:=0 to ComponentsCount-1
  do if Components [i] is Label
  then if (Components [i] as TLabel).Name='Label1'
    then begin
    lab:=Components [i] as TLabel;
    break;
  exit;
end;

Находишь нужный Label, присваиваешь ему Caption - и задача решена.

novashdima 10-02-2013 21:20 2087363

Цитата:

Цитата Любезный
Находишь нужный Label, присваиваешь ему Caption - и задача решена. »

Ну... получилось что-то такое:
Код:

procedure TMainForm.MetChange(Sender: TObject);
var lab: TsLabel;
    namestr: string;
begin
  if not (Sender is TsSpinEdit) then exit;
 try
  if (IsNan((Sender as TsSpinEdit).Value) = False)
  and ((Sender as TsSpinEdit).Value <> 0)
      and (((Sender as TsSpinEdit).Value) < ((Sender as TsSpinEdit).MaxValue))
  then UpdateMetProduction
  else if (IsNan((Sender as TsSpinEdit).Value) = True) or ((Sender as TsSpinEdit).Value = 0)
        then begin
              namestr := (Sender as TsSpinEdit).Name;
              Insert('Label', namestr, Length(namestr)-1);
              with Self
                do for I:=0 to MainForm.ComponentCount - 1
                  do if (Components[i] is TsLabel)
                  then if ((Components [i] as TsLabel).Name = namestr)
                      then begin
                              lab:=Components [i] as TsLabel;
                              break;
                              exit;
                      end;
                      lab.Caption := '';
                      MetLabel.Caption := '';
            end
        else (Sender as TsSpinEdit).Value := (Sender as TsSpinEdit).MaxValue- 1;
 except
    on E:EConvertError do
    (Sender as TsSpinEdit).Clear;
 end;
end;

Думаю стоит выделить поиск компонента в отдельную функцию, а то понадобится она еще не раз, так как у меня около 2к строк кода просто повторение почти одного и того же кода(

Любезный 10-02-2013 21:43 2087386

Ну это уж решай сам - всё зависит от конкретной задачи.

И, кстати, чтобы код проще читался, можно объявить отдельную переменную типа TsSpinEdit, присвоить ей значение Sender as TsSpinEdit и указывать в коде её, а не столь длинную фразу.

novashdima 10-02-2013 22:25 2087420

Нашел вот еще один способ:
Код:

S:='CheckBox'+IntToStr(I+1);
 with (FindComponent(S) as TCheckBox) do Checked:=True


Любезный 10-02-2013 22:41 2087442

Согласен, тоже вариант.

novashdima 10-02-2013 23:02 2087466

Цитата:

Цитата Любезный
Согласен, тоже вариант. »

Мне кажется он получше, так как зачем перебирать все компоненты, если можно использовать уже готовую функцию для этого.

Любезный 11-02-2013 00:58 2087542

Цитата:

Цитата novashdima
Мне кажется он получше, так как зачем перебирать все компоненты, если можно использовать уже готовую функцию для этого. »

Он лучше в том случае, когда надо найти один компонент. Если же нужно найти сразу группу компонентов, лучше сразу попробовать сделать это в одном цикле и тут же присвоить значения ссылок на эти компоненты соответствующим переменным.

novashdima 11-02-2013 01:16 2087554

Цитата:

Цитата Любезный
Он лучше в том случае, когда надо найти один компонент. Если же нужно найти сразу группу компонентов, лучше сразу попробовать сделать это в одном цикле и тут же присвоить значения ссылок на эти компоненты соответствующим переменным. »

А что мешает сделать типа такого?
Код:

for i := 1 to Count do
begin
S:='Name'+IntToStr(I+1);
 with FindComponent(S) do Caption := 'BlaBlaBla...';
end


novashdima 11-02-2013 05:45 2087635

Ну что же, весь код я пересмотрел и переделал, в результате главный исходник уменьшился с 2900 строк кода до 1700, что не может не радовать. Также введя такую обработку я избавился от головняка в плане сохранения настроек в файл, за что огромное спасибо. Однако остается открытым два вопроса, каким образом можно объединить такие процедуры:
Код:

procedure TMainForm.EnergyInfo(Sender: TObject);
begin
if EnergyLevel.Value <> 0
then begin
      Clipboard.Clear;
      Clipboard.SetTextBuf(PChar(EnergyLabel.Caption + ' ' + EnergyLevel.Text +
      ' уровень. Время исследования: ' + EnergyTime.Caption + '. Стоимость: ' +
      EnergyResource.Caption + '.'));
    end;
end;

procedure TMainForm.LaserInfo(Sender: TObject);
begin
  if LaserLevel.Value <> 0
  then begin
        Clipboard.Clear;
        Clipboard.SetTextBuf(PChar(LaserLabel.Caption + ' ' + LaserLevel.Text +
        ' уровень. Время исследования: ' + LaserTime.Caption + '. Стоимость: ' +
        LaserResource.Caption + '.'));
      end;
end;

И так далее. Весь вопрос в том, как бы перебрать все эти компоненты, учитывая, что название компонентов разной длины, единственное, что везде одинаково это окончание названия компонента ~Label/~Level/~Time. Используя всякие AnsiIndexStr/AnsiPos/Copy/Delete/Insert и т.д. из модуля StrUtils я намучаюсь так, что брошу это дело...

Iska 11-02-2013 07:26 2087644

novashdima, желательно под каждый новый вопрос, не имеющий непосредственного отношения к названию этой темы, заводить новую.

Любезный 11-02-2013 11:19 2087728

Цитата:

Цитата novashdima
А что мешает сделать типа такого? »

FindComponent - это такой же цикл. По сути дела, это выполнение одной и той же работы по нескольку раз. В случае очень многократного применения могут быть проблемы с производительностью.

novashdima 11-02-2013 15:20 2087917

Цитата:

Цитата Iska
novashdima, желательно под каждый новый вопрос, не имеющий непосредственного отношения к названию этой темы, заводить новую. »

Понимаю, но имхо лучше все вопросы обсудить и закрыть тему, а не создавать кучу тем(в данном случае мне пришлось бы создавать темы для: сжатия 7zip, поиск компонента, загрузка из ини, сохранение в файл, суть этой темы), вышло бы тем 10.

Цитата:

Цитата Любезный
FindComponent - это такой же цикл. По сути дела, это выполнение одной и той же работы по нескольку раз. В случае очень многократного применения могут быть проблемы с производительностью. »

Понятно, тогда подскажите, как найти оптимально 3 раза по 3 компонента, не перебирая все компоненты 9 раз. Как проверить, все ли компоненты найдены и как узнать, что я все нужные компоненты нашел и выйти из цикла. Ничего простого не приходит в голову, только флаг для проверки найденных всех компонентов, при нахождении компонента сразу же присваивать его переменной...
И подскажите по поводу остальных вопросов.

upd
Создал темы под каждый вопрос.

Iska 11-02-2013 16:40 2087985

Цитата:

Цитата novashdima
Понимаю, но имхо лучше все вопросы обсудить и закрыть тему, а не создавать кучу тем »

Имхо у нас у каждого своё, но есть Общие правила конференции OSZone.net, п.3.12. Лучше всего руководствоваться правилом — «Один вопрос — одна тема». И Вам легче, и отвечающим удобнее.

Любезный 11-02-2013 17:49 2088036

Цитата:

Цитата novashdima
Понятно, тогда подскажите, как найти оптимально 3 раза по 3 компонента, не перебирая все компоненты 9 раз. Как проверить, все ли компоненты найдены и как узнать, что я все нужные компоненты нашел и выйти из цикла. Ничего простого не приходит в голову, только флаг для проверки найденных всех компонентов, при нахождении компонента сразу же присваивать его переменной... »

На первый взгляд - три цикла. Конкретно каким образом - зависит от задачи.


Время: 02:27.

Время: 02:27.
© OSzone.net 2001-