![]() |
|
|
![]()
|
|
| Brodyaga |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Всем здравствуйте!
Хочу создать окно зарегестрированого класса с помощью MFC. Создаю класс наследник от CWnd. Далее в функции Create передаю имя зарегестрированного оконного класс:
Вставляю этот код в функции OnInitDialog. Программа вылетает на функции Create. Если делаю без MFC на чистом WinApi, то всё работает. Сначала переопределяю оконную процедуру, а затем в событии щелчка мышкой по форме делаю следующее:
Так всё работает. Что я делаю не правильно в первом варианте? |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Куда вылетает-то? В окно? Ты же программист...
Видишь, у тебя разница не только в применении MFC: во втором варианте ты создаешь контрол не на ининциализации диалога, а по щелчку мыши. Может, в этом дело? А вообще, надо понимать, что сабклассинг в MFC - это не совсем сабклассинг АПИ. MFC подставляет всем контролируемым окнам одну и ту же оконную процедуру (из которой по Default уже вызывается родная процедура класса). Тут тоже могут быть тонкости. Но из приведенной тобой информации ничего не ясно. Возьми отладчик и сходи внутрь Create. -------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Потому что сообщение WM_CREATE вообще не приходит... |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Кому не приходит и в каком варианте?
-------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
В обоих вариантах. если оконную процедуру диалога переопределяю(WM_CREATE) и если просто на событие MFC диалога подписываюсь (OnCreate)
|
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Т.е. диалогу не приходит? Собственно, на WM_CREATE рано еще контролы создавать. Это нужно делать на WM_INITDOALOG (в MFC-варианте - на OnInitDialog).
-------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Earnest, суть такая, что я хочу создать окно, определённого в системе класса и разместить его на диалоге наследованном от класса CDialog.
Хотел сделать это в OnInitDialog средствами MFC. Это у меня не получилось, тогда я решил попробовать на чистом WinApi. Для этого переопределил оконную процедуру(в методе OnInitDialog) у диалога. Подписался там на сообщения WM_CREATE и WM_INITDIALOG, но они в оконную процедуру не пришли. Тогда подписался на сообщение щелчка мыши и без MFC создал нужное мне окно так:
Всё получилось! Вопрос1: как создать окно зарегистрированного в системе класа средствами MFC? Вопрос2: в какой момент и ГДЕ мне переопределить оконную процедуру, чтобы сообщения WM_CREATE и WM_INITDIALOG успели прийти в неё? Жду помощи! |
|||
|
||||
| Andrey44 |
|
||||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1501 Регистрация: 4.12.2006 Где: На работе Репутация: 12 Всего: 26 |
-------------------- ????? ??, ??????? ?????. |
||||||||
|
|||||||||
| Brodyaga |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Это именно создасться окно класса MyRichEdit. А если для зареганова оконного класса в системе нет MFC-шного класса? как тогда быть?
Создал метод BOOL PreCreateWindow(CREATESTRUCT& cs) и поставил там брекпоинт. При отображении диалога на экране, программа не перешла по этому брекпоинту... Сам диалог где хочу разместить окно зарегестрированного в системе класса показываю так:
Кстати.. сейчас вычитал, что CDialog не наследует PreCreateWindow от CWnd.. Это сообщение отредактировал(а) Brodyaga - 26.2.2010, 11:23 |
||||||
|
|||||||
| Earnest |
|
||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
1. Передать имя класса в CWnd::Create (кажется, первый параметр) 2. Написать свой класс (наследник от наиболее подходящего MFC-класса) и переопределить для него либо PreCreateWindow, либо написать свой вариант Create (не виртуальный, только с нужными параметрами). Все это по сути одно и то же, т.к. сводится к 1 пункту.
Ты все время нас путаешь: где и что ты создаешь. Есть диалоги и есть контролы. Это две большие разницы. Диалогу действительно не приходит PreCreateWindow, т.к. окно создается не через CreateWindow и не в MFC. Но WM_CREATE перехватить реально, хотя лучще всего все-таки для диалога делать все инициализации в OnInitDialog. Далее, если ты добавляешь контрол на диалог в редакторе ресурсов, то PreCreate тоже не получишь.
1) Можно положить контрол на шаблон диалога в редакторе ресурсов (Custom Control), обязательно правильно указав имя его Window-класса 2) Можно динамически, в OnInitDialog, через Create - написала выше как.
Оконную процедуру диалога? Нигде. В MFC ты не переопределяешь оконную процедуру, ты добавляешь обработчики в стандартную процедуру, которая одна на все окна (почти). Насчет WM_CREATE не совсем уверена, но по-моему все точно так как и для остальных окон - просто нужно написать обработчик в своем классе (и добавить в карту сообщений). OnInitDialog - виртуальная, просто переопределяешь ее в своем классе-диалоге. -------------------- ... |
||||||||
|
|||||||||
| Brodyaga |
|
||||||||||||||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Переопределяю этот метод у диалога естественно, на котором хочу разместить окно зарегистрированного в системе класса. Но создаю этот диалог я в MFC, я же написал как, вот:
IDD_DIALOG1-это идентификатор диалога, на котором я хочу разместить окно зарегистрированного класса(WC_RICHINK). Функцию PreCreateWindow я хотел переопределить, для того, чтобы в ней переопределить оконную процедуру диалога этого (IDD_DIALOG1) и успеть в переопределённой оконной процедуре обработать событие WM_CREATE или WM_INITDIALOG для создания с помощью WinApi окна на этом диалоге зарегестрированного в системе класса, так как не знаю, как это сделать с помощью MFC в функции OnInitDialog().
Так пробовал. Не получилось. Окно зарегистрированного в системе класса не появилось на диалоге.
Вот так мне и надо было, чтобы через MFC, тогда и оконную процедуру не надо переопределять, так как всё с помощью MFC можно было бы сделать, но... попробовал так, программа вылетела в диалог с ошибкой в wincore.cpp файле.
А я переопределил для диалога нормально, вот так:
Пробовал так, написал обработчик OnCreate(LPCREATESTRUCT lpCreateStruct) и добавил в карту... по брекпоинту при создании этого диалога программа не переходит(Напоминаю, может не совсем понятно... это обработчик события создания диалога на котором я хочу разместить окно зарегистрированного в системе класса - IDD_DIALOG1).
Это да, с этим всё нормально. Теперь мне в этой функции надо создать окно зарегестрированного в системе класса с помощью MFC, что не получается через предложенный вами способ(CWnd::Create), что именно случается в этом случае я писал выше. Почему может не работать предложенный вами вариант? |
||||||||||||||||||||
|
|||||||||||||||||||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Я не говорила "невозможно". Кошерно нельзя, да и не надо.
Значит, что-то сделано неправильно - способ рабочий, пробовала. Может, забыл вызвать инициализацию библиотеки (InitRichInkDLL())? Это надо делать пораньше, до создания диалога (можно в его конструкторе). Я же не телепат, однако. Что за ошибка-то? В PreCreateWindow делать этого просто нельзя - на то оно и PreCreate, а что касается ошибки, то с ней и надо разбираться, т.к. идеологически вариант правильный. Такое ощущение, что ты бессистемно тычешься, пробуя разные варианты и бросая их при первой же неудаче. Переходить к следующему варианту нужно только тогда, когда ты поймешь, почему предыдущий не может работать - или заставишь его заработать. Итак, правильных путей ровно 2: через редактор ресурсов и через Create (в OnInitDialog). А теперь давай попробуем понять, что же не так с Create? -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
В конструкторе и инициализирую, просто привёл в одном месте для ясности.
в PreCreateWindow я хотел переопределить оконную процедуру диалога(IDD_DIALOG1), чтобы в ней успеть поймать сообщение WM_CREATE или WM_INITDIALOG и там уже с помощью WinApi создать окно зареганного класса на диалоге этом, так как с помощью MFC не знал как.
Так и есть, я мечусь между двумя вариантами: 1. в OnInitDialog создать окно зареганного в системе класса с помощью MFC. 2. переопределить оконную процедуру диалога до прихода в неё сообщений WM_CREATE или WM_INITDIALOG и в обработчике этих сообщений создать окно зареганного в системе класса с помощью WinApi (так как с помощью WinApi я знаю как, есть пример и всё работает) Сейчас тогда добиваем первый вариант. Ошибка, которая вылазит при вызове функции CWnd::Create:
|
||||||||
|
|||||||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
У меня в этой строке никакого ASSERT нет.
Строку приведи, куда ссылается ASSERT (а лучше функцию целиком). Кто тебе сказал, что у меня тот же компилятор и та же версия MFC? Добавлено через 1 минуту и 4 секунды
В PreCreate это делать рано, т.к. окно еще не создано. Даже если бы оно приходило диалогу. Добавлено через 4 минуты Вот еще увидела:
Ты создаешь локальную переменную и после выхода из функции ее теряешь. И как ты собираешься управлять окно (и удалить потом этот объект)? Указатель на динамический контрол нужно где-то хранить, в диалоге, например. Но причиной ASSERT это вряд ли является. -------------------- ... |
||||
|
|||||
| Brodyaga |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Да это всё понятно, я для теста просто написал на коленке, мне сейчас главное, чтобы окно показалось на диалоге.
Мне кажется дело в ID который я передаю в функцию Create. Я туда передаю ID диалога на котором хочу отобразить окно зареганного в системе класса. это ведь верно? Это сообщение отредактировал(а) Brodyaga - 3.3.2010, 10:39 |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Нет, неверно. В функцию Create нужно передавать ID, который будет присвоен контролу, и по которому ты в любой момент сможешь его достать. Но я не вижу, где ты его передаешь. Это волшебное число 137 что ли? Если так, то проблема вряд ли в этом. Ты мог бы посмотреть отладчиком значения переменных ID и hWndCtrl какое именно условие не выполняется. Кроме того, ранее ты говорил, что вылетаешь на строчек с функцией Create, так причем тут OnCommand? Действительно ли этот вызов находится во фрейме Create (т.е. где-то внутри Create -> посмотри стек). Если так, то похоже, что контрол при создании шлет извещение диалогу (проверь, что this в этот момент показывает на твой диалог), причем шлет его неправильно (не соблюдает соглашения о содержании WPARAM\LPARAM). Или может это твоя подкрутка? В любом случае это не фатальная ошибка, если нажать Ignore, все должно продолжать работать, но ты этот видимо не пробовал. Проверь, но в любом случае разобраться с Assert ом надо, ибо он указавает на некошерность поведения. -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
137 - это id диалога на котором я хочу разместить созданное окно. а как узнать какой id должен быть у контрола? как узнать, что нужно вместо 137 передать?
Значение ID почемуто 10003, hWndCtrl тоже не пустое. Следовательно второе условие не выполняется.
да, в этот момент hwnd равно hwnd моего диалога. никакой подкрутки нет...
Я это пробовал, всеровно вылетает. |
||||||||
|
|||||||||
| Andrey44 |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1501 Регистрация: 4.12.2006 Где: На работе Репутация: 12 Всего: 26 |
Прочти хотя бы одну книгу по MFC или по WinAPI, тогда не будешь задавать таких вопросов. -------------------- ????? ??, ??????? ?????. |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Любой, ты его сам назначаешь. Странно, если передаешь ты 137, а получаешь 10003... возможно это уведомление от другого контрола? Есть у тебя на диалоге контрол с таким ID? Или это все же этот? А что касается hWndCtrl - стало быть, не выполняется IsWindow(hWndCtrl), т.е. не знает система такого окна. Нужно выяснить, кто посылает эту хрень. Я стек просила посмотреть. Но ведь в другом месте? Где? Добавлено через 4 минуты и 14 секунд Кстати, о птичках... В WinAPI варианте ты никакого ID не передавал! Так зачем это делать в MFC-выарианте? Все параметры должны быть такие же, с учетом разницы hWnd - pWnd! Кто его знает, что у тебя за контрол? Например, тултипы тоже без ID создаются. Передай-ка вместо 137 0. И книжки почитай, не помешает... -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Передавал.. тамже вылетает, с id равным 10003...
Нету контрола с таким id. Скорее это при создании такой id назначается этому контролу. В варианте с переопределением оконной процедуры и созданием контрола на диалоге с помощью WinApi, тоже после создания в оконную процедуру поступают сообщения WM_COMMAND с 10003 id.
Похоже после вызова этой функции идут сообщения WM_COMMAND в форму
По стеку понять чтото не могу, просто вызов от одной функции к другой передаётся, как посмотреть откуда вызов то был:
Но думаю вызов посылает контрол диалогу при создании. Потому что при создании самого диалога, он тоже сообщения со своим id посылается родителю(другому, главному диалогу), правда в этот раз id корректный, тот который указан в ресурсе и всё проходит без ошибок.
в этом же, просто при нажатии Ignore, программа проходит дальше, но потом снова присылается это сообщение с теми же параметрами и в этом же месте уже вылетает. (В варианте с переопределением оконной процедуры и созданием контрола на диалоге с помощью WinApi оно тоже несколько раз присылается, а после него ещё идут сообщения WM_COMMAND с id=10006 и id=10000) Это сообщение отредактировал(а) Brodyaga - 5.3.2010, 13:17 |
||||||||||||
|
|||||||||||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Просто смотри дальше вниз, где-то должен быть твой Create.... но иногда среда может врать, съезжает у нее чего-то... я так понимаю, библиотека с контролом не твоя и кода нет.
Тоже самое сообщение тоже можно проигнорировать. Нажми Ignore столько раз, сколько нужно - либо пройдешь, либо вылетишь не на ASSERT, а на что-то посерьезнее. Я это к тому, что нужно проверить, стоит ли пытаться обойти эту бяку, или твой контрол вообще нельзя через MFC создавать. Дело в том, что MFC подменяет оконную процедуру, а в контроле может наступить какой-нибудь конфликт в связи с этим. Можно еще попробовать сделать так: создавать через ::CreateWindow, как ты уже делал, но тоже в OnInitDialog. Нет никакой необходимости ради этого подменять процедуру диалога. Тогда ты получишь hWnd, но можно легко сделать из него CWnd*, если оно надо. Вызывая апишную функцию для создания контрола, ты избегаешь установки хука на создание контрола, подмены процедуры и т.д. Если получится, можно при желании сделать для этого контрола MFC обертку (с собственной функцией Create). -------------------- ... |
||||
|
|||||
| Brodyaga |
|
||||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Это всё что есть. Библиотека не моя, примеры её использования есть только на WinApi.
Это первое, что я попробовал. Вылетает именно на ASSERT, так как на следующую после него строку я поставил брекпоинт, после первого игнора на него программа переходит, но после второго вылетает не переходя на поставленный брекпоинт.
А вот тут самое интересное. Я потому и сталподменять процедуру диалога, так как если это делать в OnInitDialog, то вылетает в том же месте(на ASSERT в wincore.cpp, Ln 2598) с теми же симптомами. А при переопределении оконной процедуры диалога всё работает. Подозреваю, что это изза того, что я не передаю управление старой оконной процедуре с помощью CallWindowProc после своих действий, а при ненужных мне сообщениях передаю управление DefWindowProc. Кстати при WM_COMMAND туда же сообщение уходит:
И всё нормально. Сейчас попробовал отдать управление старой оконной процедуре диалога. Тоесть после создание окна контрола в WM_INITDIALOG, как и раньше присылаются сообщения WM_COMMAND с id=10003, но в мою переопределённую процедуру, но оттуда я отдаю управление старой процедуре:
Вылетело с теми же симптомами, что и раньше!(тоесть всё там же на Ln2598). Что скажете? Это сообщение отредактировал(а) Brodyaga - 5.3.2010, 16:12 |
||||||||||
|
|||||||||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Куда вылетает-то? Ты используешь "вылетает" для самых разных ситуаций, попробуй пойми. Есть ASSERT'ы, есть исключения. Дело в том, что обойти первый ассерт довольно легко. Иногда сам факт останова на ASSERT (т.е. появление MessageBox) вызывает дальнейшие проблемы. Ибо нет после того ASSERT'а ничего фатального, на первый взгляд... Но нужно понять точно. Фактически, получается, что контрол посылает WM_COMMAND с LPARAM, которая не является окном... Странно, конечно. Попробуй обойти так: В диалоге переопредели OnCommand и отфильтруй это сообщение (т.е. если флаг стоит и сообщение от этого контрола сразу выходим). Проще всего сделать это с помощью флага, который будет ставится перед созданием контрола, а потом сниматься. Это чтобы по-быстрому проверить. Если поможет, то можно будет думать о том, чтобы менее криво сделать. -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Никуда. Просто программа прекращает своё выполнение. Сделал так:
Wnd - это объект типа CWnd*, обёртка для моего контрола. Создаю так:
ID равный 10008 включил, так как с ним потом тоже пошли сообщения, при обработке которых CDialog::OnCommand(wParam,lParam), вылетало всё на том же ASSERT'е. Правда после нажатия Ignor в этот раз прога продолжила своё выполнение без проблем.. ну да ладно.. всеровно решил управление ::DefWindowProc передать. Вообщем так заработало, но что интересно hWndCtrl(ID элемента управления посылающего сообщение) и hWndControl(ID контрола) никогда не равны между собой. hWndCtrl всегда меняется.. тоесть сообщения всегда приходят от разных элементов управления.. Я думал что их контрол должен слать моему диалогу... разве не так? |
||||||
|
|||||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Строго говоря, да. Но это всего лишь соглашение - что при посылке WM_COMMAND в LPARAM должен быть HWND посылающего контрола. А соглашение можно и нарушить. Это ведь сам контрол делает, т.е. его автор. И чего он там написал - хз. По твоим словам получается, что LPARAM содержит совсем не HWND, а какую-то другую фигню. Осталось непонятным, откуда берутся ид-ры 10003 и 10008, которые не ты назначаешь. Посмотри Спаем на контрол после создания диалога - возможно он содержит вложенные элементы или сам состоит из нескольких частей... Еще интересно, чему равен NotifyCode, число из любопытства.
Кстати, я думаю, что вызов DefWindowProc можно простить, вернуть просто TRUE (или FALSE) - вряд ли там есть какая-то разумная обработка, раз соглашение о параметрах нарушено. -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Всегда 0. Хоть с каким ID(10003, 10008) Также там ещё приходят сообщения с 10006 и 10000, но с ними не вылетает.
Не приходилось таким пользовался, это программа шпион специальная? дайте название конкретной программки тогда |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Да так и называется - Spy. Есть в поставке Visual Studio. Очень удобно для исследования окон, как своих, так и чужих.
-------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Боюсь это не поможет... У меня программа запускается на эмуляторе...
|
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |