I am translating a C# project into F#. While the logic part is easy, I am confused with the GUI part:
public partial class GomokuGUI : Form {
private void GomokuGUI_Load(object sender, EventArgs e)
{
this.Width = 500;
this.Height = 550;
...
this.Paint += new PaintEventHandler(GomokuGUI_Paint);
Graphics gp = this.CreateGraphics();
DrawChessbord(gp);
}
private void GomokuGUI_Paint(object sender, PaintEventArgs e)
{
Graphics gp = e.Graphics;
DrawChessbord(gp);
}
void DrawChessbord(Graphics gp)
{
float w, h;
SolidBrush br = new SolidBrush(linecolor);
Pen p = new Pen(br, frame);
gp.DrawLine(p, 20, 45, this.Width - 25, 45);
...
}
private void Form1_Click(object sender, EventArgs e) {
Graphics gp = this.CreateGraphics();
DrawChess(gp);
...
}
}
Problem:开发者_高级运维 How to write above C# code in F#...Thanks
Note that F# doesn't have any WinForms designer, so if you have some controls in the Form, you'll need to create them manually (alternatively you can design the form in C#, compile it and reference it from F#). You could start with something like this:
type GomokuGUI() as this =
inherit Form(Width = 300, Height = 550)
let DrawChessbord (gp:Graphics) =
let br = new SolidBrush(linecolor)
let p = new Pen(br, frame)
gp.DrawLine(p, 20, 45, this.Width - 25, 45)
// ...
let paintGui (e:PaintEventArgs) =
let gp = e.Graphics
DrawChessbord(gp)
do
this.Paint.Add(paintGui)
this.Click.Add(fun _ ->
let gp = this.CreateGraphics()
DrawChess(gp)
(* ... *) )
It uses a couple of interesting things:
- You can specify some parameters such as
Width
andHeight
in the constructor when calling the base class constructor. - You need to use
as this
in the class declaration, so that you can refer to the class in thedo
code (which is run during construction) - You can use
Add
to register event handler and you can either give it a named function (e.g.patinGui
) or a lambda function if you need to do only some simple call (e.g. handling ofClick
)
Here's another example of using a form but this time with an outside 3D library called Mogre.
type MogreForm() as this =
inherit Form()
let mogrePanel = new System.Windows.Forms.Panel()
// Between Suspend and Resume Layout is normal form Designer Code
do base.SuspendLayout()
mogrePanel.Location <- new System.Drawing.Point(0, 0)
mogrePanel.Name <- "mogrePanel"
mogrePanel.Size <- new System.Drawing.Size(483, 375)
mogrePanel.TabIndex <- 0
base.AutoScaleDimensions <- new System.Drawing.SizeF(6.0f, 13.0f)
base.AutoScaleMode <- System.Windows.Forms.AutoScaleMode.Font
base.ClientSize <- new System.Drawing.Size(483, 375)
base.Controls.Add(mogrePanel)
base.Name <- "MogreForm"
base.Text <- "Simple F# Mogre Form";
base.ResumeLayout(false)
let mogreWin = new OgreWindow(Point(100, 30), mogrePanel.Handle)
this.Disposed.Add(fun _ -> mogreWin.Dispose())
this.Paint.Add(fun _ -> mogreWin.Paint())
Here is the full code if you want to try running it. You will need to download Mogre and reference the Mogre dll. Also since this code pulls resources out of the samples you have to set your projects working directory to "C:\MogreSDK\bin\Debug"
open System
open System.Windows.Forms
open System.Drawing
open Mogre
type OgreWindow(origin, hWnd) =
//-----------------------------------------------------
// 1 enter ogre
//-----------------------------------------------------
let root = new Root()
do //-----------------------------------------------------
// 2 configure resource paths
//-----------------------------------------------------
let cf = new ConfigFile()
cf.Load("resources.cfg", "\t:=", true)
// Go through all sections & settings in the file
let seci = cf.GetSectionIterator()
// Normally we would use the foreach syntax, which enumerates the values, but in this case we need CurrentKey too;
while seci.MoveNext() do
for pair in seci.Current do
ResourceGroupManager.Singleton.AddResourceLocation(pair.Value, pair.Key, seci.CurrentKey)
//-----------------------------------------------------
// 3 Configures the application and creates the window
//-----------------------------------------------------
root.RenderSystem <- root.GetAvailableRenderers() |> Seq.find (fun rs -> rs.Name = "Direct3D9 Rendering Subsystem")
root.RenderSystem.SetConfigOption("Full Screen", "No")
root.RenderSystem.SetConfigOption("Video Mode", "640 x 480 @ 32-bit colour")
root.Initialise(false) |> ignore
let misc = new NameValuePairList()
misc.["externalWindowHandle"] <- hWnd.ToString()
let window = root.CreateRenderWindow("Simple Mogre Form Window", 0u, 0u, false, misc.ReadOnlyInstance)
ResourceGroupManager.Singleton.InitialiseAllResourceGroups()
//-----------------------------------------------------
// 4 Create the SceneManager
//
// ST_GENERIC = octree
// ST_EXTERIOR_CLOSE = simple terrain
// ST_EXTERIOR_FAR = nature terrain (depreciated)
// ST_EXTERIOR_REAL_FAR = paging landscape
// ST_INTERIOR = Quake3 BSP
//-----------------------------------------------------
let sceneMgr = root.CreateSceneManager(SceneType.ST_GENERIC, "SceneMgr")
sceneMgr.AmbientLight <- new ColourValue(0.5f, 0.5f, 0.5f)
//-----------------------------------------------------
// 5 Create the camera
//-----------------------------------------------------
let camera = sceneMgr.CreateCamera("SimpleCamera")
camera.Position <- new Vector3(0.0f, 0.0f, 100.0f)
// Look back along -Z
camera.LookAt(new Vector3(0.0f, 0.0f, -300.0f))
camera.NearClipDistance <- 5.0f
let viewport = window.AddViewport(camera)
viewport.BackgroundColour <- new ColourValue(0.0f, 0.0f, 0.0f, 1.0f)
let ent = sceneMgr.CreateEntity("ogre", "ogrehead.mesh")
let node = sceneMgr.RootSceneNode.CreateChildSceneNode("ogreNode")
node.AttachObject(ent)
member this.Paint() =
root.RenderOneFrame() |> ignore
member this.Dispose() =
if root <> null then
root.Dispose()
type MogreForm() as this =
inherit Form()
let mogrePanel = new System.Windows.Forms.Panel()
// Between Suspend and Resume Layout is normal form Designer Code
do base.SuspendLayout()
mogrePanel.Location <- new System.Drawing.Point(0, 0)
mogrePanel.Name <- "mogrePanel"
mogrePanel.Size <- new System.Drawing.Size(483, 375)
mogrePanel.TabIndex <- 0
base.AutoScaleDimensions <- new System.Drawing.SizeF(6.0f, 13.0f)
base.AutoScaleMode <- System.Windows.Forms.AutoScaleMode.Font
base.ClientSize <- new System.Drawing.Size(483, 375)
base.Controls.Add(mogrePanel)
base.Name <- "MogreForm"
base.Text <- "Simple F# Mogre Form";
base.ResumeLayout(false)
let mogreWin = new OgreWindow(Point(100, 30), mogrePanel.Handle)
this.Disposed.Add(fun _ -> mogreWin.Dispose())
this.Paint.Add(fun _ -> mogreWin.Paint())
let main() =
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(false)
Application.Run(new MogreForm())
[<STAThread>]
do main()
精彩评论