Click here to Skip to main content
15,867,488 members
Articles / General Programming / String
Alternative
Tip/Trick

Load a Windows string resource into a std::string or std::wstring

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
10 Jun 2010CPOL2 min read 13.1K   2   3
Alain's (original, now much hacked) narrow character version, could leak if std::basic_string::asign threw. To make the function exception safe either use a local buffer (if the size is fixed) or a vector (if the size isn't known).In both cases it's usually more efficient (and readable) to...
Alain's (original, now much hacked) narrow character version, could leak if std::basic_string<>::asign threw. To make the function exception safe either use a local buffer (if the size is fixed) or a vector (if the size isn't known).

In both cases it's usually more efficient (and readable) to return a string by value than construct it outside the function and essentially reconstruct it within the function. This doesn't help too much if you want the semantics of the windows LoadString but there's not a lot of reason to return the size of the loaded string. This information isn't needed in the wide character case and is useless in the narrow character case (it's always going to be less than the size passed into the function).

I'd be tempted to use:

[When I first wrote this I was seduced into the idea that you could directly initialise a string from a pointer and a length. However the C++ standard doesn't specify which order parameters are evaluated prior to a function call so we need to stick a sequence point in between the read and the string construction.]

std::wstring load_wstring_from_resource( HINSTANCE instance_handle, unsigned resource_id )
{
    wchar_t *buffer = 0;
    std::size_t string_length = LoadStringW(
        instance_handle,
        resource_id,
        reinterpret_cast<wchar_t *>( &buffer ),
        0 );

    return std::wstring( buffer, string_length );
 );
}


or:

std::string load_string_from_resource( HINSTANCE instance_handle, unsigned resource_id )
{
    char buffer[ 1024 ] = { '\0' };
    std::size_t string_length = LoadStringA(
        instance_handle,
        resource_id,
        buffer,
        1024 );

    return std::string( buffer, string_length );
}


[Note that here you could get away with doing it all in one line as there's no way the location of buffer is going to change. However it leads more naturally onto the next one...]

And for those that really want big strings and dynamic memory allocation, you can get that by:

std::string load_string_from_resource( HINSTANCE instance_handle, unsigned resource_id, std::size_t max_size )
{
    std::vector<char> buffer( max_size );
    std::size_t string_length = LoadStringA(
        instance_handle,
        resource_id,
        &buffer[ 0 ],
        max_size );

    return std::string( &buffer[ 0 ], string_length );
}


No exception handling required and is still exception safe. And on VC++ 2010 it's faster using the vector than manually handling exceptions from new[].

Just remember folks - new and delete, there's usually a better way. Be exception safe out there!

Ash

PS: Edited to buggery as I'd forgotten to escape a couple of angle brackets.

PPS: Edited more to buggery as I'd been making assumptions about the order of evaluation of parameters to functions.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I've been programming since 1985 - starting with Fortran 77, then moving onto assembler, C and C++ in about 1991. I also know enough Java and Python to read code but you probably wouldn't want me writing it.

I've worked in a wide variety of application areas - defense, banking, games and security with the longest stints being in security. I also seem to end up programming devices far too often. This time I'm programming terahertz band body scanners.

Comments and Discussions

 
GeneralSee my last update :) Pin
Alain Rist10-Jun-10 10:31
Alain Rist10-Jun-10 10:31 
GeneralAnything in the standard library can throw unless it's docum... Pin
Aescleal8-Jun-10 11:29
Aescleal8-Jun-10 11:29 
GeneralHi, std::basic_string<>::assign() does NOT throw (or it is u... Pin
Alain Rist8-Jun-10 11:16
Alain Rist8-Jun-10 11:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.