Click here to Skip to main content
15,881,413 members
Articles / Desktop Programming / Win32

April Fools! Evil Windows Dialog Prank

Rate me:
Please Sign up or sign in to vote.
5.00/5 (15 votes)
31 Mar 2011CPOL5 min read 55.9K   572   24   21
Prank your coworkers with a dialog box that appears and disappears randomly by using a notification area app.

Introduction

Here’s the scenario. A co-worker sits down at his desk. After a few minutes, a message box pops up telling him that Windows encountered an error. Before he can respond, the box vanishes. He stresses, then figures it can be safely ignored. Then it returns. He goes to click the Cancel button, but the form jumps to a different location. He pursues it around his two monitors before it vanishes again, only to come back later.

The fake system warning dialog

Insert evil laugh here. But quietly, as you don't want him to know it was you who installed this small application on his machine.

This app was written using Visual Studio 2008, but should work with any version of the .NET Framework. It has been tested on Windows 7 64 bit and XP.

AppContext

The prank runs out of a descendant of ApplicationContext, which lets it run without needing a form. If you are unfamiliar with this class or have never written notification area apps, you may wish to read an earlier article of mine, Create a System Tray Application in VB.NET[^]. Start with a standard Windows application, and add this class.

VB.NET
Public Class AppContext
    Inherits ApplicationContext

#Region " Storage "
     Private Frm As MsgForm
    Private Rnd As Random

    Private WithEvents Ico As NotifyIcon
    Private WithEvents Menu As ContextMenuStrip
    Private WithEvents mnuExit As ToolStripMenuItem
    Private WithEvents Time As Timer

#End Region

#Region " Constructors "
     Public Sub New()
        Frm = New MsgForm
        Rnd = New Random
        Time = New Timer

        Dim MaxHeight As Integer = 0
        Dim Width As Integer = 0
        Dim Boundary As Rectangle = Nothing

        For Each S As Screen In Screen.AllScreens
            Width += S.Bounds.Width
            If S.Bounds.Height > MaxHeight Then MaxHeight = S.Bounds.Height
        Next

        mnuExit = New ToolStripMenuItem("Exit")
        Menu = New ContextMenuStrip
        Menu.Items.Add(mnuExit)

        Ico = New NotifyIcon
        Ico.Icon = My.Resources.MainIcon
        Ico.ContextMenuStrip = Menu
        Ico.Text = ""
        Ico.Visible = True

        Frm.Icon = My.Resources.MainIcon
        Frm.Arena = New Rectangle(0, 0, Width - 1, MaxHeight - 1)
        Time.Interval = Rnd.Next(30, 50) * 1000 'Seconds to next appearance
        Time.Enabled = True
    End Sub

#End Region

