Reputation: 1464
I want to write an text editor and to assign the txt files to it. My problem is that I want to have only one instance running and when a new file is opened to send the filename to the first app that is already running... (I want to do this using mutex). Here is a small test
DPR looks like this
uses
Windows, Messages, SysUtils,
Forms,
wndMain in 'wndMain.pas' {frmMain};
{$R *.res}
var
PrevWindow : HWND;
S : string;
CData : TCopyDataStruct;
begin
PrevWindow := 0;
if OpenMutex(MUTEX_ALL_ACCESS, False, 'MyMutex') <> 0 then
begin
repeat
PrevWindow:=FindWindow('TfrmMain', nil);
until PrevWindow<>Application.Handle;
if IsWindow(PrevWindow) then
begin
SendMessage(PrevWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
BringWindowToTop(PrevWindow);
SetForegroundWindow(PrevWindow);
if FileExists(ParamStr(1)) then
begin
S:=ParamStr(1);
CData.dwData:=0;
CData.lpData:=PChar(S);
CData.cbData:=1+Length(S);
SendMessage(PrevWindow, WM_COPYDATA, 0, DWORD(@CData) );
end;
end;
end
else
CreateMutex(nil, False, 'MyMutex');
Application.Initialize;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.
PAS:
type TfrmMain = class(TForm)
memo: TMemo;
private
procedure WMCopyData ( var msg : TWMCopyData ) ; message WM_COPYDATA;
public
procedure OpenFile(f : String);
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.WMCopyData ( var msg : TWMCopyData ) ;
var
f : String;
begin
f:=PChar(msg.CopyDataStruct.lpData);
//ShowMessage(f);
OpenFile(f);
end;
procedure TfrmMain.OpenFile(f : String);
begin
memo.Clear;
memo.Lines.LoadFromFile(f);
Caption:=f;
end;
this code should be ok, but if i want to open a text file (from the second app), the first app receives a message like this:
alt text http://img218.imageshack.us/img218/2175/errorjd.jpg
thanks
Upvotes: 1
Views: 1010
Reputation: 163247
I suspect you're using Delphi 2009 or Delphi 2010. Those version use Unicode strings, so the Length
function tells the number of characters in a string, but not the number bytes. The wm_CopyData
message needs to know the number of bytes to send. Multiply the character count by two, or SizeOf(WideChar)
.
CData.lpData := PWideChar(S);
CData.cbData := (1+Length(S)) * SizeOf(WideChar);
Upvotes: 0
Reputation: 84540
This looks like a Unicode problem. You're probably in D2009 or D2010. You need to give the size in bytes, not in chaaracters. Try multiplying your length
call by sizeof(char)
and it should work.
Upvotes: 1