Skip to content

Commit cb9a8ec

Browse files
committed
Added support for "Banner" notification, an always-on-top banner which stands above any directdraw/opengl windows.
1 parent b9e51a9 commit cb9a8ec

13 files changed

+620
-7
lines changed
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/********************************************************************
2+
* Copyright (C) 2015-2017 Antoine Aflalo
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 2
7+
* of the License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
********************************************************************/
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using System.Text;
19+
using System.Threading.Tasks;
20+
21+
namespace SoundSwitch.Framework.Banner
22+
{
23+
/// <summary>
24+
/// Contains configuration data for the banner form.
25+
/// </summary>
26+
public class BannerData
27+
{
28+
/// <summary>
29+
/// Gets/sets the title of the banner
30+
/// </summary>
31+
public string Title { get; internal set; }
32+
33+
/// <summary>
34+
/// Gets/sets the text of the banner
35+
/// </summary>
36+
public string Text { get; internal set; }
37+
38+
/// <summary>
39+
/// Gets/sets the path for an image, this is optional.
40+
/// </summary>
41+
public string ImagePath { get; internal set; }
42+
43+
/// <summary>
44+
/// Gets/sets the path for a wav sound to be playedc during the notification, this is optional.
45+
/// </summary>
46+
public string SoundFilePath { get; internal set; }
47+
}
48+
}

SoundSwitch/Framework/Banner/BannerForm.Designer.cs

+125
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/********************************************************************
2+
* Copyright (C) 2015-2017 Antoine Aflalo
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 2
7+
* of the License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
********************************************************************/
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.ComponentModel;
18+
using System.Linq;
19+
using System.Text;
20+
using System.Drawing;
21+
using System.Threading.Tasks;
22+
using System.Windows.Forms;
23+
24+
namespace SoundSwitch.Framework.Banner
25+
{
26+
/// <summary>
27+
/// This class implements the UI form used to show a Banner notification.
28+
/// </summary>
29+
public partial class BannerForm : Form
30+
{
31+
private Timer timerHide;
32+
private bool hiding;
33+
private System.Media.SoundPlayer player;
34+
35+
/// <summary>
36+
/// Constructor for the <see cref="BannerForm"/> class
37+
/// </summary>
38+
public BannerForm()
39+
{
40+
InitializeComponent();
41+
42+
this.Location = new Point(50, 60);
43+
}
44+
45+
protected override bool ShowWithoutActivation => true;
46+
47+
/// <summary>
48+
/// Override the parameters used to create the window handle.
49+
/// Ensure that the window will be top-most and do not activate or take focus.
50+
/// </summary>
51+
protected override CreateParams CreateParams
52+
{
53+
get
54+
{
55+
CreateParams p = base.CreateParams;
56+
p.ExStyle |= 0x08000000; // WS_EX_NOACTIVATE
57+
p.ExStyle |= 0x00000008; // WS_EX_TOPMOST
58+
return p;
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Called internally to configure pass notification parameters
64+
/// </summary>
65+
/// <param name="data">The configuration data to setup the notification UI</param>
66+
internal void SetData(BannerData data)
67+
{
68+
if (this.timerHide == null)
69+
{
70+
this.timerHide = new Timer();
71+
this.timerHide.Interval = 3000;
72+
this.timerHide.Tick += TimerHide_Tick;
73+
}
74+
else
75+
{
76+
this.timerHide.Enabled = false;
77+
}
78+
79+
if (!string.IsNullOrEmpty(data.ImagePath) && System.IO.File.Exists(data.ImagePath))
80+
this.pbxLogo.ImageLocation = data.ImagePath;
81+
82+
DestroySound();
83+
84+
if (!string.IsNullOrEmpty(data.SoundFilePath))
85+
{
86+
this.player = new System.Media.SoundPlayer();
87+
player.SoundLocation = data.SoundFilePath;
88+
player.Play();
89+
}
90+
91+
this.hiding = false;
92+
this.Opacity = .8;
93+
this.lblTop.Text = data.Title;
94+
this.lblTitle.Text = data.Text;
95+
this.timerHide.Enabled = true;
96+
97+
this.Show();
98+
}
99+
100+
/// <summary>
101+
/// Destroy current sound player (if any)
102+
/// </summary>
103+
private void DestroySound()
104+
{
105+
if (this.player != null)
106+
{
107+
this.player.Dispose();
108+
this.player = null;
109+
}
110+
}
111+
112+
/// <summary>
113+
/// Event handler for the "hiding" timer.
114+
/// </summary>
115+
/// <param name="sender">The sender of the event</param>
116+
/// <param name="e">Arguments of the event</param>
117+
private void TimerHide_Tick(object sender, EventArgs e)
118+
{
119+
this.hiding = true;
120+
this.timerHide.Enabled = false;
121+
DestroySound();
122+
FadeOut();
123+
}
124+
125+
/// <summary>
126+
/// Implements an "fadeout" animation while hiding the window.
127+
/// In the end of the animation the form is self disposed.
128+
/// <remarks>The animation is canceled if the method <see cref="SetData"/> is called along the animation.</remarks>
129+
/// </summary>
130+
private async void FadeOut()
131+
{
132+
while (this.Opacity > 0.0)
133+
{
134+
await Task.Delay(50);
135+
136+
if (!this.hiding)
137+
break;
138+
this.Opacity -= 0.05;
139+
}
140+
141+
if (this.hiding)
142+
{
143+
this.Dispose();
144+
}
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)