Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Запрет запуска второго экземпляра приложения [XP]


Страницы:   1 2

Германн ©   (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. Ну совсем засада! :(


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо