Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  09:13[Войти] | [Зарегистрироваться]
Ответ на вопрос № 80530

12-01-2012 11:48
Создание формы, компонентов на ней и управление обработчиками этих компонент в Run-Time

Создаю форму в ран-тайме и создаю на ней 3 Edit и 2 Button, подскажите как сделать обработчик этих компонентов.
Чтоб иметь доступ из этих кнопок с свойствам формы.


procedure cr_form;
var
  F: TForm;

  procedure cr_edit(x, y, order: integer);
  var
    E: TEdit;
  begin
    E := TEdit.Create(F);
    try
      E.Parent := F;
      E.Name := 'Ed'+IntToStr(order);
      E.Text := '';
      E.TabOrder:=order;
      E.Left := x;
      E.Top := y;
      E.Height := 25;
      E.Width := 200;
    finally
      // E.Free;
    end;
  end;

  procedure cr_but(x, y, order: integer; Cap: string);
  var
    B: TButton;
  begin
    B := TButton.Create(F);
    try
      B.Parent := F;
      B.Name := 'Bu'+IntToStr(order);
      B.Caption := Cap;
      B.Left := x;
      B.Top := y;
      B.Height := 25;
      B.Width := 75;
      //B.OnClick := OnClickButton;
    finally
      // E.Free;
    end;
  end;

begin
  F := TForm.Create(NIL);
  F.Position := poScreenCenter;
  F.Name:='F_Add';
  F.Caption:='Добавить новую запись';
  F.BorderStyle:=bsDialog;
  cr_edit(10, 10, 1);
  cr_edit(10, 35, 2);
  cr_edit(10, 60, 3);

  cr_but(10, 130, 1, 'Ок');
  cr_but(90, 130, 2, 'Отмена');
  try
    F.ShowModal;
  finally
    F.Free;
  end;
end;

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

16-01-2012 16:17
Полностью автоматическое формирование может понадобиться достаточно редко и действительно скорее в случаях вроде DatabaseDesktop. Однако полуавтоматический вариант может быть очень полезен. Например, в случае необходимости редактирования множества справочников без особых изысков. В этом случае вариант с одной универсальной формой, доводимой до ума под конкретный случай десятком строчек был бы горазд более предпочтителен, нежели пара десятков пар файлов pas+dfm.
В общем, вопрос показался мне интересным и я ради спортивного интереса наваял пример. Реализация не идеальна, это скорее набор идей, доведённый до минимально рабочего состояния, но пример полностью рабочий, готовый к немедленному применению и как минимум удовлетворяет критериям того, чего хотел автор вопроса.
Для удобства тестирования привожу все файлы проекта.

Project3.dpr

program Project3;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  RecEdit_Form in 'RecEdit_Form.pas' {RecEditForm},
  Form_Utils in 'Form_Utils.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.



Unit1.pas

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, DBTables, Grids, DBGrids;

type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    Table1: TTable;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    Button9: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure Button9Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses RecEdit_Form;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Все поля горизонтально';
    AddAllFields;
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Все поля вертикально';
    MakeVert;
    VStep := VStep - 3;
    AddAllFields;
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Комментарии автоматически по DisplayName';
    AddField('FIRST_NAME');
    AddField('LAST_NAME');
    AddField('STATE');
    AddField('CITY');
    AddField('ADDRESS_1');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Горизонтально, по умолчанию, свои комментарии';
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    AddField('ADDRESS_1', 'Адрес');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Комментарий укорочен';
    CaptionWidth := 50;
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Узкая форма, меньше шаг';
    CaptionWidth := 50;
    Width := 200;
    VStep := VStep - 3;
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Вертикально, по умолчанию';
    MakeVert;
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button8Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Узкая форма, уменьшен шаг';
    MakeVert;
    Width := 200;
    VStep := VStep - 7;
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    EditRec;
  finally
    Free;
  end;
end;

