Jak użyć SHFileOperation w Qt. Conversja QString do PCZZTSTR.

0

Witam.
Szukam sposobu na kopiowanie całych katalogów wraz z zawartością do innego katalogu pod Windows w Qt.
Używam Qt5.6.0-VS2013x64-beta. Googlałem trochę i nie znalazłem prostej metody w Qt, ale jest funkcja SHFileOperation z "Windows.h".
Problem wtym że nie potrafię przekonwerować Qstring do PCZZTSTR. (to potrzebne do uzupełnienia struktury SHFILEOPSTRUCT.

Gdy próbowałem na sztywno wpisać ścieżki, to działa:

  LPSHFILEOPSTRUCTW shf;
  shf->hwnd = NULL;
  shf->pFrom = L"C:\\Users\\PRO\\Documents\\Qt_copy_test_AA\\\0";
  shf->pTo   = L"C:\\Users\\PRO\\Documents\\Qt_copy_test\\\0";
  SHFileOperationW(shf); 

Nie stety, potrzebuję conversji z QString:

  b1 = itm->item(0 ,1)->text().utf16(); // to jest pobranie tekstu z QStandartItem.
 shf->pFrom =b1;
 

próbowałem też;

 
  WCHAR b1[MAX_PATH];
  int ln = itm->item(0 ,1)->text().toWCharArray(b1);
  b1[ln] = '\0';
  b1[ln+1] = '\0'; 
  shf->hwnd = NULL;
  shf->pFrom = b1;
  shf->pTo   = L"C:\\Users\\PRO\\Documents\\Qt_copy_test\\\0";
  SHFileOperationW(shf);

Nie stety, albo się nie kompiluje albo program się wywala przy uruchomieniu SHFileOperationW
Ma ktoś doświadczenie jak to rozgryźć?
Dziękuję i pozdrawiam
P.S.
Jeżeli nie ten dzial, to proszę o przeniesienie wątku.

2

Problem pierwszy kodowanie!
Ustal jakiego kodowania używa Windows dla napisów typu PCZZTSTR i funkcji SHFileOperationW.
Upewnij się, że jest to to samo kodowanie co użyte przy QString::toWCharArray i wielkość wchar jest ta sama.
Zwróć uwagę, że Qt udostępnia też inne funkcje które mogą pomóc:
http://doc.qt.io/qt-5/qstring.html#utf16
http://doc.qt.io/qt-5/qstring.html#toUcs4
http://doc.qt.io/qt-5/qstring.html#toStdWString

Problem drugi separator katalogów!
Qt jest wielkoformatowy i bardziej jest zakorzeniony w systemach Unixopodobnych. Dlatego domyślnym separatorem katalogów w Qt jest /, a nie \ i jest to jednolite zachowanie na wszystkich platformach, ergo QOpenDialog zwróci ci ścieżkę: C:/Users/PRO/Documents/Qt_copy_test/, a nie: C:\Users\PRO\Documents\Qt_copy_test\!
Dlatego zanim dokonasz konwersji napisu, musisz też zadbać o zgodność separatorów katalogu.

3

SHFILEOPSTRUCT to struktura.
LPSHFILEOPSTRUCT to wskaźnik.

mażesz po niezaalokowanej pamięci.

1
#define _WIN32_WINNT 0x501
#include <windows.h>
#include <shellapi.h>
#include <QString>
#include <iostream>

#pragma comment(lib, "shell32.lib")

using namespace std;

int main()
{
    QString dupa = QStringLiteral("plik1.txt\0");
    QString dupb = QStringLiteral("plik2.txt\0");
    
    SHFILEOPSTRUCT shf = {};
    shf.wFunc = FO_COPY;
    shf.pFrom = (wchar_t*)dupa.utf16();
    shf.pTo   = (wchar_t*)dupb.utf16();
    cout << SHFileOperation(&shf) << endl;
}
0

@Azarien - Dzięki bardzo za odpowiedź.
Nie zadziałało to co podałeś (próbowałem na wiele sposobów)

Natomiast wykombinowałem coś takiego;

   std::wstring b1 = itm->item(0 ,1)->text().toStdWString();
              b1.push_back(L'\0');
              
  SHFILEOPSTRUCT shf = {};
  shf.hwnd = 0;
  shf.wFunc = FO_COPY;
  shf.pFrom = b1.c_str(); //(wchar_t*)(itm->item(0 ,1)->text().utf16());
  shf.pTo   = L"C:\\Users\\PRO\\Documents\\Qt_copy_test\\\0";
  SHFileOperation(&shf);

użycie std::wstring pozwala na dodanie kończącego '\0' do ścieżki. W helpie na MSDN można znaleźć info, że PCZZWSTR musi być zakończony podwójnym: \0\0. OK działa.
Teraz pytanie czy to jest bezpieczne i poprawne rozwiązanie.
Dziękuję wszystkim za odpowiedzi.
Pozdrawiam.

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