using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Collections;
using System.Threading;
using System.IO;
using System.Reflection;
using Microsoft.Win32;
namespace abPlayer
{
public struct FlyingTextItem
{
public int line;
public String originalText;
public String flyingText;
};
public partial class frmPlayer
{
// constants used for display positioning
const int DISPLAY_TOP = 40;
const int DISPLAY_GUTTER = 20;
private int RECTANGLED_DISPLAY_HEIGHT = 26;
const int RECTANGLED_DISPLAY_TOP = 5;
// paint resources
Bitmap fgBMP = null;
Graphics fgGraphics = null;
Bitmap bgBMP = null;
Graphics bgGraphics = null;
IntPtr apiDC = IntPtr.Zero;
Graphics screenGraphics = null;
// flying text data
FlyingTextItem[] fti = new FlyingTextItem[7];
int flyingTextCount = 0;
const String FLYING_TEXT_PREFIX = " "; // 6 blanks
const String FLYING_TEXT_SUFFIX = " "; // 8 blanks
const int FLYING_TEXT_WIDTH_THRESHOLD = 24;
// text positioning information
int textHeight;
// tod and power font
Font todFont = null;
const int TOD_FONT_SIZE = 10;
// paint
void PaintScreen()
{
PaintScreen(screenGraphics);
}
void PaintScreen(Graphics dc)
{
// black out the whole paint rectangle
bgGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0,
bgBMP.Width, bgBMP.Height);
if (tmr.Enabled)
{
// draw battery life pecentage and time of day
DrawBatteryVolAndTOD(bgGraphics);
// only if we are playing a playlist...
if (Player.PlaylistCount > 0)
{
DrawMediaTags(bgGraphics);
DrawLocation(bgGraphics);
}
DrawStatus(bgGraphics, Player.StatusString);
}
// commit the whole thing to the screen
dc.DrawImage(bgBMP, 0, pnlTop.Height);
}
// flying text
void PaintFlyingText()
{
for(int i = 0; i< flyingTextCount; i++)
{
fgGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0,
fgBMP.Width, fgBMP.Height);
SizeF strWH = fgGraphics.MeasureString(fti[i].flyingText, this.Font);
if (strWH.Width > Width)
fti[i].flyingText = fti[i].flyingText.Substring(1);
else
fti[i].flyingText = fti[i].originalText;
fgGraphics.DrawString(fti[i].flyingText, this.Font, new SolidBrush(TextColor),
0, 0);
screenGraphics.DrawImage(fgBMP, 0, pnlTop.Height +
DISPLAY_TOP + DISPLAY_GUTTER * fti[i].line,
new Rectangle(0, 0, Width,
textHeight), GraphicsUnit.Pixel);
}
}
// battery volume & tod display
void PaintBatteryVolAndTOD()
{
fgGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0,
fgBMP.Width, fgBMP.Height);
DrawBatteryVolAndTOD(fgGraphics);
screenGraphics.DrawImage(fgBMP, 0, pnlTop.Height + RECTANGLED_DISPLAY_TOP,
new Rectangle(0, RECTANGLED_DISPLAY_TOP, Width,
RECTANGLED_DISPLAY_HEIGHT + 4), GraphicsUnit.Pixel);
}
// show location
void PaintLocation()
{
fgGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0,
fgBMP.Width, fgBMP.Height);
DrawLocation(fgGraphics);
screenGraphics.DrawImage(fgBMP, 0, pnlTop.Height + DISPLAY_TOP + DISPLAY_GUTTER * 6,
new Rectangle(0, DISPLAY_TOP + DISPLAY_GUTTER * 6, Width, textHeight), GraphicsUnit.Pixel);
}
// player status
void PaintStatus(String status)
{
fgGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0,
fgBMP.Width, fgBMP.Height);
DrawStatus(fgGraphics, status);
screenGraphics.DrawImage(fgBMP, 0, pnlTop.Height + DISPLAY_TOP + DISPLAY_GUTTER * 7 + 4,
new Rectangle(0, DISPLAY_TOP + DISPLAY_GUTTER * 7 + 4, Width, RECTANGLED_DISPLAY_HEIGHT + 5), GraphicsUnit.Pixel);
}
// draws battery state & clock
void DrawBatteryVolAndTOD(Graphics dc)
{
// get battery life percentage and establish relevant font color
int batt = GetBatteryLifePercentAndSetTextColor();
// format as string
String str = " " + batt.ToString() + " % ";
SizeF strWH = dc.MeasureString(str, todFont);
int volL = (int)(strWH.Width + 24 + 3);
// draw a rectangle around it
dc.DrawRectangle(new Pen(SystemColors.Control, 2), 1, RECTANGLED_DISPLAY_TOP,
(int)(strWH.Width + 2 + 24), RECTANGLED_DISPLAY_HEIGHT + 2);
// draw the battery life percent
dc.DrawString(str, todFont, new SolidBrush(TextColor),
1 + 24,
(RECTANGLED_DISPLAY_HEIGHT / 2 - strWH.Height / 2) + RECTANGLED_DISPLAY_TOP + 2);
try
{
dc.DrawImage(picBattery.Image,
new Rectangle(1,
RECTANGLED_DISPLAY_TOP + 2,
24, 24),
new Rectangle(0, 0, picBattery.Image.Width, picBattery.Image.Height),
GraphicsUnit.Pixel);
}
catch { }
// format time-of-day to string
str = " " + ((DateTime.Now.TimeOfDay.Hours < 10) ?
"0" + DateTime.Now.TimeOfDay.Hours.ToString() :
DateTime.Now.TimeOfDay.Hours.ToString()) + ":" +
((DateTime.Now.TimeOfDay.Minutes < 10) ?
"0" + DateTime.Now.TimeOfDay.Minutes.ToString() :
DateTime.Now.TimeOfDay.Minutes.ToString()) + " ";
strWH = dc.MeasureString(str, todFont);
int volR = (int)(Width - strWH.Width - 24 - 4);
// draw a rectangle arount time of day
dc.DrawRectangle(new Pen(SystemColors.Control, 2), (int)(Width - strWH.Width - 4 - 24),
RECTANGLED_DISPLAY_TOP, (int)strWH.Width + 2 + 24,
RECTANGLED_DISPLAY_HEIGHT + 2);
// draw time of day
dc.DrawString(str, todFont, new SolidBrush(TextColor),
Width - strWH.Width - 3,
(RECTANGLED_DISPLAY_HEIGHT / 2 - strWH.Height / 2) + RECTANGLED_DISPLAY_TOP + 2);
try
{
dc.DrawImage(picClock.Image,
new Rectangle((int)(Width - strWH.Width - 3 - 24),
RECTANGLED_DISPLAY_TOP + 2,
24, 24),
new Rectangle(0, 0, picClock.Image.Width, picClock.Image.Height),
GraphicsUnit.Pixel);
}
catch { }
// draw volume
str = " " + DeviceSpecifics.Volume.ToString() + " % ";
strWH = dc.MeasureString(str, todFont);
volL = (int)((volR - volL) / 2 - (strWH.Width + 24 + 2) / 2) + volL;
dc.DrawRectangle(new Pen(SystemColors.Control, 2), volL,
RECTANGLED_DISPLAY_TOP, (int)strWH.Width + 2 + 24,
RECTANGLED_DISPLAY_HEIGHT + 2);
dc.DrawString(str, todFont, new SolidBrush(TextColor),
volL +1 + 24,
(RECTANGLED_DISPLAY_HEIGHT / 2 - strWH.Height / 2) + RECTANGLED_DISPLAY_TOP + 2);
try
{
dc.DrawImage(picVol.Image,
new Rectangle(volL + 2,
RECTANGLED_DISPLAY_TOP + 2,
24, 24),
new Rectangle(0, 0, picVol.Image.Width, picVol.Image.Height),
GraphicsUnit.Pixel);
}
catch { }
}
// draw media info
void DrawMediaTags(Graphics dc)
{
try
{
flyingTextCount = 0;
// draw active book name
DrawStringAndTestFlying(dc, Library.BookStore.ActiveBookName, 0);
// draw album tag
DrawStringAndTestFlying(dc, Player.GetMediaTAG(eTagNames.ALBUM), 1);
// draw title tag if present, otherwise draw file name
String str = Player.GetMediaTAG(eTagNames.TITLE);
if (str.Length == 0)
str = Player.PlayingName;
DrawStringAndTestFlying(dc, str, 2);
// draw author tag
DrawStringAndTestFlying(dc, Player.GetMediaTAG(eTagNames.AUTHOR), 3);
// draw comment tag
DrawStringAndTestFlying(dc, Player.GetMediaTAG(eTagNames.COMMENT), 4);
// draw media index in the playlist and playllist media count
DrawStringAndTestFlying(dc, (Player.PlayingIndex + 1).ToString() +
" / " + Player.PlaylistCount.ToString(), 5);
}
catch { }
}
// test for flying text candidates and draw
void DrawStringAndTestFlying(Graphics dc, String str, int line)
{
str = (str.Replace('\n', ' ')).Replace('\r', ' ');
SizeF strWH = dc.MeasureString(str, this.Font);
if ((strWH.Width + FLYING_TEXT_WIDTH_THRESHOLD) > Width)
{
fti[flyingTextCount].line = line;
fti[flyingTextCount].originalText = fti[flyingTextCount].flyingText =
FLYING_TEXT_PREFIX + str + FLYING_TEXT_SUFFIX;
dc.DrawString(fti[flyingTextCount].flyingText,
this.Font, new SolidBrush(TextColor),
0, DISPLAY_TOP + DISPLAY_GUTTER * line);
flyingTextCount++;
}
else
DrawString(dc, str, DISPLAY_TOP + line * DISPLAY_GUTTER, strWH);
}
// the timeline marker and media full duration are called from either
// the paint event or the media location changed event.
void DrawLocation(Graphics dc)
{
try
{
int fileDuration = Player.FileDuration(Player.PlayingIndex);
String str = Player.LocationString + " / " + Player.DurationString +
((fileDuration == -1)? "":
(Math.Abs(fileDuration - Player.Duration) > 1)? " -" : " +");
DrawString(dc, str, DISPLAY_TOP + 6 * DISPLAY_GUTTER,
dc.MeasureString(str, this.Font));
}
catch { }
}
// function also called from several places
void DrawStatus(Graphics dc, String status)
{
SizeF strWH = dc.MeasureString(status, this.Font);
dc.DrawString(status, this.Font, new SolidBrush(TextColor),
this.Width / 2 - strWH.Width / 2,
DISPLAY_TOP + DISPLAY_GUTTER * 7 +
(RECTANGLED_DISPLAY_HEIGHT / 2 - strWH.Height / 2) + 7);
dc.DrawRectangle(new Pen(SystemColors.Control, 2),
(int)(this.Width / 2 - strWH.Width / 2 - 8), DISPLAY_TOP + DISPLAY_GUTTER * 7 + 5,
(int)(strWH.Width + 14), RECTANGLED_DISPLAY_HEIGHT + 2);
}
// this function calculates the size of the display and positions
// it in the horizontal middle
void DrawString(Graphics dc, String str, int h, SizeF strWH)
{
dc.DrawString(str, this.Font, new SolidBrush(TextColor),
this.Width / 2 - strWH.Width / 2, h);
}
}
}