Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 19.08.2022, 21:07
Gareth Gareth вне форума
Активный
 
Регистрация: 21.03.2013
Адрес: Приднестровье
Сообщения: 202
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Пишу блокнот

блокнот с pagecontrol, вкладки, все дела...
Столкнулся с проблемой. Ассоциировал .txt со своей программой.
В OnCreate обрабатываю Paramstr(1)
Открываю файл - всё ок, открываю файл еще раз - запускается вторая копия моей программы, но хотелось бы в новой вкладке...

Как мне поймать parastr(1) и открыть в новой вкладке?
Или Paramstr(1) работает только в OnCreate ?
Ответить с цитированием
  #2  
Старый 20.08.2022, 03:10
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,052
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

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

Вот пример, как сделано у меня, но мне не евдо было передавать имя файла, просто "поднять" уже существующую копию:
Код:
program PwdKeeper;

uses
  System.Types,
  Winapi.Windows,
  Vcl.Forms,
  MainFrm in 'MainFrm.pas' {MainForm},
  Model in 'Model.pas',
  SetupGeneralPwdFrm in 'SetupGeneralPwdFrm.pas' {SetupGeneralPwdForm},
  EnterGeneralPwdFrm in 'EnterGeneralPwdFrm.pas' {EnterGeneralPwdForm},
  AddEditPwdFrm in 'AddEditPwdFrm.pas' {AddEditPwdForm},
  AboutFrm in 'AboutFrm.pas' {AboutForm},
  UserProfile in 'Common\UserProfile.pas',
  SysFolders in 'Common\SysFolders.pas',
  Settings in 'Settings.pas',
  FindFrm in 'FindFrm.pas' {FindForm},
  SearchParams in 'SearchParams.pas',
  VerInfo in 'Common\VerInfo.pas',
  FormSizePosStorage in 'Common\FormSizePosStorage.pas';

{$R *.res}

function AllowSetForegroundWindow(dwProcessId: DWORD): BOOL; stdcall; external 'user32.dll';

function IsSecondCopy : Boolean;
var
  hMutex : THandle;
begin
  Result := False;

  WndMessage := RegisterWindowMessage(PChar("PWDKEEPER_MSG"));

  hMutex := CreateMutex(Nil, True, PChar("PWDKEEPER_MTX"));
  If hMutex<>0 Then
    If GetLastError=ERROR_ALREADY_EXISTS Then
      Begin
        AllowSetForegroundWindow(DWORD(-1));
        PostMessage(HWND_BROADCAST,WndMessage,0,0);
        Result := True;
      End;
end;

begin
  If IsSecondCopy Then Halt(0);
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := 'Password Keeper';
  Application.CreateForm(TMainForm, MainForm);
  Application.HookMainWindow(MainForm.HookMessageProc);
  Application.Run;
end.
Я заменил имена сообщения и мьютекса на константы, в оригинальном коде эти имена создаются для каждого юзера, т.о. если в системе залогинены несколько пользователей, то каждый может запустить свою копию, но только одну.
А вот, собственно, как вышеуказанное сообщение обраватывается в главной форме:
Код:
type
  TMainForm = class(TForm)
    ...
  public
    { Public declarations }
    function HookMessageProc(var Message : TMessage) : Boolean;
  end;

var
  MainForm: TMainForm;
  WndMessage : Cardinal;

...

function TMainForm.HookMessageProc(var Message : TMessage) : Boolean;
begin
  Result := False;
  If Message.Msg = WndMessage Then
    Begin
      If WindowState = wsMinimized Then Application.Restore;
      Application.BringToFront;
      SetForegroundWindow(Self.Handle);
      Result := True;
    End;
end;
Как я говорил, мне надо просто "поднять" предыдущую копию. Можно ли прямо в этом сообщении переслать имя файла - надо "курить" MSDN...
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Gareth (20.08.2022)
  #3  
