Question

I have an enum:

type Tool = 
    | Rectangle = 0
    | Circle = 1

And a variable to hold a enum value:

let mutable selectedTool : Tool = Tool.Rectangle

I have two buttons:

let btn (location:Point) (size:Size) =
    let bt = new Button()
    do bt.Location <- location
    do bt.Size <- size
    bt
// These badboys right here:
let rectangleButton = btn (Point(0, 0)) (Size(50,50))
let ellipseButton = btn (Point(50, 0)) (Size(50,50))

They each have an event connected to them:

let btnRectEvent = rectangleButton.Click.Add(fun(x) -> selectedTool <-Tool.Rectangle)
let btnElliEvent = ellipseButton.Click.Add(fun(x) -> selectedTool <- Tool.Circle)

I want my events to change the value of the selectedTool variable. Currently, it doesen't work.
I then record my MouseDown event on my drawing area to draw a shape using this event:

let mouseEvent =
    let x = selectedTool
    form.MouseDown
    |> Event.add ( fun (evArgs1) -> 
            if x = Tool.Circle then
                graphics.Graphics.DrawEllipse(whitePen, evArgs1.X, evArgs1.Y, 15, 15)
            else 
                graphics.Graphics.DrawRectangle(whitePen, evArgs1.X, evArgs1.Y, 15, 15)
            form.Refresh())

form is running as follows:

form.Controls.Add(rectangleButton)
form.Controls.Add(ellipseButton)

form.Show()
while form.Created do
    Application.DoEvents()

Bonus Question but not in need of answering:
Is it possible to catch a click event on the button, wait for a mousedown event on the drawing area, place the first corner of my shape, have a preview of the shape when I'm moving my mouse around, and set the second corner on mouseUp, in an not-too-overkill way?

TL;DR bonus question: Can I easily make the rectangledrawing work like in MSPaint?

Was it helpful?

Solution

So I spotted the problem:

when you do

let x = selectedTool
form.MouseDown
|> Event.add ( fun (evArgs1) -> 
    Something goes here

Inside the lambda x won't change. You probably want to either get rid of the let x = ... before the lambda or use a ref cell like this:

let selectedTool  = ref Rectangle

then you assign with

selectedTool := Circle

and get the value with

if (!selectedTool) = Circle

Although a match would be more common - like so

form.MouseDown
|> Event.add ( fun (evArgs1) -> 
    match (!selectedTool) with
    |Circle -> graphics.Graphics.DrawEllipse(whitePen, evArgs1.X, evArgs1.Y, 15, 15)
    |Rectangle -> graphics.Graphics.DrawRectangle(whitePen, evArgs1.X, evArgs1.Y, 15,15)
    form.Refresh())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top