![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запрет запуска второго экземпляра приложения [XP]
Германн © (2010-10-30 01:39:00)с переключением на первый экземпляр.
Обнаружил что старый добрый SetForegroundWindow нынче не работает. Пошерстил в поисковиках, нашел кучу вариантов. Но в самых свежих сообщениях, которые я нашел, все эти варианты называются "хаками" и не дающими гарантии. Насколько смог уразуметь сейчас самым прямым путем является использование функции AllowSetForegroundWindow. Вот сейчас сижу и пытаюсь найти наиболее красивое решение. Этой функции нужен ProcessID. Искать его перебором как-то не красиво. Процесс то мой собственный. Кроме того функции SetForegroundWindow нужен Handle окна того процесса. Опять искать?
А что если использовать для данной задачи CreateFileMapping? И в этом файле передавать и PID и Handle?
P.S. Давно уже так близко кWinAPI не подходил. Дрожат коленки. :(
P.P.S. Пока сам попробовать не могу. Вчерашние эксперименты привели к необходимости переустановки Д2007.
Германн (2010-10-31 01:25:00) [21]
> DVM © (30.10.10 23:09) [6]
>
>
> > Германн ©
>
> я всегда пользуюсь таким примерно кодом:
>
Вот тут http://codeguru.ru/windows/windows/common/%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BE%D0%BA%D0%BD%D0%B0-%D0%BD%D0%B0-%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9-%D0%BF%D0%BB%D0%B0%D0%BD.html
примерно такое же решение. Но тоже "хакерское" и вероятно тоже если не кривое, то и не прямое.
DVM (2010-10-30 23:11:00) [22]Еще есть недокументированная SwitchToThisWindow живет в user32.dll ей таскбар пользуется для переключения окон, правда давно не проверял, работает ли еще она.
DVM (2010-10-30 23:09:00) [23]
> Германн ©
я всегда пользуюсь таким примерно кодом:
function ForceForegroundWindow(hWnd: HWND): BOOL;
const
SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
var
OsVerInfo: TOSVersionInfo;
Win32MajorVersion: Integer;
Win32MinorVersion: Integer;
Win32Platform: Integer;
ForegroundThreadID: DWORD;
ThisThreadID: DWORD;
Timeout: DWORD;
begin
OsVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
GetVersionEx(osVerInfo);
Win32MajorVersion := OsVerInfo.dwMajorVersion;
Win32MinorVersion := OsVerInfo.dwMinorVersion;
Win32Platform := OsVerInfo.dwPlatformId;
if IsIconic(hWnd) then ShowWindow(hWnd, SW_RESTORE);
if GetForegroundWindow = hWnd then Result := True
else
begin
if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or
((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4) or
((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then
begin
Result := False;
ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil);
ThisThreadID := GetWindowThreadPRocessId(hWnd, nil);
if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then
begin
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
AttachThreadInput(ThisThreadID, ForegroundThreadID, False);
Result := (GetForegroundWindow = hWnd);
end;
if not Result then
begin
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @Timeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, @Timeout, SPIF_SENDCHANGE);
end;
end
else
begin
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
end;
Result := (GetForegroundWindow = hWnd);
end;
end; // End of function ForceForegroundWindow
Германн (2010-10-30 22:43:00) [24]
> 0x00FF00 ©
Спасибо! Буду иметь в виду такой вариант.
0x00FF00 (2010-10-30 17:01:00) [25]И, да: PID не нужно передавать, если уже есть Handle окна.
PID можно узнать, имея лишь Handle, с помощью GetWindowThreadProcessId:
http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx
Так что, в программе не придётся даже делать каких-то серьёзных "перестановок", просто переменную, хранящую хендл целевого окна, выделить в отдельный сегмент. Нормальной работе программы это не повредит.
0x00FF00 (2010-10-30 16:37:00) [26]https://forums.embarcadero.com/message.jspa?messageID=181022#181022
Вот так должно на Delphi выглядеть создание SHARED-сегмента, по мнению экспертов Embarcadero (в самом начале, где#pragma).
Далее, с этими переменными можно работать, как с обычными.
0x00FF00 (2010-10-30 16:07:00) [27]> Германн © (30.10.10 01:39)
http://www.wasm.ru/article.php?article=1005015
Вот здесь весьма оригинальный подход к проблеме — разделяемый сегмент памяти.
Держим в нём две переменные, при инициализации выставляемые в нуль.
При запуске проверяем — действительно ли нули? Если да, значит ура, мы первые. Если нет — читаем, выставляем в AllowSetЧегоТоТам, завершаемся.
Дополнительного кода, как с мапированными файлами, не нужно, просто проверка на равенство 0.
Германн (2010-10-30 01:51:00) [28]Хм. AllowSetForegroundWindow оказывается в Д2007 не описана.
В хелпе присутствует, в исходниках отсутствует. Значит нужно её ещё и ручками вытаскивать из user32.dll. Ну совсем засада! :(