#Region " Event handlers "
     Private Sub AppContext_ThreadExit_
	(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.ThreadExit
        Ico.Visible = False
    End Sub

    Private Sub mnuExit_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles mnuExit.Click
        Application.Exit()
    End Sub

    Private Sub Time_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Time.Tick
        Time.Enabled = False
        Frm.Display()
        Time.Interval = Rnd.Next(30, 50) * 1000 'Seconds to next appearance
        Time.Enabled = True
    End Sub

#End Region

End Class

The class AppContext inherits from System.Windows.Forms.ApplicationContext. Using this makes the app easier to scale, and offers us the ThreadExit event where we can guarantee things will get cleaned up no matter how the application may end. To make it possible to shut down the app (come on, even that guy in Accounting should be given an out), we create a NotifyIcon where we can access a menu.

To make this more fun, we allow for multiple monitors. Typically, monitors are arranged in a row, so our "arena" is the combined width of the monitors, and the height of the tallest. This defines the region where the form can jump.

We use a Random object to set how often the form appears, which helps to keep them guessing. For demonstration purposes, I've set this to be pretty fast, every 30 to 50 seconds, but it might be more annoying if you use 300 to 900 seconds, which would be between five to fifteen minutes.

When the app is running, an icon will appear in the notification area (sometimes called the system tray.) You (or your users, if they get curious) can right click on the icon to pull up the context menu and select Exit. That ends the application thread, which in turn triggers the ThreadExit event. This event gets called no matter how the thread ends: Windows is shutting down, the user went in through the Process Manager, and so on.

MsgForm

The prank form is also pretty basic.

VB.NET
Friend Class MsgForm

    Private WithEvents Time As Timer
    Private pArena As Rectangle
    Private Rnd As Random
    Private Sounds() As System.Media.SystemSound = { _
        Media.SystemSounds.Asterisk, _
        Media.SystemSounds.Beep, _
        Media.SystemSounds.Exclamation, _
        Media.SystemSounds.Hand, _
        Media.SystemSounds.Question _
    }

    Public Property Arena() As Rectangle
        Get
            Return pArena
        End Get
        Set(ByVal value As Rectangle)
            pArena = value
        End Set
    End Property

    Public Sub New()
        InitializeComponent()
        pArena = Screen.PrimaryScreen.Bounds
        Rnd = New Random
        Time = New Timer
    End Sub

    Public Sub Display()
        Me.CenterToScreen()
        Time.Interval = Rnd.Next(10, 40) * 500
        Sounds(Rnd.Next(0, Sounds.Length - 1)).Play()
        Me.Show()
        Time.Enabled = True
    End Sub

    Private Sub MsgForm_FormClosing_
	(ByVal sender As Object, ByVal e As FormClosingEventArgs) _
    Handles Me.FormClosing
        If e.CloseReason = CloseReason.UserClosing Then
            e.Cancel = True
        End If
    End Sub

    Private Sub MsgForm_MouseEnter(ByVal sender As Object, ByVal e As EventArgs) _
    Handles Me.MouseEnter
        Me.Location = New Point(Rnd.Next(0, pArena.Width - Me.Width), _
                                Rnd.Next(0, pArena.Height - Me.Height))
    End Sub

    Private Sub Time_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Time.Tick
        Time.Enabled = False
        Me.Hide()
    End Sub
End Class

The form has its own Timer: when it expires, the timer is disabled and the form hidden. Note that the values are set using half second increments. As written, the form will vanish after 5 to 20 seconds.

The property Arena gives the boundaries as to where the form can jump, and the array Sounds() lets the form generate a random system sound every time it appears.

The form is activated from AppContext by calling the its Display method. This centers the form to the current monitor, sets the timer, plays a random sound, shows the form and starts the timer. When Time goes off, the timer is disabled and the form hidden.

The MouseEnter event is where things get interesting. When the user moves the mouse in to click on one of the buttons, the form jumps to a random location on the desktop. Hilarity ensues. If the user manages to reach the form's close button, the attempt to close the form gets canceled in the FormClosing event so nothing happens, which adds just a bit more frustration.

Putting It Together

Because this is written in VB, there are a few extra steps that (I think) C# programmers do not need to do. The first is to write our entry point.

VB.NET
Public Module Launch

    Public Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New AppContext)
    End Sub

End Module

Next, we have to tell the bootstrapper to use it instead of a starting form. This is done by going to the My Project interface, unchecking Enable application framework and selecting Sub Main as the startup object. Disabling the application framework also disables the visual styles, which is why they get turned back on manually in Main. Strictly speaking, we don't need to do this, but the form will not look right if we don't.

The last thing is to deploy the app. Assuming your chosen victim's workstation has the .NET framework already installed on it, it should just be a matter of compiling the code, copying the executable to somewhere handy, and running it.

For the Truly Evil

