delphiwinapidelphi-10.4-sydney

Trying to complete the ShFileOpStruct in Delphi Sydney CE


I am trying to move from Delphi 7 and these pWide....

The code below only loads the '123' string. The pFrom is a PWideChar, so how do I load the file names with a separator of #0? And append #0#0 to complete the requirement?

procedure TForm13.Button1Click(Sender: TObject);
var
  s: String;
  sfo: TSHFileOpStruct;
begin
  s:='123'+#0+'456'+#0;
  sfo.pfrom:=pchar(s);
end;

I have tried various options, using pWideString or pChar as above, but to no avail. Trying to concatenate the pFrom with #0 also failed with an error:

operator not applicable to this operand type

Please help a newbie.


Solution

  • Simply drop the + when building up your string literal, eg:

    procedure TForm13.Button1Click(Sender: TObject);
    var
      s: String;
      sfo: TSHFileOpStruct;
    begin
      s := '123'#0'456'#0;
      sfo.pfrom := PChar(s);
    end;
    

    This is described in Delphi's documentation:

    Fundamental Syntactic Elements (Delphi): Character Strings

    A control string is a sequence of one or more control characters, each of which consists of the # symbol followed by an unsigned integer constant from 0 to 65,535 (decimal) or from $0 to $FFFF (hexadecimal) in UTF-16 encoding, and denotes the character corresponding to a specified code value. Each integer is represented internally by 2 bytes in the string. This is useful for representing control characters and multibyte characters. The control string:

    #89#111#117

    Is equivalent to the quoted string:

    'You'

    You can combine quoted strings with control strings to form larger character strings. For example, you could use:

    'Line 1'#13#10'Line 2'

    To put a carriage-return line-feed between 'Line 1' and 'Line 2'. However, you cannot concatenate two quoted strings in this way, since a pair of sequential apostrophes is interpreted as a single character. (To concatenate quoted strings, use the + operator or simply combine them into a single quoted string.)

    This should work in Delphi 7, too.

    On the other hand, if you want to do it more dynamically (say, the filenames are coming from variables), then you can do something more like this:

    procedure TForm13.Button1Click(Sender: TObject);
    var
      fileNames: array of string; // or whatever container you want
      fileName, s: String;
      len: Integer;
      P: PChar;
      sfo: TSHFileOpStruct;
    begin
      SetLength(fileNames, 2);
      fileNames[0] := '123';
      fileNames[1] := '456';
    
      len := 0;
      for fileName in fileNames do
        Inc(len, Length(fileName)+1);
    
      SetLength(s, len);
      P := PChar(s);
    
      for fileName in fileNames do
      begin
        len := Length(fileName);
        Move(PChar(fileName)^, P^, len*SizeOf(Char));
        Inc(P, len);
        P^ := #0;
        Inc(P);
      end;
    
      sfo.pfrom := PChar(s);
    end;
    

    Alternatively:

    procedure TForm13.Button1Click(Sender: TObject);
    var
      fileNames: TStringList;
      s: String;
      sfo: TSHFileOpStruct;
    begin
      fileNames := TStringList.Create;
      try
        fileNames.Add('123');
        fileNames.Add('456');
    
        fileNames.Delimiter := #0;
        fileNames.QuoteChar := #0;
        fileNames.StrictDelimiter := True;
    
        s := fileNames.DelimitedText + #0;
      finally
        fileNames.Free;
      end;
    
      sfo.pfrom := PChar(s);
    end;