procedure TForm1.Button9Click(Sender: TObject);
begin
  with TRecEditForm.Create(DataSource1) do
  try
    Caption := 'Комбинированное расположение';
    CaptionWidth := 80;
    Width := 250;
    VStep := VStep - 3;
    {Горизонтально}
    AddField('FIRST_NAME', 'Имя');
    AddField('LAST_NAME', 'Фамилия');
    AddField('BIRTH_DATE', 'Дата рождения');
    AddField('STATE', 'Штат');
    AddField('CITY', 'Город');
    {Вертикально}
    VStep := VStep + 10;
    AddField('ADDRESS_1', 'Адрес');
    VStep := VStep - 10 - 5;
    MakeVert;          // Применяется, начиная с предыдущей
    AddField('OCCUPATION', 'Род занятий');
    AddField('INTERESTS', 'Интересы');
    EditRec;
  finally
    Free;
  end;
end;

end.



Unit1.dfm

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 486
  ClientWidth = 735
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  DesignSize = (
    735
    486)
  PixelsPerInch = 96
  TextHeight = 13
  object DBGrid1: TDBGrid
    Left = 0
    Top = 0
    Width = 735
    Height = 317
    Align = alTop
    Anchors = [akLeft, akTop, akRight, akBottom]
    DataSource = DataSource1
    ReadOnly = True
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
  end
  object GroupBox1: TGroupBox
    Left = 20
    Top = 331
    Width = 146
    Height = 105
    Anchors = [akLeft]
    Caption = #1042#1089#1077' '#1087#1086#1083#1103' '#1072#1074#1090#1086#1084#1072#1090#1080#1095#1077#1089#1082#1080
    TabOrder = 1
    ExplicitTop = 330
    object Button1: TButton
      Left = 15
      Top = 25
      Width = 106
      Height = 25
      Caption = #1043#1086#1088#1080#1079#1086#1085#1090#1072#1083#1100#1085#1086
      TabOrder = 0
      OnClick = Button1Click
    end
    object Button2: TButton
      Left = 15
      Top = 61
      Width = 106
      Height = 25
      Caption = #1042#1077#1088#1090#1080#1082#1072#1083#1100#1085#1086
      TabOrder = 1
      OnClick = Button2Click
    end
  end
  object GroupBox2: TGroupBox
    Left = 230
    Top = 331
    Width = 211
    Height = 151
    Anchors = [akLeft]
    Caption = #1043#1086#1088#1080#1079#1086#1085#1090#1072#1083#1100#1085#1086' '#1074#1099#1073#1086#1088#1086#1095#1085#1086
    TabOrder = 2
    ExplicitTop = 330
    object Button3: TButton
      Left = 8
      Top = 20
      Width = 188
      Height = 25
      Caption = #1050#1086#1084#1084#1077#1085#1090#1072#1088#1080#1080' '#1087#1086' DisplayName'
      TabOrder = 0
      OnClick = Button3Click
    end
    object Button4: TButton
      Left = 10
      Top = 51
      Width = 186
      Height = 25
      Caption = #1057#1074#1086#1080' '#1082#1086#1084#1084#1077#1085#1090#1072#1088#1080#1080
      TabOrder = 1
      OnClick = Button4Click
    end
    object Button5: TButton
      Left = 10
      Top = 82
      Width = 186
      Height = 25
      Caption = #1050#1086#1084#1084#1077#1085#1090#1072#1088#1080#1080' '#1091#1082#1086#1088#1086#1095#1077#1085#1099
      TabOrder = 2
      OnClick = Button5Click
    end
    object Button6: TButton
      Left = 10
      Top = 113
      Width = 186
      Height = 25
      Caption = #1059#1079#1082#1072#1103' '#1092#1086#1088#1084#1072', '#1091#1084#1077#1085#1100#1096#1077#1085' '#1096#1072#1075' '
      TabOrder = 3
      OnClick = Button6Click
    end
  end
  object GroupBox3: TGroupBox
    Left = 447
    Top = 333
    Width = 209
    Height = 119
    Anchors = [akLeft]
    Caption = #1042#1077#1088#1090#1080#1082#1072#1083#1100#1085#1086' '#1074#1099#1073#1086#1088#1086#1095#1085#1086
    TabOrder = 3
    ExplicitTop = 332
    object Button7: TButton
      Left = 10
      Top = 20
      Width = 186
      Height = 25
      Caption = #1055#1086' '#1091#1084#1086#1083#1095#1072#1085#1080#1102
      TabOrder = 0
      OnClick = Button7Click
    end
    object Button8: TButton
      Left = 10
      Top = 51
      Width = 186
      Height = 25
      Caption = #1059#1079#1082#1072#1103' '#1092#1086#1088#1084#1072', '#1091#1084#1077#1085#1100#1096#1077#1085' '#1096#1072#1075
      TabOrder = 1
      OnClick = Button8Click
    end
    object Button9: TButton
      Left = 10
      Top = 82
      Width = 186
      Height = 25
      Caption = #1050#1086#1084#1073#1080#1085#1080#1088#1086#1074#1072#1085#1085#1086#1077' '#1088#1072#1089#1087#1086#1083#1086#1078#1077#1085#1080#1077
      TabOrder = 2
      OnClick = Button9Click
    end
  end
  object DataSource1: TDataSource
    DataSet = Table1
    Left = 105
    Top = 440
  end
  object Table1: TTable
    Active = True
    DatabaseName = 'DBDEMOS'
    TableName = 'clients.dbf'
    Left = 45
    Top = 440
  end
