Проверка наличия предыдущего экземпляра

Задача. Окно приложения стиля временного окна с кнопкой минимизации и с фоном цвета рабочего стола Windows занимает весь экран. При попытке запуска второго экземпляра на передний план переместить окно первого экземпляра и завершить работу.

Анализ задания. (Полный текст приложения приведен ниже, в листинге 1.2.)

Для поиска других экземпляров приложения воспользуемся функцией FindWindow:

HWND hwnd = FindWindow(szMainClass, szTitle);

Она возвращает дескриптор окна класса szMainClass с заголовком szTitle. Если такого окна нет, то это первый экземпляр приложения и дескриптору hwnd присваивается NULL. Иначе, возвращается дескриптор найденного окна.

Функция FindWindow проверяет только совпадение имени класса и заголовка. То есть, если работает экземпляр другого приложения с окном класса с таким же именем szMainClass и заголовком szTitle, то функция вернет дескриптор окна другого приложения.

Если "предыдущий экземпляр приложения" обнаружен, выводим сообщение:

MessageBox(hwnd,

"Можно запускать только одну копию приложения!!!\n\n"

"Перемещаю на передний план первый экземпляр",

szTitle, МВ_ОК | MB_CONSTOP);

До перемещения окна на передний план проверяем состояние этого окна и, если оно свернуто, восстанавливаем его предыдущее состояние:

if (IsIconic(hwnd)) ShowWindow(hwnd, SW_RESTORE);

Перемещаем окно первого экземпляра приложения на передний план:

SetForegroundWindow(hwnd);

Затем второй экземпляр приложения завершает работу.

Если предыдущий экземпляр приложения не найден, регистрируем класс окна:

if (!RegClass(WndProc, szMainClass, COLOR_DESKTOP))

return FALSE;

Цвет фона окна приложения определяем по табл. 1.4 – COLOR_DESKTOP.

Для создания максимально распахнутого окна приложения определяем ширину и высоту экрана в пикселях:

int w=GetSystemMetrics(SM_CXSCREEN);

int h=GetSystemMetrics(SM_CYSCREEN);

Создаем окно:

hwnd = CreateWindow(szMainClass, szTitle,

WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE,

0, 0, w, h, 0, 0, hInstance, NULL);

Стиль временного окна с кнопкой минимизации и заголовком определяем по табл. 1.5 – WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE.

Далее активизируем цикл обработки и диспетчеризации сообщений:

while(GetMessage(&msg, 0, 0, 0))

DispatchMessage(&msg);

Это приложение не предусматривает обработки сообщений с клавиатуры. Поэтому в цикле отсутствует вызов функции трансляции клавиатурных сообщений.

Любые действия над окном передают функции окна:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch (msg)

{

case WM_DESTROY: {PostQuitMessage(0); return 0;}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

Такая функция окна ранее уже была рассмотрена.

Листинг 1.2. Запрет запуска второго экземпляра приложения.

#include <windows.h>

//Объявления функций

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hInstance;

TCHAR szMainClass[] = TEXT("MainClass");

TCHAR szTitle[]= TEXT("Пример 1.2");

//Главная функция приложения

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

MSG msg;

hInstance=hInst;

HWND hwnd = FindWindow(szMainClass, szTitle);

if (hwnd)

{

MessageBox(hwnd,

TEXT("Можно запускать только один экземпляр приложения\nПеремещаю на передний план первый экземпляр"),

szTitle, MB_OK | MB_ICONSTOP);

//Если окно свернуто, восстанавливаем

if (IsIconic(hwnd))

ShowWindow(hwnd, SW_RESTORE);

SetForegroundWindow(hwnd);

return 0;

}

if (!RegClass(WndProc, szMainClass, COLOR_DESKTOP))

return FALSE;

//До создания окна узнаем габариты экрана в пикселях

int w = GetSystemMetrics(SM_CXSCREEN)-1; //Ширина

int h = GetSystemMetrics(SM_CYSCREEN)-1; //Высота

hwnd = CreateWindow(szMainClass, szTitle, WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE, 0, 0, w, h, 0, 0, hInstance, NULL);

if (!hwnd) return FALSE;

while(GetMessage(&msg, 0,0, 0))

DispatchMessage(&msg);

return msg.wParam;

}

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc;

wc.style = wc.cbClsExtra = wc.cbWndExtra = 0;

wc.lpfnWndProc = Proc;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(brBackground + 1);

wc.lpszMenuName = (LPCTSTR)NULL;

wc.lpszClassName = szName;

return (RegisterClass(&wc)!= 0);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch (msg)

{

case WM_DESTROY:

{ PostQuitMessage(0); return 0; }

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: