I'm translating some WinAPI structs so I can make use of the Raw Input API exposed by user32.dll. Most of them are straight forward but a few have unions. I've never attempted to translate structs to records before and I'm just need some confirmation.

I'm translating some WinAPI structs so I can make use of the Raw Input API exposed by user32.dll. Most of them are straight forward but a few have unions. I've never attempted to translate structs to records before and I'm just need some confirmation.

I have the following two structs:

typedef struct tagRAWMOUSE {
  USHORT usFlags;
  union {
    ULONG  ulButtons;
    struct {
      USHORT usButtonFlags;
      USHORT usButtonData;
    };
  };
  ULONG  ulRawButtons;
  LONG   lLastX;
  LONG   lLastY;
  ULONG  ulExtraInformation;
} RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;

typedef struct tagRAWINPUT {
  RAWINPUTHEADER header;
  union {
    RAWMOUSE    mouse;
    RAWKEYBOARD keyboard;
    RAWHID      hid;
  } data;
} RAWINPUT, *PRAWINPUT, *LPRAWINPUT;

And here are my attempts to translate:

type
  RAWMOUSE = record
    usFlags: USHORT;
    case Boolean of
    False: (ulButtons: ULONG);
    True: (usButtonFlags: USHORT;
           usButtonData: USHORT;
           ulRawButtons: ULONG;
           lLastX: LongInt;
           lLastY: LongInt;
           ulExtraInformation: ULONG);
  end;
  PRAWMOUSE = ^RAWMOUSE;
  LPRAWMOUSE = PRAWMOUSE;

type
  RAWINPUT = record
    header: RAWINPUTHEADER;
    case Integer of
    0: (mouse: RAWMOUSE);
    1: (keyboard: RAWKEYBOARD);
    2: (hid: RAWHID);
  end;
PRAWINPUT = ^RAWINPUT;
LPRAWINPUT = PRAWINPUT;

How close to the mark did I get?

Comments

  1. The RAWMOUSE record has a wrong closing bracket. It must be placed after the ulButtonData:USHORT declaration.

    ReplyDelete
  2. That was intentional. See http://rvelthuis.de/articles/articles-convert.html on translating structs with unions in the middle. If I understood it correctly the offsets for ulRawButtons et al should be the same.

    ReplyDelete
  3. Go Delphi-Jedi and download from svn last release of jwa (Jedi windows api) project, chances are it is already there

    ReplyDelete
  4. Yes, it is in JwaWinUser.pas. And it is declared like this (comments stripped):

    type
      tagRAWMOUSE = record
        usFlags: USHORT;
        union: record
        case Integer of
          0: (
            ulButtons: ULONG);
          1: (
            usButtonFlags: USHORT;
            usButtonData: USHORT);
        end;
        ulRawButtons: ULONG;
        //
        lLastX: LONG;
        lLastY: LONG;
        ulExtraInformation: ULONG;
      end;
      
    So the trick was to translate the anonymous C++ union to a named sub-record "union". Which has a little drawback when accessing the variables inside.

    ReplyDelete
  5. Ah, I see. I had looked at jedi wapi already but was looking in the wrong place. I'll give it another look.

    ReplyDelete
  6. In Pascal, that's called a variant record.

    ReplyDelete

Post a Comment