Ścieżka do folderu specjalnego - desktop

0

Witam
Mam problem z pewnym zagadnieniem. Chcę stworzyć na pulpicie folder. Używam procedury

mkdir((GetSpecialFolderPath(CSIDL_DESKTOPDIRECTORY))+'\Test');

Teoretycznie działa. Jednak problem się pojawia, gdy zmienię profil w Windowsie, który posiada polskie litery np. profil o nazwie Paweł, pojawia się błąd i nie tworzy folderu - polskie znaki zamieniają się w ?. Próbowałem używać AnsitoUTF8 i UTF8toAnsii ale nie pomogło.

Proszę o pomoc. Z góry dziękuje

2

Funkcja SHGetSpecialFolderPath jest przestarzała i w niedalekiej przyszłości zostanie całkowicie usunięta z WinAPI. Dla wsparcia systemów starszych niż Vista wykorzystaj SHGetFolderPath, a dla nowszych użyj SHGetKnownFolderPath.

Po drugie, używaj funkcji z sufiksem W, czyli wersji wspierającej unikod.

0

Witam po dłuższej przerwie

dziękuję za podpowiedź

Idąc tym tropem znalazłem kolejny problem (zaczerpnąłem przykład z Internetu)

uses 
...
type
...
const
FOLDERID_DESKTOP: TGUID = '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}';
KF_FLAG_CREATE = $00008000;

function SHGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle; var ppszPath: LPWSTR): HResult; stdcall; external 'Shell32.dll';

....

procedure TForm5.SpeedButton14Click(Sender: TObject);
begin

showmessage(SHGetKnownFolderPath(FOLDERID_DESKTOP, KF_FLAG_CREATE, 'test', Path));   

Pojawia mi się błąd podczas kompilacji z uwagi na "LPWSTR", nie wiem jak sobie z nim poradzić

Dziękuję z góry za pomoc

0
koper9090 napisał(a):

Pojawia mi się błąd podczas kompilacji z uwagi na "LPWSTR", nie wiem jak sobie z nim poradzić

Wklej dokładny komunikat błędu, jeśli chcesz szybko uzyskać pomoc.

0

Proponuję utworzyć folder z uprawnieniami administratora. Możesz mieć kod, który działa poprawnie a stanie się dla Ciebie łamigłówką. tylko z pozycji uprawnień. kod działa w delphi i lazarusie.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ShlObj, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function FolderDesktop(const Folder: Integer): string;
var
  Path: shortstring;
begin
  SHGetSpecialFolderPath(0, @Path, Folder , False);
  FolderDesktop := StrPas(@Path);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Sciezka: string;
  s : string;
begin
  s := InputBox('Podaj nazwę folderu', 'Podaj proszę nazwę folderu utworzonego w Pulpit', s);
  Sciezka :=  FolderDesktop(CSIDL_DESKTOP);

  Caption := 'Ścieżka zostanie utworzona'+Sciezka;

  CreateDir(Sciezka+'\'+s);  //  Nowy folder o nazwie wpisanej do inputbox
end;

end.

0

Demo w Lazarus

1

W takim razie, kiedy masz do czynienia z polskimi znakami w ścieżce używaj nazwy DOS Np.

begin
Showmessage('LOKALIZACJA PROGRAMU Project1.exe'+#13+
 'Ścieżka pełna : '+Application.ExeName+#13+
 'Ścieżka skrócona : '+ExtractShortPathName(application.ExeName) ;
end;

Ścieżka skrócona w tym przypadku właściwy wybór

1

Funkcja SHGetSpecialFolderPath jest przestarzała i nie warto jej w ogóle używać. To już nie chodzi o to, że jest zdeprecjonowana – została już oznaczona jako niewspierana, więc przy najbliższej okazji zostanie całkowicie usunięta z biblioteki systemowej. A to spowoduje, że programy ją wykorzystujące nie dość że nie będą działać prawidłowo, to mogą się w ogóle nie uruchomić, skoro nie znajdą punktu wejścia. Tak więc to co proponujesz nie ma najmniejszego sensu.

Jeśli zależy komuś na wsparciu systemów starszych niż Vista, należy skorzystać z funkcji SHGetFolderPath. Ta funkcja jest zdeprecjonowana, ale w najbliższych latach nie grozi jej usunięcie z API. Dla systemów Vista+ jest funkcja SHGetKnownFolderPath, więc jeśli wsparcie starych systemów nie jest potrzebne, jej należy użyć.

0

Witam jeszcze raz.
korzystałem z różnych podpowiedzi jednak żadna nie przyniosła rozwiązania problemu związanego z stworzeniem folderu na pulpicie. Wszystko niby działa do czasu konta w Windows z polskimi znakami. Za każdym razem występuje komunikat "Nie wykonano procedury gdyż nie znaleziono \Pawe?\Deskop\Test"

np.
uses
...shlobj...

const
  FOLDERID_DESKTOP: TGUID = '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}';
  KF_FLAG_CREATE = $00008000;

  function SHGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle; var ppszPath: LPWSTR): HResult; stdcall; external 'Shell32.dll';
        

podczas kompilacji wyskakuje błąd

unit5.pas(406,1) Error: Identifier not found "LPWSTR"

Czy mógłbym prosić o jakąś podpowiedź co robię źle?

3
uses
  WinDirs, LazUTF8, LazFileUtils;

begin
  CreateDirUTF8(WinCPToUTF8(GetWindowsSpecialDir(CSIDL_DESKTOPDIRECTORY)) + 'test');
end;
1
koper9090 napisał(a):

podczas kompilacji wyskakuje błąd

unit5.pas(406,1) Error: Identifier not found "LPWSTR"

Czy mógłbym prosić o jakąś podpowiedź co robię źle?

Źle robisz, że nie próbujesz zrozumieć dlaczego ten błąd dostajesz. ;)

A powód jest prosty – typ danych LPWSTR nie jest znany w czasie kompilacji, więc musisz dodać moduł, który zawiera jego deklarację. Jest to typ danych przeznaczony dla funkcji WinAPI, więc jego deklaracja znajduje się w module Windows. Tak więc dodaj ten moduł do listy uses i próbuj.

Choć @Paweł Dmitruk podał jeszcze inne rozwiązanie, więc spróbuj też jego sugestii.

2
furious programming napisał(a):

Po drugie, używaj funkcji z sufiksem W, czyli wersji wspierającej unikod.

Jest też nowe rozwiązanie - począwszy od Windows 10 ver 1903 można z odpowiednim manifestem w exeku używać UTF-8 w funkcjach z sufixem A:

https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page

0

Dziękuje za szybka odpowiedź, sprawę rozwiązanie @PAWEŁ Dmitruk.

Co do modułu Windows to mogę nadmienić, że po jego wpisaniu pojawił mi się kolejny błąd przy istniejących procedurach w kodzie źródłowym

np

procedure TForm5.ListBox7MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);    

...
ItemAtPos(Point(X,Y),true);
unit5.pas(1201,34) Fatal: Syntax error, ")" expected but "," found

błąd dotyczy przecinka pomiędzy X Y

bez tego modułu działa poprawnie, z modułem niestety nie

1
ItemAtPos(Classes.Point(X, Y), True);
3
koper9090 napisał(a):

Co do modułu Windows to mogę nadmienić, że po jego wpisaniu pojawił mi się kolejny błąd przy istniejących procedurach w kodzie źródłowym

Znany problem – występuje ”kolizja” identyfikatorów i kompilator wybiera pierwszy znany. Widać w Twoim przypadku, typ POINT z modułu Windows znany jest wcześniej niż funkcja Point z modułu Types (lub Classes), dlatego ten jest brany pod uwagę. Zapis z nawiasami kompilator traktuje jako rzutowanie, w którym przecinek oczywiście nie jest dozwolony – rzutowanie jest jednoargumentowe (jako wartość lub wynik wyrażenia). Dlatego określenie pochodzenia identyfikatora (jak pokazał @Paweł Dmitruk wyżej) jest konieczne.

To samo będzie w przypadku typu Windows.RECT oraz funkcji Types.Rect. Dlatego zamiast używania funkcji, polecam wykorzystać konstruktory typów danych, np. TPoint.Create czy TRect.Create – ból głowy będzie mniejszy.

0

Dziękuję za podpowiedź

1 użytkowników online, w tym zalogowanych: 0, gości: 1