
Contents
Introduction
I like the Snipping Tool tool in Windows 7 but it does not allow
pixelized image fragments. And... I made it.
The program (FoxTools Screen Shooter) interface is similar to a Snipping Tool, but my program has several
special features.
Features:
- Capturing the screen in one of three modes: free-form, rectangle, full screen.
- Drawing tools: pen, marker, pixelation, eraser.
- Send images to FoxTools.ru or ZzWeb.ru.
- Saving images in graphic formats: PNG, JPG (JPEG), and GIF.
- Multilingual interface (Russian, English).
This is a complete software. You can use it, it's free. The program is open
source and you can modify the code for yourself.
In this article, I will explain how to use the source code. And also I will give answers to some questions that were raised during the creation of a program.
Using the code
I used the development environment Visual Studio 2010. To open the project, use the file FoxTools.Shooter.vbproj
.
Opening the Forms on the Design mode you may get an error:

It's normal. You need to build (compile) a project.
When you build (compile) a project you may get an error: FileTracker : error FTK1011:
C:\some path\FileTracker FoxTools.Shooter.

It's not normal, but it's not my fault.
Check that the path to a project does not contain spaces.
A program consists of three main forms: Main
- the screen capture tool; ScreenContainer
- the screen container; Result
- the
image editor.
For Main
form I created a custom ToolStripSplitButton
- FoxToolStripSplitButton
and
a ToolStripMenuItem
- FoxToolStripMenuItem
.
In the FoxToolStripSplitButton
control I created custom Paint
method, because necessary to draw a pushed button style.
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
If Me.Pushed Then
Dim g As Graphics = e.Graphics
ControlPaint.DrawBorder3D(g, Me.ButtonBounds)
ControlPaint.DrawBorder3D(g, Me.DropDownButtonBounds)
End If
End Sub
And also I created Info
property for storing help information.
The FoxToolStripMenuItem
control contains one extra property - Mode
.
This property will set the mode screen capture: Full
, Window
(todo), Rectangle
, and Custom
.
The ScreenContainer
form has a simple code. But note, to debug mode
please set False
for TopMost
property.
Public Sub New(mf As Main, mode As Enums.ScreenMode)
InitializeComponent()
End Sub
Result
form has drawing tools. Now it's: Pen
, Marker
, Pixelate
, and
Eraser
.
I created custom ToolStripButton
- it's FoxToolStripButton
, which
has one extra property - ShapeType
. ShapeType
is tool type of
drawing.
You can see the variable _shapes
in a Result
form code.
This is collection of shapes. Shape can be added to the collection when a user
clicks on the button tool, excluding eraser. All tool buttons has one click
handler, is btnShapeType_Click
. The variable _shapeType
contains
information about type of selected shape.
The drawing tools may have config forms. I crated base class for config forms - ConfigShapeForm
.
Pen tool is ConfigPen
, Pixelate tool is ConfigPixelate
.
Configuration from can be displayed before start drawing (Pen), or after
(Pixelate). The variable _shapeConfig
contains link to configuration form for
current shape.
Drawing starts after clicking the left mouse button on a PictureBox
, you can
see it in the MouseDown
event handler. To add a shape to collection
using the AddShape
method. For Pixelate type of shape, the item is
added to the top of the list. For other types of shapes, a item is added to the
bottom of a list.
Shapes is drawing in the DrawShapes
method to the Graphics
object.
The finished image can be generated by GetImage
method, or GetImageBuffer
for byte array.
Sending images to Internet created via API.FoxTools.ru. This is my independent project and currently it's only
for russian language, sorry. But you can do sending data to your server, without
my API. It's easy. You can use my helper class from FoxTools.Lib.dll.
Private Sub CustomSend()
Dim t As New Thread(AddressOf CustomSend_Start)
t.IsBackground = True
t.Start()
End Sub
Private Sub CustomSend_Start()
Using w As New FoxTools.Lib.Net.Web()
w.Method = FoxTools.Lib.Net.Enums.HttpMethod.POST
w.Url = "http://example.com/upload.php"
w.ContentType = "multipart/form-data"
w.Queries.AddFile("myfile", "test.png", GetImageBuffer(), "image/png")
Dim result As String = w.ExecuteString()
ShowResultOfSending(result)
End Using
End Sub
Posted file, you can get on a server:
' ASP (.NET)
Request.Files("myfile")
$_FILES["myfile"]
You can use FoxTools.Lib.dll for other projects, I don't forbid it. But
you do not have permissions for disassemble the library. As for API, you can use
it, if you will understand how it works. I created opening API key special for
CodeProject members: ID = 13
, Access key = e91268b7-1162-4044-9236-7191c8c3b5d2
.
FoxTools Screen Shooter using other limited Access key, you can see it in the
Settings window.

For this Access key set permissions only on the Screen
and the ZzWeb
API methods. But the API has many more methods and CodeProject
Key has permissions for all this methods.
For example, a request for information about the IP address:
Dim myApi As New FoxTools.Lib.Api(13, "e91268b7-1162-4044-9236-7191c8c3b5d2")
Dim ip As FoxTools.Lib.Objects.Ip = myApi.Ip("171.204.20.75")
Console.WriteLine("Is proxy server: {0}", ip.IsProxy)
If ip.Country IsNot Nothing Then
Console.WriteLine("Country: {0} ({1})", ip.Country.NameEn, ip.Country.ISO3166A2)
If ip.City IsNot Nothing Then
Console.WriteLine("City: {0}", ip.City.NameEn)
Console.WriteLine("Location: {0} - {1}", ip.City.Latitude, ip.City.Longitude)
End If
End If
You can see all methods on the http://api.foxtools.ru. But that's another theme.
TODO
This is TODO List for next versions:
- Marker is wrong. In the current implementation, the marker color is
overlaid, but must mix. I have not idea, how to do it.
- Capture windows. I have not idea, how to do it. I tried using Windows API, but without result.
I can not get a list of visible windows on the display.
- Image resize.
- Image print.
- Send by Email.
- Undo the last changes (Ctrl + Z).
- Remove TopMost (
ScreenContainer
)... What do you think about this? - Add drawing tools.
- Your ideas...
Questions and Answers
Screen Capture
Capture screen is very simple. You can get screen via of the same name class.
Dim s As Screen = Screen.PrimaryScreen
Dim bmp As New Bitmap(s.Bounds.Width, s.Bounds.Height, PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(bmp)
g.CopyFromScreen(s.Bounds.X, s.Bounds.Y, 0, 0, s.Bounds.Size, CopyPixelOperation.SourceCopy)
I used only the primary screen - PrimaryScreen
, but a computer can have multiple screens. You can get each screens from AllScreens
property.
For Each s As Screen In Screen.AllScreens
Dim bmp As New Bitmap(s.Bounds.Width, s.Bounds.Height, PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(bmp)
g.CopyFromScreen(s.Bounds.X, s.Bounds.Y, 0, 0, s.Bounds.Size, CopyPixelOperation.SourceCopy)
bmp.Save(String.Format("{0}.png", System.Text.RegularExpressions.Regex.Replace(_
s.DeviceName, "[^\w\d]+", "")), System.Drawing.Imaging.ImageFormat.Png)
Next
Rectangle area selection
To implement the selection of a image area, you need to handle mouse events.
Imports System.Drawing.Imaging
Public Class Form1
Private _bmp As Bitmap
Private _start As Point?
Private _end As Point?
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.DoubleBuffered = True
Dim s As Screen = Screen.PrimaryScreen
_bmp = New Bitmap(s.Bounds.Width, s.Bounds.Height, PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(_bmp)
g.CopyFromScreen(s.Bounds.X, s.Bounds.Y, 0, 0, s.Bounds.Size, CopyPixelOperation.SourceCopy)
End Sub
Private Sub Form1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
_start = e.Location
_end = e.Location
Me.Refresh()
End Sub
Private Sub Form1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
If _start.HasValue Then
_end = e.Location
Me.Refresh()
End If
End Sub
Private Sub Form1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
_start = Nothing
_end = Nothing
Me.Refresh()
End Sub
Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics
g.DrawImage(_bmp, 0, 0)
Dim r As New Region(New Rectangle(0, 0, _bmp.Width, _bmp.Height))
If _start.HasValue AndAlso _end.HasValue Then
Dim p As New Pen(Brushes.Red)
Dim rec As Rectangle = Rectangle.Empty
Dim x, y, w, h As Integer
If _end.Value.X - _start.Value.X < 0 Then
x = _end.Value.X
w = _start.Value.X - _end.Value.X
Else
x = _start.Value.X
w = _end.Value.X - _start.Value.X
End If
If _end.Value.Y - _start.Value.Y < 0 Then
y = _end.Value.Y
h = _start.Value.Y - _end.Value.Y
Else
y = _start.Value.Y
h = _end.Value.Y - _start.Value.Y
End If
rec = New Rectangle(x, y, w, h)
If Not rec = Rectangle.Empty Then
g.DrawRectangle(p, rec)
End If
End If
End Sub
End Class
It is code for Windows Forms application.
Overlay
Overlay - is filling a translucent color image. You can make an overlay using the FillRegion
method.
Dim b As SolidBrush = New SolidBrush(Color.FromArgb(100, Color.White))
g.FillRegion(b, r)
This code should be at end of the Form1_Paint
method.
Overlay with hole
To make a hole in the overlay, you must use the Exclude
method of
Region
instance.
If Not rec = Rectangle.Empty Then
r.Exclude(rec)
g.DrawRectangle(p, rec)
End If

You can download project file here.
Rectangle area selection is simple, but the free-form area selection easier!
Imports System.Drawing.Imaging
Public Class Form1
Private _bmp As Bitmap
Private _points As List(Of Point)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'to avoid flicker
Me.DoubleBuffered = True
' get primary screen
Dim s As Screen = Screen.PrimaryScreen
' create bitmap
_bmp = New Bitmap(s.Bounds.Width, s.Bounds.Height, PixelFormat.Format32bppArgb)
' create graphics from bitmap
Dim g As Graphics = Graphics.FromImage(_bmp)
' copy screen to bitmap
g.CopyFromScreen(s.Bounds.X, s.Bounds.Y, 0, 0, s.Bounds.Size, CopyPixelOperation.SourceCopy)
End Sub
Private Sub Form1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
'start selection
_points = New List(Of Point)
_points.Add(e.Location)
Me.Refresh()
End Sub
Private Sub Form1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
'selecting
If _points IsNot Nothing Then
_points.Add(e.Location)
Me.Refresh()
End If
End Sub
Private Sub Form1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
'end selection
_points = Nothing
Me.Refresh()
End Sub
Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics
'draw image
g.DrawImage(_bmp, 0, 0)
'create region
Dim r As New Region(New Rectangle(0, 0, _bmp.Width, _bmp.Height))
'highlight the selected area
If _points IsNot Nothing AndAlso _points.Count > 1 Then
Dim p As New Pen(Brushes.Red)
Dim gp As New System.Drawing.Drawing2D.GraphicsPath()
gp.AddCurve(_points.ToArray())
'r.Exclude(gp)
g.DrawPath(p, gp)
End If
'draw overlay
Dim b As SolidBrush = New SolidBrush(Color.FromArgb(100, Color.White)) 'create brush
g.FillRegion(b, r) 'overlay
End Sub
End Class

You can download project file here.
Pixelization
Pixelization it is a lowering an image resolution for hiding individual
fragments or full an image.
To solve this problem, I calculated average color of a pixel and drawn big
pixel via FillRectangle
method.
Imports System.Drawing.Imaging
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim tab As New TabControl()
tab.Dock = DockStyle.Fill
tab.TabPages.Add("Original")
Dim pic As New PictureBox() With {.Left = 0, .Top = 0, .Width = 250, .Height = 135}
pic.Image = Image.FromStream(New System.IO.MemoryStream( _
New System.Net.WebClient().DownloadData(_
"http://s.codeproject.com/App_Themes/Std/Img/logo250x135.gif") _
))
tab.TabPages(tab.TabPages.Count - 1).Controls.Add(pic)
For i As Integer = 1 To 8
tab.TabPages.Add(String.Format("Pixelate {0}px", i * 4))
Dim pic2 As New PictureBox() With {.Left = 0, .Top = 0, .Width = 250, .Height = 135}
pic2.Image = Pixelization(pic.Image, i * 4)
tab.TabPages(tab.TabPages.Count - 1).Controls.Add(pic2)
Next
Me.Controls.Add(tab)
End Sub
Private Function Pixelization(img As Bitmap, size As Integer) As Bitmap
Dim result As New Bitmap(img.Width, img.Height)
Try
Dim g2 As Graphics = Graphics.FromImage(result)
Dim pixWidth As Integer = size
Dim pixHeight As Integer = size
If pixWidth > size Then
pixWidth = img.Width
End If
If pixHeight > size Then
pixHeight = img.Height
End If
For x As Integer = 0 To img.Width Step pixWidth
For y As Integer = 0 To img.Height Step pixHeight
Dim ir As Integer? = Nothing, ig As Integer? = Nothing, ib As Integer? = Nothing
For x2 As Integer = x To x + pixWidth - 1
If x2 >= img.Width Then Exit For
For y2 As Integer = y To y + pixHeight - 1
If y2 >= img.Height Then Exit For
Dim clr As Color = img.GetPixel(x2, y2)
If Not ir.HasValue Then
ir = 0 : ig = 0 : ib = 0
End If
ir += clr.R
ig += clr.G
ib += clr.B
Next
Next
If ir.HasValue Then
ir \= pixWidth * pixHeight
ig \= pixWidth * pixHeight
ib \= pixWidth * pixHeight
g2.FillRectangle(New SolidBrush(Color.FromArgb(255, ir, ig, ib)), x, y, pixWidth, pixHeight)
End If
Next
Next
Catch ex As Exception
End Try
Return result
End Function
End Class

You can download project file here.
Epilog
I hope that my program will be useful to you, and I hope the article will help
answer some of your questions.
Thanks all for reading this article.
Started programming in 1998 on the G-Basic and QBasic.
At various times worked with programming languages and technologies: Visaul Basic, Delphi, C, Visual C++, Java, PHP, ASP VBScript and JScript.
Currently engaged in programming based on .NET Framework technologies. Mainly the development of websites on the ASP.NET MVC, C#, TypeScript, SCSS and also database programming (SQL Server and PostgreSQL).
In 2016 started the AdminStock.net - solutions for administrators.