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

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

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

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

GUI-приложение: C Runtime -> ‘main’ функция (сгенерированная компилятором) -> ‘WinMain’ (ручная кодировка)

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

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

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

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

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

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

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

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

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

    [В программировании на Windows] Почему не была указана точка входа приложения main? Ну, во-первых, название 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 должна будет добавить свои параметры в конец самой длинной существующей версии main, а затем вам придется скрестить пальцы и надеяться, что язык C никогда не добавил другую альтернативную версию main. Если вы пошли по этому маршруту, ваши скрещенные пальцы вам не дали, потому что выяснилось, что третий параметр был добавлен в основное время спустя некоторое время, и это противоречило вашей версии, совместимой с Windows.

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

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

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

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

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