![]() |
|
|
#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)
| ||