Click here to Skip to main content
13,353,706 members (55,308 online)
Click here to Skip to main content
Add your own
alternative version


109 bookmarked
Posted 7 Feb 2004

Interoperating with Windows Media Player using P/Invoke and C#

, 7 Feb 2004
Rate this:
Please Sign up or sign in to vote.
An article demonstrating the usage of Platform Invoke Services in Visual C# to interoperate with Windows Media Player.


This article hopes to demonstrate:

  • How to use P/Invoke to call unmanaged code.
  • How to use Spy++ to log Windows messages and get wParam and lParam values.
  • How to implement FindWindow() and SendMessage() in C#.
  • How to Interoperate with Windows Media Player.

Introduction to Win32 APIs

MSDN's definition of the Windows API is:

The Windows API (Application Programming Interface) consists of the functions, messages, data structures, data types, and statements you can use in creating applications that run under Microsoft Windows. The parts of the API you use most are code elements for calling API functions from Windows. These include procedure declarations (for the Windows functions), user-defined type definitions (for data structures passed to those functions), and constant declarations (for values passed to and returned from those functions).

In short, Windows APIs are DLLs that are embedded in the Microsoft Windows operating system. The advantage of using Windows APIs in your code is that development time and complexity may be reduced because they contain hundreds of useful functions already written. The disadvantage is that Windows APIs do not use managed code and have data types that are different from those used with Visual Studio .NET. While the .NET framework has wrapped a significant portion of the Win32 API into managed code, the ones that remain unmanaged and without a .NET equivalent may be called by managed code using the platform invoke service.

Introducing Platform Invocation Services

Platform Invocation Services (P/Invoke) is a mechanism by which managed code calls unmanaged functions that are implemented in a DLL.


When calling an unmanaged function, platform invoke must have the DLL file name and function or ordinal number. The DLLImport attribute is used to specify the DLL location that contains the implementation of an external method and its parameters are used to specify specific behavior such as EntryPoint and CharSet. For more information on the syntax of the DllImport attribute, see DllImportAttribute class at MSDN.

Table 1: Commonly used DLLs in the Win32 API


Description of its contents


Low-level operating system functions for memory management and resource handling.


Graphics Device Interface (GDI) functions for device output, such as those for drawing and font management.


Windows management functions for message handling, timers, menus, and communications.

Steps to call Win32 API using C#

  1. Import the System.Runtime.InteropServices namespace.
  2. Define functions by using DLLImport.
  3. Add code to call the Win32 API.

We are going to implement the FindWindow() and SendMessage() related Win32 API functions found in the User32.dll as illustrated in the Win32 class below.

public class Win32
    // The WM_COMMAND message is sent when the user
    // selects a command item from a menu, 
    // when a control sends a notification message
    // to its parent window, or when an 
    // accelerator keystroke is translated.
    public const int WM_COMMAND = 0x111;

    // The FindWindow function retrieves a handle
    // to the top-level window whose class name
    // and window name match the specified strings.
    // This function does not search child windows.
    // This function does not perform a case-sensitive search.
    public static extern int FindWindow(string strClassName, 
                                             string strWindowName);

    // The FindWindowEx function retrieves
    // a handle to a window whose class name 
    // and window name match the specified strings.
    // The function searches child windows, beginning
    // with the one following the specified child window.
    // This function does not perform a case-sensitive search.
    public static extern int FindWindowEx(int hwndParent, 
        int hwndChildAfter, string strClassName, string strWindowName);

    // The SendMessage function sends the specified message to a 
    // window or windows. It calls the window procedure for the specified 
    // window and does not return until the window procedure
    // has processed the message. 
    public static extern Int32 SendMessage(
        int hWnd,               // handle to destination window
        int Msg,                // message
        int wParam,             // first message parameter
        [MarshalAs(UnmanagedType.LPStr)] string lParam); 
                                // second message parameter

    public static extern Int32 SendMessage(
        int hWnd,               // handle to destination window
        int Msg,                // message
        int wParam,             // first message parameter
        int lParam);            // second message parameter

    public Win32()



Windows Media Player Interoperability Conceptual Art

Sample screenshot


  • Microsoft Visual Studio .NET
  • Microsoft Spy++
  • Windows Media Player
  1. Open Spy++ and press the Log Messages button, or press Ctrl + M.
  2. Open Microsoft Windows Media Player and arrange your windows so that Spy++ and Windows Media Player are both visible.
  3. Make sure Windows Media Player is not using the Auto Hide Menu bar feature and drag the Finder Tool to the outer Windows Media Player Window entitled “Windows Media Player”.

- Or -

If you know the handle of the Windows Media Player window, you may type it into the Handle box.


Next, proceed to the Messages tab and clear all selected messages. In the Messages to View list box, scroll down and select WM_COMMAND and click on OK.

At this point, having only WM_COMMAND selected will make the next step much easier.


Next, choose Play->Stop from the Windows Media Player Main Menu or simply press Ctrl+S for Spy++ to log the WM_COMMAND message:

<00001> 0023017A P WM_COMMAND wNotifyCode:0 (sent from a menu) wID:18809

The Messages view appears as shown below. Note that the first column contains the window handle, and the second column contains a message code. Message parameters and return values are on the right.


Double click on this entry to view additional Message Properties such as the wParam and lParam hex values.


