Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Не открыть бы несколько раз...


Автор: bagira 5.5.2004, 15:32
Извините, может быть мой вопрос глупый...

Пользователь стал тестировать мою программу - открыл одно окно, свернул его, снова запустил программу - открылось второе, и также - третий раз и т.д. В-общем, издевался как мог... И их накопилось довольно много... А я раньше не задумывалась об этом. butbut.gif

Такое положение нежелательно... Окно программы должно открыться только один раз, а повторно программа не должна запускаться...

Я первый раз делала программу на Дельфи, и не знаю, как это организовать?
Подскажите, если можно, пожалуйста!!! sad.gif

(убегаю, приду вечером...)

Автор: Maverick 5.5.2004, 15:45
В FAQ на запрос "копия" я первой получил такую ссылку...

Как сделать, чтобы запускалась только одна копия приложения?

Советую сделать тоже самое.... smile.gif


Автор: bagira 5.5.2004, 21:40
Maverick
Ты прав, как всегда... Вот, только что скачала его... А до этого ни разу не удавалось докачать до конца... Что ж, будем искать... Спасибо.

Автор: Medved 5.5.2004, 22:28
Обычно я использую такой механизм:

в модуль проекта (*.dpr) добавляешь следующие строчки:
Код

uses  syncobjs
...
var
 CheckEvent: TEvent;
...
begin
 CheckEvent := TEvent.Create(nil, false, true, 'MYPROGRAMM_CHECKEXIST');
 if CheckEvent.WaitFor(10) <> wrSignaled then
 begin
   Application.Terminate;
 end;
...
end;

Автор: bagira 5.5.2004, 22:55
rolleyes.gif
Pegas

Получилось!!! И все работает превосходно! Спасибо! rolleyes.gif

Автор: Chyslyvchyk 20.5.2004, 16:04
Pegas, эээээ, а можно поподробнее куда вписать нужно?
Например, есть файл Project.dpr, состоящий из:
Код
program Project;

uses
 Forms,
 Unit1 in 'Unit1.pas' {Form1},
 Unit2 in 'Unit2.pas' {Form2},

{$R *.res}

begin
 Application.Initialize;
 Application.CreateForm(TForm2, Form2);
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.


Как вписать код, который ты привел? adv/54.gif

Автор: p0s0l 20.5.2004, 16:41
2 Chyslyvchyk :
Код
program Project;

uses
syncobjs, Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2},

{$R *.res}

var
CheckEvent: TEvent;

begin
CheckEvent := TEvent.Create(nil, false, true, 'MYPROGRAMM_CHECKEXIST');
if CheckEvent.WaitFor(10) <> wrSignaled then Application.Terminate;
Application.Initialize;
Application.CreateForm(TForm2, Form2);
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Только я бы вместо Application.Terminate делал Exit...


Автор: Chyslyvchyk 20.5.2004, 18:29
To p0s0l: Спасибо! Использую Exit - работает. smile.gif

Автор: Chyslyvchyk 20.5.2004, 19:47
To p0s0l: Допустим пользователь открыл программу и свернул ее. Через некоторое время он забыл, что он программу уже открывал и кликнул на *.exe программы еще раз. Копия программы теперь запускаться не будет. А как сделать, чтобы развернулась или активировалась, или (как это еще назвать....) программа, что он свернул? То есть, чтобы перед светлыми очами пользователя открылась программа, которую он свернул.

Автор: _hunter 20.5.2004, 19:59
нйти среди окон программу с твоим названием:
Код
HWND FindWindow(
   LPCTSTR lpClassName, // pointer to class name
   LPCTSTR lpWindowName  // pointer to window name
  );


и послать ей определенное сообщение ( по которому программа будет себя показывать )

Автор: Chyslyvchyk 20.5.2004, 20:10
To _hunter:И снова: а куда это прописывать. smile.gif

Автор: Pakshin A. S. 20.5.2004, 20:58
Если прога есть, т. е. при ветке if'а перед exit'ом послать сообщение уже запущенной программы (где-то я это видел), которая, обработав его, выполнит Application.Restore...

Автор: p0s0l 20.5.2004, 23:06
Тогда можно обойтись без Event'ов. Вот так:
Код
program Project;

uses

Windows, Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2},

{$R *.res}

var
wnd : HWND;

begin
wnd := FindWindow('TForm2', 'Form2');
if wnd <> 0 then
begin
 ShowWindow(wnd, SW_SHOW);
 SetForeGroundWindow(wnd);
 exit;

end;
Application.Initialize;
Application.CreateForm(TForm2, Form2);
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Только обзови Form2 в что-нибудь по-замудреннее.
Если Form2.Name будет = 'Form2',
а Form2.Caption будет = 'Абракадабра',
то FindWindow делай таким:
wnd := FindWindow('TForm2', 'Абракадабра');

Автор: z-END 20.5.2004, 23:11
ЗЫ. Конечно же можно (и лучьше) делать как сказал г-н p0s0l, но это невсегда помогает, например когда свернуто приложение, еще свернута форма и ктому же она инвисибле, тогда приведенный им пример несработает sad.gif
А вот такой пример поможет:
тело проекта
Код

if (FindWindow (PAnsiChar ('Tform1'), PAnsiChar ('Form1')) = 0)
    or
  (FindWindow (nil, PAnsiChar ('Delphi 7')) <> 0)
{когда запущен Delphi то прога может найти это же окно в delphi и передумать запускаться}
then          
begin
  Application.CreateForm (TForm1, Form1);
  ....
  Application.Run;
end
else
begin
  a := FindWindow (PAnsiChar ('TForm1'),PAnsiChar('Form1'));
SendMessage (A, WM_ACTIVATEAPP, a, 0); //посылает сообщение с параметром равным handle окна
end;

главный юнит
Код
 ...
 private
      procedure WndProc(var Message: TMessage); override;
....
procedure TForm1.WndProc(var Message: TMessage);
begin
if (Message.Msg = WM_ACTIVATEAPP) and (Message.WParam = Handle)
   then
     begin
        {здесь выполняешь все необходимые действия по развертыванию проги}
     end
 else
   inherited
end;

Автор: Chyslyvchyk 21.5.2004, 15:55
To p0s0l: nJIaKca.spb прав. Если окно приложения свернуто, тогда фокус просто переходит на него, но оно не открывается. sad.gif

To nJIaKca.spb: Если использовать твой код - ругается: Undeclared identifier: 'WM_ACTIVATEAPP'. И как должна быть оглашена переменная 'а'?

Автор: _hunter 21.5.2004, 16:23
to Chyslyvchyk
подключи Windows.pas

Автор: Chyslyvchyk 21.5.2004, 17:02
Дык вроде прописано:
uses
Windows, ...

Автор: _hunter 21.5.2004, 17:04
фиг его знает smile.gif
тогда просто определи такое сообщение и при его получении разворачивай форму

Автор: z-END 21.5.2004, 17:10
Chyslyvchyk
FindWindow возвращает handle окна соответственно a должна быть - Thandle или Cardinal как тебе больше понравитьсяsmile.gif
а по поводу WM_ACTIVEAPP то можно сделать так:
Код
const WM_MYACTIVEAPP=66655;

и использовать вместо WM_ACTIVEAPP ее

Автор: <Spawn> 21.5.2004, 17:22
WM_ACTIVATEAPP в Messages лежит

Автор: _hunter 21.5.2004, 17:25
???
а как это:
Цитата
Declared in Winuser.h, include Windows.h

понимать?

Автор: Chyslyvchyk 21.5.2004, 18:29
To All: WM_ACTIVATEAPP точно в Messages лежит smile.gif

To nJIaKca.spb:
...
private
procedure WndProc(var Message: TMessage); override;
....
procedure TForm1.WndProc(var Message: TMessage);
begin
if (Message.Msg = WM_ACTIVATEAPP) and (Message.WParam = Handle)
then
begin
А КАКИЕ, НАПРИМЕР, НЕОБХОДИМЫЕ ДЕЙСТВИЯ ПО РАЗВЕРТЫВАНИЮ ПРОГИ НУНО ЗДЕСЬ ВЫПОЛНЯТЬ? smile.gif
end
else
inherited
end;

