用Go写Windows桌面应用 - 使用窗体设计器

目前来说,用Go写Windows应用还没有非常成熟的设计器,习惯了C#那种强大的IDE,再过来看会觉得一朝回到解放前。而且gform现在的设计思路需要使用者对win32 api非常熟悉,否则用起来会非常难受。吐舌笑脸 这也是我一直在想改善方案的地方,毕竟一个类库要以好用为目标,只是我充满了OO思想的头脑还没有完全适应Go的设计方式,很多以前信手拈来的思路用到Go上就会出现问题,或者就算套上去了也会觉得与语言格格不入。最明显就是在努力了两周之后,我突然发现竟然在模拟类的继承,天!当时就感觉真的需要停下来了,否则按照现在的惯性做出来的东西肯定一塌糊涂。

关于gform这个框架我的思考还在继续进行,在弄清楚到底怎样才是Go的设计模式之后,我相信会对它进行一次大的重构。

好了,现在进入正题,用窗体设计器做界面。原理是还是MFC的老方法,在资源文件中做好对话框设计,然后在运行时attach上去。

打开ResEdit,添加一个对话框,然后在上面放好各种控件。下图中是一个我做的小工具的实际例子。

image

其中,为每个控件都设置一个有意义的ID。比如,上图中“过滤”右边的文本框,ID为“IDC_FILTER”。

保存之后会发现,ResEdit自动生成了一个与资源文件同名的头文件,如下所示。

image

打开这个头文件,发现里面其实只是简单的定义了控件ID的值,如下所示。

image

我们现在新建一个go文件,叫做app.go,把头文件中的常量定义全都复制进来,变成Go的常量定义,比如:

const (
    IDD_DIALOG1  = 104
    IDC_CLOSE= 1006
)

可以看到,对话框的ID是IDD_DIALOG1,好,我们现在可以用gform.NewDialogFromResId来把这个对话框读取出来。

func main() {
    gform.Init()

    mainform := gform.NewDialogFromResId(nil, IDD_DIALOG1)
    mainform.Show()

    gform.RunMainLoop()
}

运行一下看看,怎么样?看到窗体了吧。现在来试试相应按钮的事件,使用gform.AttachPushButton,之后相应OnLBUp(On Left Button Up即当鼠标左键弹起时)。

btnClose = gform.AttachPushButton(mainform, IDC_CLOSE)
btnClose.OnLBUp().Attach(btnClose_OnLBUp)

 

func btnClose_OnLBUp(arg *gform.EventArg) {

//事件响应代码写在这里

}

gform中的事件响应函数很想C#中的委托,每个事件都可以Attach多个事件处理函数,事件激发是会单线程依次调用。而事件响应函数只有一个参数,让我们来看看gform.EventArg的定义。

type EventArg struct {
    sender Controller
    data interface{}
}

sender顾名思义,代表激发事件的控件。data里面附带的就是事件信息,比如,鼠标按键事件,data就是MouseEventData类型,定义如下。

type MouseEventData struct {
    X, Y   int
    Button int
    Wheel  int
}

其他的事件都有自己的事件数据,这里就不一一例举了。Go的interface{}挺好用的,加上它的静态类型检查,很安全、高效。

 

这样就完成了,目前gform支持Label、Button、Combobox、Edit、ListView、ProgressBar(因为我写的小工具仅用到了这几个控件微笑)。之后支持的控件会慢慢变多。

下一篇会讲到如何自定义控件,先秀一下近期正在做的小软件的界面,还远远没有完工,但我自己挺满意的。呵呵

image

posted @ 2012-02-28 22:14  AllenDang  阅读(9446)  评论(23编辑  收藏  举报