Repeating the above for the Start button yields:

<00001> 0023017A P WM_COMMAND wNotifyCode:0 (sent from a menu) wID:18808

Using P/Invoke and Spy++, it’s easy to extend functionality to include other options such as Eject, Repeat, or Volume control but for demonstration purposes, we shall only implement Start/Pause and Stop.

private System.Int32 iHandle;

private void btnStop_Click(object sender, System.EventArgs e)
    Win32.SendMessage(iHandle, Win32.WM_COMMAND, 0x00004979, 0x00000000);

private void btnPlayPause_Click(object sender, System.EventArgs e)
    Win32.SendMessage(iHandle, Win32.WM_COMMAND, 0x00004978, 0x00000000);

private void MainForm_Load(object sender, System.EventArgs e)
    // get Window handle
    iHandle = Win32.FindWindow("WMPlayerApp", "Windows Media Player"); 


I had fun writing this article even though it’s not an original idea, but hopefully somebody out there will find it useful enough. Originally, I was thinking to dig deep into Windows Media player using FindWindowEx() and start playing with ATL:SysListView32 the “Current Playlist” to manipulate Windows Media Player Playlists on selected remote machines using WMI. If anyone has any other ideas or feature request, just let me know.


  • Version 1.0 - February 08 2004 - Original submission.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Alexander Kent
Kentdome LLC
United States United States
Biography in progress Wink | ;-)

You may also be interested in...


Comments and Discussions

AnswerRe: any way to determine wParam and lParam from menu item name? Pin
Saccomani24-Aug-09 15:28
memberSaccomani24-Aug-09 15:28 
QuestionDetermining WMP Status? Pin
john@datavox.net10-Aug-06 13:56
memberjohn@datavox.net10-Aug-06 13:56 
GeneralSimply WOW! Pin
MANSATAN17-Jul-06 10:22
memberMANSATAN17-Jul-06 10:22 
GeneralSet MDIParent Property Pin
bboyle123425-Apr-06 21:19
memberbboyle123425-Apr-06 21:19 
GeneralRequest.. Pin
CSutherland7-Jan-06 17:02
memberCSutherland7-Jan-06 17:02 
GeneralGood article. Pin
CSutherland7-Jan-06 16:56
memberCSutherland7-Jan-06 16:56 
GeneralRe: Good article. Pin
iKevenaar12-Jul-09 4:49
memberiKevenaar12-Jul-09 4:49 
GeneralOther managed equivalent Pin
Adarsh Shah21-Dec-05 21:26
memberAdarsh Shah21-Dec-05 21:26 
Is there any managed equivalent of:

public extern static int GetWindowRect(IntPtr hWnd, out Rect lpRect);

public static extern int GetClientRect(IntPtr hWnd, out Rect lpRect);

I do not want to use unmanaged code.

Thanks and Regards,
Shah Adarsh.Smile | :)
GeneralThanks and very helpful Pin
AmanBhandari2-Dec-05 2:14
memberAmanBhandari2-Dec-05 2:14 
QuestionHow to control the save file dialog of WMP? Pin
caveman_19781-Nov-05 4:55
membercaveman_19781-Nov-05 4:55 
GeneralAny chance of a hand!! Pin
pokabot15-Jul-05 1:59
memberpokabot15-Jul-05 1:59 
GeneralRe: Any chance of a hand!! Pin
Alexander Kent15-Jul-05 11:06
memberAlexander Kent15-Jul-05 11:06 
GeneralRe: Any chance of a hand!! Pin
pokabot17-Jul-05 13:39
memberpokabot17-Jul-05 13:39 
GeneralRe: Any chance of a hand!! Pin
pokabot17-Jul-05 22:10
memberpokabot17-Jul-05 22:10 
Generaljuke box Pin
AAyub14-Jul-05 9:27
memberAAyub14-Jul-05 9:27 
GeneralRe: juke box Pin
Alexander Kent15-Jul-05 11:08
memberAlexander Kent15-Jul-05 11:08 
GeneralGreat Article Pin
tomcoleman17-Dec-04 10:04
membertomcoleman17-Dec-04 10:04 
Generalusing buttons instead of menu's Pin
Preet Sethi11-Oct-04 11:50
memberPreet Sethi11-Oct-04 11:50 
GeneralRe: using buttons instead of menu's Pin
flandersucf19-Jul-05 9:00
memberflandersucf19-Jul-05 9:00 
GeneralContext Menus... Pin
Jumpin' Jeff14-Sep-04 12:50
memberJumpin' Jeff14-Sep-04 12:50 
General30 Second Skip Ahead Pin
Bill West11-Feb-04 4:16
memberBill West11-Feb-04 4:16 
GeneralA better (documented) way - WM_APPCOMMAND Pin
eran_ru8-Feb-04 23:11
membereran_ru8-Feb-04 23:11 
GeneralRe: A better (documented) way - WM_APPCOMMAND Pin
Maximian2621-May-06 23:13
memberMaximian2621-May-06 23:13 
GeneralThanks Pin
Tom H8-Feb-04 18:44
sussTom H8-Feb-04 18:44 
GeneralRe: Thanks Pin
Michael Draper28-Jul-05 4:45
memberMichael Draper28-Jul-05 4:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 8 Feb 2004
Article Copyright 2004 by Alexander Kent
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid