Motion-Detecting, Blood Squirting Halloween Skull

![]() |
Build an application that will drip animated blood down your victim's computer screen for a scary Halloween treat! |
Difficulty: Easy
Time Required:
Less than 1 hour
Cost: Free
Hardware: None
Download: Download
Introduction |
If you're anything like me, and I hope for your friends' and family's sake you're not, you believe that annoying others is amazingly entertaining. If that's the case, then this article is for you.
We are going to build an application that you will copy to a friend's PC that will, at a specified date and time, cause the computer to appear to start dripping blood down the screen and, after a few seconds, switch to a full-screen image of something terrifying while playing a screaming sound effect. This should sufficiently scare your victim for Halloween (hear the built-in scary sound).
We will be creating a full-screen, always-on-top, transparent form that will overlay the entire screen. This will be our display surface for the dripping blood.
The form can be created as described by modifying the following properties:
BackColor – Fuchsia
FormBorderStyle – None
DoubleBuffered – True
Text - <empty string>
WindowState – Maximized
ShowInTaskbar – False
TransparencyKey – Fuchsia
TopMost - True
This will create our full-screen, transparent form with no visible name, no icon in the task bar, no border that will remain on top of all other windows. With this in place, we can draw whatever we want to on to the form and it will be displayed over whatever happens to be on the screen. A nice bonus to this is that even though the form is maximized, because it is transparent, mouse and keyboard events will pass through to the visible active forms below. The user's PC should act as though nothing is happening!
With the images set as resources, we can load the images in the BloodDrop constructor as follows:
Visual Basic
Public Sub New() ' load each animation frame from the app's resources and add it to our frame list For Each file As String In _files Dim img As Image = Image.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("HalloweenVB." + file)) _frames.Add(img) Next ' set our first frame _image = _frames(0) End Sub
Visual C#
public BloodDrop() { // load each animation frame from the app's resources and add it to our frame list foreach(string file in _files) { Image img = Image.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Halloween.images." + file)); _frames.Add(img); } // set our first frame _image = _frames[0]; }
The FromStream method of the Image object allows loading of an image file from an application's embedded resource list. To get access to the stream for a specific resource, the name of the resource needs to be known, which is the fully qualified name of the file. In the case of the C# project, the resources are named Halloween.images.<filename>. The VB project's resources are named HalloweenVB.<filename>. Though the images are stored in a directory named images in both projects, only the C# version includes the directory name as part of the fully qualified name.
In either case, each file is loaded and stored in a List of Image objects.
In creating this application, I decided to stay entirely within the framework so deployment would be as simple as copying a single executable to your victim's machine. Therefore, I decided to use standard GDI+ calls for drawing, instead of Managed DirectX or some other method.
At first, I experimented with making each blood droplet a PictureBox control and moving the control down the screen, but that was not quick enough for smooth animation. I next tried using a timer and drawing to the screen directly inside the Tick event, however this too was too jerky. Finally, I set the Tick event to simply invalidate the screen, causing the OnPaint event to fire. I found that performing screen updates inside this method with the DoubleBuffered property set to True allowed for the smoothest animation.
When the blood is set to be drawn, a timer is started that ticks every 100 milliseconds. This timer simply calls the Invalidate method of the current form object. When invalidated, the form calls its OnPaint handler, which we override.
Inside the OnPaint handler, we create a new BloodDrop object and assign a random horizontal position and vertical velocity to it. This provides for an interesting display as the blood drips down. The newly created BloodDrop is then added to a List of BloodDrop types. Finally, the full list of blood drops is enumerated, animated, and drawn.
Visual Basic
' create a new blood drop Dim drop As BloodDrop = New BloodDrop() ' set it to a random location on the screen drop.Location = New Point(_random.Next(SystemInformation.PrimaryMonitorSize.Width), 0) ' set it's velocity to a random number drop.Velocity = _random.Next(40) + 20 ' add it to our drawing list _dropList.Add(drop) ' enumerate the drawing list For Each bd As BloodDrop In _dropList ' animate and then draw the drop bd.Animate() bd.Draw(g) Next
Visual C#
// create a new blood drop BloodDrop drop = new BloodDrop(); // set it to a random location on the screen drop.Location = new Point(_random.Next(SystemInformation.PrimaryMonitorSize.Width), 0); // set it's velocity to a random number drop.Velocity = _random.Next(40) + 20; // add it to our drawing list _dropList.Add(drop); // enumerate the drawing list foreach(BloodDrop bd in _dropList) { // animate and then draw the drop bd.Animate(); bd.Draw(g); }
At application startup, an instance of the Random class is created and stored in our _random member variable. The Next method requires a parameter for the maximum value of the random number to be returned. In the case of setting the drop's location, I use the maximum screen width, determined by using the SystemInformation object. In the case of velocity, a maximum value of 40 pixels is requested, and an additional 20 pixels is added on in case a very low number is randomly selected.
Drawing the actual drop is pretty simple. The Draw method of our BloodDrop class looks like the following:
Visual Basic
' draw the drop Public Sub Draw(ByVal g As Graphics) ' if we're in "drop" mode, draw the stream behind it If _index >= 4 Then g.DrawImage(_frames(4), Me._location.X + 24, 0, _frames(4).Width, Me._location.Y + 10) End If ' if we're beyond the bottom of the screen, don't bother drawing the drop If Me._location.Y < SystemInformation.PrimaryMonitorSize.Height Then g.DrawImage(_image, Me._location.X, Me._location.Y, _image.Width, _image.Height) End If End Sub
Visual C#
// draw the drop public void Draw(Graphics g) { // if we're in "drop" mode, draw the stream behind it if(_index >= 4) g.DrawImage(_frames[4], this._location.X + 24, 0, _frames[4].Width, this._location.Y + 10); // if we're beyond the bottom of the screen, don't bother drawing the drop if(this._location.Y < SystemInformation.PrimaryMonitorSize.Height) g.DrawImage(_image, this._location.X, this._location.Y, _image.Width, _image.Height); }
In each case, we use the Graphics object provided to us and use the DrawImage method to draw the correct frame number to the correct position. In order to save some CPU cycles, we first determine whether the drop has passed the lower edge of the screen and, if it is, it is not drawn. The size of the screen can be determined by using the SystemInformation object and using the PrimaryMonitorSize method.
The second part of this method draws the blood trail that follows behind the droplet as it falls. This is done by stretching an image that is 1 pixel tall down the screen to the top of the blood drop graphic.
In my first attempts at drawing the blood in this manner, I found that the DrawImage method, when scaling an image as it is doing here, will anti-alias and blend the image to make it appear less blocky. Unfortunately, this caused a great deal of distortion, making the trail look awful. After some experimenting, I found that setting the following properties of the Graphics object before drawing would allow the image to be stretched without modification.
Visual Basic
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) ... ' grab the Graphics object for me app and set some properties for correct drawing Dim g As Graphics = e.Graphics g.PixelOffsetMode = PixelOffsetMode.Half g.InterpolationMode = InterpolationMode.NearestNeighbor g.CompositingQuality = CompositingQuality.HighSpeed ... End Sub
Visual C#
protected override void OnPaint(PaintEventArgs e) { ... // grab the Graphics object for this app and set some properties for correct drawing Graphics g = e.Graphics; g.PixelOffsetMode = PixelOffsetMode.Half; g.InterpolationMode = InterpolationMode.NearestNeighbor; g.CompositingQuality = CompositingQuality.HighSpeed; ... }
After the blood has dripped down the screen for several seconds (10 in the default case), the animation timer is disabled, the screen is cleared and a scary image is quickly displayed along with a loud screaming sound, which should hopefully scare the person at the keyboard. A running count of the time elapsed is stored in a member variable and is incremented by the timer's Interval value each time our OnPaint method is called.
This is accomplished by creating a PictureBox on the fly and loading an image into the box. This box is then added to the Controls collection of the form and displayed. Additionally, two events are handled that will dismiss the application when a user clicks the mouse or presses a key on the keyboard.
The sound is then loaded from a resource and played using the SoundPlay object. This looks like the following:
Visual Basic
' disable the animation timer tmrAnim.Enabled = False ' create a Picturebox Dim pb As PictureBox = New PictureBox() ' pull in the scary image from our resources pb.Image = Image.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("HalloweenVB.scary.jpg")) ' set it to fill the screen pb.SizeMode = PictureBoxSizeMode.Zoom pb.Width = SystemInformation.PrimaryMonitorSize.Width pb.Height = SystemInformation.PrimaryMonitorSize.Height pb.BackColor = Color.Black ' if it gets clicked, or someone presses a key, we want to end the app AddHandler pb.Click, AddressOf pb_Click AddHandler Me.KeyDown, AddressOf MainForm_KeyDown ' add the Picturebox to the controls list Me.Controls.Add(pb) ' play a scary sound Dim sp As SoundPlayer = New SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HalloweenVB.scream.wav")) sp.Play()
Visual C#
// disable the animation timer tmrAnim.Enabled = false; // create a Picturebox PictureBox pb = new PictureBox(); // pull in the scary image from our resources pb.Image = Image.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Halloween.images.scary.jpg")); // set it to fill the screen pb.SizeMode = PictureBoxSizeMode.Zoom; pb.Width = SystemInformation.PrimaryMonitorSize.Width; pb.Height = SystemInformation.PrimaryMonitorSize.Height; pb.BackColor = Color.Black; // if it gets clicked, or someone presses a key, we want to end the app pb.Click += new EventHandler(pb_Click); this.KeyDown += new KeyEventHandler(MainForm_KeyDown); // add the Picturebox to the controls list this.Controls.Add(pb); // play a scary sound SoundPlayer sp = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("Halloween.scream.wav")); sp.Play();
As you can see, the sound and image resources are loaded in an identical manner as the frames of animation shown earlier.
The final piece of the puzzle was to allow a user to select the date and time that the animation would start on the victim's PC. I created a simple configuration dialog box that is displayed the first time the application is run. The dialog allows the person setting up the application to choose the date and time the animation should be fired. This is saved using the Settings object of the project. This way, the user can put the application in the startup group, or create a registry key to load it on startup, so if the PC is rebooted before the desired time is reached, the application will restart and wait for the time to occur.
Settings can be added by right-clicking the project in the Solution Explorer and choosing Properties. Select the Settings tab and a new value can be entered. The one for this application looks like the following:
Now, on application startup, the application's Settings can be checked to determine if the configuration dialog needs to be shown, or just wait for the time specified.
When the application is started, a scheduler timer is created which ticks every minute. The Tick method for this timer looks at the current time, and if it is greater than or equal to the specified time, it will disable the scheduler timer, maximize the hidden window, and start the animation timer, which will automatically start drawing our blood droplets.
Visual Basic
Private Sub tmrScheduler_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrScheduler.Tick If DateTime.Now >= My.Settings.Time Then ' re-maximize the window Me.WindowState = FormWindowState.Maximized ' disable me timer tmrScheduler.Enabled = False ' enable the animation timer tmrAnim.Enabled = True End If End Sub
Visual C#
// called once per minute to check whether it's time to run the show 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) { // re-maximize the window this.WindowState = FormWindowState.Maximized; // disable this timer tmrScheduler.Enabled = false; // enable the animation timer tmrAnim.Enabled = true; } }
As mentioned earlier, one of the main goals of this project was to have an extremely easily deployable application. In order to achieve this, all code was kept inside the framework with no dependencies on things like Managed DirectX. Additionally, all resources used by the application (images and sounds) were setup as embedded resources so they do not need to be deployed separately.
When you are ready to scare your friend, simply copy the Halloween.exe file to his or her PC. )You may want to enlist someone as the “lookout” so you don't get caught while doing so!) 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.
And there we have it. A very simple application requiring very little code that will elicit quite a reaction from your victim. The code can be very easily modified to include different images, a different sound effect, or even different animation effects. There is plenty of time between now and April Fool's Day to modify the project for even more fun.
A special thanks to Joey Buczek for drawing up the blood drop animation, Mark Zaugg for testing on a few machines outside my house, and Michelle Leavitt for making my writing a bit more palatable for the masses.
Though Brian is 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, 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/.
This simple code section have saved me a lot of trouble.Am thinking of re-editing it to submit as my final year project.Pls if you can help me with more articles like this on any controls on c# pls do.Thanks
I don't see why there are no comments on this. This is really cool, thanks!
ok im brand new at this can you do a step by step?
In this application, Brian Peek demonstrates how to create two spooky Halloween applications to trick
Great. Thanks for the tips, I'm gonna try it now.
@enrique doing a quick glance the the article, commenting out a few lines of code and this should be rather an easy task since it draws the blood on to a picture box control
FAntastic !!
Can I apply the effect to a single image JPG ??
any sample code about it ?? thanks