end



RecEdit_Form.pas

unit RecEdit_Form;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Mask, DBCtrls, DB, DBTables;

type
  TRecEditForm = class(TForm)
    btnOk: TButton;
    btnCancel: TButton;
    Label1: TLabel;
    DBEdit1: TDBEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FVStep: integer;
    FDataSource: TDataSource;
    FDataSet: TDataSet;
    FFieldCount: Integer;
    FLabel: TLabel;
    FDBEdit: TDBEdit;
    procedure SetCaptionWidth(const Value: integer);
  public
    constructor Create(ADataSource: TDataSource); reintroduce;
    property VStep: integer read FVStep write FVStep;
    property CaptionWidth: integer write SetCaptionWidth;
    procedure AddField(AFieldName: String; ACaption: String = '');
    procedure AddAllFields;
    function EditRec: Boolean;
    procedure MakeVert;
  end;

//var
//  RecEditForm: TRecEditForm;

implementation

uses Form_Utils;

{$R *.dfm}

constructor TRecEditForm.Create(ADataSource: TDataSource);
begin
  inherited Create(nil);
  FDataSource := ADataSource;
  FDataSet := FDataSource.DataSet;
  FFieldCount := 0;
  FVStep := 25;
  FLabel := Label1;
  DBEdit1.DataSource := ADataSource;  // Будет клонироваться
  FDBEdit := DBEdit1;
  ActiveControl := DBEdit1;  // TabOrder: btnOk, btnCancel, DBEdit1, <добавляемые>
end;

function TRecEditForm.EditRec: Boolean;
begin
  FDataSet.Edit;
  Result := (ShowModal = mrOk);
end;

procedure TRecEditForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if ModalResult = mrOk then
  try
    FDataSet.Post;
    if FDataSet is TBDEDataSet then
      TBDEDataSet(FDataSet).FlushBuffers;
  except
    ShowMessage('Ошибка при сохранении');
    Action := caNone;
  end
  else
    FDataSet.Cancel;
end;

procedure TRecEditForm.MakeVert;
var
  OldTop, DeltaY: Integer;
begin
  FDBEdit.Width := (FDBEdit.Left + FDBEdit.Width) - FLabel.Left;
  FDBEdit.Left := FLabel.Left;
  FLabel.Width := FDBEdit.Width;
  OldTop := FDBEdit.Top;
  FDBEdit.Top := FLabel.Top + FLabel.Height + 2;
  DeltaY := FDBEdit.Top - OldTop;
  VStep := VStep + DeltaY;
  Height := Height + DeltaY;
end;

procedure TRecEditForm.SetCaptionWidth(const Value: integer);
var
  Delta: Integer;
begin
  Delta := Value - FLabel.Width;
  FLabel.Width := Value;
  FDBEdit.Left := FDBEdit.Left + Delta;
  FDBEdit.Width := FDBEdit.Width - Delta;
end;

procedure TRecEditForm.AddField(AFieldName: String; ACaption: String = '');
begin
  try
    FDataSet.FieldByName(AFieldName)
  except
    ShowMessage('Поле не найдено: ' + AFieldName);
    Exit;
  end;
  Inc(FFieldCount);
  if FFieldCount > 1 then
  begin
    FLabel := CloneLabel(FLabel);  // Клонируем по предыдущей и присв. ссылку той-же переменной
    FLabel.Top := FLabel.Top + FVStep;
    FDBEdit := CloneDBEdit(FDBEdit);
    FDBEdit.Top := FDBEdit.Top + FVStep;
    Height := Height + FVStep;
  end;
  FDBEdit.DataField := AFieldName;
  if ACaption = '' then
    FLabel.Caption := FDBEdit.Field.DisplayName  // После назначения поля
  else
    FLabel.Caption := ACaption;
end;

procedure TRecEditForm.AddAllFields;
var
  i: Integer;
begin
  for i:=0 to FDataSet.FieldCount-1 do
    AddField(FDataSet.Fields[i].FieldName);
end;

end.



RecEdit_Form.dfm

object RecEditForm: TRecEditForm
  Left = 0
  Top = 0
  BorderStyle = bsDialog
  Caption = 'RecEditForm'
  ClientHeight = 93
  ClientWidth = 398
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  OnClose = FormClose
  DesignSize = (
    398
    93)
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 17
    Width = 106
    Height = 13
    AutoSize = False
    Caption = 'Label1'
  end
  object btnOk: TButton
    Left = 228
    Top = 60
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'Ok'
    ModalResult = 1
    TabOrder = 0
  end
  object btnCancel: TButton
    Left = 315
    Top = 60
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 1
  end
  object DBEdit1: TDBEdit
    Left = 120
    Top = 13
    Width = 270
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    AutoSize = False
    TabOrder = 2
  end
end



Form_Utils.pas

unit Form_Utils;

interface

uses StdCtrls, DBCtrls;

  function CloneLabel(ALabel: TLabel): TLabel;
  function CloneDBEdit(ADBEdit: TDBEdit): TDBEdit;

implementation

uses Controls;

function CloneLabel(ALabel: TLabel): TLabel;
begin
  with ALabel do
  begin
    Result := TLabel.Create(Owner);
    Result.Parent := Parent;
    Result.AutoSize := AutoSize;
    Result.SetBounds(Left, Top, Width, Height);
    Result.Anchors := Anchors;
    Result.Caption := Caption;
    //...
  end;
end;

function CloneDBEdit(ADBEdit: TDBEdit): TDBEdit;
begin
  with ADBEdit do
  begin
    Result := TDBEdit.Create(Owner);
    Result.Parent := Parent;
    Result.AutoSize := AutoSize;
    Result.SetBounds(Left, Top, Width, Height);
    Result.Anchors := Anchors;
    Result.DataSource := DataSource;
    Result.DataField := DataField;
    Result.ReadOnly := ReadOnly;
    //...
  end;
end;

end.



16-01-2012 15:57 | Комментарий к предыдущим ответам
в общем случае с программой работает не программист, а неквалифицированный пользователь
В данном случае речь идет о заполнении справочников. Это уровень квалифицированного пользователя :)

16-01-2012 12:10 | Комментарий к предыдущим ответам
Однако мы пользуемся ObjectInspector'ом который умеет отображать структуру произвольного компонента.
Почему бы не работать подобным образом с записью произвольной базы? Там, ведь, тоже можно получить информацию о всех полях и их типах.


Потому что в общем случае с программой работает не программист, а неквалифицированный пользователь, страждущий дружелюбного интерфейса. И кстати, ObjectInspector позволяет настроить взаимоисключающие свойства, что тоже вряд ли понравится пользователю.

16-01-2012 10:46 | Комментарий к предыдущим ответам
Однако мы пользуемся ObjectInspector'ом который умеет отображать структуру произвольного компонента.
Почему бы не работать подобным образом с записью произвольной базы? Там, ведь, тоже можно получить информацию о всех полях и их типах.
В параметрической CAD-системе TFlex реализованы оба варианта для редактирования параметров фрагментов: стандартным образом генерируется табличка: имя параметра, тип, комментарий, значение, а, при необходимости, можно нарисовать уникальный диалог со всевозможными пояснениями, рисунками, комбобоксами и т.д.

16-01-2012 02:59 | Комментарий к предыдущим ответам
Я могу представить лишь один случай, когда автоматическая генерация формы по датасету удобна - программа типа Database Desktop, которой пользуются разработчики. Если программой пользуются обычные юзеры - лучше их все-таки пожалеть :)

16-01-2012 01:30 | Комментарий к предыдущим ответам
>>> Разве что для программы, работающей с произвольными данными
Для работы с произвольными данными — это пущая мелкомягкие делают: получается откровенная гадость, но все верят, что это круто. Я же говорил про ситуацию, когда "разнообразие датасетов не очень велико (при большом количестве самих форм)".

16-01-2012 00:44 | Комментарий к предыдущим ответам
Ну ты докопался!
Я докопался? Борланд раньше меня докопался, когда создал среду визуального программирования :)
Помню, как я на Клиппере создавал диалоги путем ручного описания координат каждого элемента. Бр-р-р... :)

реализовать правила автоматической генерации форм — вполне разумное решение.
Разве что для программы, работающей с произвольными данными, у которой не будет осмысленного с точки зрения обычного пользователя интерфейса (ну типа того же Акцесса).

16-01-2012 00:15 | Комментарий к предыдущим ответам
>>> То есть, удобнее 10-20 форм создавать через cr_edit, cr_button, cr_combobox, cr_dateedit, cr_label и т.п. с указанием координат каждого компонента, без возможности проверки корректности ввода?
Ну ты докопался! Знаешь такую вещь как MS Access? :D Вот там есть команда автоматической генерации формы по датасету. Иногда это даже удобно, хотя в общем случае результат, зачастую, получается весьма корявым и требует доработки напильником. Но если у тебя разнообразие датасетов не очень велико (при большом количестве самих форм), то реализовать правила автоматической генерации форм — вполне разумное решение.

15-01-2012 23:12
если одна две формы то проще так, но если надо заполнять 10-20 разный справочников... то ни разу не удобно

То есть, удобнее 10-20 форм создавать через cr_edit, cr_button, cr_combobox, cr_dateedit, cr_label и т.п. с указанием координат каждого компонента, без возможности проверки корректности ввода? Ну, на вкус, на цвет товарища нет...

15-01-2012 02:20
буду писать как умею...

А не проще все-таки создать форму в дизайн-тайм?


если одна две формы то проще так, но если надо заполнять 10-20 разный справочников... то ни разу не удобно

15-01-2012 02:18
Дизайнтайм: Берем обычный грид. Устанавливаем два столбца.
Рантайм: Указываем число строк равное числу полей в базе. Первый столбец заполняем названиями полей.

Гораздо проще, чем в рантайм плодить эдиты.
В Дельфи7 есть и готовый компонент на два столбца, но названия я не помню, так как сам пользуюсь гридом в три столбца: во второй вывожу тип поля (в зависимости от него и подключается нужный обработчик).


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

15-01-2012 02:06
буду писать как умею...

А не проще все-таки создать форму в дизайн-тайм?

14-01-2012 18:03
Дизайнтайм: Берем обычный грид. Устанавливаем два столбца.
Рантайм: Указываем число строк равное числу полей в базе. Первый столбец заполняем названиями полей.

Гораздо проще, чем в рантайм плодить эдиты.
В Дельфи7 есть и готовый компонент на два столбца, но названия я не помню, так как сам пользуюсь гридом в три столбца: во второй вывожу тип поля (в зависимости от него и подключается нужный обработчик).

14-01-2012 03:05
я думал Сергей Перовский говорит о каком то компоненте, который позволяет редактировать записи предлагая изменять их отдельно от грида... но как я понимаю чудес не бывает ) буду писать как умею... если идея получится, то сделаю отдельный юнит с функциями и выложу сюда, людям на радость)

14-01-2012 03:00
Сергей Перовский имел ввиду, что DBGrid может сам вывести все поля таблицы, даже если их количество заранее неизвестно. Но вряд ли это решение можно назвать универсальным. Иногда гораздо удобнее редактировать запись в отдельной форме. Которую, естественно, гораздо удобнее создать прямо в Дельфи, а не мучаться с рантайм.

13-01-2012 14:39
не совсем понял...

13-01-2012 14:21
Для начала посмотрите примеры работы с DBGrid.
Если явным образом не указано иное, выводятся все столбцы указанной таблицы.
Если нужно отображать отдельную запись, то существует компонент, аналогичный ObjectInspector'у.
На память названия не скажу.
Там придется прописывать имена параметров, но это проще, чем создавать кучу эдитов.
Наконец, можно сделать самому на основе StringGrid'а.

13-01-2012 13:52
13-01-2012 05:51Вы не первый, кому нужно работать с таблицами, заранее неизвестной структуры.
Вовсе не обязательно создавать Edit-ы для этой цели.
Для этих целей существуют специальные компоненты.


не знал что такие компоненты существуют, подскажите пожалуйста какие?

13-01-2012 05:51
Вы не первый, кому нужно работать с таблицами, заранее неизвестной структуры.
Вовсе не обязательно создавать Edit-ы для этой цели.
Для этих целей существуют специальные компоненты.

13-01-2012 03:30
ну так создайте еще одну форму с эдитами и кнопками...
перед ее показом заполняйте (если необходимо) поля "по умолчанию", а после "Ок" вносите данные с формы в БД


with form2 do
  begin
  edit1.text:='Иванов';
  if ShowModal = mrOk then <Обработка введенных данных>
  end;



Удачи

13-01-2012 02:50
хочу заполнять через форму родителя справочники, а динамическая форма будет иметь Едиты чтоб данные вводить а при нажатии Ок введенные данные передаются в Родителя и там проверяются и заносятся в базу...

Не очень удачная идея. Вид динамически созданной формы непредсказуем, например, при смене разрешения у винды. Да и программировать такие формы весьма непросто. Не для того ли придумали визуальную среду программирования, чтобы "рисовать" формы на экране, а не мучительно прописывать их в коде? Кроме того, проверку введенных данных и их занесение в базу правильно организовывать не в родителе, а в самой форме ввода данных. А то получится, что юзер ввел 100 полей, нажал "ОК", а форма выведа сообщение "Не указан номер телефона" и удалилась вместе со всеми введенными данными :)

13-01-2012 02:31
хочу заполнять через форму родителя справочники, а динамическая форма будет иметь Едиты чтоб данные вводить а при нажатии Ок введенные данные передаются в Родителя и там проверяются и заносятся в базу...
вот...

13-01-2012 02:28
Я тоже не понял, зачем создавать форму в ран-тайм. Но если уж так надо - вовсе незачем делать обработчики для кнопок, достаточно назначить этим кнопкам соответствующий ModalResult.

13-01-2012 02:21 | Вопрос к автору: запрос дополнительной информации
Добрый день.
А зачем такая необходимость - создавать форму в ран-тайме?
Почему нельзя создать форму а потом ее просто вызывать?

13-01-2012 01:40
Не пойдеть. Для создаваемой в рантайм формы сделайте класс-наследник от TForm, в него и поместите обработчик нажатия кнопки. Глобальную переменную выкиньте. А в самом обработчике обходитесь без переменной вообще, поскольку форма будет доступна, естественно, как Self. Такие вещи как явное обращение к Form3 в методах TForm3 (т.е. использование глобальной переменной вместо Self по умолчанию) - моветон.

13-01-2012 01:35
не так выразился, надо было объявить переменную F для родительской формы, а я ее указывал в процедуре...


unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DBGridEhGrouping, GridsEh, DBGridEh,
  Vcl.ExtCtrls, Data.DB, Data.Win.ADODB, Vcl.StdCtrls, Vcl.Buttons;

type

  TForm3 = class(TForm)
    ADOQuery1: TADOQuery;
    DataSource1: TDataSource;
    Panel1: TPanel;
    Panel2: TPanel;
    DBGridEh1: TDBGridEh;
    Panel3: TPanel;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Edit1: TEdit;
    StaticText1: TStaticText;
    procedure Edit1Change(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    procedure MyOnClickEvent(Sender: TObject);
    { Public declarations }
  end;

var
  Form3: TForm3;
  F: TForm;

implementation

{$R *.dfm}

procedure TForm3.MyOnClickEvent;
begin
  F.Close;
end;

procedure cr_form;

  procedure cr_edit(x, y, order: integer);
  var
    E: TEdit;
  begin
    E := TEdit.Create(F);
    try
      E.Parent := F;
      E.Name := 'Ed' + IntToStr(order);
      E.Text := '';
      E.TabOrder := order;
      E.Left := x;
      E.Top := y;
      E.Height := 25;
      E.Width := 200;
    finally
      // E.Free;
    end;
  end;

  procedure cr_but(x, y, order: integer; Cap: string);
  var
    B: TButton;
  begin
    B := TButton.Create(F);
    try
      B.Parent := F;
      B.Name := 'But' + IntToStr(order);
      B.Caption := Cap;
      B.Left := x;
      B.Top := y;
      B.Height := 25;
      B.Width := 75;
      B.OnClick := Form3.MyOnClickEvent;
    finally
      // E.Free;
    end;
  end;

begin
  F := TForm.Create(Application);
  F.Parent := Form3;
  F.Position := poScreenCenter;
  F.Name := 'F_Add';
  F.Caption := 'Добавить новую запись';
  F.BorderStyle := bsDialog;
  cr_edit(10, 10, 1);
  cr_edit(10, 35, 2);
  cr_edit(10, 60, 3);
  cr_but(10, 130, 1, 'Ок');
  cr_but(90, 130, 2, 'Отмена');
  try
    F.ShowModal;
  finally
    F.Free;
  end;
end;

procedure TForm3.BitBtn1Click(Sender: TObject);
begin
  cr_form;
end;

procedure TForm3.Edit1Change(Sender: TObject);
begin
  Form3.ADOQuery1.Close;
  Form3.ADOQuery1.SQL.Clear;
  Form3.ADOQuery1.SQL.Add('SELECT * FROM sc_ship WHERE sc_ship.name_full LIKE '
    + CHR(39) + '%' + Form3.Edit1.Text + '%' + CHR(39));
  // Form3.ADOQuery1.Parameters.Refresh;
  // Form3.ADOQuery1.Parameters.ParseSQL(Form3.ADOQuery1.SQL.Text, True);
  // Form3.ADOQuery1.Parameters[0].Value:=Form3.Edit1.Text;
  Form3.ADOQuery1.Open;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  Form3.Caption := 'Справочник';
end;

end.


13-01-2012 01:31
>>>я переменную F объявил локально, а надо было глобально...
А вот тут поподробнее... Глобальные переменные вообще вещь ограниченного пользования, а как она к Вашей проблеме относится, если все в одном месте делается?

13-01-2012 01:20
получилось, спасибо...
я переменную F объявил локально, а надо было глобально...

13-01-2012 01:03
>>>не могли бы Вы кинуть примерчик?
А в посте 12-01-2012 12:15 вроде как он и был

13-01-2012 01:03
Покажите, что у Вас не выходит

13-01-2012 00:00
не выходит (
не могли бы Вы кинуть примерчик?

12-01-2012 12:15
>>> подскажите как сделать обработчик этих компонентов
Я так понял, что речь идет об обработчиках событий, так? Назначать обработчики так же как и задавать любое другое значение процедурного типа. Через оператор присваивания.

Свойство TButton.OnClick (а именно это свойство содержит обработчик данного события) имеет тип TNotifyEvent. Если Вы заглянете в хелп или исходнки VCL, то можете найти, что этот тип определяется следующим образом

type
  TNotifyEvent = procedure (Sender: TObject) of object;


То есть обработчиком можно назначить любой метод класса procedure с одним единственным параметром типа TObject.

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

type
  Form1 = class(TForm)
  // ...
  public
    procedure MyOnClickEvent(Sender: TObject);
  // ...
  end;


Тогда Вы можете написать, например, вот так:

  procedure cr_but(x, y, order: integer; Cap: string);
  var
    B: TButton;
  begin
    B := TButton.Create(F);
    try
      B.Parent := F;
      B.OnClick := F.MyOnClickEvent;
      // ...


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
"Мы с тобой одной крови — ты и я!". Чьи это заветные слова?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования