1

I'm trying to write a simple application that skips currently playing track similarly to how media buttons on a keyboard would work.

I have found LParam values for mute (0x80000) but I don't know how to find the values for commands such as next / previous track or how 8 (from article below) maps to 0x80000 so I can work out how map 11 (next track from article below) to a code that works?.

The muting works by using 0x80000 but not when using 8.

Sorry if this is a silly question, I've never done any interop stuff before.

Thanks

https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275%28v=vs.85%29.aspx

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class Form1 : Form
{
    private const int WM_APPCOMMAND = 0x319;

    private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
    private const int APPCOMMAND_VOLUME_MUTE_INT = 8;

    //private const int APPCOMMAND_MEDIA_NEXT_TRACK = ?;
    private const int APPCOMMAND_MEDIA_NEXT_TRACK = 11;

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

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // doesn't work
        //SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
        //    APPCOMMAND_VOLUME_MUTE_INT);

        SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
            APPCOMMAND_VOLUME_MUTE);
    }
}
Ant
  • 336
  • 1
  • 3
  • 14

1 Answers1

2

The arguments to SendMessage() are often packed in unusual ways. A necessary evil because it has just simple argument types and needs to support many different kind of messages. Also designed to be used from C, a language that doesn't support anything like method overloads. WM_APPCOMMAND has this in spades, the lparam is packed to carry 3 values (command, device number, keystate).

Proper code is:

  SendMessage(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)((int)cmd << 16));

Where cmd is the command you want to send. Like APPCOMMAND_VOLUME_MUTE_INT or APPCOMMAND_MEDIA_NEXT_TRACK in your sample code. Also explains where 0x8000 comes from, it is 8 << 16.

Note that your SendMessage() declaration is wrong, the last argument is IntPtr, not int. You'll find a C# wrapper class that can be used in any kind of project in this post.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536