Как написать приложение Windows без использования WinMain?

Приложения Windows GUI, написанные на C/С++, имеют "WinMain" в качестве точки входа (а не "основной" ). Мое понимание этого заключается в том, что компилятор генерирует "главную" функцию, которая будет вызываться C Runtime. Эта "основная" функция устанавливает необходимую среду для графического интерфейса пользователя и вызывает "WinMain" (с указанием дескрипторов экземпляра и т.д.).

Короче говоря, я считаю, что запуск консоли и GUI-приложений различается следующим образом:

Консольное приложение: C Runtime → 'main' (ручная кодировка)

Приложение GUI: C Runtime → 'main' function (сгенерированная компилятором) → 'WinMain' (ручная кодировка)

Я хотел бы как подтвердить это понимание, так и выяснить, как я могу вручную кодировать графический интерфейс Windows с помощью только "основной" функции (т.е. без необходимости писать "WinMain" ).

Ответы

Ответ 1

У вас неправильное понимание. Разница между основным и WinMain, помимо некоторого кода инициализации differet, - это переданные ему параметры.

main выглядит следующим образом:

int main(int argc, char* argv[]);

Пока WinMain выглядит так:

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
);

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

Вы можете, конечно, написать свой собственный код запуска, просто зайдите в исходный каталог Visual С++, и вы можете найти код запуска, который называется crt0.c, и он находится в каталоге VC\crt\src.

Ответ 2

С основным, вы не можете скопировать Winmain. Для обоснований следующие утверждения были взяты из  http://blogs.msdn.com/oldnewthing/archive/2007/12/03/6644060.aspx

[В программировании на Windows] Почему не была указана точка входа приложения главный? Ну, во-первых, название main уже было принято, и У Windows не было полномочий резервировать альтернативное определение. Тогда не было комитета по стандартизации на языке С; C был что Деннис сказал, что это так, и вряд ли было гарантировано, что Деннис предпримет какие-либо специальные шаги для сохранения исходного кода Windows совместимость в любой будущей версии языка C. Поскольку K & R не указали, что реализации могут расширить приемлемые формы основной функции, вполне возможно, что существует юридическая C, который отклонил программы, которые объявили основные неправильно. текущий стандарт языка C явно разрешает специфику реализации альтернативные определения для основного, но требующие от всех компиляторов поддержки эта новая версия для Windows для компиляции программ Windows будет безвозмездно ограничивать набор компиляторов, которые вы могли бы использовать для написание программ Windows.

Если вам удастся преодолеть это препятствие, у вас возникнет проблема: версия ОС Windows должна быть примерно такой:

int main(int argc, char *argv[], HINSTANCE hinst,
         HINSTANCE hinstPrev, int nCmdShow);

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

Предположим, вам удалось убедить Денниса не допускать этого трехпараметрическая версия main. Вам все равно придется придумывать эти первые два параметра, что означает, что каждый код запуска программы должен содержать синтаксический анализатор командной строки. Назад в 16-битные дни, люди пытались сохранить каждый байт. Сообщи им: "О, и все твои программы будут на 2 КБ больше", вероятно, не заставит вас многого друзей. Я имею в виду, что четыре сектора ввода-вывода с гибкого диска!

Но, вероятно, причина, по которой точка входа Windows была другое имя должно подчеркнуть, что это другое исполнение Окружающая среда. Если бы это называлось главным, люди принимали бы C-программы предназначенные для среды консоли, бросают их в свои Windows компилятор, а затем запустить их с катастрофическими результатами.

Надеюсь, это уберет ваши сомнения.

Ответ 3

Это работает по-другому. Там статически связанный объектный файл, который поставляется вместе с компилятором, который содержит фактическую точку входа. Эта точка входа выполняет инициализацию, а затем вызывает вашу точку входа (то есть WinMain).

То, что ожидает эта статическая часть, может быть изменено. Например, в Visual Studio есть поле для имени точки входа в настройках компоновщика.