Delphi как найти компонент по имени

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

1) Берем ставим на форму 10 CheckBox

2) объявляем массив

Code:

var arr:array[1..10] of TCheckBox

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

Обратится к компоненту по имени можно например так, если стоит 10 CheckBox – от CheckBox1 до CheckBox10 то

Code:

For i:=1 to 10 do

(FindComponent(Format(‘CheckBox%d’,[i])) as TCheckBox).checked:=true;

Автор: Vit

Взято с Vingrad.ru

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

Code:

procedure TForm1.UpDown1Click(Sender: TObject; Button: TUDBtnType);

{©Drkb v.3(2007): www.drkb.ru}

var

I: Integer;

ChildControl: TControl;

begin

for I:= 0 to GroupBox1.ControlCount –1 do

begin

   ChildControl := GroupBox1.Controls[I];

   ChildControl.Top := ChildControl.Top + 15

end;

end;

Проверить тип контрола надо оператором is:

if edit1 is TEdit then….

Затем доступ ко всем свойствам путем приведения класса:

(edit1 as TEdit).text:=;

Автор ответа: Kiber_rat

Взято с Vingrad.ru

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

Code:

procedure TForm1.ActiveControlChange(Sender: TObject);

{©Drkb v.3(2007): www.drkb.ru}

begin

Caption := TScreen(Sender).ActiveForm.ActiveControl.Name;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

Screen.OnActiveControlChange := ActiveControlChange;

end;

Автор: p0s0l

Взято с Vingrad.ru

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

Например, надо найти все TCheckBox на форме и установить их все в положение checked:

Code:

var i: integer;

begin

for i := 0 to ComponentCount – 1 do

   if Components[i] is TCheckBox then

     (Components[i] as TCheckBox).Checked := true;

end;

Автор: Vit

Взято с Vingrad.ru

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

Автор: RoboSol.

 Часто возникают вопросы о работе с массивом компонентов. вот пример того как вывести список имен всех компонентов в приложении.

Code:

procedure TForm1.Button1Click(Sender : TObject);

{©Drkb v.3(2007): www.drkb.ru}

var i : integer;

begin

ListBox1.Items.Clear;

for i:=0 to ComponentCount-1 do ListBox1.Items.Add(Components[i].Name);

end;

Подробности
Родительская категория: VCL
Категория: Неявное обращение к компонентам, манипуляции в run-time

I am adding some functionality to form not created by me. It has loads and loads of buttons and I would like to test if everything works by clicking on the button which executes the code I added. I know the name of this button, but I don’t know it’s position on the form.

For now I scroll through all components of the form looking for this button. If I miss it in the first lookup, I have to start over. It’s tiresome and takes a lot of time.
Is there easy way? Something like “Find component” menu item, which would bring me directly to that button (or label, or anything really).

asked Oct 5, 2017 at 14:09

andowero's user avatar

2

There is no built-in, comfortable way of locating components on a form (even in Delphi Tokyo). But you can search and select component in the Object Inspector Instance List combo box:

enter image description here

Or perform inremental search in the Structure View‘s tree:

enter image description here

Or install some 3rd party IDE tool. For example CnWizards toolset has the Locate Components in Designer tool (which is what you’re looking for, I guess):

enter image description here

answered Oct 5, 2017 at 18:17

Victoria's user avatar

VictoriaVictoria

7,8022 gold badges21 silver badges44 bronze badges

1

While no help at design-time, if what you want is testing your code you likely do that at run-time:

TComponent has the function FindComponent that returns a TComponent owned by the calling component with matching Name.

As you know the name, to write test code you could use it like this:

var
  AButton: TButton;
begin
  AButton := Form.FindComponent(Button_Name) as TButton;
  AButton.Click;
end;

answered Oct 5, 2017 at 14:16

nil's user avatar

nilnil

1,3101 gold badge9 silver badges21 bronze badges

Часто задаваемые общие вопросы по Borland Delphi

Часть 2

Базы данных – компоненты и VCL.

  1. Какие визуальные

    компоненты для работы с данными входят в  Delphi?

  2. Использование псевдонимов

    в запросе SQL.

  3. Ошибка в SQL запросе.

  4. Проблемы при работе

    с MS Access через TQuery.

  5. Как создать

    таблицу при помощи SQL (или почему не работает TQuery.Open)?

  6. Возврат значения

    select max() и подобных SQL-выражений.

  7. Автоматический подсчет

    сумм при помощи TQuery.

  8. Использование

    кавычек в параметризированном запросе.

  9. Как создать отдельный компонент

    TTable?

  10. Как узнать,

    какая ячейка при просмотре TDBGrid текущая?

  11. Как выделить цветом

    текущую строку в TDBGrid?

  12. Как изменить цвет ячейки в TDBGrid?

  13. Как узнать,

    что пользователь перешел на другую запись, например, в TDBGrid?

  14. Как устанавливать

    собственный цвет или шрифт для столбца TDBGrid?

  15. Почему указатель

    ползунка в TDBGrid не показывает текущее положение в таблице?

  16. Как установить

    фокус на определенное поле в TDBGrid?

  17. Как создать обработчик

    события OnClick для TDBGrid?

  18. Как создать маску для TDBEdit?

  19. Хотелось бы иметь для

    OLE объектов, сохраненных в базе данных, компонент вроде TDBImage.

  20. Что нужно сделать,

    чтобы при открытии запароленной таблицы не появлялся диалог запроса пароля?

  21. Как определить

    реальный размер поля типа BLOB, которое сохранено в таблице?

  22. Как осуществить

    поиск по неиндексированному полю в таблице?

  23. Как узнать, что

    изменилась текущая запись?

  24. Как считать даты

    для вычисляемых полей?

Компоненты и VCL

  1. Почему возникает ошибка

    компиляции при обращении к объекту Sender в обработчике события?

  2. Проблемы

    с полями класса типа TObject, TTable и т.д.

  3. Как закрыть модальную

    форму (ShowModal) ? И вообще, каков лучший способ закрыть любую форму?

  4. Перемещение

    существующих компонентов на TPanel, TGroup и т.п.

  5. Как можно

    добавить новый компонент на страницу TTabbedNoteBook во время выполнения

    программы? Как нужно определить свойство Parent для этого компонента?

  6. Как включить символ &

    в надпись (Caption)?

  7. Как сделать окно (TForm)

    без заголовка (Caption)?

  8. Почему некоторые

    компоненты типа TPanel и TEdit не имеют свойства Canvas?

  9. Почему при уничтожении

    компонента в методе OnClick происходит ошибка?

  10. Есть ли у TDBGrid

    события OnMouseDown, OnMouseUp и OnMouseMove?

  11. Поиск компонента в форме по

    имени.

  12. Как получить горизонтальный

    ScrollBar на ListBox?

  13. Как определить текущую

    колонку и строку каретки в компоненте TMemo?

  14. Постранична

    прокрутка TMemo, реализация Undo и определение строки курсора.

  15. Как поместить BLOB Memo

    в компонент TMemo?

  16. Как показать содержимое

    Memo поля в TDBGrid?

  17. Не возникает событие TSpeedButton.OnDblClick.

  18. Как разделить

    обработку OnClick и OnDblClick? Ведь OnClick будет вызываться всегда, и

    перед DblClick.

  19. Как определить

    из обработчика события OnClick в Popup.MenuItem, для какого объекта это

    произошло?

  20. Как использовать

    case, чтобы определить, какой объект вызвал процедуру?

  21. Как обрабатывать события

    от множества однотипных компонентов.

  22. Использование TPanel в качестве

    “индикатора”.

  23. Включение и выключение подсказок (Hints) для всех элементов на форме.

  24. Как в меню поместить bitmap?

  25. Каким образом можно поместить двумерный массив в TImage?

  26. Как из программы ‘открыть’ TComboBox?

  27. Как заменить надпись ‘Read only’ в компонентах TSaveDialog и TOpenDialog?

  28. Проблема в использовании компонента TCustomGrid.

  29. Как установить формат для поля таблицы?

  30. Можно ли использовать клавишу ENTER при вводе данных для перехода от поля

    к полю?

Базы данных – компоненты и VCL.

1. Какие

визуальные компоненты для работы с данными входят в  Delphi?

Различные версии Delphi содержат следующие наборы компонентов:

Компоненты  Краткое описание  Версии Delphi 
TDBGrid  Представление данных в виде таблицы (очень сложный и наиболее популярный

компонент) 

1.02.03.0 
TDBEdit  Редактирования одного поля  1.02.03.0 
TDBNavigator  Как видно из названия, компонент позволяет перемещаться по таблице  1.02.03.0 
TDBLabel  Статическое отображение содержимого поля  1.02.03.0 
TDBMemo  Редактирования текста в поле типа BLOB  1.02.03.0 
TDBImage  Отображение картинок из BLOB-а  1.02.03.0 
TDBRadioGroup, TDBCheckBox  Дополнительные средства отображения данных  1.02.03.0 
TDBComboBox, TDBListBox  Упрощают ввод данных, предлагая несколько заранее определенных вариантов  1.02.03.0 
TDBLookupListBox, TDBLookupComboBox  То же самое, но возможные варианты выбираются из другой таблички  1.02.03.0 
TDBCtrlGrid  Вариант представления записей с произвольным расположением полей  2.03.0 
TDBChart  Компонент для построение графиков и диаграмм на основании данных, хранящихся

в таблице 

3.0 
TDecisionGrid, TDecisionChart  Компоненты для поддержки принятия решений  3.0 

2.

Использование псевдонимов в запросе SQL.

Q:Я делаю запрос по

двум таблицам разных форматов, находящихся по разным псевдонимам.

    SELECT DB1.Column1, DB2.Column2 FROM :Alias1:DB1, :Alias2:DB2

но в результате получаю ошибку ‘неизвестный тип поля “Alias1:DB1″‘

A:На самом деле вы получаете

ошибку Unknown Keyword, следовательно всего-лишь нужно заключить псевдоним

и имя таблицы в двойные кавычки.

    SELECT D1.Column1, D2.Column2 FROM “:Alias1:DB1” D1, “:Alias2:DB2”

    D2

Вообще экспериментировать с SQL-запросами проще следующим образом – создайте

запрос QBE, настройте его так, как вам нужно, а затем оттранслируйте его

в SQL. В результате вы получите правильный текст нужного вам SQL-запроса.

Владельцы Delphi Client/Server могут использовать также и Visual Query

Builder. Однако, не все QBE-запросы могут быть оттранслированы в SQL.

3. Ошибка в SQL запросе.

Q:У меня есть TQuery

и TDataSource. В свойстве SQL для TQuery я пишу

    SELECT * FROM dbo.AnyTable

база данных на MS SQL Server. Когда я устанавливаю Active в True,

то получаю ошибку: ‘Token not found. Token :dbo. line number:1’.

Что не так?

A:Если свойство RequestLive=True,

то имя таблицы нужно брать в кавычки:

    SELECT * FROM “dbo.table”

Если свойство RequestLive=False, кавычек не требуется:

    SELECT * FROM dbo.table

4. Проблемы

при работе с MS Access через TQuery.

Q:Я безуспешно пытался

использовать данные из Microsoft Access иначе, нежели просто с помощью

TTable.  Используя TQuery я могу только читать результат,

но не могу редактировать. После “login screen” возникает сообщение типа

‘Passthrough SQL connection must be shared’.

A:Измените в настройке

псевдонима (alias) пункт ‘SQLPASSTHRU MODE’ на ‘SHARED AUTOCOMMIT’.

5.

Как создать таблицу при помощи SQL (или почему не работает TQuery.Open)?

TQuery.Open возвращает результат в виде курсора, в связи с этим

он работает только для тех выражений, которые возвращают курсор. CREATE

TABLE возвращает только результат операции – поэтому для выполнения этого

