Golang绑定VCL组件

govcl

1、现在基本上主体算完成了,还有些绘图相关的函数添加
2、XML创建UI上还未完成,但不影响使用。

项目已经公开。

https://gitee.com/ying32/govcl

目录

项目介绍

1、由于现有第三方的Go UI库不是太宠大就是用的不习惯,或者组件太少。就萌生了自己写一个UI库的相法
Delphi有些许多优秀的VCL组件,不拿来使用太可惜了。所以就索性做了一套。目前支持Win32跟Win64,
只需要带上一个libvcl.dll即可。

2、项目现在支持VCL标准控件中的大部分,足以满足日常操作了,具体见支持的组件列表
事件方面也支持部分,如下:

TGoEvent = (geClick,geClose,geFormClose,geFormCloseQuery,geChange,geupdownClick,geTreeViewChange,geListViewChange,geDblClick,gePaint,geResize,geShow,geMenuChange,geEnter,geExit,gePopup,geBalloonClick,geLinkClick,geExecute,geUpdate,geException,geTimer,geminimize,geRestore,geHide,geKeyDown,geKeyPress,geKeyUp,geMouseDown,geMouseEnter,geMouseLeave,geMouseMove,geMouseUp,geMouseWheel);

重要说明

所有的代码只会存储在OSC的码云中,原因在于go包路径的问题。
至于github上会建一个同名的项目govcl,但不会提交任何代码

使用方法

go get gitee.com/ying32/govcl

package main

import (
   "gitee.com/ying32/govcl/vcl"
)

var (
   mainForm *vcl.TForm
)

func main() {
    vcl.Application.Initialize()
    mainForm = vcl.Application.CreateForm()
    mainForm.SetCaption("Hello")
    mainForm.EnabledMaximize(false)
    mainForm.ScreenCenter()
    vcl.Application.Run()
}

项目中的包说明

  • api
    包含各种类型定义、枚举值、DLL函数申明与重新包装
  • dylib
    仅针对Linux及MacOS,模拟windows下动态调用,需要用到cgo
  • rtl
    包含Delphi中Set类型操作、内存操作等其它函数
  • win
    包含windows下的常量、函数、类型定义
  • xui
    包含一个使用xml创建UI的类

实例类说明

按照Delphi中的Application、 Screen、 Mouse、Clipboard四个类实例是可以直接访问的,不需要释放
其实组件带有Owner参数的一般指定当前组件对应的TForm就好了,这样就不需要手动释放,反之Owner填
写nil则需要手动调用Free,就像其它非组件类的。

支持的组件列表

支持组件和非组件类列表:

TApplication
TForm
TButton
TEdit
TMainMenu
TPopupMenu
TMemo
TCheckBox
TradioButton
TGroupBox
TLabel
TListBox
TComboBox
TPanel
timage
TLinkLabel
TSpeedButton
TSplitter
TradioGroup
TStaticText
TColorBox
TColorListBox
TTrayIcon
TBalloonHint
TCategoryPanelGroup
TOpenDialog
TSaveDialog
TColorDialog
TFontDialog
TPrintDialog
TOpenPictureDialog
TSavePictureDialog
TSaveTextFileDialog
TOpenTextFileDialog
TRichEdit
TTrackBar
timageList
Tupdown
TProgressBar
THotKey
TDateTimePicker
TMonthCalendar
TListView
TTreeView
TStatusBar
TToolBar
TPageControl
TTabSheet
TControl
TActionList
TToolButton
TPaintBox
TTimer

TIcon
TBitmap
TMemoryStream
TFont
TStrings
TStringList
TBrush
TPen
TMenuItem
TListGroups
TPicture
TListColumns
TListItems
TTreeNodes
TListItem
TTreeNode
TScreen
TMouse
TListGroup
TListColumn
TCollectionItem
TStatusPanels
TStatusPanel
TCanvas
TObject
TPngImage
TJPEGImage
TGIFImage
TGIFFrame
tiniFile
TRegistry
TClipboard
TMonitor
TMargins
TList
TGraphic
TComponent

截图


备注

文件名后面带有def的为手动编写

作者信息

by: ying32

代码示例

// govcl project main.go
// go.exe build -i -ldflags="-H windowsgui"
package main

import (
    "fmt"

    "gitee.com/ying32/govcl/vcl"
    "gitee.com/ying32/govcl/vcl/api"
    "gitee.com/ying32/govcl/vcl/rtl"
    "gitee.com/ying32/govcl/vcl/win"
)

var (
    mainForm *vcl.TForm
    trayicon *vcl.TTrayIcon
)

func main() {

    // 异常捕获
    defer func() {
        err := recover()
        if err != nil {
            fmt.Println("Exception: ",err)
            vcl.ShowMessage(err.(error).Error())
        }
    }()

    fmt.Println("main")
    icon := vcl.NewIcon()
    //icon.LoadFromFile(".\\imgs\\0.ico")
    icon.LoadFromresourceID(rtl.MainInstance(), 3)
    defer icon.Free()
    vcl.Application.Initialize()

    vcl.Application.SetonException(func(vcl.IObject,vcl.IObject) {
        fmt.Println("exception.")
    })

    vcl.Application.SetIcon(icon)
    vcl.Application.SetTitle("Hello World!")
    vcl.Application.SetMainFormOnTaskBar(true)
    mainForm = vcl.Application.CreateForm()
    mainForm.SetWidth(600)
    mainForm.SetHeight(400)
    mainForm.SetonClose(func(Sender vcl.IObject,Action uintptr) {
        fmt.Println("close")
    })

    fmt.Println("MainForm ClientRect: ",mainForm.ClientRect())

    mainForm.SetonCloseQuery(func(Sender vcl.IObject,CanClose uintptr) {
        rtl.SetFormCanClose(CanClose,vcl.MessageDlg("是否退出?",api.Mtinformation,api.MbYes,api.MbNo) == vcl.MrYes)
        fmt.Println("OnCloseQuery")
    })

    mainForm.SetCaption(vcl.Application.Title())
    mainForm.EnabledMaximize(false)
    mainForm.SetDoubleBuffered(true)
    mainForm.SetPosition(api.PoScreenCenter)
    mainForm.SetKeyPreview(true)
    mainForm.SetonKeyDown(func(Sender vcl.IObject,Key uintptr,Shift int32) {
        fmt.Println(rtl.InSets(uint32(Shift),api.SsCtrl))
        fmt.Println(rtl.GetKey(Key))
    })

    mainForm.SetonMouseDown(func(sender vcl.IObject,button,shift,x,y int32) {
        fmt.Println("Button:",button == api.MbLeft,",X:",y:",y)
        fmt.Println("OnMouseDown")
    })

    chk := vcl.NewCheckBox(mainForm)
    chk.SetParent(mainForm)
    chk.SetChecked(true)
    chk.SetCaption("测试")
    chk.SetLeft(1)
    chk.SetTop(60)
    chk.SetonClick(func(vcl.IObject) {
        fmt.Println("chk.Checked=",chk.Checked())
    })

    // action
    action := vcl.NewAction(mainForm)
    action.SetCaption("action1")
    action.SetonUpdate(func(sender vcl.IObject) {
        vcl.ActionFromObj(sender).SetEnabled(chk.Checked())
    })
    action.SetonExecute(func(vcl.IObject) {
        fmt.Println("action execute")
    })
    btn := vcl.NewButton(mainForm)
    btn.SetParent(mainForm)
    btn.SetBounds(250, 30, 90, 25)
    btn.SetCaption("action")
    btn.SetAction(action)

    trayicon = vcl.NewTrayIcon(mainForm)
    trayicon.SetIcon(icon)
    trayicon.SetHint(mainForm.Caption())
    trayicon.SetVisible(true)
    trayicon.SetonClick(func(vcl.IObject) {
        trayicon.SetBalloonTitle("test")
        trayicon.SetBalloonTimeout(10000)
        trayicon.SetBalloonHint("我是提示正文啦")
        trayicon.ShowBalloonHint()
        fmt.Println("TrayIcon Click.")
    })

    // img
    img := vcl.NewImage(mainForm)
    img.SetBounds(132, 156, 97)
    img.SetParent(mainForm)
    img.Picture().LoadFromFile(".\\imgs\\1.jpg")
    //img.SetStretch(true)
    img.SetProportional(true)

    // linklabel
    linklbl := vcl.NewLinkLabel(mainForm)
    linklbl.SetAlign(api.AlBottom)
    linklbl.SetCaption("<a href=\"https://github.com/ying32/govcl\">govcl测试链接</a>")
    linklbl.SetParent(mainForm)
    linklbl.SetonLinkClick(func(sender vcl.IObject,link string,linktype int32) {
        fmt.Println("link label: ",link,type: ",linktype)
        rtl.SysOpen(link)
    })

    // menu
    mainMenu := vcl.NewMainMenu(mainForm)
    item := vcl.NewMenuItem(mainForm)
    item.SetCaption("File(&F)")
    mainMenu.Items().Add(item)

    item2 := vcl.NewMenuItem(mainForm)
    item2.SetCaption("MemoryStreamTest")
    item2.SetonClick(func(vcl.IObject) {
        mem := vcl.NewMemoryStream()
        defer mem.Free()
        mem.Write([]byte("测试"))
        mem.SavetoFile("test.txt")

        mem.SetPosition(0)
        n,bs := mem.Read(int32(mem.Size()))
        fmt.Println("n:",n,bs:",bs,str:",string(bs))
    })
    item.Add(item2)

    item2 = vcl.NewMenuItem(mainForm)
    item2.SetCaption("Exit(&E)")
    item2.SetShortCutFromString("Ctrl+Q")
    item2.SetonClick(func(vcl.IObject) {
        mainForm.Close()
    })
    item.Add(item2)

    // mainForm.EnabledMinimize(false)
    // mainForm.EnabledSystemMenu(false)

    button := vcl.NewButton(mainForm)

    button.SetCaption("消息")
    button.SetParent(mainForm)
    button.SetonClick(func(vcl.IObject) {
        fmt.Println("button click")
        vcl.ShowMessage("这是一个消息")
        vcl.Application.MessageBox("Hello!","Message",win.MB_YESNO+win.MB_ICONinformatION)
    })
    button.SetLeft(50)
    button.SetTop(50)
    button.SetAlign(api.AlRight)

    edit := vcl.NewEdit(mainForm)
    edit.SetParent(mainForm)
    edit.SetLeft(1)
    edit.SetTop(30)
    edit.SetTextHint("测试")
    edit.SetonChange(func(vcl.IObject) {
        fmt.Println("edit OnChange")
    })

    button2 := vcl.NewButton(mainForm)
    button2.SetParent(mainForm)
    button2.SetCaption("a")
    button2.SetWidth(100)
    button2.SetHeight(28)
    button2.SetonClick(func(vcl.IObject) {
        fmt.Println("button2 click")

        edit.SetText("Hello!")
        fmt.Println("ScreenWidth:",vcl.Screen.Width(),ScreenHeight:",vcl.Screen.Height())
    })
    button2.SetAlign(api.AlTop)

    combo := vcl.NewComboBox(mainForm)
    combo.SetAlign(api.AlBottom)
    combo.SetParent(mainForm)
    combo.SetText("ffff")
    combo.Items().Add("1")
    combo.Items().Add("2")
    combo.SetItemIndex(0)
    combo.SetonChange(func(vcl.IObject) {
        if combo.ItemIndex() != -1 {
            fmt.Println("combo Change: ",combo.Items().Strings(combo.ItemIndex()))
        }

    })

    page := vcl.NewPageControl(mainForm)
    page.SetParent(mainForm)
    page.SetAlign(api.AlBottom)
    sheet := vcl.NewTabSheet(mainForm)
    sheet.SetPageControl(page)
    sheet.SetCaption("第一页")

    // 需要先将TabSheet设置了父窗口,TListView才可用,不然就会报错
    lv1 := vcl.NewListView(mainForm)
    lv1.SetAlign(api.AlClient)
    lv1.SetParent(sheet)

    lv1.SetViewStyle(api.VsReport)
    lv1.SetRowSelect(true)
    lv1.SetReadOnly(true)
    lv1.SetGridLines(true)
    col := lv1.Columns().Add()
    col.SetCaption("序号")
    col.SetWidth(100)
    col = lv1.Columns().Add()
    col.SetCaption("名称")
    col.SetWidth(200)
    col = lv1.Columns().Add()
    col.SetCaption("内容")
    col.SetWidth(200)
    lv1.SetonClick(func(vcl.IObject) {
        if lv1.ItemIndex() != -1 {
            item := lv1.Selected() // lv1.Items().Item(lv1.ItemIndex())
            fmt.Println(item.Caption(),item.SubItems().Strings(0),item.SubItems().Strings(1))
        }
    })

    lv1.Items().BeginUpdate()
    for i := 1; i <= 50; i++ {
        lstitem := lv1.Items().Add()
        lstitem.SetCaption(fmt.Sprintf("%d",i))
        lstitem.SubItems().Add(fmt.Sprintf("第%d",i))
        lstitem.SubItems().Add(fmt.Sprintf("内容%d",i))
    }
    lv1.Items().EndUpdate()

    sheet = vcl.NewTabSheet(mainForm)
    sheet.SetCaption("第二页")
    sheet.SetPageControl(page)

    tv1 := vcl.NewTreeView(mainForm)
    tv1.SetAutoExpand(true)
    tv1.SetParent(sheet)
    tv1.SetAlign(api.AlClient)
    tv1.SetonClick(func(vcl.IObject) {
        if tv1.SelectionCount() > 0 {
            node := tv1.Selected()
            fmt.Println("text:",node.Text(),index:",node.Index())
        }
    })
    tv1.Items().BeginUpdate()
    node := tv1.Items().AddChild(nil,"首个")
    for i := 1; i <= 50; i++ {
        tv1.Items().AddChild(node,fmt.Sprintf("Node%d",i))
    }
    node = tv1.Items().AddChild(nil,"第二个")
    for i := 1; i <= 50; i++ {
        tv1.Items().AddChild(node,i))
    }
    tv1.Items().EndUpdate()

    fmt.Println("Compoment Count:",mainForm.ComponentCount())
    // mainForm.ScreenCenter()

    vcl.Application.Run()
}

相关文章

什么是Go的接口? 接口可以说是一种类型,可以粗略的理解为他...
1、Golang指针 在介绍Golang指针隐式间接引用前,先简单说下...
1、概述 1.1&#160;Protocol buffers定义 Protocol buffe...
判断文件是否存在,需要用到"os"包中的两个函数: os.Stat(...
1、编译环境 OS :Loongnix-Server Linux release 8.3 CPU指...
1、概述 Golang是一种强类型语言,虽然在代码中经常看到i:=1...