* Support for renaming to *.scr and running as a screensaver
* Made the gradients prettier
* Timer to force to the foreground in an attempt to keep kids out when they press custom keyboard buttons
* Minor bug fixes in rendering from the IssueTracker
This commit is contained in:
shanselman 2008-07-15 20:48:58 +00:00
Родитель c222771312
Коммит 9888717397
5 изменённых файлов: 323 добавлений и 296 удалений

Просмотреть файл

@ -20,66 +20,55 @@ namespace BabySmash
public static Dictionary<string, string> cachedWavs = new Dictionary<string, string>();
public static object cachedWavsLock = new object();
[DllImport("winmm.dll", SetLastError = true)]
static extern bool PlaySound(string pszSound, IntPtr hmod, UInt32 fdwSound);
[DllImport("winmm.dll")]
public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags);
public void PlayWavResource(string wav)
[DllImport("winmm.dll", SetLastError = true)]
static extern bool PlaySound(string pszSound, IntPtr hmod, UInt32 fdwSound);
public void PlayWavResource(string wav)
{
string s = GetWavResource(wav);
PlaySound(s, IntPtr.Zero, SND_ASYNC);
}
public void PlayWavResourceYield(string wav)
{
string s = GetWavResource(wav);
PlaySound(s, IntPtr.Zero, SND_ASYNC | SND_NOSTOP);
}
TempFileCollection tempFiles = new TempFileCollection();
private string GetWavResource(string wav)
{
//TODO: Is this valid double-check caching?
string retVal = null;
if (cachedWavs.ContainsKey(wav))
retVal = cachedWavs[wav];
if (retVal == null)
{
lock (cachedWavsLock)
{
string s = GetWavResource(wav);
PlaySound(s, IntPtr.Zero, SND_ASYNC);
}
// get the namespace
string strNameSpace = Assembly.GetExecutingAssembly().GetName().Name;
public void PlayWavResourceYield(string wav)
{
string s = GetWavResource(wav);
PlaySound(s, IntPtr.Zero, SND_ASYNC | SND_NOSTOP);
}
//public static void PlayWavResource(string wav)
//{
// byte[] b = GetWavResource(wav);
// PlaySound(b, IntPtr.Zero, SND_ASYNC | SND_MEMORY);
//}
//public static void PlayWavResourceYield(string wav)
//{
// byte[] b = GetWavResource(wav);
// PlaySound(b, IntPtr.Zero, SND_ASYNC | SND_MEMORY | SND_NOSTOP);
//}
TempFileCollection tempFiles = new TempFileCollection();
private string GetWavResource(string wav)
{
//TODO: Is this valid double-check caching?
string b = null;
if (cachedWavs.ContainsKey(wav))
b = cachedWavs[wav];
if (b == null)
// get the resource into a stream
using (Stream str = Assembly.GetExecutingAssembly().GetManifestResourceStream(strNameSpace + wav))
{
lock (cachedWavsLock)
{
// get the namespace
string strNameSpace = Assembly.GetExecutingAssembly().GetName().Name;
// get the resource into a stream
using (Stream str = Assembly.GetExecutingAssembly().GetManifestResourceStream(strNameSpace + wav))
{
string tempfile = System.IO.Path.GetTempFileName();
tempFiles.AddFile(tempfile,false);
var bStr = new Byte[str.Length];
str.Read(bStr, 0, (int)str.Length);
File.WriteAllBytes(tempfile, bStr);
cachedWavs.Add(wav, tempfile);
return tempfile;
}
}
string tempfile = System.IO.Path.GetTempFileName();
tempFiles.AddFile(tempfile,false);
var bStr = new Byte[str.Length];
str.Read(bStr, 0, (int)str.Length);
File.WriteAllBytes(tempfile, bStr);
cachedWavs.Add(wav, tempfile);
return tempfile;
}
return b;
}
}
return retVal;
}
//private static byte[] GetWavResource(string wav)
//{

Просмотреть файл

@ -11,269 +11,306 @@ using BabySmash.Properties;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using WinForms = System.Windows.Forms;
using System.Windows.Threading;
using System.Runtime.InteropServices;
using System.Windows.Interop;
namespace BabySmash
{
public class Controller
{
private bool isDrawing = false;
private readonly SpeechSynthesizer objSpeech = new SpeechSynthesizer();
private readonly List<MainWindow> windows = new List<MainWindow>();
private int FiguresCount = 0;
private readonly Win32Audio audio = new Win32Audio();
public class Controller
{
[DllImport("user32.dll")]
private static extern IntPtr SetFocus(IntPtr hWnd);
public void Launch()
{
foreach (WinForms.Screen s in WinForms.Screen.AllScreens)
{
MainWindow m = new MainWindow(this)
{
WindowStartupLocation = WindowStartupLocation.Manual,
Left = s.WorkingArea.Left,
Top = s.WorkingArea.Top,
Width = s.WorkingArea.Width,
Height = s.WorkingArea.Height,
WindowStyle = WindowStyle.None,
Topmost = true
};
m.Show();
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
//TODO: Start - COMMENT IN for Debugging
//m.Width = 700;
//m.Height = 600;
//m.Left = 900;
//m.Top = 500;
//TODO: END - COMMENT IN for Debugging
private bool isOptionsDialogShown = false;
private bool isDrawing = false;
private readonly SpeechSynthesizer objSpeech = new SpeechSynthesizer();
private readonly List<MainWindow> windows = new List<MainWindow>();
private int FiguresCount = 0;
private readonly Win32Audio audio = new Win32Audio();
private DispatcherTimer timer = new DispatcherTimer();
public void Launch()
{
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = new TimeSpan(0, 0, 1);
foreach (WinForms.Screen s in WinForms.Screen.AllScreens)
{
MainWindow m = new MainWindow(this)
{
WindowStartupLocation = WindowStartupLocation.Manual,
Left = s.WorkingArea.Left,
Top = s.WorkingArea.Top,
Width = s.WorkingArea.Width,
Height = s.WorkingArea.Height,
WindowStyle = WindowStyle.None,
Topmost = true
};
m.Show();
//TODO: Start - COMMENT OUT for Debugging
m.WindowState = WindowState.Maximized;
//TODO: Start - COMMENT OUT for Debugging
windows.Add(m);
}
//TODO: Start - COMMENT IN for Debugging
//m.Width = 700;
//m.Height = 600;
//m.Left = 900;
//m.Top = 500;
//TODO: END - COMMENT IN for Debugging
//TODO: Start - COMMENT OUT for Debugging
m.WindowState = WindowState.Maximized;
//TODO: Start - COMMENT OUT for Debugging
windows.Add(m);
}
//if someone made us a screensaver, then don't show the options dialog.
string ext = System.IO.Path.GetExtension(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
if (String.CompareOrdinal(ext, ".SCR") != 0)
{
ShowOptionsDialog();
}
}
timer.Start();
}
public void ProcessKey(FrameworkElement uie, KeyEventArgs e)
{
bool Alt = (Keyboard.Modifiers & ModifierKeys.Alt) != 0;
bool Control = (Keyboard.Modifiers & ModifierKeys.Control) != 0;
bool Shift = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
void timer_Tick(object sender, EventArgs e)
{
if (isOptionsDialogShown) return;
if (uie.IsMouseCaptured)
uie.ReleaseMouseCapture();
try
{
IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
SetForegroundWindow(windowHandle);
SetFocus(windowHandle);
}
catch (Exception)
{
//Wish me luck!
}
}
//TODO: Might be able to remove this: http://www.ageektrapped.com/blog/using-commands-in-babysmash/
if (Alt && Control && Shift && e.Key == Key.O)
public void ProcessKey(FrameworkElement uie, KeyEventArgs e)
{
bool Alt = (Keyboard.Modifiers & ModifierKeys.Alt) != 0;
bool Control = (Keyboard.Modifiers & ModifierKeys.Control) != 0;
bool Shift = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
if (uie.IsMouseCaptured)
uie.ReleaseMouseCapture();
//TODO: Might be able to remove this: http://www.ageektrapped.com/blog/using-commands-in-babysmash/
if (Alt && Control && Shift && e.Key == Key.O)
{
ShowOptionsDialog();
e.Handled = true;
return;
}
if (FiguresCount == Settings.Default.ClearAfter)
ClearAllFigures();
string s = e.Key.ToString();
if (s.Length == 2 && s[0] == 'D') s = s[1].ToString(); //HACK: WTF? Numbers start with a "D?" as in D1?
AddFigure(uie, s);
}
private void ClearAllFigures()
{
foreach (MainWindow m in this.windows)
{
m.mainCanvas.Children.Clear();
}
}
private void AddFigure(FrameworkElement uie, string s)
{
FigureTemplate template = FigureGenerator.GenerateFigureTemplate(s);
foreach (MainWindow m in this.windows)
{
UserControl f = FigureGenerator.NewUserControlFrom(template);
m.AddUserControl(f);
f.Width = 300;
f.Height = 300;
Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualWidth - f.Width)));
Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualHeight - f.Height)));
Storyboard storyboard = Animation.CreateDPAnimation(uie, f,
UIElement.OpacityProperty,
new Duration(TimeSpan.FromSeconds(Settings.Default.FadeAfter)));
if (Settings.Default.FadeAway) storyboard.Begin(uie);
IHasFace face = f as IHasFace;
if (face != null)
{
ShowOptionsDialog();
e.Handled = true;
return;
face.FaceVisible = Settings.Default.FacesOnShapes ? Visibility.Visible : Visibility.Hidden;
}
f.MouseLeftButtonDown += HandleMouseLeftButtonDown;
f.MouseEnter += f_MouseEnter;
f.MouseWheel += f_MouseWheel;
}
FiguresCount++;
PlaySound(template);
}
if (FiguresCount == Settings.Default.ClearAfter)
ClearAllFigures();
string s = e.Key.ToString();
if (s.Length == 2 && s[0] == 'D') s = s[1].ToString(); //HACK: WTF? Numbers start with a "D?" as in D1?
AddFigure(uie, s);
}
private void ClearAllFigures()
{
foreach (MainWindow m in this.windows)
void f_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (lastEnteredUserControl != null)
{
if (e.Delta < 0)
{
m.mainCanvas.Children.Clear();
}
}
private void AddFigure(FrameworkElement uie, string s)
{
FigureTemplate template = FigureGenerator.GenerateFigureTemplate(s);
foreach (MainWindow m in this.windows)
{
UserControl f = FigureGenerator.NewUserControlFrom(template);
m.AddUserControl(f);
f.Width = 300;
f.Height = 300;
Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualWidth - f.Width)));
Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualHeight - f.Height)));
Storyboard storyboard = Animation.CreateDPAnimation(uie, f,
UIElement.OpacityProperty,
new Duration(TimeSpan.FromSeconds(Settings.Default.FadeAfter)));
if (Settings.Default.FadeAway) storyboard.Begin(uie);
IHasFace face = f as IHasFace;
if (face != null)
{
face.FaceVisible = Settings.Default.FacesOnShapes ? Visibility.Visible : Visibility.Hidden;
}
f.MouseLeftButtonDown += HandleMouseLeftButtonDown;
f.MouseEnter += f_MouseEnter;
f.MouseWheel += f_MouseWheel;
}
FiguresCount++;
PlaySound(template);
}
void f_MouseWheel(object sender, MouseWheelEventArgs e)
{
if(lastEnteredUserControl != null)
{
if (e.Delta < 0)
{
Animation.ApplyZoom(lastEnteredUserControl, new Duration(TimeSpan.FromSeconds(0.5)), 2.5);
}
else
{
Animation.ApplyZoom(lastEnteredUserControl, new Duration(TimeSpan.FromSeconds(0.5)), 0.5);
}
}
}
private UserControl lastEnteredUserControl;
void f_MouseEnter(object sender, MouseEventArgs e)
{
lastEnteredUserControl = sender as UserControl;
}
void HandleMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UserControl f = sender as UserControl;
if (f != null && f.Opacity > 0.1) //can it be seen?
{
isDrawing = true; //HACK: This is a cheat to stop the mouse draw action.
Animation.ApplyRandomAnimationEffect(f, Duration.Automatic);
PlayLaughter(); //Might be better to re-speak the name, color, etc.
}
}
public void PlaySound(FigureTemplate template)
{
if (Settings.Default.Sounds == "Laughter")
{
PlayLaughter();
}
if (objSpeech != null && Settings.Default.Sounds == "Speech")
{
if (template.Letter != null && template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0]))
{
SpeakString(template.Letter);
}
else
{
SpeakString(Utils.ColorToString(template.Color) + " " + template.Name);
}
}
}
private void PlayLaughter()
{
audio.PlayWavResource(Utils.GetRandomSoundFile());
}
private void SpeakString(string s)
{
objSpeech.SpeakAsyncCancelAll();
objSpeech.Rate = -1;
objSpeech.Volume = 100;
objSpeech.SpeakAsync(s);
}
private void ShowOptionsDialog()
{
var o = new Options();
Mouse.Capture(null);
foreach (MainWindow m in this.windows)
{
m.Topmost = false;
}
o.Topmost = true;
o.Focus();
o.ShowDialog();
Debug.Write("test");
foreach (MainWindow m in this.windows)
{
m.Topmost = true;
}
}
public void MouseDown(MainWindow main, MouseButtonEventArgs e)
{
if (isDrawing || Settings.Default.MouseDraw) return;
// Create a new Ellipse object and add it to canvas.
Point ptCenter = e.GetPosition(main.mainCanvas);
MouseDraw(main, ptCenter);
isDrawing = true;
main.CaptureMouse();
audio.PlayWavResource(".Resources.Sounds." + "smallbumblebee.wav");
}
public void MouseWheel(MainWindow main, MouseWheelEventArgs e)
{
if (e.Delta > 0)
{
audio.PlayWavResourceYield(".Resources.Sounds." + "rising.wav");
Animation.ApplyZoom(lastEnteredUserControl, new Duration(TimeSpan.FromSeconds(0.5)), 2.5);
}
else
{
audio.PlayWavResourceYield(".Resources.Sounds." + "falling.wav");
Animation.ApplyZoom(lastEnteredUserControl, new Duration(TimeSpan.FromSeconds(0.5)), 0.5);
}
}
}
}
public void MouseUp(MainWindow main, MouseButtonEventArgs e)
{
isDrawing = false;
if (Settings.Default.MouseDraw) return;
private UserControl lastEnteredUserControl;
void f_MouseEnter(object sender, MouseEventArgs e)
{
lastEnteredUserControl = sender as UserControl;
}
void HandleMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UserControl f = sender as UserControl;
if (f != null && f.Opacity > 0.1) //can it be seen?
{
isDrawing = true; //HACK: This is a cheat to stop the mouse draw action.
Animation.ApplyRandomAnimationEffect(f, Duration.Automatic);
PlayLaughter(); //Might be better to re-speak the name, color, etc.
}
}
public void PlaySound(FigureTemplate template)
{
if (Settings.Default.Sounds == "Laughter")
{
PlayLaughter();
}
if (objSpeech != null && Settings.Default.Sounds == "Speech")
{
if (template.Letter != null && template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0]))
{
SpeakString(template.Letter);
}
else
{
SpeakString(Utils.ColorToString(template.Color) + " " + template.Name);
}
}
}
private void PlayLaughter()
{
audio.PlayWavResource(Utils.GetRandomSoundFile());
}
private void SpeakString(string s)
{
objSpeech.SpeakAsyncCancelAll();
objSpeech.Rate = -1;
objSpeech.Volume = 100;
objSpeech.SpeakAsync(s);
}
private void ShowOptionsDialog()
{
isOptionsDialogShown = true;
var o = new Options();
Mouse.Capture(null);
foreach (MainWindow m in this.windows)
{
m.Topmost = false;
}
o.Topmost = true;
o.Focus();
o.ShowDialog();
Debug.Write("test");
foreach (MainWindow m in this.windows)
{
m.Topmost = true;
}
isOptionsDialogShown = false;
}
public void MouseDown(MainWindow main, MouseButtonEventArgs e)
{
if (isDrawing || Settings.Default.MouseDraw) return;
// Create a new Ellipse object and add it to canvas.
Point ptCenter = e.GetPosition(main.mainCanvas);
MouseDraw(main, ptCenter);
isDrawing = true;
main.CaptureMouse();
audio.PlayWavResource(".Resources.Sounds." + "smallbumblebee.wav");
}
public void MouseWheel(MainWindow main, MouseWheelEventArgs e)
{
if (e.Delta > 0)
{
audio.PlayWavResourceYield(".Resources.Sounds." + "rising.wav");
}
else
{
audio.PlayWavResourceYield(".Resources.Sounds." + "falling.wav");
}
}
public void MouseUp(MainWindow main, MouseButtonEventArgs e)
{
isDrawing = false;
if (Settings.Default.MouseDraw) return;
main.ReleaseMouseCapture();
}
public void MouseMove(MainWindow main, MouseEventArgs e)
{
if (Settings.Default.MouseDraw && main.IsMouseCaptured == false)
main.CaptureMouse();
if (isDrawing || Settings.Default.MouseDraw)
{
MouseDraw(main, e.GetPosition(main));
}
//Cheesy, but hotkeys are ignored when the mouse is captured.
// However, if we don't capture and release, the shapes will draw forever.
if (Settings.Default.MouseDraw && main.IsMouseCaptured)
main.ReleaseMouseCapture();
}
}
public void MouseMove(MainWindow main, MouseEventArgs e)
{
if (Settings.Default.MouseDraw && main.IsMouseCaptured == false)
main.CaptureMouse();
private void MouseDraw(MainWindow main, Point p)
{
//sanity check
if (main.mainCanvas.Children.Count > 300) main.mainCanvas.Children.Clear();
if (isDrawing || Settings.Default.MouseDraw)
{
MouseDraw(main, e.GetPosition(main));
}
//randomize at some point?
Shape shape = new Ellipse
{
Stroke = SystemColors.WindowTextBrush,
StrokeThickness = 0,
Fill = Utils.GetGradientBrush(Utils.GetRandomColor()),
Width = 50,
Height = 50
};
main.mainCanvas.Children.Add(shape);
Canvas.SetLeft(shape, p.X - 25);
Canvas.SetTop(shape, p.Y - 25);
//Cheesy, but hotkeys are ignored when the mouse is captured.
// However, if we don't capture and release, the shapes will draw forever.
if (Settings.Default.MouseDraw && main.IsMouseCaptured)
main.ReleaseMouseCapture();
}
if (Settings.Default.MouseDraw)
audio.PlayWavResourceYield(".Resources.Sounds." + "smallbumblebee.wav");
}
private void MouseDraw(MainWindow main, Point p)
{
//sanity check
if (main.mainCanvas.Children.Count > 300) main.mainCanvas.Children.Clear();
//randomize at some point?
Shape shape = new Ellipse
{
Stroke = SystemColors.WindowTextBrush,
StrokeThickness = 3,
Fill = Utils.GetGradientBrush(Utils.GetRandomColor()),
Width = 50,
Height = 50
};
main.mainCanvas.Children.Add(shape);
Canvas.SetLeft(shape, p.X - 25);
Canvas.SetTop(shape, p.Y - 25);
if (Settings.Default.MouseDraw)
audio.PlayWavResourceYield(".Resources.Sounds." + "smallbumblebee.wav");
}
public void LostMouseCapture(MainWindow main, MouseEventArgs e)
{
if (Settings.Default.MouseDraw) return;
if (isDrawing) isDrawing = false;
}
}
public void LostMouseCapture(MainWindow main, MouseEventArgs e)
{
if (Settings.Default.MouseDraw) return;
if (isDrawing) isDrawing = false;
}
}
}

Просмотреть файл

@ -9,7 +9,7 @@
d:DesignWidth="6.666" d:DesignHeight="10">
<Grid x:Name="LayoutRoot">
<Canvas x:Name="Letter" Height="400" Width="400">
<Canvas x:Name="Letter" >
<Path x:Name="letterPath" StrokeThickness="10" Stroke="#ff000000" >
<Path.Fill>
<RadialGradientBrush MappingMode="Absolute" GradientOrigin="123,198" Center="123,198" RadiusX="102" RadiusY="102">

Просмотреть файл

@ -32,7 +32,8 @@ namespace BabySmash
this.letterPath.Fill = x;
this.letterPath.Data = MakeCharacterGeometry(GetLetterCharacter(letter));
this.Height = 400;
this.Width = this.letterPath.Data.Bounds.Width + this.letterPath.Data.Bounds.X + this.letterPath.StrokeThickness / 2;
this.Height = this.letterPath.Data.Bounds.Height + this.letterPath.Data.Bounds.Y + this.letterPath.StrokeThickness / 2;
}
private static Geometry MakeCharacterGeometry(string t)

Просмотреть файл

@ -52,9 +52,9 @@ namespace BabySmash
{
RadialGradientBrush myBrush = new RadialGradientBrush();
myBrush.GradientOrigin = new Point(0.75, 0.25);
myBrush.GradientStops.Add(new GradientStop(color.LightenOrDarken(-50), 0.0));
myBrush.GradientStops.Add(new GradientStop(color.LightenOrDarken(50), 0.0));
myBrush.GradientStops.Add(new GradientStop(color, 0.5));
myBrush.GradientStops.Add(new GradientStop(color.LightenOrDarken(50), 1.0));
myBrush.GradientStops.Add(new GradientStop(color.LightenOrDarken(-50), 1.0));
return myBrush;
}