Introduction
This is my first article on F# programming language and I decided to start with graphics programming, since graphics programming has always been interesting to me.
In this article, I will show you how to use GDI+ in F# programming language to design country flag.
Using the Code
First of all, we will create the main window of our application. We will need the following .NET namespaces for that purpose:
open System;
open System.Windows;
open System.Windows.Forms;
And the following namespaces are also required for using the GDI+:
open System.Drawing;
open System.Drawing.Drawing2D;
Don't forget to add all the references for those namespaces through the Reference Manager of Visual Studio.
Since form designer is not available for F# in Visual Studio, we have to manually write codes for our application Graphical User Interface.
This MainWindow
class represents our application main window:
type MainWindow() =
inherit Form()
member this.Init =
this.Text <- "Flag Design With GDI+"
this.Size <- new System.Drawing.Size(600, 560)
this.BackColor <- System.Drawing.Color.DeepSkyBlue
The MainWindow
class inherits the System.Windows.Forms.Form
class. The Init
member function initializes some basic property of the window. Our entry point function will call this function.
This is the entry point of our application which creates object of the MainWindow
class, initializes it and runs it:
[<STAThread>]
let START =
let mainWindow = new MainWindow()
mainWindow.Init
Application.Run(mainWindow)
By calling the MainWindow.Init
method, we initialize the basic properties of our MainWindow
.
The Application.Run
method will make our main window visible and run standard application message loop on the current thread.
Compiling and running the application at this stage, you will see a Window filled with DeepSkyBlue
color. The color was specified inside the Init
member function of MainWindow
class.
Remember that a default F# application is always a Console Application, you have to manually set the application type to Windows Application in the project properties. Otherwise, you will see a black DOS/Command window behind your main window.
Now, we will write codes for drawing our flags. To draw anything using the GDI+ in our main window, we will need to create a Paint Event Handler.
So let's do it.
Create a member function called Event_Paint
inside the MainWindow
class.
member this.Event_Paint(sender : System.Object, e : PaintEventArgs) =
........
........ .. .
This is our Paint
event handler function. That means this function will handle paint event for our main window.
Inside the Init
member function of the MainWindow
class, write the following line:
this.Paint.AddHandler(new Windows.Forms.PaintEventHandler(fun s pe ->this.Event_Paint(s, pe)))
Here the fun
keyword is used for defining an anonymous function. Which is also called lambda expression.
Syntax of fun
keyword is:
fun parameter-list -> expression
According to MSDN:
The parameter-list typically consists of names and, optionally, types of parameters. The expression is the body of the function.
As a valid lambda expression, we use the Event_Paint
function which is our Paint
event handler. So when our main window needs to be painted, it will call our Event_Paint
function and anything we draw using GDI+ inside the function, will be showing in our main window.
In the Event_Paint
function, we set the Smoothing and Compositing property of Graphics
class to HighQuality
for getting better image quality.
e.Graphics.SmoothingMode <- SmoothingMode.HighQuality
e.Graphics.CompositingQuality <- CompositingQuality.HighQuality
Now, we can call our flag drawing function inside the Event_Paint
function to draw it inside our main window. I have implemented six country flag drawing function. Which are Bangladesh, Canada, United States Of America, United Kingdom and Germany.
Here is the source code of Bangladesh flag drawing function:
member this.Draw_BangladeshFlag(x :float32, y :float32, g : System.Drawing.Graphics) =
g.FillRectangle(Brushes.Green, x, y, 260.0f, 156.0f)
g.FillEllipse(Brushes.Red, x + 70.0f, y + 30.0f, 100.0f, 100.0f)
In this function, we use the Graphics.FillRectangle
and Graphics.FillEllipse
method to draw the green background and red center circle of the flag.
We can call this function inside the Event_Paint
member function thus:
this.Draw_BangladeshFlag(20.0f, 10.0f, e.Graphics)
USA flag has star symbol. So, we need a star drawing function for that purpose.
The following member function is for drawing star:
member this.Draw_Star(x :float32, y :float32, r: float32, g : System.Drawing.Graphics) =
let radian72 = (float) ( (float) System.Math.PI * (float) 4.0 ) / (float) 5.0
let pts : PointF array = Array.zeroCreate 5
for i in 0 .. pts.Length - 1 do
Array.set pts i ( new PointF(x + r * (float32)(Math.Sin((float)i * radian72)),
y - r * (float32)(Math.Cos( (float)i * radian72 )) ))
g.FillPolygon( Brushes.White, pts, FillMode.Winding)
This function takes x
and y
parameter value as the center of the star and r
parameter value for the star radius. Then it creates a PointF
typed array and fills it with necessary values through the for ... in loop. And finally, it passes the point array to the Graphics.FillPolygon
method parameter to draw the star. The Graphics.FillPolygon
method fills the interior of a polygon defined by an array of points.
Default color of the star is white. But you might want to change the color to use it for other purposes.
I have used the GraphicsPath
class of GDI+ and AddLine
method of the class to draw the Canada flag center leaf:
let path = new GraphicsPath()
path.StartFigure()
path.AddLine(leafX + 133.f, leafY + 150.0f, leafX + 134.f, leafY + 120.0f)
path.AddLine(leafX + 134.f, leafY + 120.0f, leafX + 110.f, leafY + 123.0f)
.........
.................
path.CloseFigure()
g.DrawPath(Pens.Red, path)
g.FillPath(redBrush, path)
The Graphics
class represents a series of connected lines and curves. Using the Graphics.DrawPath
method, we draw the path to our window and we fill the path with red color through the Graphics.FillPath
method.
Here is other country flag drawing functions prototype:
member MainWindow.Draw_UsaFlag : flagX :float32, flagY :float32, g : System.Drawing.Graphics ->uint
member MainWindow.Draw_GermanyFlag : x :float32, y :float32, g : System.Drawing.Graphics -> uint
member MainWindow.Draw_UkFlag : x :float32, y :float32, g : System.Drawing.Graphics -> uint
member MainWindow.Draw_CanadaFlag : x :float32, y :float32, g : System.Drawing.Graphics -> uint
Finally, we draw all our flags inside the Event_Paint
member function in this way:
this.Draw_BangladeshFlag(20.0f, 10.0f, e.Graphics)
e.Graphics.DrawString("Bangladesh", font, clrText, new PointF(18.0f, 9.0f))
this.Draw_CanadaFlag(300.0f, 10.0f, e.Graphics)
e.Graphics.DrawString("Canada", font, clrText, new PointF(300.0f, 9.0f))
this.Draw_UsaFlag(20.0f, 186.0f, e.Graphics)
e.Graphics.DrawString("United States Of America", font, clrText, new PointF(18.0f, 168.0f))
this.Draw_UkFlag(300.0f, 186.0f, e.Graphics)
e.Graphics.DrawString("United Kingdom", font, clrText, new PointF(300.0f, 168.0f))
this.Draw_GermanyFlag(180.0f, 350.0f, e.Graphics)
e.Graphics.DrawString("Germany", font, clrText, new PointF(18.0f, 352.0f))
Here, we use the Graphics.DrawString
method of GDI+ to draw all the country's name at the top left corner of their flag. 12
sized Arial
is used as font of the country name.
Conclusion
F# is a strongly typed functional programming language. Though it is a functional programming language, object-oriented is also supported as well. And it is fully capable to use the power of .NET. So using the F# language and GDI+ library, you can create various great graphics design since GDI+ is also a powerful graphics library.
Although I have only added six country flag drawing functions, I hope this tip will help you to learn graphics programming with the F# programming language.