{"id":2626,"date":"2018-12-31T12:29:02","date_gmt":"2018-12-31T04:29:02","guid":{"rendered":"https:\/\/damogame.cn:15443\/wordpress\/?p=2626"},"modified":"2018-12-31T12:29:02","modified_gmt":"2018-12-31T04:29:02","slug":"go%e5%ae%9e%e6%88%98-%e4%bd%bf%e7%94%a8golang%e5%bc%80%e5%8f%91windows-gui%e6%a1%8c%e9%9d%a2%e7%a8%8b%e5%ba%8flxn-walk","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/2626","title":{"rendered":"Go\u5b9e\u6218&#8211;\u4f7f\u7528golang\u5f00\u53d1Windows Gui\u684c\u9762\u7a0b\u5e8f(lxn\/walk)"},"content":{"rendered":"<div class=\"article-header-box\">\n<div class=\"article-header\">\n<div class=\"article-title-box\"><\/div>\n<div class=\"article-info-box\">\n<div class=\"article-bar-top\">\n<div class=\"tags-box space\">\u00a0\u7248\u6743\u58f0\u660e\uff1a\u672c\u6587\u4e3a\u535a\u4e3b\u539f\u521b\u6587\u7ae0\uff0c\u672a\u7ecf\u535a\u4e3b\u5141\u8bb8\u4e0d\u5f97\u8f6c\u8f7d\u3002 https:\/\/blog.csdn.net\/wangshubo1989\/article\/details\/77949252<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<article class=\"baidu_pl\">\n<div id=\"article_content\" class=\"article_content clearfix csdn-tracking-statistics\" data-pid=\"blog\" data-mod=\"popu_307\" data-dsm=\"post\">\n<div id=\"content_views\" class=\"markdown_views\">\n<p>\u751f\u547d\u4e0d\u6b62\uff0c\u7ee7\u7eed go go go!!!<\/p>\n<p>golang\u5b98\u65b9\u5e76\u6ca1\u6709\u63d0\u4f9bWindows gui\u5e93\uff0c\u4f46\u662f\u4eca\u5929\u8fd8\u662f\u8981\u8ddf\u5927\u5bb6\u5206\u4eab\u4e00\u4e0b\u4f7f\u7528golang\u5f00\u53d1Windows\u684c\u9762\u7a0b\u5e8f\uff0c\u5f53\u7136\u53c8\u662f\u9762\u5411github\u7f16\u7a0b\u4e86\u3002<\/p>\n<p>\u77e5\u4e4e\u4e0a\u6709\u4e00\u4e2a\u95ee\u7b54\uff1a<br \/>\n<a href=\"https:\/\/www.zhihu.com\/question\/22483719\" target=\"_blank\" rel=\"nofollow noopener\">golang\u4e3a\u4ec0\u4e48\u6ca1\u6709\u5b98\u65b9\u7684gui\u5305\uff1f<\/a><\/p>\n<p>\u8fd9\u91cc\uff0c\u4e3b\u8981\u4f7f\u7528\u7b2c\u4e09\u65b9\u5e93lxn\/walk\uff0c\u8fdb\u884cWindows GUI\u7f16\u7a0b\u3002<\/p>\n<h3 id=\"lxnwalk\"><a name=\"t0\"><\/a><strong>lxn\/walk<\/strong><\/h3>\n<p><strong>github\u5730\u5740\uff1a<\/strong><br \/>\n<a href=\"https:\/\/github.com\/lxn\/walk\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/github.com\/lxn\/walk<\/a><\/p>\n<p><strong>star:<\/strong><br \/>\n2018<\/p>\n<p><strong>\u63cf\u8ff0\uff1a<\/strong><br \/>\nA Windows GUI toolkit for the Go Programming Language<\/p>\n<p><strong>\u83b7\u53d6\uff1a<\/strong><\/p>\n<pre class=\"prettyprint\"><code class=\"hljs cs has-numbering\">go <span class=\"hljs-keyword\">get<\/span> github.com\/lxn\/walk<\/code><\/pre>\n<ul class=\"pre-numbering\">\n<li>1<\/li>\n<\/ul>\n<p><strong>\u4f8b\u5b50\uff1a<\/strong><\/p>\n<p>main.go<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n    \"strings\"\r\n)\r\n\r\nfunc main() {\r\n    var inTE, outTE *walk.TextEdit\r\n\r\n    MainWindow{\r\n        Title:   \"SCREAMO\",\r\n        MinSize: Size{600, 400},\r\n        Layout:  VBox{},\r\n        Children: []Widget{\r\n            HSplitter{\r\n                Children: []Widget{\r\n                    TextEdit{AssignTo: &amp;inTE},\r\n                    TextEdit{AssignTo: &amp;outTE, ReadOnly: true},\r\n                },\r\n            },\r\n            PushButton{\r\n                Text: \"SCREAM\",\r\n                OnClicked: func() {\r\n                    outTE.SetText(strings.ToUpper(inTE.Text()))\r\n                },\r\n            },\r\n        },\r\n    }.Run()\r\n}<\/pre>\n<p>go build\u751f\u6210go_windows_gui.exe\u3002<\/p>\n<p>go_windows_gui.exe.manifest<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\r\n    &lt;assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"&gt;\r\n        &lt;assemblyIdentity version=\"1.0.0.0\" processorArchitecture=\"*\" name=\"SomeFunkyNameHere\" type=\"win32\"\/&gt;\r\n        &lt;dependency&gt;\r\n            &lt;dependentAssembly&gt;\r\n                &lt;assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.Common-Controls\" version=\"6.0.0.0\" processorArchitecture=\"*\" publicKeyToken=\"6595b64144ccf1df\" language=\"*\"\/&gt;\r\n            &lt;\/dependentAssembly&gt;\r\n        &lt;\/dependency&gt;\r\n    &lt;\/assembly&gt;<\/pre>\n<p>\u8fd0\u884c\u7ed3\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202033606?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<h3 id=\"\u4ec0\u4e48\u662fmanifest\"><a name=\"t1\"><\/a><strong>\u4ec0\u4e48\u662fmanifest<\/strong><\/h3>\n<p>\u4e0a\u9762\u63d0\u5230\u4e86manifest\uff0c\u8fd9\u662f\u5e72\u4ec0\u4e48\u7684\u5462\uff1f<\/p>\n<p><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa375365(v=vs.85).aspx\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa375365(v=vs.85).aspx<\/a><\/p>\n<p>\u4ecb\u7ecd\uff1a<br \/>\nManifests are XML files that accompany and describe side-by-side assemblies or isolated applications. Manifests uniquely identify the assembly through the assembly\u2019s assemblyIdentity element. They contain information used for binding and activation, such as COM classes, interfaces, and type libraries, that has traditionally been stored in the registry. Manifests also specify the files that make up the assembly and may include Windows classes if the assembly author wants them to be versioned. Side-by-side assemblies are not registered on the system, but are available to applications and other assemblies on the system that specify dependencies in manifest files.<\/p>\n<p>\u662f\u4e00\u79cdxml\u6587\u4ef6\uff0c\u6807\u660e\u6240\u4f9d\u8d56\u7684side-by-side\u7ec4\u5efa\u3002<\/p>\n<p>\u5982\u679c\u7528VS\u5f00\u53d1\uff0c\u53ef\u4ee5Set\u901a\u8fc7porperty-&gt;configuration properties-&gt;linker-&gt;manifest file-&gt;Generate manifest To Yes\u6765\u81ea\u52a8\u521b\u5efamanifest\u6765\u6307\u5b9a\u7cfb\u7edf\u7684\u548cCRT\u7684assembly\u7248\u672c\u3002<\/p>\n<p><strong>\u8be6\u89e3<\/strong><br \/>\n\u89c2\u5bdf\u4e0a\u9762\u7684manifest\u6587\u4ef6\uff1a<\/p>\n<pre class=\"prettyprint\"><code class=\"hljs xml has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&lt;xml&gt;\u8fd9\u662fxml\u58f0\u660e\uff1a\r\n\r\n\u7248\u672c\u53f7----&lt;?xml version=\"1.0\"?&gt;\u3002\r\n\u8fd9\u662f\u5fc5\u9009\u9879\u3002 \u5c3d\u7ba1\u4ee5\u540e\u7684 XML \u7248\u672c\u53ef\u80fd\u4f1a\u66f4\u6539\u8be5\u6570\u5b57\uff0c\u4f46\u662f 1.0 \u662f\u5f53\u524d\u7684\u7248\u672c\u3002\r\n\r\n\u7f16\u7801\u58f0\u660e------&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\u8fd9\u662f\u53ef\u9009\u9879\u3002 \u5982\u679c\u4f7f\u7528\u7f16\u7801\u58f0\u660e\uff0c\u5fc5\u987b\u7d27\u63a5\u5728 XML \u58f0\u660e\u7684\u7248\u672c\u4fe1\u606f\u4e4b\u540e\uff0c\u5e76\u4e14\u5fc5\u987b\u5305\u542b\u4ee3\u8868\u73b0\u6709\u5b57\u7b26\u7f16\u7801\u7684\u503c\u3002\r\n\r\nstandalone\u8868\u793a\u8be5xml\u662f\u4e0d\u662f\u72ec\u7acb\u7684\uff0c\u5982\u679c\u662fyes\uff0c\u5219\u8868\u793a\u8fd9\u4e2aXML\u6587\u6863\u65f6\u72ec\u7acb\u7684\uff0c\u4e0d\u80fd\u5f15\u7528\u5916\u90e8\u7684DTD\u89c4\u8303\u6587\u4ef6\uff1b\u5982\u679c\u662fno\uff0c\u5219\u8be5XML\u6587\u6863\u4e0d\u662f\u72ec\u7acb\u7684\uff0c\u8868\u793a\u53ef\u4ee5\u7528\u5916\u90e8\u7684DTD\u89c4\u8303\u6587\u6863\u3002\r\n\r\n<\/pre>\n<p>&lt;dependency&gt;\u8fd9\u4e00\u90e8\u5206\u6307\u660e\u4e86\u5176\u4f9d\u8d56\u4e8e\u4e00\u4e2a\u5e93\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&lt;pre\u00a0class=\"prettyprint\"&gt;&lt;code\u00a0class=\"hljs\u00a0haskell\u00a0has-numbering\"&gt;&lt;assemblyIdentity&gt;\u5c5e\u6027\u91cc\u9762\u8fd8\u5206\u522b\u662f\uff1a\r\ntype----\u7cfb\u7edf\u7c7b\u578b\uff0c\r\nversion----\u7248\u672c\u53f7\uff0c\r\nprocessorArchitecture----\u5e73\u53f0\u73af\u5883\uff0c\r\npublicKeyToken----\u516c\u5319&lt;\/code\u00a0class=\"hljs\u00a0haskell\u00a0has-numbering\"&gt;&lt;\/pre\u00a0class=\"prettyprint\"&gt;<\/pre>\n<pre class=\"prettyprint\"><code class=\"hljs xml has-numbering\"><\/code><\/pre>\n<pre class=\"prettyprint\"><code class=\"hljs haskell has-numbering\"><\/code><\/pre>\n<h3 id=\"\u5e94\u7528\"><a name=\"t2\"><\/a><strong>\u5e94\u7528<\/strong><\/h3>\n<h4 id=\"\u505a\u4e00\u4e2a\u5de8\u4e11\u65e0\u6bd4\u7684\u767b\u5f55\u6846\">\u505a\u4e00\u4e2a\u5de8\u4e11\u65e0\u6bd4\u7684\u767b\u5f55\u6846<\/h4>\n<p>\u8fd9\u91cc\u7528\u5230\u4e86LineEdit\u3001LineEdit\u63a7\u4ef6<\/p>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n)\r\n\r\nfunc main() {\r\n    var usernameTE, passwordTE *walk.LineEdit\r\n    MainWindow{\r\n        Title:   \"\u767b\u5f55\",\r\n        MinSize: Size{270, 290},\r\n        Layout:  VBox{},\r\n        Children: []Widget{\r\n            Composite{\r\n                Layout: Grid{Columns: 2, Spacing: 10},\r\n                Children: []Widget{\r\n                    VSplitter{\r\n                        Children: []Widget{\r\n                            Label{\r\n                                Text: \"\u7528\u6237\u540d\",\r\n                            },\r\n                        },\r\n                    },\r\n                    VSplitter{\r\n                        Children: []Widget{\r\n                            LineEdit{\r\n                                MinSize:  Size{160, 0},\r\n                                AssignTo: &amp;usernameTE,\r\n                            },\r\n                        },\r\n                    },\r\n                    VSplitter{\r\n                        Children: []Widget{\r\n                            Label{MaxSize: Size{160, 40},\r\n                                Text: \"\u5bc6\u7801\",\r\n                            },\r\n                        },\r\n                    },\r\n                    VSplitter{\r\n                        Children: []Widget{\r\n                            LineEdit{\r\n                                MinSize:  Size{160, 0},\r\n                                AssignTo: &amp;passwordTE,\r\n                            },\r\n                        },\r\n                    },\r\n                },\r\n            },\r\n\r\n            PushButton{\r\n                Text:    \"\u767b\u5f55\",\r\n                MinSize: Size{120, 50},\r\n                OnClicked: func() {\r\n                    if usernameTE.Text() == \"\" {\r\n                        var tmp walk.Form\r\n                        walk.MsgBox(tmp, \"\u7528\u6237\u540d\u4e3a\u7a7a\", \"\", walk.MsgBoxIconInformation)\r\n                        return\r\n                    }\r\n                    if passwordTE.Text() == \"\" {\r\n                        var tmp walk.Form\r\n                        walk.MsgBox(tmp, \"\u5bc6\u7801\u4e3a\u7a7a\", \"\", walk.MsgBoxIconInformation)\r\n                        return\r\n                    }\r\n                },\r\n            },\r\n        },\r\n    }.Run()\r\n}<\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<p>\u6548\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202057742?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<h4 id=\"tableview\u7684\u4f7f\u7528\">TableView\u7684\u4f7f\u7528<\/h4>\n<p>\u8fd9\u91cc\u4e3b\u8981\u4f7f\u7528\u7684\u662fTableView\u63a7\u4ef6\uff0c\u4ee3\u7801\u53c2\u8003github\uff1a<\/p>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"fmt\"\r\n    \"sort\"\r\n\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n)\r\n\r\ntype Condom struct {\r\n    Index   int\r\n    Name    string\r\n    Price   int\r\n    checked bool\r\n}\r\n\r\ntype CondomModel struct {\r\n    walk.TableModelBase\r\n    walk.SorterBase\r\n    sortColumn int\r\n    sortOrder  walk.SortOrder\r\n    items      []*Condom\r\n}\r\n\r\nfunc (m *CondomModel) RowCount() int {\r\n    return len(m.items)\r\n}\r\n\r\nfunc (m *CondomModel) Value(row, col int) interface{} {\r\n    item := m.items[row]\r\n\r\n    switch col {\r\n    case 0:\r\n        return item.Index\r\n    case 1:\r\n        return item.Name\r\n    case 2:\r\n        return item.Price\r\n    }\r\n    panic(\"unexpected col\")\r\n}\r\n\r\nfunc (m *CondomModel) Checked(row int) bool {\r\n    return m.items[row].checked\r\n}\r\n\r\nfunc (m *CondomModel) SetChecked(row int, checked bool) error {\r\n    m.items[row].checked = checked\r\n    return nil\r\n}\r\n\r\nfunc (m *CondomModel) Sort(col int, order walk.SortOrder) error {\r\n    m.sortColumn, m.sortOrder = col, order\r\n\r\n    sort.Stable(m)\r\n\r\n    return m.SorterBase.Sort(col, order)\r\n}\r\n\r\nfunc (m *CondomModel) Len() int {\r\n    return len(m.items)\r\n}\r\n\r\nfunc (m *CondomModel) Less(i, j int) bool {\r\n    a, b := m.items[i], m.items[j]\r\n\r\n    c := func(ls bool) bool {\r\n        if m.sortOrder == walk.SortAscending {\r\n            return ls\r\n        }\r\n\r\n        return !ls\r\n    }\r\n\r\n    switch m.sortColumn {\r\n    case 0:\r\n        return c(a.Index &lt; b.Index)\r\n    case 1:\r\n        return c(a.Name &lt; b.Name)\r\n    case 2:\r\n        return c(a.Price &lt; b.Price)\r\n    }\r\n\r\n    panic(\"unreachable\")\r\n}\r\n\r\nfunc (m *CondomModel) Swap(i, j int) {\r\n    m.items[i], m.items[j] = m.items[j], m.items[i]\r\n}\r\n\r\nfunc NewCondomModel() *CondomModel {\r\n    m := new(CondomModel)\r\n    m.items = make([]*Condom, 3)\r\n\r\n    m.items[0] = &amp;Condom{\r\n        Index: 0,\r\n        Name:  \"\u675c\u857e\u65af\",\r\n        Price: 20,\r\n    }\r\n\r\n    m.items[1] = &amp;Condom{\r\n        Index: 1,\r\n        Name:  \"\u6770\u58eb\u90a6\",\r\n        Price: 18,\r\n    }\r\n\r\n    m.items[2] = &amp;Condom{\r\n        Index: 2,\r\n        Name:  \"\u5188\u672c\",\r\n        Price: 19,\r\n    }\r\n\r\n    return m\r\n}\r\n\r\ntype CondomMainWindow struct {\r\n    *walk.MainWindow\r\n    model *CondomModel\r\n    tv    *walk.TableView\r\n}\r\n\r\nfunc main() {\r\n    mw := &amp;CondomMainWindow{model: NewCondomModel()}\r\n\r\n    MainWindow{\r\n        AssignTo: &amp;mw.MainWindow,\r\n        Title:    \"Condom\u5c55\u793a\",\r\n        Size:     Size{800, 600},\r\n        Layout:   VBox{},\r\n        Children: []Widget{\r\n            Composite{\r\n                Layout: HBox{MarginsZero: true},\r\n                Children: []Widget{\r\n                    HSpacer{},\r\n                    PushButton{\r\n                        Text: \"Add\",\r\n                        OnClicked: func() {\r\n                            mw.model.items = append(mw.model.items, &amp;Condom{\r\n                                Index: mw.model.Len() + 1,\r\n                                Name:  \"\u7b2c\u516d\u611f\",\r\n                                Price: mw.model.Len() * 5,\r\n                            })\r\n                            mw.model.PublishRowsReset()\r\n                            mw.tv.SetSelectedIndexes([]int{})\r\n                        },\r\n                    },\r\n                    PushButton{\r\n                        Text: \"Delete\",\r\n                        OnClicked: func() {\r\n                            items := []*Condom{}\r\n                            remove := mw.tv.SelectedIndexes()\r\n                            for i, x := range mw.model.items {\r\n                                remove_ok := false\r\n                                for _, j := range remove {\r\n                                    if i == j {\r\n                                        remove_ok = true\r\n                                    }\r\n                                }\r\n                                if !remove_ok {\r\n                                    items = append(items, x)\r\n                                }\r\n                            }\r\n                            mw.model.items = items\r\n                            mw.model.PublishRowsReset()\r\n                            mw.tv.SetSelectedIndexes([]int{})\r\n                        },\r\n                    },\r\n                    PushButton{\r\n                        Text: \"ExecChecked\",\r\n                        OnClicked: func() {\r\n                            for _, x := range mw.model.items {\r\n                                if x.checked {\r\n                                    fmt.Printf(\"checked: %v\\n\", x)\r\n                                }\r\n                            }\r\n                            fmt.Println()\r\n                        },\r\n                    },\r\n                    PushButton{\r\n                        Text: \"AddPriceChecked\",\r\n                        OnClicked: func() {\r\n                            for i, x := range mw.model.items {\r\n                                if x.checked {\r\n                                    x.Price++\r\n                                    mw.model.PublishRowChanged(i)\r\n                                }\r\n                            }\r\n                        },\r\n                    },\r\n                },\r\n            },\r\n            Composite{\r\n                Layout: VBox{},\r\n                ContextMenuItems: []MenuItem{\r\n                    Action{\r\n                        Text:        \"I&amp;nfo\",\r\n                        OnTriggered: mw.tv_ItemActivated,\r\n                    },\r\n                    Action{\r\n                        Text: \"E&amp;xit\",\r\n                        OnTriggered: func() {\r\n                            mw.Close()\r\n                        },\r\n                    },\r\n                },\r\n                Children: []Widget{\r\n                    TableView{\r\n                        AssignTo:         &amp;mw.tv,\r\n                        CheckBoxes:       true,\r\n                        ColumnsOrderable: true,\r\n                        MultiSelection:   true,\r\n                        Columns: []TableViewColumn{\r\n                            {Title: \"\u7f16\u53f7\"},\r\n                            {Title: \"\u540d\u79f0\"},\r\n                            {Title: \"\u4ef7\u683c\"},\r\n                        },\r\n                        Model: mw.model,\r\n                        OnCurrentIndexChanged: func() {\r\n                            i := mw.tv.CurrentIndex()\r\n                            if 0 &lt;= i {\r\n                                fmt.Printf(\"OnCurrentIndexChanged: %v\\n\", mw.model.items[i].Name)\r\n                            }\r\n                        },\r\n                        OnItemActivated: mw.tv_ItemActivated,\r\n                    },\r\n                },\r\n            },\r\n        },\r\n    }.Run()\r\n}\r\n\r\nfunc (mw *CondomMainWindow) tv_ItemActivated() {\r\n    msg := ``\r\n    for _, i := range mw.tv.SelectedIndexes() {\r\n        msg = msg + \"\\n\" + mw.model.items[i].Name\r\n    }\r\n    walk.MsgBox(mw, \"title\", msg, walk.MsgBoxIconInformation)\r\n}<\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<p>\u6548\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202117028?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<h4 id=\"\u6587\u4ef6\u9009\u62e9\u5668\u52a0\u5165\u4e86icon\">\u6587\u4ef6\u9009\u62e9\u5668(\u52a0\u5165\u4e86icon)<\/h4>\n<p>\u8fd9\u91cc\u5c31\u662f\u8c03\u7528Windows\u7684\u6587\u4ef6\u9009\u62e9\u6846<br \/>\n\u4e3b\u8981\u662f\u4f7f\u7528\uff1aFileDialog<\/p>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n)\r\n\r\nimport (\r\n    \"fmt\"\r\n    \"os\"\r\n)\r\n\r\ntype MyMainWindow struct {\r\n    *walk.MainWindow\r\n    edit *walk.TextEdit\r\n\r\n    path string\r\n}\r\n\r\nfunc main() {\r\n    mw := &amp;MyMainWindow{}\r\n    MW := MainWindow{\r\n        AssignTo: &amp;mw.MainWindow,\r\n        Icon:     \"test.ico\",\r\n        Title:    \"\u6587\u4ef6\u9009\u62e9\u5bf9\u8bdd\u6846\",\r\n        MinSize:  Size{150, 200},\r\n        Size:     Size{300, 400},\r\n        Layout:   VBox{},\r\n        Children: []Widget{\r\n            TextEdit{\r\n                AssignTo: &amp;mw.edit,\r\n            },\r\n            PushButton{\r\n                Text:      \"\u6253\u5f00\",\r\n                OnClicked: mw.pbClicked,\r\n            },\r\n        },\r\n    }\r\n    if _, err := MW.Run(); err != nil {\r\n        fmt.Fprintln(os.Stderr, err)\r\n        os.Exit(1)\r\n    }\r\n\r\n}\r\n\r\nfunc (mw *MyMainWindow) pbClicked() {\r\n\r\n    dlg := new(walk.FileDialog)\r\n    dlg.FilePath = mw.path\r\n    dlg.Title = \"Select File\"\r\n    dlg.Filter = \"Exe files (*.exe)|*.exe|All files (*.*)|*.*\"\r\n\r\n    if ok, err := dlg.ShowOpen(mw); err != nil {\r\n        mw.edit.AppendText(\"Error : File Open\\r\\n\")\r\n        return\r\n    } else if !ok {\r\n        mw.edit.AppendText(\"Cancel\\r\\n\")\r\n        return\r\n    }\r\n    mw.path = dlg.FilePath\r\n    s := fmt.Sprintf(\"Select : %s\\r\\n\", mw.path)\r\n    mw.edit.AppendText(s)\r\n}<\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<p>\u6548\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202146062?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<h4 id=\"\u6587\u672c\u68c0\u7d22\u5668\">\u6587\u672c\u68c0\u7d22\u5668<\/h4>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"fmt\"\r\n    \"log\"\r\n    \"strings\"\r\n\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n)\r\n\r\nfunc main() {\r\n    mw := &amp;MyMainWindow{}\r\n\r\n    if _, err := (MainWindow{\r\n        AssignTo: &amp;mw.MainWindow,\r\n        Title:    \"SearchBox\",\r\n        Icon:     \"test.ico\",\r\n        MinSize:  Size{300, 400},\r\n        Layout:   VBox{},\r\n        Children: []Widget{\r\n            GroupBox{\r\n                Layout: HBox{},\r\n                Children: []Widget{\r\n                    LineEdit{\r\n                        AssignTo: &amp;mw.searchBox,\r\n                    },\r\n                    PushButton{\r\n                        Text:      \"\u68c0\u7d22\",\r\n                        OnClicked: mw.clicked,\r\n                    },\r\n                },\r\n            },\r\n            TextEdit{\r\n                AssignTo: &amp;mw.textArea,\r\n            },\r\n            ListBox{\r\n                AssignTo: &amp;mw.results,\r\n                Row:      5,\r\n            },\r\n        },\r\n    }.Run()); err != nil {\r\n        log.Fatal(err)\r\n    }\r\n\r\n}\r\n\r\ntype MyMainWindow struct {\r\n    *walk.MainWindow\r\n    searchBox *walk.LineEdit\r\n    textArea  *walk.TextEdit\r\n    results   *walk.ListBox\r\n}\r\n\r\nfunc (mw *MyMainWindow) clicked() {\r\n    word := mw.searchBox.Text()\r\n    text := mw.textArea.Text()\r\n    model := []string{}\r\n    for _, i := range search(text, word) {\r\n        model = append(model, fmt.Sprintf(\"%d\u68c0\u7d22\u6210\u529f\", i))\r\n    }\r\n    log.Print(model)\r\n    mw.results.SetModel(model)\r\n}\r\n\r\nfunc search(text, word string) (result []int) {\r\n    result = []int{}\r\n    i := 0\r\n    for j, _ := range text {\r\n        if strings.HasPrefix(text[j:], word) {\r\n            log.Print(i)\r\n            result = append(result, i)\r\n        }\r\n        i += 1\r\n    }\r\n    return\r\n}<\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<p>\u6548\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202200762?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<h4 id=\"\u90ae\u4ef6\u7fa4\u53d1\u5668\">\u90ae\u4ef6\u7fa4\u53d1\u5668<\/h4>\n<p>\u522b\u4eba\u5199\u7684\u90ae\u4ef6\u7fa4\u53d1\u5668\uff0c\u51fa\u81ea\uff1a<br \/>\n<a href=\"https:\/\/studygolang.com\/articles\/2078\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/studygolang.com\/articles\/2078<\/a><br \/>\n\u5173\u4e8egolang\u4e2dstmp\u7684\u4f7f\u7528\uff0c\u8bf7\u770b\u535a\u5ba2\uff1a<br \/>\n<a href=\"http:\/\/blog.csdn.net\/wangshubo1989\/article\/details\/70808989\" target=\"_blank\" rel=\"nofollow noopener\">Go\u5b9e\u6218\u2013\u901a\u8fc7net\/smtp\u53d1\u9001\u90ae\u4ef6(The way to go)<\/a><\/p>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package main\r\n\r\nimport (\r\n    \"bufio\"\r\n    \"encoding\/gob\"\r\n    \"errors\"\r\n    \"fmt\"\r\n    \"io\"\r\n    \"net\/smtp\"\r\n    \"os\"\r\n    \"strconv\"\r\n    \"strings\"\r\n    \"time\"\r\n)\r\n\r\nimport (\r\n    \"github.com\/lxn\/walk\"\r\n    . \"github.com\/lxn\/walk\/declarative\"\r\n)\r\n\r\ntype ShuJu struct {\r\n    Name    string\r\n    Pwd     string\r\n    Host    string\r\n    Subject string\r\n    Body    string\r\n    Send    string\r\n}\r\n\r\nfunc SendMail(user, password, host, to, subject, body, mailtype string) error {\r\n    fmt.Println(\"Send to \" + to)\r\n    hp := strings.Split(host, \":\")\r\n    auth := smtp.PlainAuth(\"\", user, password, hp[0])\r\n    var content_type string\r\n    if mailtype == \"html\" {\r\n        content_type = \"Content-Type: text\/html;charset=UTF-8\"\r\n    } else {\r\n        content_type = \"Content-Type: text\/plain;charset=UTF-8\"\r\n    }\r\n    body = strings.TrimSpace(body)\r\n    msg := []byte(\"To: \" + to + \"\\r\\nFrom: \" + user + \"&lt;\" + user + \"&gt;\\r\\nSubject: \" + subject + \"\\r\\n\" + content_type + \"\\r\\n\\r\\n\" + body)\r\n    send_to := strings.Split(to, \";\")\r\n    err := smtp.SendMail(host, auth, user, send_to, msg)\r\n    if err != nil {\r\n        fmt.Println(err.Error())\r\n    }\r\n    return err\r\n}\r\n\r\nfunc readLine2Array(filename string) ([]string, error) {\r\n    result := make([]string, 0)\r\n    file, err := os.Open(filename)\r\n    if err != nil {\r\n        return result, errors.New(\"Open file failed.\")\r\n    }\r\n    defer file.Close()\r\n    bf := bufio.NewReader(file)\r\n    for {\r\n        line, isPrefix, err1 := bf.ReadLine()\r\n        if err1 != nil {\r\n            if err1 != io.EOF {\r\n                return result, errors.New(\"ReadLine no finish\")\r\n            }\r\n            break\r\n        }\r\n        if isPrefix {\r\n            return result, errors.New(\"Line is too long\")\r\n        }\r\n        str := string(line)\r\n        result = append(result, str)\r\n    }\r\n    return result, nil\r\n}\r\n\r\nfunc DelArrayVar(arr []string, str string) []string {\r\n    str = strings.TrimSpace(str)\r\n    for i, v := range arr {\r\n        v = strings.TrimSpace(v)\r\n        if v == str {\r\n            if i == len(arr) {\r\n                return arr[0 : i-1]\r\n            }\r\n            if i == 0 {\r\n                return arr[1:len(arr)]\r\n            }\r\n            a1 := arr[0:i]\r\n            a2 := arr[i+1 : len(arr)]\r\n            return append(a1, a2...)\r\n        }\r\n    }\r\n    return arr\r\n}\r\n\r\nfunc LoadData() {\r\n    fmt.Println(\"LoadData\")\r\n    file, err := os.Open(\"data.dat\")\r\n    defer file.Close()\r\n    if err != nil {\r\n        fmt.Println(err.Error())\r\n        SJ.Name = \"\u7528\u6237\u540d\"\r\n        SJ.Pwd = \"\u7528\u6237\u5bc6\u7801\"\r\n        SJ.Host = \"SMTP\u670d\u52a1\u5668:\u7aef\u53e3\"\r\n        SJ.Subject = \"\u90ae\u4ef6\u4e3b\u9898\"\r\n        SJ.Body = \"\u90ae\u4ef6\u5185\u5bb9\"\r\n        SJ.Send = \"\u8981\u53d1\u9001\u7684\u90ae\u7bb1\uff0c\u6bcf\u884c\u4e00\u4e2a\"\r\n        return\r\n    }\r\n    dec := gob.NewDecoder(file)\r\n    err2 := dec.Decode(&amp;SJ)\r\n    if err2 != nil {\r\n        fmt.Println(err2.Error())\r\n        SJ.Name = \"\u7528\u6237\u540d\"\r\n        SJ.Pwd = \"\u7528\u6237\u5bc6\u7801\"\r\n        SJ.Host = \"SMTP\u670d\u52a1\u5668:\u7aef\u53e3\"\r\n        SJ.Subject = \"\u90ae\u4ef6\u4e3b\u9898\"\r\n        SJ.Body = \"\u90ae\u4ef6\u5185\u5bb9\"\r\n        SJ.Send = \"\u8981\u53d1\u9001\u7684\u90ae\u7bb1\uff0c\u6bcf\u884c\u4e00\u4e2a\"\r\n    }\r\n}\r\n\r\nfunc SaveData() {\r\n    fmt.Println(\"SaveData\")\r\n    file, err := os.Create(\"data.dat\")\r\n    defer file.Close()\r\n    if err != nil {\r\n        fmt.Println(err)\r\n    }\r\n    enc := gob.NewEncoder(file)\r\n    err2 := enc.Encode(SJ)\r\n    if err2 != nil {\r\n        fmt.Println(err2)\r\n    }\r\n}\r\n\r\nvar SJ ShuJu\r\nvar runing bool\r\nvar chEnd chan bool\r\n\r\nfunc main() {\r\n    LoadData()\r\n    chEnd = make(chan bool)\r\n    var emails, body, msgbox *walk.TextEdit\r\n    var user, password, host, subject *walk.LineEdit\r\n    var startBtn *walk.PushButton\r\n    MainWindow{\r\n        Title:   \"\u90ae\u4ef6\u53d1\u9001\u5668\",\r\n        MinSize: Size{800, 600},\r\n        Layout:  HBox{},\r\n        Children: []Widget{\r\n            TextEdit{AssignTo: &amp;emails, Text: SJ.Send, ToolTipText: \"\u5f85\u53d1\u9001\u90ae\u4ef6\u5217\u8868\uff0c\u6bcf\u884c\u4e00\u4e2a\"},\r\n            VSplitter{\r\n                Children: []Widget{\r\n                    LineEdit{AssignTo: &amp;user, Text: SJ.Name, CueBanner: \"\u8bf7\u8f93\u5165\u90ae\u7bb1\u7528\u6237\u540d\"},\r\n                    LineEdit{AssignTo: &amp;password, Text: SJ.Pwd, PasswordMode: true, CueBanner: \"\u8bf7\u8f93\u5165\u90ae\u7bb1\u767b\u5f55\u5bc6\u7801\"},\r\n                    LineEdit{AssignTo: &amp;host, Text: SJ.Host, CueBanner: \"SMTP\u670d\u52a1\u5668:\u7aef\u53e3\"},\r\n                    LineEdit{AssignTo: &amp;subject, Text: SJ.Subject, CueBanner: \"\u8bf7\u8f93\u5165\u90ae\u4ef6\u4e3b\u9898\u2026\u2026\"},\r\n                    TextEdit{AssignTo: &amp;body, Text: SJ.Body, ToolTipText: \"\u8bf7\u8f93\u5165\u90ae\u4ef6\u5185\u5bb9\", ColumnSpan: 2},\r\n                    TextEdit{AssignTo: &amp;msgbox, ReadOnly: true},\r\n                    PushButton{\r\n                        AssignTo: &amp;startBtn,\r\n                        Text:     \"\u5f00\u59cb\u7fa4\u53d1\",\r\n                        OnClicked: func() {\r\n                            SJ.Name = user.Text()\r\n                            SJ.Pwd = password.Text()\r\n                            SJ.Host = host.Text()\r\n                            SJ.Subject = subject.Text()\r\n                            SJ.Body = body.Text()\r\n                            SJ.Send = emails.Text()\r\n                            SaveData()\r\n\r\n                            if runing == false {\r\n                                runing = true\r\n                                startBtn.SetText(\"\u505c\u6b62\u53d1\u9001\")\r\n                                go sendThread(msgbox, emails)\r\n                            } else {\r\n                                runing = false\r\n                                startBtn.SetText(\"\u5f00\u59cb\u7fa4\u53d1\")\r\n                            }\r\n                        },\r\n                    },\r\n                },\r\n            },\r\n        },\r\n    }.Run()\r\n}\r\n\r\nfunc sendThread(msgbox, es *walk.TextEdit) {\r\n    sendTo := strings.Split(SJ.Send, \"\\r\\n\")\r\n    susscess := 0\r\n    count := len(sendTo)\r\n    for index, to := range sendTo {\r\n        if runing == false {\r\n            break\r\n        }\r\n        msgbox.SetText(\"\u53d1\u9001\u5230\" + to + \"...\" + strconv.Itoa((index\/count)*100) + \"%\")\r\n        err := SendMail(SJ.Name, SJ.Pwd, SJ.Host, to, SJ.Subject, SJ.Body, \"html\")\r\n        if err != nil {\r\n            msgbox.AppendText(\"\\r\\n\u5931\u8d25:\" + err.Error() + \"\\r\\n\")\r\n            if err.Error() == \"550 Mailbox not found or access denied\" {\r\n                SJ.Send = strings.Join(DelArrayVar(strings.Split(SJ.Send, \"\\r\\n\"), to), \"\\r\\n\")\r\n                es.SetText(SJ.Send)\r\n            }\r\n            time.Sleep(1 * time.Second)\r\n            continue\r\n        } else {\r\n            susscess++\r\n            msgbox.AppendText(\"\\r\\n\u53d1\u9001\u6210\u529f!\")\r\n            SJ.Send = strings.Join(DelArrayVar(strings.Split(SJ.Send, \"\\r\\n\"), to), \"\\r\\n\")\r\n            es.SetText(SJ.Send)\r\n        }\r\n        time.Sleep(1 * time.Second)\r\n    }\r\n    SaveData()\r\n    msgbox.AppendText(\"\u505c\u6b62\u53d1\u9001!\u6210\u529f \" + strconv.Itoa(susscess) + \" \u6761\\r\\n\")\r\n}<\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<pre class=\"prettyprint\"><code class=\"language-go hljs  has-numbering\"><\/code><\/pre>\n<p>&nbsp;<\/p>\n<p>\u6548\u679c\uff1a<br \/>\n<img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202218926?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<hr \/>\n<p><img decoding=\"async\" title=\"\" src=\"https:\/\/img-blog.csdn.net\/20170912202329730?watermark\/2\/text\/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3NodWJvMTk4OQ==\/font\/5a6L5L2T\/fontsize\/400\/fill\/I0JBQkFCMA==\/dissolve\/70\/gravity\/SouthEast\" alt=\"\u8fd9\u91cc\u5199\u56fe\u7247\u63cf\u8ff0\" \/><\/p>\n<\/div>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>\u00a0\u7248\u6743\u58f0\u660e\uff1a\u672c\u6587\u4e3a\u535a\u4e3b\u539f\u521b\u6587\u7ae0\uff0c\u672a\u7ecf\u535a\u4e3b<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[122],"class_list":["post-2626","post","type-post","status-publish","format-standard","hentry","tag-06-godocker"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/2626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=2626"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/2626\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=2626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=2626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=2626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}