Реализация обычных окон в Delphi
Резюме в библиотеке VCL в Delphi для удобства использования и реализации приложение Application Object создает скрытое окно для обработки ответов сообщений. Именно это окно делает программы, разработанные с VCL, кажутся несколько деформированными, например, неспособность организовать и плитку с другими окнами. Благодаря углубленному анализу VCL, эта статья предоставляет решение, которое может решить проблему, только изменяя 3 строки кода в файл проекта приложения без каких-либо изменений в исходном методе программирования.
Ключевое слово VCL, нормальное окно, нормализация
1 Введение
Приложения Windows, написанные в библиотеке классов VCL, предоставленной Delphi, имеют особую функцию, которая, очевидно, отличается от стандартного окна Windows - системное меню главного окна отличается от меню системы на панели задач. Вообще говоря, в меню системы в главном окне есть шесть пунктов меню, в то время как в меню системы панели задач есть только три пункта меню. В реальном использовании мы обнаружили, что программы, разработанные с VCL, имеют следующее смущение:
1) недостаточно красиво. Это точно, если он не соответствует стандартам, оно, естественно, будет выглядеть немного деформированным.
2) Не существует эффекта анимации, когда главное окно сведено к минимуму.
3) Окно не может быть расположено, а плитка обычно с другими окнами.
4) Меню системы панели задач имеет самый высокий приоритет. В присутствии модального окна вся программа все еще может быть сведена к минимуму, в отличие от дизайна модального окна.
Проблема минимизации анимационных эффектов в главном окне была решена с помощью функции ShowwinnoaniMate в формах. PAS в версиях после Delphi 5.0, но оставшиеся проблемы всегда существовали. Хотя в большинстве случаев это не окажет никакого влияния на приложение, в некоторых ситуациях это действительно неприемлемо, когда профессиональные последствия осуществляются. Поскольку C ++ Builder и Delphi используют один и тот же набор библиотек классов, вышеуказанные задачи также существуют в приложениях Windows, написанных с использованием C ++ Builder.
Я обсуждал эту проблему в предыдущих статьях (можно найти в доме Форреста Гампа), и повествование в то время казалось в основном трюком, и я обнаружил этот метод случайно. Задача этой статьи состоит в том, чтобы проанализировать библиотеку классов VCL, чтобы объяснить принцип этого, а затем дать метод, который использует только 3 строки кода, чтобы полностью решить проблему этого «ненормального окна» в Delphi.
2 принцип
2.1 Процесс создания приложений
Вот типичный файл проекта Delphi приложения.
Программа Project1;
Использование
Формы,
UNIT1 в 'Unit1.pas' {form1};
{$ R *.res}
Начинать
Application.initialize;
Application.createform (tform1, form1);
Application.Run;
конец .
Скрытое окно создается объектом приложения, так откуда взялся объект приложения? Нажмите и удерживайте CTRL в окне редактирования кода Delphi и нажмите приложение, вы обнаружите, что объект приложения является одним из нескольких глобальных объектов, определенных в блоке Forms.PAS. Этого недостаточно, мы хотим знать, где был создан объект приложения, потому что экземпляр класса TAPPLICATION должен быть успешно создан, прежде чем мы сможем обратиться к нему.
Подумайте об этом, есть ли какой -нибудь код, который будет выполнен до Application.initialize? Кстати, это код в сегменте кода инициализации. После тщательной отладки исходного кода VCL вы можете знать, что многие единицы в VCL имеют сегменты кода инициализации. Все действия инициализации.
Поиск в каталоге исходного кода VCL с помощью ключевого слова "tapplication.create", мы нашли код для создания объекта приложения в блоке Controls.PAS. В сегменте кода инициализации элемента управления.
Управление единицей ;
…
Инициализация
...
InitControls;
Процедура initControls;
Начинать
...
Мышь: = tmouse.create;
Экран: = tscreen.create ( nil );
Приложение: = tapplication.create ( nil );
...
конец ;
Хорошо, на этот момент наш анализ выполнил первый шаг, поскольку для решения проблемы ненормальных окон мы должны сделать одну вещь перед инициализацией объекта приложения, поэтому очень важно понять процесс инициализации приложения.
2.2 Переменные Islibrary
Переменная Islibrary является одной из глобальных переменных флагов, определенных в системе. Если значение Islibrary верно, это означает, что программный модуль является библиотекой динамических ссылок, в противном случае это исполняемая программа. Некоторые процессы в библиотеке классов VCL завершают различные действия на основе различных значений этой переменной флага. То есть эта переменная играет ключевую роль в решении аномальной задачи Delphi.
Как упоминалось ранее, для удобства было создано невидимое окно, когда был инициализирован объект приложения (то есть окно с «tapplication» как имя класса, которое можно увидеть с такими инструментами, как Spy ++), но также из -за этого невидимого окна производит Программы, разработанные с Delphi, показывают много нарушений. Хорошо, если мы сможем удалить это невидимое окно (и одновременно удалить меню системы панели задач) и заменить его на наше главное окно приложения, разве все проблемы не будут решены?
Это просто, но требуется ли серьезная операция для реализации исходного кода VCL? Разве это не было бы немного поставить телегу перед лошадью? Конечно, ответ - нет, в противном случае эта статья не была бы доступна. Я хочу сказать здесь, что в следующем анализе мы увидим, что так называемый «способ программирования лежит в одном уме», практика непреднамеренной посадки ивы в дизайне TAPPLICATION фактически оставляет нам решение этой проблемы .. Если вы не проводите анализ исходного кода, вам, возможно, придется ходить по кругу, но на самом деле мы увидим, что гениальный дизайн оставляет нас не более или менее, как раз правильно.
Откройте конструктор создать класс Tapplication, и мы найдем такую строку кода.
конструктор tapplication.create (aowner: tcomponent);
Начинать
...
Если нет Islibrary , то CreateHandle;
...
конец ;
Здесь сказано, что если модуль программы не является библиотекой динамической ссылки, то выполните CreateHandle, а работа, выполненная CreateHandle Окно « - это невидимое окно, упомянутое выше, которое является виновным. Это для завершения различных действий в соответствии со значением Islibrary, потому что в библиотеках динамических ссылок циклов сообщений, как правило, не требуются, а для использования объектов приложения для разработки библиотек динамических ссылок с VCL, поэтому вот проект. Хорошо, нам просто нужно обмануть объект приложения, назначить Islibrary true до его создания, и отфильтровать выполнение CreateHandle и удалить это раздражающее окно.
Код, назначенный Islibrary, должен быть помещен в сегмент кода инициализации определенной единицы. Создан объект приложения, в файле проекта мы должны разместить устройство, содержащее код назначения перед блоком форм следующим образом (при условии, что устройство называется UnitDllexe.PAS):
Шаблон программы ;
Использование
UnitDllexe в 'UnitDllexe.pas',
Формы,
Formmain в 'formmain.pas' {mainform},
...
Список кода UnitDllexe.PAS выглядит следующим образом:
единица UnitDllexe;
интерфейс
Выполнение
Инициализация
Islibrary: = true;
// Скажите объекту Applciation, что это библиотека динамических ссылок, и ему не нужно создавать скрытые окна.
конец .
Хорошо, составьте и запустите его. окна Но проблема в том, что окно не может быть сведено к минимуму. Что происходит? Это все еще старый путь, следуйте за ним.
2.3 Минимизация основного окна
Минимизация принадлежит к системным командам, и в конечном итоге она должна быть названа функцией API DefWindowProc, чтобы минимизировать окно, поэтому мы обнаружили, что функция WmsyScommand в Tcustomform, которая отвечает на сообщение WM_SYSCOMMAND без каких -либо трудностей, которое четко записывает, чтобы перенаправить минимизированное сообщение на приложение. .Wndproc для обработки:
Процедура tcustomform.wmsyscommand ( var Сообщение: Twmsyscommand);
Начинать
с сообщением
Начинать
if (cmdtype и $ fff0 = sc_minimize) и (application.mainform = self) тогда
Application.wndproc (tmessage (сообщение))
...
конец ;
конец ;
В Application.wndproc минимальный метод приложения вызывается в ответ на минимизированное сообщение, поэтому суть проблемы должна быть в процессе минимизации.
процедура tapplication.wndproc ( var Сообщение: tmessage);
...
Начинать
...
с сообщением
случай MSG OF
Wm_syscommand:
case wparam и $ fff0
Sc_minimize: минимизировать;
SC_Restore: RESTORE;
еще
По умолчанию;
...
конец ;
Наконец, найдите tapplication.minimize, и вы все поймете. Призыв к функции DefWindowProc здесь не дает никакого эффекта, почему? Поскольку мы обманывали объект приложения ранее, отфильтровали вызов CreateHandle и не создавал окно, необходимое для ответа на сообщение объекта приложения, ручка Fhandle равен 0, а вызов, конечно, неудачный. Если вы сможете указать на наше основное окно приложения, это решит проблему.
Процедура tapplication.minimize;
Начинать
...
Defwindowproc (fhandle, wm_syscommand, sc_minimize, 0);
// значение fhandle здесь 0
...
конец ;
3 реализация
Непреднамеренный дизайн гений Борланда снова позволил нам решить проблему. Из предыдущего анализа мы знаем, что в библиотеке динамических ссылок, разработанной с VCL, нет скрытого окна для получения сообщений Windows (CreateHandle не выполняется), но в библиотеке динамических ссылок, если вы хотите отобразить окно, вам нужно родительское окно. Как решить эту проблему? VCL Designer разрабатывает переменную Fhandle, которая содержит невидимые ручки с окнами в качестве записи, поэтому мы можем просто присвоить значение fhandle, чтобы предоставить родительское окно для окна ребенка, которое необходимо отобразить. Например, в подключателе библиотеки динамической ссылки для отображения формы мы обычно передаем дескриптор объекта приложения через функцию библиотеки динамических ссылок в исполняемом файле основного модуля и назначаем его приложению. Руководитель динамического Библиотека ссылок в исполняемом файле основного модуля и присваивается его приложению. Руководитель библиотеки динамических ссылок в приложении.
Процедура SetApplicationHandle (mainAppwnd: hwnd)
Начинать
Application.handle: = mainAppwnd;
конец ;
Хорошо, так как нанесение нанесения нанесения. Рука - это всего лишь ручка окон, которая используется внутри, для ответа на сообщения, а невидимое окно, которое должно было быть создано Это достаточно, чтобы просто скрыть ручку первоначально ненужного окна? Где я могу найти такое окно? Основное окно приложения является лучшим выбором, поэтому доступен следующий код.
Шаблон программы ;
Использование
UnitDllexe в 'UnitDllexe.pas',
Формы,
Formmain в 'formmain.pas' {mainform};
{$ R *.res}
Начинать
Application.initialize;
Application.createform (tformmain, formmain);
Application.handle: = formmain.handle;
Application.Run;
конец .
Итак, все проблемы были решены. Вам не нужно вносить какие -либо изменения в исходный код VCL, и вам не нужно вносить какие -либо изменения в исходную программу. из трех строк кода, чтобы ваше окно приложения было так же нормально, как и любое стандартное окно Windows.
1) Панель задач и панель заголовка окна имеет последовательные системы системы.
2) Существует эффект анимации, когда главное окно минимизируется.
3) Окно может быть расположено и склонен с другими окнами.
4) Когда есть модальное окно, оно не может работать в своем родительском окне.
Приведенный выше код реализации используется во всех версиях Delphi.