Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
ВнизДинамическая форма в библиотечном модуле Найти похожие ветки
← →
msguns © (2005-07-21 13:53) [0]В продолжение ветки
http://delphimaster.net/view/1-1121773434/
Все же я пришел к выводу, что в библиотечном модуле целесообразно объявить класс формы, которую надо создавать и показывать при обращении к соответстующим процедурам/функциям библиотечного модуля. Там же прописывать все визуальные объекты и, главное, методы и евенты контролов. В этом случае я могу обращаться из этих методов друг к другу как к методам класса.
Например, в событии OnChange эдита легко можно активировать/деактивировать соотв.кнопки, по OnClick в листбоксе запросто вызвать метод поиска записи в датасете внешнего модуля, продеклариованный и описанный в этом же классе. Кроме того, становятся отовсюду доступны переменные как самой формы, так и всех "подотчетных" и продекларированных в ней контролов.
При реализации подобных действий способом из приведенной ссылки ("надув" компиллятора по рецепту ЮЗ) чрезвычайно геморный. Текст получается громоздкий и плохочитаемый.
Подчеркну, что имеется в виду не форма типа MessageBox, а достаточно "нагруженное" окно, предназначенное для универсального поиска юзером записей в произвольных датасетах (6 контролов типа чекбокс, едит, комбобокс, листбокс, несколько кнопок, куча лабелей. И все это лежит на "наполеоне" из панелей.
Прошу высказаться за либо против принятого мною решения.
С благодарностью.
← →
Stakan © (2005-07-21 14:41) [1]Я уже высказывался за такой подход в той ветке.
Всё получается красиво и никаких недокументированных приёмов.
← →
msguns © (2005-07-21 15:00) [2]>Stakan © (21.07.05 14:41) [1]
Т.е. "ЗА" ?
ЗЫ. Извиняюсь, что ветка попала в "Базы". ИМХО, было бы неплохо пересадить ее в "Основную"
← →
evvcom © (2005-07-21 15:06) [3]Возможно, что проще действительно создать класс формы. Я прибегаю к способу [5] из той ветки действительно в крайних случаях. Например, в последнем проекте:
В конструктор динамически создаваемой формы передается массив записей с типами и свойствами создаваемых на форме контролов. Для некоторых контролов важны дополнительные параметры из "его" записи. Вот ссылку на эту запись я и передаю через параметр Data в обработчик-процедуру. Получается в процедуре все очень наглядно, так как и имена и типы такие, какие мне удобны. Можно, конечно, то же самое сделать и через метод класса, а параметр через Tag передать, хотя тоже не в каждом объекте этот Tag имеется.
← →
msguns © (2005-07-21 16:18) [4]Прошу сильно не смеяться, я такого не делал еще, а Тексейры под рукой нет.
Код:unit DBServ; // Библиотечный модуль
interface
Uses Forms, Classes, Controls, StdCtrls, ComCtrls, ExtCtrls, Graphics,
Buttons, DB, Grids, Types, DBGrids, Dialogs;
type
TDBServ_SearchDlgForm = class(TForm)
// Контролы, которые должны быть созданы формой
pnUserTop: TPanel; // Панель пользователя
lbColumnName: TLabel;
cmbColumnList: TComboBox;
lbPromptEnter: TLabel;
edSample: TEdit;
pnSearchOptions: TPanel; // Панель опций поиска
lbSearchMode: TLabel;
rbtSearchImdl: TRadioButton;
rbtSearchFirst: TRadioButton;
rbtSearchList: TRadioButton;
lbSearchOptions: TLabel;
chbSearchCaseIns: TCheckBox;
lbSearchResume: TLabel;
spbStartSearch: TSpeedButton;
spbCloseForm: TSpeedButton;
pnFindResult: TPanel; // Панель результатов спискового поиска
lbFindResult: TLabel;
lsbFindList: TListBox;
pnListStatus: TPanel;
private
public
// constructor Create(AOwner: TComponent);
// procedure FormShow(Sender: TObject);
end;
...
type
procedure DBServ_SearchRecordByUserDialog(Grid: TDBGrid);
...
implementation
...
procedure DBServ_SearchRecordByUserDialog(Grid: TDBGrid);
begin
with TDBServ_SearchDlgForm.Create(Application) do
begin
ShowMessage("Форма создана") ;
// ShowModal;
end;
end;
При обращении к этой процедуре дохнет с сообщением о невозможности найти файл ресурсов.
Ради Бога, побейте ногами !
← →
msguns © (2005-07-21 16:23) [5]Теоретически я понимаю, что дельфя пытается создать на форме контролы, свойства которых (парент, местоположение и т.д.) должны находиться в .res. Но у меня и вся фишка в том, что нет и не может быть файла ресурсов ! Закомментарив все эти контролы и оставив только саму форму, получил тот же эффект.
← →
alex_*** (2005-07-21 16:29) [6]честно говоря нет времени читать всю ветку по ссылке, но нельзя ли тогда все контролы создавать руками в runtime без файла ресурсов и руками же вешать события на них? если уж так хочется чтоб все было настраиваемое
← →
evvcom © (2005-07-21 16:34) [7]
> При обращении к этой процедуре дохнет с сообщением о невозможности
> найти файл ресурсов.
Правильно дохнет. У тебя исходники VCL есть? Если бы туда заглянул, то увидел бы, что в TCustomForm.Create есть такое:
if not InitInheritedComponent(Self, TForm) then
raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
в InitInheritedComponent вызывается InternalReadComponentRes до тех пор пока не дойдет до RootAncestor = TForm.
Либо создавай форму с ресурсами, либо наследуйся от TObject, например, и заведи поле класса TForm.
← →
msguns © (2005-07-21 16:35) [8]>alex_*** (21.07.05 16:29) [6]
Да я так и делаю сейчас. Только вот код страшный:procedure DBServ_SearchRecordByUserDialog(Grid: TDBGrid);
// Создание окна поискового диалога
Const
MinHeight: integer = 320;
MinWidth: integer = 360;
var
i: integer;
SearchForm: TForm;
SamplePanel,SearchPanel,SearchOptionPanel,FindListPanel: TPanel;
LablPromptCol,SampleLabel,OptTitle1Label,OptTitle2Label,ListTitleLabel: TLabel;
ColumnList: TComboBox;
ListFind: TListBox;
ListStatus: TPanel;
OptRadioImdl, OptRadioFirst, OptRadioList: TRadioButton;
OptCheckCase, OptCheckPartial: TCheckBox;
SampleEdit: TEdit;
GridActiveCell: TRect;
MColChange, MEditChange: TMethod;
MRadioButtonClick: TMethod;
//---------------------------------------------------------------
// Обработчики событий динамически созданных визуальных контролов
//---------------------------------------------------------------
procedure OnChangeColumn(Self: TDBGrid; Sender: TObject);
var
i: integer;
begin
// Определить имя поля датасета по титулу выбранной колонки
with Self, Sender as TComboBox do
for i := 0 to Self.Columns.Count-1 do
if (Self.Columns[i].Field.FieldKind=fkData) and
(Self.Columns[i].Title.Caption=Items[Itemindex]) then
begin
// Сделать выбранную колонку текущей в гриде
SelectedIndex := i;
break;
end;
end;
//---------------------------------------------------------------
procedure OnChangeSample(Self: TDBGrid; Sender: TObject);
begin
if TEdit(Sender).Tag>0 then exit;
with Self do
DBServ_LocateRecord(DataSource.DataSet,SelectedField.FieldName,TEdit(Sender).Text);
end;
//---------------------------------------------------------------
procedure OnClickRadioButton(Self: TEdit; Sender: TObject);
begin
if TRadioButton(Sender).Caption="Немедленный поиск" then Self.Tag := 0 else Self.Tag := 1;
end;
begin
// with TDBServ_SearchDlgForm.Create(Application) do
// begin
// ShowMessage("Форма создана") ;
// ShowModal;
// end;
// exit;
MColChange.Code := @OnChangeColumn;
MColChange.Data := Grid;
MEditChange.Code := @OnChangeSample;
MEditChange.Data := Grid;
MRadioButtonClick.Code := @OnClickRadioButton;
// ******************* СОЗДАНИЕ ВИЗУАЛЬНЫХ КОНРОЛОВ ******************
// Получить координаты ячейки
GridActiveCell := TDBGridCrack(Grid).CellRect(TDBGridCrack(Grid).Col,TDBGridCrack(Grid).Row);
// Создать форму
SearchForm := TForm.Create(Grid.Owner);
with SearchForm do
begin
BorderIcons := [biSystemMenu];
BorderStyle := bsSingle;
Height := MinHeight; // 200
Width := MinWidth; // 360
// Позиционировать форму
if (Grid.ClientOrigin.X+GridActiveCell.Right+MinWidth)>(TForm(Grid.Owner).Left+TForm(Grid.Owner).Width) then
// Слева от ячейки
Left := Grid.ClientOrigin.X+GridActiveCell.Left-MinWidth
else
Left := Grid.ClientOrigin.X+GridActiveCell.Right;
Top := TForm(Grid.Owner).Top+TForm(Grid.Owner).Height div 2 - Height div 2;
Caption := "Поиск записей по значению колонки";
end;
// Создать панель пользователя
SamplePanel := TPanel.Create(SearchForm);
with SamplePanel do
begin
Parent := SearchForm; Align := alTop; BevelOuter := bvLowered; Height := 48;
end;
LablPromptCol := TLabel.Create(SearchForm);
with LablPromptCol do
begin
Caption := "Поиск по колонке ";
Left := 4;
Top := 6;
Parent := SamplePanel;
end;
// Создать комбобокс для списка колонок
ColumnList := TCombobox.Create(SearchForm);
with ColumnList do
begin
Top := 2;
Parent := SamplePanel;
Left := LablPromptCol.Left+LablPromptCol.Width+4;
Width := MinWidth-Left-10;
Sorted := false;
// Заполнить список названиями колонок
for i := 0 to Grid.Columns.Count-1 do
if Grid.Columns[i].Field.FieldKind=fkData then
begin
Items.Add(Grid.Columns[i].Title.Caption);
if Grid.Columns[i].Field=Grid.SelectedField then
ItemIndex := i; // Текущее поле
end;
OnChange := TNotifyEvent(MColChange);
end;
← →
msguns © (2005-07-21 16:37) [9]
// Создать надпись перед шаблоном
SampleLabel := TLabel.Create(SearchForm);
with SampleLabel do
begin
Caption := "Маска поиска "; Left := 4; Parent := SamplePanel;
end;
// Создать эдит для ввода шаблона поиска
SampleEdit := TEdit.Create(SearchForm);
with SampleEdit do
begin
Top := ColumnList.Top+ColumnList.Height+1;
Left := SampleLabel.Left+SampleLabel.Width+4;
Width := MinWidth-Left-10;
Text := Grid.SelectedField.AsString;
OnChange := TNotifyEvent(MEditChange);
Parent := SamplePanel;
end;
MRadioButtonClick.Data := SampleEdit;
// Выровнять метку по высоте
SampleLabel.Top := SampleEdit.Top+3; //(ColumnList.Top-LablPromptCol.Top);
// Создать панель поиска
SearchPanel := TPanel.Create(SearchForm);
with SearchPanel do
begin
Parent := SearchForm; Align := alClient; BevelOuter := bvLowered;
end;
// Создать панель опций поиска
SearchOptionPanel := TPanel.Create(SearchForm);
with SearchOptionPanel do
begin
Parent := SearchPanel; Align := alLeft; BevelOuter := bvRaised; Width := 160;
end;
// Создать заголовок режимов
OptTitle1Label := TLabel.Create(SearchForm);
with OptTitle1Label do
begin
Caption := "Режимы поиска"; Parent := SearchOptionPanel;
Font.Style := [fsbold]; Height := 20; //Layout := tlBottom;
Align := alTop; Alignment := taCenter; Layout := tlCenter;
end;
// Создать радиобатоны переключения режимов поиска
OptRadioImdl := TRadioButton.Create(SearchForm);
OptRadioFirst := TRadioButton.Create(SearchForm);
OptRadioList := TRadioButton.Create(SearchForm);
with OptRadioImdl do
begin
Caption := "Немедленный поиск"; Parent := SearchOptionPanel;
Left := 4; Width := TPanel(Parent).Width-Left-4;
Top := OptTitle1Label.Top+OptTitle1Label.Height+2; Checked := true;
OnClick := TNotifyEvent(MRadioButtonClick);
end;
with OptRadioFirst do
begin
Caption := "Поиск первой похожей"; Parent := SearchOptionPanel;
Left := OptRadioImdl.Left; Width := OptRadioImdl.Width;
Top := OptRadioImdl.Top+OptRadioImdl.Height+2; // Checked := false;
OnClick := TNotifyEvent(MRadioButtonClick);
end;
with OptRadioList do
begin
Caption := "Поиск всех похожих"; Parent := SearchOptionPanel;
Left := OptRadioImdl.Left; Width := OptRadioImdl.Width;
Top := OptRadioFirst.Top+OptRadioFirst.Height+2; // Checked := false;
OnClick := TNotifyEvent(MRadioButtonClick);
end;
// Создать заголовок опций
OptTitle2Label := TLabel.Create(SearchForm);
with OptTitle2Label do
begin
Caption := "Опции поиска"; Parent := SearchOptionPanel;
Font.Style := [fsbold];
Left := 2; Width := TPanel(Parent).Width-4;
Top := OptRadioList.Top+OptRadioList.Height+8;
Alignment := taCenter;
end;
← →
msguns © (2005-07-21 16:38) [10]
// Создать чекбоксы опций
OptCheckCase := TCheckBox.Create(SearchForm);
OptCheckPartial := TCheckBox.Create(SearchForm);
with OptCheckCase do
begin
Caption := "Игнорировать регистр"; Parent := SearchOptionPanel;
Top := OptTitle2Label.Top+OptTitle2Label.Height+2;
Left := 6; Width := TPanel(Parent).Width-8;
Checked := true;
end;
with OptCheckPartial do
begin
Caption := "Полное совпадение"; Parent := SearchOptionPanel;
Top := OptCheckCase.Top+OptCheckCase.Height+2;
Left := 6; Width := TPanel(Parent).Width-8;
Checked := true;
end;
// Создать панель со списком найденных
FindListPanel := TPanel.Create(SearchForm);
with FindListPanel do
begin
Parent := SearchPanel; Align := alClient; BevelOuter := bvRaised;
end;
// Создать надпись
ListTitleLabel := TLabel.Create(SearchForm);
with ListTitleLabel do
begin
Caption := "Результат поиска"; Parent := FindListPanel;
Font := OptTitle1Label.Font; Align := alTop; Height := OptTitle1Label.Height;
Alignment := OptTitle1Label.Alignment;
Layout := OptTitle1Label.Layout;
end;
// Создать панель статуса
ListStatus := TPanel.Create(SearchForm);
with ListStatus do
begin
Parent := FindListPanel; Align := alBottom;
Height := 18; BevelOuter := bvLowered;
Alignment := taCenter; Caption := " Запись 2 из 9999";
end;
// Создать список найденных
ListFind := TListBox.Create(SearchForm);
with ListFind do
begin
Parent := FindListPanel; Align := alClient;
Color := TPanel(Parent).Color;
end;
SearchForm.ShowModal;
end;
function DBServ_LocateRecord(DataSet: TDataSet; FieldName,Sample: string;
CaseIns: boolean = true; PartKey: boolean = true): boolean;
begin
result := DataSet.Locate(FieldName,Sample,[loCaseInsensitive,loPartialKey]);
end;
← →
msguns © (2005-07-21 16:40) [11]Кроме того, непонятки с тем, как мне в процедурах - обработчиках событий обращаться к другим (не Sender`у) контролам и, главное, как выполнить процедуры, определенные внутри DBServ_SearchRecordByUserDialog
← →
evvcom © (2005-07-21 16:47) [12]
> procedure OnChangeColumn(Self: TDBGrid; Sender: TObject);
> var
> i: integer;
> begin
> // Определить имя поля датасета по титулу выбранной
> колонки
> with Self, Sender as TComboBox do
> for i := 0 to Self.Columns.Count-1 do
...
> =Items[Itemindex])
Ты опять "не читатель", ты опять "писатель"? Я ж писал тебе в той еще ветке. Замени, ведь нагляднее будет так:
procedure OnChangeColumn(DBGrid: TDBGrid; ComboBox: TComboBox);
...
for i := 0 to DBGrid.Columns.Count-1 do
...
= ComboBox.Items[ComboBox.Itemindex])
и мой совет, прекращай with использовать, код с ним менее читабелен, а отладка затруднительна. Вместо with Object1.Object2.Object3 лучше завести локальную переменную и явно ей присвоить эту байду, а потом к свойствам/методам обращаться уже через нее.
← →
evvcom © (2005-07-21 16:52) [13]Во, напостил! Одного я не пойму, чего тебе так обычная форма с ресурсом не нравится? Политические убеждения или вера не позволяет?
← →
msguns © (2005-07-21 17:00) [14]>evvcom © (21.07.05 16:52) [13]
>Одного я не пойму, чего тебе так обычная форма с ресурсом не нравится? Политические убеждения или вера не позволяет?
Это фрагмент библиотечного модуля, содержащего универсальные фичи работы с произвольным НД. К нему я буду обращаться из конкретных приложений с помощью uses.
Какие в нем могут быть ресурсы и формы ?
Работает же OpenDialog безо всяких визуальных компонент, самодостаточно.
← →
stakan © (2005-07-21 17:03) [15]
unit FormUnit;
interface
procedure ShowUnitForm;
implementation
uses
Forms, StdCtrls, Dialogs, Classes, Windows;
type
TUnitForm = class(TForm)
private
Button: TButton;
procedure ButtonClick(Sender: TObject);
public
constructor CreateNew(AOwner: TComponent); reintroduce;
end;
procedure ShowUnitForm;
var
Form: TUnitForm;
begin
Form := TUnitForm.CreateNew(Application);
try
Form.Button := TButton.Create(Form);
Form.Button.Parent := Form;
Form.Button.OnClick := Form.ButtonClick;
Form.ShowModal;
finally
Form.Free;
end;
end;
{ TUnitForm }
procedure TUnitForm.ButtonClick(Sender: TObject);
begin
ShowMessage("Banzai");
end;
constructor TUnitForm.CreateNew(AOwner: TComponent);
var
NonClientMetrics: TNonClientMetrics;
begin
inherited CreateNew(AOwner);
NonClientMetrics.cbSize := sizeof(NonClientMetrics);
if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then
Font.Handle := CreateFontIndirect(NonClientMetrics.lfMessageFont);
end;
end.
Подсмотрено в Dialogs.pas
← →
Stakan © (2005-07-21 17:07) [16]
>public
> constructor CreateNew(AOwner: TComponent);
> reintroduce;
Лишнее.
Главное - это Form := TUnitForm.CreateNew(Application);
← →
evvcom © (2005-07-22 08:23) [17]
> Какие в нем могут быть ресурсы и формы ?
Обычные. Чем тебе ресурсы-то не нравятся? Ну будет у тебя не один юнит, а dfm-ка еще с ним, чего плохого?
> Работает же OpenDialog безо всяких визуальных компонент,
> самодостаточно.
OpenDialog, насколько я помню, просто надстройка над API-шной функцией, чтобы параметры передать в стиле Delphi.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.012 c