7

I was searching right here on StackOverflow and found the answer to Mute Volume in C#. I don't understand what's going on with the answer. I've never gotten deep into Marshaling or P/Invoke. I've used them before but never understood what I was doing.

So here's what I'm confused about:

private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int WM_APPCOMMAND = 0x319;
  • When declaring these, does it matter what they are named, or are they just treated like any integer regardless of what they're called?

  • Where do the values 0x80000 and 0x319 come from?

Community
  • 1
  • 1
Frank
  • 185
  • 13
  • The constant names do not matter, but it is a good idea to keep the names as they are standard. Using other names could be confusing to anyone who is familiar with the API. The values are basically magic numbers that are defined by the API that is being called using PInvoke. – phoog Jun 04 '14 at 20:43
  • WinAPI is full of magic numbers, you are getting those numbers from MSDN. Why magic numbers? Because Microsoft employees are magicians. – Bura Chuhadar Jun 04 '14 at 20:49

4 Answers4

4

These values are defined in Winuser.h, which is included in the more common Windows.h.

The Winuser constants for WM_APPCOMMAND are documented on this MSDN page.

How you name these variables in your code, as with any variable, is technically up to you. However, it is common practice to keep naming consistent with that used by the library you are invoking (in this case Winuser.h). I see no reason to name them anything else.

Dan Bechard
  • 5,104
  • 3
  • 34
  • 51
  • Thank you for the documentation, so just for example if I wanted to paste something and the command code was 38 for that. Would I go about that like: `private const int APPCOMMAND_PASTE = 0x38000;` `SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_PASTE);` Assuming you have already imported the user32.dll and declared SendMessage of course. – Frank Jun 04 '14 at 21:17
  • @Frank Close. As kobigurk pointed out the values are LPARAM and need to be placed in the high order bits, so you should define it as `APPCOMMAND_PASTE = 0x380000;` (pad right side with *four* zeros). The full 8-bit value is actually `0x00380000` (mute is `0x00080000`), we just leave off the leading zeros the same way you write `int a = 1;` instead of `int a = 00000001;`. – Dan Bechard Jun 05 '14 at 05:25
2

The names are for convenience, but are taken from the WinAPI documentation / header files. Many of these constants have a mnemonic prefix as a hint of where they are used, e.g. WM_ => Windows Message, SPI_ => SystemParametersInfo, etc.

It's probably a good idea not to change them, if only so that you can look them up in the documentation if necessary.

In addition to the Microsoft documentation, pinvoke.net is a community-maintained wiki that documents the WinAPI. You can look up the constant values there if needed. Ultimately, they are what they are because that's how they're defined in the WinAPI.

pmcoltrane
  • 3,052
  • 1
  • 24
  • 30
1

The naming convention doesn't matter and it's just containing a int value. It's commonly used to use these names but you can use any name.

The values are used by SendMessage e.q.

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_MUTE);

SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_UP);

http://www.blackwasp.co.uk/BasicVolumeControl.aspx

Martijn van Put
  • 3,293
  • 18
  • 17
0

The names don't matter, it's as you expect - those are values that are ints, and they are taken from MSDN.

Keep in mind that the values there are LPARAM, which means they're the high order bits. WPARAM will be the low order bits. Both are 32 bits (4 bytes), and in this case they are zero - that's why "0x8" becomes "0x80000".

Community
  • 1
  • 1
kobigurk
  • 731
  • 5
  • 14