Форум: "Основная";
Текущий архив: 2006.11.26;
Скачать: [xml.tar.bz2];
Вниз
Как правильно активизировать окно Найти похожие ветки
← →
DelphiLexx © (2006-10-16 11:41) [0]Мое приложение должно работать в одном экземпляре для этого я используя:
function
CheckAppRun:
integer;
var
Map: THandle;
begin
Map := CreateFileMapping($FFFFFFFF, nil, PAGE_READONLY, 0, 32,
"%af_src_comm_0");
if Map = 0 then
Result := -1
else if GetLastError = ERROR_ALREADY_EXISTS then
Result := 1
else
Result := 0
end;
function
ActivatePreviousInstance(WndClass: PChar): boolean;
var
Wnd: HWND;
begin
Result := false;
if (CheckAppRun = 1) then
begin
if (WndClass <> nil) then
begin
{если окно программы указано сделать его активным в системе}
Wnd := FindWindow(WndClass, nil);
if (Wnd <> 0) then
begin
{Хочу отобразить мое приложение, но оно не отображается}
SwitchToThisWindow(Wnd, True);
end;
end
else
MessageBox(0, "Приложение уже запущено!", "Сообщение",
MB_ICONINFORMATION or MB_OK);
Result := true;
end;
end;
if ActivatePreviousInstance("TMainForm") then Halt(1);
Для отображения своего приложения я использовал SwitchToThisWindow(Wnd, True), но оно не отображается. Я использовал ShowWindow(Wnd, SW_SHOWMAXIMIZED) окно отображается, но после такой операции его нельзя свернуть.
Так как же правильно отобразить свое приложение не зависимо от того минимизировано оно или нет?
← →
RWolf (2006-10-16 16:34) [1]посылать найденному окну пользовательское сообщение, пусть само разворачивается.
← →
DelphiLexx © (2006-10-16 16:36) [2]
> посылать найденному окну пользовательское сообщение, пусть
> само разворачивается.
Каким образом?
← →
clickmaker © (2006-10-16 17:03) [3]if IsIconic(hWnd) then
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
← →
DelphiLexx © (2006-10-16 17:09) [4]
> if IsIconic(hWnd) then
> ShowWindow(hWnd, SW_RESTORE);
> SetForegroundWindow(hWnd);
Если окно приложения свернуто, то твой код не отображает его.
← →
RWolf (2006-10-16 17:17) [5]> Каким образом?
Как-то так:
Application.Restore;
if Application.MainForm.WindowState = wsMinimized then
Application.MainForm.WindowState := wsNormal;
Application.MainForm.Visible := True;
SetForegroundWindow(Application.Handle);
← →
Leonid Troyanovsky © (2006-10-16 17:22) [6]
> DelphiLexx © (16.10.06 17:09) [4]
> Если окно приложения свернуто, то твой код не отображает
Вполне отображает.
Только, окно приложения - это окно класса (windows) TApplication.
Если есть хендл любого другого окна приложения (дельфи, билдер),
то окно приложения можно найти как
happ := GetWindowLong(wnd, GWL_HWNDPARENT)
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-10-16 17:26) [7]
> RWolf (16.10.06 17:17) [5]
> Как-то так:
Не так.
Не foreground приложение не может сделать себя
(другого) foreground.
Т.е., посылка подобных сообщений бесполезна.
--
Regards, LVT.
← →
RWolf © (2006-10-16 17:39) [8]мое предложение заключалось в том, что делать foreground-ом приложение будет именно себя, свой экземпляр; см. [1]
← →
Leonid Troyanovsky © (2006-10-16 17:50) [9]
> RWolf © (16.10.06 17:39) [8]
> мое предложение заключалось в том, что делать foreground-
> ом приложение будет именно себя, свой экземпляр; см. [1]
Оное и обсуждалось.
При получении сообщения не-foreground приложение пытается
сделать себя (другого) foreground, что запрещено политикой MS
(и правильно запрещено, IMHO).
--
Regards, LVT.
← →
RWolf © (2006-10-16 18:01) [10]
> Оное и обсуждалось.При получении сообщения не-foreground
> приложение пытается сделать себя (другого) foreground, что
> запрещено политикой MS(и правильно запрещено, IMHO).
Просто я как раз такой механизм использую для восстановления программы из трея при запуске 2 экземпляра.
Или мы говорим о разных вещах?
← →
Leonid Troyanovsky © (2006-10-16 18:35) [11]
> RWolf © (16.10.06 18:01) [10]
> Или мы говорим о разных вещах?
Мои утверждения вполне, IMHO, применимы
к любым не-foreground windows приложениям.
--
Regards, LVT.
← →
gdaujk © (2006-10-16 21:09) [12]...а сколько копий было сломано...
unit gdaOneAppByFileMapping;
interface
var
MIError: Integer;
const
MI_ERROR_NONE = 0;
MI_ERROR_CREATINGMAP = 1;
MI_ERROR_MAPPINGFILE = 2;
function GetMEError(): Integer;
implementation
uses Windows, Forms;
var
hMap: THandle;
UniqueMes: Integer;
const
UNIQUE_APP_STR = "{FC9D27F6-D173-4CF6-8A9A-3A2197C72390}"; //желательно изменить
function GetMEError(): Integer;
begin
Result := MIError;
end;
procedure InitInstance;
var
pFile: Pointer;
hApp: HWND;
const
pFileSize = SizeOf(HWND);
begin
hMap := CreateFileMapping(INVALID_HANDLE_VALUE,
nil,
PAGE_READWRITE,
0,
pFileSize,
UNIQUE_APP_STR);
if GetLastError = ERROR_ALREADY_EXISTS
then
begin
Application.ShowMainForm := False;
pFile := MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if pFile <> nil
then
begin
hApp := HWND(pFile^);
ShowWindow(hApp, SW_SHOWNORMAL);
SetForegroundWindow(hApp);
UnmapViewOfFile(pFile);
end
else MIError := MIError or MI_ERROR_MAPPINGFILE;
Application.Terminate;
end
else
if hMap = 0
then MIError := MIError or MI_ERROR_CREATINGMAP
else
begin
pFile := MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
if pFile <> nil
then
begin
CopyMemory(pFile, @Application.Handle, pFileSize);
UnmapViewOfFile(pFile);
end
else MIError := MIError or MI_ERROR_MAPPINGFILE;
end;
end;
initialization
UniqueMes := RegisterWindowMessage(UNIQUE_APP_STR);
InitInstance;
finalization
if hMap <> 0
then CloseHandle(hMap);
end.
← →
Leonid Troyanovsky © (2006-10-16 22:15) [13]
> gdaujk © (16.10.06 21:09) [12]
> UNIQUE_APP_STR = "{FC9D27F6-D173-4CF6-8A9A-3A2197C72390}";
> //желательно изменить
Не желательно, а : Обязательно изменить!
Вообще-то, подобные вещи должны браться из реестра.
Т.е., сделать в HKCU раздел формата
\Software\CompanyName\ProductName\..
где второе, третье и др. брать из Version Info,
ключ ActivatePrevInstance (REG_DWORD) 0x1.
Т.е., имя проекции файла формировать из уникальной цепочки.
Кроме того, для активации предыдущей копии полезно
передавать дополнительно параметры комстроки.
Этого можно добиться, например, перечитыванием mmf
при Application.OnActivate. Хотя, это потребует некоторых
усилий по синхронизации. Например, четыре байта файла
использовать для переменной, которая будет
InterLockedCompareExchange.
Ну, и для приложений с формами можно предложить
вполне сравнимый способ без использования
объектов ядра.
--
Regards, LVT.
← →
gdaujk © (2006-10-16 23:06) [14]
> Leonid Troyanovsky © (16.10.06 22:15) [13]
> Ну, и для приложений с формами можно предложитьвполне сравнимый
> способ
>
Так предложите. Или хотя бы намекните :-)
← →
Leonid Troyanovsky © (2006-10-17 20:07) [15]
> gdaujk © (16.10.06 23:06) [14]
>> Ну, и для приложений с формами можно предложить
> Так предложите. Или хотя бы намекните :-)
Например:
В CreateWnd (override) главной формы делаем (до inherited)
EnumWindows для поиска окон формы по ее классу, и,
в случае обнаружения такого окна, посылаем ему через
SendMessageTimeOut(wnd, WM_COPYDATA,
параметры комстроки, а также, в cds.dwData - искомый uid.
А в обработчике WM_COPYDATA главной формы полученный uid
сравнивается с собственным, и, в случае равенства,
возвращается (после приема комстроки) Result <> 0.
Т.е., если SendMessageTO успешно - активируем предыдущую копию,
иначе - вызываем inherited для создания окна формы.
Вот, собс-но, вся схема.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-10-17 20:20) [16]
> Leonid Troyanovsky © (17.10.06 20:07) [15]
> Т.е., если SendMessageTO успешно - активируем предыдущую
> копию,
активируем предыдущую копию и Halt(..),
иначе - вызываем inherited
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.11.26;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.04 c