This repository has been archived by the owner on Mar 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FormEmitter.cs
186 lines (155 loc) · 7.45 KB
/
FormEmitter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
using Microsoft.VisualBasic;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.IO;
namespace VBA_Export
{
public class FormEmitter : IDisposable
{
public VBCodeProvider Provider { get; } = new VBCodeProvider();
public string Name { get; private set; }
CodeDomSerializer serializer = new CodeDomSerializer();
DesignerSerializationManager manager = new DesignerSerializationManager();
List<IDisposable> disposables = new List<IDisposable>();
// https://stackoverflow.com/questions/59529839/hosting-windows-forms-designer-serialize-designer-at-runtime-and-generate-c-sh
public FormEmitter(string name)
{
this.Name = name;
// Create empty Namespace
var frmNameSpace = new CodeNamespace();
// Create class definition for Form
FormType = new CodeTypeDeclaration(name) { Attributes = MemberAttributes.Public };
FormType.IsPartial = true;
FormType.BaseTypes.Add(new CodeTypeReference(typeof(System.Windows.Forms.Form)));
// Create InitializeComponent method definition
InitializeComponentMethod = new CodeMemberMethod() { Name = "InitializeComponent", Attributes = MemberAttributes.Private };
InitializeComponentMethod.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.Diagnostics.DebuggerStepThroughAttribute))));
FormType.Members.Add(InitializeComponentMethod);
frmNameSpace.Types.Add(FormType);
unit.Namespaces.Add(frmNameSpace);
// Create session for designer serialization
disposables.Add(manager.CreateSession());
CallMethod(new CodeThisReferenceExpression(), "SuspendLayout");
}
public void EmitButton(string name, string text, Rectangle rect)
{
InitControl(name, "Button");
SetProperty(name, "Text", text);
SetProperty(name, "Location", rect.Location);
SetProperty(name, "Size", rect.Size);
}
public void EmitTextBox(string name, Rectangle rect)
{
InitControl(name, "TextBox");
SetProperty(name, "Location", rect.Location);
SetProperty(name, "Size", rect.Size);
}
public void EmitComboBox(string name, Rectangle rect)
{
InitControl(name, "ComboBox");
SetProperty(name, "Location", rect.Location);
SetProperty(name, "Size", rect.Size);
}
public void EmitLabel(string name, string text, Rectangle rect, Font font)
{
InitControl(name, "Label");
SetProperty(name, "Text", text);
SetProperty(name, "Location", rect.Location);
SetProperty(name, "Size", rect.Size);
SetProperty(name, "AutoSize", true);
SetProperty(name, "Font", font);
}
public void EmitFormProperties(Size size)
{
// Insert Comment to mark start of control initialization
AppendStatement(new CodeCommentStatement(""));
AppendStatement(new CodeCommentStatement(" " + Name));
AppendStatement(new CodeCommentStatement(""));
SetProperty(new CodeThisReferenceExpression(), "Name", Name);
SetProperty(new CodeThisReferenceExpression(), "Text", Name);
SetProperty(new CodeThisReferenceExpression(), "ClientSize", size);
SetProperty(new CodeThisReferenceExpression(), "AutoScaleMode", System.Windows.Forms.AutoScaleMode.Font);
SetProperty(new CodeThisReferenceExpression(), "AutoScaleDimensions", new SizeF(4f, 13f));
CallMethod(new CodeThisReferenceExpression(), "ResumeLayout");
}
#region Internal Code Generation
#region Core
CodeCompileUnit unit = new CodeCompileUnit();
CodeTypeDeclaration FormType;
CodeMemberMethod InitializeComponentMethod;
private void AppendStatement(CodeStatement statement)
{
InitializeComponentMethod.Statements.Add(statement);
}
private void CreateVar(string name, string typeName)
{
var field = new CodeMemberField(new CodeTypeReference(typeName), name) { Attributes = MemberAttributes.FamilyAndAssembly };
// http://www.dotnetframework.org/default.aspx/Dotnetfx_Win7_3@5@1/Dotnetfx_Win7_3@5@1/3@5@1/DEVDIV/depot/DevDiv/releases/whidbey/NetFXspW7/ndp/fx/src/xsp/System/Web/Compilation/BaseTemplateCodeDomTreeGenerator@cs/2/BaseTemplateCodeDomTreeGenerator@cs
field.UserData["WithEvents"] = true;
FormType.Members.Add(field);
}
#endregion
private void InitControl(string name, string typeName)
{
// Create Variable in type
CreateVar(name, typeName);
// Insert Comment to mark start of control initialization
AppendStatement(new CodeCommentStatement(""));
AppendStatement(new CodeCommentStatement(" " + name));
AppendStatement(new CodeCommentStatement(""));
// Create instance of variable
AppendStatement(new CodeAssignStatement(new CodeVariableReferenceExpression(name), new CodeObjectCreateExpression(new CodeTypeReference(typeName))));
// Set property "Name" to name
SetProperty(name, "Name", name);
// Add control to form controls
CallMethod(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Controls"), "Add", new[] { new CodeVariableReferenceExpression(name) });
}
#region CallMethod
private void CallMethod(CodeExpression targetObject, string methodName, params CodeExpression[] parameters)
{
AppendStatement(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(targetObject, methodName), parameters)));
}
#endregion
#region SetProperty
private void SetProperty(string varName, string propName, object value)
{
SetProperty(new CodeVariableReferenceExpression(varName), propName, value);
}
private void SetProperty(CodeExpression targetObject, string propName, object value)
{
if (value.GetType().IsPrimitive || value.GetType() == typeof(string))
SetProperty(targetObject, propName, new CodePrimitiveExpression(value));
else
SetProperty(targetObject, propName, (CodeExpression)serializer.Serialize(manager, value));
}
private void SetProperty(CodeExpression targetObject, string propName, CodeExpression value)
{
AppendStatement(new CodeAssignStatement(new CodePropertyReferenceExpression(targetObject, propName), value));
}
#endregion
#endregion
public override string ToString()
{
string buffer = "";
using (var writer = new StringWriter())
{
Provider.GenerateCodeFromCompileUnit(unit, writer, new CodeGeneratorOptions());
buffer += writer.ToString();
}
return buffer;
}
public void Dispose()
{
foreach (IDisposable item in disposables)
try
{
item.Dispose();
}
catch { }
}
}
}