Старый 27.08.2022, 08:29
Gareth Gareth вне форума
Активный
 
Регистрация: 21.03.2013
Адрес: Приднестровье
Сообщения: 202
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Нашёл ответ на свой вопрос... может кому пригодится

Решение такое

Код:
  private
    { Private declarations }
    procedure GetMessages(var Msg: TWMCopyData); message WM_COPYDATA;


procedure TForm1.GetMessages(var Msg: TWMCopyData);
var
   s : string;
   Len : Integer;
begin
   Len := Msg.CopyDataStruct.cbData div SizeOf(Char);
   SetLength(s, Len);
   Move(PChar(Msg.CopyDataStruct.lpData)^, PChar(s)^, Len * SizeOf(Char));
   Memo1.Lines.Add(s); // Переданный параметр обрабатывается как тебе нужно
end;

В файле .dpr (Project-ViewSource)

Код:
uses
  Windows, Messages, Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
   hMutex : THandle;

procedure SendMessageToFirstInstance(FirstHwnd : HWND; s : string);
var
   MesData: TCopyDataStruct;
begin
   MesData.cbData := Length(s) * sizeof(char);
   MesData.lpData := PChar(s);
   SendMessage(FirstHwnd, WM_COPYDATA, 0, LPARAM(@MesData));
end;

begin
   hMutex := CreateMutex(nil, True, PChar('BlaBlaBlaVeryUniqueName'));
   if GetLastError = ERROR_ALREADY_EXISTS then
   begin
      SendMessageToFirstInstance(FindWindow('TForm1', nil), ParamStr(1));
      Exit;
   end;

   Application.Initialize;
   Application.MainFormOnTaskbar := True;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
end.
Ответить с цитированием
  #4  
Старый 28.08.2022, 05:09
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,052
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Угумс. Про WM_COPYDATA то известно. Вопрос был в том, можно ли использовать для пересылки данных именно созданное сообщение. Походу, если не ошибаюсь, то нельзя.

Теперь вопросы.
1. В твоем коде, что произойдет, если приложений с заголовком TForm1 будет несколько? Какому из них придет сообщение?
2. А если ты будешь менять заголовок (ну как во всех блокнотах добавлять туда имя файла, например, или еще чего-нить)? Как ты найдешь нужное тебе окно.
3. Что будет с твоим кодом, если приложение, которому ты посылаешь сообщение, повисло? (Это к вопросу об использовании тут SendMessage).
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Gareth (29.08.2022)
  #5  
Старый 29.08.2022, 21:34
Gareth Gareth вне форума
Активный
 
Регистрация: 21.03.2013
Адрес: Приднестровье
Сообщения: 202
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Угумс. Про WM_COPYDATA то известно. Вопрос был в том, можно ли использовать для пересылки данных именно созданное сообщение. Походу, если не ошибаюсь, то нельзя.

Теперь вопросы.
1. В твоем коде, что произойдет, если приложений с заголовком TForm1 будет несколько? Какому из них придет сообщение?
2. А если ты будешь менять заголовок (ну как во всех блокнотах добавлять туда имя файла, например, или еще чего-нить)? Как ты найдешь нужное тебе окно.
3. Что будет с твоим кодом, если приложение, которому ты посылаешь сообщение, повисло? (Это к вопросу об использовании тут SendMessage).
1 - заголовок в смысли caption? Он не по Caption ищет. кэпшн отсутствует у меня... Я сам удивился..
А саму форму можно ведь назвать как нибудь оригинально)
3 - не знаю)
Ответить с цитированием
  #6  
Старый 29.08.2022, 23:47
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,052
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

1. А, хначит там ищет по имени класса. Ну так и классов окна с таким именем может быть много.
3. Повисенет. SendMessage ждет ответа от принимающего окна. А вот PostMessage - не ждет. В остальном по функционалу они одинаковые.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Gareth (30.08.2022)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 15:31.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter