Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Delphi中带字符串的Concat PChar_String_Delphi_Pointers_Delphi 2010 - Fatal编程技术网

String Delphi中带字符串的Concat PChar

String Delphi中带字符串的Concat PChar,string,delphi,pointers,delphi-2010,String,Delphi,Pointers,Delphi 2010,我需要构造一个字符串并通过PostMessage发送它,即 FileName := String_1 + String_2 + String_3; PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName)); FileName := AnotherString + Directory_Str + FileName; PostMessage(FWndHandle, WM_BLA_BLA, NotifyData

我需要构造一个字符串并通过
PostMessage
发送它,即

FileName := String_1 + String_2 + String_3;
PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));
FileName := AnotherString + Directory_Str + FileName;
PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));
但有些东西不起作用。另外,文件名是一个PChar。代码如下所示:

var
   FileName : PChar;
   Directory_Str : String;
   AnotherString : String;
begin
    // Get memory for filename and fill it with data
    GetMem(FileName, NotifyData^.FileNameLength + SizeOf(WideChar));
    Move(NotifyData^.FileName, Pointer(FileName)^, NotifyData^.FileNameLength);
    PWord(Cardinal(FileName) + NotifyData^.FileNameLength)^ := 0;

    // TODO: Contact string before sending message
    // FileName := AnotherString + Directory_Str + FileName;

    PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));

    ...
end;
function HeapAllocatedPChar(const Value: string): PChar;
var
  bufferSize: Integer;
begin
  bufferSize := (Length(Value)+1)*SizeOf(Char);
  GetMem(Result, bufferSize);
  Move(PChar(Value)^, Result^, bufferSize);
end;

procedure PostString(Window: HWND; Msg: UINT; wParam: WPARAM; 
  const Value: string);
var
  P: PChar;
begin
  P := HeapAllocatedPChar(Value);
  if not PostMessage(Window, Msg, wParam, LPARAM(P)) then
    FreeMem(P);
end;
PostString(FWndHandle, WM_BLA_BLA, NotifyData^.Action, FDirectory + FileName);
现在,在调用
PostMessage
之前,我需要联系变量
FileName
的另一个字符串

FileName := String_1 + String_2 + String_3;
PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));
FileName := AnotherString + Directory_Str + FileName;
PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));
如果文件名是一个字符串,这将起作用,但这里的情况并非如此

有人知道如何使用PChar吗?我尝试过这些方法,有时有效,但最后总会有东西坏掉:

StrPCopy(FileName, FDirectory + String(FileName));


对于通过引用传递的数据,您无法轻松使用
PostMessage
。原因是
PostMessage
异步执行,您需要保持传递的内存处于活动状态,直到收件人处理完邮件。我想这就是你的
GetMem
代码背后的原因

显然,这只在同一过程中起作用。您还将发现Windows不允许您对其接收指针的任何消息使用
PostMessage
。例如,
PostMessage
WM_SETTEXT
总是失败。您只能希望使用用户定义的消息来执行此操作。当然,您需要释放接收消息的代码中的内存

我假设您使用的是用户定义的消息,它允许发送带有
PostMessage
的字符串。在这种情况下,您已经有了解决方案。使用字符串变量进行连接,然后使用答案中的第一块代码

虽然您可以像这样使它更干净:

var
   FileName : PChar;
   Directory_Str : String;
   AnotherString : String;
begin
    // Get memory for filename and fill it with data
    GetMem(FileName, NotifyData^.FileNameLength + SizeOf(WideChar));
    Move(NotifyData^.FileName, Pointer(FileName)^, NotifyData^.FileNameLength);
    PWord(Cardinal(FileName) + NotifyData^.FileNameLength)^ := 0;

    // TODO: Contact string before sending message
    // FileName := AnotherString + Directory_Str + FileName;

    PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));

    ...
end;
function HeapAllocatedPChar(const Value: string): PChar;
var
  bufferSize: Integer;
begin
  bufferSize := (Length(Value)+1)*SizeOf(Char);
  GetMem(Result, bufferSize);
  Move(PChar(Value)^, Result^, bufferSize);
end;

procedure PostString(Window: HWND; Msg: UINT; wParam: WPARAM; 
  const Value: string);
var
  P: PChar;
begin
  P := HeapAllocatedPChar(Value);
  if not PostMessage(Window, Msg, wParam, LPARAM(P)) then
    FreeMem(P);
end;
PostString(FWndHandle, WM_BLA_BLA, NotifyData^.Action, FDirectory + FileName);
你可以这样调用这个过程:

var
   FileName : PChar;
   Directory_Str : String;
   AnotherString : String;
begin
    // Get memory for filename and fill it with data
    GetMem(FileName, NotifyData^.FileNameLength + SizeOf(WideChar));
    Move(NotifyData^.FileName, Pointer(FileName)^, NotifyData^.FileNameLength);
    PWord(Cardinal(FileName) + NotifyData^.FileNameLength)^ := 0;

    // TODO: Contact string before sending message
    // FileName := AnotherString + Directory_Str + FileName;

    PostMessage(FWndHandle, WM_BLA_BLA, NotifyData^.Action, LParam(FileName));

    ...
end;
function HeapAllocatedPChar(const Value: string): PChar;
var
  bufferSize: Integer;
begin
  bufferSize := (Length(Value)+1)*SizeOf(Char);
  GetMem(Result, bufferSize);
  Move(PChar(Value)^, Result^, bufferSize);
end;

procedure PostString(Window: HWND; Msg: UINT; wParam: WPARAM; 
  const Value: string);
var
  P: PChar;
begin
  P := HeapAllocatedPChar(Value);
  if not PostMessage(Window, Msg, wParam, LPARAM(P)) then
    FreeMem(P);
end;
PostString(FWndHandle, WM_BLA_BLA, NotifyData^.Action, FDirectory + FileName);
您当前的代码失败,因为:

  • 调用StrPCopy时,不会为较长的字符串分配任何内存
  • 当您编写
    PChar(另一个字符串+目录\u Str+文件名)
    时,您陷入了您试图用
    GetMem
    避免的陷阱。这是一个本地字符串,在处理消息时已解除分配

  • 如果您可以找到一种解决问题的方法,而无需使用
    PostMessage
    来传递字符串,那么这可能比所有这些复杂度都要好。

    请参阅David的答案,了解代码失败的原因

    我总是定义一个类,用于通过
    PostMessage
    操作分发字符串。 没有泄漏的风险,并且可以通过更多信息轻松扩展

    Type
      TMyMessage = class
        msg : String;
        Constructor Create(aMessage : String);
      end;
    
    
    // Sending the message
    var
      myMsg : TMyMessage;
    ...
    myMsg := TMyMessage.Create('A message');
    
    if not PostMessage(someHandle,WM_something,WParam(myMsg),0)
    then begin
      myMsg.free;
      ... Take care of this condition if PostMessage fails !!
    end;  
    
    // Receiving the message
    
    procedure TSomeForm.GetMessage(var msg : TMessage);
    var
      aMsg : TMyMessage;
    begin
      ...
      aMsg := TMyMessage(msg.WParam);
      try
        ...
        // Do something with the message
      finally
        aMsg.Free;
      end;
    end;
    

    “有些东西不起作用”和“总是有些东西在最后坏了”是什么意思?你有什么具体问题?为什么要使用
    PChar
    GetMem
    ?(哦,为什么一开始就要混合这些类型?)PostMessage字符串的一个问题是,当字符串在目标线程/窗口中接收到之前超出范围时,字符串往往会被破坏-PostMessage只是传递指针,它不知道字符串上的refCount,因此不会增加它。@MartinJames,这就是问题中的代码使用
    GetMem
    分配缓冲区的原因@KenWhite:你完全正确,时间真的很晚了,我只是快速键入了问题,没有详细说明,但David得到了它,它的解决方案工作得很好!这是一个很好的例子,说明了为什么将代码分成小的功能部分是值得的。通过将GetMem/buffer复制代码与消息发布代码混合在一起,重新处理该代码变得更加困难。但是,将关注点分离为单独的函数这一琐碎的权宜之计突然变得容易了。当然,事后诸葛亮总是让我们更容易看到正确的功能分解。但要时刻注意这些问题,并注意更好地分解代码。