Автор: z-END 22.5.2004, 08:38
Chyslyvchyk
ну например
Код
Form1.Show;
 Form1.WindowState := wsNormal;
 Applcation.Restore;
ShowMessage('Программа уже запущена');

ну и т.п. все зависит от того как у тебя сприятана прога и че необходимо сделатьsmile.gif

Автор: <Spawn> 22.5.2004, 09:48
Цитата(_hunter @ 21.5.2004, 09:25)
???
а как это:
Цитата
Declared in Winuser.h, include Windows.h

понимать?

Ну дак это для Си smile.gif В Дельфях свои модули.

Автор: Chyslyvchyk 22.5.2004, 16:19
НичАво не работает....
Так, гляньте, что не так. В project.dpr прописывается:
Код
program Project1;

uses
 Windows,
 syncobjs,
 Forms,
 Messages,
 Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
a : Thandle;

begin
if (FindWindow (PAnsiChar ('Tform1'), PAnsiChar ('Form1')) = 0)
   or
 (FindWindow (nil, PAnsiChar ('Delphi 6')) <> 0)
{когда запущен Delphi то прога может найти это же окно в delphi и передумать запускаться}
then          
begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end
else
begin
 a := FindWindow (PAnsiChar ('TForm1'),PAnsiChar('Form1'));
SendMessage(A, WM_ACTIVATEAPP, a, 0); //посылает сообщение с параметром равным handle окна
end;
end.


В юнит:
Код
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ShellAPI;
type
 TForm1 = class(TForm)
 
 private
    procedure WndProc(var Message: TMessage); override;
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WndProc(var Message: TMessage);
begin
if (Message.Msg = WM_ACTIVATEAPP) and (Message.WParam = Handle)
  then
    begin
        Form1.Show;
        //Form1.WindowState := wsNormal;
        //Applcation.Restore;
        ShowMessage('Программа уже запущена');
    end
else
  inherited
end;

end.


To nJIaKca.spb:
Цитата
ну и т.п. все зависит от того как у тебя сприятана прога и че необходимо сделать
Нужно только форму развернуть, када она свернутая.

Автор: z-END 22.5.2004, 19:44
Chyslyvchyk
сразу скажу при запущеных дельфях это неработаетsad.gif
у тя хоть сообщение появлентся что прога запущена?
а вообще для того чтобы развенруть форму нуно WindowSate:=wsNormal а если у тебя приложение свернуто то Application.Restore
Добавлено @ 19:49
ЗЫ если тебя это неустраивает то убери етот кусок
Цитата
  or
(FindWindow (nil, PAnsiChar ('Delphi 6')) <> 0)
{когда запущен Delphi то прога может найти это же окно в delphi и передумать запускаться}

но тогда (по крайней мере у меняsmile.gif ) прога при запуске находит Design-Time форму и не запускается...

Автор: Chyslyvchyk 22.5.2004, 20:17
nJIaKca.spb: Все работает, если проект в дельфях закрыть. hehe.gif
Только проблемка в том, что и WindowSate:=wsNormal, и Application.Restore - просто разворачивают прогу фоном, а фокус на нее не передают. Было испробовано сначала удалить одну запись, потом другую. А нужно, чтобы она еще и поверх всех окон "вылазила". smile.gif

Автор: z-END 23.5.2004, 19:36
Chyslyvchyk для этого используй BringToFront а еше лучше SetForegroundWindow щас нет Дельфей под руками так что более конкретно сказать несмогу.
а чтобы поверх всех то это FromStyle:=fsStayonTop и Application.RestoreTopMost

Автор: Akella 24.5.2004, 08:17
В процедуре показа формы напиши
Код
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE);

Автор: Albinos_x 27.5.2004, 22:04
Также можно прописать приведённый пример в
procedure TForm1.FormCreate(Sender: TObject);
и перед завершение проги выдавать сообщение
ShowMessage()
с предупреждением, что прога уже запущена!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)