Текущий архив: 2005.07.11;
Скачать: CL | DM;
ВнизComboBox с выпадающей формой TForm Найти похожие ветки
← →
AlexGreG (2004-06-25 09:17) [0]Привет программистам.
Сделал компоненту "комбо-бокс с выпадающей формой"
Но проблема в публикации свойства DropDownForm:
property DropDownForm: TForm read FDropDownForm write SetDropDownForm;
При открытии в Инспекторе объектов списка доступных форм, отображаются все подключенные формы к модулю, в котором компонента расположена. Так и должно быть. Но при выборе какой либо формы, Дельфи ругается, мол Invalid property value.
Бросаю это дело (установку свойства в инспекторе объектов) и пытаюсь установить свойство
в run-time. Успешно. И работает всё как задумал (выпадает форма и прячется когда надо).
В чём подвох? Никак не могу разобраться.
Подскажите, в каком направлении искать ответ и решение.
Если можно, на почту киньте весточку AlexGreG@Yandex.ru
← →
wisekaa © (2004-06-25 12:01) [1]Посмотри как реализован TCheckListEdit у фирмы TMS, входит в компелек TMS Edits
← →
dm © (2004-06-25 12:09) [2]
unit CustomEdit22;
interface
uses Types, Windows, Messages, Graphics,
SysUtils, Classes, Controls, StdCtrls, forms, Dialogs;
type
TCustomEdit22 = class(TCustomEdit)
private
FDropDownForm: TForm;
procedure SetDropDownForm(const Value: TForm);
protected
public
constructor Create(aOwner:TComponent); override;
destructor Destroy; override;
procedure DropDown;
procedure CloseUp;
published
property DropDownForm: TForm read FDropDownForm write SetDropDownForm;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents("CustComp", [TCustomEdit22]);
end;
{ TCustomEdit22 }
procedure TCustomEdit22.CloseUp;
begin
if Assigned(FDropDownForm) then
FDropDownForm.Hide;
end;
constructor TCustomEdit22.Create(aOwner: TComponent);
begin
inherited;
end;
destructor TCustomEdit22.Destroy;
begin
if Assigned(DropDownForm)then DropDownForm.Free;
inherited;
end;
procedure TCustomEdit22.DropDown;
var
P: TPoint;
Y: Integer;
begin
P := Parent.ClientToScreen(Point(Left,Top));
Y := P.Y + Height;
if Y + DropDownForm.Height > Screen.Height then Y := P.Y - DropDownForm.Height;
DropDownForm.top:=y;
DropDownForm.left:=p.x;
DropDownForm.Show;
end;
procedure TCustomEdit22.SetDropDownForm(const Value: TForm);
begin
if Assigned(value)and (not Assigned(FDropDownForm))
then begin
FDropDownForm:=Value.CreateNew(self);
FDropDownForm.Name:=name+"_ddf";
FDropDownForm.Color:= clBtnFace;
end;
end;
end
← →
wisekaa © (2004-06-25 15:42) [3]
> procedure TCustomEdit22.SetDropDownForm(const Value: TForm);
> begin
> if Assigned(value)and (not Assigned(FDropDownForm))
> then begin
> FDropDownForm:=Value.CreateNew(self);
> FDropDownForm.Name:=name+"_ddf";
> FDropDownForm.Color:= clBtnFace;
> end;
> end;
Твоя ошибка в этом куске кода!
← →
Юрий Зотов © (2004-06-25 17:42) [4]> dm © (25.06.04 12:09) [2]
procedure TCustomEdit22.SetDropDownForm(const Value: TForm);
begin
...
FDropDownForm := Value.CreateNew(self);
То есть, Вы вызываете конструктор через ссылку на ЭКЗЕМПЛЯР класса, а не на САМ класс. Такой вызов нового объекта не создает.
В свойстве нужно хранить КЛАСС формы, а не ссылку на ее экземпляр. И хранить этот класс можно в строковом виде. То есть, получится примерно следующее (все не имеющее прямого отношения к сабжу опущено):
type
TCustomEdit22 = class(TCustomEdit)
private
FDropDownForm: TForm;
function GetDropDownForm: string;
procedure SetDropDownForm(const Value: string);
...
published
property DropDownForm: string
read GetDropDownForm write SetDropDownForm;
end;
function TCustomEdit22.GetDropDownForm: string;
begin
if FDropDownForm = nil then
Result := ""
else
Result := FDropDownForm.ClassName
end;
procedure TCustomEdit22.SetDropDownForm(const Value: string);
var
AClass: TClass;
begin
if not SameText(DropDownForm, Value) then
if Value <> "" then
begin
AClass := FindClass(Value);
if not AClass.InheritsFrom(TForm) then
raise Exception.Create(...);
if FDropDownForm <> nil then
FDropDownForm.Free;
FDropDownForm := TFormClass(AClass).Create(Self)
end
else
if FDropDownForm <> nil then
FreeAndNil(FDropDownForm)
end;
Естественно, все классы возможных DropDown-форм должны быть зарегистрированы (cм. RegisterClasses) и должны находиться в design-time пакете, а для свойства DropDownForm потребуется собственный редактор (чтобы отображать имена этих классов в выпадающем списке).
← →
Petr V. Abramov © (2004-06-25 17:52) [5]> должны находиться в design-time пакете,
может, имелось в виду в run-time пакете???
← →
Anatoly Podgoretsky © (2004-06-25 17:58) [6]Petr V. Abramov © (25.06.04 17:52) [5]
в run-time инспектор объектов отсутвует
← →
wisekaa © (2004-06-25 19:02) [7]
> Юрий Зотов ©
А вообще в принципе это возможно, из общения в чате я понял, что человек хочет сделать компонет Edit+Button(or DropDown) причем на действие повесить вывод, сделанной произвольной формы в дизайнере, а не заранее подготовленных в копоненте?
← →
Колбасьев (2004-06-25 21:36) [8]Попутный вопрос к AlexGreG (и остальным):
Когда Ваша форма (DropDownForm) открывается, то загоровок родительского окна сереет (т.е. окно становиться неактивным)? У меня - да (сделал компонент - PopUpWindow - окно всплавает по команде PopUp обычно прописанной в OnClick кнопок и т.п.) что выглядит непривычно (сильно непривычно), так как при открытии выпадающей части ComboBox, меню и т.п. такого не наблюдается.
И как от этого избавиться? (В справке вообще сказано, что нельзя установить (и это так) стиль POPUP и CHILD одновременно)
← →
Petr V. Abramov © (2004-06-26 15:30) [9]> Anatoly Podgoretsky © (25.06.04 17:58) [6]
> в run-time инспектор объектов отсутвует
Ну и что, да зачем он вообще нужен? :)
Получится, что за приложением юзеру придется тащить design-time пакет, что не есть хорошо.
Design-time пакет может (и должен) содержать только редакторы св-в и все, что с ними связано, и в requies содержать runtime пакет.
Только не говори, что ты все это не знал :)
← →
GrayFace © (2004-06-27 08:04) [10]А зачем
FDropDownForm := Value.CreateNew(self);
, ссылкф на класс? Ведь отделить так созданную форму от изначальной все-равно не получится, ведь var"ы принадлежат классу.
В SetDropDownForm еще в вашем случае надо удалять старый объект.
Колбасьев
>И как от этого избавиться? (В справке вообще сказано, что нельзя установить (и это так) стиль POPUP и CHILD одновременно)
А зачем тебе WS_POPUP?... Че он вообще дает?
← →
Колбасьев © (2004-06-27 13:06) [11]>> FDropDownForm:=Value.CreateNew(self);
Чушь какая-то! И дело даже не в Value. Когда устанавливается новая форма, надо просто хранить ссылку на нее, а не создавать новую.
То есть что получается: есть у меня две формы. На одной компонент. Беру я и выбираю в свойстве вторую форму, и тогда создается третья, пустая, в памяти... Зачем????
Если я что-то пропустил или не понял... объясните :-\]]
>>А зачем тебе WS_POPUP?... Че он вообще дает?
Процедурой (ф-ей) SetWindowLong с этим параметром устанавливаю стиль окна. Кажеться, зачем надо так делать, если есть св-во BorderStyle. Например, вот зачем: когда ставишь bsNone и Caption := "" и Height := CleintHeight, то у формы нет краев и заголовка. А если установить стиль WS_BORDER (и др. аналогичные значения, просто эффект будет немного другой), то не будит заголовка, но будет рамка вокруг окна. Причем она не считается клиентской областью, что может дать удобство, например при размещении компонентов на ней (они не "налезут" на нарисованную вручную рамку (если вы рисовали ее)).
Но, вы наверное это уже знаете ;-)
← →
dm © (2004-06-28 12:04) [12]Сейчас у меня есть рабочий вариант обсуждаемой компоненты, при настройке которой просто указываю имя класса формы, которая будет выпадать.
Недостаток в том, что я не могу устанавливать свойства этой формы, как, например, при настрйке грида я могу устанавливать свойства датасета, а при настройке датасета - могу настраивать подключение к БД.
Вопрос в том, что необходимо сделать для решения этой задачи?
Ещё есть идея с фреймом поэкспериментировать. Но пока не добрался до него.
← →
RagE © (2004-07-02 16:56) [13]Народ обьясните мне почему нельзя сделать так
FDropDownForm := Value;
Страницы: 1 вся ветка
Текущий архив: 2005.07.11;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.044 c