|
|
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Иногда бывает полезно знать некие "недокументированные" или же "плохо описанные" возможности того инструмента, на котором работаешь. Как человек, который знаком с PB совершенно недавно (к тому же плохо знает английский и не имеет столько свободного времени для рытья в англоязычных ресурсах в интернете), мне было бы интересно собрать копилку таких полезных решений, скрытых в недрах PB. Предлагаю в данный топик писать и обсуждать все интересное и секретное по PB, думаю проффы смогут размяться, а новичкам не надо будет набивать себе шишки. P.S. Желательно при описании решения ссылаться на номер версии PB. Итак открою копилку и перечислю все то странное и интересное, с чем мне пришлось столкнуться с PB в результате его освоения. Версия PB 9.01 Build 6533 У визуальных и невизуальных обьектов событие constructor не всегда гарантированно отрабатывается первым после создания обьекта. Если в этом событии например создаются экземпляры собственных невизуальных классов, то иногда получаешь Null reference. Как выход я использовал вариант не создавать их вручную, а вставлять в пайнтере как Insert nonvisual object. Частенько в пайнтере формы в зависимости от ее типа становятся недоступными для изменения некоторые ее свойства, которые по мнению разработчиков PB должны быть только такими и никакими иначе. Сия проблема решается элементарным ручным редактированием Source формы, в разделе Global Type. Например чтобы выключить TitleBar у формы достаточно там написать: Код: plaintext Далее входим в пайнтер и видим, что Titlebar выключен, несмотря на то, что пайнтер не дает его изменять. Для новичков - изменение Source так же позволяет обойти ошибки открытия обьектов, родитель которых были изменен (например у родителя был удален метод), причем открыть их в пайнтере нельзя. Входим в source такого обьекта, ремарим/меняем ссылки на несуществующие обьекты или методы. Теперь пайнтер позволит открыть обьект. Если уж что то хочется сделать раньше всех других действий на создание или удаление обьекта, то события Constructor и Destructor для этой цели не подойдут. Как вариант решения - можно войти в source обьекта и на методы create и destroy (эти методы пишутся как on ClassNameObject.create и on ClassNameObject.destroy ) ручками вписать все необходимое. Однако следует помнить, что пайнтеры этого не увидят и если после ручного изменения source обьекта войти в painter и в нем сохранить обьект, наши изменения будут потеряны. Если в разделе Instance variables класса обьявить public переменную, то все наследники этого класса в пайнтере будут ее показывать в Properties, что довольно удобно для инициализации свойств родительского обьекта без кодирования. В классах PB можно организовывать свои свойства (является недокументированной возможностью PB). Пишем в разделе Instance variables обьявление своего свойства: Код: plaintext В итоге обьявляем в классе собственное свойство NewProp, с указанием функции записи значения этого свойства SetNewProp и функции считывания значения GetNewProp. Соотвествующе эти функции обьявляются как: Код: plaintext 1. Механизмы работы со свойствами такие же, как и в других языках. Замечание - в отличие от public переменных свойства не показываются в Properties пайнтера обьекта. Стоит помнить, что рабочую область формы стоит получать не через Width и Height, а через WorkspaceWidth() и WorkspaceHeight(). Иначе получите полную длину и ширину окна вместе с его заголовком и рамками. Однако не забывайте, что такой подход не допустим для получения рабочей области MDI окна, так как в нем еще могут быть панели и строка состояния. Для этого у MDI окон есть обьект MDI_1, который выступает прокладкой для дочерних окон MDI и стабильно занимает нужную площадь. Так что для MDI рабочую область получаем так: Код: plaintext 1. 2. На сегодня все. Думаю я еще сюда попишу, как снова появиться свободное время. Надеюсь что не только я :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2003, 17:00 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
1) Если в разделе Instance variables класса обьявить public переменную, то все наследники этого класса в пайнтере будут ее показывать в Properties, что довольно удобно для инициализации свойств родительского обьекта без кодирования. Код: plaintext 2) У визуальных и невизуальных обьектов событие constructor не всегда гарантированно отрабатывается первым после создания обьекта. Код: plaintext вставлять в пайнтере как Insert nonvisual object Код: plaintext 3) Если уж что то хочется сделать раньше всех других действий на создание или удаление обьекта, то события Constructor и Destructor для этой цели не подойдут Код: plaintext 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2003, 18:56 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
PB 9.01 Насчет видимости protected в пайнтере спасибо, не обратил внимания (вернее по умолчанию привык как в Java и Delphi, что кроме public в дизайнере других свойств не видно). У визуальных и невизуальных обьектов событие constructor не всегда гарантированно отрабатывается первым после создания обьекта. Наглядный пример - шлепаем MessageBox для MDI формы на события Open и Resize. Открываем окно - первым выполняется Resize, далее Open, далее снова Resize. Идиология скажем так странная, так как Open по идее должно быть раньше любого другого события класса. Для не MDI формы все работает правильно. вставлять в пайнтере как Insert nonvisual object Теперь представим для предыдущего случая, что на Open формы мы создаем экземпляр класса, описанный в instance, к которому мы обращаемся в событии Resize. Null reference object гарантированно. Кстати были аналогичные проблемы с вызовом события Constructor для класса, наследованного от Transaction и указанного, как тип для SQLCA. Сначала отрабатывалось событие Open для application, а вот событие Transaction.Constructor не вызывалось вообще. Естественно я ничего такого в коде дикого не творил - в Application.Open подцеплялся через SQLCA к БД и открывал форму, в Transaction.Constructor просто создавал экземпляр своего невизуального класса. Проблема решилась сама собой, после часа сидения с отладчиком, full rebuild проекта и т.д. Причем ничего я в коде не менял - просто в один прекрасный момент вдруг все взяло и заработало. Insert nonvisual object я не делаю практически никогда, потому что вставленные таким образом объекты - public по умолчанию, и контроля над доступом к ним нет, что на мой взгляд противоречит ООП... Не согласен - дочерние обьекты класса абсолютно не противоречат ООП, будучи public. Вспомним Java с архитектурой работы модель-контроллер-документ, где все повязано через интерфейсы именно на работе служебных дочерних public обьектов и все не только прекрасно работает, но и позволяет добиться большей гибкости и эффективности. В PB эта концепция тоже вписывается - любой дочерний (служебный) обьект спокойно позволяет описать сервис, отвечающий за определенный набор логики, плюс его родитель и все его потомки имеют право реализовывать код в событиях служебного обьекта в пайнтере, избавляя от необходимости плодить события в его родителе, что очевидно дает преимущества в гибкости и автономности использования служебных классов. Например у меня были реализованы классы Listener (публикатор событий) и Eventer (подписчик событий) по аналогу Java, что привело к возможности при удобных случаях пользоваться преимуществами делегирования событий, например если бросить на форму NonVisual обьект: Код: plaintext на событие open формы написать Код: plaintext то переключившись в пайнтере на обьект ev_Tran я смогу написать свой код в 2 его событиях: ue_Connect и ue_Disconnect, который гарантированно будет вызываться при любом подключении и отключении sqlca от БД. Очень даже удобно, особенно когда дело касается написание базовых иеархий форм и сервисов и код получается читабельный - вот обьект, полностью отвечающий за некую часть логики главного обьекта, вот и его пользовательские события, позволяющие реагировать и контролировать ход проводимых работ. И вообще, если у вас появляются мысли о пунтах 2 и 3, у вас скорее всего проблемы с дизайном объектов... Насчет ручного вписания кода в базовый метод класса Create полностью согласен - это прокатывает только в том случае, если мы решили забыть о пайнтере. Насчет ручного изменения значения свойств в Source - все нормально проходит, в принципе пока я пишу правильно, все и будет проходить. Например где это в API Windows написано, что дочерние MDI формы всегда должны иметь TitleBar и Border - запрещает сам пайнтер IDE, хотя Power Script естественно пропускает и при выполнении успешно создает форму с указанными параметрами, не нарушающих правила Windows. Могли бы возникнуть проблемы, если бы PB был кроссплатформенным, но он уже давно как оказалось не кроссплатформенный. Естественно надо взвешенно подходить к обходу "правил" PB, но в некоторых случаях когда это оправдано и работает думаю немножно поиздеваться над PB не повредит. Кстати критические правила PB вычисляются быстро - например когда я ради интереса в source своего класса приложения Application описал собственную global переменную (аналогично sqlca, sqlsa и т.д.), правильно прописал ее создание и удаление в методы create и destroy, то класс скомпилился и сохранился, в пайнтерах в секции global variable ее видно не было, однако PB разрешал к ней обращение из кода приложения. Самое интересное, когда я открыл пайнтер Application и нажал на Additional properties, вкладку Variable types в смутной надежде - а вдруг моя глобальная переменная там появиться (как известно мы всегда надеемся на чудо, даже когда очевидно, что его точно не будет). Естественно там было все как прежде, далее при попытке сохранения Application пайнтер выдал ошибку на необьявленную глобальную переменную и PB счастливо вышел с критической ошибкой. Больше эту pbl я открыть не смог, из чего я сделал правильный вывод о допустимости границ редактирования source. Да простят мне присутствующие такие вот издевательства, но я только изучаю PB, хочется выявить все его слабые/сильные/полезные/вредные стороны до того счастливого момента, как я начну на нем писать крупный проект, чтобы точно представлять - на чем я пишу, как это работает и на автопилоте учитывать возможные ньюансы, возможные проблемы и иметь представления о пути их решения. Пока о PB сложилось мнение, что это штука о трех отдельных и очень разных головах: PBVM (Power Script) - "чистый" ООП (как не парадоксально), сборщик мусора, глобальный пул обьектов, механизм доступа к внешним библиотекам ОС, встроенный SQL PB extension - пайнтеры IDE, классы собственных обьектов, классы обвязывающие встроенные обьекты/контролсы Windows DataWindow - чудесная штука, даже нет таких красивых слов, чтобы описать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2003, 23:36 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ну пойдём по порядку. 1) У визуальных и невизуальных обьектов событие constructor не всегда гарантированно отрабатывается первым после создания обьекта. Наглядный пример - шлепаем MessageBox для MDI формы на события Open и Resize. Открываем окно - первым выполняется Resize, далее Open, далее снова Resize. Идиология скажем так странная, так как Open по идее должно быть раньше любого другого события класса. Для не MDI формы все работает правильно. Во-первых сие есть неправда, первым едет Open, потом Resize, покопайся в своём коде и увидишь что нибудь... Во-вторых Open и constructor - две большие разницы, так что нечего передёргивать :-) 2) Теперь представим для предыдущего случая, что на Open формы мы создаем экземпляр класса, описанный в instance, к которому мы обращаемся в событии Resize. Null reference object гарантированно Только не надо собственное неаккуратное кодирование пытаться маскировать с помощью воображаемых багов РВ. Посмотри как в PFC Resize event проскритан - первая строчка - IF IsValid(inv_resize) THEN, и так везде, что единственно верный подход. 3) И вот в это я не верю, поскольку не видел подобного НИКОГДА за 8 лет работы: Кстати были аналогичные проблемы с вызовом события Constructor для класса, наследованного от Transaction и указанного, как тип для SQLCA. Сначала отрабатывалось событие Open для application, а вот событие Transaction.Constructor не вызывалось вообще 4) Соображения типа дочерние обьекты класса абсолютно не противоречат ООП, будучи public почему то не убеждают. Всё что ты описал, делается и не имея сервис классов как public переменных, а к интерфейсам а-ля Java имеет мало отношения. Всё, что я увидел - это усиление взаимозависимости объетов, вместо того чтобы наоборот... 5) Если как следует порыться в Microsoft User Interface Design Guidelines, то наверняка найдём, что дочерние MDI формы всегда должны иметь TitleBar ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 00:09 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
PB 9.01 Филлип Жалко, что Вы не хотите вдуматься в смысл вышесказанного мною и опираясь на свой авторитет и опыт программирования в PB опровергаете то, что выявленно практическим путем. Не надо говорить верю/не верю, не надо обвинять меня в неаккуратном программировании (я для этого не давал повода) и могу Вас уверить, что мой опыт программирования, пусть и не в PB тоже не 5 и не 10 лет, так что опыт это не показатель. Проведите простой эксперимент на PB 9.01 - создайте форму, назначьте ей тип MDI, в событие Open впишите MessageBox( 'Info', 'Open' ), в событие Resize впишите MessageBox( 'Info', 'Resize' ) . Далее по желанию - вызывайте это окно из приложения или в IDE нажмите Run/Preview. Сообщите о результатах очередности выполнения событий. Теперь просьба мне обьяснить разницу между событиями Open для форм и Constructor для других классов PB. Мое личное мнение, что в обоих случаях они должны вызываться первыми после создания обьекта: В Help написанно: event Open: Occurs when a window is opened by one of the Open functions. The event occurs after the window has been opened but before it is displayed. event Constructor: Occurs when the control or object is created, just before the Open event for the window that contains the control. В обоих случаях события вызываются после создания обьекта, причем в описании события Constructor допущена неточность - насчет его вызова перед событием Open окна это применимо только к вставленным через Painter обьектам, если обьект описывался как instance и создавался в Open, то естественно только во время создания и будет вызван Constructor. Только не надо собственное неаккуратное кодирование пытаться маскировать с помощью воображаемых багов РВ. Абсолютно не согласен - мое "неаккуратное кодирование" придерживается строгой логике выполнения кода и событий, поэтому если я в Resize обращаюсь к обьекту, значит он дочерний обьект класса, инициализируется при его создании и его отсуствие означает ошибочную логику выполнения приложения и правильно сигнализирует об моей ошибке или PB баге. Или Вы считаете, что легче в таком случае написать IsValid и потом долго и муторно пытаться понять, почему не работает, хотя ошибок нет. По аналогии конечно можно и конечному приложению просто на ошибочные действия юзера ничего не делать и не сохранять данные, но боюсь за такое никто благодарности не скажет. Не вижу разницы между этими случаями. И вот в это я не верю, поскольку не видел подобного НИКОГДА за 8 лет работы Не верьте на здоровье :) Микола, который тоже много много лет работает на PB и в момент этого глюка гостил у меня тоже не сразу поверил. И Debuger мы с ним поюзали и много чего поделали. Когда все заработало, никто так и не понял, что это было - ни он, ни я. Всё что ты описал, делается и не имея сервис классов как public переменных, а к интерфейсам а-ля Java имеет мало отношения. Всё, что я увидел - это усиление взаимозависимости объетов, вместо того чтобы наоборот... Простой вопрос - можно ли вписать код в пайнтере в события дочернего класса обьекта, обьявленного в instance variable с целью его расширения функциональности с определенными условиями родительского обьекта ? Если нельзя, то в чем заключается усиление взаимозависимости обьектов ? В моем случае описанный в библиотеке класс является понятием служебного класса, а его наследник в родительском обьекте является реализацией частного случая. Кстати дополнительный вопрос - если касаться не невизуальных классов, а контролсов - Вам не кажется это явным нарушением ООП, что все визуальные обьекты в PB ложаться на контейнер как публичные обьекты, их нельзя контролировать и есть возможность писать в пайнтере код на их события ? Или вы все визуальные обьекты тоже в instance ложите, чтобы не нарушать парадигму ООП ? Если как следует порыться в Microsoft User Interface Design Guidelines, то наверняка найдём, что дочерние MDI формы всегда должны иметь TitleBar Если почитать в Win32 Developers References анотацию WINAPI метода CreateWindow, то в описании структуры lpParam ни слова не сказано о том, что клиентские окна MDI обязаны иметь рамку и заголовок окна. Единственное скромное уточнение - что такие окна не могут быть скрыты и всегда видимы, что мы собственно говоря и все знаем. Теперь песни о главном - уважаемый Филлип, тема моего топика была просьба к профам поделиться интересными решениями/наблюдениями/обходами багов в PB. Я сюда написал, что нашел, как говориться за то и продал :) Не надо меня критиковать, причем с высокой точки зрения "Я долго работал, я все знаю", абсолютно не проверяя факты и аргументируя свои высказывания фразами "Я не верю". Иногда так можно попасть в большой просак, что было бы мне в первую очередь не приятно ;) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 01:03 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Опять по порядку. 1) Первое, что я сделал, это в РВ8.03 запустил MDI app с MessageBox ( 'Info', 'Open' ) в Open, и MessageBox( 'Info', 'Resize' ) в событие Resize. Первым выскакивает 'Info', 'Open' , то бишь скорее всего это либо где то у вас в предке вашего окна бежит какой то код или это РВ9 глюкавый. 2) Во всех версиях РВ хелп написано в грубом переводе следующее: "строгая логика" выполнения вашего кода НЕ МОЖЕТ полагаться на очередность и порядок выполнения событий, поскольку сей порядок есть implementation detail и может меняться от релиза к релизу РВ. 3) Open для форм и Constructor для классов таки зовутся ПЕРВЫМИ и с этой точки зрения между ними нет разницы, разница наблюдается в процессе инициализации визуальных и невизуальных объектов 4) Если посмотреть сюда: http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/multipledocumentinterface/aboutthemultipledocumentinterface.asp то можно увидеть следующее: Child Window Activation Any number of child windows can appear in the client window at any one time, but only one can be active. The active child window is positioned in front of all other child windows, and its border is highlighted. (Это к вопросу о бордере, если кто не понял). Ну и если посмотреть, то там есть картинка того как клиентские окна MDI выглядеть должны, и написано что они должны иметь возможность типа максимизироваться/минимизироваться, да ещё и иконку демонстрировать в минимизированном состоянии, которая без title bar жить будет где? Пральна, можете не рифмовать :-) А возвращаясь к главным песням, я очень часто наблюдаю в англоязычных форумах посты, которые классифицирую как отправление читателей на то, что по английски называется Wild Goose Chase (к сожалению не могу придумать сходу русского эквивалента). Так вот навскидку в вашем этого тоже много, потому и стал не то чтобы критиковать, а предостерегать других от искушения отправиться в погоню за дикими гусями... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 01:41 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Всем кто работает с PB следует помнить, что использование отладчика может изменить очередность выполнения событий. Поэтому если у вас возникли проблеммы с трассировкой событий, то можно воспользоваться встроеннымы средствами PowerBuilder. Для этого: - используем меню Tools | System Oprtions.. выбираем закладку General - Выставляем флаг в поле Enable PBDebug Tracing - Указываем путь и имя файла трассировки в поле PBDebug Output Pth После долгой и мучительной работы с файлом трассировки не забываем убрать флаг в поле Enable PBDebug Tracing Давайте проанализируем что происходит с окном при его открытии - Первым же событием окна является событие create - этого же окна!!! Это видно если открыть исходный исходник объекта через Edit Source. ( Результат подтверждается анализом файлом трассировки ) Задачей которого является создание объектов находяшихся в окне. Если у окна есть меню, то именно этот объект создается первым. После этого вызывается событие resize окна, т.к. создание меню привело к изменению рабочей области окна (mdi - всегда имеет меню). Далее создаются остальные объекты расположенные в окне. Соответственно для каждого из них будет вызываться обработка события Constructor. После того как закончится создание всех объектов окна, завершится и выполнение события Create . Только теперь начнет выполняться событие Open для окна. Другое дело, что пользователю оффициально доступно для написание кода событие Open и оно для него оффициально является первым событием которое выполняет окно, но это не так. PS. Не берусь судить насколько логично такое выполнение событий с точки зрения системного программиста. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 08:27 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Филлип 1. Мда - видно PB 9 глюкавый - окно чистое, наследуется от Window, первым вызывается Resize - но, только если окно MDI. Видимо получается баг. 2. Насчет строгой логики я и не претендую :) Однако согласитесь какое то событие должно гарантированно первым вызываться при создании экземпляра класса (то же самое можно сказать и про освобождение экземпляра), раз уж нельзя напрямую наследоваться от конструктора Create, а в Source как Вы правильно заметили Create править не стоит - дизайнер все равно потом при следующем сохранении сотрет. 3. Уточняю как я понимаю насчет разности логики создания визуальных и невизуальных классов - на PB 9.01 это выглядит так - создается форма, потом создаются все ее визуальные, далее все ее невизуальные обьекты, далее визуальные обьекты заносяться в массив Control, вызываются события Constructor всех невизуальных обьектов, далее Constructor всех визуальных обьектов, далее событие Open формы. С точки зрения логики все правильно и просто замечательно (если конечно забыть про глюк MDI окна в PB 9). 4. В примерах MDI окон у MS дано просто виденье, как они видят себе работу MDI приложений, однако строгих ограничений на дочерние MDI окна нет. Из за чего сыр бор - я уже много много лет использую механизм MDI для создания однодокументного плоского интерфейса, где есть понятие главная форма и рабочее пространство, которое на один момент времени полностью занято под один режим (аналог IE, Outlook и т.д.). Естественно MDI для этой цели просто прекрасно подходит - дочерние окна без заголовка и границ просто растягиваются на всю рабочую область главного окна, toolbar главного окна тоже вписывается в концепцию интерфейса, который в последнее время практикует тот же MS. Все это у меня работало на Delphi много лет, сейчас после ходовых испытаний могу с уверенностью сказать, что все это будет работать и на PB, так как механизм создания окон у него и Delphi идентичен (ну разве что у Delphi он немного гибче и позволяет контролировать само создание Handle окна и получить доступ к структуре его параметров перед вызовом API). Согласитесь - лучше MDI ничего в PB нет, любой другой интерфейс потребует гораздо больших усилий и напрягов от разработчика. Однако мои пользователи привыкли работать с SDI, так что не считаю зазорным из MDI сделать то, что нравиться им, но то, что легко сделать мне на PB. 5. Наверное Вы просто меня не правильно поняли - я не приглашал других кидаться открывать Source и начинать ручками все править, игнорируя стандарты PB, я приглашал поделиться знаниями по поводу работы скрытых механизмов PB, так как эти знания помогают лучше понять как внутри работает PB, что лично для меня немаловажно при освоении любого продукта. Согласитесь - плох тот водитель, который никогда в жизни не открывал капот своей машины и никогда не знал, что же там находиться. Уф, считаю что с этим разобрались, прокомментировали и утряслись. Думаю дальше процесс выкладывания в данный топик интересных возможностей и хитрых багов пойдет легче, так как уже присутствует автор затеи (Ваш покорный слуга), опытный критик и цензор (Филлип), ждем Ваших предложений :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 08:46 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
...уже много много лет использую механизм MDI для создания однодокументного плоского интерфейса, где есть понятие главная форма и рабочее пространство, которое на один момент времени полностью занято под один режим (аналог IE, Outlook и т.д.). Естественно MDI для этой цели просто прекрасно подходит... То есть сделал КЛАССИЧЕСКИЙ SDI - смех, да и только, ну да ладно, замнём :-)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 09:01 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ermak Вы меня обогнали :) Я кстати заметил, что не только использования отладчика изменяет порядок очередности следования событий. В PB еще есть приоритеты выполнения событий. Простой пример - если в событии окна Resize вызвать функцию или событие, то она выполниться сразу. Если же функцию или событие положить в очередь командой post, то выполниться она только после того, как изменение размеров окна будет завершенно. Однако если вспомнить, что WM_Resize посылается Windows только на реальное изменение окна, а PB будет ждать, даже когда мы просто ухватили мышкой за бордюр и не тянем форму, то выводиться еще одно правило - очередь событий, производных от событий Windows имеет преимущества перед очередью событий, организованных разработчиком PB. Филлип Зачем же заминать ? :) Можно ли Outlook назвать классическим SDI ? Как бы Вы на PB реализовали интерфейс, подобный Outlook, где есть понятие рабочего пространства главной формы и понятие переключения между режимами для этого пространства ? Было бы очень интересно услышать Ваше решение. Пока слышу только критику, пора бы Филлип все таки и какое то свое видение/решение дать. P.S. Я бы Вам рекомендовал немножно изменить свое отношения к правилам общения на русскоязычных и англоязычных форумах. Согласитесь, гораздо культурнее сказать не "Смех, да и только, замнем", а "Я бы лучше реализовал так ..." или "Я бы не рекомендовал так делать, потому что ... ". Да и информативности бы больше было и не приходилось бы вытягивать из Вас клещами, чем же не нравяться Вам предложенные решения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 09:17 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ну не вызывается Resize первым!!! Его инициирует создание меню, которое просто обязано быть в MDI окне. Добавте меню к окну с windowType main!, что получится? То же самое. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 09:21 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
2 All Появление и логика ответов в данной ветке наглядно демонстрирует очередь событий в win ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 09:24 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ermak Скажем проще - для форм с меню событие Resize вызывается раньше чем Open, о чем и следует помнить. Ну а очередь событий к моему сожалению ушла далеко от того направления, которое я предлагал обсудить. Мне хотелось, чтобы просто знающие люди для начинающих высказали свои мысли по поводу того, что они такого ценного делали в PB, где спотыкались и как обходили, что нигде не написано в книжках (PBScript, Interface, DataWindow). То что получилось, действительно стало больше смахивать на очередь событий API Windows :) Ну что ж ... хотел как лучше :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 10:11 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ну что же, кину и я свои три копейки... Совсем недавно столкнулся со следующей странностью: Есть дерево подразделений (чесное дерево). На событии Clicked висит обработка, которая в зависимости от номера подразделения, на котором произошел клик, либо дисейблит, либо энейблит кнопку в меню. Сталю в этот код точку останова и запускаюсь под дебаггером. Кликаю по дереву с подразделения на подразделение. И, как это ни странно, далеко не всегда попадаю в точку останова, хотя попадать должен. Соответственно и в run-time mode кнопка далеко не всегда дисейблится или энейблится (в связи с чем, собственно, я туда и полез). Сие безобразие творится как в PB 6.5.1, так и в PB 8.0.3 build 9704... Ну а на тему "хтростей в PB" скажу вот что: При миграции с 6.5.1 на 8.0.3, DW в синтаксисе которых есть *= или =* мигрируются не всегда корректно. Синтаксис заменяется на LEFT OUTHER JOIN или RIGHT OUTHER JOIN. Некорректность заключается в том, что PB при миграции может заменть например *= как на LEFT OUTHER JOIN, так и на RIGHT OUTHER JOIN по своим собственным принцыпам (мне не известным)... Ежли я в чем то не прав, прошу не пинать ногами и не кричать "ЛАМЕР!", а просто ткнуть харькой в обшибочку... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 11:05 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ikar Если не сложно описать - а как победили глюк дерева ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 12:10 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Мне тоже нравится когда в MDI окне Sheet занимает все видимое пространство. Точнее мне не нравится тот хаос который возникает если sheet'ы не занимают всю клиентскую область. Для этого в оконах-листах определяю следующие свойства: - ControlMenu off - WindowType main! - WindowState maximazed! Открытие листов идет так: openSheet(w_sheet1, w_mdiframe,0, original!) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 12:10 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
2 ASCRUS: Дык пока еще не победили, бьемси... Копаем в том направлении, что событие getFocus вреде как, на вскидку, отрабатывает всегда... Попробуем оттудова принудиловкой дергать Clicked... Посмотрим, что из этого выйдет... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 12:32 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
To Ikar: А не проще воспользоваться методом selectionchanged(long oldhandle, long newhandle) Он вроде всегда отрабатывает при смене элемента. По крайней мере у меня проблем небыло ни на 7 ни на 8 PB ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 12:56 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
2Kuzya: Проще то оно может быть и проще, да ведь разобраться хочется, понять, почему и из за чего ошибочка происходит... :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 13:10 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
2Ikar На событии Clicked висит обработка, которая в зависимости от номера подразделения, на котором произошел клик, либо дисейблит, либо энейблит кнопку в меню. Сталю в этот код точку останова и запускаюсь под дебаггером. Кликаю по дереву с подразделения на подразделение. И, как это ни странно, далеко не всегда попадаю в точку останова, хотя попадать должен. Что-то не понятно, покапайся в своих исходниках. У меня PB 6.5.1, нареканий нет по данной проблеме (хотя никогда не использую Clicked!) И вообще, если "иногда" - то уже настараживает, что это баг не билдера ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 13:33 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Ермак Ух ты - все прекрасно работает. Здорово - и не надо мудрить с растягиванием дочерних форм :) Я пытался через Maximized! сделать, но видимо не отключил в форме ControlMenu - при закрытии дочернего окна PB почему то все лежащие перед ним окна восстанавливал в нормальное состояние. Большое сенкс :) Теперь все красиво, приятно и без лишних напрягов :) Единственное - XP пытается форму сначала нарисовать, а потом растянуть, что вызывает эффект мигания, однако это победилось с помощью вызова SetRedraw главного окна перед OpenSheet. Еще вопросик на вскидку - как в Вашем интерфейсе организован ввод и изменение детализированной информации сложных данных с их дочерними данными ? Все окна идут внутри рабочей области MDI или же какие то работают отдельно от главного окна ? Я например давно уже привык работать в стиле интерфейса аля Outlook, когда главная форма служит рабочей областью для режимов просмотра списка данных (ну и ввода соотвествующе легких данных, стыкующихся с концепцией грида), а для ввода и изменения сложных данных используется отдельное от главного не модальное окно, регистрирующее свой заголовок в Taskbar (например окно ввода нового сотрудника с как его основной информацией - ФИО, дата рождения, ..., так и дополнительной информацией - список налоговых вычетов, предоставленных льгот, и т.д.). Единственное отличие у меня от Outlook - нельзя одновременно открыть более одного окна на добавление или изменение информации, т.е. пользователь может сколько угодно лазить по режимам-окнам главной формы, но в одном режиме у меня может быть открыта для добавления или изменения информации только одна вспомогательная форма. Ikar Как победите дерево, обязательно сообщите :) Если я правильно понял Вашу проблему, то мне почему то кажется, что правильней было бы обрабатывать логику перемещения по дереву не через событие Clicked, а событие SelectionChanged, так как Clicked не гарантирует выбора пользователем node, а только сигнализирует о нажатии мышки на дереве и может срабатывать во многих ситуациях - например при клике на пустое пространство дерева или же на плюсик для открытия ветки, что не означает, что пользователь изменил активную node. Попробуйте покопать в этом направлении. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 13:41 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. Вот этот код проверялся в PB 6.5.1 EE, 7.0.3 build 10213, 8.0.1 build 8004... Во всех версиях resize вызывается ДО и ПОСЛЕ события open... Но Филипп абсолютно прав - if IsValid() надо вызывать всегда :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 15:02 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
Насчет вызывания всегда IsValid не согласен. Пример - никто думаю из присутствующих не пишет такой код внутри своих форм: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Ну а если бы писали, то это уже был бы клинический случай :) Если обьект гарантированно создается внутри родителя-контейнера, то он гарантированно существует и такие проверки просто извращения. И без разницы, как создается этот обьект - на автопилоте самим PB, так как он был вставлен через дизайнер в раздел публичных обьектов или же был обьявлен в instance variable и по логике обязательно имеет полный цикл жизни вместе с родительским обьектом, четко создаваясь в его конструкторе и удаляясь в его деструкторе. В случае формы ее доступным и легальным конструктором является событие Open, а деструктором Close. Поэтому IsValid в моем случае был не уместен, так как шло обращение к дочернему обьекту, который создается и удаляется вместе с формой (не путать с проверками на существование временных обьектов, ссылок на обьекты, которые в ходе работы приложения могут обнуляться и меняться на другие обьекты и т.д.). В PFC IsValid стоит по другой причине - их библиотеки общий случай, так что внутри кода они не могли бы гарантировать существования обьекта из за их схемы работы PFC. У меня же частный случай, где гарантией существования обьекта, к которому идет обращение являюсь я сам :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 15:36 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
2 ASCRUS Именно так и пишу :-) Правда, должен оговориться, что в форме все элементы управления создаются динамически, а код, похожий на приведенный выше пишется в невизуальном объекте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 16:45 |
|
||
|
Хитрости PB
|
|||
|---|---|---|---|
|
#18+
PL99 , ваш пример с экспортированным кодом к сожалению не катит. Речь идёт о дочернем окне, а не о MDI Frame. Как известно у дочерних окон меню нет, оно всегда у MDI Frame. Что можно из этого вывести? Только одно - что необходимость корректировки размера дочернего окна у MDI Framа возникнет (или не возникнет) в зависимости от того в каком состоянии вы это дочернее окно открываете, то бишь от последнего аргумента функции OpenSheet..., или в переводе на русский язык, от наших кривоватых (или не очень) ручек :-)) Поэтому, как вы пральна заметили, if IsValid() надо вызывать всегда :-) ASCRUS , можно ли Outlook назвать классическим SDI ? Да, безусловно, он считается классическим примером SDI. Никаких решений я приводить не стал, поскольку у меня возникли сомнения в вашем понимании разницы между MDI и SDI :-)) А вообще у нас тут любят принцип KISS (Keep It Simple Stupid) проповедовать. Не хотите со своим statusbarом трепыхаться, а хотите РВшный реюзать, но при этом SDI иметь - не пользуйтесь командой OpenSheet, ди всё. Сделайте ваше(и) окно(а) типа Child! и открывайте их из MDI Framа командой Open, размещайте/ресайзайте как вам надо и вперёд. Можно и совсем по другому, брать окно типа Main!, на него сажать Microsoft statusbar и открывать из него Child! окна. Пример statusbar лежит тут: http://www.pbdr.com/software/comp/StatusBar.zip Пример того как делать Outlook интерфейс лежит тут: http://www.teamsybase.com/roy.kiesler/downloads/outlook.zip В PFC IsValid стоит НЕ по другой причине , а только по одной - называется Defensive Coding ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2003, 19:11 |
|
||
|
|

start [/forum/topic.php?fid=15&msg=32278966&tid=1337821]: |
0ms |
get settings: |
9ms |
get forum list: |
21ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
70ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
80ms |
get tp. blocked users: |
1ms |
| others: | 239ms |
| total: | 440ms |

| 0 / 0 |
