Delphi: Что такое Application.Handle?

45

Что такое TApplication.Handle?

  • Откуда он?
  • Почему он существует?
  • И самое главное: почему все формы имеют его как дескриптор родительского окна?

Справка Delphi говорит:

TApplication.Handle

Предоставляет доступ к дескриптору окна основной формы (окна) приложение.

property Handle: HWND;

Описание

Использовать Handle при вызове Windows API функции, требующие родительского окна ручка. Например, DLL, которая отображает собственное всплывающее окно верхнего уровня для окон требуется родительское окно для отобразить его окна в выражение. Использование свойства Handle делает такие окна частью приложения, чтобы они были минимизированы, восстановлены, включены и отключено приложением.

Если я сосредоточусь на словах "дескриптор окна основной формы приложения", и я считаю, что это означает дескриптор окна основной формы приложения, то я могу сравнить:

  • "дескриптор окна основной формы приложения",
  • дескриптор окна MainForm Application

но они не совпадают:

Application.MainForm.Handle: 11473728
Application.Handle: 11079574

Итак, что такое Application.Handle?

  • Откуда он?
  • Что такое Windows & reg; дескриптор окна?
  • Если , Windows & reg; дескриптор окна Application MainForm, то почему они не соответствуют?
  • Если это не дескриптор окна Application MainForm, то что это такое?
  • Что еще важнее: почему он является основным родителем каждой формы?
  • И самое главное: почему все происходит с haywire, если я пытаюсь иметь форму, не имеющую аналогов (так что она может появиться на TaskBar) или попытаться использовать что-то вроде IProgressDialog?

Действительно, я спрашиваю: что такое обоснование дизайна, которое делает Application.Handle существующим? Если я смогу понять, почему, то как должно стать очевидным.


Обновить Понимание игры из двадцати вопросов:

Говоря о том, что решение о создании окна появляется на панели задач, сделав его владельца null, Питер Ниже в 2000 году сказал:

Это может вызвать некоторые проблемы с модальными формами, показанными на вторичные формы.

Если пользователь отключается от приложения, а модальный форма вверх, а затем обратно в форму, которая показала ее, модальная форма может спрятаться под формой. С этим можно справиться, убедившись модальная форма родилась на форме, которая показала ее (используя `params.WndParent``, как указано выше)

Но это невозможно в стандартном диалогов из блока Dialogs и исключений, которые требуют больше усилий для заставить их работать правильно (в основном обработка Application.OnActivate, ищет модальные формы, родившиеся для Приложения через GetLastActivePopupи доводя их до вершины Z-порядка через SetWindowPos).

  • Почему модальная форма заканчивается за другими формами?
  • Какой механизм обычно переносит модальную форму на передний план и почему она не работает здесь?
  • Окно & рег; отвечает за отображение стеков окон. Что пошло не так, что Windows & reg; не показывает правильные окна?

Он также рассказывал об использовании нового расширенного стиля Windows, который заставляет окно появляться на панели задач (когда обычные правила его неактуальности недостаточны, непрактичны или нежелательны), добавив расширенный стиль WS_EX_APPWINDOW

procedure TForm2.CreateParams(var Params: TCreateParams); 
begin 
   inherited CreateParams( params ); 

   Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; 
end; 

Но затем он предупреждает:

Если вы нажмете на кнопку панели задач вторичной формы, в то время как другое приложение active это все равно приведет к появлению всех форм приложений. если ты не хотите, чтобы есть опция

Кто приносит все формы на фронт, когда владелец формы все еще Application.Handle. Является Приложением это? Почему он это делает? Вместо этого, не следует ли это делать не? В чем заключается недостаток не; я вижу недостаток делать (системное меню не работает должным образом, миниатюры кнопок на панели задач неточны, Windows & reg; оболочка не может свести к минимуму окна.


В другом сообщении, посвященном Application, Майк Эденфилд говорит, что родительское окно отправляет другому окну сводку, максимизацию и восстановление сообщений:

Это добавит кнопку панели задач для вашей формы, но есть еще несколько мелких деталей для ручка. Наиболее очевидно, что ваша форма по-прежнему получает сведения об уменьшении/максимизации, которые отправляются родителям форма (основная форма заявки). Чтобы этого избежать, вы можете установить сообщение обработчик для WM_SYSCOMMAND, добавив строку, например:

procedure WMSysCommand(var Msg: TMessage); WM_SYSCOMMAND; 

procedure TParentForm.WMSysCommand(var Msg: TMessage); 
begin 
   if Msg.wParam = SC_MINIMIZE then 
   begin 
      // Send child windows message, don't 
      // send to windows with a taskbar button. 
   end; 
end; 

Обратите внимание, что этот обработчик находится в форме PARENT той, которую вы хотите вести независимо от > остальной части приложения, чтобы избежать передачи сообщения минимизации. Вы можете добавить аналогичный код для SC_MAXIMIZE, SC_RESTORE и т.д.

Как это минимизировать/максимизировать/восстановить сообщения для моей Windows & reg; окна не ходят в мое окно? Это потому, что сообщения, предназначенные для окна, отправляются Windows & reg; владельцу окна? И в этом случае все формы в приложении Delphi "принадлежат" Application? Не означает ли это, что владелец null:

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
   inherited;
   Params.WndParent := 0; //NULL
end;

удалит Application, и это окно Handle из-за вмешательства в мою форму, и Windows должна снова отправить мне мои сообщения mimimize/maximize/restore?


Возможно, если бы мы сравнивали и сопоставляли теперь "нормальное" приложение Windows, это делало то, как Borland изначально разрабатывал приложения Delphi для выполнения каких-либо действий - в отношении этого объекта Application и его основного цикла.

  • Каким решением было решение Application?
  • Какие изменения были внесены в более поздних версиях Delphi, чтобы эти же проблемы не существовали?
  • Не изменилось ли изменение в более поздних версиях Delphi других проблем, которые так сильно решались в дизайне приложения?
  • Как эти новые приложения могут работать без приложения, препятствующего им?

Очевидно, Borland осознал недостаток в своем первоначальном дизайне. Каков был их первоначальный дизайн, какая проблема была в его решении, каков недостаток, какой был перепроектирован и как он решает проблему?

  • 0
    Я думаю, вам будет интересно узнать об этих двух хитростях: yoy.be/item.asp?i89 yoy.be/item.asp?i87
  • 2
    @ Стинх Сандерс: я видел их, они не решают проблемы. Кроме того, никогда, никогда, никогда не передавайте GetDesktopWindow как владельца окна, как предполагают те и другие посты по теме. Это обычно приводило к зависанию Windows. Это была такая проблема, что Microsoft пропатчила CreateWindow, поэтому любой, кто передает GetDesktopWindow в качестве владельца, меняется на использование NULL. И если бы я мог редактировать этот пост на yoy.com , я бы сделал .
Показать ещё 1 комментарий
Теги:
delphi-5

3 ответа

47
Лучший ответ

Причиной для окна приложения является немного грубая история. При разработке Delphi 1 мы знали, что хотим использовать "SDI" (окна, разбросанные по всему рабочему столу) для модели IDE. Мы также знали, что Windows высасывает (и все еще делает) эту модель. Однако мы также заметили, что Visual Basic в то время использовал эту модель, и она, похоже, хорошо работала. После дальнейшего изучения мы обнаружили, что VB использовал специальное "скрытое" окно парковки, которое использовалось как "владелец" (Windows иногда размывает понятие родителя и владельца, но это отличие похоже на VCL) для всех других видимых окон.

Так мы решили "проблему", когда окна, содержащие основное меню, редко фокусировались, поэтому обработка Alt-F для меню "Файл" просто не сработала. Используя это центральное окно парковки в качестве посредника, мы могли бы легче отслеживать и маршрутизировать сообщения в соответствующие окна.

Эта схема также решила еще одну проблему, когда обычно несколько окон верхнего уровня были полностью независимыми. Сделав приложение обработчиком "владельца" всех этих окон, все они будут вести себя согласованно. Например, вы, возможно, заметили, что при выборе любого окна приложения все окна приложений перемещаются на передний план и сохраняют их z-порядок относительно друг друга. Это также позволит минимизировать и восстановить приложение в качестве функциональной группировки.

Это следствие использования этой модели. Мы могли бы вручную выполнить всю эту работу, чтобы все было в порядке, но философия дизайна заключалась в том, чтобы не изобретать Windows, а использовать ее там, где мы могли. Вот почему TButton или TEdit - это действительно класс и стиль окна "Пользователь" BUTTON и EDIT соответственно.

По мере развития Windows эта модель "SDI" стала неаккуратной. Фактически Windows сама стала становиться "враждебной" к этому стилю приложения. Начиная с Windows Vista и продолжая до 7, пользовательская оболочка, похоже, не работает с приложением, используя окно парковки. Итак, мы решили перетасовать вещи в VCL, чтобы устранить окно парковки и переместить его функцию в основную форму. Это показало несколько проблем "курица и яйцо", в результате чего нам нужно иметь окно парковки, доступное достаточно рано в инициализации приложения, чтобы другие окна могли "прикрепить" к нему, но сама основная форма не может быть построена достаточно скоро. TApplication должен проскользнуть через несколько обручей, чтобы заставить это работать, и было несколько тонких краевых случаев, которые вызвали проблему, но большинство проблем было разработано. Тем не менее, для любого приложения, которое вы продвигаете вперед, оно останется с использованием старой модели окна парковки.

  • 3
    +1 интернет. И принято.
  • 1
    +1 за признание того, что это было противно. А взломы Windows XP, добавленные на уровень управления окнами Microsoft, стали частью смерти этой системы, так как начали появляться неожиданные ошибки Z-Order при запуске приложений Delphi 7 на XP.
Показать ещё 1 комментарий
11

Все приложения VCL имеют "скрытое" окно верхнего уровня, называемое Application. Это автоматически создается при запуске приложения. Среди прочего, это основной обработчик сообщений Windows для VCL - следовательно Application.ProcessMessages.

Наличие скрытого окна верхнего уровня приложений вызывает некоторые странные вещи, заметно неполное системное меню, которое отображается на панели задач, и неправильные окна ногтей пальцев в Vista. Более поздние версии Delphi исправляют это.

Однако не все окна должны иметь его как родительский, Windows просто работает лучше, если это так. Однако любая форма, созданная с помощью Application.CreateForm, будет иметь ее как родительскую, и она также будет принадлежать объекту Application. Поскольку они принадлежат, они будут освобождены после того, как приложение будет освобождено. Это происходит за кулисами в Forms.DoneApplication

  • 3
    Для форм верхнего уровня вашего приложения свойство Parent не установлено в окне приложения! Только Владелец установлен на объект Приложения. Просто для пояснения: Application.ProcessMessages обрабатывает сообщения для ВСЕХ окон в главном потоке (все окна VCL), это фактически шаг в обычном цикле обработки сообщений, который есть во всех приложениях Windows GUI.
  • 0
    @Ritsaert Hornstra: Что делать обрабатывать верхние формы на уровне моего приложения имеют в качестве родителя? Также обратите внимание, что любые формы, которые я создаю , имеют Application.Handle качестве родителя.
Показать ещё 7 комментариев
7

От взгляда на источник в forms.pas(Delphi 2009), похоже, что они создают "главное" окно в приложениях win32 gui для разрешения вызовов

  • TApplication.Minimize
  • TApplication.Restore
  • и т.д.

Похоже, что сообщения, переданные в Application.Handle, перенаправляются в соответствии с MainForm, если они существуют. Это позволит приложению реагировать на минимизацию и т.д., Если главное окно не было создано. Изменив источник проекта, вы можете создать приложение delphi без главного окна.

В этом случае методы TApplication будут работать, даже если вы не создали главное окно. Не уверен, что я хватаю все цели, но у меня нет времени, чтобы пройти весь код TApplication.

По всем вопросам:

  • Откуда он? Это дескриптор окна, созданного в TApplication.Create

  • Что такое дескрипторы Windows? поддельное окно, которое требуется каждому приложению gui delphi как часть абстракции TApplication

  • Является ли это дескриптором окна основной формы приложения Нет

  • Если это не дескриптор приложения mainform, то что это такое? См. выше

  • : почему он является конечным родителем каждой формы?, полагая, что вы правы, что его конечный родитель, я предполагаю, что это так, потому что это позволяет легко найти все формы в вашем приложении (перечисление детей этой "основной" формы).

  • , и самое главное: почему все идет с трудом, если я пытаюсь получить форму без унифицированного Я думаю, потому что скрытая "основная" форма получает системные сообщения, которые она должна передать его детей и/или основной формы, но не могут найти несравненную форму.

Во всяком случае, я беру на себя это. Вероятно, вы можете узнать больше, посмотрев декларацию TApplication и код в forms.pas. Суть в том, что я вижу, это удобная абстракция.

С уважением,

Дон

  • 2
    В Delphi 2007 VCL изменил значение по умолчанию на отсутствие скрытого окна, но вы также можете выбрать старый способ, если это поможет. Скрытое окно остановило предварительный просмотр Windows 7.
  • 0
    @ mj2008: есть ли у вас ссылка для получения дополнительной информации об этом? В настоящее время я обновляю проект из C ++ Builder 2006 -> C ++ Builder 2009, и я считаю, что вижу мой Application-> Handle ptr как NULL. Так ли это сейчас в Builder 2009? И если так, будет ли использование MainForm-> Handle хорошей заменой?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню