Как я могу загрузить Gdiplus :: Bitmap из строки пути? - PullRequest
0 голосов
/ 10 ноября 2019

Я использую библиотеку GDI +, и у меня проблема. Я хочу использовать строковую переменную для загрузки переменной Bitmap. Я не знаю, как ее вызвать, потому что я новичок в этой библиотеке.

Моя программа просто берет путь image.bmp внутри строковой переменной:

string username()
{
    char username[UNLEN + 1];
    DWORD username_len = UNLEN + 1;
    GetUserName(username, &username_len);
    string pcuser = username;
    return pcuser;
}

int main()
{
    Gdiplus::Bitmap bmp("C:\\Users\\" + username() + "\\Documents\\Visual Studio Things\\image.bmp");
    return 0;
}

Я пыталсяиспользуйте .c_str() с username(), но это не работает. Любые предложения?

Я получаю эту ошибку:

Error (active)  E0289   no instance of constructor "Gdiplus::Bitmap::Bitmap" matches the argument list                  argument types are: (std::basic_string<char, std::char_traits<char>, std::allocator<char>>)

Итак, как я могу использовать username() для загрузки Bitmap?

1 Ответ

1 голос
/ 11 ноября 2019

Конструктор Bitmap, который вы пытаетесь вызвать, принимает const wchar_t* в качестве ввода, а не const char*, поэтому вам нужно использовать std::wstring вместо std::string, например:

#include <windows.h>
#include <gdiplusheaders.h>
#include <string>

wstring username()
{
    wstring pcuser;
    wchar_t username[UNLEN + 1];
    DWORD username_len = UNLEN + 1;

    if (GetUserNameW(username, &username_len))
        pcuser.assign(username, username_len-1);

    return pcuser;
}

void doWork()
{
    wstring path = L"C:\\Users\\" + username() + L"\\Documents\\Visual Studio Things\\image.bmp";
    Gdiplus::Bitmap bmp(path.c_str());
    ...
} 

int main()
{
    GdiplusStartupInput input;
    ULONG_PTR token;

    GdiplusStartup(&token, &input, NULL);

    doWork();

    GdiplusShutdown(token);

    return 0;
}

Как говорится, использование GetUserName() для создания пути к папке Documents пользователя - неправильный путь. Профили пользователей не всегда расположены на C:\Users\ на каждой машине. Папка пользователя Documents не всегда находится внутри профиля пользователя и не всегда называется "Documents". Путь может быть настроен пользователями, поэтому он может буквально располагаться в любом месте на машине.

Вы НЕ ДОЛЖНЫ создавать такие пути вручную в своем коде. API оболочки имеет функции SHGetFolderPath() и SHGetKnownFolderPath(), которые специально предназначены , чтобы знать, где находятся предопределенные системные папки и пользовательские папки,включая папку пользователя Documents. Используйте эти API, чтобы получить реальный путь, не предполагайте, вы знаете, где находится путь, вы иногда будете ошибаться.

Например:

#include <windows.h>
#include <Shlobj.h>
#include <shlwapi.h>
#include <gdiplusheaders.h>
#include <string>

wstring userdocs()
{
    wstring pcdocs;
    wchar_t path[MAX_PATH];

    if (SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path) == S_OK) 
    {
        if (PathAddBackslashW(path))
            pcdocs = path;
    }

    return pcdocs;
}

void doWork()
{
    wstring path = userdocs();
    if (path.empty()) return;
    path += L"Visual Studio Things\\image.bmp";

    Gdiplus::Bitmap bmp(path.c_str());
    ...
}

int main()
{
    GdiplusStartupInput input;
    ULONG_PTR token;

    GdiplusStartup(&token, &input, NULL);

    doWork();

    GdiplusShutdown(token);

    return 0;
}

В качестве альтернативы:

wstring userdocs()
{
    wstring pcdocs;
    wchar_t *path;

    if (SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &path) == S_OK)
    {
        pcdocs = path;
        pcdocs += L"\\";
        CoTaskMemFree(path);
    }

    return pcdocs;
}
...