Функция WinMain
Функция WinMain не имеет никаких особенностей. Сразу после запуска приложения она сохраняет идентификатор приложения в глобальной переменной hInst и проверяет, нет ли в памяти копии приложения, запущенной раньше. Для такой проверки используется методика, основанная на вызове функции FindWindow и описанная в предыдущем томе “Библиотеки системного программиста”, посвященного программированию для операционной системы Microsoft Windows NT. Если будет найдена копия работающего приложения, его окно выдвигается на передний план при помощи функций ShowWindow и SetForegroundWindow.
Далее функция WinMain регистрирует класс главного окна прилжения, создает и отображает это окно, а затем запускает цикл обработки сообщений.
Функция WinMain проверяет существование запущенной ранее копии приложения. Если такая копия будет обнаружена, окно работающей копии активизируется и выдвигается на передний план. Если нет - функция WinMain выполняет обычную инициализацию приложения, создавая его главное окно и запуская цикл обработки сообщений.
Функция WinMain приложения RCLOCK сразу после запуска приложения выполняет поиск своей копии, используя для этого функцию FindWindow. Если такая копия найдена, главное окно этой копии выдвигается на передний план функцией SetForegroundWindow, после чего работа функции WinMain завершается. Такая техника уже использовалась нами ранее.
В том случае, когда запускается первая копия приложения RCLOCK, функция WinMain выполняет обычные действия. Она регистрирует класс окна и создает главное окно приложения. Для того чтобы это окно имело вид, показанный на рис. 2.2, для него указываются стили WS_POPUPWINDOW и WS_THICKFRAME:
hWnd = CreateWindow(szAppName, szAppTitle,
WS_POPUPWINDOW | WS_THICKFRAME,
100, 100, 100, 100, NULL, NULL, hInst, NULL);
Для определения размеров и расположения главного окна приложения RCLOCK функция WinMain определяет размеры окна рабочего стола, сохраняя их в глобальной переменной rc:
GetWindowRect(GetDesktopWindow(), &rc);
Размещение главного окна приложения RCLOCK выполняется функцией MoveWindow, как это показано ниже:
MoveWindow(hWnd,
rc.right - cxChar * 25, rc.bottom - cyChar * 3,
cxChar * 10, cyChar * 2, TRUE);
Заметим, что метрики шрифта cxChar и cyChar определяются при обработке сообщения WM_CREATE, который получает управление при вызове функции CreateWindow. Поэтому после возвращения из функции CreateWindow содержимое глобальных переменных cxChar и cyChar будет отражать размеры рабочего стола.
После изменения размеров и расположения главного окна приложения RCLOCK выполняется отображение этого окна и запуск обычного цикла обработки сообщений.
После поиска своей собственной копии приложение STIME ищет окно серверного приложения RCLOCK:
hWndServer = FindWindow(szServerAppName, NULL);
Если это приложение не найдено, выдается сообщение об ошибке, вслед за чем работа приложения STIME завершается.
В случае успешного поиска идентификатор найденного окна приложения RCLOCK записывается в глобальную переменную hWndServer. Вслед за этим выполняется процедура регистрации класса главного окна приложения STIME, создается главное окно приложения и запускается обычный цикл обработки сообщений.
Функция WinMain сохраняет идентификатор прилождения в глобальной переменной hInst а затем проверяет, не было ли это приложение уже запущено. Если было, главное окно приложения выдвигается на передний план.
Далее функция WinMain регистрирует класс главного окна приложения, создает и отображает это окно. Затем запускается обычный цикл обработки сообщений.
Помимо выполнения обычных действий, необходимых для создания главного окна приложения, функция WinMain получает список установленных раскладок клавиатуры, сохраняя его в глобальном массиве lpList. Память для этого массива заказывается динамически, поэтому перед завершением работы приложения мы освобождаем эту память явным образом.
Для определения размера списка и для получения самого списка раскладок клавиатуры мы используем функцию GetKeyboardLayoutList:
UINT uLayouts;
HKL * lpList;
uLayouts = GetKeyboardLayoutList(0, NULL);
lpList = malloc(uLayouts * sizeof(HKL));
uLayouts = GetKeyboardLayoutList(uLayouts, lpList);