wiki.php 用Markdown写wiki是一种什么样的体验?

IL写窗体程序的流程.md

最后更新于 2019-10-06 15:00:40

这是一篇旧文档

我们写的第一个IL程序就是控制台的“你好宇宙”,第二个IL程序是一个进程剿灭。
虽然它们都是能运行得很好的程序,但基本上它们不是没什么用,就是与用户的交互性很差。
传统WINDOWS编程上的观念就是程序=窗体。
今天来教大家写窗体!!!

其实窗体程序的写法与控制台基本相同,唯一不同的在于窗体会执行一个无限的窗体消息循环,如果用户不关闭窗体,则程序不会结束。当然,在C++中写窗体消息处理非常的麻烦,而在.NET中FR框架会帮助我们进行窗体消息的处理。

下面的IL代码可以执行创建消息以及对窗体的图标和指针属性进行的操作,具体说明在代码后面。

f.il 文件代码:

/* 创建窗体程序 GUI */

.assembly extern mscorlib {
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
.assembly extern System.Windows.Forms {
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
.assembly myGUIapp {
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.ver 1:0:0:0
}
.subsystem 2

.method static void Main() {
.entrypoint
.maxstack 2
.locals init (class [System.Windows.Forms]System.Windows.Forms.Form)

// 创建并存储一个窗体对象
newobj instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()
stloc.0

// 设置窗体的标签文本
ldloc.0
ldstr "哇哈~"
callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)

// 再来一个好玩的吧!设置窗体图标为 鼠标的手型指针
ldloc.0
ldc.i4.s 45
call class [System.Drawing]System.Drawing.Icon [System.Drawing]System.Drawing.Icon::FromHandle(native int)
//newobj instance void [System.Drawing]System.Drawing.Icon::.ctor(native int) //与上相同
callvirt instance void [System.Windows.Forms]System.Windows.Forms.Form::set_Icon(class [System.Drawing]System.Drawing.Icon)
// 设置窗体指针(沙漏),基本是一样的...
ldloc.0
ldc.i4.s 43
newobj instance void [System.Windows.Forms]System.Windows.Forms.Cursor::.ctor(native int)
callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Cursor(class [System.Windows.Forms]System.Windows.Forms.Cursor)

// 执行内部窗体消息循环
ldloc.0
call void [System.Windows.Forms]System.Windows.Forms.Application::Run(class [System.Windows.Forms]System.Windows.Forms.Form)

ret
}

能省就省就是我的原则,所以在本段代码中我只使用了一个临时变量,用以存储窗体实例。
如果要用代码来解释,那么上面的代码可以用下面的VB代码来解释:

Shared Sub Main()
    Dim f As New System.Windows.Forms.Form() '创建并存储实例
    f.Text = "哇哈~" '设置窗体标签
    f.Icon = System.Drawing.Icon.FormHandle(45) '这句在VB中其实是错误的,如果想要通过运行请设置为 f.Icon = Icon.FormHandle(New IntPtr(45))
    f.Cursor = New System.Windows.Forms.Cursor(45) '同上的错误
    System.Windows.Forms.Application.Run(f) '执行消息循环
End Sub

我们来解读我们自己写得更加简略的IL代码:
首先通过 newobj 指令创建一个类型实例,存储到变量中。
然后加载变量,加载字符,推送到变量的实例函数中执行。(注意:在.NET程序中的属性概念在底层处理上与VB及C#完全不同,比如你设置文本 f.text = "" 时,在底部调用的其实是一个函数 f.set_text(string) ,而并不是直接调用一个字段,所以我们在推送字符的时候调用的是一个函数。)
下面是设置窗体的图标,我们通过 Icon.FormHandle 方法从系统的图标堆指针中获取一个图标实例,指针45就是我们系统中的鼠标手型指针。在IL中,整数型数值可以直接转换为指针数值,所以不需要经过转换。
当然,设置真正的鼠标指针的方法和上面的差不多,不多赘述了。
最后,就是使用 Application.Run 方法来自动进行窗体循环。