выражения необходимо использовать TQuery.ExecSQL. Но и это может

не сработать, если конкретный драйвер БД не поддерживает операцию создания

таблиц – для получения характеристик драйвера используйте функции BDE (DbiOpenDriverList,

DbiGetDriverDesc). 

6. Возврат

значения select max() и подобных SQL-выражений.

Я хочу выполнить SQL-выражение и получить результат в свою переменную,

что-то типа

    SELECT MAV(FieldA) FROM TableB INTO :VariableC;

Вам не нужно использовать оператор INTO для программного доступа к результату

– его можно получить используя свойства Fields или FieldByName

соответствующего компонента TQuery.

    TQuery1.Add(‘ SELECT MAX(FiledA) FROM TableB ‘);

    TQuery.Open;

    VariableC := TQuery1.Fields[0];

Или, если результат нужно визуально отобразить, достаточно подключить к

используемому TQuery компоненты TDataSource и TDBText.

7. Автоматический

подсчет сумм при помощи TQuery.

Q:Меня интересует

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

A:Есть очень простой

способ – предположим, что у вас есть на форме Query1, DataSource1,

DBGrid1. Добавьте на эту-же форму компоненты Query2, DataSource2,

DBText1. Установите property Query2.DataSource=DataSource1.

В Query2.SQL напишите

    SELECT SUM(FieldName) FROM TableName

где TableName – имя той-же таблицы что и у Query1, а FieldName

– имя столбца по которому производится подсуммирование. Далее свяжите между

собой Query2, DataSource2 и DBText1.

При изменении Query1 (если конечно Query1.RequestLive=True)

Query2 будет автоматически перевыполняться. Это решение хоть и простое,

но неэкономичное – особенно при большом количестве записей в исходной таблице.

Более того, запрос Query2 должен иметь WHERE идентичный Query1.

Для подсчета сумм правильнее использовать событие TQuery.OnCalcFields.

Хорошим примером является X:DELPHIDEMOSDBMASTAPPMASTAPP.DPR. 

8.

Использование кавычек в параметризированном запросе.

Q:Мой запрос получает

параметр. Проблема в том, что строка параметра содержит ” (двойную кавычку),

которая приводит к Runtime Error.

A:Вам необходимо использовать

динамический SQL-запрос, иначе при указании например

    WHERE TABLE.FIELD = ‘let”ter’

вы получите ошибку.

9. Как создать

отдельный компонент TTable?

Легко и просто – точно также как и обычный компонент. При этом в качестве

параметра конструктору можно передавать значение nil.

 

var 

  MyTable: TTable; 

begin 

  MyTable := TTable.Create(nil); 

  try 

    MyTable.DatabaseName := ‘MyDB’

    MyTable.TableName := ‘MyTable.db’

    Mytable.IndexName := ‘MyIndex’

    MyTable.Open; 

    { делать то, что надо } 

  finally 

    MyTable.Free; 

  end

end

 

     

10.

Как узнать, какая ячейка при просмотре TDBGrid текущая?

Здесь процедура для сохранения текущего номера строки и колонки. Следующий

код в методе MyDBGridDrawDataCell обновляет переменные Col

и Row (которые не должны быть локальными для этого метода) каждый

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

что Col и Row указывают на текущую колонку и строку соответственно.

 

var 

  Col, Row: Integer; 

procedure TForm1.MyDBGridDrawDataCell(Sender: TObject; const

Rect: TRect; 

  Field: TField; State: TGridDrawState); 

var 

  RowHeight: Integer; 

begin 

  if gdFocused in State then 

  begin 

    RowHeight := Rect.Bottom – Rect.Top; 

    Row := (Rect.Top div RowHeight) – 1; 

    Col := Field.Index; 

  end

end

 

     

11. Как выделить

цветом текущую строку в TDBGrid?

Для TDBGrid в свойстве Options установите dgRowSelect

в True.

12. Как изменить цвет

ячейки в TDBGrid?

Введите следующий код в обработчике события OnDrawDataCell:

 

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const

Rect: TRect; 

  Field: TField; State: TGridDrawState); 

begin 

  if gdFocused in State then 

  with (Sender as TDBGrid).Canvas do 

  begin 

    Brush.Color := clRed; 

    FillRect(Rect); 

    TextOut(Rect.Left, Rect.Top, Field.AsString); 

  end

end

 

     

Установите свойство DefaultDrawing в True. Здесь перерисовывается

только выделенная ячейка. Если установить DefaultDrawing в False,

то вы должны самостоятельно перерисовать все ячейки аналогично примеру.

13.

Как узнать, что пользователь перешел на другую запись, например, в TDBGrid?

Переход на новую запись – это событие, которое относится не к визуальному

компоненту, а к источнику данных. Соответствующее событие называется OnDataChange

и имеется у компонента TDataSource.

14.

Как устанавливать собственный цвет или шрифт для столбца TDBGrid?

1.0Выключите property

DefaultDrawing, и обрабатывайте событие OnDrawDataCell:

 

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const

Rect: TRect; 

  Field: TField; State: TGridDrawState); 

begin 

  if Field.FieldName = ‘Name’ then DBGrid1.Canvas.Font.Style

:= [fsBold]; 

  DBGrid1.DefaultDrawDataCell(Rect, Field, State); 

end

 

     

Это приведет к тому, что содержимое столбца ‘Name’ будет показываться

жирным шрифтом.

2.0В Delphi 2.0 вы

можете использовать редактор столбцов для той же самой цели.

15. Почему

указатель ползунка в TDBGrid не показывает текущее положение в таблице?

Дело в том, что TDBGrid предполагает многопользовательский доступ

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

или удалять записи, в результате информация о количестве записей на текущий

момент становится неопределенной.

Конечно, в однопользовательском варианте количество записей всегда известно,

но поскольку TDBGrid работает через промежуточный источник данных

DataSource, ему неизвестен конкретный способ доступа к данным –

навигационный или SQL. Например, для SQL существует только один способ

узнать количество записей – выполнить специальный запрос с их подсчетом,

а на это может потребоваться значительное время.

По всем этим причинам TDBGrid является универсальным средством

для просмотра таблиц, которое работает во всех случаях и с любыми источниками

данных.

16.

Как установить фокус на определенное поле в TDBGrid?

Используйте код:

    DBGrid1.SelectedField := Table1SomeField;

    DBGrid1.SetFocus;

17.

Как создать обработчик события OnClick для TDBGrid?

Как и всякий TControl (иерархия наследования TControl-> TWinControl->

TCustomControl-> TCustomGrid-> TCustomDBGrid-> TDBGrid) у TDBGrid

есть событие OnClick, но оно protected. Так что можно либо

создать новый класс, производный от TDBGrid, в котором объявить

это свойство как published, либо использовать другой вариант. Например,

вы можете использовать событие OnColEnter.

18.

Как создать маску для TDBEdit?

Маска относится к полю в таблице (компонент TField) а не к самому

TDBEdit. Дважды щелкните мышкой на TTable и в FieldEditor’е

добавьте все нужные вам поля. Когда поле выбрано в списке, его свойства

показаны в Object Inspector, включая маску ввода. Связывание TDBEdit

и любых других компонентов с этим TTable будет вызывать наложение

маски на соответствующее поле.

19. Хотелось

бы иметь для OLE объектов, сохраненных в базе данных, компонент вроде TDBImage.

В стандартном наборе такого компонента действительно нет. Возможно,

кто-нибудь скоро напишет что-нибудь в этом роде. В принципе, можно обойтись

и без данного компонента. Например, есть табличка .db с BLOB полем для

OLE объекта. При движении по записям можно OLE сохранять в базе, уничтожать,

создавать новый, считывать из базы.

Чтение/запись OLE:

  • создать поток, связанный с BLOB полем

  • для OLE контейнера выполнить чтение/запись с потоком (SaveToStream

    и LoadFromStream)

Естественно, OLE объект должен быть Embedded.

20.

Что нужно сделать, чтобы при открытии запароленной таблицы не появлялся

диалог запроса пароля?

Просто дайте этот пароль объекту Session перед открытием таблицы:

    Session.AddPassword(‘PASSWORD’);

После закрытия таблицы, пароль можно удалить RemovePassword(‘PASSWORD’),

можно удалить все пароли: RemoveAllPasswords.

2ю0Если ваш компонент

доступа к данным (TTable или TQuery) связан с сессий, отличной

от той, которая выставляется по умолчанию, то добавлять пароль нужно именно

у этого компонента TSession.

21.

Как определить реальный размер поля типа BLOB, которое сохранено в таблице?

Ниже приведена функция GetBlobSize, которая возвращает размер

данного BLOB или MEMO поля.

 

function GetBlobSize(Field: TBlobField): Longint; 

begin 

  with TBlobStream.Create(Field, bmRead) do 

  try 

    Result := Seek(0, 2); 

  finally 

    Free; 

  end

end

procedure TForm1.Button1Click(Sender: TObject); 

begin 

{ This sets the Edit1 edit box to display the size of } 

{ a memo field named Notes.                          

} 

  Edit1.Text := IntToStr(GetBlobSize(Notes)); 

end

 

     

22.

Как осуществить поиск по неиндексированному полю в таблице?

Вы можете добавить следующую функцию в ваш модуль и вызвать, например:

    Locate(Table1, Table1LName, ‘Beman’);

Table1 – компонент TTable, Table1LNameTField,

который вы добавили с помощью Fields Editor и ‘Beman’ – имя, которое

вы хотите найти.

23.

Как узнать, что изменилась текущая запись?

Событие TDataSource.OnDataChange когда State=dsBrowse.

24. Как

считать даты для вычисляемых полей?

При вычислении дат важно удостовериться в том, что все используемые

значения подходят по типу. В документации не совсем явно отражен тот факт,

что на самом деле тип TDataTime эквивалентен типу Double,

который можно использовать далее.

В примере, D1 и D2 (поля в Table1) могут быть типа

или Date, или TDateTime, а D3 – поле типа Integer.

 

procedure TForm1.Table1CalcFields(DataSet: TDataset); 

var 

  T1, T2: TDateTime; 

begin 

  Table1D1.AsDateTime := Date+2; 

{ or Table1D1.Value := Date+2; } 

  Table1D2.AsDateTime := Date-2; 

  T1 := Table1D1.AsDateTime; 

  T2 := Table1D2.AsDateTime; 

  Table1D3.AsInteger := Trunc(Double(T1) – Double(T2)); 

end

Компоненты и VCL

1.

Почему возникает ошибка компиляции при обращении к объекту Sender в обработчике

события?

Q:Я в обработчике

события OnChange для компонента TEdit пытаюсь получить содержимое

его текстового буфера. Однако, следующая конструкция вызывает ошибку компиляции

‘неизвестный идентификатор’:

    Caption := Sender.Text;

A:Если вы рассматривали

декларацию, объект Sender имеет тип TObject, который является

классом, который наследуется почти всеми остальными объектами. Вы, вероятно,

пробуете обращаться к свойству, которое не определено в TObject,

вроде Text или Caption. По этой причине, выражение Sender.Text

вызовет ошибку, но если (для примера) вы знаете, что Sender имеет тип TEdit,

тогда вы можете использовать выражение:

    Caption := (Sender as TEdit).Text;

Если вы не уверены, что объект Sender будет всегда иметь данный

тип, то рекомендуется предварительно проверить это:

    if Sender is TEdit then

2.

Проблемы с полями класса типа TObject, TTable и т.д.

Q:Я объявляю поле

класса как TTable, но при обращении к нему происходит ошибка.

A:Дело в том, что в

Delphi все экземпляры объектов, объявленых как class, являются динамическими.

Соответственно поле MyTable, объявленное как

 

type 

   TMyClass = class(TObject) 

   public 

     MyTable: TTable; 

     constructor Create; 

     destructor Destroy; override

   end

 

     

является указателем на класс TTable, и должно быть инициализировано

в конструкторе вашего объекта и соответственно разрушено в деструкторе

следующим образом:

 

constructor TMyClass.Create; 

begin 

  MyTable := TTable.Create(nil); 

  MyTable.DatabaseName := ‘DBDEMOS’

end

destructor TMyClass.Destroy; 

begin 

  MyTable.Free; 

end

Подробнее см. Changes in Object Pascal Language в документации или on-line

help.

3.

Как закрыть модальную форму (ShowModal) ? И вообще, каков лучший способ

закрыть любую форму?

Вообще говоря, нужно вызывать метод Close для формы. Close

вызывает событие OnClose (обработчик которого может решить, что

форму нельзя закрывать, например, если имеются несохраненные данные). Close

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

в обработчик события вызов метода Release.

Если вы хотите уничтожить форму без вызова события OnClose, используйте

метод Release. Этот метод работает подобно Free, но позволяет

всем обработчикам событий данной формы закончить работу перед тем, как

память будет освобождена.

Модальные формы “прекращают свой модальный статус”, когда вы устанавливаете

свойство ModalResult формы в любое значение, отличное от нуля. Если

вы поместите кнопку на модальную форму и установите свойство ModalResult

для кнопки в некоторое значение, то, когда пользователь нажмет на эту кнопку,

форма закроется с результатом, который вы определили. Этот результат можно

узнать вызывая ShowModal как функцию. То есть:

    Result := Form.ShowModal;

4.

Перемещение существующих компонентов на TPanel, TGroup и т.п.

Q:Я поместил кнопку

(или что-то другое) на форму, затем поместил панель, и решил переместить

кнопку на панель, но ничего не получилось.

A:Действительно, чтобы

поместить кнопку на панель, необходимо на форму сначала поместить панель,

выбрать ее, а затем уже помещать кнопку.

Но и в вашей ситуации есть решение. Скопируйте (Copy) или вырежьте (Cut)

нужный компонент, выберите панель, и сделайте вставку (Paste). Рекомендуется

предварительно “подогнать” копируемый компонент в левый верхний угол формы,

иначе компонент на панели может выпасть из “пределов видимости” панели

(или любого другого группового компонента).

Если компонент все-таки “выпал” из пределов видимости – найдите этот

компонент в Инспекторе Объектов, и установите нужные значения его свойств

Left и Top.

Используя группы компонент можно огранизовать форму-шаблон, на которой

можно складывать (например в Notebook) компоненты с предварительно заданными

свойствами, отличными от стандартных. Это решение проще чем добавлять такие

компоненты в палитру компонент – не увеличивается размер библиотеки компонентов

DCL (Delphi 3.0 не считается), не загромождается палитра компонент.

Учтите, что при таком копировании компонент их имена меняются на новые

(Button1, Button2 и т.д.).

5.

Как можно добавить новый компонент на страницу TTabbedNoteBook во время

выполнения программы? Как нужно определить свойство Parent для этого компонента?

Для того, чтобы добавить компонент на страницу TabbedNotebook,

свойству Parent нового компонента нужно присвоить указатель на требуемую

страницу. Способ для доступа к любой странице TTabbedNotebook во

время выполнения – массив свойств Objects у свойства Pages

компонента TTabbedNotebook. Другими словами, страницы сохранены

в виде объектов в свойстве Pages (тип TStringList). Пример

демонстрирует создание кнопки TButton на второй странице TabbedNotebook1:

 

var 

  NewButton: TButton; 

begin 

  NewButton := TButton.Create(Self); 

  NewButton.Parent := TWinControl(TabbedNotebook1.Pages.Objects[0]); 

То же самое справедливо и для компонента TNotebook.

6. Как включить

символ & в надпись (Caption)?

Попробуйте: &&

7. Как сделать

окно (TForm) без заголовка (Caption)?

Попробуйте использовать следующий код:

 

constructor TPanelForm.Create(AOwner: TComponent); 

{ Вызов SetWindowLong API для изменения стиля окна главной формы.

} 

{ Берется существующий стиль и убирается флаг WS_CAPTION         

} 

var  

  LStyle: Longint; 

begin 

  inherited Create(AOwner); 

  BorderIcons := []; 

  LStyle := GetWindowLong(Handle, GWL_STYLE); 

  LStyle := LStyle and not WS_CAPTION; 

  SetWindowLong(Handle, GWL_STYLE, LStyle); 

{ Перерисуем окно } 

  ForceRepaint; 

end

procedure TPanelForm.ForceRepaint; 

var 

  RectWnd: TRect; 

  WWidth, WHeight: Integer; 

begin 

{ получаем размер окна } 

  GetWindowRect(Handle, RectWnd); 

  WWidth := RectWnd.Right-RectWnd.Left; 

  WHeight := RectWnd.Bottom-RectWnd.Top; 

{ Форсируем полную перерисовку. Это должен делать InvalidateRect()

} 

{ но почему-то не делает  : (  } 

{ “сожмем” окно } 

  SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE); 

{ восстановим окно } 

  SetWindowPos(Handle, HWND_TOP, 0, 0, WWidth, WHeight, SWP_NOMOVE); 

end

 

     

Можно поступить другим способом – выставить у формы свойство BorderStyle

= bsNone, и написать следующий обработчик OnPaint:

 

procedure TForm1.FormPaint(Sender: TObject); 

begin 

  Canvas.Brush.Style := bsClear; 

  Canvas.Rectangle(0, 0, Width, Height); 

end

 

     

8.

Почему некоторые компоненты типа TPanel и TEdit не имеют свойства Canvas?

Все наследники TCustomControl имеют Canvas, однако, в

большинстве случаев это свойство объявлено protected для предотвращения

рисования ‘чужаками’ на компоненте. Наследники компонента всегда могут

получить доступ к унаследованным protected свойствам (типа Canvas),

но пользователь компонента-никогда.

 

type 

  TCanvasPanel = class(TPanel) 

  public 

    property Canvas; 

  end

Если вы хотите рисовать на компоненте, у которого нет public

свойства Canvas, то используйте, например, компонент TPaintBox:

положите его на панель TPanel, сделайте Align = Client и

рисуйте на TPaintBox.Canvas.

9. Почему

при уничтожении компонента в методе OnClick происходит ошибка?

Q:Допустим, вы поместили

на форму кнопку, и создали метод OnClick в котором вызываете Button1.Free.

Вы видите, что это метод формы – казалось-бы, какие препятствия для правильного

уничтожения кнопки?

A:На самом деле Button1.OnClick

является свойством и после запуска вашего приложения содержит адрес метода

Form1.Button1Click. Именно кнопка вызывает этот метод как свой собственный.

А это означает, что кнопка не может удалить себя в своем-же методе. Даже

если вы попытаетесь удалить ссылку в OnClick:

    Button1.OnClick := nil;

    Button1.Free;

то это не поможет – стек настроен на возврат в обработчик TButton,

который и вызвал OnClick. Поскольку к моменту возврата объект разрушен

– возникает GPF или Access Violation.

10. Есть

ли у TDBGrid события OnMouseDown, OnMouseUp и OnMouseMove?

Они есть, но не объявлены published. Вы можете создать наследника

TDBGrid и сделать их published.

11. Поиск компонента

в форме по имени.

Q:Я хочу делать текущими

в форме произвольные компоненты. Как выставить фокус у конкретного компонента

ясно – ListBox1.SetFocus. А если я хочу обращаться к некоему компоненту

по имени (свойство Name)?

A:Свойство TForm.Components

– массив компонентов формы, который и нужен вам. Вы можете перемещаться

по этому массиву пока не найдете компонент с нужным Name. Например:

 

procedure TForm1.DooDah; 

var 

  Count: Integer; 

begin 

  Count := 0; 

  while (Count < ComponentCount) and (Components[Count]

<> ‘Button1’) do Inc(Count); 

  TButton(Components[Count]).SetFocus; 

end;

 

    или еще проще:

 

procedure TForm1.DooDah; 

var 

  Target: TComponent; 

begin 

  Target := FindComponent(‘Button1’); 

  TButton(Target).SetFocus; 

end

 

     

Оба этих примера показывают как найти компонент TButton с именем

Button1, и вызвать его метод SetFocus.

12. Как

получить горизонтальный ScrollBar на ListBox?

Пошлите сообщение LB_SETHORIZONTALEXTENT в ListBox. Например,

сообщение может быть отослано в момент создания формы:

 

procedure TForm1.FormCreate(Sender: TObject); 

begin 

  SendMessage(Listbox1.Handle, LB_SETHORIZONTALEXTENT, 1000,

Longint(0)); 

end

13. Как

определить текущую колонку и строку каретки в компоненте TMemo?

Вы можете использовать сообщения Windows API EM_LINEFROMCHAR

и EM_LINEINDEX для определения положения.

 

var 

  LineNum: Longint; 

  CharsBeforeLine: Longint; 

begin 

  LineNum := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, Memo1.SelStart,

0); 

  CharsBeforeLine := SendMessage(Memo1.Handle, EM_LINEINDEX,

LineNum, 0); 

  Label1.Caption := ‘Line ‘ + IntToStr(LineNum + 1) 

  Lebel2.Caption := ‘Position ‘ + IntToStr(Memo1.SelStart

– CharsBeforeLine + 1); 

end;

14.

Постранична прокрутка TMemo, реализация Undo и определение строки курсора.

Q:Как прокрутить содержимое

компонента TMemo?

A:Приведенная ниже процедура

предполагает, что фокус находится на Edit1 и осуществляет прокрутку

в соответствии с нажатыми клавишами.

 

procedure TForm1.Edit1KeyDown(Sender: TObject; var

Key: Word; Shift: TShiftState); 

begin 

  if Key = VK_F8 then 

    SendMessage(Memo1.Handle,  { HWND для

Memo } 

               

WM_VSCROLL,    { сообщение Windows } 

               

SB_PAGEDOWN,   { на страницу вниз } 

               

0)            

{ не используется } 

  else if Key = VK_F7 then SendMessage(Memo1.Handle,

WM_VSCROLL, SB_PAGEUP, 0); 

end

 

     

Q:Если определено всплывающее

(popup) меню для TMemo,и заданы клавиши для операций Cut, Copy,

Paste, то я могу обрабатывать эти события, вызывая методы CutToClipboard,

CopyToClipboard, и т.д. Однако, если я поместили пункт Undo в меню (обычно

Ctrl+Z), то как дать знать TMemo, что нужно выполнить Undo?

A:Если встроенного Undo

достаточно, то это очень просто:

    Memo1.Perform(EM_UNDO, 0, 0);

Для переключения свойства Enabled пункта меню Undo1:

    Undo1.Enabled := Memo1.Perform(EM_CANUNDO, 0, 0) <> 0;

Q:Как можно определить,

на какой строке в TMemo находится курсор?

A:Весь фокус в сообщении

EM_LINEFROMCHAR. Попробуйте:

 

procedure TMyForm.BitBtn1Click(Sender: TObject); 

var 

  ILine: Integer; 

begin 

  ILine := Memo1.Perform(EM_LINEFROMCHAR, $FFFF, 0); 

{ Внимание: номера строк начинаются с нуля } 

  MessageDlg(‘Line Number: ‘ + IntToStr(ILine), mtInformation,

[mbOK], 0); 

end

15. Как поместить

BLOB Memo в компонент TMemo?

Попробуйте так:

 

procedure TForm1.Button1Click(Sender: TObject); 

var 

  S: TBlobStream; 

begin 

  S := TBlobStream.Create(Table1BBBMemo, bmRead); 

  Memo1.Lines.LoadFromStream(S); 

  S.Free; 

end

