Автор работы: Пользователь скрыл имя, 03 Ноября 2014 в 16:17, лекция
Windows поддерживает два типа приложений: основанные на графическом интерфейсе (graphical user interface, GUI) и консольные (console user interface, CUI). У приложений первого типа внешний интерфейс графический, GUI-приложения создают окна, имеют меню, взаимодействуют с пользователем через диалоговые. Почти все стандартные программы Windows — Notepad, Calculator, Wordpad и др — являются GUI-приложениями. Приложения консольного типа работают в текстовом режиме: они не формируют окна, не обрабатывают сообщения и не требуют GUI. И хотя консольные приложения на экране тоже размещаются в окне, в нем содержится только текст. Командные процессоры вроде Cmd.exe (в Windows 2000) или Command.com (в Windows 98) — типичные образцы подобных приложений.
Системное программирование
Лекция № 2
План лекции
Windows поддерживает два типа приложений: основанные на графическом интерфейсе (graphical user interface, GUI) и консольные (console user interface, CUI). У приложений первого типа внешний интерфейс графический, GUI-приложения создают окна, имеют меню, взаимодействуют с пользователем через диалоговые. Почти все стандартные программы Windows — Notepad, Calculator, Wordpad и др — являются GUI-приложениями. Приложения консольного типа работают в текстовом режиме: они не формируют окна, не обрабатывают сообщения и не требуют GUI. И хотя консольные приложения на экране тоже размещаются в окне, в нем содержится только текст. Командные процессоры вроде Cmd.exe (в Windows 2000) или Command.com (в Windows 98) — типичные образцы подобных приложений.
Вместе с тем граница между двумя типами приложений весьма условна. Можно, например, создать консольное приложение, способное отображать диалоговые окна. Скажем, в командном процессоре вполне может быть специальная команда, открывающая графическое диалоговое окно со списком команд. В то же время можно создать и GUI-приложение, выводящее текстовые строки в консольное окно.
Когда создается проект приложения, Microsoft Visual C++ устанавливает такие ключи для компоновщика, чтобы в исполняемом файле был указан соответствующий тип подсистемы. Для CUI-программ используется ключ /SUBSYSTEM:CONSOLE, а для GUI-приложений — /SUBSYSTEM:WINDOWS. Когда пользователь запускает приложение, загрузчик операционной системы проверяет номер подсистемы, хранящийся в заголовке образа исполняемого файла, и определяет, что это за программа — GUI или CUI. Если номер указывает на приложение последнего типа, загрузчик автоматически создает текстовое консольное окно, а если номер свидетельствует о противоположном — просто загружает программу в память. После того как приложение начинает работать, операционная система больше не интересуется, к какому типу оно относится.
Во всех Windows-приложениях должна быть входная функция. Существует четыре такие функции:
int WINAPI WinMain (HINSTANCE hinstExe, HINSTANCE,
PSTR pszCmdLine, int nCmdShow);
int WINAPT wWinMain (HINSTANCE hinstExe, HINSTANCE,
PWSTR pszCmdLine, int nCmdShow);
int _cdecl main (int argc, char*argv[], char*envp[]);
int _cdecl wmain (int argc, wchar_t*argv[], wchar_t*envp[]);
На самом деле входная функция операционной системой не вызывается. Вместо этого происходит обращение к стартовой функции из библиотеки С++. Она инициализирует библиотеку С++, а также обеспечивает корректное создание любых объявленных глобальных и статических С++-объектов до того, как начнется выполнение кода. В следующей таблице показано, в каких случаях реализуются те или иные входные функции.
Тип приложения |
Входная функция |
Стартовая функция |
GUI-приложение, работающее с ANSI-символами и строками |
WinMain |
WinMainCRTStartup |
GUI-приложение, работающее с Unicode-символами и строками |
wWinMain |
wWinMainCRTStartup |
GUI-приложение, работающее с ANSI-символами и строками |
main |
mainCRTStartup |
GUI-приложение, работающее с Unicode-символами и строками |
wmain |
wmainCRTStartup |
В проекте можно вообще не указывать ключ /SUBSYSTEM компоновщика, тогда компоновщик будет сам определять подсистему для приложения. При компоновке он проверит, какая из четырех функций (WinMain, wWinMain, main или wmain) присутствует в коде, и на основании этого выберет подсистему и стартовую функцию из библиотеки С++.
Все стартовые функции из библиотеки С++ делают практически одно и то же. Разница лишь в том, какие строки они обрабатывают (в ANSI или Unicode) и какую входную функцию вызывают после инициализации библиотеки. А теперь рассмотрим, какие операции они выполняют:
Когда входная функция возвращает управление, стартовая обращается к функции exit библиотеки С++ и передает ей значение nMainRetVal. Функция exit выполняет следующие операции:
При создании новому процессу передается командная строка. В этой строке как минимум содержится имя исполняемого файла, использованного при создании этого процесса. Параметр pszCmdLine, передаваемый в функцию (w)WinMain представляет собой командную строку без имени исполняемого файла. Причем для функции WinMain – это ANSI-строка, а для wWinMain - Unicode-строка. Указатель на полную командную строку можно получить вызвав функцию
PTSTR GetCommandLine();
Эта функция возвращает указатель на буфер содержащий командную строку с полным именем (с путем) исполняемого файла. Но чаще всего удобнее использовать командную строку, предварительно разбитую на отдельные компоненты. В таком виде командную строку можно получить через глобальные переменные
unsigned int __argc; //количество компонентов
char**__argv; //массив указателей на ANSI-строки
wchar_t**__wargv; //массив указателей на Unicode-строки
С любым процессом связан блок переменных окружения. Каждая переменная имеет имя и значение. Получить значение переменной окружения можно при помощи функции
DWORD GetEnvironmentVariable (LPCTSTR lpName,
LPTSTR lpBuffer, DWORD nSize);
Через параметр lpName в функцию передается имя переменной окружения, lpBuffer – это указатель на буфер, в который будет помещено значение указанной переменной. Размер передаваемого буфера задается параметром nSize. Многие переменные окружения и строки в реестре имеют формат
%USERPROFILE%\My Documents
Для подстановки действительных значений переменных окружения в таких строках используется функция ExpandEnvironmentStrings:
DWORD ExpandEnvironmentStrings (LPCTSTR lpSrc, LPTSTR lpDst,
Первым параметром этой функции передается исходная строка, содержащая подставляемые части. Второй и третий параметры представляют собой буфер для строки результата и количество символов (не байтов!!!) в выделенном буфере. Приведенная в качестве примера строка может быть преобразована в следующий вид
C:\Documents and Settings\Administrator\My Documents
Кроме получения значений переменных окружения и использования их для подстановки в строки программа может изменять их значения. Для этого предназначена функция SetEnvironmentVariable:
DWORD SetEnvironmentVariable(PCTSTR pszName,
PCTSTR pszValue);
Эта функция устанавливает переменной окружения pszName значение pszValue. Если значение параметра pszValue равно NULL, то соответствующая переменная удаляется из блока.
Текущий каталог текущего диска – это то место, где системные функции ищут файлы и подкаталоги, если не указаны полные пути к файлам. Поток может получать и устанавливать текущие диск и каталог с помощью следующих функций:
DWORD GetCurrentDirectory(DWORD cchCurDir, PTSTR pszCurDir);
BOOL SetCurrentDirectory(PCTSTR pszCurDir);
Информация о работе Программы Win32: консольная (CUI) и оконная (GUI)