YeahTrivia: Creating a Trivia Server/Client with WPF and WCF

![]() |
In this application, Brian Peek demonstrates how to create two spooky Halloween applications to trick your friends and colleagues. |
Difficulty: Easy
Time Required:
Less than 1 hour
Cost: Free
Hardware: None
Download: Download
|
Last year I wrote two articles on how to annoy your friends and family by dripping blood down their computer screen, or by squirting them with (hopefully) fake blood from (even more hopefully) a fake skull. Halloween is just around the corner, so here are two more applications which you can use to further bother the people around you.
If you have ever seen the horror film The Ring, then you can likely guess the basic premise of this application. For those that haven't, the film is about a video tape which, when watched, will cause the viewer to die within a week of viewing it. So, what better way to annoy and terrify your friends than by playing the "cursed video" at a time you schedule without their knowing?
This application will use a library from Managed DirectX to play the video. If you haven't already, grab the full DirectX SDK and install. Note that we will be creating a dependency on DirectX, so the victim's PC will need to have DirectX 9.0c installed. Almost every XP desktop has it installed at this point, but be sure to test the app on the target PC. Additionally, I have had mixed success drawing a semi-transparent video with every method I've tried (DX, WPF, etc.). It is very dependent on video drivers, so the intended effect may not be perfect on all PCs. Again, be sure to test.
Next, create a new C#/VB Windows Application project and set references to the Microsoft.DirectX and Microsoft.DirectX.AudioVideoPlayback assemblies as shown:
Next, we need to make some modifications to the form. The video will be played at 50% transparency against the victim's desktop, which gives a very creepy effect. The form should also be hidden from view until the video is ready to be played at the selected time. To do this, set the following properties on the form:
Property | Value |
BackColor | Fuchsia |
FormBorderStyle | None |
WindowState | Minimized |
Opacity | 50% |
ShowInTaskbar | False |
TopMost | True |
TransparencyKey | Fuchsia |
Next, we need to provide a surface onto which the video can be drawn. Drop a PictureBox control onto the form and set its properties as follows:
Property | Value |
BackColor | Fuchsia |
Dock | Fill |
Now we need a method which will play the video. Bring in the Microsoft.DirectX.AudioVideoPlayback namespace with the using/Imports keyword and then add the following method to the form:
C#
using Microsoft.DirectX.AudioVideoPlayback; ... Video _video; public void StartShow() { // create a new video from a filename this._video = Video.FromFile("ring.wmv"); // set the drawable surface to the picturebox this._video.Owner = pictureBox1; // setup an event handler so we can pop up a msgbox when the video is over this._video.Ending += new EventHandler(video_Ending); // play it! this._video.Play(); } void video_Ending(object sender, EventArgs e) { // called when the video ends MessageBox.Show("Happy Halloween!"); this.Close(); }
VB
Imports Microsoft.DirectX.AudioVideoPlayback ... Private _video As Video Public Sub StartShow() ' create a new video from a filename Me._video = Video.FromFile("ring.wmv") ' set the drawable surface to the picturebox Me._video.Owner = pictureBox1 ' setup an event handler so we can pop up a msgbox when the video is over AddHandler _video.Ending, AddressOf video_Ending ' play it! Me._video.Play() End Sub Private Sub video_Ending(ByVal sender As Object, ByVal e As EventArgs) ' called when the video ends MessageBox.Show("Happy Halloween!") Me.Close() End Sub
This simply creates a new Video object by loading a specific filename (ring.wmv), then assigns the video's Owner property to the PictureBox, which is where the video will be drawn. Next, an event is setup so we are notified when the clip has ended, and finally, the video is played with the Play method.
The video_Ending event handler displays a message box and closes down the application.
x86/x64
The Managed DirectX assemblies are compiled to run in x86 mode only. If you are compiling the application on an x64 OS, you will have to ensure that the main application is built as an x86 target. To do so, choose Configuration Manager from the build menu. In the dialog that appears, choose <New...> from the Active solution platform drop down:
Finally, choose x86 from the Type or select the new platform drop down:
Get back to the project and rebuild and you will have an x86-native application which will run successfully on both x86 and x64 platforms.
The code which handles the configuration, scheduling and testing will be the same for both of these applications, so please jump to that section by clicking here.
If you have seen The Shining, you can probably guess where this one is heading, too. The basic plot is that an author and his family retreat to an isolated hotel for the winter, and some paranormal activity causes the father to go a bit insane, among other things. In the film, as the author goes crazy, he starts typing "All work and no play makes Jack a dull boy" over and over again on the typewriter. So, this application will mimic that by, at the appointed time, popping up an instance of Notepad and having the computer type the phrase over and over again on its own.
Once again, create a new VB/C# Windows Application project. As with the previous project, we want the main form to be hidden, but this time, it should be hidden at all times. So, set the form properties as follows:
Property | Value |
FormBorderStyle | None |
WindowState | Minimized |
ShowInTaskbar | False |
Size | 10, 10 |
Next, drag a timer onto the form named tmrType and create an event handler for the Tick event which we will fill in later.
Create a method named StartShow as follows:
C#
using System.Diagnostics; ... private Process _process; public void StartShow() { _process = Process.Start("notepad.exe"); tmrType.Start(); }
VB
Imports System.Diagnostics ... ' the Notepad process Private _process As Process Public Sub StartShow() _process = Process.Start("notepad.exe") tmrType.Start() End Sub
This code starts an instance of Notepad and then starts the tmrType ticking. That tick event will send the appropriate letter to the Notepad window from the phrase:
C#
using System.Runtime.InteropServices; ... [DllImport("user32")] public static extern int SetForegroundWindow(IntPtr hwnd); // counter variables private int i, j; // the message to type out private const string msg = "All work and no play makes Jack a dull boy."; ... private void tmrType_Tick(object sender, EventArgs e) { // make sure the Notepad window is at the front SetForegroundWindow(_process.MainWindowHandle); // send the next letter to the window if(i < msg.Length) SendKeys.Send(msg[i++].ToString()); else { // send a carriage return if we're at the end of the line SendKeys.Send("{ENTER}"); // write the line 5 times if(++j < 5) i = 0; else { // when done, stop the timer, display the msgbox and close it up tmrType.Stop(); MessageBox.Show("Happy Halloween!"); this.Close(); } } }
VB
Imports System.Runtime.InteropServices ... <DllImport("user32")> _ Public Shared Function SetForegroundWindow(ByVal hwnd As IntPtr) As Integer End Function ' counter variables Private i, j As Integer ' the message to type out Private Const msg As String = "All work and no play makes Jack a dull boy." Private Sub tmrType_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles tmrType.Tick ' make sure the Notepad window is at the front SetForegroundWindow(_process.MainWindowHandle) ' send the next letter to the window If i < msg.Length Then SendKeys.Send(msg.Chars(i).ToString()) i += 1 Else ' send a carriage return if we're at the end of the line SendKeys.Send("{ENTER}") ' write the line 5 times j = j + 1 If j < 5 Then i = 0 Else ' when done, stop the timer, display the msgbox and close it up tmrType.Stop() MessageBox.Show("Happy Halloween!") Me.Close() End If End If End Sub
At the start of the tick, a call is made to the Win32 API function SetForegroundWindow, passing in the window handle (_process.MainWindowHandle) of the Notepad process. This ensures that the Notepad window is focused before we send the next letter to the window using the SendKeys method. When the end of the phrase is reached, a carriage return is sent using SendKeys and the string {ENTER}. This repeats 5 times at which point the timer is stopped, the message box is displayed, and the application closes.
The final piece is to setup a time at which the effect will display on the victim's PC. Create a simple dialog box with a DateTimePicker control that allows the choosing of the appropriate date/time to run:
Next, create a new application setting named Time as shown:
Next, setup the events on the Configuration form as follows:
C#
private void ConfigForm_Load(object sender, EventArgs e) { // if no time has been specified, show today's date, otherwise, show the date previously selected if(Properties.Settings.Default.Time == DateTime.MinValue) dateTimePicker1.Value = DateTime.Now.Date; else dateTimePicker1.Value = Properties.Settings.Default.Time; } private void btnSave_Click(object sender, EventArgs e) { // save the currently selected date/time to the Settings collection Properties.Settings.Default.Time = dateTimePicker1.Value; Properties.Settings.Default.Save(); // tell the user what's up MessageBox.Show("Date and time saved. When you click OK, the application will continue running and the show will start upon the specified date and time. If you wish to reset the date/time, restart the application with the '-config' switch.", "Configuration updated", MessageBoxButtons.OK, MessageBoxIcon.Information); // close it up this.DialogResult = DialogResult.OK; this.Close(); } private void btnCancel_Click(object sender, EventArgs e) { // close it up this.DialogResult = DialogResult.Cancel; this.Close(); }
VB
Private Sub ConfigForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' if no time has been specified, show today's date, otherwise, show the date previously selected If My.Settings.Default.Time = DateTime.MinValue Then dateTimePicker1.Value = DateTime.Now.Date Else dateTimePicker1.Value = My.Settings.Default.Time End If End Sub Private Sub btnSave_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSave.Click ' save the currently selected date/time to the Settings collection My.Settings.Default.Time = dateTimePicker1.Value My.Settings.Default.Save() ' tell the user what's up MessageBox.Show("Date and time saved. When you click OK, the application will continue running and the show will start upon the specified date and time. If you wish to reset the date/time, restart the application with the '-config' switch.", "Configuration updated", MessageBoxButtons.OK, MessageBoxIcon.Information) ' close it up Me.DialogResult = System.Windows.Forms.DialogResult.OK Me.Close() End Sub Private Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCancel.Click ' close it up Me.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Close() End Sub
The code loads the current value at start (if it exists), saves it when the Save button is clicked, and does nothing when Cancel is clicked.
Back on the main form of either application, drag and drop a timer control named tmrScheduler to the main design surface. Set the properties as follows:
Property | Value |
Enabled | True |
Interval | 60000 |
This will start the timer immediately and call the Tick event once every minute. That event will check to see whether the requested time has passed and, if so, starts the show:
C# - Cursed Video
private void tmrScheduler_Tick(object sender, EventArgs e) { // if the current time is greater than the time set by the user if(DateTime.Now >= Properties.Settings.Default.Time) { // bring up the window this.WindowState = FormWindowState.Maximized; // disable this timer tmrScheduler.Enabled = false; // bring it to the top this.BringToFront(); // play the movie StartShow(); } }
VB - Cursed Video
Private Sub tmrScheduler_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles tmrScheduler.Tick ' if the current time is greater than the time set by the user If DateTime.Now >= My.Settings.Default.Time Then ' bring up the window Me.WindowState = FormWindowState.Maximized ' disable this timer tmrScheduler.Enabled = False ' bring it to the top Me.BringToFront() ' play the movie StartShow() End If End Sub
C# - The Shining
private void tmrScheduler_Tick(object sender, EventArgs e) { // if the current time is greater than the time set by the user if(DateTime.Now >= Properties.Settings.Default.Time) { // disable this timer tmrScheduler.Enabled = false; // start typing StartShow(); } }
VB - The Shining
Private Sub tmrScheduler_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles tmrScheduler.Tick ' if the current time is greater than the time set by the user If DateTime.Now >= My.Settings.Default.Time Then ' disable this timer tmrScheduler.Enabled = False ' start typing StartShow() End If End Sub
To make it easy to reset the launch time, and to test the effect without scheduling it, two command line parameters can be added to Program.cs/vb to re-run the configuration or test. Add the following code prior to the call to Application.Run:
C#
// test the effect if(Environment.CommandLine.IndexOf("test") > -1) { Form1 f = new Form1(); f.StartShow(); f.ShowDialog(); return; } // if we haven't set the time, or the user requested the config dialog, display it if(Properties.Settings.Default.Time == DateTime.MinValue || Environment.CommandLine.IndexOf("config") > -1) { if(new ConfigForm().ShowDialog() == DialogResult.Cancel) return; }
VB
' test the effect If Environment.CommandLine.IndexOf("test") > -1 Then Dim f As Form1 = New Form1() f.StartShow() f.ShowDialog() Return End If ' if we haven't set the time, or the user requested the config dialog, display it If My.Settings.Default.Time = DateTime.MinValue OrElse Environment.CommandLine.IndexOf("config") > -1 Then If New ConfigForm().ShowDialog() = DialogResult.Cancel Then Return End If End If
If -test is passed on the command line, the form is created and the show is started. If -config is passed on the command line, the Configuration dialog is displayed and the application continues as it would the first time it ran.
Cursed Video
Copy the exe, Microsoft.DirectX and Microsoft.DirectX.AudioVideoPlayback to a folder on the user's PC along with a video clip named ring.wmv. Of course, you can replace that video clip with any clip of your choosing, though if you wish to use a different filename, you will have to change the code and recompile.
The Shining
Copy the exe to a folder on the user's PC.
For either, create a shortcut to it in the Startup program group, or set it up to run via the registry using the following key for the logged in user:
Simply create a new string key with any Name, and a Data value of the path to the executable.
Next, start the application once on their PC to setup the date and time for the show to begin. Once that is done, the application will remain running in the background. If the PC is restarted, and the application is setup to run at startup as described above, it will start silently and remain running, waiting for the date and time specified.
Two Halloween applications for the price of one. Not that you paid for either. Be sure to have fun with them this Halloween and disturb anyone you can. Enjoy!
Thanks to Giovanni Montrone for testing out these applications during development.
Brian is a Microsoft C# MVP and a recognized .NET expert with over 6 years experience developing .NET solutions, and over 9 years of professional experience architecting and developing solutions using Microsoft technologies and platforms, although he has been "coding for fun" for as long as he can remember. Outside the world of .NET and business applications, Brian enjoys developing both hardware and software projects in the areas of gaming, robotics, and whatever else strikes his fancy for the next ten minutes. He rarely passes up an opportunity to dive into a C/C++ or assembly language project. You can reach Brian via his blog at http://www.brianpeek.com/.
Hi I'm using C# 2008 Express but the configuration manager in the build menu is not active,
what can be happening?
@Hiram: use the contact page so I can get a better understanding of what is happening.
Here is a list of my current Coding4Fun articles: WiiEarthVR Animated Musical Holiday Light Show - Version
What Type do you select for the Time settings, it is unclear from the picture..
@Will If I understand what you're asking, that is a control built into the framework.