Зачем делать первый вызов ShowWindow ()?

Во-первых, я только совсем недавно начал изучать WinAPI. Я уверен, что этот вопрос задавали много раз раньше, но по какой-то причине я нигде не могу найти его в Интернете. Вопрос просто в следующем; зачем возиться с первоначальным вызовом ShowWindow() в теле WinMain() перед выполнением цикла сообщений? Почему бы просто не установить изначально видимое окно с помощью флага WS_VISIBLE?

У меня также есть вопросы по механике работы функции ShowWindow(). Какие сообщения он на самом деле отправляет? В MSDN говорится, что:

If a window has the WS_VISIBLE style when it is created, the window receives this message [WM_SHOWWINDOW] after it is created, but before it is displayed. A window also receives this message when its visibility state is changed by the ShowWindow or ShowOwnedPopups function.

Означает ли это, что основным средством связи между функцией ShowWindow() и Windows является сообщение WM_SHOWWINDOW? В нем также говорится, что:

The WM_SHOWWINDOW message is not sent under the following circumstances:

  • When a top-level, overlapped window is created with the WS_MAXIMIZE or WS_MINIMIZE style.

  • When the SW_SHOWNORMAL flag is specified in the call to the ShowWindow function.

В MSDN также говорится, что:

The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter.

Петцольд заявляет, что аргумент, передаваемый этому параметру nCmdShow, будет либо SW_SHOWNORMAL, либо SW_SHOWMAXIMIZED, либо SW_SHOWMINNOACTIVE. Должен ли я брать из этого, что единственный раз, когда функция ShowWindow() не отправляет сообщение WM_SHOWWINDOW, - это когда мы делаем этот самый первый первоначальный вызов в Winmain()? Если да, то как затем заставить окно отображаться? Кроме того, как все это связано с фактической окраской окна?

Извините, если мой вопрос представляет собой беспорядочный беспорядок, но механика отображения окна сбивает меня с толку, и по какой-то причине трудно найти четкие ответы на эти вопросы в Интернете (в отличие от просто кусочков информации ). Мы будем благодарны за любую помощь в прояснении всего этого!

Если вы используете стиль WS_VISIBLE в главном окне, тогда система неявно вызывает ShowWindow (конечно, функцию win32k в ядре). По умолчанию используется SW_SHOW, если только x не является CW_USEDEFAULT, а y не является CW_USEDEFAULT, то есть y является некоторым значением nCmdShow.

Eryk Sun 29.05.2018 06:22

При первом вызове ShowWindow для главного окна, явно или неявно, и только в первый раз, тогда, если nCmdShow - это SW_SHOW, SW_SHOWNORMAL или SW_SHOWDEFAULT, тогда система вместо этого использует либо значение STARTUPINFOwShowWindow, если установлен флаг STARTF_USESHOWWINDOW, либо в противном случае SW_SHOWNORMAL если флаг не установлен. Значение STARTUPINFO используется только для вызова первый. Последующие вызовы ShowWindow, которые указывают SW_SHOWDEFAULT, фактически будут использовать SW_SHOWNORMAL.

Eryk Sun 29.05.2018 06:23

Что касается [w]WinMain - конечно, его значение nCmdShow - это просто значение STARTUPINFOwShowWindow, если установлен флаг STARTF_USESHOWWINDOW, и в противном случае - SW_SHOWDEFAULT.

Eryk Sun 29.05.2018 06:30

Кроме того, ответ ниже подразумевает, что у процесса не может быть STARTUPINFO. Это не имеет смысла. WinAPI STARTUPINFO - это сочетание RTL_USER_PROCESS_PARAMETERS NT и атрибутов создания (например, STARTUPINFOEXlpAttributeList). Указатель на ProcessParameters всегда существует в блоке среды процесса. Сюда входит запись WinAPI STARTUPINFO, включая WindowFlags, ShowWindowFlags, WindowTitle, DesktopInfo, ShellInfo, StandardInput и т. д. Это то, что WinAPI GetStartupInfo использует для восстановления записи STARTUPINFO.

Eryk Sun 29.05.2018 06:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
4
1 100
2

Ответы 2

Идея, лежащая в основе параметра nCmdShow для WinMain, заключается в том, что он дает Windows возможность сообщить вашему приложению, как Windows хочет, чтобы оно отображало окно. Этот механизм, вероятно, больше не полезен, но, возможно, есть крайние случаи. В любом случае вы должны передать его во все, что вы считаете своим главным окном, после того, как вы его создали. Его скрытие позволяет создавать любые дочерние окна без мерцания, что и делает большинство людей.

Я думаю, что логика, лежащая в основе того, когда WM_SHOWWINDOW отправляется и не отправляется, заключается в том, чтобы позволить вам использовать его для перехвата вызовов ShowWindow (hWnd, SW_HIDE) и ShowWindow (hWnd, SW_SHOW) в вашем оконном процессе, поскольку вполне вероятно, что вы, возможно, захотите предпринять какие-то действия в это время (например, прекратить воспроизведение аудио, например). И, возможно, также SW_MINIMIZE, SW_MAXIMIZE и SW_RESTORE, я думаю, все зависит от этого.

Это вообще помогает?

Редактировать

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

  1. Параметр nCmdShow для WinMain кажется историческим. Вместо этого первый вызов ShowWindow действует так, как если бы вы передали ему это значение, нравится вам это или нет, так что этот вызов должен быть в вашем главном окне. Тем не менее, при этом, вы могли бы также сыграть в игру и передать ее, как знать.

  2. Прочтите и поймите комментарий Ханса Пассанта к этому сообщению. Это скажет вам, откуда в пользовательском интерфейсе Windows чаще всего берется это значение.

  3. К вашему сведению, нормально создавать окна ребенок с установленным WS_VISIBLE. Вы не увидите их, пока не откроете главное окно.

Ладно, я готов. Иногда лучше меньше, да лучше.

Он по-прежнему полезен, устанавливается свойством Run ярлыка на рабочем столе. Хотя SW_HIDE намеренно опущен, это вариант вредоносной программы :)

Hans Passant 28.05.2018 14:18

@HansPassant О да, он все еще там, как в старые добрые времена.

Paul Sanders 28.05.2018 15:11

Спасибо, помогло. Таким образом, идея вызова ShowWindow() состоит в том, чтобы иметь возможность фактически определять дополнительные элементы клиентской области (например, дочерние окна) до фактического отображения главного окна, чтобы предотвратить возможное возникновение определенной «задержки», когда главное окно уже открыто. отображается, но некоторые элементы его клиентской области все еще создаются? Кроме того, вы, вероятно, правы насчет использования WS_SHOWWINDOW (хотя я обнаружил, что он отправляется только при изменении видимости окна, для минимизации / максимизации / восстановления вместо этого отправляется сообщение WM_SIZE).

PvtWitt 29.05.2018 11:37

О, хорошо, в этом [WM_SIZE] есть смысл. Я также вижу, перечитывая документация, что есть другие обстоятельства, при которых отправляется WM_SHOWWINDOW. А по поводу ShowWindow (), в основном, да.

Paul Sanders 29.05.2018 12:36

Если вы не используете WS_VISIBLE и, следовательно, явно вызываете ShowWindow, вам не нужно использовать значение nCmdShow, которое передается WinMain реальной точкой входа C / C++. Это избыточность устаревшего программирования для Windows. nCmdShow поступает от ProcessParameters, если установлен флаг STARTF_USESHOWWINDOW, в противном случае - от SW_SHOWDEFAULT. Диспетчер окон уже по умолчанию использует это значение при первом вызове ShowWindow для главного окна с помощью SW_SHOW, SW_SHOWNORMAL или SW_SHOWDEFAULT. Все, что касается WinMain, можно игнорировать. Это просто чушь.

Eryk Sun 30.05.2018 00:12

why bother with the initial call to ShowWindow() in the body of WinMain() before the execution of the message loop?

Ответ находится в документации ShowWindow():

nCmdShow

Controls how the window is to be shown. This parameter is ignored the first time an application calls ShowWindow, if the program that launched the application provides a STARTUPINFO structure. Otherwise, the first time ShowWindow is called, the value should be the value obtained by the WinMain function in its nCmdShow parameter.

Если приложение запускается пользователем, STARTUPINFO отсутствует, и следует использовать nCmdShow из WinMain(), чтобы определить, как должен отображаться ваш основной пользовательский интерфейс (или нет).

Если приложение запускается системой или другим приложением, скорее всего, это STARTUPINFO, поэтому вам следует игнорировать nCmdShow из WinMain() и использовать вместо него nCmdShow из STARTUPINFO.

Вызов ShowWindow() обрабатывает оба условия за вас. Но если вы заставляете окно отображаться с помощью VS_VISIBLE, вы не уважаете то, как вызывающий абонент хочет, чтобы ваше приложение отображалось (или нет) при запуске.

Спасибо за Ваш ответ. По словам Петцольда, использование аргумента nCmdShow из WinMain() действительно относится только к «предпочтениям, которые пользователь устанавливает при добавлении программы в меню« Пуск »». Я даже не уверен, возможно ли это. Мне кажется, что либо по умолчанию используется SW_SHOWNORMAL (в зависимости от спецификации программы), либо SW_SHOWDEFAULT (когда задействован родительский процесс). Я думаю, что отсутствие флага WS_VISIBLE гораздо больше связано с ответом Пола Сандерса, который дал выше.

PvtWitt 29.05.2018 12:17

@PvtWitt "Я даже не уверен, возможно ли это." - конечно все еще возможно. Ярлыки можно создавать в любом месте файловой системы, а не только в меню «Пуск».

Remy Lebeau 29.05.2018 16:51

@PvtWitt, ОС не вызывает [w]WinMain. Он вызывает исполняемую точку входа с указателем на его блок среды процесса (PEB), который сам по себе является избыточным параметром, поскольку поток может легко получить TEB и PEB. Для приложения Microsoft C / C++ реальная точка входа вызывает GetStartupInfo для восстановления записи STARTUPINFO из ProcessParameters PEB, каждый из которых обрабатывает должны быть. Если флаг STARTF_USESHOWWINDOW не установлен, точка входа C / C++ по умолчанию принимает значение SW_SHOWDEFAULT при вызове вашей функции [w]WinMain.

Eryk Sun 29.05.2018 23:59

@RemyLebeau Мои извинения, вы абсолютно правы. Спасибо за ответы!

PvtWitt 06.06.2018 14:47

Другие вопросы по теме