где:

  1. Table1BBBMemo – имя поля BLOB Memo (TMemoField).

  2. Memo1 – имя компонента TMemo.

Естественно, что этим-же способом можно обмениваться информацией с BLOB-полями

произвольного типа.

16. Как показать

содержимое Memo поля в TDBGrid?

Используйте следующий код для обработки события OnDrawDataCell

у TDBGrid. (Перед запуском программы создайте объект TMemoField

для memo поля в Fields Editor).

 

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const

Rect: TRect; 

  Field: TField; State: TGridDrawState); 

var 

  P: array [0..1023] of Char; { MemoField

buffer } 

  BS: TBlobStream; 

  S: string

begin 

  if Field is TMemoField then 

  with (Sender as TDBGrid).Canvas do 

  begin 

{ Table1Notes is the TMemoField } 

    BS := TBlobStream.Create(Table1Notes, bmRead); 

    FillChar(P, SizeOf(P), #0); 

    BS.Read(P, SizeOf(P)); 

    BS.Free; 

    S := StrPas(P); 

{ remove carriage returns & line feeds } 

    while Pos(#13, S) > 0 do

S[Pos(#13, S)] := ‘ ‘

    while Pos(#10, S) > 0 do

S[Pos(#10, S)] := ‘ ‘

{ clear the cell } 

    FillRect(Rect); 

{ fill cell with memo data } 

    TextOut(Rect.Left, Rect.Top, S); 

  end

end

 

     

17. Не возникает событие

TSpeedButton.OnDblClick.

Q:Я создаю событие

на SpeedButton1.OnDblClick, но оно, похоже, вообще никогда не возникает.

OnClick работает. Что делать?

A:На самом деле работает,

только в определенных ситуациях. Если вы помещаете на панель несколько

кнопок, то по умолчанию они независимы и соответственно не фиксируются

в нажатом состоянии. Поскольку одиночное нажатие мыши на кнопку отрабатывается

немедленно, двойной щелчок мыши воспринимается как два нажатия и отпускания.

Поэтому OnDblClick и не срабатывает.

Если  же кнопки связаны в группу (GroupIndex <> 0), то

они могут фиксироваться, и соответственно могут воспринимать двойной щелчок

мыши.

18.

Как разделить обработку OnClick и OnDblClick? Ведь OnClick будет вызываться

всегда, и перед DblClick.

Именно так и происходит в Windows – посылаются оба сообщения. Для того

чтобы обработать только какое-то одно событие необходимо чуть “задержать”

выполнение OnClick. Сделать это можно следующим способом:

 

procedure TForm1.ListBox1Click(Sender: TObject); 

var 

  Msg: TMsg; 

  TargetTime: Longint; 

begin 

{ get the maximum time to wait for a double-click message } 

  TargetTime := GetTickCount + GetDoubleClickTime; 

{ cycle until DblClick received or wait time run out } 

  while GetTickCount < TargetTime do 

  if PeekMessage(Msg, ListBox1.Handle, WM_LBUTTONDBLCLK,

WM_LBUTTONDBLCLK, WM_NOREMOVE) 

  then Exit; { Double click } 

  MessageDlg(‘Single clicked’, mtInformation, [mbOK],

0); 

end

 

     

19.

Как определить из обработчика события OnClick в Popup.MenuItem, для какого

объекта это произошло?

Используйте свойство PopupComponent компонента TPopupMenu

для определения, где была нажата правая кнопка.

 

procedure TForm1.PopupItem1Click(Sender: TObject); 

begin 

  Label1.Caption := PopupMenu1.PopupComponent.Name; 

end

Свойство ActiveControl для формы тоже можно использовать, однако,

ActiveControl не обязательно является тем элементом, для которого

произошло событие.

20.

Как использовать case, чтобы определить, какой объект вызвал процедуру?

Используйте свойство Tag. Установите значение Tag свое

у каждого объекта для опознания. (Использование констант, которые описывают

объект – идеально подходит).

 

case (Sender as TComponent).Tag of 

  Button1ID: SomeProcedure; 

  Button2ID: AnotherProcedure; 

end

Таким образом вы можете обрабатывать события как от однотипных компонент,

так и от компонент разного типа.

21. Как

обрабатывать события от множества однотипных компонентов.

Q:На моей форме находится

примерно 10 кнопок. Я хочу обрабатывать нажатие на любую из них одним событием,

но как их отличить внутри обработчика события?

A:Для этого базовый

класс VCL TComponent имеет поле Tag типа Longint.

В момент разработки вы можете присвоить этому полю любое значение, а в

момент исполнения использовать его (или переопределять). В вашей ситуации

достаточно присвоить полю ButtonX.Tag значение от 1 до 10 (или от

0 до 9, как удобнее), а в обработчике написать примерно следующее:

 

procedure MyForm.Button1Click(Sender: TObject); 

begin 

  case (Sender as TComponent).Tag of 

    1: {…}

    2: {…}

    3: {…}

  end

end

 

     

22. Использование

TPanel в качестве “индикатора”.

Q:Я пытаюсь использовать

TPanel как индикатор процесса обновления БД.  Однако надпись

на панели не обновляется пока не закончится цикл обработки БД. В цикле

вызывается Panel.Caption := …

A:После присвоения Panel.Caption

вызывайте Panel.Refresh или Application.ProcessMessages (второй

вариант предпочтительней, так как позволяет перерисовать себя всем клмплнентам,

которые в этом нуждаются).

23.

Включение и выключение подсказок (Hints) для всех элементов на форме.

Если ваша форма содержит панель подсказки в нижней части формы, то вы

можете определить подменю для этой панели, и выставлять Form.ShowHint

в True или False в зависимости от состояния Checked элемента

меню.

Например, в TMenuItem.OnClick напишите:

    ShowHint := not (Sender as TMenuItem).Checked;

В результате на локальном меню панели будет видно, включены подсказки для

всех элементов или нет.

24. Как в меню поместить

bitmap?

Можно поступить таким образом:

 

var 

  Bmp1: TBitmap; 

begin 

  Bmp1 := TBitmap.Create; 

  Bmp1.LoadFromFile(‘C:WHEREB1.BMP’); 

  SetMenuItemBitmaps(MenuItemTest.Handle, 0, MF_BYPOSITION,

Bmp1.Handle, Bmp1.Handle); 

end

Параметры:

  • MenuItemTest – имя пункта меню (горизонтальная строка)

  • 0,1 … – позиция пункта меню, в который надо вставить BMP

  • первый Handle – для показа невыбранного пункта меню (Unchecked)

  • второй Handle – для выбранного (Checked). Они могут быть разные

Код можно вставить в обработчик OnCreate для формы. При уничтожении

меню TBitmap не уничтожается, это надо делать отдельно.

25.

Каким образом можно поместить двумерный массив в TImage?

Представим, что данные находятся в массиве:

    TestArray: array [0..127, 0..127] of Byte;

Картинка будет иметь размер 128×128 точек:

    Image1.Picture.Bitmap.Width := 128;

    Image1.Picture.Bitmap.Height := 128;

Вызываем функцию Windows API для формирования bitmap:

    SetBitmapBits(Image1.Picture.Bitmap.Handle, SizeOf(TestArray),

    @TestArray);

    Image1.Refresh;  { для того, чтобы изменения отобразились

    }

Однако, если вы используете свою палитру, то ее нужно создавать специально.

26. Как из программы

‘открыть’ TComboBox?

У TComboBox есть run-time свойство, не упомянутое в on-line help

DroppedDown.

Для открытия ComboBox напишите:

    ComboBox1.DroppedDown := True;

Естественно, False закроет его.

27. Как

заменить надпись ‘Read only’ в компонентах TSaveDialog и TOpenDialog?

Попробуйте посмотреть в Windows API Help разделы, связанные с lpTemplateName.

Вообще говоря, вы можете заменить стандартный Open Dialog Box своим собственным

шаблоном.

28. Проблема

в использовании компонента TCustomGrid.

Q:Делаю так:

  1. Создаю новый компонент при помощи Эксперта Компонент

  2. Имя класса TSampleCalendar

  3. Имя родителя TCustomGrid

  4. Использую страницу ‘Samples’

  5. Сохраняю модуль с именем CALSAMP.PAS

  6. Подключаю к Палитре компонент

  7. Создаю форму, помещаю новый компонент на форму и получаю Runtime Error

    210

В чем дело?

A:Проблема в том, что

TCustomGrid имеет метод DrawCell, который является абстрактным.

То, что его безусловно надо переписывать у любого наследника TCustomGrid,

к сожалению, не отражено в документации. Создайте этот метод (пусть даже

пустой) и ваша проблема исчезнет.

29. Как установить

формат для поля таблицы?

В Fields Editor выберите поле для форматирования. Используя свойства

DisplayFormat и EditFormat сделайте то, что нужно. DisplayFormat

работает для поля, на которое не установлен фокус. EditFormat работает

для поля, на которое фокус установлен. Форматирование аналогично первому

параметру в функции FormatFloat, но без скобок.

30.

Можно ли использовать клавишу ENTER при вводе данных для перехода от поля

к полю?

Используйте данный код для события OnKeyPress компонента TEdit.

 

procedure TForm1.Edit1KeyPress(Sender: TObject; var

Key: Char); 

begin 

  if Key = #13 then 

  begin 

    SelectNext(Sender as TWinControl, True,

True); 

    Key := #0

  end

end

Теперь Enter ведет себя как Tab. Затем, выберите все объекты, которые

должны вести себя как Edit1 (за исключением кнопок) и в Object Inspector

установите обработчик OnKeyPress в Edit1KeyPress. Каждый

выбранный вами объект воспринимает Enter как Tab. Если вы хотите обрабатывать

событие на уровне формы (а не в каждом отдельном компоненте), уберите обработчики

события у всех компонент и создайте FormKeyPress – обработчик OnKeyPress

для формы:

 

procedure TForm1.FormKeyPress(Sender: TObject; var

Key: Char); 

begin 

  if Key = #13 then 

  begin 

    SelectNext(Sender as TWinControl, True,

True); 

    Key := #0

  end

end

Все объекты на форме будут воспринимать Enter как Tab.

[Назад][Содержание][Вперед]

Eswon Esk



Ученик

(57),
на голосовании



8 лет назад

Есть ситуация – множество форм, и управляющая панелька где при клике на кнопку добавляется какой-нибудь интерфейс на активное окно из оставшихся.
Как мне это сделать? То есть, например, под выбором стоит третья из пяти форм. У неё имя Form3. Я создаю динамический компонент, и в родителях указываю её вот. Но как? Что-то типа:
str:=’Form2′;
cm[i]:=TEdit.Create(str);
Не получается.

Дополнен 8 лет назад

‘Form3’*, да

Дополнен 8 лет назад

Ну из гуи что-нибудь – кнопки, мемо, скроллбары и т. д.
То есть, выбираю какое-то из окон, жму кнопку в той панельке “Добавить”, с выбранным из чекбокса например “Поле ввода”, и у меня в указанном окне появляется Edit.

Дополнен 8 лет назад

динамически созданный*

Дополнен 8 лет назад

Всем спасибо – помогли указатели

Голосование за лучший ответ

Scorpio

Просветленный

(24283)


8 лет назад

” и управляющая панелька где при клике на кнопку добавляется какой-нибудь интерфейс на активное окно из оставшихся. “
Что значит добавляется какой-то интерфейс? Куда добавляется, откуда добавляется? Что значит интерфейс?

Ирина В

Просветленный

(48880)


8 лет назад

cm: array […] of TWinControl;

Нажатие на кнопку ‘Edit’:

cm[i]:=TEdit.Create(Form2);
cm[i].Parent:=Form2;
cm[i].Name:=’Edit’+IntToStr(i);
cm[i].Visible:=True;
cm[i].BringToFront;

Добавить комментарий