Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вторая копия программы и данные из файла, Как сделать? 
:(
    Опции темы
MacTep
Дата 9.2.2006, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Программа работает из трея. С этой программой я ассоциировал свой тип файла. Если программа в данный момент не загружена, то двойным щелчком по данному файлу я открываю программу и работаю с ней и теми данными, которые есть в этом файле. Но что делать, если программа уже запущена и мне не нужно запускать ее второй раз. Я использую мьютексы для того, чтобы блокировать вторую копию программы. Но как мне сделать, чтобы уже запущенной первой копии программы была известна информация из ассоциированного файла?

Код OnCreate главной формы программы:
Код
procedure TForm1.FormCreate(Sender: TObject);
var hMutex: THandle;
    reg:TRegistry;
    f:textfile;
    s:string;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 if GetLastError = ERROR_ALREADY_EXISTS then
   begin
     // если вторая копия программы запущена, то что?????
   end
 else
   begin
     // какие -либо действия
     if ParamCount>0 then
       begin
         // какие - либо действия с данными из файла       
       end;
   end;
end;



--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
sexton
Дата 9.2.2006, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sexton=Пономарь (eng)
**


Профиль
Группа: Участник
Сообщений: 503
Регистрация: 5.5.2004
Где: Ульяновск

Репутация: 1
Всего: 9



Оригинальная задача... может сделать некое подобие autoexec, чтобы при запуске программы по щелчку, данные копировались в файл, из которого программа будет читать данные по умолчанию при каждом запуске.
PM MAIL WWW ICQ   Вверх
Snowy
Дата 9.2.2006, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Найди копию программы по FindWindow и отправь ей WM_COPYDATA, а в нем путь к файлу.
PM MAIL   Вверх
MacTep
Дата 9.2.2006, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Цитата(Snowy @ 9.2.2006, 11:42 Найти цитируемый пост)

отправь ей WM_COPYDATA, а в нем путь к файлу

Можно небольшой пример по этому делу, а то что-то недогоню никак...


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Rennigth
Дата 9.2.2006, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76



Цитата(MacTep @ 9.2.2006, 14:35 Найти цитируемый пост)

Можно небольшой пример по этому делу, а то что-то недогоню никак...

Поиск по форуму, довольно часто проскакивали темы по WM_COPYDATA.



--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
MacTep
Дата 10.2.2006, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Нашел в темах форума следующее:
Код

var
cds:TCopyDataStruct;
begin
//Любое 32-х битное число
cds.dwData:=10;
//Количество передаваемых байт
cds.cbData:=len;
//Указатель на данные
cds.lpData:=@buf;
//Посылаешь сообщение нужному окну, wParam - хендл посылающего окна, lParam - указатель на структуру с данными
SendMessage(FindWindow('TForm2',nil), WM_COPYDATA, Handle, Integer(@cds));
end;
Только все равно понятного мало. Говорят, что SendMessage отправляет только числа, а не текст. Второе, не могу понять, что такое dwData, cbData, lpData, какие нужно данные туда подставить? Все равно было бы классно примерчик увидеть...
Добавлено @ 00:07
И еще нашел следующее:
Цитата
сообщение WM_COPYDATA, чрезвычайно удобное дл пересылки блоков данных из одной программы в другую
. А мне же не нужно из программы в программу посылать. Мне нужно в одной программе все провернуть. Или я не догоняю? Разъясните непонятливому...


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Snowy
Дата 10.2.2006, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Цитата(MacTep @ 10.2.2006, 00:04 Найти цитируемый пост)
Говорят, что SendMessage отправляет только числа, а не текст.
Передает абсолютно любые данные.

Цитата(MacTep @ 10.2.2006, 00:04 Найти цитируемый пост)
Все равно было бы классно примерчик увидеть...
Это и есть пример.

Цитата(MacTep @ 10.2.2006, 00:04 Найти цитируемый пост)
А мне же не нужно из программы в программу посылать. Мне нужно в одной программе все провернуть. Или я не догоняю?
Если говорить более точно, то это сообщение передает данные между разными процессами. Две копии твоей программы это 2 разных процесса.

Вот этот пример со строкой.
Код

var    
  cds:TCopyDataStruct;
  s: string;
begin    
  s := 'Это строка, которую мы отправляем';
  //Любое 32-х битное число    
  cds.dwData:=10;
  //Количество передаваемых байт    
  cds.cbData:=Length(s);
  //Указатель на данные    
  cds.lpData:=pointer(s);    
  //Посылаешь сообщение нужному окну, wParam - хендл посылающего окна, lParam - указатель на структуру с данными    
  SendMessage(FindWindow('TForm2',nil), WM_COPYDATA, Handle, Integer(@cds));    
end;


PM MAIL   Вверх
MacTep
Дата 10.2.2006, 00:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



А что это за dwData и почему в примере стоит именно 10? smile И последнее... После того, как я передал сообщение, я могу закрыть вторую копию и принять сообщение в первой копии, так? То есть код моей программы будет включать как функцию для отправки сообщения, так и для его принятия? А как принять данное сообщение посланное мне?


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Snowy
Дата 10.2.2006, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Цитата(MacTep @ 10.2.2006, 00:41 Найти цитируемый пост)
А что это за dwData и почему в примере стоит именно 10?
Там же написано - любое 32-битное число.
Можешь вообще в него ничего не писать.
Сделано на случай, если ты будешь посылать разные данные.
Тогда ты сможешь различать их по данному числу.
Но в твоем случае данные только одни - строка с именем файла.
Так что тебе оно не нужно. Хотя для надежности можешь все же вставить проверку - вдруг это другая программа отправила тебе это сообщение по ошибке. По своему числу сможешь отличить свое от не своего.

Цитата(MacTep @ 10.2.2006, 00:41 Найти цитируемый пост)
После того, как я передал сообщение, я могу закрыть вторую копию и принять сообщение в первой копии, так?
Примерно так. Только порядок немного другой. Ты отправляешь сообщение, первая копия его принимает и потом уже вторая завершается. Но это не так важно. Порядок действий для тебя тот же.

Цитата(MacTep @ 10.2.2006, 00:41 Найти цитируемый пост)
То есть код моей программы будет включать как функцию для отправки сообщения, так и для его принятия?
Сходи в топик, из которого ты взял этот пример. Там же написано как это сообщение ловить.
PM MAIL   Вверх
MacTep
Дата 10.2.2006, 01:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Спасибо, за терпение к глупым вопросам повышаю репутацию! smile


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
MacTep
Дата 10.2.2006, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Не знаю, парни, или я такой или лыжи такие странные! smile Не получается у меня почти ничего. Вот код.
Код
type
  TForm1 = class(TForm)
    ...
  private
    { Private declarations }
    procedure CopyData(var Msg:TWMCopyData); message WM_COPYDATA;
  public
    { Public declarations }
  end;
// Действия, выполняемые при запуске приложения
procedure TForm1.FormCreate(Sender: TObject);
var hMutex: THandle;
    t:integer;
    cds:TCopyDataStruct;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 if GetLastError = ERROR_ALREADY_EXISTS then
   begin
     // берем имя файла из командной строки
     if ParamCount>0 then
       begin
         s:=ParamStr(1);
         //Любое 32-х битное число для распознавания своего сообщения WM_COPYDATA
         cds.dwData:=10;
         //Количество передаваемых байт
         cds.cbData:=Length(s);
         //Указатель на данные
         cds.lpData:=pointer(s);
         //Посылаем сообщение нужному окну
         //wParam - хендл посылающего окна
         //lParam - указатель на структуру с данными
         SendMessage(FindWindow('TForm1',nil),WM_COPYDATA,Handle,Integer(@cds));
       end;
     Halt;
   end
 else
   begin
     // ...
   end;
end;

procedure TForm1.CopyData(var Msg:TWMCopyData);
var cds:PCopyDataStruct;
    f:textfile;
    s:string;
begin
  cds:=Msg.CopyDataStruct;
  // записываем данные из файла в ListBox
  AssignFile(f,PChar(cds.lpData));
  Reset(f);
  ListBox1.Clear;
  FileNames.Clear;
  while not eof(f) do
    begin
      readln(f,s);
      ListBox1.Items.Add(s);
    end;
  CloseFile(f);
end;

Так вот беда в чем: вроде бы как данные передаются. Но если в первой процедурке строчку "Halt;" закомментировать, то вторая копия приложения не завершит свою работу. Так вот при этом происходит, что все действия, которые выполняются во второй процедуре, выполняются именно со второй копией приложения, а не с первой. Как сделать так, чтобы данные действия были применимы только лишь к первой инстанции приложения??? Уже из сил выбился. Кучу информации перечитал, а так ничего ин е добился... smile

Это сообщение отредактировал(а) MacTep - 10.2.2006, 13:58


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Snowy
Дата 10.2.2006, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Код
program Project1;

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

{$R *.res}

function AppExist: boolean;
var
  wnd: HWND;
  cd:  TCopyDataStruct;
  s:   string;
begin
  wnd := FindWindow('TCoolForm54',nil);
  if wnd <> 0 then begin
    result := true;
    if ParamCount = 0 then Exit;
    s := ParamStr(1);
    cd.dwData := $BEBE;
    cd.cbData := Length(s);
    cd.lpData := pointer(s);
    SendMessage(wnd, WM_COPYDATA, 0, Integer(@cd));
  end else result := false;
end;

begin
  if AppExist then Exit;
  Application.Initialize;
  Application.CreateForm(TCoolForm54, CoolForm54);
  Application.Run;
end.


Код
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TCoolForm54 = class(TForm)
  private
    procedure CopyData(var Msg:TWMCopyData); message WM_COPYDATA;
  public
    { Public declarations }
  end;

var
  CoolForm54: TCoolForm54;

implementation

{$R *.dfm}

procedure TCoolForm54.CopyData(var Msg:TWMCopyData);
var
  s: string;
begin
  SetLength(s, Msg.CopyDataStruct.cbData);
  move(pointer(Msg.CopyDataStruct.lpData)^, s[1], Length(s));
  SetForegroundWindow(Handle);
  if Msg.CopyDataStruct.dwData = $BEBE then
    ShowMessage(s);
end;

end.

Добавлено @ 14:31
Вот пример программы, которая ищет себя запущенную.
Если находит, то отправляет себе ParamStr(1) и умирает.
Если не находит - запускается.
Обрати внимание, что у Form1 Name оставлен не стандартный, а сделан уникальным, чтобы не перепутать себя с другими.
В примере я просто сделал вывод полученной строки в ShowMessage.
Замени на любой свой код и все.
PM MAIL   Вверх
MacTep
Дата 10.2.2006, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



 А вот теперь действительно все... smile Получилось. Оказывается, действительно нужно было имя формы сделать уникальным. И мьютексы использовать вовсе не обязательно было. Метод Snowy мне понравился больше, мне кажется он более красивым. Спасибо всем за обсуждение и помощь!  

Это сообщение отредактировал(а) MacTep - 11.5.2006, 21:09


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
MacTep
Дата 11.5.2006, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: 4
Всего: 4



Еще одна проблема с этим вопросом. Все отлично работает, если запускать программу при помощи ассоциированного с ней файла. Но если просто запустить программу из экзехи, потом второй раз, потом третий, то будут созданы и второй и третий и т.д. экземпляры программы. Как нужно изменить процедурку AppExist, чтобы она даже при таком запуске позволяла запустить программу только 1 раз? 


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Демо
Дата 12.5.2006, 08:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



MacTep
Неправильно искать второй экземпляр по имени окна.
В топике было праильное решение - использовать мьютекс.

Код

 if GetLastError = ERROR_ALREADY_EXISTS then    
   begin    
     // если вторая копия программы запущена, то что?????    
   end


Вместо комментариев - либо Exit, либо Halt.

Но у тебя 2 задачи. КРоме того, чтобы не допустить второго запуска программы, тебе надо еще и передать параметры уже запущенной копии.

Для этого проще воспользоваться MMF - Memory Mapped File.
Запущенное приложение первым делом создает MMF, записывает туда нужную информаци, например - дескриптор окна, которому можно посылать сообщения, параметры пли запуске, и вообще любую информацию.

При запуске второй копии приложение также пытается создать MMF, но, так как MMF уже существует, просто открывает его, записывает нужную информацию и посылает сообщение первой копии. 


--------------------
    
PM MAIL ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1016 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.