It's a Media Player that works with transparency effects. It also plays MP3 and wav files, displays the tags if present and displays the album art image if present.
Original Media Player user interface is impossible to control using your finger. Here I have tried to solve this problem.
As a sample, I used an interface just like the iPod touch one. In this tutorial, mostly I continue to explain a better way to work with transparency on Windows Mobile. For an introduction to this article, I suggest you read my previous article on transparency iPhone UI[^].
In this article, you can also read about:
- Resolution-aware and Orientation-aware
- Dynamic graphic text resize
- Mouse gesture
- Intercepting button
- Work with Windows Media Player OCX on Windows Mobile
I found some problem with sound files in particular for retrieving the tag info and the current position time, after a long search, I chose to use the Windows Media Player OCX. The article Audio Book Player [^] by brochpirate gives you a fast way to use the OCX on Mobile through the OpenNETCF.org, it's a great working sample. Here, I explain a bit about how you can play with it.
How to Work with WMP
To use the Windows Media Player, you only need to import this DLL as reference:
And add the
cPlayer to your app. Now you are ready to get control of WMP, really cool, isn't it?
Using the Code
Going deep into the solution, you can find:
iPlayer class, the main form with: Resolution-aware, dynamic graphic text resize, mouse gesture, and work also with Windows Media Player COM
cPlayer class, this class works with Media Player OCX, it's under the
abPlayer. I add only few properties - the loop and the volume
FilesManger class, this class gets all the MP3 and Wav files of your mobile device
ImageButtons class, a class button with transparency and other stuff
PlatformAPIs class, it is the class to manage the P/Invoke
SlideButton class, the class that moves the Image (progress)
- BMPs folder, it contains all the BMPs used in the code
This is the main form of the app. I paint all the forms in the method
myPaint(Graphics dc). The
myPaint can be called from the
Paint eventhandler and use the
e.Graphics or can be called when a state changes and the
dc used is the
CreateGraphics(). Then my paint draws all the screen with all the controls inside, beginning with the background, the
LocationBar (if needed),
BottomBar, and the various buttons used.
bitmapBackImage Bitmap is loaded as a background and the default image of the first image found in the song directory. To choose the image, I preferred to display the "Folder.jpg" if it exists because it is the default used by the default internet CD searching.
This is the code:
private void SearchBGImage()
if (FormListScanFiles.lvwSoundFiles.Items.Count != 0)
string path = Player.PlayingPath.Remove(Player.PlayingPath.LastIndexOf(@"\"),
Player.PlayingPath.Length - Player.PlayingPath.LastIndexOf(@"\"));
String ImageFiles = GetImageFiles(path);
if (ImageFiles.Length != 0)
foreach (string ImageFile in ImageFiles)
if (ImageFile.Remove(0, ImageFile.LastIndexOf(@"\") + 1).ToLower() ==
bitmapBackImage = new Bitmap(ImageFile);
bitmapBackImage = new Bitmap(ImageFiles);
bitmapBackImage = bitmapBackImageDefault;
The default image:
If I need to stretch the image, I use this code:
Rectangle srcRect = new Rectangle(0, 0, bitmapBackImage.Width, bitmapBackImage.Height);
Rectangle destRect = new Rectangle(0, 0, this.Width, this.Height);
gxBuffer.DrawImage(bitmapBackImage, destRect, srcRect, GraphicsUnit.Pixel);
else I draw centre & unscaled:
int x = (this.Width - this.bitmapBackImage.Width) / 2;
int y = (this.Height - this.bitmapBackImage.Height) / 2;
gxBuffer.DrawImage(this.bitmapBackImage, x, y);
This part is similar to the iPhone UI article but here I change the position of the images dynamically. The
Topbar is divided in 4 images and the time text:
- The Battery level, with a left anchor with no stretch
- The timeline, with left anchor (the battery level width), right anchor (the GSM level width +
- Current Player status width), use the stretch
- Current Player status, with left anchor (timeline width+ battery level width), right anchor (the battery level width) no stretch
- The GSM level, with a right anchor with no stretch
- The time is drowned in the middle of the screen width and in the middle centred in the middle of the timeline (timeline height/2- text height/2)
All the images:
- Battery Level Bitmaps
- GSM Level Bitmaps
- Top Player status
and these two samples of the view:
The SongBar with text resize
This part is a stretch of a single bitmap to all the width of the screen and with a fixed height.
This is the original bitmap:
And these are two stretch samples:
Over it, I put two
ImageButtons, one for Exit and one for the files list. The buttons are centred in the middle of the
SongTopBar bitmap height, and the exit has the left anchor, the right has the right anchor.
In the middle of the screen, I put the Artist name, the song name and the album name. The strings are the tags retrieved from the current file selected.
Here I use my
DynamicGraphicTextResizing for a "Dynamic graphic text resize". If the width of the displayed string is much greater than the display width, I modify the
string with the minimum size that fits the screen weight and I add to the end "..."
private void DynamicGraphicTextResizing(ref string text,
ref SizeF size, Font songTitleFont)
while (size.Width > this.Width - buttonExit.Image.Width - buttonList.Image.Width)
text = text.Remove(text.Length - 4, 4);
text = text + "...";
size = gxBuffer.MeasureString(text, songTitleFont);
To draw the
string, I use this code:
string title = Player.GetMediaTAG(eTagNames.TITLE);
SizeF sizeTitle = gxBuffer.MeasureString(title, FontsongTitle);
DynamicGraphicTextResizing(ref title, ref sizeTitle, FontsongTitle);
xSong = this.Width / 2 - (int)sizeTitle.Width / 2 + buttonExit.Image.Width / 2;
gxBuffer.DrawString(title, FontSong, BrushWhite, xSong,
bitmapTopHeader.Height + sizeTitle.Height - 2);
Info: brochpirate in his article adds a way to scroll the text. Take a look there, I think you can find it useful.
These are all the images used:
This is a sample on how it works:
Info: This part is shown only if the users click on the
SongBar, it displays the current location, the song duration, and a progress bar for the current location.
To show the Location bar, I use an internal bool value
ShowTimeLine and I decide to draw it if you click over the
SongBar. When the
LocationBar is shown, it enables a timer every second to draw the current location and to draw the step for the progress.
private bool SongMouseUp(MouseEventArgs e)
if (ClientAreaSong().Contains(e.X, e.Y))
ShowTimeLine = !ShowTimeLine;
timerDrawLocation.Enabled = SetTimerDrawLocation();
LocationBar is divided in 8 parts.
- Repeat button with 2 states, pressed On, Off
- Current Location time + the background
- Progress of the song is divided in 2 parts, the played and not played
- Duration time + the background
- Shuffle button with 2 states, pressed On, Off
Note: Here I've not covered everything in the algorithm but I believe that you will understand these easily.
The Repeat button is set to the WMP repeat state. The anchor is left and it's not stretched.
The current location time and the duration time are string retrieved from the player
Player.DurationString. The Background image is this:
The progress is divided in 2 parts, the played and not played, I use two images and I calculate the location position on the screen
iWidthProgressPlayed. After I draw the
PlayedProgress from a fixed start to the
iWidthProgressPlayed and the
iWidthProgressPlayed with a dynamic width (all the size possible less than played)
iWidthTotal - iWidthProgressPlayed.
The Shuffle button is set to the WMP repeat state.
All the images used:
These are 3 samples on how it works:
Attention: I tried the app under a few devices and sometimes I found it slow, I suggest you to use the
LocationBar only if needed. The program starts with the
Middle of the screen
If the search doesn't find a file (MP3 or wav), it displays a text in the middle of the screen "No files found".
This is the code:
private void DrawSongNumber(Graphics gx)
if (FormListScanFiles.lvwSoundFiles.Items.Count == 0)
NoFilesFound = "No files found";
SizeF sizeNoFilesFound =
int xSong = this.Width / 2 - (int)sizeNoFilesFound.Width / 2;
int ySong = this.Height / 2 - (int)sizeNoFilesFound.Height / 2;
int widthMessage = (int)sizeNoFilesFound.Width ;
int xMessage = (this.Width / 2 - (int)widthMessage / 2 )-10;
int yMessage = this.Height / 2 - (int)bitmapMessage.Height / 2;
170, xMessage, yMessage, widthMessage);
FontSongNoFilesFound, BrushWhite, xSong, ySong);
and this is a sample:
The Bottom bar
For the bottom, I used a large background with the left anchor and the right anchor.
The bitmap is divided in two sections (the first half and the second half).
In the first half, I put the Player controls: Previous, Play/Pause, Next. These images are stored in three
ImageButtons. Also the player status is over in the Topbar.
The second half contains the volume slide, it's a
SlideButton. Here I add a modification on the previous posted in the iPhone UI. I add possibility to interact with the progress, and set it with a percentage. When the mouse is moved over the Slide button, the volume changes and it displays the percentage is similar to the used in the location bar.
These are all the images used:
These are two samples:
Points of Interest
I would like to remind that this program is not a complete interface. This article adds some features used in the iPhone UI and I hope you find them useful.
Note: I believe that the article contains some translation errors, please humour me and go ahead reading the article. Soon I'll translate it better.
- Audio Book Player here[^], many thanks for your help BrochPirate.
- The Hosting ActiveX Controls in the .NET Compact Framework 2.0 here[^]
- The introduction of this article iPhone UI[^]
- 7 Jan 2009 - First release
- 10 Jan 2009 - Second release
- Minor bug fixes
- Hidden the
LocationBar at the start
- Added the