Formsを使ってみる
FlowLayoutPanelを使ってみた。配置だけはうまくいくけど、自動リサイズやウェイトのかけ方が良くわからない。
- scriptrunner.cs
namespace ScriptRunner { using System; using System.Collections.Generic; using System.Windows.Forms; using System.CodeDom.Compiler; using System.Reflection; using System.IO; using System.Text; public class ScriptForm: Form { private TextBox scriptBox; private TextBox resultBox; private TextBox classBox; private ComboBox langBox; private DictionarylangProviders = new Dictionary (); private string items; private StreamToTextBox outRedirector; private StreamToTextBox errorRedirector; private const string InitScript = @"using System; class MainClass { public static void Main(string args) { Console.WriteLine(""Hello World!""); } } "; private const string InitMain = "MainClass"; public ScriptForm(): base() { langProviders["C#"] = new Microsoft.CSharp.CSharpCodeProvider(); langProviders["Visual Basic"] = new Microsoft.VisualBasic.VBCodeProvider(); //langProviders["JScript"] = new Microsoft.JScript.JScriptCodeProvider(); items = new string[langProviders.Count]; langProviders.Keys.CopyTo(items, 0); InitControls(); outRedirector = new StreamToTextBox(resultBox); errorRedirector = new StreamToTextBox(resultBox); } private void InitControls() { FlowLayoutPanel vPanel = new FlowLayoutPanel(); vPanel.Dock = DockStyle.Fill; vPanel.FlowDirection = FlowDirection.TopDown; vPanel.WrapContents = false; vPanel.AutoSize = true; this.Controls.Add(vPanel); langBox = new ComboBox(); langBox.Items.AddRange(items); langBox.SelectedIndex = 0; vPanel.Controls.Add(langBox); scriptBox = new TextBox(); scriptBox.Multiline = true; scriptBox.AutoSize = true; scriptBox.Height = 100; scriptBox.Width = 280; scriptBox.Text = InitScript; scriptBox.ScrollBars = ScrollBars.Vertical; vPanel.Controls.Add(scriptBox); FlowLayoutPanel hPanel = new FlowLayoutPanel(); hPanel.FlowDirection = FlowDirection.LeftToRight; hPanel.WrapContents = false; hPanel.AutoSize = true; vPanel.Controls.Add(hPanel); Label classLabel = new Label(); classLabel.Text = "Main Class: "; hPanel.Controls.Add(classLabel); classBox = new TextBox(); classBox.Text = InitMain; hPanel.Controls.Add(classBox); Button runButton = new Button(); runButton.Text = "Run!"; runButton.Click += delegate(object sender, EventArgs ev) { this.RunScript(); }; hPanel.Controls.Add(runButton); resultBox = new TextBox(); resultBox.Multiline = true; resultBox.AutoSize = true; resultBox.Height = 100; resultBox.Width = 280; resultBox.ScrollBars = ScrollBars.Vertical; vPanel.Controls.Add(resultBox); } private void RunScript() { CodeDomProvider provider = langProviders[items[langBox.SelectedIndex]]; resultBox.Clear(); TextWriter outWriter = Console.Out; TextWriter errorWriter = Console.Error; Console.SetOut(outRedirector); Console.SetError(errorRedirector); try { ExecScript(provider, scriptBox.Text, classBox.Text); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { Console.SetOut(outWriter); Console.SetError(errorWriter); } } private void ExecScript(CodeDomProvider provider, string source, string mainClassName) { CompilerParameters options = new CompilerParameters(); options.GenerateInMemory = true; CompilerResults results = provider.CompileAssemblyFromSource(options, source); Assembly assembly = results.CompiledAssembly; Type type = assembly.GetType(mainClassName); BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding; object parameters = new object{ new string{} }; type.InvokeMember("Main", flags, null, null, parameters); } } public class StreamToTextBox: TextWriter { private TextBox redirectBox; public StreamToTextBox(TextBox redirectBox) { this.redirectBox = redirectBox; } public override Encoding Encoding { get { return Encoding.UTF8; } } public override void Write(char ch) { redirectBox.Text += ch; } } public class MainClass { [STAThread] public static void Main(string args) { Application.Run(new ScriptForm()); } } }
GenericなCollectionは別名前空間のようだ。いまいち使いにくい気もするのだが。。。
delegateも使ってみたが、EventHandlerでもいいような気もしなくはないかな^^;
あとMSBuildもつかってみる。
- Main.proj
(実際はProjectの上にはxml宣言があります。)こちらもドキュメントが少ないのでこんだけ。現状はNAntのほうがずっといい。