Конференция "Компоненты" » Если Owner не форма, то экземпляр не видно в окне «structure»
 
  • Kolan © (12.04.07 19:56) [0]
    Здравствуйте,
     Сделал компонент наследник TWinControl. Он может создовать объекты(Похоже на TPageControl).
    Создаются так:

    procedure TWizzardEditor.ExecuteVerb(Index: Integer);
    begin
     inherited;
     case Index of
       0:
       begin
         if Component is TCustomWizzard then
         begin
           (Component as TCustomWizzard).AddPage(Designer.UniqueName('WizzardPage'));
           Designer.Modified;
         end;
       end;
     end;
     
    end;

    function TCustomWizzard.AddPage(PageName: string): Integer;
    var
     TempPage: TCustomWizzardPage;
    begin
     TempPage := CreatePage;
     InitializePage(TempPage, PageName);
     Result := FPages.Add(TempPage);
    end;

    function TWizzard.CreatePage: TCustomWizzardPage;
    begin
     Result := TWizzardPage.Create(Self.Owner);
    end;



    Так вот если у созданых «страниц» Owner НЕ форма, то они не видны в окне «Structurte».
    Временно решил проблему так:

     Result := TWizzardPage.Create(Self.Owner);



    Вопросы:
    1. Почему если владелец НЕ форма их не видно?
    2. Как сделать правильно, тк мой вариант явно неправильный, тк
    Self.Owner

    невсегда форма?
  • homm © (13.04.07 05:24) [1]
    > TempPage := CreatePage;
    > InitializePage(TempPage, PageName);
    > Result := FPages.Add(TempPage);

    А почему плюем на ОПП, и пишем не так:

    TempPage := TWizzardPage.Create(Self.Owner);;
    TempPage.InitializePage(PageName);
    Result := FPages.Add(TempPage);

  • DimaBr © (13.04.07 08:53) [2]
    1. Потому что дизайнер формы их не видит.
    2.
    Result := Designer.CreateComponent(TCustomWizzardPage,Component,Left,Top,Width,Height);
    TCustomWizzardPage(Result).Wizzard := (Component as TCustomWizzard);


    А уж в SetWizard призвести добавление во внутренний список и инициализацию.
  • Kolan © (13.04.07 21:53) [3]
    > TempPage.InitializePage(PageName);

    С этим соглашусь.

    А с этим:
    TempPage := TWizzardPage.Create(Self.Owner);;


    Нет.

    Это что же мне всегда переписывать AddPage если надо создать наследника?
    Это кажись что-то вроде «фабрично метода»…

    >  DimaBr  ©   (13.04.07 08:53)


    Понятно, благодарю.
  • Kolan © (16.04.07 09:24) [4]
    TempPage := Designer.CreateComponent(TWizzardPage, Component, 0,0,0,0);


    Говорит:
    [Pascal Error] KSoftWareWizzardEditorUnit.pas(36): E2010 Incompatible types: 'TWizzardPage' and 'TComponent'



    Хотя:

    TWinControl
        ^
        |
    TCustomWizzardPage
        ^
        |
    TWizzardPage

  • DimaBr © (16.04.07 10:55) [5]

    TempPage := Designer.CreateComponent(TWizzardPage, Component, 0,0,0,0)  as  TWizzardPage;

  • DimaBr © (16.04.07 10:58) [6]

    var A: TControl;
        B: TComponent;
    begin
     B := A;
    //    но не наоборот
     A := B;  
    end;

  • Kolan © (16.04.07 11:15) [7]
    Блин, я думал он на это ругается :(.
    Designer.CreateComponent(TWizzardPage

    , Component, 0,0,0,0)

    Понятно…
  • Kolan © (16.04.07 11:22) [8]
    Угу, получилось.
    Теперь еще вопрос. Вот у меня значится на однм контроле лежат несколько других.
    И в окне «structure» соответственно дерево:
    Wizzard:
     WizzardPage1
     WizzardPage2
     WizzardPage3



    Вопрос какое событие происходит при нажатии на дочерние элементы?

    Это нужно для того чтобы все кроме выбранного скрыть, чтобы был виден только он…
  • DimaBr © (16.04.07 11:32) [9]
    Если вы говорите о дизайнере, то думаю можно попытаться отловить WM_SETFOCUS, но затея кажется глупая. Закройте окно «structure» и инспектор, и выберите потом другую панель !!!
  • Kolan © (16.04.07 11:36) [10]
    > но затея кажется глупая

    Ладно, вопрос. У меня вышел аналог TPageContol(по виду), но нет корешков. Как мен сделать возможность переключаться меж ними в дизанере. Те чтобы создать 3 штуки например, а потом накидать контролов?
  • DimaBr © (16.04.07 11:55) [11]
    Popup (Previous Page, Next Page)
  • Kolan © (16.04.07 12:04) [12]
    > Popup

    Дык это где должно быть? Механизм пказать/скрыть допустим есть. Но когда и кто будет вызывать?
  • DimaBr © (16.04.07 12:18) [13]

    > Как мен сделать возможность переключаться меж ними в дизанере.

    Кинте на форму TPageControl, нажмите над ним правой кнопкой мыши. Вот вам и Popup с сменой страниц
  • Kolan © (16.04.07 12:23) [14]
    А я понял. Соотв реализовать еще 2 «Verb'а»… Вроде понятно…
  • Kolan © (16.04.07 12:36) [15]
    Вот еще проблемма:
    В окре «структура» созданые TWizzardPage как-бы прозрачные. А если на них кинуть кнопку например, то получается, что кнопка лежит на форме, а не на TWizzardPage.
  • DimaBr © (16.04.07 12:40) [16]
    procedure TWizzardEditor.ExecuteVerb(Index: Integer);
    begin
    inherited;
    case Index of
      0://  Создание компонента
      1,2: begin // выбор панели
            TempPage := TWizzardPage(Component).GetNexPage(Index = 1);
            Designer.SelectComponent(TempPage);
       end;
    end;{case}
    end;



    Не забудьте, то при выборе из окон «structure» и инспектор панель тоже должна почвится.
  • DimaBr © (16.04.07 12:46) [17]
    Попробуйте перетащить кинутую кнопку за пределы панели. Если это вам удалось, значит она(кнопка) действительно лежит не на панели. Тогда очевидно что ваша панель не принимает контролы в дизайнере. Скорее всего поможет
    constructor TMyPanel.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    ControlStyle := ControlStyle + [csAcceptsControls]
    ...
    end;
  • Kolan © (16.04.07 12:52) [18]
    > DimaBr ©   (16.04.07 12:40)

    Сделал. Но это тут не прием. Когда я их только создаю, они(пиктограмки страниц в окне «структура») уже какбы прозрачные…
  • DimaBr © (16.04.07 12:55) [19]
    Может из-за этого

    ControlStyle := ControlStyle + [csAcceptsControls, csNoDesignVisible];
  • Kolan © (16.04.07 13:08) [20]
    > inherited Create(AOwner);
    > ControlStyle := ControlStyle + [csAcceptsControls]

    Да помогло. Но не все еще в порядке.

    Вот код PreviousPage:

    function TCustomWizzard.PreviousPage: TCustomWizzardPage;
    begin
     FCurrentPageIndex := FCurrentPageIndex — 1;
     if FCurrentPageIndex < 0 then
       FCurrentPageIndex := FPages.Count &#151; 1;
     ShowPage(FCurrentPageIndex);
     Result := FPages[FCurrentPageIndex];
    end;



    procedure TCustomWizzard.ShowPage(Index: Integer);
    var
     I: Integer;
    begin
     for I := 0 to FPages.Count &#151; 1 do
       if I = Index then
         FPages[I].Visible := True
       else
         FPages[I].Visible := False;
    end;



    Но оно не работает  так как я хочу. Те допустим есть 3 страницы.На второй кнопка. В окне «структура» она действительно на второй странице.
    Но когда я начинаю щелкать NextPage, то кнопка идна всегда. Те FPages[I].Visible несрабатывает что-ли…
    Или наоборот выбрана вкладка с кнопками, а их невидно…
    И все равно они какие-то прозрачные — странно.

    Скриншот:
    http://ksoftware.narod.ru/Struct.JPG
  • DimaBr © (16.04.07 13:24) [21]
    FPages[I].Visible прекрасно работает (но не в дизайнере) сделайте активной панели BringToFront
  • Kolan © (16.04.07 13:29) [22]
    Сделал, но не помогло.
    И если просто правой кнопкой нажать, то пункты BringToFront(стандартные) «звдизэйблены».
  • DimaBr © (16.04.07 13:36) [23]
    Не, вы не поняли.
    У главного компонента должно быть свойтсво - ActivePage, при установке которого становится активной выбранная панель.

    procedure TCustomWizzard.SetActivePage(APage: TCustomWizzardPages);
    begin
     if APage <> nil then
      if APage.Wizzard <> self then Exit;
     fActivePage := APage;    
     if fActivaPage <> nil then fActivaPage.BringToFront;
    end;


  • Kolan © (16.04.07 13:44) [24]
    Я сделал так. Смысл ессно разный, но работать имхо должно было и так…

    procedure TCustomWizzard.ShowPage(Index: Integer);
    var
     I: Integer;
    begin
     for I := 0 to FPages.Count &#151; 1 do
       if I = Index then
       begin
         if csDesigning in ComponentState then
           BringToFront
         else
           FPages[I].Visible := True
       end
       else
         FPages[I].Visible := False;
    end;



    У главного компонента должно быть свойтсво — ActivePage

    шас попробую…
  • DimaBr © (16.04.07 13:49) [25]

    if csDesigning in ComponentState then
         FPages[I].BringToFront
        else
          FPages[I].Visible := True

  • Kolan © (16.04.07 13:52) [26]
    Ура — работает…
  • DimaBr © (16.04.07 14:16) [27]
    Поздравляю !!!
  • Kolan © (16.04.07 14:20) [28]
    Блин криво получилось, ппц :). Ну хоть что-то — первый раз такое делаю :)
  • Kolan © (16.04.07 14:25) [29]
    Так, продалжаем разговор.
    В дизайнере еще рак-то рабоатет. А вот при запуске приложения получается что в FPage 0 станиц. Хотя в дизайнере они есть(NexPage работает нормально)… В чем может быть дело? Может их нао как-то сохранять…
  • DimaBr © (16.04.07 14:29) [30]

    > В чем может быть дело?

    Мне нравятся ваши вопросы. Дело может быть в чём угодно, я ж не провидец или телепат.
    Прежде всего вы должны добится чтобы при двойном Alt+F12 у вас небыло никаких ошибок, и всё было на своих местах.
    Скорее всего вы не разобрались с GetChildren.
  • Kolan © (16.04.07 14:30) [31]
    > Скорее всего вы не разобрались с GetChildren.

    Я даже незнаю что это :(


    > Alt+F12

    Это что за функция?
  • Kolan © (16.04.07 14:36) [32]
    > GetChildren

    Так его надо перекрыть? А как? Те что писать?
  • DimaBr © (16.04.07 14:50) [33]
    Alt+F12 - это комбинация клавиш на клавиатуре (Кнопочка ALT находится с боков от пробела - такая длинная клавиша, а F12 в конце верхнего ряда)

    Нажмите два раза это сочетание при выделенной форме. В первый раз форма перейдёт в режим текста, во второй раз обратно. Если всё останется на своих местах - вы Гений (обычно куча ошибок).
    В режиме такста ваш котнрол должен имет приблизительно такой вид

    object Wizard1: TCustomWizzard
       Left = 80
       Top = 24
       Width = 289
       Height = 193
       ActivePage = Page1
       object Page1: TCustomWizzardPage
           ........
       end
     end



    то есть страница находится внутри компонента
  • Kolan © (16.04.07 14:57) [34]
    > Alt+F12 — это комбинация клавиш на клавиатуре

    Что то нажимаю я эти «кнопочки» — вообще нихрена :) Мож в BDS другое сочетание?
  • {RASkov} (16.04.07 15:00) [35]
    > [34] Kolan ©   (16.04.07 14:57)

    Попробуй по форме правой кнопкой мыши>View as Text, затем в редакторе правой> View as Form....
  • Kolan © (16.04.07 15:09) [36]
    Угу, по виду тоже самое осталось, но стал ругаться так же как и ран тайме (List out of bounds 0). Те скорее всего в FPages ниче нет сейчас. Наверно как-то сохранять/загружать надо…, как?
  • DimaBr © (16.04.07 15:24) [37]
    Наверно так [2]
  • Kolan © (16.04.07 15:31) [38]
    > Наверно так [2]

    Так я делаю:
    procedure TWizzardEditor.ExecuteVerb(Index: Integer);
    var
     TempPage: TCustomWizzardPage;
    begin
     inherited;
     case Index of
       0:
       begin
         if Component is TWizzard then
         begin
           TempPage := Designer.CreateComponent(TWizzardPage, Component, 0,0,0,0) as TWizzardPage;
           TWizzardPage(TempPage).Wizzard := (Component as TWizzard);
           Designer.Modified;

         end;
       end;

  • Kolan © (16.04.07 15:34) [39]
    Но если я переключюсь текст/форма, то в дизайнере страницы есть, а вот FPages их нет…
  • DimaBr © (16.04.07 15:50) [40]
    Вы невнимательно прочитали [2], особенно в конце. Что происходит в методе TWizzardPage.SetWizard ???
  • Kolan © (16.04.07 15:51) [41]
    procedure TCustomWizzardPage.SetWizzard(const Value: TCustomWizzard);
    begin
     if FWizzard <> nil then
     begin
       FWizzard.DeletePage(Self);
     end;
     FWizzard := Value;
     FWizzard.AddPage(Self);
    end;

  • DimaBr © (16.04.07 15:59) [42]
    Ок, по аналогии так же ???

    procedure TTabSheet.ReadState(Reader: TReader);
    begin
     inherited ReadState(Reader);
     if Reader.Parent is TPageControl then
       PageControl := TPageControl(Reader.Parent);
    end;

  • Kolan © (16.04.07 16:06) [43]
    > Ок, по аналогии так же ???

    Черт, нихрена не понял. Объяснишь — справку читаю…
  • DimaBr © (16.04.07 16:11) [44]
    Метод ReadState вызывается в момент чтения компонента из ресурса, его нужно переопределить и произвести присвоение (заодно и добавление в список)  FWizzard.

    procedure TCustomWizzardPage.ReadState(Reader: TReader);
    begin
    inherited ReadState(Reader);
    if Reader.Parent is TCustomWizzard then
      Wizard := TCustomWizzard(Reader.Parent);
    end;

  • Kolan © (16.04.07 16:19) [45]
    То же самое, главное непонятно как все это отлаживать :(
  • DimaBr © (16.04.07 16:24) [46]
    Переключитесь на Текст, поставьте брейк в ReadState и запускайте.
    Надеюсь вы в описании сделали так

    TCustomWizzardPage = class()
     protected
       procedure ReadState(Reader: TReader);override;
    end;
  • Kolan © (16.04.07 16:29) [47]
    Надеюсь вы в описании сделали так


     strict protected
       procedure ReadState(Reader: TReader);  


    Вроде да.


    > Переключитесь на Текст, поставьте брейк в ReadState и запускайте.

    На точке не остановилось. Причем не важно текст или не текст.
  • Kolan © (16.04.07 16:30) [48]
    Ой, стоп
  • Kolan © (16.04.07 16:37) [49]
    Так это получилось.
    Еще:
    Где тот момент когда все уже загружено. При создании Wizzarda я написал такой код:

    constructor TCustomWizzard.Create(AOwner: TComponent);
    begin
     inherited Create(AOwner);
     FPages := TWizzardPageList.Create;
     FCurrentPageIndex := 0;
     if (not (csDesigning in ComponentState)) and (FPages.Count > 0) then
       FPages[0].Show(nil);
    end;



    Но страницы еще не загрузились, и FPages.Count = 0. А мне нужно показать 0-ую.

    Хотя в принципе работает…
  • DimaBr © (16.04.07 16:40) [50]
    procedure TCustomWizzard.Loaded;override;
    begin
     CurrentPageIndex := 0;
    end;

  • DimaBr © (16.04.07 16:52) [51]
    procedure TCustomWizzard.Loaded;override;
    begin
     inherited Loaded;
    CurrentPageIndex := 0;
    end;

  • Kolan © (16.04.07 16:58) [52]
    Угу. Вот еще что: Почемуте, по всей видимосте в FPages страницы не в том порядке в коком они отображены в окне «структура». Те Вторя по счету в FPages — 0. И сдледовательно ноказывается не то что нужно…
  • Kolan © (16.04.07 16:59) [53]
    > DimaBr ©   (16.04.07 16:52)

    Смысл я понял…
  • DimaBr © (16.04.07 17:02) [54]
    Потому что они сохраняются в ресур в порядке расположения на форме, для изменения порядка сделай так

    procedure TPageControl.GetChildren(Proc: TGetChildProc; Root: TComponent);
    var  I: Integer;
    begin
     for I := 0 to FPages.Count - 1 do Proc(TComponent(FPages[I]));
    end;


    Ни в коем случае не нужен Inherited

    Пока, до завтра !!!
  • Kolan © (16.04.07 17:18) [55]
    Пока, до завтра !!!

    Ок :)

    Теперь выходит 0 — это последняя. Пошет downto?
  • Kolan © (16.04.07 17:24) [56]
    > Пошет

    Может.
  • DimaBr © (17.04.07 08:49) [57]
    Да нет, всё должно быть нормально. Переключитесь на текст, отредактируйте DFM-ку (выставите страницы в нужном порядке), переключитесь на форму.
  • имя (27.03.09 01:15) [58]
    Удалено модератором
  • имя (27.03.09 01:15) [59]
    Удалено модератором
 
Конференция "Компоненты" » Если Owner не форма, то экземпляр не видно в окне «structure»
Есть новые Нет новых   [134466   +3][b:0][p:0.004]