Date: | January 1, 2015 / year-entry #1 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20150101-00/?p=43243 |
Comments: | 15 |
Summary: | The FindResourceEx function is an extension of the FindResource function in that it allows you to specify a particular language fork in which to search for the resource. Calilng the FindResource function is equivalent to calling FindResourceEx and passing zero as the wLanguage. Except for the horrible nasty gotcha: The second and third parameters to... |
The Except for the horrible nasty gotcha: The second and third parameters to In other words, if you are adding custom language support to a program, you cannot just stick a
The nasty part of this is that since the second and third parameters are the same type, the compiler won't notice that you got them backward. The only way you find out is that your resource code suddenly stopped working. |
Comments (15)
Comments are closed. |
Raymond, is there any sort of team at Microsoft that has oversight on official API structure?
"The nasty part of this is that since the second and third parameters are the same type".
Ah, the ancient variant of the modern "stringly typed" approach. Let's call it "types are integral for quality assurance".
How could such an horrible API extension happen?
Perhaps FindResourceEx should be deprecated in favor of a hypothetical FindResourceExEx which doesn't switch the parameters?
In retrospect, lpType looks like a good candidate for an enum.
[Though that wouldn't leave a place for user-defined types. -Raymond]
Wait, you can add user-defined types? What happens when the next version of Windows supports that type?
RT_*
). User-defined types are strings (TEXT("name")
). -Raymond]@Joshua, I imagine that most people calling FindResourceEx are also authors of the resources themselves. I suspect that interference shouldn't be much of a real problem in practice.
Joshua, the types are just recommendations, and can actually contain any data you want, if you read them in a generic way.
Of course, if you want something else to read them, then stick to the standard type values.
Ok now I feel really silly. FindResourceEx/LoadResource return the raw bytes even if it is a standard type. Calling LoadResource on an icon resource returns the bytes of the .ico file. While I'm pretty sure a cross-id would cause major headaches, it won't be a headache here (although it might have been on Win9x but that branch is not getting anymore feature releases).
Is there any specific reason why there never was a LoadStringEx method that allowed passing a language ID as well?
It's not too hard to assemble, but it shouldn't be required.
@Greg Rottensteiner. Those resource API's take an instance handle to the DLL as the first parameter. Isn't that usually the MUI DLL's handle, done by LoadMUILibrary for old Windows versions, and just LoadLibrary for Vista and beyond? (And I suppose you could implement a custom scheme if you want as long as you get the desired resource DLL HINSTANCE.) But I'm not a globalisation dude so may be wrong.
You can do user-defined types with an integer (e.g., WM_USER.)
Similar thing happened to me with WNetAddConnection2, whose prototype is (…, LPCTSTR lpPassword, LPCTSTR lpUsername, …). Who in his right mind puts the password first? That's one debugging day I'd like to have back.
In other news, C# and other modern languages have named parameters to avoid these kinds of mistakes:
WNetAddConnection2(…, lpPassword: myPassword, lpUsername: myUsername, …)
I've been pestering my team mates to add these anywhere the params are not blindingly obvious.
"In other news, C# and other modern languages have named parameters to avoid these kinds of mistakes"
And if you're using Visual Studio (or another IDE that provides an equivalent) IntelliSense will help you out as you're typing the function call out by showing you the parameter names.
"IntelliSense will help you" This helps to write a new call, but it doesn't help you to verify (understand) already written code. (I know how to force the tooltip in the IDE. But if you are looking at something in source control, you can't.)