Проблема с передачей строки работающему приложению

  • Автор темы NightmareTerrible
  • Дата начала
N

NightmareTerrible

#1
Здравствуйте, уважаемые дельфисты.
У меня возникла следующая проблема.

Есть приложение, которое можно запускать только в одном экземпляре, однако необходимо поддерживать возможность открытия ассоциированных файлов. Для решения этой задачи использую TCopyDataStruct следующим образом.

Приложение при запуске проверяет, не запущена ли уже его копия, и если да, то передаёт ему параметры командной строки.
Код:
if ParamCount <> 0 then
begin
try
cd.cbData := Length(ParamStr(1));
cd.lpData := PChar(ParamStr(1));
cd.dwData := 0;
WParam := Application.Handle;
LParam := Integer(@cd);
SendMessage(OriChemesWindow, WM_COPYDATA, WParam, LParam);
finally
end;
end;
В переменной OriChemesWindow хранится дескриптор окна открытого ранее приложения (первой копии). Также существует обработчик этого сообщения:

Код:
procedure TOriChemesForm.WMCopyData(var Msg: TWMCopyData);
var
cd:TCopyDataStruct;
FileName : string;
i,len : integer;
begin
// Открываем файл, переданный в качетсве параметра (при открытии второй копии приложения)
cd := Msg.CopyDataStruct^;
FileName := '';
len := cd.cbData;
for i := 0 to len - 1 do
FileName := Filename + (PChar(cd.lpData) + i)^;
if FileExists(FileName) then begin
FileOpen1.Dialog.FileName := FileName;
FileOpen1Accept(nil);
end;
inherited;
end;
Процедура описана как
Код:
procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
Вроде бы всё должно работать хорошо, но вот проблема: при передаче параметров происходит какая-то ошибка, и часть текста преобразуется в крякозябры, например, во второй копии это был файл D:\Chemes\ver1.4\111temp.ori , а при получении параметров в первой копии получается что-то в роде D:\Chemeﲧ酋癔醀癔＀
Помогите, пожалуйста, решить эту проблемку. Использую Delphi 2010.
 

sinkopa

Well-known member
17.06.2009
344
4
#2
Здравствуйте, уважаемые дельфисты.
Помогите, пожалуйста, решить эту проблемку. Использую Delphi 2010.
Юникод батенька... :)
1.1. String в Delphi 7 = AnsiString
1.2. String в Delphi 2010 = WideString

2.1. PChar в Delphi 7 = PAnsiChar
2.2. PChar в Delphi 2010 = PWideChar

3. Функция ParamStr возвращает AnsiString, следовательно
Код:
PWideChar(ParamStr(1)) = лабуда... :-)
нужно как минимум
Код:
cd.lpData := PAnsiChar(ParamStr(1));
4.
Код:
	 cd.cbData := Length(ParamStr(1));
cd.lpData := PChar(ParamStr(1));
С кодом прямо скажем Вы пожадничали выложить... но если это локально (внутри процедуры) память выделяется, то на мой взгляд это совсем не гуд...
Надо
Код:
var
param: AnsiString = ''; // глобальная!!!! переменная

//...
param := ParamStr(1);

cd.cbData := Length(param);
cd.lpData := PAnsiChar(param);
5. И вот это
Код:
 FileName := '';
len := cd.cbData;
for i := 0 to len - 1 do
FileName := Filename + (PChar(cd.lpData) + i)^;
я бы поменял на вот это:
Код:
var
FileName: AnsiString;
cd:TCopyDataStruct;
len: Integer;
begin

FileName := '';
len := cd.cbData;
SetLength(FileName,len);
CopyMemory(PAnsiChar(FileName),cd.lpData,len);
//...
А может и проще еще
Код:
 FileName := StrPas(PAnsiChar(cd.lpData));
 
N

NightmareTerrible

#3
sinkopa
Огромное спасибо, помогло. О том, что в 2010-м строки стали уникодовскими я знал, но видимо не хватило опыта (или сообразительности). Без вашей помощи маялся бы ещё очень долго. Кстати, через StrPas не прокатило; возможно потому, что функция преобразует к строкам паскаля.