Урок 57 Взаимное исключение No title

October 21, 2007
в колонках играет Потап и Настя Каменских – Не пара


Я подозреваю, что читатели хотят уже кинуть меня в топку, из-за того, что я их подзаебал уроками по графике, поэтому этот урок будет посвящён другой теме…

Как известно, Windows – многозадачная операционная система, предоставляющая ряд встроенных функций синхронизации нескольких программ. Иногда нам не надо, чтобы одна и та же программа работала в нескольких экземплярах. Сейчас мы научимся это предотвращать…

Есть три варианта решения этой проблемы:
I - Мьютекс:
В событии FormCreate пишем:

HANDLE hMutex = CreateMutex(NULL, true, "some_big_big_unique_mutex_name");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
// мы уже есть - ругаемся и выходим
ShowMessage("Программа уже запущена, иди на хуй!!!");
Application->Terminate();
ReleaseMutex(hMutex);

}

II - Атом:
Записываем как глобальные переменные:
AnsiString AtomName = "some_big_big_unique_atom_name";
ATOM Atom;

Затем в событии FormCreate() пишем:
if(GlobalFindAtom(AtomName.c_str()) == 0)
{
// создаём атом
Atom = GlobalAddAtom(AtomName.c_str());
}
else
{
// мы уже есть - ругаемся и выходим
ShowMessage("Программа уже запущена, отвянь!!!");

Close();
Application->Terminate();
}

А в событии OnClose():
GlobalDeleteAtom(Atom);

Недостатком этих двух методов является то, что если программа завершена некорректно, то до перезагрузки компьютера эта программа уже не заработает.

III – Поиск окна:
Указывая здесь название формы, следует к нему добавить букву «Т»

HWND hWnd = FindWindow("Tformochka",NULL); // ищем своё окно
if(hWnd!=NULL) // если нашли
{
ShowMessage("Программа уже запущена!!!");
SetForegroundWindow(hWnd); // активизируем предыдущую копию проги
Application->Terminate(); // закрываемся
}

Это надо писать в модуле проекта (открывается в меню Билдера: Project->View Source), причём так, чтобы инструкция
Try
{
{
Catch()
{
}
была внутри else.
Хотя в принципе это же можно сделать и с Мьютексом.
Пример для FindWindow:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
HWND hWnd = FindWindow("TForm1",NULL); // ищем своё окно
if(hWnd!=NULL) // если нашли
{
ShowMessage("Программа уже запущена, иди на хуй!!!");
SetForegroundWindow(hWnd); // активизируем предыдущую копию программы
Application->Terminate(); // закрываемся
}
else
{

//Выполнение программы - это противный случай условия нахождения окна
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
}
return 0; // эту инструкцию необходимо перенести за условный оператор!!!
}
//---------------------------------------------------------------------------

Примечание: приём FindWindow требует перед запуском программы закрыть в C++ Builder'e модуль формы, а иначе этот модуль будет восприниматься как форма и в итоге нихуя не запустится!

Если что-то непонятно, обращайтесь по адресу 666klaus@rambler.ru.
Ну вот, собственно и всё. Ждите новых обновлений…



Материал подготовил - Klaus, 2007
www.builderhelper.org
builder.helper@rambler.ru