├── .gitignore
├── LICENSE
├── README.md
├── app.go
├── button.go
├── declarative
├── button.go
├── control.go
├── interfaces.go
├── label.go
├── lineedit.go
├── listview.go
├── mainwindow.go
└── tabcontrol.go
├── doc
├── resedit.png
└── screenshot1.png
├── eventhandler.go
├── examples
├── basic
│ ├── basic.ico
│ ├── basic.manifest
│ ├── build.bat
│ ├── main.go
│ ├── main.rc
│ ├── mainwindow.go
│ ├── resource.go
│ └── resource.h
├── hello
│ ├── build.bat
│ ├── hello.manifest
│ ├── main.go
│ ├── main.rc
│ └── resource.h
└── tab
│ ├── build.bat
│ ├── main.go
│ ├── main.rc
│ ├── resource.h
│ └── tab.manifest
├── icon.go
├── init.go
├── label.go
├── lineedit.go
├── listview.go
├── mainwindow.go
├── msg.go
├── rect.go
├── tabcontrol.go
└── window.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Lroc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gowi
2 | Gui for golang, UI created by ResEdit
3 |
4 | # Code
5 |
6 | import (
7 | "github.com/sumorf/gowi"
8 | . "github.com/sumorf/gowi/declarative"
9 | "fmt"
10 | )
11 |
12 | type MyMainWindow struct {
13 | *gowi.MainWindow
14 | label1 *gowi.Label
15 | button1 *gowi.Button
16 | }
17 |
18 | func main() {
19 | app := gowi.New()
20 |
21 | mw := new(MyMainWindow)
22 |
23 | m := MainWindow{
24 | AssignTo:&mw.MainWindow,
25 | ID:1000,
26 | Controls:[]Control{
27 | Button{
28 | AssignTo:&mw.button1,
29 | ID:1001,
30 | OnClicked:func() {
31 | fmt.Println("Button clicked.")
32 | mw.SetWindowText("Clicked")
33 | },
34 | },
35 | },
36 | }
37 | m.Create()
38 | m.Show()
39 |
40 | mw.SetWindowText("Hello")
41 | app.Run()
42 | }
43 |
44 | # Screenshots
45 |
46 | How to design:
47 |
48 | 
49 |
50 | Run:
51 |
52 | 
53 |
--------------------------------------------------------------------------------
/app.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "github.com/sumorf/win"
5 | )
6 |
7 | var hInst win.HINSTANCE
8 |
9 | // Get application instance handle
10 | func GetAppInstance() win.HINSTANCE {
11 | return hInst
12 | }
13 |
14 | type Application struct {
15 | }
16 |
17 | // Run the main message loop
18 | func (e *Application) Run() int {
19 | var msg win.MSG
20 |
21 | for {
22 | switch win.GetMessage(&msg, 0, 0, 0) {
23 | case 0:
24 | return int(msg.WParam)
25 | case -1:
26 | return -1
27 | }
28 |
29 | win.TranslateMessage(&msg)
30 | win.DispatchMessage(&msg)
31 | }
32 |
33 | return 0
34 | }
35 |
36 | func New() *Application {
37 | app := new(Application)
38 | return app
39 | }
40 |
--------------------------------------------------------------------------------
/button.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "fmt"
5 |
6 | "bitbucket.org/CaryLorrk/gosig"
7 | )
8 |
9 | type Button struct {
10 | WindowBase
11 | OnClicked func()
12 | Clicked *gosig.Signal
13 | }
14 |
15 | func (w *Button) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
16 | fmt.Println("Button.WndProc")
17 | w.Clicked.Emit()
18 | return 0
19 | }
20 |
21 | func NewButton(window MainWindow, id uintptr) *Button {
22 | c := new(Button)
23 | c.InitWindow(window, id)
24 |
25 | //c.Clicked, _ = gosig.NewSignal(func() {})
26 | c.Clicked, _ = gosig.NewSignal(func() {})
27 | //window.Connect(b1.Clicked, w.OnButton1Clicked)
28 | c.Clicked.Connect(func() {
29 | if c.OnClicked != nil {
30 | c.OnClicked()
31 | }
32 | })
33 |
34 | fmt.Printf("RegMsg h=%v\n", c.Handle())
35 | RegMsgHandler(c)
36 |
37 | return c
38 | }
39 |
--------------------------------------------------------------------------------
/declarative/button.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | )
6 |
7 | type Button struct {
8 | AssignTo **gowi.Button
9 | ID uintptr
10 | Text Property
11 | Enabled Property
12 | Visible Property
13 | OnClicked gowi.EventHandler
14 | }
15 |
16 | func (b Button) Create(window *MainWindow) {
17 | win := *window.AssignTo
18 | c := gowi.NewButton(*win, b.ID)
19 | if b.Text != nil {
20 | c.SetWindowText(b.Text.(string))
21 | }
22 | if b.Enabled != nil {
23 | c.SetEnabled(b.Enabled.(bool))
24 | }
25 | if b.Visible != nil {
26 | c.SetVisible(b.Visible.(bool))
27 | }
28 | c.OnClicked = b.OnClicked
29 | if b.AssignTo != nil {
30 | *b.AssignTo = c
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/declarative/control.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | type Control interface {
4 | Create(window *MainWindow)
5 | }
6 |
--------------------------------------------------------------------------------
/declarative/interfaces.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | type Property interface{}
4 |
--------------------------------------------------------------------------------
/declarative/label.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | )
6 |
7 | type Label struct {
8 | AssignTo **gowi.Label
9 | ID uintptr
10 | Text Property
11 | }
12 |
13 | func (l Label) Create(window *MainWindow) {
14 | win := *window.AssignTo
15 | c := gowi.NewLabel(*win, l.ID)
16 | if l.Text != nil {
17 | c.SetWindowText(l.Text.(string))
18 | }
19 | if l.AssignTo != nil {
20 | *l.AssignTo = c
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/declarative/lineedit.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | )
6 |
7 | type LineEdit struct {
8 | AssignTo **gowi.LineEdit
9 | ID uintptr
10 | Text Property
11 | }
12 |
13 | func (l LineEdit) Create(window *MainWindow) {
14 | win := *window.AssignTo
15 | c := gowi.NewLineEdit(*win, l.ID)
16 | if l.Text != nil {
17 | c.SetWindowText(l.Text.(string))
18 | }
19 | if l.AssignTo != nil {
20 | *l.AssignTo = c
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/declarative/listview.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | )
6 |
7 | type ListViewHeader struct {
8 | }
9 |
10 | type ListView struct {
11 | AssignTo **gowi.ListView
12 | ID uintptr
13 | }
14 |
15 | func (l ListView) Create(window *MainWindow) {
16 | win := *window.AssignTo
17 | c := gowi.NewListView(*win, l.ID)
18 | if l.AssignTo != nil {
19 | *l.AssignTo = c
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/declarative/mainwindow.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | "github.com/sumorf/win"
6 | )
7 |
8 | type MainWindow struct {
9 | AssignTo **gowi.MainWindow
10 | ID uintptr
11 | Icon string
12 | Controls []Control
13 | }
14 |
15 | func (this *MainWindow) Create() {
16 | w := &gowi.MainWindow{}
17 | w.Create(this.ID)
18 |
19 | if this.AssignTo != nil {
20 | *this.AssignTo = w
21 | }
22 |
23 | for _, c := range this.Controls {
24 | c.Create(this)
25 | }
26 | }
27 |
28 | func (this *MainWindow) Show() {
29 | // Center in the owner window
30 | w := *this.AssignTo
31 |
32 | //fmt.Printf("aaaa\n")
33 | sWidth := win.GetSystemMetrics(win.SM_CXFULLSCREEN)
34 | sHeight := win.GetSystemMetrics(win.SM_CYFULLSCREEN)
35 | if sWidth != 0 && sHeight != 0 {
36 | rect := w.Bounds()
37 | rect.X = (int(sWidth) / 2) - (rect.Width / 2)
38 | rect.Y = (int(sHeight) / 2) - (rect.Height / 2)
39 | w.SetBounds(rect)
40 | }
41 |
42 | w.Show()
43 | }
44 |
--------------------------------------------------------------------------------
/declarative/tabcontrol.go:
--------------------------------------------------------------------------------
1 | package declarative
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | )
6 |
7 | type TabPage struct {
8 | }
9 |
10 | type TabControl struct {
11 | AssignTo **gowi.TabControl
12 | ID uintptr
13 | Pages []TabPage
14 | }
15 |
16 | func (l TabControl) Create(window *MainWindow) {
17 | win := *window.AssignTo
18 | c := gowi.NewTabControl(*win, l.ID)
19 | if l.AssignTo != nil {
20 | *l.AssignTo = c
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/doc/resedit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/f0cii/gowi/db711580c0da2285603510063aa09f0d7dbb3752/doc/resedit.png
--------------------------------------------------------------------------------
/doc/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/f0cii/gowi/db711580c0da2285603510063aa09f0d7dbb3752/doc/screenshot1.png
--------------------------------------------------------------------------------
/eventhandler.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | type EventHandler func()
4 |
--------------------------------------------------------------------------------
/examples/basic/basic.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/f0cii/gowi/db711580c0da2285603510063aa09f0d7dbb3752/examples/basic/basic.ico
--------------------------------------------------------------------------------
/examples/basic/basic.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/basic/build.bat:
--------------------------------------------------------------------------------
1 | @if exist "main-res.syso" (
2 | @del "main-res.syso"
3 | )
4 |
5 | windres -o main-res.syso main.rc
6 | go build
7 |
8 | pause
9 |
--------------------------------------------------------------------------------
/examples/basic/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/sumorf/gowi"
7 | )
8 |
9 | func main() {
10 | fmt.Println("init")
11 |
12 | app := gowi.New()
13 |
14 | w := NewMainWindow()
15 | w.SetWindowText("app example")
16 | w.Show()
17 |
18 | app.Run()
19 | }
20 |
--------------------------------------------------------------------------------
/examples/basic/main.rc:
--------------------------------------------------------------------------------
1 | // Generated by ResEdit 1.6.6
2 | // Copyright (C) 2006-2015
3 | // http://www.resedit.net
4 |
5 | #include
6 | #include
7 | #include
8 | #include "resource.h"
9 |
10 |
11 |
12 |
13 | //
14 | // Dialog resources
15 | //
16 | LANGUAGE LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED
17 | IDD_MAIN DIALOGEX 0, 0, 186, 95
18 | STYLE DS_CENTER | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
19 | CAPTION "HELLO"
20 | FONT 8, "MS Shell Dlg", 0, 0, 1
21 | {
22 | PUSHBUTTON "\x5F00\x59CB", IDD_BUTTON1, 63, 34, 54, 20, BS_CENTER | BS_VCENTER, WS_EX_LEFT
23 | LTEXT "\x4EB2", IDD_LABEL1, 20, 15, 25, 12, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
24 | }
25 |
26 |
27 |
28 | //
29 | // Version Information resources
30 | //
31 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
32 | 1 VERSIONINFO
33 | FILEVERSION 0,0,0,0
34 | PRODUCTVERSION 0,0,0,0
35 | FILEOS VOS__WINDOWS32
36 | FILETYPE VFT_APP
37 | FILESUBTYPE VFT2_UNKNOWN
38 | FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PATCHED | VS_FF_PRIVATEBUILD | VS_FF_INFOINFERRED | VS_FF_SPECIALBUILD
39 | FILEFLAGS 0
40 | {
41 | BLOCK "StringFileInfo"
42 | {
43 | BLOCK "000003A8"
44 | {
45 | VALUE "CompanyName", ""
46 | VALUE "FileDescription", ""
47 | VALUE "FileVersion", ""
48 | VALUE "InternalName", ""
49 | VALUE "LegalCopyright", ""
50 | VALUE "LegalTrademarks", ""
51 | VALUE "OriginalFilename", ""
52 | VALUE "ProductName", ""
53 | VALUE "ProductVersion", ""
54 | VALUE "Comments", ""
55 | }
56 | }
57 | BLOCK "VarFileInfo"
58 | {
59 | VALUE "Translation", 0x0000, 0x03A8
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/examples/basic/mainwindow.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/sumorf/gowi"
7 | )
8 |
9 | type MainWindow struct {
10 | gowi.MainWindow
11 | button1 *gowi.Button
12 | label1 *gowi.Label
13 | }
14 |
15 | func NewMainWindow() *MainWindow {
16 | w := &MainWindow{}
17 |
18 | w.Create(IDD_MAIN)
19 |
20 | b1 := gowi.NewButton(w.MainWindow, IDD_BUTTON1)
21 | l1 := gowi.NewLabel(w.MainWindow, IDD_LABEL1)
22 |
23 | b1.OnClicked = w.OnButton1Clicked
24 |
25 | l1.SetWindowText("Hello!")
26 |
27 | w.button1 = b1
28 | w.label1 = l1
29 |
30 | return w
31 | }
32 |
33 | func (w *MainWindow) OnButton1Clicked() {
34 | fmt.Println("OnButton1Clicked")
35 | text := w.button1.GetWindowText()
36 | if text == "Start" {
37 | w.button1.SetWindowText("Stop")
38 | } else {
39 | w.button1.SetWindowText("Start")
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/examples/basic/resource.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var IDD_MAIN uintptr = 100
4 | var IDD_BUTTON1 uintptr = 101
5 | var IDD_LABEL1 uintptr = 102
6 |
--------------------------------------------------------------------------------
/examples/basic/resource.h:
--------------------------------------------------------------------------------
1 | #ifndef IDC_STATIC
2 | #define IDC_STATIC (-1)
3 | #endif
4 |
5 | #define IDD_MAIN 100
6 | #define IDD_BUTTON1 101
7 | #define IDD_LABEL1 102
8 |
--------------------------------------------------------------------------------
/examples/hello/build.bat:
--------------------------------------------------------------------------------
1 | @if exist "main-res.syso" (
2 | @del "main-res.syso"
3 | )
4 |
5 | windres -o main-res.syso main.rc
6 | go build
7 |
8 | pause
9 |
--------------------------------------------------------------------------------
/examples/hello/hello.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/hello/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/sumorf/gowi"
7 | . "github.com/sumorf/gowi/declarative"
8 | )
9 |
10 | type MyMainWindow struct {
11 | *gowi.MainWindow
12 | label1 *gowi.Label
13 | lineedit1 *gowi.LineEdit
14 | button1 *gowi.Button
15 | }
16 |
17 | func main() {
18 | app := gowi.New()
19 |
20 | mw := new(MyMainWindow)
21 |
22 | m := MainWindow{
23 | AssignTo: &mw.MainWindow,
24 | ID: 100,
25 | Controls: []Control{
26 | Label{
27 | AssignTo: &mw.label1,
28 | ID: 1002,
29 | Text: "????",
30 | },
31 | LineEdit{
32 | AssignTo: &mw.lineedit1,
33 | ID: 40004,
34 | Text: "abc",
35 | },
36 | Button{
37 | AssignTo: &mw.button1,
38 | ID: 1001,
39 | Text: "Click Me!",
40 | OnClicked: func() {
41 | fmt.Println("Button clicked.")
42 | //ll := mw.lineedit1.GetWindowText()
43 | //fmt.Printf("ll=%v\n", ll)
44 | },
45 | },
46 | },
47 | }
48 | m.Create()
49 | m.Show()
50 |
51 | mw.SetWindowText("Hello!")
52 | app.Run()
53 | }
54 |
--------------------------------------------------------------------------------
/examples/hello/main.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/f0cii/gowi/db711580c0da2285603510063aa09f0d7dbb3752/examples/hello/main.rc
--------------------------------------------------------------------------------
/examples/hello/resource.h:
--------------------------------------------------------------------------------
1 | #ifndef IDC_STATIC
2 | #define IDC_STATIC (-1)
3 | #endif
4 |
5 | #define ID_DLG1 100
6 | #define ID_BUTTON1 1001
7 | #define ID_LABEL1 1002
8 | #define IDC_LIST1 40000
9 | #define IDC_PROGRESS1 40001
10 | #define IDC_COMBO1 40002
11 | #define IDC_DATETIMEPICKER1 40003
12 | #define IDC_RADIO1 40004
13 | #define IDC_RADIO2 40005
14 | #define IDC_REBAR1 40006
15 | #define IDC_TAB1 40007
16 | #define IDC_TREE1 40008
17 | #define IDC_EDIT1 40009
18 |
--------------------------------------------------------------------------------
/examples/tab/build.bat:
--------------------------------------------------------------------------------
1 | @if exist "main-res.syso" (
2 | @del "main-res.syso"
3 | )
4 |
5 | windres -o main-res.syso main.rc
6 | go build
7 |
8 | pause
9 |
--------------------------------------------------------------------------------
/examples/tab/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/sumorf/gowi"
5 | . "github.com/sumorf/gowi/declarative"
6 | )
7 |
8 | type MyMainWindow struct {
9 | *gowi.MainWindow
10 | tab1 *gowi.TabControl
11 | }
12 |
13 | func main() {
14 | app := gowi.New()
15 |
16 | mw := &MyMainWindow{}
17 |
18 | m := MainWindow{
19 | AssignTo: &mw.MainWindow,
20 | ID: 108,
21 | Controls: []Control{
22 | TabControl{
23 | AssignTo: &mw.tab1,
24 | ID: 40000,
25 | },
26 | },
27 | }
28 |
29 | m.Create()
30 | m.Show()
31 |
32 | app.Run()
33 | }
34 |
--------------------------------------------------------------------------------
/examples/tab/main.rc:
--------------------------------------------------------------------------------
1 | // Generated by ResEdit 1.6.6
2 | // Copyright (C) 2006-2015
3 | // http://www.resedit.net
4 |
5 | #include
6 | #include
7 | #include
8 | #include "resource.h"
9 |
10 |
11 |
12 |
13 | //
14 | // Dialog resources
15 | //
16 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
17 | IDD_PAGE2 DIALOG 0, 0, 186, 95
18 | STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_POPUP | WS_SYSMENU
19 | FONT 8, "Ms Shell Dlg"
20 | {
21 | LTEXT "Page 2", IDC_STATIC, 45, 36, 24, 9, SS_LEFT, WS_EX_LEFT
22 | }
23 |
24 |
25 |
26 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
27 | IDD_PAGE1 DIALOG 0, 0, 186, 95
28 | STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_POPUP | WS_SYSMENU
29 | FONT 8, "Ms Shell Dlg"
30 | {
31 | LTEXT "Page 1", IDC_STATIC, 50, 39, 24, 9, SS_LEFT, WS_EX_LEFT
32 | }
33 |
34 |
35 |
36 | LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
37 | IDD_DIALOG1 DIALOG 0, 0, 269, 148
38 | STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
39 | CAPTION "Tab"
40 | FONT 8, "Ms Shell Dlg"
41 | {
42 | CONTROL "", IDC_TAB1, WC_TABCONTROL, 0, 7, 7, 251, 131, WS_EX_LEFT
43 | }
44 |
--------------------------------------------------------------------------------
/examples/tab/resource.h:
--------------------------------------------------------------------------------
1 | #ifndef IDC_STATIC
2 | #define IDC_STATIC (-1)
3 | #endif
4 |
5 | #define IDD_DIALOG1 108
6 | #define IDD_PAGE1 109
7 | #define IDD_PAGE2 110
8 | #define IDC_TAB1 40000
9 |
--------------------------------------------------------------------------------
/examples/tab/tab.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/icon.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "errors"
5 | "image"
6 | "path/filepath"
7 | "syscall"
8 | "unsafe"
9 |
10 | "github.com/sumorf/win"
11 | )
12 |
13 | // Icon is a bitmap that supports transparency and combining multiple
14 | // variants of an image in different resolutions.
15 | type Icon struct {
16 | hIcon win.HICON
17 | isStock bool
18 | }
19 |
20 | func IconApplication() *Icon {
21 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_APPLICATION)), true}
22 | }
23 |
24 | func IconError() *Icon {
25 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_ERROR)), true}
26 | }
27 |
28 | func IconQuestion() *Icon {
29 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_QUESTION)), true}
30 | }
31 |
32 | func IconWarning() *Icon {
33 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_WARNING)), true}
34 | }
35 |
36 | func IconInformation() *Icon {
37 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_INFORMATION)), true}
38 | }
39 |
40 | func IconWinLogo() *Icon {
41 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_WINLOGO)), true}
42 | }
43 |
44 | func IconShield() *Icon {
45 | return &Icon{win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_SHIELD)), true}
46 | }
47 |
48 | // NewIconFromFile returns a new Icon, using the specified icon image file.
49 | func NewIconFromFile(filePath string) (*Icon, error) {
50 | absFilePath, err := filepath.Abs(filePath)
51 | if err != nil {
52 | return nil, err
53 | }
54 |
55 | hIcon := win.HICON(win.LoadImage(
56 | 0,
57 | syscall.StringToUTF16Ptr(absFilePath),
58 | win.IMAGE_ICON,
59 | 0,
60 | 0,
61 | win.LR_DEFAULTSIZE|win.LR_LOADFROMFILE))
62 | if hIcon == 0 {
63 | return nil, errors.New("LoadImage")
64 | }
65 |
66 | return &Icon{hIcon: hIcon}, nil
67 | }
68 |
69 | // NewIconFromResource returns a new Icon, using the specified icon resource.
70 | func NewIconFromResource(resName string) (ic *Icon, err error) {
71 | hInst := win.GetModuleHandle(nil)
72 | if hInst == 0 {
73 | err = errors.New("GetModuleHandle")
74 | return
75 | }
76 | if hIcon := win.LoadIcon(hInst, syscall.StringToUTF16Ptr(resName)); hIcon == 0 {
77 | err = errors.New("LoadIcon")
78 | } else {
79 | ic = &Icon{hIcon: hIcon}
80 | }
81 | return
82 | }
83 |
84 | func NewIconFromImage(im image.Image) (ic *Icon, err error) {
85 | hIcon, err := createAlphaCursorOrIconFromImage(im, image.Pt(0, 0), true)
86 | if err != nil {
87 | return nil, err
88 | }
89 | return &Icon{hIcon: hIcon}, nil
90 | }
91 |
92 | // Dispose releases the operating system resources associated with the Icon.
93 | func (i *Icon) Dispose() error {
94 | if i.isStock || i.hIcon == 0 {
95 | return nil
96 | }
97 |
98 | if !win.DestroyIcon(i.hIcon) {
99 | return errors.New("DestroyIcon")
100 | }
101 |
102 | i.hIcon = 0
103 |
104 | return nil
105 | }
106 |
107 | func (i *Icon) Destroy() bool {
108 | return win.DestroyIcon(i.hIcon)
109 | }
110 |
111 | func (i *Icon) Handle() win.HICON {
112 | return i.hIcon
113 | }
114 |
115 | // create an Alpha Icon or Cursor from an Image
116 | // http://support.microsoft.com/kb/318876
117 | func createAlphaCursorOrIconFromImage(im image.Image, hotspot image.Point, fIcon bool) (win.HICON, error) {
118 | hBitmap, err := hBitmapFromImage(im)
119 | if err != nil {
120 | return 0, err
121 | }
122 | defer win.DeleteObject(win.HGDIOBJ(hBitmap))
123 |
124 | // Create an empty mask bitmap.
125 | hMonoBitmap := win.CreateBitmap(int32(im.Bounds().Dx()), int32(im.Bounds().Dy()), 1, 1, nil)
126 | if hMonoBitmap == 0 {
127 | return 0, errors.New("CreateBitmap failed")
128 | }
129 | defer win.DeleteObject(win.HGDIOBJ(hMonoBitmap))
130 |
131 | var ii win.ICONINFO
132 | if fIcon {
133 | ii.FIcon = win.TRUE
134 | }
135 | ii.XHotspot = uint32(hotspot.X)
136 | ii.YHotspot = uint32(hotspot.Y)
137 | ii.HbmMask = hMonoBitmap
138 | ii.HbmColor = hBitmap
139 |
140 | // Create the alpha cursor with the alpha DIB section.
141 | hIconOrCursor := win.CreateIconIndirect(&ii)
142 |
143 | return hIconOrCursor, nil
144 | }
145 |
146 | func hBitmapFromImage(im image.Image) (win.HBITMAP, error) {
147 | var bi win.BITMAPV5HEADER
148 | bi.BiSize = uint32(unsafe.Sizeof(bi))
149 | bi.BiWidth = int32(im.Bounds().Dx())
150 | bi.BiHeight = -int32(im.Bounds().Dy())
151 | bi.BiPlanes = 1
152 | bi.BiBitCount = 32
153 | bi.BiCompression = win.BI_BITFIELDS
154 | // The following mask specification specifies a supported 32 BPP
155 | // alpha format for Windows XP.
156 | bi.BV4RedMask = 0x00FF0000
157 | bi.BV4GreenMask = 0x0000FF00
158 | bi.BV4BlueMask = 0x000000FF
159 | bi.BV4AlphaMask = 0xFF000000
160 |
161 | hdc := win.GetDC(0)
162 | defer win.ReleaseDC(0, hdc)
163 |
164 | var lpBits unsafe.Pointer
165 |
166 | // Create the DIB section with an alpha channel.
167 | hBitmap := win.CreateDIBSection(hdc, &bi.BITMAPINFOHEADER, win.DIB_RGB_COLORS, &lpBits, 0, 0)
168 | switch hBitmap {
169 | case 0, win.ERROR_INVALID_PARAMETER:
170 | return 0, errors.New("CreateDIBSection failed")
171 | }
172 |
173 | // Fill the image
174 | bitmap_array := (*[1 << 30]byte)(unsafe.Pointer(lpBits))
175 | i := 0
176 | for y := im.Bounds().Min.Y; y != im.Bounds().Max.Y; y++ {
177 | for x := im.Bounds().Min.X; x != im.Bounds().Max.X; x++ {
178 | r, g, b, a := im.At(x, y).RGBA()
179 | bitmap_array[i+3] = byte(a >> 8)
180 | bitmap_array[i+2] = byte(r >> 8)
181 | bitmap_array[i+1] = byte(g >> 8)
182 | bitmap_array[i+0] = byte(b >> 8)
183 | i += 4
184 | }
185 | }
186 |
187 | return hBitmap, nil
188 | }
189 |
--------------------------------------------------------------------------------
/init.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "github.com/sumorf/win"
5 | )
6 |
7 | func init() {
8 | hInst := win.GetModuleHandle(nil)
9 | if hInst == 0 {
10 | panic("GetModuleHandle")
11 | }
12 | gWindowRegistry = make(map[win.HWND]Window)
13 | }
14 |
--------------------------------------------------------------------------------
/label.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type Label struct {
8 | WindowBase
9 | }
10 |
11 | func (w *Label) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
12 | fmt.Println("Label.WndProc")
13 | return 0
14 | }
15 |
16 | func NewLabel(window MainWindow, id uintptr) *Label {
17 | c := new(Label)
18 | c.InitWindow(window, id)
19 |
20 | fmt.Printf("RegMsg h=%v\n", c.Handle())
21 | RegMsgHandler(c)
22 |
23 | return c
24 | }
25 |
--------------------------------------------------------------------------------
/lineedit.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type LineEdit struct {
8 | WindowBase
9 | }
10 |
11 | func (e *LineEdit) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
12 | fmt.Println("LineEdit.WndProc")
13 | return 0
14 | }
15 |
16 | func NewLineEdit(window MainWindow, id uintptr) *LineEdit {
17 | c := new(LineEdit)
18 | c.InitWindow(window, id)
19 |
20 | fmt.Printf("RegMsg h=%v\n", c.Handle())
21 | RegMsgHandler(c)
22 |
23 | return c
24 | }
25 |
--------------------------------------------------------------------------------
/listview.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | type ListView struct {
4 | WindowBase
5 | }
6 |
7 | func (e *ListView) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
8 | return 0
9 | }
10 |
11 | func NewListView(window MainWindow, id uintptr) *ListView {
12 | c := new(ListView)
13 | c.InitWindow(window, id)
14 |
15 | RegMsgHandler(c)
16 |
17 | return c
18 | }
19 |
--------------------------------------------------------------------------------
/mainwindow.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "fmt"
5 | "syscall"
6 |
7 | "bitbucket.org/CaryLorrk/gosig"
8 | "github.com/sumorf/win"
9 | )
10 |
11 | var defaultDialogProcPtr = syscall.NewCallback(defaultDialogProc)
12 |
13 | // Dialog class
14 | type MainWindow struct {
15 | WindowBase
16 | }
17 |
18 | func (w *MainWindow) AsWindowBase() *MainWindow {
19 | return w
20 | }
21 |
22 | func (w *MainWindow) Create(idd uintptr) {
23 | if idd == 0 {
24 | panic("Create MainWindow FAIL.")
25 | }
26 | w.idd = idd
27 |
28 | w.hwnd = win.CreateDialogParam(hInst, win.MAKEINTRESOURCE(w.idd), 0, defaultDialogProcPtr, 0)
29 | fmt.Printf("Create window hwnd=%v\n", w.hwnd)
30 | if w.hwnd == win.HWND(0) {
31 | fmt.Printf("Create window fail.[%v]\n", idd)
32 | }
33 | }
34 |
35 | func (w *MainWindow) Connect(sig *gosig.Signal, slot interface{}) {
36 | sig.Connect(slot)
37 | }
38 |
39 | func defaultDialogProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
40 | switch msg {
41 | case win.WM_COMMAND:
42 | fmt.Printf("WM_COMMAND msg=%v\n", msg)
43 | if lParam != 0 { //Reflect message to control
44 | h := win.HWND(lParam)
45 | fmt.Printf("WM_COMMAND h=%v\n", h)
46 | if handler := GetMsgHandler(h); handler != nil {
47 | fmt.Println("WM_COMMAND handler.WndProc")
48 | ret := handler.WndProc(msg, wParam, lParam)
49 | if ret != 0 {
50 | //win.SetWindowLong(hwnd, win.DWL_MSGRESULT, int32(ret))
51 | fmt.Println("WM_COMMAND TRUE")
52 | return win.TRUE
53 | }
54 | }
55 | }
56 | fmt.Println("WM_COMMAND DONE")
57 | return 0
58 | case win.WM_CLOSE:
59 | win.DestroyWindow(hwnd)
60 | return 0
61 | case win.WM_DESTROY:
62 | win.PostQuitMessage(0)
63 | return 1
64 | }
65 |
66 | return 0
67 | }
68 |
--------------------------------------------------------------------------------
/msg.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "github.com/sumorf/win"
5 | )
6 |
7 | var gWindowRegistry map[win.HWND]Window
8 |
9 | func RegMsgHandler(window Window) {
10 | gWindowRegistry[window.Handle()] = window
11 | }
12 |
13 | func UnRegMsgHandler(hwnd win.HWND) {
14 | delete(gWindowRegistry, hwnd)
15 | }
16 |
17 | func GetMsgHandler(hwnd win.HWND) Window {
18 | if widget, isExists := gWindowRegistry[hwnd]; isExists {
19 | return widget
20 | }
21 |
22 | return nil
23 | }
24 |
--------------------------------------------------------------------------------
/rect.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "github.com/sumorf/win"
5 | )
6 |
7 | type Rect struct {
8 | X, Y, Width, Height int
9 | }
10 |
11 | func rectFromRECT(r win.RECT) Rect {
12 | return Rect{
13 | X: int(r.Left),
14 | Y: int(r.Top),
15 | Width: int(r.Right - r.Left),
16 | Height: int(r.Bottom - r.Top),
17 | }
18 | }
19 |
20 | func (r Rect) ToRECT() win.RECT {
21 | return win.RECT{
22 | int32(r.X),
23 | int32(r.Y),
24 | int32(r.X + r.Width),
25 | int32(r.Y + r.Height),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tabcontrol.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | type TabControl struct {
4 | WindowBase
5 | }
6 |
7 | func (w *TabControl) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
8 | return 0
9 | }
10 |
11 | func NewTabControl(window MainWindow, id uintptr) *TabControl {
12 | c := new(TabControl)
13 | c.InitWindow(window, id)
14 |
15 | RegMsgHandler(c)
16 |
17 | return c
18 | }
19 |
--------------------------------------------------------------------------------
/window.go:
--------------------------------------------------------------------------------
1 | package gowi
2 |
3 | import (
4 | "fmt"
5 | "syscall"
6 | "unsafe"
7 |
8 | "github.com/sumorf/win"
9 | )
10 |
11 | // Window
12 | type Window interface {
13 | AsWindowBase() *WindowBase
14 |
15 | InitWindow(window MainWindow, id uintptr)
16 |
17 | Handle() win.HWND
18 |
19 | GetWindowText() string
20 |
21 | SetWindowText(title string)
22 |
23 | SetIcon(iconType int, icon *Icon)
24 |
25 | Show()
26 |
27 | Hide()
28 |
29 | ShowMinimized()
30 |
31 | ShowMaximized()
32 |
33 | ShowFullScreen()
34 |
35 | ShowNormal()
36 |
37 | IsEnabled() bool
38 |
39 | IsVisible() bool
40 |
41 | SetVisible(value bool)
42 |
43 | SetEnabled(b bool)
44 |
45 | SetDisabled(disable bool)
46 |
47 | SetFocus()
48 |
49 | Bounds() Rect
50 |
51 | SetBounds(value Rect)
52 |
53 | Close()
54 |
55 | WndProc(msg uint32, wparam, lparam uintptr) uintptr
56 | }
57 |
58 | // WindowBase
59 | type WindowBase struct {
60 | hwnd win.HWND
61 | parent win.HWND
62 | idd uintptr
63 | }
64 |
65 | func (w *WindowBase) AsWindowBase() *WindowBase {
66 | return w
67 | }
68 |
69 | // Set window resource Idd
70 | func (w *WindowBase) InitWindow(window MainWindow, id uintptr) {
71 | w.idd = id
72 | h := window.AsWindowBase().Handle()
73 | fmt.Printf("h=%v\n", h)
74 | w.hwnd = win.GetDlgItem(h, id)
75 | fmt.Printf("w.hwnd=%v\n", w.hwnd)
76 | }
77 |
78 | func (w *WindowBase) Handle() win.HWND {
79 | return w.hwnd
80 | }
81 |
82 | func (w *WindowBase) SetWindowText(title string) {
83 | fmt.Printf("SetCaption hwnd: %v, %s\n", w.hwnd, title)
84 | win.SetWindowText(w.hwnd, title)
85 | }
86 |
87 | func (w *WindowBase) GetWindowText() string {
88 | textLength := win.SendMessage(w.hwnd, win.WM_GETTEXTLENGTH, 0, 0)
89 | buf := make([]uint16, textLength+1)
90 | win.SendMessage(w.hwnd, win.WM_GETTEXT, uintptr(textLength+1), uintptr(unsafe.Pointer(&buf[0])))
91 | return syscall.UTF16ToString(buf)
92 | }
93 |
94 | // IconType: 1 - ICON_BIG; 0 - ICON_SMALL
95 | func (w *WindowBase) SetIcon(iconType int, icon *Icon) {
96 | if iconType > 1 {
97 | panic("IconType is invalid")
98 | }
99 |
100 | win.SendMessage(w.hwnd, win.WM_SETICON, uintptr(iconType), uintptr(icon.Handle()))
101 | }
102 |
103 | func (w *WindowBase) Show() {
104 | win.ShowWindow(w.hwnd, win.SW_SHOW)
105 | }
106 |
107 | func (w *WindowBase) Hide() {
108 | win.ShowWindow(w.hwnd, win.SW_HIDE)
109 | }
110 |
111 | func (w *WindowBase) ShowMinimized() {
112 | win.ShowWindow(w.hwnd, win.SW_MINIMIZE)
113 | }
114 |
115 | func (w *WindowBase) ShowMaximized() {
116 | win.ShowWindow(w.hwnd, win.SW_MAXIMIZE)
117 | }
118 |
119 | func (w *WindowBase) ShowFullScreen() {
120 | win.ShowWindow(w.hwnd, win.SW_SHOWMAXIMIZED)
121 | }
122 |
123 | func (w *WindowBase) ShowNormal() {
124 | win.ShowWindow(w.hwnd, win.SW_SHOWNORMAL)
125 | }
126 |
127 | func (w *WindowBase) IsEnabled() bool {
128 | return win.IsWindowEnabled(w.hwnd)
129 | }
130 |
131 | func (w *WindowBase) IsVisible() bool {
132 | return win.IsWindowVisible(w.hwnd)
133 | }
134 |
135 | func (w *WindowBase) SetVisible(value bool) {
136 | var cmd int32
137 | if value {
138 | cmd = win.SW_SHOW
139 | } else {
140 | cmd = win.SW_HIDE
141 | }
142 | win.ShowWindow(w.hwnd, cmd)
143 | }
144 |
145 | func (w *WindowBase) SetEnabled(b bool) {
146 | win.EnableWindow(w.hwnd, b)
147 | }
148 |
149 | func (w *WindowBase) SetDisabled(disable bool) {
150 | win.EnableWindow(w.hwnd, !disable)
151 | }
152 |
153 | func (w *WindowBase) Close() {
154 | win.SendMessage(w.hwnd, win.WM_CLOSE, 0, 0)
155 | }
156 |
157 | func (w *WindowBase) SetFocus() {
158 | win.SetFocus(w.hwnd)
159 | }
160 |
161 | func (w *WindowBase) Bounds() Rect {
162 | var rect win.RECT
163 | win.GetWindowRect(w.hwnd, &rect)
164 | return rectFromRECT(rect)
165 | }
166 |
167 | func (w *WindowBase) SetBounds(value Rect) {
168 | win.MoveWindow(w.hwnd, int32(value.X), int32(value.Y), int32(value.Width), int32(value.Height), true)
169 | }
170 |
171 | func (w *WindowBase) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
172 | fmt.Println("WidgetBase.WndProc")
173 | return uintptr(0)
174 | }
175 |
--------------------------------------------------------------------------------