user12210905
user12210905

Reputation:

How can I load a Gdiplus::Bitmap from a path string?

I am using the GDI+ library and I have a problem. I want to use a string variable to load aBitmap variable. I don't know how to call it because I am new with this library.

My program is just taking the image.bmp path inside a string variable:

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;
}

I tried to use .c_str() with the username() but this is not working. Any suggestions?

I'm getting this error:

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>>)

So, how can I use username() to load a Bitmap?

Upvotes: 1

Views: 989

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595961

The Bitmap constructor you are trying to call takes a const wchar_t* as input, not a const char*, so you need to use std::wstring instead of std::string, eg:

#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;
}

That being said, using GetUserName() to build up a path to the user's Documents folder is the wrong way to go. User profiles are not always located at C:\Users\ on every machine. The user's Documents folder is not always located inside the user's profile, and is not always named "Documents". The path can be customized by users, so it could literally be located anywhere on the machine.

You SHOULD NOT build up such paths manually in your code. The Shell API has SHGetFolderPath() and SHGetKnownFolderPath() functions that are specifically designed to know where pre-defined system folders and user-specific folders are located, including the user's Documents folder. Use those APIs to get the real path, don't assume you know where the path is, you WILL be wrong sometimes.

For example:

#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;
}

Alternatively:

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

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

    return pcdocs;
}

Upvotes: 2

Related Questions