|
#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)
|