Why Does Makeintresource() Work

Why does MAKEINTRESOURCE() work?

This works because Windows doesn't allow mapping pages for the first 64 KB of the address space. To catch null pointer references. But I think also to catch pointer bugs in programs that were converted from the 16-bit version of Windows.

A side-effect is that this allows to reliably distinguish resource IDs packed into a pointer value since they'll always point to non-mappable memory.

How MAKEINTRESOURCE and WM_NOTIFY works?

lParam is not a pointer, it is an integer type parameter, so you have to cast it to the proper pointer type before using it.

LPNMHDR is just a typedef used for historical reason. You can just as well use NMHDR*. The FAR and _far qualifiers were used with 16-bit Windows, and are just noise left over from that time.

The MAKEINTRESOURCE is a trick used by the Windows C language interface, to simulate what an overloaded function would do in C++. This way you can call the CreateDialog with either a pointer (to string) parameter or an integer parameter. This uses knowledge that strings will never be allocated at very low addresses, so these can be reserved as an alias for the resource IDs. A rather ugly hack!

MAKEINTRESOURCE returning bad pointers for resource ID's

If by "bad pointers" you mean "pointers that don't point to resource objects in memory", then MAKEINTRESOURCE() is working correctly. The thing is that in order to pass either strings or integer IDs using the same function parameter, the Windows API functions make a weird pointer conversion which is detected by the function as a "oh wait, this is not a pointer, it's a resource ID".

This is documented behavior. For example, in the documentation for LoadBitmap(), it says:

lpBitmapName [in]:

A pointer to a null-terminated string that contains the name of the bitmap resource to be
loaded. Alternatively, this parameter can consist of the resource identifier in the
low-order word and zero in the high-order word. The MAKEINTRESOURCE macro can be used
to create this value.

Creating an invalid pointer by re-interpreting an arbitrary integer value is a legal C++ construct, but dereferencing the invalid pointer is undefined behavior.

In this case, the function receiving the argument checks if the high-order word is 0 and if so, uses the low-order word as an integer and never dereferences the pointer.

Note: If this feels like a nasty hack, it's because it is a nasty hack.

win32 DialogBox() and MAKEINTRESOURCE(): how to modify the app's ui?

You need to use resource editor (or even a text editor) to modify the dialog template in the resource file.

Missing resource name in Code::Blocks and therefore FindResource doesn't work

Resource types are identified by ID or name. Your resource script defines a resource type with name IMAGE (that's why you see "IMAGE" in ResEdit; note the quotation marks).

You are passing a resource type with name PNG to the call to FindResource. The module doesn't have a resource type named PNG. It contains a resource type named IMAGE. When you pass _T("IMAGE") your code starts to work.

Using resource names in WinAPI

Solution and Results:

Okay, so I've finally got a predictable results.

The way you find the resource is partially dependent on the resource type. In this case, DWG1 is a BINARY resource which is a custom type. There does not exist a predefined RT_* among the resource types, so you will need to specify the type as an LPCTSTR:

FindResource(hInstance, _T("DWG1"), _T("BINARY"));

For a predefined resource type, you cannot specify the type name as a LPCTSTR. Instead you must use the corresponding RT_* value. This is probably because each RT_* value corresponds to a MAKEINTRESOURCE(WORD), and if my understanding is correct, that macro result points to an invalid address within the portable executable file, not to a textual representation of the resource type.

This questions addresses MAKEINTRESOURCE

The issue with the ICON1 resource was that the type should have been RT_GROUP_ICON instead of RT_ICON. The difference of these two types is that the former is hardware-independent and the latter is hardware-dependent. Though, I do not know why RT_ICON didn't work.

Last, the issue with HTML1 was a fault on my part because I hadn't made sure that the referenced file actually had data. During the build, it was probably omitted since it was essentially a null resource. The correct type to use for this resource is RT_HTML.

Now, in regards to the names. As mentioned by Ben Voigt in a comment to his answer, non-numeric names are required in order to specify the name as a LPCTSTR. If numeric names are used, then one must use MAKEINTRESOURCE instead.

Visual Studio's resource editor makes it a bit cumbersome to name resources with strings instead of numbers, since by default it creates macros for each resource. These macros then replace the resource name with a number during the preprocessing phase.

In order to change the name into a string, you have 2 options:

  • Surround the ID of the resource (found in the properties) with double quotes. This prevents the resource editor from creating a macro for the name. However, a macro might already exist if quotations were placed around a previously set ID.

                                                   Resource Properties

  • Alternatively, open the resource script file in any text editor and choose the name like that. Again the idea is to prevent a macro from being generated. So detaching the the resource script and resource header would work, or simply make sure the macro doesn't exist in the header.

FindResource() doesn't work

In order to work i specified resource type manually:

HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_EXE1), L"EXE");

WinAPI - Loading Ressources from a DLL

Use simply LoadCursor with the corresponding hInstance. This works in the MFC and all of my Windows applications.

How to implement Win32 macro MAKEINTRESOURCE

I have found the solution of this problem. I am upgrading my code for this:

result = User32Ex.INSTANCE.GetMenuItemInfoW(hMenu.getPointer(), 4, true, menuiteminfow.getPointer());
if (!result.booleanValue()) {
int errorCode = Native.getLastError();
System.out.println("Error Code: " + errorCode);
return false;
}

CMINVOKECOMMANDINFOEX cmInvokeCommandEx = new CMINVOKECOMMANDINFOEX();
cmInvokeCommandEx.cbSize = cmInvokeCommandEx.size();
cmInvokeCommandEx.fMask = 0x00004000;
cmInvokeCommandEx.hwnd = null;
cmInvokeCommandEx.lpVerbW = new WTypes.LPWSTR(new Pointer(menuiteminfow.wId - 1));
cmInvokeCommandEx.lpVerb = new WTypes.LPSTR(new Pointer(menuiteminfow.wId - 1));
cmInvokeCommandEx.lpParameters = null;
cmInvokeCommandEx.lpParametersW = null;
cmInvokeCommandEx.lpDirectory = new WTypes.LPSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.lpDirectoryW = new WTypes.LPWSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.nShow = 5;
cmInvokeCommandEx.dwHotKey = 0;
cmInvokeCommandEx.hIcon = Pointer.NULL;
cmInvokeCommandEx.lpTitle = null;
cmInvokeCommandEx.lpTitleW = null;
cmInvokeCommandEx.ptInvoke = point;
cmInvokeCommandEx.write();

hResult = contextMenu2.InvokeCommand(cmInvokeCommandEx.getPointer());

The key change is that when you want invoke command threw the id and not the command you must define the wId to the lpVerb variable and not to the lpVerbW or both. Because the lpVerbW is for the unicode string command only.



Related Topics



Leave a reply



Submit