Recent

Author Topic: [SOLVED] Correct way to pass ordinary String to WinAPI Unicode functions  (Read 2572 times)

furious programming

  • Hero Member
  • *****
  • Posts: 858
There are at least few ways to convert standard String variable and pass the result as a PWideChar to Windows API functions with postfix W. But I am looking for a solution that is, above all, correct, short and will work without any problems on modern Windows (especially Windows 10) and using the OBJFPC mode.

So, in my program I store all strings as a standard String type. Now I need to pass two such strings to the ShellExecuteW function. These strings are to include the directory path and the file name. The function is to open a given directory in the file explorer and highlight the given file (setting lpOperation to explore). What is the correct way to pass such a strings to ShellExecuteW function?

Thanks for any suggestions.
« Last Edit: April 05, 2021, 09:08:50 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

ASerge

  • Hero Member
  • *****
  • Posts: 2241
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #1 on: April 05, 2021, 05:59:59 pm »
There are at least few ways to convert standard String variable and pass the result as a PWideChar to Windows API functions with postfix W. But I am looking for a solution that is, above all, correct, short and will work without any problems on modern Windows (especially Windows 10) and using the OBJFPC mode.

So, in my program I store all strings as a standard String type. Now I need to pass two such strings to the ShellExecuteW function. These strings are to include the directory path and the file name. The function is to open a given directory in the file explorer and highlight the given file (setting lpOperation to explore). What is the correct way to pass such a strings to ShellExecuteW function?
Use UnicodeString:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2.  
  3. uses Windows, ActiveX, ShellApi;
  4.  
  5. procedure SelectFileInExplorer(const FileName: string);
  6. var
  7.   Params: UnicodeString;
  8. begin
  9.   Params := ' /select, ' + UTF8Decode(FileName);
  10.   ShellExecuteW(0, nil, 'explorer.exe', PWideChar(Params), nil, SW_SHOW);
  11. end;
  12.  
  13. begin
  14.   SetMultiByteConversionCodePage(CP_UTF8); // Lazarus compatible
  15.   CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE);
  16.   SelectFileInExplorer('c:\Windows\system.ini');
  17. end.

Aidex

  • Jr. Member
  • **
  • Posts: 82
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #2 on: April 05, 2021, 06:10:04 pm »
I use this line ...
Code: Pascal  [Select][+][-]
  1. SysUtils.ExecuteProcess(UnicodeString('explorer.exe'),UnicodeString('/select,"'+fn+'"'),[]);  
  2.  

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1314
    • Lebeau Software
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #3 on: April 05, 2021, 07:45:51 pm »
I use this line ...
Code: Pascal  [Select][+][-]
  1. SysUtils.ExecuteProcess(UnicodeString('explorer.exe'),UnicodeString('/select,"'+fn+'"'),[]);  
  2.  

Are the typecasts really necessary?  ExecuteProcess() is overloaded for RawByteString and UnicodeString, so if the type-casts are removed:

Code: Pascal  [Select][+][-]
  1. SysUtils.ExecuteProcess('explorer.exe', '/select,"'+fn+'"', []);  
  2.  

Then, if String is a (UTF-8 encoded) AnsiString then the RawByteString overload will be called, otherwise String will be UnicodeString so the UnicodeString overload will be called instead.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Aidex

  • Jr. Member
  • **
  • Posts: 82
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #4 on: April 05, 2021, 08:00:10 pm »
The Unicode typecast is not necessary.
I only use it because I saw in the Windows specific sourcecodes of FreePascal that there is always a typecast to Unicode done internally.
Therefore I got used to use UnicodeString for paths and filenames if possible. At least under Windows it is no disadvantage, I think.
Since in my other source codes the filename is already defined as UnicodeString, I did so.
« Last Edit: April 05, 2021, 08:10:29 pm by Aidex »

furious programming

  • Hero Member
  • *****
  • Posts: 858
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #5 on: April 05, 2021, 08:51:55 pm »
To this day, I have used two ways to convert — one was:

Code: Pascal  [Select][+][-]
  1. PWideChar(UnicodeString(MyString))

and the other was:

Code: Pascal  [Select][+][-]
  1. PWideChar(UTF8ToUTF16(MyString))

Both worked, without any extra things. But I found it strange that the same conversion (regular String to PWideChar) could be solved in different ways. It seemed to me that they are not unambiguous. And now @ASerge gave another one, this time using the UTF8Decode function and UnicodeString as a temp variable (and other initialization functions, which is more complex that simple casting/converting).

Actually all these ways are correct?


Ultimately, I used ExecuteProcess because it allows me to skip the conversion (there is a version for RawByteString), and secondly, I can open the directory in the file explorer and additionally select the file, if it should be selected. The only problem is that I can't select multiple files this way — I tried various ways to use the /select parameter, but it didn't do anything.

Anyone have an idea how to open a directory in the system file explorer and highlight a few files? Is such a thing possible?
« Last Edit: April 05, 2021, 08:53:30 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

ASerge

  • Hero Member
  • *****
  • Posts: 2241
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #6 on: April 05, 2021, 08:59:19 pm »
Anyone have an idea how to open a directory in the system file explorer and highlight a few files? Is such a thing possible?
See SHOpenFolderAndSelectItems.

furious programming

  • Hero Member
  • *****
  • Posts: 858
Re: Correct way to pass ordinary String to WinAPI Unicode functions
« Reply #7 on: April 05, 2021, 09:08:12 pm »
Ok, thanks for the reply. But in my project this is additional feature, so I will consider its implementation. Thank you all for help, problems solved.
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

 

TinyPortal © 2005-2018