1

Hello everyone, I have some confusion regarding some Win32 API data types and macros that we use-:

Firstly-: Regarding the WM_NOTIFY message. The lparam contains the pointer to the NMHDR structure. So if its a pointer why is it illegal to access the NMHDR structure like this-:

(*lparam)->idFrom

I mean if its a pointer then I could just use an indirection operator to get to the structure. LPARAM is itself typedefed from LONG_PTR. Why do I have to write the code like this-:

((LPNMHDR)lparam)->idFrom

What is LPNMHDR? LPNMHDR is typedefed in the following way-:

typedef NMHDR FAR * LPNMHDR;

FAR* is again defined in the following way-:

#define FAR _far

What is _far and why to I have to use LPNMHDR cast to access the NMHDR structure from LPARAM?

Secondly-: What does the MAKEINTRESOURCE macro do? I have seen a lot of authors use a plain string when specifying resources to functions. For example-:

CreateDialog(hInst,"Dialog Box",
                hwnd,(DLGPROC)DialogFunc);

But in modern compilers we use-:

CreateDialog(hInst,MAKEINTRESOURCE(DIALOG_BOX),
                hwnd,(DLGPROC)DialogFunc);

I know that if we use a string identifier in the resource file instead of a number then we can omit this macro so does this macro convert a number to a string. For example does it convert 23 into "23"?? Because if it did then I would be able to use -:

CreateDialog(hInst,"23",
                hwnd,(DLGPROC)DialogFunc);

if my dialog box resource was defined with 23. But this doesn't work.

So I want to know what is the outcome after this macro processes an identifier? How does it work? What would I have to do in order to print the value of the MAKEINTRESOURCE in a message box because I am facing problems while copying the value to a string using the the sprintf function. But I know that MAKEINTRESOURCE outputs a LPSTR because it is defined in the following way-:

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))

I have not yet found any documentation on how this macro works. The msdn states that MAKEINTRESOURCE is a macro which 'converts an integer value to a resource type compatible with the resource-management functions'. Thank You.

Sreyan
  • 357
  • 2
  • 12
  • These are basic questions but hard to answer without knowing what you know. It does require a book to fully answer, I recommend http://www.amazon.com/Code-Language-Computer-Hardware-Software/dp/0735611319/ref=sr_1_1?ie=UTF8&qid=1340613078&sr=8-1&keywords=petzold+code – Hans Passant Jun 25 '12 at 08:33
  • As for the answer to your second question, see the answers here: http://stackoverflow.com/questions/3610565/why-does-makeintresource-work – Cody Gray - on strike Aug 05 '12 at 12:05

1 Answers1

4

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!

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • I want to know what the MAKEINTRESOURCE does to the integer parameter that I send to it. How does it convert it into a string? And I don't understand what does allocating strings at higher address spaces have anything to do with resource ID's. – Sreyan Jun 25 '12 at 10:03
  • 1
    The integer is just cast to a pointer, and passed instead of the string. The receiving function the looks at the pointer, and casts pointers to low addresses back to resource IDs. This assumes the range of IDs and real pointers don't overlap. – Bo Persson Jun 25 '12 at 10:20
  • @Sreyan: "The return value is the specified value in the low-order word and zero in the high-order word" – Deanna Jun 25 '12 at 12:24
  • @Bo Persson Thank You very much. I had this doubt for a very long time. But can you tell me how the function can understand whether to use the pointer as a string or use the low order bytes as a resource id. I mean how can I detect this through C code??? – Sreyan Jun 25 '12 at 18:34
  • @Sreyan `if (ptr & 0xFFFF0000 == 0) { /* ptr is a resource ID */ } else { /* ptr is a pointer */ }` – Felix Dombek Sep 09 '14 at 15:47
  • @FelixDombek What is 0xFFFF0000 ? What is the advantage of such a comparison why not just use normal string names for resources ? – Sreyan Sep 19 '14 at 16:58
  • 1
    @Sreyan `0x...` is a hexadecimal number in C++. `ptr & 0xFFFF0000 == 0` simply tests if there are NO bits set in the upper 16 bit of `ptr` , which makes it a resource ID. – Felix Dombek Sep 22 '14 at 15:15
  • @FelixDombek But why go through such a complex process ? Why not just use resource ids which are strings ? – Sreyan Sep 23 '14 at 09:11
  • This is not a complex process, this is done in about two clock ticks! It gives the user of the function the opportunity to decide whether they want to use a real string as a dialog box template, OR load the dialog from a resource. Resource IDs aren't strings because IDs are usually just integers (because numbers are much more efficient). – Felix Dombek Sep 24 '14 at 14:43