As written, this is an annoying but harmless prank. While I really hope you will keep it harmless, there are other ways you can make it much more annoying. One thought is to scan the user's machine for sound files, and play one at random when the form manifests. Or you could add a menu that lets you put the application thread to sleep for a few hours before waking up again. Maybe instead of a system warning, the form could display complaints like "Is it warm in here or is my processor overheating?" or offer useful suggestions like "Screw this, let's go for a beer." The possibilities are limited only by your evil, twisted imagination.

Have fun, and if you come up with a particularly fiendish variation, please let me know!

History

  • Version 1 - 2011-03-31 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Gregory Gadow recently graduated from Central Washington University with a B.S. that combined economics and statistical analysis, and currently works for the Washington Department of Fish & Wildlife as an IT developer. He has been writing code for 30 years in more than a dozen programming languages, including Visual Basic, VB.Net, C++, C#, ASP, HTML, XML, SQL, and R.

Comments and Discussions

 
Generalgreat idea Gregory Pin
Abhimanyu Kumar Vatsa19-Apr-11 4:23
Abhimanyu Kumar Vatsa19-Apr-11 4:23 
GeneralThe solution Pin
frijolebandito11-Apr-11 11:05
frijolebandito11-Apr-11 11:05 
Generalanother idea Pin
DkUltra4-Apr-11 7:02
DkUltra4-Apr-11 7:02 
GeneralRe: another idea Pin
Gregory Gadow4-Apr-11 7:40
Gregory Gadow4-Apr-11 7:40 
GeneralIts just not funny to me..... Pin
Patrick Blackman1-Apr-11 7:34
professionalPatrick Blackman1-Apr-11 7:34 
GeneralRe: Its just not funny to me..... Pin
Gregory Gadow1-Apr-11 9:34
Gregory Gadow1-Apr-11 9:34 
GeneralI like this sort of thing, last year I did this one Pin
Sacha Barber31-Mar-11 19:58
Sacha Barber31-Mar-11 19:58 
GeneralRe: I like this sort of thing, last year I did this one Pin
Nish Nishant1-Apr-11 1:27
sitebuilderNish Nishant1-Apr-11 1:27 
GeneralRe: I like this sort of thing, last year I did this one Pin
Gregory Gadow1-Apr-11 1:44
Gregory Gadow1-Apr-11 1:44 
GeneralRe: I like this sort of thing, last year I did this one Pin
Sacha Barber1-Apr-11 1:58
Sacha Barber1-Apr-11 1:58 
GeneralRe: I like this sort of thing, last year I did this one Pin
Gregory Gadow1-Apr-11 3:09
Gregory Gadow1-Apr-11 3:09 
GeneralRe: I like this sort of thing, last year I did this one Pin
Sacha Barber1-Apr-11 3:32
Sacha Barber1-Apr-11 3:32 
GeneralMy vote of 1 Pin
_Maxxx_31-Mar-11 17:33
professional_Maxxx_31-Mar-11 17:33 
GeneralRe: My vote of 1 Pin
Gregory Gadow31-Mar-11 18:53
Gregory Gadow31-Mar-11 18:53 
GeneralRe: My vote of 1 Pin
AspDotNetDev1-Apr-11 5:50
protectorAspDotNetDev1-Apr-11 5:50 
GeneralGreat joke Pin
Lex Steers31-Mar-11 13:11
Lex Steers31-Mar-11 13:11 
GeneralRe: Great joke Pin
Gregory Gadow31-Mar-11 15:36
Gregory Gadow31-Mar-11 15:36 
GeneralMy vote of 1 Pin
rctaubert31-Mar-11 13:10
rctaubert31-Mar-11 13:10 
GeneralRe: My vote of 1 Pin
Gregory Gadow31-Mar-11 15:34
Gregory Gadow31-Mar-11 15:34 
GeneralMy vote of 5 Pin
bwhittington31-Mar-11 13:02
bwhittington31-Mar-11 13:02 
GeneralAhhh Pin
The_Mega_ZZTer31-Mar-11 12:23
The_Mega_ZZTer31-Mar-11 12:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.