![]()  | 
	
 
  | 
| 
		 
			 
			#1  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 блокнот с pagecontrol, вкладки, все дела... 
		
	
		
		
		
		
		
	
		
		
	
	
	Столкнулся с проблемой. Ассоциировал .txt со своей программой. В OnCreate обрабатываю Paramstr(1) Открываю файл - всё ок, открываю файл еще раз - запускается вторая копия моей программы, но хотелось бы в новой вкладке... Как мне поймать parastr(1) и открыть в новой вкладке? Или Paramstr(1) работает только в OnCreate ?  | 
| 
		 
			 
			#2  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Тут все сложнее. 
		
	
		
		
		
		
		
	
		
		
	
	
	Тебе надо при старте новой копии определить, что передан файл. Потом найти существующую копию, передать в нее имя файла, а текущую копию закрыть. Вот пример, как сделано у меня, но мне не евдо было передавать имя файла, просто "поднять" уже существующую копию: Код: 
	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; | 
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
 
Gareth (20.08.2022)
  | ||
| 
		 
			 
			#3  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Нашёл ответ на свой вопрос...  может кому пригодится 
		
	
		
		
		
		
		
	
		
		
	
	
	Решение такое Код: 
	  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  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Угумс. Про WM_COPYDATA то известно. Вопрос был в том, можно ли использовать для пересылки данных именно созданное сообщение. Походу, если не ошибаюсь, то нельзя. 
		
	
		
		
		
		
		
	
		
		
	
	
	Теперь вопросы. 1. В твоем коде, что произойдет, если приложений с заголовком TForm1 будет несколько? Какому из них придет сообщение? 2. А если ты будешь менять заголовок (ну как во всех блокнотах добавлять туда имя файла, например, или еще чего-нить)? Как ты найдешь нужное тебе окно. 3. Что будет с твоим кодом, если приложение, которому ты посылаешь сообщение, повисло? (Это к вопросу об использовании тут SendMessage).  | 
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
 
Gareth (29.08.2022)
  | ||
| 
		 
			 
			#5  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Цитата: 
	
 А саму форму можно ведь назвать как нибудь оригинально) 3 - не знаю)  | 
| 
		 
			 
			#6  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 1. А, хначит там ищет по имени класса. Ну так и классов окна с таким именем может быть много. 
		
	
		
		
		
		
		
	
		
		
	
	
	3. Повисенет. SendMessage ждет ответа от принимающего окна. А вот PostMessage - не ждет. В остальном по функционалу они одинаковые.  | 
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
 
Gareth (30.08.2022)
  | ||