diff --git a/v2/cmd/wails/internal/commands/dev/dev.go b/v2/cmd/wails/internal/commands/dev/dev.go index 89ce03a5b..7cc39114e 100644 --- a/v2/cmd/wails/internal/commands/dev/dev.go +++ b/v2/cmd/wails/internal/commands/dev/dev.go @@ -73,6 +73,7 @@ type devFlags struct { debounceMS int devServerURL string appargs string + saveConfig bool } // AddSubcommand adds the `dev` command for the Wails application @@ -96,6 +97,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { command.IntFlag("debounce", "The amount of time to wait to trigger a reload on change", &flags.debounceMS) command.StringFlag("devserverurl", "The url of the dev server to use", &flags.devServerURL) command.StringFlag("appargs", "arguments to pass to the underlying app (quoted and space searated)", &flags.appargs) + command.BoolFlag("save", "Save given flags as defaults", &flags.saveConfig) command.Action(func() error { // Create logger @@ -294,15 +296,12 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e return nil, err } - var shouldSaveConfig bool - if flags.assetDir == "" && projectConfig.AssetDirectory != "" { flags.assetDir = projectConfig.AssetDirectory } if flags.assetDir != projectConfig.AssetDirectory { projectConfig.AssetDirectory = filepath.ToSlash(flags.assetDir) - shouldSaveConfig = true } if flags.assetDir != "" { @@ -318,7 +317,6 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e if flags.reloadDirs != projectConfig.ReloadDirectories { projectConfig.ReloadDirectories = filepath.ToSlash(flags.reloadDirs) - shouldSaveConfig = true } if flags.devServerURL == defaultDevServerURL && projectConfig.DevServerURL != defaultDevServerURL && projectConfig.DevServerURL != "" { @@ -327,7 +325,6 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e if flags.devServerURL != projectConfig.DevServerURL { projectConfig.DevServerURL = flags.devServerURL - shouldSaveConfig = true } if flags.wailsjsdir == "" && projectConfig.WailsJSDir != "" { @@ -340,7 +337,6 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e if flags.wailsjsdir != projectConfig.WailsJSDir { projectConfig.WailsJSDir = filepath.ToSlash(flags.wailsjsdir) - shouldSaveConfig = true } if flags.debounceMS == 100 && projectConfig.DebounceMS != 100 { @@ -352,14 +348,13 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e if flags.debounceMS != projectConfig.DebounceMS { projectConfig.DebounceMS = flags.debounceMS - shouldSaveConfig = true } if flags.appargs == "" && projectConfig.AppArgs != "" { flags.appargs = projectConfig.AppArgs } - if shouldSaveConfig { + if flags.saveConfig { err = projectConfig.Save() if err != nil { return nil, err @@ -584,7 +579,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc LogRed("Error during build: %s", err.Error()) continue } - // If we have a new process, save it + // If we have a new process, saveConfig it if newBinaryProcess != nil { debugBinaryProcess = newBinaryProcess } diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.sum b/v2/cmd/wails/internal/commands/generate/template/base/go.sum index 86e6a1fd8..3c219b526 100644 --- a/v2/cmd/wails/internal/commands/generate/template/base/go.sum +++ b/v2/cmd/wails/internal/commands/generate/template/base/go.sum @@ -82,16 +82,12 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM= github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y= github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0= -github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 h1:nK/JTPyJi5QRqYjVZjXgtN4/dhg2qtngoLxLDVn429k= -github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM= github.com/leaanthony/gosod v1.0.2/go.mod h1:W8RyeSFBXu7RpIxPGEJfW4moSyGGEjlJMLV25wEbAdU= github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0= github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod b/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod index 875bab063..d3dd6ecd2 100644 --- a/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod +++ b/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod @@ -1,37 +1,37 @@ module changeme -go 1.17 + go 1.17 -require github.com/wailsapp/wails/v2 {{.WailsVersion}} + require github.com/wailsapp/wails/v2 {{.WailsVersion}} -require ( -github.com/andybalholm/brotli v1.0.2 // indirect -github.com/davecgh/go-spew v1.1.1 // indirect -github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect -github.com/gabriel-vasile/mimetype v1.3.1 // indirect -github.com/go-ole/go-ole v1.2.5 // indirect -github.com/gofiber/fiber/v2 v2.17.0 // indirect -github.com/gofiber/websocket/v2 v2.0.8 // indirect -github.com/google/uuid v1.1.2 // indirect -github.com/imdario/mergo v0.3.12 // indirect -github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect -github.com/klauspost/compress v1.12.2 // indirect -github.com/leaanthony/debme v1.2.1 // indirect -github.com/leaanthony/go-ansi-parser v1.0.1 // indirect -github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect -github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect -github.com/leaanthony/slicer v1.5.0 // indirect -github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect -github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect -github.com/pkg/errors v0.9.1 // indirect -github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect -github.com/tkrajina/go-reflector v0.5.5 // indirect -github.com/valyala/bytebufferpool v1.0.0 // indirect -github.com/valyala/fasthttp v1.28.0 // indirect -github.com/valyala/tcplisten v1.0.0 // indirect -golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect -) + require ( + github.com/andybalholm/brotli v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect + github.com/gabriel-vasile/mimetype v1.3.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/gofiber/fiber/v2 v2.17.0 // indirect + github.com/gofiber/websocket/v2 v2.0.8 // indirect + github.com/google/uuid v1.1.2 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect + github.com/klauspost/compress v1.12.2 // indirect + github.com/leaanthony/debme v1.2.1 // indirect + github.com/leaanthony/go-ansi-parser v1.0.1 // indirect + github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect + github.com/leaanthony/slicer v1.5.0 // indirect + github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect + github.com/tkrajina/go-reflector v0.5.5 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.28.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect + golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect + ) -// replace github.com/wailsapp/wails/v2 {{.WailsVersion}} => {{.WailsDirectory}} \ No newline at end of file + // replace github.com/wailsapp/wails/v2 {{.WailsVersion}} => {{.WailsDirectory}} \ No newline at end of file diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl index 6c0aac70d..06f70133e 100644 --- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl +++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl @@ -19,10 +19,10 @@ github.com/klauspost/compress v1.12.2 // indirect github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect -github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect +github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect +github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum index eb6e2e881..bba38583c 100644 --- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum +++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum @@ -83,16 +83,12 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM= github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y= github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0= -github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd h1:6m4zZ/esiByaDbzgdvDxjsOaIDgtuG1q2cyhjAi6uAg= -github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM= github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0= github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl index 6c0aac70d..06f70133e 100644 --- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl +++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl @@ -19,10 +19,10 @@ github.com/klauspost/compress v1.12.2 // indirect github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect -github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect +github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect +github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum index eb6e2e881..bba38583c 100644 --- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum +++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum @@ -83,16 +83,12 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM= github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y= github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0= -github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd h1:6m4zZ/esiByaDbzgdvDxjsOaIDgtuG1q2cyhjAi6uAg= -github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM= github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0= github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0= -github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= diff --git a/v2/go.mod b/v2/go.mod index 14e1b5a3f..ce475f5b9 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -18,16 +18,15 @@ require ( github.com/gorilla/websocket v1.4.1 github.com/imdario/mergo v0.3.12 github.com/jackmordaunt/icns v1.0.0 + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e github.com/leaanthony/clir v1.0.4 github.com/leaanthony/debme v1.2.1 github.com/leaanthony/go-ansi-parser v1.0.1 github.com/leaanthony/go-common-file-dialog v1.0.3 - github.com/leaanthony/go-webview2 v1.0.3-0.20220314105146-f44268990abe github.com/leaanthony/gosod v1.0.3 github.com/leaanthony/idgen v1.0.0 github.com/leaanthony/slicer v1.5.0 github.com/leaanthony/typescriptify-golang-structs v0.1.7 - github.com/leaanthony/winc v0.0.0-20220323084916-ea5df694ec1f github.com/leaanthony/winicon v1.0.0 github.com/matryer/is v1.4.0 github.com/olekukonko/tablewriter v0.0.4 @@ -56,7 +55,6 @@ require ( github.com/go-ole/go-ole v1.2.6 // indirect github.com/google/go-cmp v0.5.5 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/klauspost/compress v1.12.2 // indirect github.com/kr/pretty v0.3.0 // indirect diff --git a/v2/go.sum b/v2/go.sum index ee11171e3..f408167df 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -88,7 +88,6 @@ github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmA github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= @@ -118,8 +117,6 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM= github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y= github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0= -github.com/leaanthony/go-webview2 v1.0.3-0.20220314105146-f44268990abe h1:8MRHsDSWiVHE5FIwyXKBTtdOGMQEOfmPNF1nGcbx3iY= -github.com/leaanthony/go-webview2 v1.0.3-0.20220314105146-f44268990abe/go.mod h1:iX54IaVk1FnDqMuHJ47VYLPQOcVqQiOe9SJACt9CAbU= github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw= @@ -128,10 +125,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0= github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js= -github.com/leaanthony/winc v0.0.0-20220208061147-37b059b9dc3b h1:cJ+VfVwX3GkRGSy0SiOyZ7FjSGMPAY/rS/wJzilo23I= -github.com/leaanthony/winc v0.0.0-20220208061147-37b059b9dc3b/go.mod h1:OPfk8SNMAKRcSv8Vw1QL0yupmwcRtJyXZUgtMoaHUGc= -github.com/leaanthony/winc v0.0.0-20220323084916-ea5df694ec1f h1:RM0TNQXGTt06ZrSysdo+r9E9fk1ObACFBOww+W1zOiU= -github.com/leaanthony/winc v0.0.0-20220323084916-ea5df694ec1f/go.mod h1:OPfk8SNMAKRcSv8Vw1QL0yupmwcRtJyXZUgtMoaHUGc= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= @@ -253,7 +246,6 @@ golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/v2/internal/appng/app_bindings.go b/v2/internal/appng/app_bindings.go index 563dff791..6f94e211f 100644 --- a/v2/internal/appng/app_bindings.go +++ b/v2/internal/appng/app_bindings.go @@ -98,7 +98,7 @@ func generateBindings(bindings *binding.Bindings) error { // Write backend method wrappers bindingsFilename := filepath.Join(targetDir, "bindings.js") - err = bindings.GenerateBackendJS(bindingsFilename, true) + err = bindings.GenerateBackendJS(bindingsFilename) if err != nil { return err } diff --git a/v2/internal/appng/app_default_windows.go b/v2/internal/appng/app_default_windows.go index 59174e834..cf70cef90 100644 --- a/v2/internal/appng/app_default_windows.go +++ b/v2/internal/appng/app_default_windows.go @@ -6,7 +6,7 @@ package appng import ( "os/exec" - "github.com/leaanthony/winc/w32" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/pkg/options" ) diff --git a/v2/internal/appng/app_dev.go b/v2/internal/appng/app_dev.go index 7069ccaa2..f47b25bb6 100644 --- a/v2/internal/appng/app_dev.go +++ b/v2/internal/appng/app_dev.go @@ -211,7 +211,7 @@ func generateBindings(bindings *binding.Bindings) error { // Write backend method wrappers bindingsFilename := filepath.Join(targetDir, "bindings.js") - err = bindings.GenerateBackendJS(bindingsFilename, false) + err = bindings.GenerateBackendJS(bindingsFilename) if err != nil { return err } diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go index f98daf965..1d0a1b186 100644 --- a/v2/internal/binding/generate.go +++ b/v2/internal/binding/generate.go @@ -16,7 +16,7 @@ import ( //go:embed assets/package.json var packageJSON []byte -func (b *Bindings) GenerateBackendJS(targetfile string, isDevBindings bool) error { +func (b *Bindings) GenerateBackendJS(targetfile string) error { store := b.db.store var output bytes.Buffer @@ -26,15 +26,6 @@ func (b *Bindings) GenerateBackendJS(targetfile string, isDevBindings bool) erro // This file is automatically generated. DO NOT EDIT `) - if isDevBindings { - json, err := b.ToJSON() - if err != nil { - return err - } - output.WriteString("window.wailsbindings = " + json + ";") - output.WriteString("\n") - } - output.WriteString(`const go = {`) output.WriteString("\n") diff --git a/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go b/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go index 108386c10..7b9f9592d 100644 --- a/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go +++ b/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go @@ -1,7 +1,7 @@ package wv2runtime import ( - "github.com/leaanthony/go-webview2/webviewloader" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader" ) const MinimumRuntimeVersion string = "91.0.992.28" diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index e8ddf4ab0..d8d6a3adf 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -14,13 +14,13 @@ import ( "strings" "text/template" - "github.com/leaanthony/go-webview2/pkg/edge" - "github.com/leaanthony/winc" - "github.com/leaanthony/winc/w32" "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend/assetserver" "github.com/wailsapp/wails/v2/internal/frontend/desktop/common" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/pkg/options" ) diff --git a/v2/internal/frontend/desktop/windows/go-webview2/LICENSE b/v2/internal/frontend/desktop/windows/go-webview2/LICENSE new file mode 100644 index 000000000..ef2a0f485 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2020 John Chadwick +Some portions Copyright (c) 2017 Serge Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/v2/internal/frontend/desktop/windows/go-webview2/README.md b/v2/internal/frontend/desktop/windows/go-webview2/README.md new file mode 100644 index 000000000..5555fa619 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/README.md @@ -0,0 +1,27 @@ +# go-webview2 + +This is a proof of concept for embedding Webview2 into Go without CGo. It is based +on [webview/webview](https://github.com/webview/webview) and provides a compatible API. + +## Notice + +Because this version doesn't currently have an EdgeHTML fallback, it will not work unless you have a Webview2 runtime +installed. In addition, it requires the Webview2Loader DLL in order to function. Adding an EdgeHTML fallback should be +technically possible but will likely require much worse hacks since the API is not strictly COM to my knowledge. + +## Demo + +For now, you'll need to install the Webview2 runtime, as it does not ship with Windows. + +[WebView2 runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) + +After that, you should be able to run go-webview2 directly: + +``` +go run github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/cmd/demo +``` + +This will use go-winloader to load an embedded copy of WebView2Loader.dll. + +If this does not work, please try running from a directory that has an appropriate copy of `WebView2Loader.dll` for your +GOARCH. If _that_ worked, *please* file a bug so we can figure out what's wrong with go-winloader :) \ No newline at end of file diff --git a/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go b/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go new file mode 100644 index 000000000..cfd1bfbda --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go @@ -0,0 +1,154 @@ +package w32 + +import ( + "golang.org/x/sys/windows" + "syscall" + "unicode/utf16" + "unsafe" +) + +var ( + ole32 = windows.NewLazySystemDLL("ole32") + Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx") + + kernel32 = windows.NewLazySystemDLL("kernel32") + Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId") + + shlwapi = windows.NewLazySystemDLL("shlwapi") + shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream") + + user32 = windows.NewLazySystemDLL("user32") + User32LoadImageW = user32.NewProc("LoadImageW") + User32GetSystemMetrics = user32.NewProc("GetSystemMetrics") + User32RegisterClassExW = user32.NewProc("RegisterClassExW") + User32CreateWindowExW = user32.NewProc("CreateWindowExW") + User32DestroyWindow = user32.NewProc("DestroyWindow") + User32ShowWindow = user32.NewProc("ShowWindow") + User32UpdateWindow = user32.NewProc("UpdateWindow") + User32SetFocus = user32.NewProc("SetFocus") + User32GetMessageW = user32.NewProc("GetMessageW") + User32TranslateMessage = user32.NewProc("TranslateMessage") + User32DispatchMessageW = user32.NewProc("DispatchMessageW") + User32DefWindowProcW = user32.NewProc("DefWindowProcW") + User32GetClientRect = user32.NewProc("GetClientRect") + User32PostQuitMessage = user32.NewProc("PostQuitMessage") + User32SetWindowTextW = user32.NewProc("SetWindowTextW") + User32PostThreadMessageW = user32.NewProc("PostThreadMessageW") + User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW") + User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW") + User32AdjustWindowRect = user32.NewProc("AdjustWindowRect") + User32SetWindowPos = user32.NewProc("SetWindowPos") +) + +const ( + SystemMetricsCxIcon = 11 + SystemMetricsCyIcon = 12 +) + +const ( + SWShow = 5 +) + +const ( + SWPNoZOrder = 0x0004 + SWPNoActivate = 0x0010 + SWPNoMove = 0x0002 + SWPFrameChanged = 0x0020 +) + +const ( + WMDestroy = 0x0002 + WMMove = 0x0003 + WMSize = 0x0005 + WMClose = 0x0010 + WMQuit = 0x0012 + WMGetMinMaxInfo = 0x0024 + WMNCLButtonDown = 0x00A1 + WMMoving = 0x0216 + WMApp = 0x8000 +) + +const ( + GWLStyle = -16 +) + +const ( + WSOverlapped = 0x00000000 + WSMaximizeBox = 0x00020000 + WSThickFrame = 0x00040000 + WSCaption = 0x00C00000 + WSSysMenu = 0x00080000 + WSMinimizeBox = 0x00020000 + WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox) +) + +type WndClassExW struct { + CbSize uint32 + Style uint32 + LpfnWndProc uintptr + CnClsExtra int32 + CbWndExtra int32 + HInstance windows.Handle + HIcon windows.Handle + HCursor windows.Handle + HbrBackground windows.Handle + LpszMenuName *uint16 + LpszClassName *uint16 + HIconSm windows.Handle +} + +type Rect struct { + Left int32 + Top int32 + Right int32 + Bottom int32 +} + +type MinMaxInfo struct { + PtReserved Point + PtMaxSize Point + PtMaxPosition Point + PtMinTrackSize Point + PtMaxTrackSize Point +} + +type Point struct { + X, Y int32 +} + +type Msg struct { + Hwnd syscall.Handle + Message uint32 + WParam uintptr + LParam uintptr + Time uint32 + Pt Point + LPrivate uint32 +} + +func Utf16PtrToString(p *uint16) string { + if p == nil { + return "" + } + // Find NUL terminator. + end := unsafe.Pointer(p) + n := 0 + for *(*uint16)(end) != 0 { + end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) + n++ + } + s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n] + return string(utf16.Decode(s)) +} + +func SHCreateMemStream(data []byte) (uintptr, error) { + ret, _, err := shlwapiSHCreateMemStream.Call( + uintptr(unsafe.Pointer(&data[0])), + uintptr(len(data)), + ) + if ret == 0 { + return 0, err + } + + return ret, nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go new file mode 100644 index 000000000..43eb12e0b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go @@ -0,0 +1,8 @@ +package edge + +type COREWEBVIEW2_COLOR struct { + A uint8 + R uint8 + G uint8 + B uint8 +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go new file mode 100644 index 000000000..6a378fcb8 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go @@ -0,0 +1,9 @@ +package edge + +type COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND uint32 + +const ( + COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = iota + COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW + COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS +) diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go new file mode 100644 index 000000000..0b5715887 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go @@ -0,0 +1,10 @@ +package edge + +type COREWEBVIEW2_KEY_EVENT_KIND uint32 + +const ( + COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0 + COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1 + COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2 + COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3 +) diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go new file mode 100644 index 000000000..e901101ef --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go @@ -0,0 +1,9 @@ +package edge + +type COREWEBVIEW2_MOVE_FOCUS_REASON uint32 + +const ( + COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0 + COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = 1 + COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = 2 +) diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go new file mode 100644 index 000000000..8fc93e0e5 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go @@ -0,0 +1,10 @@ +package edge + +type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct { + RepeatCount uint32 + ScanCode uint32 + IsExtendedKey bool + IsMenuKeyDown bool + WasKeyDown bool + IsKeyReleased bool +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go new file mode 100644 index 000000000..9ca9c41cf --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go @@ -0,0 +1,23 @@ +package edge + +type COREWEBVIEW2_WEB_RESOURCE_CONTEXT uint32 + +const ( + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = 1 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = 2 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = 3 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = 4 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = 5 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = 6 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = 7 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = 8 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = 9 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = 10 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = 11 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = 12 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = 13 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = 14 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = 15 + COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = 16 +) diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go new file mode 100644 index 000000000..e3ff7bb53 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go @@ -0,0 +1,76 @@ +package edge + +import ( + "golang.org/x/sys/windows" + "unsafe" +) + +type _ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct { + _IUnknownVtbl + GetKeyEventKind ComProc + GetVirtualKey ComProc + GetKeyEventLParam ComProc + GetPhysicalKeyStatus ComProc + GetHandled ComProc + PutHandled ComProc +} + +type ICoreWebView2AcceleratorKeyPressedEventArgs struct { + vtbl *_ICoreWebView2AcceleratorKeyPressedEventArgsVtbl +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) { + var err error + var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND + _, _, err = i.vtbl.GetKeyEventKind.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&keyEventKind)), + ) + if err != windows.ERROR_SUCCESS { + return 0, err + } + return keyEventKind, nil +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) { + var err error + var virtualKey uint + _, _, err = i.vtbl.GetVirtualKey.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&virtualKey)), + ) + if err != windows.ERROR_SUCCESS { + return 0, err + } + return virtualKey, nil +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetPhysicalKeyStatus() (COREWEBVIEW2_PHYSICAL_KEY_STATUS, error) { + var err error + var physicalKeyStatus COREWEBVIEW2_PHYSICAL_KEY_STATUS + _, _, err = i.vtbl.GetPhysicalKeyStatus.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&physicalKeyStatus)), + ) + if err != windows.ERROR_SUCCESS { + return COREWEBVIEW2_PHYSICAL_KEY_STATUS{}, err + } + return physicalKeyStatus, nil +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) error { + var err error + + _, _, err = i.vtbl.PutHandled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(handled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go new file mode 100644 index 000000000..093cc8044 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go @@ -0,0 +1,51 @@ +package edge + +type _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type ICoreWebView2AcceleratorKeyPressedEventHandler struct { + vtbl *_ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl + impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventHandler) AddRef() uintptr { + return i.AddRef() +} +func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface(this *ICoreWebView2AcceleratorKeyPressedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke(this *ICoreWebView2AcceleratorKeyPressedEventHandler, sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr { + return this.impl.AcceleratorKeyPressed(sender, args) +} + +type _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl interface { + _IUnknownImpl + AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr +} + +var _ICoreWebView2AcceleratorKeyPressedEventHandlerFn = _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke), +} + +func newICoreWebView2AcceleratorKeyPressedEventHandler(impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl) *ICoreWebView2AcceleratorKeyPressedEventHandler { + return &ICoreWebView2AcceleratorKeyPressedEventHandler{ + vtbl: &_ICoreWebView2AcceleratorKeyPressedEventHandlerFn, + impl: impl, + } +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go new file mode 100644 index 000000000..8ecdd57e4 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go @@ -0,0 +1,132 @@ +package edge + +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" + "golang.org/x/sys/windows" +) + +type _ICoreWebView2ControllerVtbl struct { + _IUnknownVtbl + GetIsVisible ComProc + PutIsVisible ComProc + GetBounds ComProc + PutBounds ComProc + GetZoomFactor ComProc + PutZoomFactor ComProc + AddZoomFactorChanged ComProc + RemoveZoomFactorChanged ComProc + SetBoundsAndZoomFactor ComProc + MoveFocus ComProc + AddMoveFocusRequested ComProc + RemoveMoveFocusRequested ComProc + AddGotFocus ComProc + RemoveGotFocus ComProc + AddLostFocus ComProc + RemoveLostFocus ComProc + AddAcceleratorKeyPressed ComProc + RemoveAcceleratorKeyPressed ComProc + GetParentWindow ComProc + PutParentWindow ComProc + NotifyParentWindowPositionChanged ComProc + Close ComProc + GetCoreWebView2 ComProc +} + +type ICoreWebView2Controller struct { + vtbl *_ICoreWebView2ControllerVtbl +} + +func (i *ICoreWebView2Controller) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2Controller) GetBounds() (*w32.Rect, error) { + var err error + var bounds w32.Rect + _, _, err = i.vtbl.GetBounds.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&bounds)), + ) + if err != windows.ERROR_SUCCESS { + return nil, err + } + return &bounds, nil +} + +func (i *ICoreWebView2Controller) PutBounds(bounds w32.Rect) error { + var err error + + _, _, err = i.vtbl.PutBounds.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&bounds)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Controller) MoveFocus(reason COREWEBVIEW2_MOVE_FOCUS_REASON) error { + var err error + + _, _, err = i.vtbl.MoveFocus.Call( + uintptr(unsafe.Pointer(i)), + uintptr(reason), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Controller) AddAcceleratorKeyPressed(eventHandler *ICoreWebView2AcceleratorKeyPressedEventHandler, token *_EventRegistrationToken) error { + var err error + _, _, err = i.vtbl.AddAcceleratorKeyPressed.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(eventHandler)), + uintptr(unsafe.Pointer(&token)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error { + var err error + + _, _, err = i.vtbl.PutIsVisible.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isVisible)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 { + + var result *ICoreWebView2Controller2 + + iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}") + i.vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iidICoreWebView2Controller2)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error { + var err error + _, _, err = i.vtbl.NotifyParentWindowPositionChanged.Call( + uintptr(unsafe.Pointer(i)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go new file mode 100644 index 000000000..26835495c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go @@ -0,0 +1,72 @@ +package edge + +import ( + "golang.org/x/sys/windows" + "unsafe" +) + +type _ICoreWebView2Controller2Vtbl struct { + _IUnknownVtbl + GetIsVisible ComProc + PutIsVisible ComProc + GetBounds ComProc + PutBounds ComProc + GetZoomFactor ComProc + PutZoomFactor ComProc + AddZoomFactorChanged ComProc + RemoveZoomFactorChanged ComProc + SetBoundsAndZoomFactor ComProc + MoveFocus ComProc + AddMoveFocusRequested ComProc + RemoveMoveFocusRequested ComProc + AddGotFocus ComProc + RemoveGotFocus ComProc + AddLostFocus ComProc + RemoveLostFocus ComProc + AddAcceleratorKeyPressed ComProc + RemoveAcceleratorKeyPressed ComProc + GetParentWindow ComProc + PutParentWindow ComProc + NotifyParentWindowPositionChanged ComProc + Close ComProc + GetCoreWebView2 ComProc + GetDefaultBackgroundColor ComProc + PutDefaultBackgroundColor ComProc +} + +type ICoreWebView2Controller2 struct { + vtbl *_ICoreWebView2Controller2Vtbl +} + +func (i *ICoreWebView2Controller2) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2Controller2) GetDefaultBackgroundColor() (*COREWEBVIEW2_COLOR, error) { + var err error + var backgroundColor *COREWEBVIEW2_COLOR + _, _, err = i.vtbl.GetDefaultBackgroundColor.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&backgroundColor)), + ) + if err != windows.ERROR_SUCCESS { + return nil, err + } + return backgroundColor, nil +} + +func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(backgroundColor COREWEBVIEW2_COLOR) error { + var err error + + // Cast to a uint32 as that's what the call is expecting + col := *(*uint32)(unsafe.Pointer(&backgroundColor)) + + _, _, err = i.vtbl.PutDefaultBackgroundColor.Call( + uintptr(unsafe.Pointer(i)), + uintptr(col), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go new file mode 100644 index 000000000..ca92d34b3 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go @@ -0,0 +1,51 @@ +package edge + +type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2CreateCoreWebView2ControllerCompletedHandler struct { + vtbl *_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl + impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl +} + +func (i *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) AddRef() uintptr { + return i.AddRef() +} +func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, errorCode uintptr, createdController *ICoreWebView2Controller) uintptr { + return this.impl.CreateCoreWebView2ControllerCompleted(errorCode, createdController) +} + +type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl interface { + _IUnknownImpl + CreateCoreWebView2ControllerCompleted(errorCode uintptr, createdController *ICoreWebView2Controller) uintptr +} + +var _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn = _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke), +} + +func newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler { + return &iCoreWebView2CreateCoreWebView2ControllerCompletedHandler{ + vtbl: &_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn, + impl: impl, + } +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go new file mode 100644 index 000000000..e304bb9d3 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go @@ -0,0 +1,16 @@ +package edge + +type _ICoreWebView2NavigationCompletedEventArgsVtbl struct { + _IUnknownVtbl + GetIsSuccess ComProc + GetWebErrorStatus ComProc + GetNavigationId ComProc +} + +type ICoreWebView2NavigationCompletedEventArgs struct { + vtbl *_ICoreWebView2NavigationCompletedEventArgsVtbl +} + +func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr { + return i.AddRef() +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go new file mode 100644 index 000000000..6fbfe724c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go @@ -0,0 +1,51 @@ +package edge + +type _ICoreWebView2NavigationCompletedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type ICoreWebView2NavigationCompletedEventHandler struct { + vtbl *_ICoreWebView2NavigationCompletedEventHandlerVtbl + impl _ICoreWebView2NavigationCompletedEventHandlerImpl +} + +func (i *ICoreWebView2NavigationCompletedEventHandler) AddRef() uintptr { + return i.AddRef() +} +func _ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationCompletedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationCompletedEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease(this *ICoreWebView2NavigationCompletedEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this *ICoreWebView2NavigationCompletedEventHandler, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr { + return this.impl.NavigationCompleted(sender, args) +} + +type _ICoreWebView2NavigationCompletedEventHandlerImpl interface { + _IUnknownImpl + NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr +} + +var _ICoreWebView2NavigationCompletedEventHandlerFn = _ICoreWebView2NavigationCompletedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2NavigationCompletedEventHandlerInvoke), +} + +func newICoreWebView2NavigationCompletedEventHandler(impl _ICoreWebView2NavigationCompletedEventHandlerImpl) *ICoreWebView2NavigationCompletedEventHandler { + return &ICoreWebView2NavigationCompletedEventHandler{ + vtbl: &_ICoreWebView2NavigationCompletedEventHandlerFn, + impl: impl, + } +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go new file mode 100644 index 000000000..7f6e1b9b5 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go @@ -0,0 +1,268 @@ +package edge + +import ( + "golang.org/x/sys/windows" + "unsafe" +) + +type _ICoreWebView2SettingsVtbl struct { + _IUnknownVtbl + GetIsScriptEnabled ComProc + PutIsScriptEnabled ComProc + GetIsWebMessageEnabled ComProc + PutIsWebMessageEnabled ComProc + GetAreDefaultScriptDialogsEnabled ComProc + PutAreDefaultScriptDialogsEnabled ComProc + GetIsStatusBarEnabled ComProc + PutIsStatusBarEnabled ComProc + GetAreDevToolsEnabled ComProc + PutAreDevToolsEnabled ComProc + GetAreDefaultContextMenusEnabled ComProc + PutAreDefaultContextMenusEnabled ComProc + GetAreHostObjectsAllowed ComProc + PutAreHostObjectsAllowed ComProc + GetIsZoomControlEnabled ComProc + PutIsZoomControlEnabled ComProc + GetIsBuiltInErrorPageEnabled ComProc + PutIsBuiltInErrorPageEnabled ComProc +} + +type ICoreWebView2Settings struct { + vtbl *_ICoreWebView2SettingsVtbl +} + +func (i *ICoreWebView2Settings) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) { + var err error + var isScriptEnabled bool + _, _, err = i.vtbl.GetIsScriptEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isScriptEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isScriptEnabled, nil +} + +func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsScriptEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isScriptEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetIsWebMessageEnabled() (bool, error) { + var err error + var isWebMessageEnabled bool + _, _, err = i.vtbl.GetIsWebMessageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isWebMessageEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isWebMessageEnabled, nil +} + +func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsWebMessageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isWebMessageEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetAreDefaultScriptDialogsEnabled() (bool, error) { + var err error + var areDefaultScriptDialogsEnabled bool + _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return areDefaultScriptDialogsEnabled, nil +} + +func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(areDefaultScriptDialogsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetIsStatusBarEnabled() (bool, error) { + var err error + var isStatusBarEnabled bool + _, _, err = i.vtbl.GetIsStatusBarEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isStatusBarEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isStatusBarEnabled, nil +} + +func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsStatusBarEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isStatusBarEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetAreDevToolsEnabled() (bool, error) { + var err error + var areDevToolsEnabled bool + _, _, err = i.vtbl.GetAreDevToolsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&areDevToolsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return areDevToolsEnabled, nil +} + +func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error { + var err error + _, _, err = i.vtbl.PutAreDevToolsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(areDevToolsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetAreDefaultContextMenusEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) error { + var err error + _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetAreHostObjectsAllowed() (bool, error) { + var err error + var allowed bool + _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&allowed)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return allowed, nil +} + +func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error { + var err error + + _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(allowed)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetIsZoomControlEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsZoomControlEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsZoomControlEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2Settings) GetIsBuiltInErrorPageEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go new file mode 100644 index 000000000..06a9671cf --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go @@ -0,0 +1,46 @@ +package edge + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +type _ICoreWebView2WebResourceRequestVtbl struct { + _IUnknownVtbl + GetUri ComProc + PutUri ComProc + GetMethod ComProc + PutMethod ComProc + GetContent ComProc + PutContent ComProc + GetHeaders ComProc +} + +type ICoreWebView2WebResourceRequest struct { + vtbl *_ICoreWebView2WebResourceRequestVtbl +} + +func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) { + var err error + // Create *uint16 to hold result + var _uri *uint16 + _, _, err = i.vtbl.GetUri.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&_uri)), + ) + if err != windows.ERROR_SUCCESS { + return "", err + } // Get result and cleanup + uri := windows.UTF16PtrToString(_uri) + windows.CoTaskMemFree(unsafe.Pointer(_uri)) + return uri, nil +} + +func (i *ICoreWebView2WebResourceRequest) Release() error { + return i.vtbl.CallRelease(unsafe.Pointer(i)) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go new file mode 100644 index 000000000..9b093bd2a --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go @@ -0,0 +1,49 @@ +package edge + +import ( + "golang.org/x/sys/windows" + "unsafe" +) + +type _ICoreWebView2WebResourceRequestedEventArgsVtbl struct { + _IUnknownVtbl + GetRequest ComProc + GetResponse ComProc + PutResponse ComProc + GetDeferral ComProc + GetResourceContext ComProc +} + +type ICoreWebView2WebResourceRequestedEventArgs struct { + vtbl *_ICoreWebView2WebResourceRequestedEventArgsVtbl +} + +func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2WebResourceRequestedEventArgs) PutResponse(response *ICoreWebView2WebResourceResponse) error { + var err error + + _, _, err = i.vtbl.PutResponse.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(response)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) { + var err error + var request *ICoreWebView2WebResourceRequest + _, _, err = i.vtbl.GetRequest.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&request)), + ) + if err != windows.ERROR_SUCCESS { + return nil, err + } + return request, nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go new file mode 100644 index 000000000..8cdf58e88 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go @@ -0,0 +1,48 @@ +package edge + +type _ICoreWebView2WebResourceRequestedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2WebResourceRequestedEventHandler struct { + vtbl *_ICoreWebView2WebResourceRequestedEventHandlerVtbl + impl _ICoreWebView2WebResourceRequestedEventHandlerImpl +} + +func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebResourceRequestedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2WebResourceRequestedEventHandlerInvoke(this *iCoreWebView2WebResourceRequestedEventHandler, sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr { + return this.impl.WebResourceRequested(sender, args) +} + +type _ICoreWebView2WebResourceRequestedEventHandlerImpl interface { + _IUnknownImpl + WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr +} + +var _ICoreWebView2WebResourceRequestedEventHandlerFn = _ICoreWebView2WebResourceRequestedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerInvoke), +} + +func newICoreWebView2WebResourceRequestedEventHandler(impl _ICoreWebView2WebResourceRequestedEventHandlerImpl) *iCoreWebView2WebResourceRequestedEventHandler { + return &iCoreWebView2WebResourceRequestedEventHandler{ + vtbl: &_ICoreWebView2WebResourceRequestedEventHandlerFn, + impl: impl, + } +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go new file mode 100644 index 000000000..a6a0eddaf --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go @@ -0,0 +1,26 @@ +package edge + +import "unsafe" + +type _ICoreWebView2WebResourceResponseVtbl struct { + _IUnknownVtbl + GetContent ComProc + PutContent ComProc + GetHeaders ComProc + GetStatusCode ComProc + PutStatusCode ComProc + GetReasonPhrase ComProc + PutReasonPhrase ComProc +} + +type ICoreWebView2WebResourceResponse struct { + vtbl *_ICoreWebView2WebResourceResponseVtbl +} + +func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebView2WebResourceResponse) Release() error { + return i.vtbl.CallRelease(unsafe.Pointer(i)) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go new file mode 100644 index 000000000..c2441ab2d --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go @@ -0,0 +1,16 @@ +package edge + +type iCoreWebView2_2Vtbl struct { + iCoreWebView2Vtbl + AddWebResourceResponseReceived ComProc + RemoveWebResourceResponseReceived ComProc + NavigateWithWebResourceRequest ComProc + AddDomContentLoaded ComProc + RemoveDomContentLoaded ComProc + GetCookieManager ComProc + GetEnvironment ComProc +} + +type ICoreWebView2_2 struct { + vtbl *iCoreWebView2_2Vtbl +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go new file mode 100644 index 000000000..9802b8c0c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go @@ -0,0 +1,60 @@ +package edge + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +type iCoreWebView2_3Vtbl struct { + iCoreWebView2_2Vtbl + TrySuspend ComProc + Resume ComProc + GetIsSuspended ComProc + SetVirtualHostNameToFolderMapping ComProc + ClearVirtualHostNameToFolderMapping ComProc +} + +type ICoreWebView2_3 struct { + vtbl *iCoreWebView2_3Vtbl +} + +func (i *ICoreWebView2_3) SetVirtualHostNameToFolderMapping(hostName, folderPath string, accessKind COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND) error { + _hostName, err := windows.UTF16PtrFromString(hostName) + if err != nil { + return err + } + + _folderPath, err := windows.UTF16PtrFromString(folderPath) + if err != nil { + return err + } + + _, _, err = i.vtbl.SetVirtualHostNameToFolderMapping.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(_hostName)), + uintptr(unsafe.Pointer(_folderPath)), + uintptr(accessKind), + ) + if err != windows.ERROR_SUCCESS { + return err + } + + return nil +} + +func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 { + var result *ICoreWebView2_3 + + iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}") + _, _, _ = i.vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iidICoreWebView2_3)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (e *Chromium) GetICoreWebView2_3() *ICoreWebView2_3 { + return e.webview.GetICoreWebView2_3() +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go new file mode 100644 index 000000000..701601bc0 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go @@ -0,0 +1,394 @@ +package edge + +import ( + "golang.org/x/sys/windows" + "unsafe" +) + +// ICoreWebviewSettings is the merged settings class + +type _ICoreWebViewSettingsVtbl struct { + _IUnknownVtbl + GetIsScriptEnabled ComProc + PutIsScriptEnabled ComProc + GetIsWebMessageEnabled ComProc + PutIsWebMessageEnabled ComProc + GetAreDefaultScriptDialogsEnabled ComProc + PutAreDefaultScriptDialogsEnabled ComProc + GetIsStatusBarEnabled ComProc + PutIsStatusBarEnabled ComProc + GetAreDevToolsEnabled ComProc + PutAreDevToolsEnabled ComProc + GetAreDefaultContextMenusEnabled ComProc + PutAreDefaultContextMenusEnabled ComProc + GetAreHostObjectsAllowed ComProc + PutAreHostObjectsAllowed ComProc + GetIsZoomControlEnabled ComProc + PutIsZoomControlEnabled ComProc + GetIsBuiltInErrorPageEnabled ComProc + PutIsBuiltInErrorPageEnabled ComProc + GetUserAgent ComProc + PutUserAgent ComProc + GetAreBrowserAcceleratorKeysEnabled ComProc + PutAreBrowserAcceleratorKeysEnabled ComProc + GetIsPasswordAutosaveEnabled ComProc + PutIsPasswordAutosaveEnabled ComProc + GetIsGeneralAutofillEnabled ComProc + PutIsGeneralAutofillEnabled ComProc + GetIsPinchZoomEnabled ComProc + PutIsPinchZoomEnabled ComProc + GetIsSwipeNavigationEnabled ComProc + PutIsSwipeNavigationEnabled ComProc +} + +type ICoreWebViewSettings struct { + vtbl *_ICoreWebViewSettingsVtbl +} + +func (i *ICoreWebViewSettings) AddRef() uintptr { + return i.AddRef() +} + +func (i *ICoreWebViewSettings) GetIsScriptEnabled() (bool, error) { + var err error + var isScriptEnabled bool + _, _, err = i.vtbl.GetIsScriptEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isScriptEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isScriptEnabled, nil +} + +func (i *ICoreWebViewSettings) PutIsScriptEnabled(isScriptEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsScriptEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isScriptEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsWebMessageEnabled() (bool, error) { + var err error + var isWebMessageEnabled bool + _, _, err = i.vtbl.GetIsWebMessageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isWebMessageEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isWebMessageEnabled, nil +} + +func (i *ICoreWebViewSettings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsWebMessageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isWebMessageEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetAreDefaultScriptDialogsEnabled() (bool, error) { + var err error + var areDefaultScriptDialogsEnabled bool + _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return areDefaultScriptDialogsEnabled, nil +} + +func (i *ICoreWebViewSettings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(areDefaultScriptDialogsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsStatusBarEnabled() (bool, error) { + var err error + var isStatusBarEnabled bool + _, _, err = i.vtbl.GetIsStatusBarEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&isStatusBarEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return isStatusBarEnabled, nil +} + +func (i *ICoreWebViewSettings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsStatusBarEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(isStatusBarEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetAreDevToolsEnabled() (bool, error) { + var err error + var areDevToolsEnabled bool + _, _, err = i.vtbl.GetAreDevToolsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&areDevToolsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return areDevToolsEnabled, nil +} + +func (i *ICoreWebViewSettings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error { + var err error + _, _, err = i.vtbl.PutAreDevToolsEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(areDevToolsEnabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetAreDefaultContextMenusEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutAreDefaultContextMenusEnabled(enabled bool) error { + var err error + _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetAreHostObjectsAllowed() (bool, error) { + var err error + var allowed bool + _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&allowed)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return allowed, nil +} + +func (i *ICoreWebViewSettings) PutAreHostObjectsAllowed(allowed bool) error { + var err error + + _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(allowed)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsZoomControlEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsZoomControlEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutIsZoomControlEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsZoomControlEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsBuiltInErrorPageEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutIsBuiltInErrorPageEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetUserAgent() (string, error) { + var err error + // Create *uint16 to hold result + var _userAgent *uint16 + _, _, err = i.vtbl.GetUserAgent.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(_userAgent)), + ) + if err != windows.ERROR_SUCCESS { + return "", err + } // Get result and cleanup + userAgent := windows.UTF16PtrToString(_userAgent) + windows.CoTaskMemFree(unsafe.Pointer(_userAgent)) + return userAgent, nil +} + +func (i *ICoreWebViewSettings) PutUserAgent(userAgent string) error { + var err error + // Convert string 'userAgent' to *uint16 + _userAgent, err := windows.UTF16PtrFromString(userAgent) + if err != nil { + return err + } + + _, _, err = i.vtbl.PutUserAgent.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(_userAgent)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetAreBrowserAcceleratorKeysEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetAreBrowserAcceleratorKeysEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutAreBrowserAcceleratorKeysEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutAreBrowserAcceleratorKeysEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsPinchZoomEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsPinchZoomEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutIsPinchZoomEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsPinchZoomEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +func (i *ICoreWebViewSettings) GetIsSwipeNavigationEnabled() (bool, error) { + var err error + var enabled bool + _, _, err = i.vtbl.GetIsSwipeNavigationEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&enabled)), + ) + if err != windows.ERROR_SUCCESS { + return false, err + } + return enabled, nil +} + +func (i *ICoreWebViewSettings) PutIsSwipeNavigationEnabled(enabled bool) error { + var err error + + _, _, err = i.vtbl.PutIsSwipeNavigationEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(enabled)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go new file mode 100644 index 000000000..75ed3e7bc --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go @@ -0,0 +1,15 @@ +package edge + +import "unsafe" + +type _IStreamVtbl struct { + _IUnknownVtbl +} + +type IStream struct { + vtbl *_IStreamVtbl +} + +func (i *IStream) Release() error { + return i.vtbl.CallRelease(unsafe.Pointer(i)) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go new file mode 100644 index 000000000..ef9010923 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go @@ -0,0 +1,351 @@ +//go:build windows +// +build windows + +package edge + +import ( + "log" + "os" + "path/filepath" + "sync/atomic" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" + "golang.org/x/sys/windows" +) + +type Chromium struct { + hwnd uintptr + controller *ICoreWebView2Controller + webview *ICoreWebView2 + inited uintptr + envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler + controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler + webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler + permissionRequested *iCoreWebView2PermissionRequestedEventHandler + webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler + acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler + navigationCompleted *ICoreWebView2NavigationCompletedEventHandler + + environment *ICoreWebView2Environment + + // Settings + Debug bool + DataPath string + + // permissions + permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState + globalPermission *CoreWebView2PermissionState + + // Callbacks + MessageCallback func(string) + WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs) + NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) + AcceleratorKeyCallback func(uint) bool +} + +func NewChromium() *Chromium { + e := &Chromium{} + /* + All these handlers are passed to native code through syscalls with 'uintptr(unsafe.Pointer(handler))' and we know + that a pointer to those will be kept in the native code. Furthermore these handlers als contain pointer to other Go + structs like the vtable. + This violates the unsafe.Pointer rule '(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.' because + theres no guarantee that Go doesn't move these objects. + AFAIK currently the Go runtime doesn't move HEAP objects, so we should be safe with these handlers. But they don't + guarantee it, because in the future Go might use a compacting GC. + There's a proposal to add a runtime.Pin function, to prevent moving pinned objects, which would allow to easily fix + this issue by just pinning the handlers. The https://go-review.googlesource.com/c/go/+/367296/ should land in Go 1.19. + */ + e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e) + e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e) + e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e) + e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e) + e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e) + e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e) + e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e) + e.permissions = make(map[CoreWebView2PermissionKind]CoreWebView2PermissionState) + + return e +} + +func (e *Chromium) Embed(hwnd uintptr) bool { + e.hwnd = hwnd + + dataPath := e.DataPath + if dataPath == "" { + currentExePath := make([]uint16, windows.MAX_PATH) + _, err := windows.GetModuleFileName(windows.Handle(0), ¤tExePath[0], windows.MAX_PATH) + if err != nil { + // What to do here? + return false + } + currentExeName := filepath.Base(windows.UTF16ToString(currentExePath)) + dataPath = filepath.Join(os.Getenv("AppData"), currentExeName) + } + + res, err := createCoreWebView2EnvironmentWithOptions(nil, windows.StringToUTF16Ptr(dataPath), 0, e.envCompleted) + if err != nil { + log.Printf("Error calling Webview2Loader: %v", err) + return false + } else if res != 0 { + log.Printf("Result: %08x", res) + return false + } + var msg w32.Msg + for { + if atomic.LoadUintptr(&e.inited) != 0 { + break + } + r, _, _ := w32.User32GetMessageW.Call( + uintptr(unsafe.Pointer(&msg)), + 0, + 0, + 0, + ) + if r == 0 { + break + } + w32.User32TranslateMessage.Call(uintptr(unsafe.Pointer(&msg))) + w32.User32DispatchMessageW.Call(uintptr(unsafe.Pointer(&msg))) + } + e.Init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}") + return true +} + +func (e *Chromium) Navigate(url string) { + e.webview.vtbl.Navigate.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))), + ) +} + +func (e *Chromium) Init(script string) { + e.webview.vtbl.AddScriptToExecuteOnDocumentCreated.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(script))), + 0, + ) +} + +func (e *Chromium) Eval(script string) { + + _script, err := windows.UTF16PtrFromString(script) + if err != nil { + log.Fatal(err) + } + + e.webview.vtbl.ExecuteScript.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(_script)), + 0, + ) +} + +func (e *Chromium) Show() error { + return e.controller.PutIsVisible(true) +} + +func (e *Chromium) Hide() error { + return e.controller.PutIsVisible(false) +} + +func (e *Chromium) QueryInterface(_, _ uintptr) uintptr { + return 0 +} + +func (e *Chromium) AddRef() uintptr { + return 1 +} + +func (e *Chromium) Release() uintptr { + return 1 +} + +func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr { + if int64(res) < 0 { + log.Fatalf("Creating environment failed with %08x", res) + } + env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env))) + e.environment = env + env.vtbl.CreateCoreWebView2Controller.Call( + uintptr(unsafe.Pointer(env)), + e.hwnd, + uintptr(unsafe.Pointer(e.controllerCompleted)), + ) + return 0 +} + +func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller *ICoreWebView2Controller) uintptr { + if int64(res) < 0 { + log.Fatalf("Creating controller failed with %08x", res) + } + controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller))) + e.controller = controller + + var token _EventRegistrationToken + controller.vtbl.GetCoreWebView2.Call( + uintptr(unsafe.Pointer(controller)), + uintptr(unsafe.Pointer(&e.webview)), + ) + e.webview.vtbl.AddRef.Call( + uintptr(unsafe.Pointer(e.webview)), + ) + e.webview.vtbl.AddWebMessageReceived.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(e.webMessageReceived)), + uintptr(unsafe.Pointer(&token)), + ) + e.webview.vtbl.AddPermissionRequested.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(e.permissionRequested)), + uintptr(unsafe.Pointer(&token)), + ) + e.webview.vtbl.AddWebResourceRequested.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(e.webResourceRequested)), + uintptr(unsafe.Pointer(&token)), + ) + e.webview.vtbl.AddNavigationCompleted.Call( + uintptr(unsafe.Pointer(e.webview)), + uintptr(unsafe.Pointer(e.navigationCompleted)), + uintptr(unsafe.Pointer(&token)), + ) + + e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token) + + atomic.StoreUintptr(&e.inited, 1) + + return 0 +} + +func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr { + var message *uint16 + args.vtbl.TryGetWebMessageAsString.Call( + uintptr(unsafe.Pointer(args)), + uintptr(unsafe.Pointer(&message)), + ) + if e.MessageCallback != nil { + e.MessageCallback(w32.Utf16PtrToString(message)) + } + sender.vtbl.PostWebMessageAsString.Call( + uintptr(unsafe.Pointer(sender)), + uintptr(unsafe.Pointer(message)), + ) + windows.CoTaskMemFree(unsafe.Pointer(message)) + return 0 +} + +func (e *Chromium) SetPermission(kind CoreWebView2PermissionKind, state CoreWebView2PermissionState) { + e.permissions[kind] = state +} + +func (e *Chromium) SetGlobalPermission(state CoreWebView2PermissionState) { + e.globalPermission = &state +} + +func (e *Chromium) PermissionRequested(_ *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr { + var kind CoreWebView2PermissionKind + args.vtbl.GetPermissionKind.Call( + uintptr(unsafe.Pointer(args)), + uintptr(kind), + ) + var result CoreWebView2PermissionState + if e.globalPermission != nil { + result = *e.globalPermission + } else { + var ok bool + result, ok = e.permissions[kind] + if !ok { + result = CoreWebView2PermissionStateDefault + } + } + args.vtbl.PutState.Call( + uintptr(unsafe.Pointer(args)), + uintptr(result), + ) + return 0 +} + +func (e *Chromium) WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr { + req, err := args.GetRequest() + if err != nil { + log.Fatal(err) + } + defer req.Release() + + if e.WebResourceRequestedCallback != nil { + e.WebResourceRequestedCallback(req, args) + } + return 0 +} + +func (e *Chromium) AddWebResourceRequestedFilter(filter string, ctx COREWEBVIEW2_WEB_RESOURCE_CONTEXT) { + err := e.webview.AddWebResourceRequestedFilter(filter, ctx) + if err != nil { + log.Fatal(err) + } +} + +func (e *Chromium) Environment() *ICoreWebView2Environment { + return e.environment +} + +// AcceleratorKeyPressed is called when an accelerator key is pressed. +// If the AcceleratorKeyCallback method has been set, it will defer handling of the keypress +// to the callback. That callback returns a bool indicating if the event was handled. +func (e *Chromium) AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr { + if e.AcceleratorKeyCallback == nil { + return 0 + } + eventKind, _ := args.GetKeyEventKind() + if eventKind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN || + eventKind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN { + virtualKey, _ := args.GetVirtualKey() + status, _ := args.GetPhysicalKeyStatus() + if !status.WasKeyDown { + args.PutHandled(e.AcceleratorKeyCallback(virtualKey)) + return 0 + } + } + args.PutHandled(false) + return 0 +} + +func (e *Chromium) GetSettings() (*ICoreWebViewSettings, error) { + return e.webview.GetSettings() +} + +func (e *Chromium) GetController() *ICoreWebView2Controller { + return e.controller +} + +func boolToInt(input bool) int { + if input { + return 1 + } + return 0 +} + +func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr { + if e.NavigationCompletedCallback != nil { + e.NavigationCompletedCallback(sender, args) + } + return 0 +} + +func (e *Chromium) NotifyParentWindowPositionChanged() error { + //It looks like the wndproc function is called before the controller initialization is complete. + //Because of this the controller is nil + if e.controller == nil { + return nil + } + return e.controller.NotifyParentWindowPositionChanged() +} + +func (e *Chromium) Focus() { + err := e.controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) + if err != nil { + log.Fatal(err) + } +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go new file mode 100644 index 000000000..8362f4bbd --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go @@ -0,0 +1,24 @@ +//go:build windows +// +build windows + +package edge + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" + "unsafe" +) + +func (e *Chromium) Resize() { + if e.controller == nil { + return + } + var bounds w32.Rect + w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds))) + e.controller.vtbl.PutBounds.Call( + uintptr(unsafe.Pointer(e.controller)), + uintptr(bounds.Left), + uintptr(bounds.Top), + uintptr(bounds.Right), + uintptr(bounds.Bottom), + ) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go new file mode 100644 index 000000000..9835e3ecb --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go @@ -0,0 +1,21 @@ +//go:build windows +// +build windows + +package edge + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" + "unsafe" +) + +func (e *Chromium) Resize() { + if e.controller == nil { + return + } + var bounds w32.Rect + w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds))) + e.controller.vtbl.PutBounds.Call( + uintptr(unsafe.Pointer(e.controller)), + uintptr(unsafe.Pointer(&bounds)), + ) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go new file mode 100644 index 000000000..92b2e2978 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go @@ -0,0 +1,26 @@ +//go:build windows +// +build windows + +package edge + +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" +) + +func (e *Chromium) Resize() { + if e.controller == nil { + return + } + + var bounds w32.Rect + w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds))) + + words := (*[2]uintptr)(unsafe.Pointer(&bounds)) + e.controller.vtbl.PutBounds.Call( + uintptr(unsafe.Pointer(e.controller)), + words[0], + words[1], + ) +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go new file mode 100644 index 000000000..9c23da2f3 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go @@ -0,0 +1,480 @@ +//go:build windows +// +build windows + +package edge + +import ( + "log" + "runtime" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader" + "golang.org/x/sys/windows" +) + +func init() { + runtime.LockOSThread() + + r, _, _ := w32.Ole32CoInitializeEx.Call(0, 2) + if int(r) < 0 { + log.Printf("Warning: CoInitializeEx call failed: E=%08x", r) + } +} + +type _EventRegistrationToken struct { + value int64 +} + +type CoreWebView2PermissionKind uint32 + +const ( + CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota + CoreWebView2PermissionKindMicrophone + CoreWebView2PermissionKindCamera + CoreWebView2PermissionKindGeolocation + CoreWebView2PermissionKindNotifications + CoreWebView2PermissionKindOtherSensors + CoreWebView2PermissionKindClipboardRead +) + +type CoreWebView2PermissionState uint32 + +const ( + CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota + CoreWebView2PermissionStateAllow + CoreWebView2PermissionStateDeny +) + +func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentOptions uintptr, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) (uintptr, error) { + return webviewloader.CreateCoreWebView2EnvironmentWithOptions( + browserExecutableFolder, + userDataFolder, + environmentOptions, + uintptr(unsafe.Pointer(environmentCompletedHandle)), + ) +} + +// ComProc stores a COM procedure. +type ComProc uintptr + +// NewComProc creates a new COM proc from a Go function. +func NewComProc(fn interface{}) ComProc { + return ComProc(windows.NewCallback(fn)) +} + +//go:uintptrescapes +// Call calls a COM procedure. +func (p ComProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) { + // The magic uintptrescapes comment is needed to prevent moving uintptr(unsafe.Pointer(p)) so calls to .Call() also + // satisfy the unsafe.Pointer rule "(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall." + // Otherwise it might be that pointers get moved, especially pointer onto the Go stack which might grow dynamically. + // See https://pkg.go.dev/unsafe#Pointer and https://github.com/golang/go/issues/34474 + switch len(a) { + case 0: + return syscall.Syscall(uintptr(p), 0, 0, 0, 0) + case 1: + return syscall.Syscall(uintptr(p), 1, a[0], 0, 0) + case 2: + return syscall.Syscall(uintptr(p), 2, a[0], a[1], 0) + case 3: + return syscall.Syscall(uintptr(p), 3, a[0], a[1], a[2]) + case 4: + return syscall.Syscall6(uintptr(p), 4, a[0], a[1], a[2], a[3], 0, 0) + case 5: + return syscall.Syscall6(uintptr(p), 5, a[0], a[1], a[2], a[3], a[4], 0) + case 6: + return syscall.Syscall6(uintptr(p), 6, a[0], a[1], a[2], a[3], a[4], a[5]) + case 7: + return syscall.Syscall9(uintptr(p), 7, a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0) + case 8: + return syscall.Syscall9(uintptr(p), 8, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0) + case 9: + return syscall.Syscall9(uintptr(p), 9, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]) + case 10: + return syscall.Syscall12(uintptr(p), 10, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0) + case 11: + return syscall.Syscall12(uintptr(p), 11, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0) + case 12: + return syscall.Syscall12(uintptr(p), 12, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]) + case 13: + return syscall.Syscall15(uintptr(p), 13, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0) + case 14: + return syscall.Syscall15(uintptr(p), 14, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0) + case 15: + return syscall.Syscall15(uintptr(p), 15, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14]) + default: + panic("too many arguments") + } +} + +// IUnknown + +type _IUnknownVtbl struct { + QueryInterface ComProc + AddRef ComProc + Release ComProc +} + +func (i *_IUnknownVtbl) CallRelease(this unsafe.Pointer) error { + _, _, err := i.Release.Call( + uintptr(this), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} + +type _IUnknownImpl interface { + QueryInterface(refiid, object uintptr) uintptr + AddRef() uintptr + Release() uintptr +} + +// ICoreWebView2 + +type iCoreWebView2Vtbl struct { + _IUnknownVtbl + GetSettings ComProc + GetSource ComProc + Navigate ComProc + NavigateToString ComProc + AddNavigationStarting ComProc + RemoveNavigationStarting ComProc + AddContentLoading ComProc + RemoveContentLoading ComProc + AddSourceChanged ComProc + RemoveSourceChanged ComProc + AddHistoryChanged ComProc + RemoveHistoryChanged ComProc + AddNavigationCompleted ComProc + RemoveNavigationCompleted ComProc + AddFrameNavigationStarting ComProc + RemoveFrameNavigationStarting ComProc + AddFrameNavigationCompleted ComProc + RemoveFrameNavigationCompleted ComProc + AddScriptDialogOpening ComProc + RemoveScriptDialogOpening ComProc + AddPermissionRequested ComProc + RemovePermissionRequested ComProc + AddProcessFailed ComProc + RemoveProcessFailed ComProc + AddScriptToExecuteOnDocumentCreated ComProc + RemoveScriptToExecuteOnDocumentCreated ComProc + ExecuteScript ComProc + CapturePreview ComProc + Reload ComProc + PostWebMessageAsJSON ComProc + PostWebMessageAsString ComProc + AddWebMessageReceived ComProc + RemoveWebMessageReceived ComProc + CallDevToolsProtocolMethod ComProc + GetBrowserProcessID ComProc + GetCanGoBack ComProc + GetCanGoForward ComProc + GoBack ComProc + GoForward ComProc + GetDevToolsProtocolEventReceiver ComProc + Stop ComProc + AddNewWindowRequested ComProc + RemoveNewWindowRequested ComProc + AddDocumentTitleChanged ComProc + RemoveDocumentTitleChanged ComProc + GetDocumentTitle ComProc + AddHostObjectToScript ComProc + RemoveHostObjectFromScript ComProc + OpenDevToolsWindow ComProc + AddContainsFullScreenElementChanged ComProc + RemoveContainsFullScreenElementChanged ComProc + GetContainsFullScreenElement ComProc + AddWebResourceRequested ComProc + RemoveWebResourceRequested ComProc + AddWebResourceRequestedFilter ComProc + RemoveWebResourceRequestedFilter ComProc + AddWindowCloseRequested ComProc + RemoveWindowCloseRequested ComProc +} + +type ICoreWebView2 struct { + vtbl *iCoreWebView2Vtbl +} + +func (i *ICoreWebView2) GetSettings() (*ICoreWebViewSettings, error) { + var err error + var settings *ICoreWebViewSettings + _, _, err = i.vtbl.GetSettings.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&settings)), + ) + if err != windows.ERROR_SUCCESS { + return nil, err + } + return settings, nil +} + +// ICoreWebView2Environment + +type iCoreWebView2EnvironmentVtbl struct { + _IUnknownVtbl + CreateCoreWebView2Controller ComProc + CreateWebResourceResponse ComProc + GetBrowserVersionString ComProc + AddNewBrowserVersionAvailable ComProc + RemoveNewBrowserVersionAvailable ComProc +} + +type ICoreWebView2Environment struct { + vtbl *iCoreWebView2EnvironmentVtbl +} + +// CreateWebResourceResponse creates a new ICoreWebView2WebResourceResponse, it must be released after finishing using it. +func (e *ICoreWebView2Environment) CreateWebResourceResponse(content []byte, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) { + var err error + var stream uintptr + + if len(content) > 0 { + // Create stream for response + stream, err = w32.SHCreateMemStream(content) + if err != nil { + return nil, err + } + + // Release the IStream after we are finished, CreateWebResourceResponse Call will increase the reference + // count on IStream and therefore it won't be freed until the reference count of the response is 0. + defer (*IStream)(unsafe.Pointer(stream)).Release() + } + + // Convert string 'uri' to *uint16 + _reason, err := windows.UTF16PtrFromString(reasonPhrase) + if err != nil { + return nil, err + } + // Convert string 'uri' to *uint16 + _headers, err := windows.UTF16PtrFromString(headers) + if err != nil { + return nil, err + } + var response *ICoreWebView2WebResourceResponse + _, _, err = e.vtbl.CreateWebResourceResponse.Call( + uintptr(unsafe.Pointer(e)), + stream, + uintptr(statusCode), + uintptr(unsafe.Pointer(_reason)), + uintptr(unsafe.Pointer(_headers)), + uintptr(unsafe.Pointer(&response)), + ) + if err != windows.ERROR_SUCCESS { + return nil, err + } + return response, nil + +} + +// ICoreWebView2WebMessageReceivedEventArgs + +type iCoreWebView2WebMessageReceivedEventArgsVtbl struct { + _IUnknownVtbl + GetSource ComProc + GetWebMessageAsJSON ComProc + TryGetWebMessageAsString ComProc +} + +type iCoreWebView2WebMessageReceivedEventArgs struct { + vtbl *iCoreWebView2WebMessageReceivedEventArgsVtbl +} + +// ICoreWebView2PermissionRequestedEventArgs + +type iCoreWebView2PermissionRequestedEventArgsVtbl struct { + _IUnknownVtbl + GetURI ComProc + GetPermissionKind ComProc + GetIsUserInitiated ComProc + GetState ComProc + PutState ComProc + GetDeferral ComProc +} + +type iCoreWebView2PermissionRequestedEventArgs struct { + vtbl *iCoreWebView2PermissionRequestedEventArgsVtbl +} + +// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler + +type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl interface { + _IUnknownImpl + EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr +} + +type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler struct { + vtbl *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl + impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl +} + +func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, res uintptr, env *ICoreWebView2Environment) uintptr { + return this.impl.EnvironmentCompleted(res, env) +} + +var iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn = iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke), +} + +func newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler { + return &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{ + vtbl: &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn, + impl: impl, + } +} + +// ICoreWebView2WebMessageReceivedEventHandler + +type iCoreWebView2WebMessageReceivedEventHandlerImpl interface { + _IUnknownImpl + MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr +} + +type iCoreWebView2WebMessageReceivedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2WebMessageReceivedEventHandler struct { + vtbl *iCoreWebView2WebMessageReceivedEventHandlerVtbl + impl iCoreWebView2WebMessageReceivedEventHandlerImpl +} + +func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebMessageReceivedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2WebMessageReceivedEventHandlerInvoke(this *iCoreWebView2WebMessageReceivedEventHandler, sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr { + return this.impl.MessageReceived(sender, args) +} + +var iCoreWebView2WebMessageReceivedEventHandlerFn = iCoreWebView2WebMessageReceivedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerInvoke), +} + +func newICoreWebView2WebMessageReceivedEventHandler(impl iCoreWebView2WebMessageReceivedEventHandlerImpl) *iCoreWebView2WebMessageReceivedEventHandler { + return &iCoreWebView2WebMessageReceivedEventHandler{ + vtbl: &iCoreWebView2WebMessageReceivedEventHandlerFn, + impl: impl, + } +} + +// ICoreWebView2PermissionRequestedEventHandler + +type iCoreWebView2PermissionRequestedEventHandlerImpl interface { + _IUnknownImpl + PermissionRequested(sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr +} + +type iCoreWebView2PermissionRequestedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2PermissionRequestedEventHandler struct { + vtbl *iCoreWebView2PermissionRequestedEventHandlerVtbl + impl iCoreWebView2PermissionRequestedEventHandlerImpl +} + +func _ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2PermissionRequestedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2PermissionRequestedEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease(this *iCoreWebView2PermissionRequestedEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2PermissionRequestedEventHandlerInvoke(this *iCoreWebView2PermissionRequestedEventHandler, sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr { + return this.impl.PermissionRequested(sender, args) +} + +var iCoreWebView2PermissionRequestedEventHandlerFn = iCoreWebView2PermissionRequestedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2PermissionRequestedEventHandlerInvoke), +} + +func newICoreWebView2PermissionRequestedEventHandler(impl iCoreWebView2PermissionRequestedEventHandlerImpl) *iCoreWebView2PermissionRequestedEventHandler { + return &iCoreWebView2PermissionRequestedEventHandler{ + vtbl: &iCoreWebView2PermissionRequestedEventHandlerFn, + impl: impl, + } +} + +func (i *ICoreWebView2) AddWebResourceRequestedFilter(uri string, resourceContext COREWEBVIEW2_WEB_RESOURCE_CONTEXT) error { + var err error + // Convert string 'uri' to *uint16 + _uri, err := windows.UTF16PtrFromString(uri) + if err != nil { + return err + } + _, _, err = i.vtbl.AddWebResourceRequestedFilter.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(_uri)), + uintptr(resourceContext), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} +func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error { + var err error + _, _, err = i.vtbl.AddNavigationCompleted.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(eventHandler)), + uintptr(unsafe.Pointer(&token)), + ) + if err != windows.ERROR_SUCCESS { + return err + } + return nil +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go new file mode 100644 index 000000000..64d89534f --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go @@ -0,0 +1,223 @@ +package edge + +// This code has been adapted from: https://github.com/go-ole/go-ole + +/* + +The MIT License (MIT) + +Copyright © 2013-2017 Yasuhiro Matsumoto, + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +const hextable = "0123456789ABCDEF" +const emptyGUID = "{00000000-0000-0000-0000-000000000000}" + +// GUID is Windows API specific GUID type. +// +// This exists to match Windows GUID type for direct passing for COM. +// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +// NewGUID converts the given string into a globally unique identifier that is +// compliant with the Windows API. +// +// The supplied string may be in any of these formats: +// +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// The conversion of the supplied string is not case-sensitive. +func NewGUID(guid string) *GUID { + d := []byte(guid) + var d1, d2, d3, d4a, d4b []byte + + switch len(d) { + case 38: + if d[0] != '{' || d[37] != '}' { + return nil + } + d = d[1:37] + fallthrough + case 36: + if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { + return nil + } + d1 = d[0:8] + d2 = d[9:13] + d3 = d[14:18] + d4a = d[19:23] + d4b = d[24:36] + case 32: + d1 = d[0:8] + d2 = d[8:12] + d3 = d[12:16] + d4a = d[16:20] + d4b = d[20:32] + default: + return nil + } + + var g GUID + var ok1, ok2, ok3, ok4 bool + g.Data1, ok1 = decodeHexUint32(d1) + g.Data2, ok2 = decodeHexUint16(d2) + g.Data3, ok3 = decodeHexUint16(d3) + g.Data4, ok4 = decodeHexByte64(d4a, d4b) + if ok1 && ok2 && ok3 && ok4 { + return &g + } + return nil +} + +func decodeHexUint32(src []byte) (value uint32, ok bool) { + var b1, b2, b3, b4 byte + var ok1, ok2, ok3, ok4 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + b3, ok3 = decodeHexByte(src[4], src[5]) + b4, ok4 = decodeHexByte(src[6], src[7]) + value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) + ok = ok1 && ok2 && ok3 && ok4 + return +} + +func decodeHexUint16(src []byte) (value uint16, ok bool) { + var b1, b2 byte + var ok1, ok2 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + value = (uint16(b1) << 8) | uint16(b2) + ok = ok1 && ok2 + return +} + +func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { + var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool + value[0], ok1 = decodeHexByte(s1[0], s1[1]) + value[1], ok2 = decodeHexByte(s1[2], s1[3]) + value[2], ok3 = decodeHexByte(s2[0], s2[1]) + value[3], ok4 = decodeHexByte(s2[2], s2[3]) + value[4], ok5 = decodeHexByte(s2[4], s2[5]) + value[5], ok6 = decodeHexByte(s2[6], s2[7]) + value[6], ok7 = decodeHexByte(s2[8], s2[9]) + value[7], ok8 = decodeHexByte(s2[10], s2[11]) + ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 + return +} + +func decodeHexByte(c1, c2 byte) (value byte, ok bool) { + var n1, n2 byte + var ok1, ok2 bool + n1, ok1 = decodeHexChar(c1) + n2, ok2 = decodeHexChar(c2) + value = (n1 << 4) | n2 + ok = ok1 && ok2 + return +} + +func decodeHexChar(c byte) (byte, bool) { + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + + return 0, false +} + +// String converts the GUID to string form. It will adhere to this pattern: +// +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// If the GUID is nil, the string representation of an empty GUID is returned: +// +// {00000000-0000-0000-0000-000000000000} +func (guid *GUID) String() string { + if guid == nil { + return emptyGUID + } + + var c [38]byte + c[0] = '{' + putUint32Hex(c[1:9], guid.Data1) + c[9] = '-' + putUint16Hex(c[10:14], guid.Data2) + c[14] = '-' + putUint16Hex(c[15:19], guid.Data3) + c[19] = '-' + putByteHex(c[20:24], guid.Data4[0:2]) + c[24] = '-' + putByteHex(c[25:37], guid.Data4[2:8]) + c[37] = '}' + return string(c[:]) +} + +func putUint32Hex(b []byte, v uint32) { + b[0] = hextable[byte(v>>24)>>4] + b[1] = hextable[byte(v>>24)&0x0f] + b[2] = hextable[byte(v>>16)>>4] + b[3] = hextable[byte(v>>16)&0x0f] + b[4] = hextable[byte(v>>8)>>4] + b[5] = hextable[byte(v>>8)&0x0f] + b[6] = hextable[byte(v)>>4] + b[7] = hextable[byte(v)&0x0f] +} + +func putUint16Hex(b []byte, v uint16) { + b[0] = hextable[byte(v>>8)>>4] + b[1] = hextable[byte(v>>8)&0x0f] + b[2] = hextable[byte(v)>>4] + b[3] = hextable[byte(v)&0x0f] +} + +func putByteHex(dst, src []byte) { + for i := 0; i < len(src); i++ { + dst[i*2] = hextable[src[i]>>4] + dst[i*2+1] = hextable[src[i]&0x0f] + } +} + +// IsEqualGUID compares two GUID. +// +// Not constant time comparison. +func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { + return guid1.Data1 == guid2.Data1 && + guid1.Data2 == guid2.Data2 && + guid1.Data3 == guid2.Data3 && + guid1.Data4[0] == guid2.Data4[0] && + guid1.Data4[1] == guid2.Data4[1] && + guid1.Data4[2] == guid2.Data4[2] && + guid1.Data4[3] == guid2.Data4[3] && + guid1.Data4[4] == guid2.Data4[4] && + guid1.Data4[5] == guid2.Data4[5] && + guid1.Data4[6] == guid2.Data4[6] && + guid1.Data4[7] == guid2.Data4[7] +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll new file mode 100644 index 000000000..cd1c694b8 Binary files /dev/null and b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll differ diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go new file mode 100644 index 000000000..7566c2894 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go @@ -0,0 +1,140 @@ +package webviewloader + +import ( + "fmt" + "sync" + "unsafe" + + "github.com/jchv/go-winloader" + "golang.org/x/sys/windows" +) + +var ( + nativeModule = windows.NewLazyDLL("WebView2Loader") + nativeCreate = nativeModule.NewProc("CreateCoreWebView2EnvironmentWithOptions") + nativeCompareBrowserVersions = nativeModule.NewProc("CompareBrowserVersions") + nativeGetAvailableCoreWebView2BrowserVersionString = nativeModule.NewProc("GetAvailableCoreWebView2BrowserVersionString") + + memOnce sync.Once + memModule winloader.Module + memCreate winloader.Proc + memCompareBrowserVersions winloader.Proc + memGetAvailableCoreWebView2BrowserVersionString winloader.Proc + memErr error +) + +// CompareBrowserVersions will compare the 2 given versions and return: +// -1 = v1 < v2 +// 0 = v1 == v2 +// 1 = v1 > v2 +func CompareBrowserVersions(v1 string, v2 string) (int, error) { + + _v1, err := windows.UTF16PtrFromString(v1) + if err != nil { + return 0, err + } + _v2, err := windows.UTF16PtrFromString(v2) + if err != nil { + return 0, err + } + + nativeErr := nativeModule.Load() + if nativeErr == nil { + nativeErr = nativeCompareBrowserVersions.Find() + } + var result int + if nativeErr != nil { + err := loadFromMemory(nativeErr) + if err != nil { + return 0, fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr) + } + _, _, err = memCompareBrowserVersions.Call( + uint64(uintptr(unsafe.Pointer(_v1))), + uint64(uintptr(unsafe.Pointer(_v2))), + uint64(uintptr(unsafe.Pointer(&result)))) + } else { + _, _, err = nativeCompareBrowserVersions.Call( + uintptr(unsafe.Pointer(_v1)), + uintptr(unsafe.Pointer(_v2)), + uintptr(unsafe.Pointer(&result))) + } + if err != windows.ERROR_SUCCESS { + return result, err + } + return result, nil +} + +// GetInstalledVersion returns the installed version of the webview2 runtime. +// If there is no version installed, a blank string is returned. +func GetInstalledVersion() (string, error) { + nativeErr := nativeModule.Load() + if nativeErr == nil { + nativeErr = nativeGetAvailableCoreWebView2BrowserVersionString.Find() + } + var err error + var result *uint16 + if nativeErr != nil { + err := loadFromMemory(nativeErr) + if err != nil { + return "", fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr) + } + _, _, err = memGetAvailableCoreWebView2BrowserVersionString.Call( + uint64(uintptr(unsafe.Pointer(nil))), + uint64(uintptr(unsafe.Pointer(&result)))) + } else { + _, _, err = nativeCompareBrowserVersions.Call( + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(&result))) + } + if err != nil { + return "", err + } + version := windows.UTF16PtrToString(result) + windows.CoTaskMemFree(unsafe.Pointer(result)) + return version, nil +} + +// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and +// call the CreateCoreWebView2EnvironmentWithOptions routine. +func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentOptions uintptr, environmentCompletedHandle uintptr) (uintptr, error) { + nativeErr := nativeModule.Load() + if nativeErr == nil { + nativeErr = nativeCreate.Find() + } + if nativeErr != nil { + err := loadFromMemory(nativeErr) + if err != nil { + return 0, err + } + res, _, _ := memCreate.Call( + uint64(uintptr(unsafe.Pointer(browserExecutableFolder))), + uint64(uintptr(unsafe.Pointer(userDataFolder))), + uint64(environmentOptions), + uint64(environmentCompletedHandle), + ) + return uintptr(res), nil + } + res, _, _ := nativeCreate.Call( + uintptr(unsafe.Pointer(browserExecutableFolder)), + uintptr(unsafe.Pointer(userDataFolder)), + environmentOptions, + environmentCompletedHandle, + ) + return res, nil +} + +func loadFromMemory(nativeErr error) error { + var err error + // DLL is not available natively. Try loading embedded copy. + memOnce.Do(func() { + memModule, memErr = winloader.LoadFromMemory(WebView2Loader) + if memErr != nil { + err = fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr) + return + } + memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions") + memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions") + memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString") + }) + return err +} diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_386.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_386.go new file mode 100644 index 000000000..174a07037 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_386.go @@ -0,0 +1,6 @@ +package webviewloader + +import _ "embed" + +//go:embed x86/WebView2Loader.dll +var WebView2Loader []byte diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_amd64.go new file mode 100644 index 000000000..53e715fdc --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_amd64.go @@ -0,0 +1,6 @@ +package webviewloader + +import _ "embed" + +//go:embed x64/WebView2Loader.dll +var WebView2Loader []byte diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_arm64.go new file mode 100644 index 000000000..a09d3fae5 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module_arm64.go @@ -0,0 +1,6 @@ +package webviewloader + +import _ "embed" + +//go:embed arm64/WebView2Loader.dll +var WebView2Loader []byte diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll new file mode 100644 index 000000000..ab15cffb4 Binary files /dev/null and b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll differ diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll new file mode 100644 index 000000000..8609d58ee Binary files /dev/null and b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll differ diff --git a/v2/internal/frontend/desktop/windows/keys.go b/v2/internal/frontend/desktop/windows/keys.go index bec6eea47..2fe5f7550 100644 --- a/v2/internal/frontend/desktop/windows/keys.go +++ b/v2/internal/frontend/desktop/windows/keys.go @@ -4,7 +4,7 @@ package windows import ( - "github.com/leaanthony/winc" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" "github.com/wailsapp/wails/v2/pkg/menu/keys" "strings" ) diff --git a/v2/internal/frontend/desktop/windows/menu.go b/v2/internal/frontend/desktop/windows/menu.go index d1a34fd1e..b71128b45 100644 --- a/v2/internal/frontend/desktop/windows/menu.go +++ b/v2/internal/frontend/desktop/windows/menu.go @@ -4,7 +4,7 @@ package windows import ( - "github.com/leaanthony/winc" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" "github.com/wailsapp/wails/v2/pkg/menu" ) diff --git a/v2/internal/frontend/desktop/windows/winc/.gitignore b/v2/internal/frontend/desktop/windows/winc/.gitignore new file mode 100644 index 000000000..f1c181ec9 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/.gitignore @@ -0,0 +1,12 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/v2/internal/frontend/desktop/windows/winc/AUTHORS b/v2/internal/frontend/desktop/windows/winc/AUTHORS new file mode 100644 index 000000000..85674b8d9 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/AUTHORS @@ -0,0 +1,12 @@ +# This is the official list of 'Winc' authors for copyright purposes. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +# Contributors +# ============ + +Tad Vizbaras diff --git a/v2/internal/frontend/desktop/windows/winc/LICENSE b/v2/internal/frontend/desktop/windows/winc/LICENSE new file mode 100644 index 000000000..a063a4370 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 winc Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/v2/internal/frontend/desktop/windows/winc/README.md b/v2/internal/frontend/desktop/windows/winc/README.md new file mode 100644 index 000000000..4d4d467bd --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/README.md @@ -0,0 +1,181 @@ +# winc + +** This is a fork of [tadvi/winc](https://github.com/tadvi/winc) for the sole purpose of integration +with [Wails](https://github.com/wailsapp/wails). This repository comes with ***no support*** ** + +Common library for Go GUI apps on Windows. It is for Windows OS only. This makes library smaller than some other UI +libraries for Go. + +Design goals: minimalism and simplicity. + +## Dependencies + +No other dependencies except Go standard library. + +## Building + +If you want to package icon files and other resources into binary **rsrc** tool is recommended: + + rsrc -manifest app.manifest -ico=app.ico,application_edit.ico,application_error.ico -o rsrc.syso + +Here app.manifest is XML file in format: + +``` + + + + + + + + + +``` + +Most Windows applications do not display command prompt. Build your Go project with flag to indicate that it is Windows +GUI binary: + + go build -ldflags="-H windowsgui" + +## Samples + +Best way to learn how to use the library is to look at the included **examples** projects. + +## Setup + +1. Make sure you have a working Go installation and build environment, see more for details on page below. + http://golang.org/doc/install + +2. go get github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc + +## Icons + +When rsrc is used to pack icons into binary it displays IDs of the packed icons. + +``` +rsrc -manifest app.manifest -ico=app.ico,lightning.ico,edit.ico,application_error.ico -o rsrc.syso +Manifest ID: 1 +Icon app.ico ID: 10 +Icon lightning.ico ID: 13 +Icon edit.ico ID: 16 +Icon application_error.ico ID: 19 +``` + +Use IDs to reference packed icons. + +``` +const myIcon = 13 + +btn.SetResIcon(myIcon) // Set icon on the button. +``` + +Included source **examples** use basic building via `release.bat` files. Note that icon IDs are order dependent. So if +you change they order in -ico flag then icon IDs will be different. If you want to keep order the same, just add new +icons to the end of -ico comma separated list. + +## Layout Manager + +SimpleDock is default layout manager. + +Current design of docking and split views allows building simple apps but if you need to have multiple split views in +few different directions you might need to create your own layout manager. + +Important point is to have **one** control inside SimpleDock set to dock as **Fill**. Controls that are not set to any +docking get placed using SetPos() function. So you can have Panel set to dock at the Top and then have another dock to +arrange controls inside that Panel or have controls placed using SetPos() at fixed positions. + +![Example layout with two toolbars and status bar](dock_topbottom.png) + +This is basic layout. Instead of toolbars and status bar you can have Panel or any other control that can resize. Panel +can have its own internal Dock that will arrange other controls inside of it. + +![Example layout with two toolbars and navigation on the left](dock_topleft.png) + +This is layout with extra control(s) on the left. Left side is usually treeview or listview. + +The rule is simple: you either dock controls using SimpleDock OR use SetPos() to set them at fixed positions. That's it. + +At some point **winc** may get more sophisticated layout manager. + +## Dialog Screens + +Dialog screens are not based on Windows resource files (.rc). They are just windows with controls placed at fixed +coordinates. This works fine for dialog screens up to 10-14 controls. + +# Minimal Demo + +``` +package main + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" +) + +func main() { + mainWindow := winc.NewForm(nil) + mainWindow.SetSize(400, 300) // (width, height) + mainWindow.SetText("Hello World Demo") + + edt := winc.NewEdit(mainWindow) + edt.SetPos(10, 20) + // Most Controls have default size unless SetSize is called. + edt.SetText("edit text") + + btn := winc.NewPushButton(mainWindow) + btn.SetText("Show or Hide") + btn.SetPos(40, 50) // (x, y) + btn.SetSize(100, 40) // (width, height) + btn.OnClick().Bind(func(e *winc.Event) { + if edt.Visible() { + edt.Hide() + } else { + edt.Show() + } + }) + + mainWindow.Center() + mainWindow.Show() + mainWindow.OnClose().Bind(wndOnClose) + + winc.RunMainLoop() // Must call to start event loop. +} + +func wndOnClose(arg *winc.Event) { + winc.Exit() +} +``` + +![Hello World](examples/hello.png) + +Result of running sample_minimal. + +## Create Your Own + +It is good practice to create your own controls based on existing structures and event model. Library contains some of +the controls built that way: IconButton (button.go), ErrorPanel (panel.go), MultiEdit (edit.go), etc. Please look at +existing controls as examples before building your own. + +When designing your own controls keep in mind that types have to be converted from Go into Win32 API and back. This is +usually due to string UTF8 and UTF16 conversions. But there are other types of conversions too. + +When developing your own controls you might also need to: + + import "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + +w32 has Win32 API low level constants and functions. + +Look at **sample_control** for example of custom built window. + +## Companion Package + +[Go package for Windows Systray icon, menu and notifications](https://github.com/tadvi/systray) + +## Credits + +This library is built on + +[AllenDang/gform Windows GUI framework for Go](https://github.com/AllenDang/gform) + +**winc** takes most design decisions from **gform** and adds many more controls and code samples to it. + + diff --git a/v2/internal/frontend/desktop/windows/winc/app.go b/v2/internal/frontend/desktop/windows/winc/app.go new file mode 100644 index 000000000..a2c3237c6 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/app.go @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "runtime" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +var ( + // resource compilation tool assigns app.ico ID of 3 + // rsrc -manifest app.manifest -ico app.ico -o rsrc.syso + AppIconID = 3 +) + +func init() { + runtime.LockOSThread() + + gAppInstance = w32.GetModuleHandle("") + if gAppInstance == 0 { + panic("Error occurred in App.Init") + } + + // Initialize the common controls + var initCtrls w32.INITCOMMONCONTROLSEX + initCtrls.DwSize = uint32(unsafe.Sizeof(initCtrls)) + initCtrls.DwICC = + w32.ICC_LISTVIEW_CLASSES | w32.ICC_PROGRESS_CLASS | w32.ICC_TAB_CLASSES | + w32.ICC_TREEVIEW_CLASSES | w32.ICC_BAR_CLASSES + + w32.InitCommonControlsEx(&initCtrls) +} + +// SetAppIconID sets recource icon ID for the apps windows. +func SetAppIcon(appIconID int) { + AppIconID = appIconID +} + +func GetAppInstance() w32.HINSTANCE { + return gAppInstance +} + +func PreTranslateMessage(msg *w32.MSG) bool { + // This functions is called by the MessageLoop. It processes the + // keyboard accelerator keys and calls Controller.PreTranslateMessage for + // keyboard and mouse events. + + processed := false + + if (msg.Message >= w32.WM_KEYFIRST && msg.Message <= w32.WM_KEYLAST) || + (msg.Message >= w32.WM_MOUSEFIRST && msg.Message <= w32.WM_MOUSELAST) { + + if msg.Hwnd != 0 { + if controller := GetMsgHandler(msg.Hwnd); controller != nil { + // Search the chain of parents for pretranslated messages. + for p := controller; p != nil; p = p.Parent() { + + if processed = p.PreTranslateMessage(msg); processed { + break + } + } + } + } + } + + return processed +} + +// RunMainLoop processes messages in main application loop. +func RunMainLoop() int { + m := (*w32.MSG)(unsafe.Pointer(w32.GlobalAlloc(0, uint32(unsafe.Sizeof(w32.MSG{}))))) + defer w32.GlobalFree(w32.HGLOBAL(unsafe.Pointer(m))) + + for w32.GetMessage(m, 0, 0, 0) != 0 { + + if !PreTranslateMessage(m) { + w32.TranslateMessage(m) + w32.DispatchMessage(m) + } + } + + w32.GdiplusShutdown() + return int(m.WParam) +} + +// PostMessages processes recent messages. Sometimes helpful for instant window refresh. +func PostMessages() { + m := (*w32.MSG)(unsafe.Pointer(w32.GlobalAlloc(0, uint32(unsafe.Sizeof(w32.MSG{}))))) + defer w32.GlobalFree(w32.HGLOBAL(unsafe.Pointer(m))) + + for i := 0; i < 10; i++ { + if w32.GetMessage(m, 0, 0, 0) != 0 { + if !PreTranslateMessage(m) { + w32.TranslateMessage(m) + w32.DispatchMessage(m) + } + } + } +} + +func Exit() { + w32.PostQuitMessage(0) +} diff --git a/v2/internal/frontend/desktop/windows/winc/bitmap.go b/v2/internal/frontend/desktop/windows/winc/bitmap.go new file mode 100644 index 000000000..235dc43fd --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/bitmap.go @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "errors" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Bitmap struct { + handle w32.HBITMAP + width, height int +} + +func assembleBitmapFromHBITMAP(hbitmap w32.HBITMAP) (*Bitmap, error) { + var dib w32.DIBSECTION + if w32.GetObject(w32.HGDIOBJ(hbitmap), unsafe.Sizeof(dib), unsafe.Pointer(&dib)) == 0 { + return nil, errors.New("GetObject for HBITMAP failed") + } + + return &Bitmap{ + handle: hbitmap, + width: int(dib.DsBmih.BiWidth), + height: int(dib.DsBmih.BiHeight), + }, nil +} + +func NewBitmapFromFile(filepath string, background Color) (*Bitmap, error) { + var gpBitmap *uintptr + var err error + + gpBitmap, err = w32.GdipCreateBitmapFromFile(filepath) + if err != nil { + return nil, err + } + defer w32.GdipDisposeImage(gpBitmap) + + var hbitmap w32.HBITMAP + // Reverse RGB to BGR to satisfy gdiplus color schema. + hbitmap, err = w32.GdipCreateHBITMAPFromBitmap(gpBitmap, uint32(RGB(background.B(), background.G(), background.R()))) + if err != nil { + return nil, err + } + + return assembleBitmapFromHBITMAP(hbitmap) +} + +func NewBitmapFromResource(instance w32.HINSTANCE, resName *uint16, resType *uint16, background Color) (*Bitmap, error) { + var gpBitmap *uintptr + var err error + var hRes w32.HRSRC + + hRes, err = w32.FindResource(w32.HMODULE(instance), resName, resType) + if err != nil { + return nil, err + } + resSize := w32.SizeofResource(w32.HMODULE(instance), hRes) + pResData := w32.LockResource(w32.LoadResource(w32.HMODULE(instance), hRes)) + resBuffer := w32.GlobalAlloc(w32.GMEM_MOVEABLE, resSize) + pResBuffer := w32.GlobalLock(resBuffer) + w32.MoveMemory(pResBuffer, pResData, resSize) + + stream := w32.CreateStreamOnHGlobal(resBuffer, false) + + gpBitmap, err = w32.GdipCreateBitmapFromStream(stream) + if err != nil { + return nil, err + } + defer stream.Release() + defer w32.GlobalUnlock(resBuffer) + defer w32.GlobalFree(resBuffer) + defer w32.GdipDisposeImage(gpBitmap) + + var hbitmap w32.HBITMAP + // Reverse gform.RGB to BGR to satisfy gdiplus color schema. + hbitmap, err = w32.GdipCreateHBITMAPFromBitmap(gpBitmap, uint32(RGB(background.B(), background.G(), background.R()))) + if err != nil { + return nil, err + } + + return assembleBitmapFromHBITMAP(hbitmap) +} + +func (bm *Bitmap) Dispose() { + if bm.handle != 0 { + w32.DeleteObject(w32.HGDIOBJ(bm.handle)) + bm.handle = 0 + } +} + +func (bm *Bitmap) GetHBITMAP() w32.HBITMAP { + return bm.handle +} + +func (bm *Bitmap) Size() (int, int) { + return bm.width, bm.height +} + +func (bm *Bitmap) Height() int { + return bm.height +} + +func (bm *Bitmap) Width() int { + return bm.width +} diff --git a/v2/internal/frontend/desktop/windows/winc/brush.go b/v2/internal/frontend/desktop/windows/winc/brush.go new file mode 100644 index 000000000..55e8ec526 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/brush.go @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +var DefaultBackgroundBrush = NewSystemColorBrush(w32.COLOR_BTNFACE) + +type Brush struct { + hBrush w32.HBRUSH + logBrush w32.LOGBRUSH +} + +func NewSolidColorBrush(color Color) *Brush { + lb := w32.LOGBRUSH{LbStyle: w32.BS_SOLID, LbColor: w32.COLORREF(color)} + hBrush := w32.CreateBrushIndirect(&lb) + if hBrush == 0 { + panic("Faild to create solid color brush") + } + + return &Brush{hBrush, lb} +} + +func NewSystemColorBrush(colorIndex int) *Brush { + //lb := w32.LOGBRUSH{LbStyle: w32.BS_SOLID, LbColor: w32.COLORREF(colorIndex)} + lb := w32.LOGBRUSH{LbStyle: w32.BS_NULL} + hBrush := w32.GetSysColorBrush(colorIndex) + if hBrush == 0 { + panic("GetSysColorBrush failed") + } + return &Brush{hBrush, lb} +} + +func NewHatchedColorBrush(color Color) *Brush { + lb := w32.LOGBRUSH{LbStyle: w32.BS_HATCHED, LbColor: w32.COLORREF(color)} + hBrush := w32.CreateBrushIndirect(&lb) + if hBrush == 0 { + panic("Faild to create solid color brush") + } + + return &Brush{hBrush, lb} +} + +func NewNullBrush() *Brush { + lb := w32.LOGBRUSH{LbStyle: w32.BS_NULL} + hBrush := w32.CreateBrushIndirect(&lb) + if hBrush == 0 { + panic("Failed to create null brush") + } + + return &Brush{hBrush, lb} +} + +func (br *Brush) GetHBRUSH() w32.HBRUSH { + return br.hBrush +} + +func (br *Brush) GetLOGBRUSH() *w32.LOGBRUSH { + return &br.logBrush +} + +func (br *Brush) Dispose() { + if br.hBrush != 0 { + w32.DeleteObject(w32.HGDIOBJ(br.hBrush)) + br.hBrush = 0 + } +} diff --git a/v2/internal/frontend/desktop/windows/winc/buttons.go b/v2/internal/frontend/desktop/windows/winc/buttons.go new file mode 100644 index 000000000..ccf0d267d --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/buttons.go @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Button struct { + ControlBase + onClick EventManager +} + +func (bt *Button) OnClick() *EventManager { + return &bt.onClick +} + +func (bt *Button) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_COMMAND: + bt.onClick.Fire(NewEvent(bt, nil)) + /*case w32.WM_LBUTTONDOWN: + w32.SetCapture(bt.Handle()) + case w32.WM_LBUTTONUP: + w32.ReleaseCapture()*/ + /*case win.WM_GETDLGCODE: + println("GETDLGCODE")*/ + } + return w32.DefWindowProc(bt.hwnd, msg, wparam, lparam) + //return bt.W32Control.WndProc(msg, wparam, lparam) +} + +func (bt *Button) Checked() bool { + result := w32.SendMessage(bt.hwnd, w32.BM_GETCHECK, 0, 0) + return result == w32.BST_CHECKED +} + +func (bt *Button) SetChecked(checked bool) { + wparam := w32.BST_CHECKED + if !checked { + wparam = w32.BST_UNCHECKED + } + w32.SendMessage(bt.hwnd, w32.BM_SETCHECK, uintptr(wparam), 0) +} + +// SetIcon sets icon on the button. Recommended icons are 32x32 with 32bit color depth. +func (bt *Button) SetIcon(ico *Icon) { + w32.SendMessage(bt.hwnd, w32.BM_SETIMAGE, w32.IMAGE_ICON, uintptr(ico.handle)) +} + +func (bt *Button) SetResIcon(iconID uint16) { + if ico, err := NewIconFromResource(GetAppInstance(), iconID); err == nil { + bt.SetIcon(ico) + return + } + panic(fmt.Sprintf("missing icon with icon ID: %d", iconID)) +} + +type PushButton struct { + Button +} + +func NewPushButton(parent Controller) *PushButton { + pb := new(PushButton) + + pb.InitControl("BUTTON", parent, 0, w32.BS_PUSHBUTTON|w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD) + RegMsgHandler(pb) + + pb.SetFont(DefaultFont) + pb.SetText("Button") + pb.SetSize(100, 22) + + return pb +} + +// SetDefault is used for dialogs to set default button. +func (pb *PushButton) SetDefault() { + pb.SetAndClearStyleBits(w32.BS_DEFPUSHBUTTON, w32.BS_PUSHBUTTON) +} + +// IconButton does not display text, requires SetResIcon call. +type IconButton struct { + Button +} + +func NewIconButton(parent Controller) *IconButton { + pb := new(IconButton) + + pb.InitControl("BUTTON", parent, 0, w32.BS_ICON|w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD) + RegMsgHandler(pb) + + pb.SetFont(DefaultFont) + // even if text would be set it would not be displayed + pb.SetText("") + pb.SetSize(100, 22) + + return pb +} + +type CheckBox struct { + Button +} + +func NewCheckBox(parent Controller) *CheckBox { + cb := new(CheckBox) + + cb.InitControl("BUTTON", parent, 0, w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD|w32.BS_AUTOCHECKBOX) + RegMsgHandler(cb) + + cb.SetFont(DefaultFont) + cb.SetText("CheckBox") + cb.SetSize(100, 22) + + return cb +} + +type RadioButton struct { + Button +} + +func NewRadioButton(parent Controller) *RadioButton { + rb := new(RadioButton) + + rb.InitControl("BUTTON", parent, 0, w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD|w32.BS_AUTORADIOBUTTON) + RegMsgHandler(rb) + + rb.SetFont(DefaultFont) + rb.SetText("RadioButton") + rb.SetSize(100, 22) + + return rb +} + +type GroupBox struct { + Button +} + +func NewGroupBox(parent Controller) *GroupBox { + gb := new(GroupBox) + + gb.InitControl("BUTTON", parent, 0, w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_GROUP|w32.BS_GROUPBOX) + RegMsgHandler(gb) + + gb.SetFont(DefaultFont) + gb.SetText("GroupBox") + gb.SetSize(100, 100) + + return gb +} diff --git a/v2/internal/frontend/desktop/windows/winc/canvas.go b/v2/internal/frontend/desktop/windows/winc/canvas.go new file mode 100644 index 000000000..46fc0d615 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/canvas.go @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Canvas struct { + hwnd w32.HWND + hdc w32.HDC + doNotDispose bool +} + +var nullBrush = NewNullBrush() + +func NewCanvasFromHwnd(hwnd w32.HWND) *Canvas { + hdc := w32.GetDC(hwnd) + if hdc == 0 { + panic(fmt.Sprintf("Create canvas from %v failed.", hwnd)) + } + + return &Canvas{hwnd: hwnd, hdc: hdc, doNotDispose: false} +} + +func NewCanvasFromHDC(hdc w32.HDC) *Canvas { + if hdc == 0 { + panic("Cannot create canvas from invalid HDC.") + } + + return &Canvas{hdc: hdc, doNotDispose: true} +} + +func (ca *Canvas) Dispose() { + if !ca.doNotDispose && ca.hdc != 0 { + if ca.hwnd == 0 { + w32.DeleteDC(ca.hdc) + } else { + w32.ReleaseDC(ca.hwnd, ca.hdc) + } + + ca.hdc = 0 + } +} + +func (ca *Canvas) DrawBitmap(bmp *Bitmap, x, y int) { + cdc := w32.CreateCompatibleDC(0) + defer w32.DeleteDC(cdc) + + hbmpOld := w32.SelectObject(cdc, w32.HGDIOBJ(bmp.GetHBITMAP())) + defer w32.SelectObject(cdc, w32.HGDIOBJ(hbmpOld)) + + w, h := bmp.Size() + + w32.BitBlt(ca.hdc, x, y, w, h, cdc, 0, 0, w32.SRCCOPY) +} + +func (ca *Canvas) DrawStretchedBitmap(bmp *Bitmap, rect *Rect) { + cdc := w32.CreateCompatibleDC(0) + defer w32.DeleteDC(cdc) + + hbmpOld := w32.SelectObject(cdc, w32.HGDIOBJ(bmp.GetHBITMAP())) + defer w32.SelectObject(cdc, w32.HGDIOBJ(hbmpOld)) + + w, h := bmp.Size() + + rc := rect.GetW32Rect() + w32.StretchBlt(ca.hdc, int(rc.Left), int(rc.Top), int(rc.Right), int(rc.Bottom), cdc, 0, 0, w, h, w32.SRCCOPY) +} + +func (ca *Canvas) DrawIcon(ico *Icon, x, y int) bool { + return w32.DrawIcon(ca.hdc, x, y, ico.Handle()) +} + +// DrawFillRect draw and fill rectangle with color. +func (ca *Canvas) DrawFillRect(rect *Rect, pen *Pen, brush *Brush) { + w32Rect := rect.GetW32Rect() + + previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) + defer w32.SelectObject(ca.hdc, previousPen) + + previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(brush.GetHBRUSH())) + defer w32.SelectObject(ca.hdc, previousBrush) + + w32.Rectangle(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) +} + +func (ca *Canvas) DrawRect(rect *Rect, pen *Pen) { + w32Rect := rect.GetW32Rect() + + previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) + defer w32.SelectObject(ca.hdc, previousPen) + + // nullBrush is used to make interior of the rect transparent + previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(nullBrush.GetHBRUSH())) + defer w32.SelectObject(ca.hdc, previousBrush) + + w32.Rectangle(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) +} + +func (ca *Canvas) FillRect(rect *Rect, brush *Brush) { + w32.FillRect(ca.hdc, rect.GetW32Rect(), brush.GetHBRUSH()) +} + +func (ca *Canvas) DrawEllipse(rect *Rect, pen *Pen) { + w32Rect := rect.GetW32Rect() + + previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) + defer w32.SelectObject(ca.hdc, previousPen) + + // nullBrush is used to make interior of the rect transparent + previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(nullBrush.GetHBRUSH())) + defer w32.SelectObject(ca.hdc, previousBrush) + + w32.Ellipse(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) +} + +// DrawFillEllipse draw and fill ellipse with color. +func (ca *Canvas) DrawFillEllipse(rect *Rect, pen *Pen, brush *Brush) { + w32Rect := rect.GetW32Rect() + + previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) + defer w32.SelectObject(ca.hdc, previousPen) + + previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(brush.GetHBRUSH())) + defer w32.SelectObject(ca.hdc, previousBrush) + + w32.Ellipse(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) +} + +func (ca *Canvas) DrawLine(x, y, x2, y2 int, pen *Pen) { + w32.MoveToEx(ca.hdc, x, y, nil) + + previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) + defer w32.SelectObject(ca.hdc, previousPen) + + w32.LineTo(ca.hdc, int32(x2), int32(y2)) +} + +// Refer win32 DrawText document for uFormat. +func (ca *Canvas) DrawText(text string, rect *Rect, format uint, font *Font, textColor Color) { + previousFont := w32.SelectObject(ca.hdc, w32.HGDIOBJ(font.GetHFONT())) + defer w32.SelectObject(ca.hdc, w32.HGDIOBJ(previousFont)) + + previousBkMode := w32.SetBkMode(ca.hdc, w32.TRANSPARENT) + defer w32.SetBkMode(ca.hdc, previousBkMode) + + previousTextColor := w32.SetTextColor(ca.hdc, w32.COLORREF(textColor)) + defer w32.SetTextColor(ca.hdc, previousTextColor) + + w32.DrawText(ca.hdc, text, len(text), rect.GetW32Rect(), format) +} diff --git a/v2/internal/frontend/desktop/windows/winc/color.go b/v2/internal/frontend/desktop/windows/winc/color.go new file mode 100644 index 000000000..ac16dbc4b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/color.go @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +type Color uint32 + +func RGB(r, g, b byte) Color { + return Color(uint32(r) | uint32(g)<<8 | uint32(b)<<16) +} + +func (c Color) R() byte { + return byte(c & 0xff) +} + +func (c Color) G() byte { + return byte((c >> 8) & 0xff) +} + +func (c Color) B() byte { + return byte((c >> 16) & 0xff) +} diff --git a/v2/internal/frontend/desktop/windows/winc/combobox.go b/v2/internal/frontend/desktop/windows/winc/combobox.go new file mode 100644 index 000000000..b389c8b40 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/combobox.go @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ComboBox struct { + ControlBase + onSelectedChange EventManager +} + +func NewComboBox(parent Controller) *ComboBox { + cb := new(ComboBox) + + cb.InitControl("COMBOBOX", parent, 0, w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.WS_VSCROLL|w32.CBS_DROPDOWNLIST) + RegMsgHandler(cb) + + cb.SetFont(DefaultFont) + cb.SetSize(200, 400) + return cb +} + +func (cb *ComboBox) DeleteAllItems() bool { + return w32.SendMessage(cb.hwnd, w32.CB_RESETCONTENT, 0, 0) == w32.TRUE +} + +func (cb *ComboBox) InsertItem(index int, str string) bool { + lp := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) + return w32.SendMessage(cb.hwnd, w32.CB_INSERTSTRING, uintptr(index), lp) != w32.CB_ERR +} + +func (cb *ComboBox) DeleteItem(index int) bool { + return w32.SendMessage(cb.hwnd, w32.CB_DELETESTRING, uintptr(index), 0) != w32.CB_ERR +} + +func (cb *ComboBox) SelectedItem() int { + return int(int32(w32.SendMessage(cb.hwnd, w32.CB_GETCURSEL, 0, 0))) +} + +func (cb *ComboBox) SetSelectedItem(value int) bool { + return int(int32(w32.SendMessage(cb.hwnd, w32.CB_SETCURSEL, uintptr(value), 0))) == value +} + +func (cb *ComboBox) OnSelectedChange() *EventManager { + return &cb.onSelectedChange +} + +// Message processer +func (cb *ComboBox) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_COMMAND: + code := w32.HIWORD(uint32(wparam)) + + switch code { + case w32.CBN_SELCHANGE: + cb.onSelectedChange.Fire(NewEvent(cb, nil)) + } + } + return w32.DefWindowProc(cb.hwnd, msg, wparam, lparam) + //return cb.W32Control.WndProc(msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/commondlgs.go b/v2/internal/frontend/desktop/windows/winc/commondlgs.go new file mode 100644 index 000000000..3e30f14bc --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/commondlgs.go @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +func genOFN(parent Controller, title, filter string, filterIndex uint, initialDir string, buf []uint16) *w32.OPENFILENAME { + var ofn w32.OPENFILENAME + ofn.StructSize = uint32(unsafe.Sizeof(ofn)) + ofn.Owner = parent.Handle() + + if filter != "" { + filterBuf := make([]uint16, len(filter)+1) + copy(filterBuf, syscall.StringToUTF16(filter)) + // Replace '|' with the expected '\0' + for i, c := range filterBuf { + if byte(c) == '|' { + filterBuf[i] = uint16(0) + } + } + ofn.Filter = &filterBuf[0] + ofn.FilterIndex = uint32(filterIndex) + } + + ofn.File = &buf[0] + ofn.MaxFile = uint32(len(buf)) + + if initialDir != "" { + ofn.InitialDir = syscall.StringToUTF16Ptr(initialDir) + } + if title != "" { + ofn.Title = syscall.StringToUTF16Ptr(title) + } + + ofn.Flags = w32.OFN_FILEMUSTEXIST + return &ofn +} + +func ShowOpenFileDlg(parent Controller, title, filter string, filterIndex uint, initialDir string) (filePath string, accepted bool) { + buf := make([]uint16, 1024) + ofn := genOFN(parent, title, filter, filterIndex, initialDir, buf) + + if accepted = w32.GetOpenFileName(ofn); accepted { + filePath = syscall.UTF16ToString(buf) + } + return +} + +func ShowSaveFileDlg(parent Controller, title, filter string, filterIndex uint, initialDir string) (filePath string, accepted bool) { + buf := make([]uint16, 1024) + ofn := genOFN(parent, title, filter, filterIndex, initialDir, buf) + + if accepted = w32.GetSaveFileName(ofn); accepted { + filePath = syscall.UTF16ToString(buf) + } + return +} + +func ShowBrowseFolderDlg(parent Controller, title string) (folder string, accepted bool) { + var bi w32.BROWSEINFO + bi.Owner = parent.Handle() + bi.Title = syscall.StringToUTF16Ptr(title) + bi.Flags = w32.BIF_RETURNONLYFSDIRS | w32.BIF_NEWDIALOGSTYLE + + w32.CoInitialize() + ret := w32.SHBrowseForFolder(&bi) + w32.CoUninitialize() + + folder = w32.SHGetPathFromIDList(ret) + accepted = folder != "" + return +} + +// MsgBoxOkCancel basic pop up message. Returns 1 for OK and 2 for CANCEL. +func MsgBoxOkCancel(parent Controller, title, caption string) int { + return MsgBox(parent, title, caption, w32.MB_ICONEXCLAMATION|w32.MB_OKCANCEL) +} + +func MsgBoxYesNo(parent Controller, title, caption string) int { + return MsgBox(parent, title, caption, w32.MB_ICONEXCLAMATION|w32.MB_YESNO) +} + +func MsgBoxOk(parent Controller, title, caption string) { + MsgBox(parent, title, caption, w32.MB_ICONINFORMATION|w32.MB_OK) +} + +// Warningf is generic warning message with OK and Cancel buttons. Returns 1 for OK. +func Warningf(parent Controller, format string, data ...interface{}) int { + caption := fmt.Sprintf(format, data...) + return MsgBox(parent, "Warning", caption, w32.MB_ICONWARNING|w32.MB_OKCANCEL) +} + +// Printf is generic info message with OK button. +func Printf(parent Controller, format string, data ...interface{}) { + caption := fmt.Sprintf(format, data...) + MsgBox(parent, "Information", caption, w32.MB_ICONINFORMATION|w32.MB_OK) +} + +// Errorf is generic error message with OK button. +func Errorf(parent Controller, format string, data ...interface{}) { + caption := fmt.Sprintf(format, data...) + MsgBox(parent, "Error", caption, w32.MB_ICONERROR|w32.MB_OK) +} + +func MsgBox(parent Controller, title, caption string, flags uint) int { + var result int + if parent != nil { + result = w32.MessageBox(parent.Handle(), caption, title, flags) + } else { + result = w32.MessageBox(0, caption, title, flags) + } + + return result +} diff --git a/v2/internal/frontend/desktop/windows/winc/controlbase.go b/v2/internal/frontend/desktop/windows/winc/controlbase.go new file mode 100644 index 000000000..1f7cb66ff --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/controlbase.go @@ -0,0 +1,518 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "runtime" + "sync" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ControlBase struct { + hwnd w32.HWND + font *Font + parent Controller + contextMenu *MenuItem + + isForm bool + + minWidth, minHeight int + maxWidth, maxHeight int + + // General events + onCreate EventManager + onClose EventManager + + // Focus events + onKillFocus EventManager + onSetFocus EventManager + + // Drag and drop events + onDropFiles EventManager + + // Mouse events + onLBDown EventManager + onLBUp EventManager + onLBDbl EventManager + onMBDown EventManager + onMBUp EventManager + onRBDown EventManager + onRBUp EventManager + onRBDbl EventManager + onMouseMove EventManager + + // use MouseControl to capture onMouseHover and onMouseLeave events. + onMouseHover EventManager + onMouseLeave EventManager + + // Keyboard events + onKeyUp EventManager + + // Paint events + onPaint EventManager + onSize EventManager + + m sync.Mutex + dispatchq []func() +} + +// initControl is called by controls: edit, button, treeview, listview, and so on. +func (cba *ControlBase) InitControl(className string, parent Controller, exstyle, style uint) { + cba.hwnd = CreateWindow(className, parent, exstyle, style) + if cba.hwnd == 0 { + panic("cannot create window for " + className) + } + cba.parent = parent +} + +// InitWindow is called by custom window based controls such as split, panel, etc. +func (cba *ControlBase) InitWindow(className string, parent Controller, exstyle, style uint) { + RegClassOnlyOnce(className) + cba.hwnd = CreateWindow(className, parent, exstyle, style) + if cba.hwnd == 0 { + panic("cannot create window for " + className) + } + cba.parent = parent +} + +// SetTheme for TreeView and ListView controls. +func (cba *ControlBase) SetTheme(appName string) error { + if hr := w32.SetWindowTheme(cba.hwnd, syscall.StringToUTF16Ptr(appName), nil); w32.FAILED(hr) { + return fmt.Errorf("SetWindowTheme %d", hr) + } + return nil +} + +func (cba *ControlBase) Handle() w32.HWND { + return cba.hwnd +} + +func (cba *ControlBase) SetHandle(hwnd w32.HWND) { + cba.hwnd = hwnd +} + +func (cba *ControlBase) GetWindowDPI() (w32.UINT, w32.UINT) { + if w32.HasGetDpiForWindowFunc() { + // GetDpiForWindow is supported beginning with Windows 10, 1607 and is the most accureate + // one, especially it is consistent with the WM_DPICHANGED event. + dpi := w32.GetDpiForWindow(cba.hwnd) + return dpi, dpi + } + + if w32.HasGetDPIForMonitorFunc() { + // GetDpiForWindow is supported beginning with Windows 8.1 + monitor := w32.MonitorFromWindow(cba.hwnd, w32.MONITOR_DEFAULTTONEAREST) + if monitor == 0 { + return 0, 0 + } + var dpiX, dpiY w32.UINT + w32.GetDPIForMonitor(monitor, w32.MDT_EFFECTIVE_DPI, &dpiX, &dpiY) + return dpiX, dpiY + } + + // If none of the above is supported fallback to the System DPI. + screen := w32.GetDC(0) + x := w32.GetDeviceCaps(screen, w32.LOGPIXELSX) + y := w32.GetDeviceCaps(screen, w32.LOGPIXELSY) + w32.ReleaseDC(0, screen) + return w32.UINT(x), w32.UINT(y) +} + +func (cba *ControlBase) SetAndClearStyleBits(set, clear uint32) error { + style := uint32(w32.GetWindowLong(cba.hwnd, w32.GWL_STYLE)) + if style == 0 { + return fmt.Errorf("GetWindowLong") + } + + if newStyle := style&^clear | set; newStyle != style { + if w32.SetWindowLong(cba.hwnd, w32.GWL_STYLE, newStyle) == 0 { + return fmt.Errorf("SetWindowLong") + } + } + return nil +} + +func (cba *ControlBase) SetIsForm(isform bool) { + cba.isForm = isform +} + +func (cba *ControlBase) SetText(caption string) { + w32.SetWindowText(cba.hwnd, caption) +} + +func (cba *ControlBase) Text() string { + return w32.GetWindowText(cba.hwnd) +} + +func (cba *ControlBase) Close() { + UnRegMsgHandler(cba.hwnd) + w32.DestroyWindow(cba.hwnd) +} + +func (cba *ControlBase) SetTranslucentBackground() { + var accent = w32.ACCENT_POLICY{ + AccentState: w32.ACCENT_ENABLE_BLURBEHIND, + } + var data w32.WINDOWCOMPOSITIONATTRIBDATA + data.Attrib = w32.WCA_ACCENT_POLICY + data.PvData = unsafe.Pointer(&accent) + data.CbData = unsafe.Sizeof(accent) + + w32.SetWindowCompositionAttribute(cba.hwnd, &data) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func (cba *ControlBase) clampSize(width, height int) (int, int) { + if cba.minWidth != 0 { + width = max(width, cba.minWidth) + } + if cba.maxWidth != 0 { + width = min(width, cba.maxWidth) + } + if cba.minHeight != 0 { + height = max(height, cba.minHeight) + } + if cba.maxHeight != 0 { + height = min(height, cba.maxHeight) + } + return width, height +} + +func (cba *ControlBase) SetSize(width, height int) { + x, y := cba.Pos() + width, height = cba.clampSize(width, height) + width, height = cba.scaleWithWindowDPI(width, height) + w32.MoveWindow(cba.hwnd, x, y, width, height, true) +} + +func (cba *ControlBase) SetMinSize(width, height int) { + cba.minWidth = width + cba.minHeight = height + + // Ensure we set max if min > max + if cba.maxWidth > 0 { + cba.maxWidth = max(cba.minWidth, cba.maxWidth) + } + if cba.maxHeight > 0 { + cba.maxHeight = max(cba.minHeight, cba.maxHeight) + } + + x, y := cba.Pos() + currentWidth, currentHeight := cba.Size() + clampedWidth, clampedHeight := cba.clampSize(currentWidth, currentHeight) + if clampedWidth != currentWidth || clampedHeight != currentHeight { + w32.MoveWindow(cba.hwnd, x, y, clampedWidth, clampedHeight, true) + } +} +func (cba *ControlBase) SetMaxSize(width, height int) { + cba.maxWidth = width + cba.maxHeight = height + + // Ensure we set min if max > min + if cba.maxWidth > 0 { + cba.minWidth = min(cba.maxWidth, cba.minWidth) + } + if cba.maxHeight > 0 { + cba.minHeight = min(cba.maxHeight, cba.minHeight) + } + + x, y := cba.Pos() + currentWidth, currentHeight := cba.Size() + clampedWidth, clampedHeight := cba.clampSize(currentWidth, currentHeight) + if clampedWidth != currentWidth || clampedHeight != currentHeight { + w32.MoveWindow(cba.hwnd, x, y, clampedWidth, clampedHeight, true) + } +} + +func (cba *ControlBase) Size() (width, height int) { + rect := w32.GetWindowRect(cba.hwnd) + width = int(rect.Right - rect.Left) + height = int(rect.Bottom - rect.Top) + return +} + +func (cba *ControlBase) Width() int { + rect := w32.GetWindowRect(cba.hwnd) + return int(rect.Right - rect.Left) +} + +func (cba *ControlBase) Height() int { + rect := w32.GetWindowRect(cba.hwnd) + return int(rect.Bottom - rect.Top) +} + +func (cba *ControlBase) SetPos(x, y int) { + info := getMonitorInfo(cba.hwnd) + workRect := info.RcWork + + w32.SetWindowPos(cba.hwnd, w32.HWND_TOP, int(workRect.Left)+x, int(workRect.Top)+y, 0, 0, w32.SWP_NOSIZE) +} + +func (cba *ControlBase) Pos() (x, y int) { + rect := w32.GetWindowRect(cba.hwnd) + x = int(rect.Left) + y = int(rect.Top) + if !cba.isForm && cba.parent != nil { + x, y, _ = w32.ScreenToClient(cba.parent.Handle(), x, y) + } + return +} + +func (cba *ControlBase) Visible() bool { + return w32.IsWindowVisible(cba.hwnd) +} + +func (cba *ControlBase) ToggleVisible() bool { + visible := w32.IsWindowVisible(cba.hwnd) + if visible { + cba.Hide() + } else { + cba.Show() + } + return !visible +} + +func (cba *ControlBase) ContextMenu() *MenuItem { + return cba.contextMenu +} + +func (cba *ControlBase) SetContextMenu(menu *MenuItem) { + cba.contextMenu = menu +} + +func (cba *ControlBase) Bounds() *Rect { + rect := w32.GetWindowRect(cba.hwnd) + if cba.isForm { + return &Rect{*rect} + } + + return ScreenToClientRect(cba.hwnd, rect) +} + +func (cba *ControlBase) ClientRect() *Rect { + rect := w32.GetClientRect(cba.hwnd) + return ScreenToClientRect(cba.hwnd, rect) +} +func (cba *ControlBase) ClientWidth() int { + rect := w32.GetClientRect(cba.hwnd) + return int(rect.Right - rect.Left) +} + +func (cba *ControlBase) ClientHeight() int { + rect := w32.GetClientRect(cba.hwnd) + return int(rect.Bottom - rect.Top) +} + +func (cba *ControlBase) Show() { + w32.ShowWindow(cba.hwnd, w32.SW_SHOWDEFAULT) +} + +func (cba *ControlBase) Hide() { + w32.ShowWindow(cba.hwnd, w32.SW_HIDE) +} + +func (cba *ControlBase) Enabled() bool { + return w32.IsWindowEnabled(cba.hwnd) +} + +func (cba *ControlBase) SetEnabled(b bool) { + w32.EnableWindow(cba.hwnd, b) +} + +func (cba *ControlBase) SetFocus() { + w32.SetFocus(cba.hwnd) +} + +func (cba *ControlBase) Invalidate(erase bool) { + // pRect := w32.GetClientRect(cba.hwnd) + // if cba.isForm { + // w32.InvalidateRect(cba.hwnd, pRect, erase) + // } else { + // rc := ScreenToClientRect(cba.hwnd, pRect) + // w32.InvalidateRect(cba.hwnd, rc.GetW32Rect(), erase) + // } + w32.InvalidateRect(cba.hwnd, nil, erase) +} + +func (cba *ControlBase) Parent() Controller { + return cba.parent +} + +func (cba *ControlBase) SetParent(parent Controller) { + cba.parent = parent +} + +func (cba *ControlBase) Font() *Font { + return cba.font +} + +func (cba *ControlBase) SetFont(font *Font) { + w32.SendMessage(cba.hwnd, w32.WM_SETFONT, uintptr(font.hfont), 1) + cba.font = font +} + +func (cba *ControlBase) EnableDragAcceptFiles(b bool) { + w32.DragAcceptFiles(cba.hwnd, b) +} + +func (cba *ControlBase) InvokeRequired() bool { + if cba.hwnd == 0 { + return false + } + + windowThreadId, _ := w32.GetWindowThreadProcessId(cba.hwnd) + currentThreadId := w32.GetCurrentThreadId() + + return windowThreadId != currentThreadId +} + +func (cba *ControlBase) Invoke(f func()) { + if cba.tryInvokeOnCurrentGoRoutine(f) { + return + } + + cba.m.Lock() + cba.dispatchq = append(cba.dispatchq, f) + cba.m.Unlock() + w32.PostMessage(cba.hwnd, wmInvokeCallback, 0, 0) +} + +func (cba *ControlBase) PreTranslateMessage(msg *w32.MSG) bool { + if msg.Message == w32.WM_GETDLGCODE { + println("pretranslate, WM_GETDLGCODE") + } + return false +} + +//Events +func (cba *ControlBase) OnCreate() *EventManager { + return &cba.onCreate +} + +func (cba *ControlBase) OnClose() *EventManager { + return &cba.onClose +} + +func (cba *ControlBase) OnKillFocus() *EventManager { + return &cba.onKillFocus +} + +func (cba *ControlBase) OnSetFocus() *EventManager { + return &cba.onSetFocus +} + +func (cba *ControlBase) OnDropFiles() *EventManager { + return &cba.onDropFiles +} + +func (cba *ControlBase) OnLBDown() *EventManager { + return &cba.onLBDown +} + +func (cba *ControlBase) OnLBUp() *EventManager { + return &cba.onLBUp +} + +func (cba *ControlBase) OnLBDbl() *EventManager { + return &cba.onLBDbl +} + +func (cba *ControlBase) OnMBDown() *EventManager { + return &cba.onMBDown +} + +func (cba *ControlBase) OnMBUp() *EventManager { + return &cba.onMBUp +} + +func (cba *ControlBase) OnRBDown() *EventManager { + return &cba.onRBDown +} + +func (cba *ControlBase) OnRBUp() *EventManager { + return &cba.onRBUp +} + +func (cba *ControlBase) OnRBDbl() *EventManager { + return &cba.onRBDbl +} + +func (cba *ControlBase) OnMouseMove() *EventManager { + return &cba.onMouseMove +} + +func (cba *ControlBase) OnMouseHover() *EventManager { + return &cba.onMouseHover +} + +func (cba *ControlBase) OnMouseLeave() *EventManager { + return &cba.onMouseLeave +} + +func (cba *ControlBase) OnPaint() *EventManager { + return &cba.onPaint +} + +func (cba *ControlBase) OnSize() *EventManager { + return &cba.onSize +} + +func (cba *ControlBase) OnKeyUp() *EventManager { + return &cba.onKeyUp +} + +func (cba *ControlBase) scaleWithWindowDPI(width, height int) (int, int) { + dpix, dpiy := cba.GetWindowDPI() + scaledWidth := ScaleWithDPI(width, dpix) + scaledHeight := ScaleWithDPI(height, dpiy) + + return scaledWidth, scaledHeight +} + +func (cba *ControlBase) tryInvokeOnCurrentGoRoutine(f func()) bool { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if cba.InvokeRequired() { + return false + } + f() + return true +} + +func (cba *ControlBase) invokeCallbacks() { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if cba.InvokeRequired() { + panic("InvokeCallbacks must always be called on the window thread") + } + + cba.m.Lock() + q := append([]func(){}, cba.dispatchq...) + cba.dispatchq = []func(){} + cba.m.Unlock() + for _, v := range q { + v() + } +} diff --git a/v2/internal/frontend/desktop/windows/winc/controller.go b/v2/internal/frontend/desktop/windows/winc/controller.go new file mode 100644 index 000000000..4fd038818 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/controller.go @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Controller interface { + Text() string + + Enabled() bool + SetFocus() + + Handle() w32.HWND + Invalidate(erase bool) + Parent() Controller + + Pos() (x, y int) + Size() (w, h int) + Height() int + Width() int + Visible() bool + Bounds() *Rect + ClientRect() *Rect + + SetText(s string) + SetEnabled(b bool) + SetPos(x, y int) + SetSize(w, h int) + EnableDragAcceptFiles(b bool) + Show() + Hide() + + ContextMenu() *MenuItem + SetContextMenu(menu *MenuItem) + + Font() *Font + SetFont(font *Font) + InvokeRequired() bool + Invoke(func()) + PreTranslateMessage(msg *w32.MSG) bool + WndProc(msg uint32, wparam, lparam uintptr) uintptr + + //General events + OnCreate() *EventManager + OnClose() *EventManager + + // Focus events + OnKillFocus() *EventManager + OnSetFocus() *EventManager + + //Drag and drop events + OnDropFiles() *EventManager + + //Mouse events + OnLBDown() *EventManager + OnLBUp() *EventManager + OnLBDbl() *EventManager + OnMBDown() *EventManager + OnMBUp() *EventManager + OnRBDown() *EventManager + OnRBUp() *EventManager + OnRBDbl() *EventManager + OnMouseMove() *EventManager + + // OnMouseLeave and OnMouseHover does not fire unless control called internalTrackMouseEvent. + // Use MouseControl for a how to example. + OnMouseHover() *EventManager + OnMouseLeave() *EventManager + + //Keyboard events + OnKeyUp() *EventManager + + //Paint events + OnPaint() *EventManager + OnSize() *EventManager + + invokeCallbacks() +} diff --git a/v2/internal/frontend/desktop/windows/winc/dialog.go b/v2/internal/frontend/desktop/windows/winc/dialog.go new file mode 100644 index 000000000..721acbf7e --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/dialog.go @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + +// Dialog displayed as z-order top window until closed. +// It also disables parent window so it can not be clicked. +type Dialog struct { + Form + isModal bool + + btnOk *PushButton + btnCancel *PushButton + + onLoad EventManager + onOk EventManager + onCancel EventManager +} + +func NewDialog(parent Controller) *Dialog { + dlg := new(Dialog) + + dlg.isForm = true + dlg.isModal = true + RegClassOnlyOnce("winc_Dialog") + + dlg.hwnd = CreateWindow("winc_Dialog", parent, w32.WS_EX_CONTROLPARENT, /* IMPORTANT */ + w32.WS_SYSMENU|w32.WS_CAPTION|w32.WS_THICKFRAME /*|w32.WS_BORDER|w32.WS_POPUP*/) + dlg.parent = parent + + // dlg might fail if icon resource is not embedded in the binary + if ico, err := NewIconFromResource(GetAppInstance(), uint16(AppIconID)); err == nil { + dlg.SetIcon(0, ico) + } + + // Dlg forces display of focus rectangles, as soon as the user starts to type. + w32.SendMessage(dlg.hwnd, w32.WM_CHANGEUISTATE, w32.UIS_INITIALIZE, 0) + RegMsgHandler(dlg) + + dlg.SetFont(DefaultFont) + dlg.SetText("Form") + dlg.SetSize(200, 100) + return dlg +} + +func (dlg *Dialog) SetModal(modal bool) { + dlg.isModal = modal +} + +// SetButtons wires up dialog events to buttons. btnCancel can be nil. +func (dlg *Dialog) SetButtons(btnOk *PushButton, btnCancel *PushButton) { + dlg.btnOk = btnOk + dlg.btnOk.SetDefault() + dlg.btnCancel = btnCancel +} + +// Events +func (dlg *Dialog) OnLoad() *EventManager { + return &dlg.onLoad +} + +func (dlg *Dialog) OnOk() *EventManager { + return &dlg.onOk +} + +func (dlg *Dialog) OnCancel() *EventManager { + return &dlg.onCancel +} + +// PreTranslateMessage handles dialog specific messages. IMPORTANT. +func (dlg *Dialog) PreTranslateMessage(msg *w32.MSG) bool { + if msg.Message >= w32.WM_KEYFIRST && msg.Message <= w32.WM_KEYLAST { + if w32.IsDialogMessage(dlg.hwnd, msg) { + return true + } + } + return false +} + +// Show dialog performs special setup for dialog windows. +func (dlg *Dialog) Show() { + if dlg.isModal { + dlg.Parent().SetEnabled(false) + } + dlg.onLoad.Fire(NewEvent(dlg, nil)) + dlg.Form.Show() +} + +// Close dialog when you done with it. +func (dlg *Dialog) Close() { + if dlg.isModal { + dlg.Parent().SetEnabled(true) + } + dlg.ControlBase.Close() +} + +func (dlg *Dialog) cancel() { + if dlg.btnCancel != nil { + dlg.btnCancel.onClick.Fire(NewEvent(dlg.btnCancel, nil)) + } + dlg.onCancel.Fire(NewEvent(dlg, nil)) +} + +func (dlg *Dialog) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_COMMAND: + switch w32.LOWORD(uint32(wparam)) { + case w32.IDOK: + if dlg.btnOk != nil { + dlg.btnOk.onClick.Fire(NewEvent(dlg.btnOk, nil)) + } + dlg.onOk.Fire(NewEvent(dlg, nil)) + return w32.TRUE + + case w32.IDCANCEL: + dlg.cancel() + return w32.TRUE + } + + case w32.WM_CLOSE: + dlg.cancel() // use onCancel or dlg.btnCancel.OnClick to close + return 0 + + case w32.WM_DESTROY: + if dlg.isModal { + dlg.Parent().SetEnabled(true) + } + } + return w32.DefWindowProc(dlg.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/dock_topbottom.png b/v2/internal/frontend/desktop/windows/winc/dock_topbottom.png new file mode 100644 index 000000000..e6f1c6231 Binary files /dev/null and b/v2/internal/frontend/desktop/windows/winc/dock_topbottom.png differ diff --git a/v2/internal/frontend/desktop/windows/winc/dock_topleft.png b/v2/internal/frontend/desktop/windows/winc/dock_topleft.png new file mode 100644 index 000000000..242c93e39 Binary files /dev/null and b/v2/internal/frontend/desktop/windows/winc/dock_topleft.png differ diff --git a/v2/internal/frontend/desktop/windows/winc/edit.go b/v2/internal/frontend/desktop/windows/winc/edit.go new file mode 100644 index 000000000..f1eeb0bcb --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/edit.go @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + +type Edit struct { + ControlBase + onChange EventManager +} + +const passwordChar = '*' +const nopasswordChar = ' ' + +func NewEdit(parent Controller) *Edit { + edt := new(Edit) + + edt.InitControl("EDIT", parent, w32.WS_EX_CLIENTEDGE, w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.ES_LEFT| + w32.ES_AUTOHSCROLL) + RegMsgHandler(edt) + + edt.SetFont(DefaultFont) + edt.SetSize(200, 22) + return edt +} + +// Events. +func (ed *Edit) OnChange() *EventManager { + return &ed.onChange +} + +// Public methods. +func (ed *Edit) SetReadOnly(isReadOnly bool) { + w32.SendMessage(ed.hwnd, w32.EM_SETREADONLY, uintptr(w32.BoolToBOOL(isReadOnly)), 0) +} + +//Public methods +func (ed *Edit) SetPassword(isPassword bool) { + if isPassword { + w32.SendMessage(ed.hwnd, w32.EM_SETPASSWORDCHAR, uintptr(passwordChar), 0) + } else { + w32.SendMessage(ed.hwnd, w32.EM_SETPASSWORDCHAR, 0, 0) + } +} + +func (ed *Edit) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_COMMAND: + switch w32.HIWORD(uint32(wparam)) { + case w32.EN_CHANGE: + ed.onChange.Fire(NewEvent(ed, nil)) + } + /*case w32.WM_GETDLGCODE: + println("Edit") + if wparam == w32.VK_RETURN { + return w32.DLGC_WANTALLKEYS + }*/ + } + return w32.DefWindowProc(ed.hwnd, msg, wparam, lparam) +} + +// MultiEdit is multiline text edit. +type MultiEdit struct { + ControlBase + onChange EventManager +} + +func NewMultiEdit(parent Controller) *MultiEdit { + med := new(MultiEdit) + + med.InitControl("EDIT", parent, w32.WS_EX_CLIENTEDGE, w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.ES_LEFT| + w32.WS_VSCROLL|w32.WS_HSCROLL|w32.ES_MULTILINE|w32.ES_WANTRETURN|w32.ES_AUTOHSCROLL|w32.ES_AUTOVSCROLL) + RegMsgHandler(med) + + med.SetFont(DefaultFont) + med.SetSize(200, 400) + return med +} + +// Events +func (med *MultiEdit) OnChange() *EventManager { + return &med.onChange +} + +// Public methods +func (med *MultiEdit) SetReadOnly(isReadOnly bool) { + w32.SendMessage(med.hwnd, w32.EM_SETREADONLY, uintptr(w32.BoolToBOOL(isReadOnly)), 0) +} + +func (med *MultiEdit) AddLine(text string) { + if len(med.Text()) == 0 { + med.SetText(text) + } else { + med.SetText(med.Text() + "\r\n" + text) + } +} + +func (med *MultiEdit) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + + case w32.WM_COMMAND: + switch w32.HIWORD(uint32(wparam)) { + case w32.EN_CHANGE: + med.onChange.Fire(NewEvent(med, nil)) + } + } + return w32.DefWindowProc(med.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/event.go b/v2/internal/frontend/desktop/windows/winc/event.go new file mode 100644 index 000000000..66feabd04 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/event.go @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +type Event struct { + Sender Controller + Data interface{} +} + +func NewEvent(sender Controller, data interface{}) *Event { + return &Event{Sender: sender, Data: data} +} diff --git a/v2/internal/frontend/desktop/windows/winc/eventdata.go b/v2/internal/frontend/desktop/windows/winc/eventdata.go new file mode 100644 index 000000000..51bd0bffd --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/eventdata.go @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type RawMsg struct { + Hwnd w32.HWND + Msg uint32 + WParam, LParam uintptr +} + +type MouseEventData struct { + X, Y int + Button int + Wheel int +} + +type DropFilesEventData struct { + X, Y int + Files []string +} + +type PaintEventData struct { + Canvas *Canvas +} + +type LabelEditEventData struct { + Item ListItem + Text string + //PszText *uint16 +} + +/*type LVDBLClickEventData struct { + NmItem *w32.NMITEMACTIVATE +}*/ + +type KeyUpEventData struct { + VKey, Code int +} + +type SizeEventData struct { + Type uint + X, Y int +} diff --git a/v2/internal/frontend/desktop/windows/winc/eventmanager.go b/v2/internal/frontend/desktop/windows/winc/eventmanager.go new file mode 100644 index 000000000..9769f50f9 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/eventmanager.go @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +type EventHandler func(arg *Event) + +type EventManager struct { + handler EventHandler +} + +func (evm *EventManager) Fire(arg *Event) { + if evm.handler != nil { + evm.handler(arg) + } +} + +func (evm *EventManager) Bind(handler EventHandler) { + evm.handler = handler +} diff --git a/v2/internal/frontend/desktop/windows/winc/font.go b/v2/internal/frontend/desktop/windows/winc/font.go new file mode 100644 index 000000000..f79353bef --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/font.go @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +const ( + FontBold byte = 0x01 + FontItalic byte = 0x02 + FontUnderline byte = 0x04 + FontStrikeOut byte = 0x08 +) + +func init() { + DefaultFont = NewFont("MS Shell Dlg 2", 8, 0) +} + +type Font struct { + hfont w32.HFONT + family string + pointSize int + style byte +} + +func NewFont(family string, pointSize int, style byte) *Font { + if style > FontBold|FontItalic|FontUnderline|FontStrikeOut { + panic("Invalid font style") + } + + //Retrive screen DPI + hDC := w32.GetDC(0) + defer w32.ReleaseDC(0, hDC) + screenDPIY := w32.GetDeviceCaps(hDC, w32.LOGPIXELSY) + + font := Font{ + family: family, + pointSize: pointSize, + style: style, + } + + font.hfont = font.createForDPI(screenDPIY) + if font.hfont == 0 { + panic("CreateFontIndirect failed") + } + + return &font +} + +func (fnt *Font) createForDPI(dpi int) w32.HFONT { + var lf w32.LOGFONT + + lf.Height = int32(-w32.MulDiv(fnt.pointSize, dpi, 72)) + if fnt.style&FontBold > 0 { + lf.Weight = w32.FW_BOLD + } else { + lf.Weight = w32.FW_NORMAL + } + if fnt.style&FontItalic > 0 { + lf.Italic = 1 + } + if fnt.style&FontUnderline > 0 { + lf.Underline = 1 + } + if fnt.style&FontStrikeOut > 0 { + lf.StrikeOut = 1 + } + lf.CharSet = w32.DEFAULT_CHARSET + lf.OutPrecision = w32.OUT_TT_PRECIS + lf.ClipPrecision = w32.CLIP_DEFAULT_PRECIS + lf.Quality = w32.CLEARTYPE_QUALITY + lf.PitchAndFamily = w32.VARIABLE_PITCH | w32.FF_SWISS + + src := syscall.StringToUTF16(fnt.family) + dest := lf.FaceName[:] + copy(dest, src) + + return w32.CreateFontIndirect(&lf) +} + +func (fnt *Font) GetHFONT() w32.HFONT { + return fnt.hfont +} + +func (fnt *Font) Bold() bool { + return fnt.style&FontBold > 0 +} + +func (fnt *Font) Dispose() { + if fnt.hfont != 0 { + w32.DeleteObject(w32.HGDIOBJ(fnt.hfont)) + } +} + +func (fnt *Font) Family() string { + return fnt.family +} + +func (fnt *Font) Italic() bool { + return fnt.style&FontItalic > 0 +} + +func (fnt *Font) StrikeOut() bool { + return fnt.style&FontStrikeOut > 0 +} + +func (fnt *Font) Underline() bool { + return fnt.style&FontUnderline > 0 +} + +func (fnt *Font) Style() byte { + return fnt.style +} diff --git a/v2/internal/frontend/desktop/windows/winc/form.go b/v2/internal/frontend/desktop/windows/winc/form.go new file mode 100644 index 000000000..b146dbf29 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/form.go @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type LayoutManager interface { + Update() +} + +// A Form is main window of the application. +type Form struct { + ControlBase + + layoutMng LayoutManager + + // Fullscreen / Unfullscreen + isFullscreen bool + previousWindowStyle uint32 + previousWindowPlacement w32.WINDOWPLACEMENT +} + +func NewCustomForm(parent Controller, exStyle int, dwStyle uint) *Form { + fm := new(Form) + + RegClassOnlyOnce("winc_Form") + + fm.isForm = true + + if exStyle == 0 { + exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW + } + + if dwStyle == 0 { + dwStyle = w32.WS_OVERLAPPEDWINDOW + } + + fm.hwnd = CreateWindow("winc_Form", parent, uint(exStyle), dwStyle) + fm.parent = parent + + // this might fail if icon resource is not embedded in the binary + if ico, err := NewIconFromResource(GetAppInstance(), uint16(AppIconID)); err == nil { + fm.SetIcon(0, ico) + } + + // This forces display of focus rectangles, as soon as the user starts to type. + w32.SendMessage(fm.hwnd, w32.WM_CHANGEUISTATE, w32.UIS_INITIALIZE, 0) + + RegMsgHandler(fm) + + fm.SetFont(DefaultFont) + fm.SetText("Form") + return fm +} + +func NewForm(parent Controller) *Form { + fm := new(Form) + + RegClassOnlyOnce("winc_Form") + + fm.isForm = true + fm.hwnd = CreateWindow("winc_Form", parent, w32.WS_EX_CONTROLPARENT|w32.WS_EX_APPWINDOW, w32.WS_OVERLAPPEDWINDOW) + fm.parent = parent + + // this might fail if icon resource is not embedded in the binary + if ico, err := NewIconFromResource(GetAppInstance(), uint16(AppIconID)); err == nil { + fm.SetIcon(0, ico) + } + + // This forces display of focus rectangles, as soon as the user starts to type. + w32.SendMessage(fm.hwnd, w32.WM_CHANGEUISTATE, w32.UIS_INITIALIZE, 0) + + RegMsgHandler(fm) + + fm.SetFont(DefaultFont) + fm.SetText("Form") + return fm +} + +func (fm *Form) SetLayout(mng LayoutManager) { + fm.layoutMng = mng +} + +// UpdateLayout refresh layout. +func (fm *Form) UpdateLayout() { + if fm.layoutMng != nil { + fm.layoutMng.Update() + } +} + +func (fm *Form) NewMenu() *Menu { + hMenu := w32.CreateMenu() + if hMenu == 0 { + panic("failed CreateMenu") + } + m := &Menu{hMenu: hMenu, hwnd: fm.hwnd} + if !w32.SetMenu(fm.hwnd, hMenu) { + panic("failed SetMenu") + } + return m +} + +func (fm *Form) DisableIcon() { + windowInfo := getWindowInfo(fm.hwnd) + frameless := windowInfo.IsPopup() + if frameless { + return + } + exStyle := w32.GetWindowLong(fm.hwnd, w32.GWL_EXSTYLE) + w32.SetWindowLong(fm.hwnd, w32.GWL_EXSTYLE, uint32(exStyle|w32.WS_EX_DLGMODALFRAME)) + w32.SetWindowPos(fm.hwnd, 0, 0, 0, 0, 0, + uint( + w32.SWP_FRAMECHANGED| + w32.SWP_NOMOVE| + w32.SWP_NOSIZE| + w32.SWP_NOZORDER), + ) +} + +func (fm *Form) Maximise() { + w32.ShowWindow(fm.hwnd, w32.SW_MAXIMIZE) +} + +func (fm *Form) Minimise() { + w32.ShowWindow(fm.hwnd, w32.SW_MINIMIZE) +} + +func (fm *Form) Restore() { + w32.ShowWindow(fm.hwnd, w32.SW_RESTORE) +} + +// Public methods +func (fm *Form) Center() { + + windowInfo := getWindowInfo(fm.hwnd) + frameless := windowInfo.IsPopup() + + info := getMonitorInfo(fm.hwnd) + workRect := info.RcWork + screenMiddleW := workRect.Left + (workRect.Right-workRect.Left)/2 + screenMiddleH := workRect.Top + (workRect.Bottom-workRect.Top)/2 + var winRect *w32.RECT + if !frameless { + winRect = w32.GetWindowRect(fm.hwnd) + } else { + winRect = w32.GetClientRect(fm.hwnd) + } + winWidth := winRect.Right - winRect.Left + winHeight := winRect.Bottom - winRect.Top + windowX := screenMiddleW - (winWidth / 2) + windowY := screenMiddleH - (winHeight / 2) + w32.SetWindowPos(fm.hwnd, w32.HWND_TOP, int(windowX), int(windowY), int(winWidth), int(winHeight), w32.SWP_NOSIZE) +} + +func (fm *Form) Fullscreen() { + if fm.isFullscreen { + return + } + + fm.previousWindowStyle = uint32(w32.GetWindowLongPtr(fm.hwnd, w32.GWL_STYLE)) + monitor := w32.MonitorFromWindow(fm.hwnd, w32.MONITOR_DEFAULTTOPRIMARY) + var monitorInfo w32.MONITORINFO + monitorInfo.CbSize = uint32(unsafe.Sizeof(monitorInfo)) + if !w32.GetMonitorInfo(monitor, &monitorInfo) { + return + } + if !w32.GetWindowPlacement(fm.hwnd, &fm.previousWindowPlacement) { + return + } + w32.SetWindowLong(fm.hwnd, w32.GWL_STYLE, fm.previousWindowStyle & ^uint32(w32.WS_OVERLAPPEDWINDOW)) + w32.SetWindowPos(fm.hwnd, w32.HWND_TOP, + int(monitorInfo.RcMonitor.Left), + int(monitorInfo.RcMonitor.Top), + int(monitorInfo.RcMonitor.Right-monitorInfo.RcMonitor.Left), + int(monitorInfo.RcMonitor.Bottom-monitorInfo.RcMonitor.Top), + w32.SWP_NOOWNERZORDER|w32.SWP_FRAMECHANGED) + fm.isFullscreen = true +} + +func (fm *Form) UnFullscreen() { + if !fm.isFullscreen { + return + } + w32.SetWindowLong(fm.hwnd, w32.GWL_STYLE, fm.previousWindowStyle) + w32.SetWindowPlacement(fm.hwnd, &fm.previousWindowPlacement) + w32.SetWindowPos(fm.hwnd, 0, 0, 0, 0, 0, + w32.SWP_NOMOVE|w32.SWP_NOSIZE|w32.SWP_NOZORDER|w32.SWP_NOOWNERZORDER|w32.SWP_FRAMECHANGED) + fm.isFullscreen = false +} + +func (fm *Form) IsFullScreen() bool { + return fm.isFullscreen +} + +// IconType: 1 - ICON_BIG; 0 - ICON_SMALL +func (fm *Form) SetIcon(iconType int, icon *Icon) { + if iconType > 1 { + panic("IconType is invalid") + } + w32.SendMessage(fm.hwnd, w32.WM_SETICON, uintptr(iconType), uintptr(icon.Handle())) +} + +func (fm *Form) EnableMaxButton(b bool) { + SetStyle(fm.hwnd, b, w32.WS_MAXIMIZEBOX) +} + +func (fm *Form) EnableMinButton(b bool) { + SetStyle(fm.hwnd, b, w32.WS_MINIMIZEBOX) +} + +func (fm *Form) EnableSizable(b bool) { + SetStyle(fm.hwnd, b, w32.WS_THICKFRAME) +} + +func (fm *Form) EnableDragMove(_ bool) { + //fm.isDragMove = b +} + +func (fm *Form) EnableTopMost(b bool) { + tag := w32.HWND_NOTOPMOST + if b { + tag = w32.HWND_TOPMOST + } + w32.SetWindowPos(fm.hwnd, tag, 0, 0, 0, 0, w32.SWP_NOMOVE|w32.SWP_NOSIZE) +} + +func (fm *Form) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + + switch msg { + case w32.WM_COMMAND: + if lparam == 0 && w32.HIWORD(uint32(wparam)) == 0 { + // Menu support. + actionID := uint16(w32.LOWORD(uint32(wparam))) + if action, ok := actionsByID[actionID]; ok { + action.onClick.Fire(NewEvent(fm, nil)) + } + } + case w32.WM_KEYDOWN: + // Accelerator support. + key := Key(wparam) + if uint32(lparam)>>30 == 0 { + // Using TranslateAccelerators refused to work, so we handle them + // ourselves, at least for now. + shortcut := Shortcut{ModifiersDown(), key} + if action, ok := shortcut2Action[shortcut]; ok { + if action.Enabled() { + action.onClick.Fire(NewEvent(fm, nil)) + } + } + } + + case w32.WM_CLOSE: + return 0 + case w32.WM_DESTROY: + w32.PostQuitMessage(0) + return 0 + + case w32.WM_SIZE, w32.WM_PAINT: + if fm.layoutMng != nil { + fm.layoutMng.Update() + } + case w32.WM_GETMINMAXINFO: + mmi := (*w32.MINMAXINFO)(unsafe.Pointer(lparam)) + hasConstraints := false + if fm.minWidth > 0 || fm.minHeight > 0 { + hasConstraints = true + + width, height := fm.scaleWithWindowDPI(fm.minWidth, fm.minHeight) + if width > 0 { + mmi.PtMinTrackSize.X = int32(width) + } + if height > 0 { + mmi.PtMinTrackSize.Y = int32(height) + } + } + if fm.maxWidth > 0 || fm.maxHeight > 0 { + hasConstraints = true + + width, height := fm.scaleWithWindowDPI(fm.maxWidth, fm.maxHeight) + if width > 0 { + mmi.PtMaxTrackSize.X = int32(width) + } + if height > 0 { + mmi.PtMaxTrackSize.Y = int32(height) + } + } + if hasConstraints { + return 0 + } + } + + return w32.DefWindowProc(fm.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/globalvars.go b/v2/internal/frontend/desktop/windows/winc/globalvars.go new file mode 100644 index 000000000..c3da17a6a --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/globalvars.go @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +//Private global variables. +var ( + gAppInstance w32.HINSTANCE + gControllerRegistry map[w32.HWND]Controller + gRegisteredClasses []string +) + +//Public global variables. +var ( + GeneralWndprocCallBack = syscall.NewCallback(generalWndProc) + DefaultFont *Font +) diff --git a/v2/internal/frontend/desktop/windows/winc/icon.go b/v2/internal/frontend/desktop/windows/winc/icon.go new file mode 100644 index 000000000..97bc79b2c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/icon.go @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "errors" + "fmt" + "syscall" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Icon struct { + handle w32.HICON +} + +func NewIconFromFile(path string) (*Icon, error) { + ico := new(Icon) + var err error + if ico.handle = w32.LoadIcon(0, syscall.StringToUTF16Ptr(path)); ico.handle == 0 { + err = errors.New(fmt.Sprintf("Cannot load icon from %s", path)) + } + return ico, err +} + +func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (*Icon, error) { + ico := new(Icon) + var err error + if ico.handle = w32.LoadIcon(instance, w32.MakeIntResource(resId)); ico.handle == 0 { + err = errors.New(fmt.Sprintf("Cannot load icon from resource with id %v", resId)) + } + return ico, err +} + +func ExtractIcon(fileName string, index int) (*Icon, error) { + ico := new(Icon) + var err error + if ico.handle = w32.ExtractIcon(fileName, index); ico.handle == 0 || ico.handle == 1 { + err = errors.New(fmt.Sprintf("Cannot extract icon from %s at index %v", fileName, index)) + } + return ico, err +} + +func (ic *Icon) Destroy() bool { + return w32.DestroyIcon(ic.handle) +} + +func (ic *Icon) Handle() w32.HICON { + return ic.handle +} diff --git a/v2/internal/frontend/desktop/windows/winc/imagelist.go b/v2/internal/frontend/desktop/windows/winc/imagelist.go new file mode 100644 index 000000000..45bf32f80 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/imagelist.go @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ImageList struct { + handle w32.HIMAGELIST +} + +func NewImageList(cx, cy int) *ImageList { + return newImageList(cx, cy, w32.ILC_COLOR32, 0, 0) +} + +func newImageList(cx, cy int, flags uint, cInitial, cGrow int) *ImageList { + imgl := new(ImageList) + imgl.handle = w32.ImageList_Create(cx, cy, flags, cInitial, cGrow) + return imgl +} + +func (im *ImageList) Handle() w32.HIMAGELIST { + return im.handle +} + +func (im *ImageList) Destroy() bool { + return w32.ImageList_Destroy(im.handle) +} + +func (im *ImageList) SetImageCount(uNewCount uint) bool { + return w32.ImageList_SetImageCount(im.handle, uNewCount) +} + +func (im *ImageList) ImageCount() int { + return w32.ImageList_GetImageCount(im.handle) +} + +func (im *ImageList) AddIcon(icon *Icon) int { + return w32.ImageList_AddIcon(im.handle, icon.Handle()) +} + +func (im *ImageList) AddResIcon(iconID uint16) { + if ico, err := NewIconFromResource(GetAppInstance(), iconID); err == nil { + im.AddIcon(ico) + return + } + panic(fmt.Sprintf("missing icon with icon ID: %d", iconID)) +} + +func (im *ImageList) RemoveAll() bool { + return w32.ImageList_RemoveAll(im.handle) +} + +func (im *ImageList) Remove(i int) bool { + return w32.ImageList_Remove(im.handle, i) +} diff --git a/v2/internal/frontend/desktop/windows/winc/imageview.go b/v2/internal/frontend/desktop/windows/winc/imageview.go new file mode 100644 index 000000000..acd4856f8 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/imageview.go @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + +type ImageView struct { + ControlBase + + bmp *Bitmap +} + +func NewImageView(parent Controller) *ImageView { + iv := new(ImageView) + + iv.InitWindow("winc_ImageView", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + RegMsgHandler(iv) + + iv.SetFont(DefaultFont) + iv.SetText("") + iv.SetSize(200, 65) + return iv +} + +func (iv *ImageView) DrawImageFile(filepath string) error { + bmp, err := NewBitmapFromFile(filepath, RGB(255, 255, 0)) + if err != nil { + return err + } + iv.bmp = bmp + return nil +} + +func (iv *ImageView) DrawImage(bmp *Bitmap) { + iv.bmp = bmp +} + +func (iv *ImageView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_SIZE, w32.WM_SIZING: + iv.Invalidate(true) + + case w32.WM_ERASEBKGND: + return 1 // important + + case w32.WM_PAINT: + if iv.bmp != nil { + canvas := NewCanvasFromHwnd(iv.hwnd) + defer canvas.Dispose() + iv.SetSize(iv.bmp.Size()) + canvas.DrawBitmap(iv.bmp, 0, 0) + } + } + return w32.DefWindowProc(iv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/imageviewbox.go b/v2/internal/frontend/desktop/windows/winc/imageviewbox.go new file mode 100644 index 000000000..be97a4435 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/imageviewbox.go @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "time" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type direction int + +const ( + DirNone direction = iota + DirX + DirY + DirX2 + DirY2 +) + +var ImageBoxPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(140, 140, 220))) +var ImageBoxHiPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(220, 140, 140))) +var ImageBoxMarkBrush = NewSolidColorBrush(RGB(40, 40, 40)) +var ImageBoxMarkPen = NewPen(w32.PS_GEOMETRIC, 2, ImageBoxMarkBrush) + +type ImageBox struct { + Name string + Type int + X, Y, X2, Y2 int + + underMouse bool // dynamic value +} + +func (b *ImageBox) Rect() *Rect { + return NewRect(b.X, b.Y, b.X2, b.Y2) +} + +// ImageViewBox is image view with boxes. +type ImageViewBox struct { + ControlBase + + bmp *Bitmap + mouseLeft bool + modified bool // used by GUI to see if any image box modified + + add bool + + Boxes []*ImageBox // might be persisted to file + dragBox *ImageBox + selBox *ImageBox + + dragStartX, dragStartY int + resize direction + + onSelectedChange EventManager + onAdd EventManager + onModify EventManager +} + +func NewImageViewBox(parent Controller) *ImageViewBox { + iv := new(ImageViewBox) + + iv.InitWindow("winc_ImageViewBox", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + RegMsgHandler(iv) + + iv.SetFont(DefaultFont) + iv.SetText("") + iv.SetSize(200, 65) + + return iv +} + +func (iv *ImageViewBox) OnSelectedChange() *EventManager { + return &iv.onSelectedChange +} + +func (iv *ImageViewBox) OnAdd() *EventManager { + return &iv.onAdd +} + +func (iv *ImageViewBox) OnModify() *EventManager { + return &iv.onModify +} + +func (iv *ImageViewBox) IsModified() bool { return iv.modified } +func (iv *ImageViewBox) SetModified(modified bool) { iv.modified = modified } +func (iv *ImageViewBox) IsLoaded() bool { return iv.bmp != nil } +func (iv *ImageViewBox) AddMode() bool { return iv.add } +func (iv *ImageViewBox) SetAddMode(add bool) { iv.add = add } +func (iv *ImageViewBox) HasSelected() bool { return iv.selBox != nil && iv.bmp != nil } + +func (iv *ImageViewBox) wasModified() { + iv.modified = true + iv.onModify.Fire(NewEvent(iv, nil)) +} + +func (iv *ImageViewBox) DeleteSelected() { + if iv.selBox != nil { + for i, b := range iv.Boxes { + if b == iv.selBox { + iv.Boxes = append(iv.Boxes[:i], iv.Boxes[i+1:]...) + iv.selBox = nil + iv.Invalidate(true) + iv.wasModified() + iv.onSelectedChange.Fire(NewEvent(iv, nil)) + return + } + } + } +} + +func (iv *ImageViewBox) NameSelected() string { + if iv.selBox != nil { + return iv.selBox.Name + } + return "" +} + +func (iv *ImageViewBox) SetNameSelected(name string) { + if iv.selBox != nil { + iv.selBox.Name = name + iv.wasModified() + } +} + +func (iv *ImageViewBox) TypeSelected() int { + if iv.selBox != nil { + return iv.selBox.Type + } + return 0 +} + +func (iv *ImageViewBox) SetTypeSelected(typ int) { + if iv.selBox != nil { + iv.selBox.Type = typ + iv.wasModified() + } +} + +func (ib *ImageViewBox) updateHighlight(x, y int) bool { + var changed bool + for _, b := range ib.Boxes { + under := x >= b.X && y >= b.Y && x <= b.X2 && y <= b.Y2 + if b.underMouse != under { + changed = true + } + b.underMouse = under + /*if sel { + break // allow only one to be underMouse + }*/ + } + return changed +} + +func (ib *ImageViewBox) isUnderMouse(x, y int) *ImageBox { + for _, b := range ib.Boxes { + if x >= b.X && y >= b.Y && x <= b.X2 && y <= b.Y2 { + return b + } + } + return nil +} + +func (ib *ImageViewBox) getCursor(x, y int) uint16 { + for _, b := range ib.Boxes { + switch d := ib.resizingDirection(b, x, y); d { + case DirY, DirY2: + return w32.IDC_SIZENS + case DirX, DirX2: + return w32.IDC_SIZEWE + } + // w32.IDC_SIZEALL or w32.IDC_SIZE for resize + } + return w32.IDC_ARROW +} + +func (ib *ImageViewBox) resizingDirection(b *ImageBox, x, y int) direction { + if b == nil { + return DirNone + } + switch { + case b.X == x || b.X == x-1 || b.X == x+1: + return DirX + case b.X2 == x || b.X2 == x-1 || b.X2 == x+1: + return DirX2 + case b.Y == y || b.Y == y-1 || b.Y == y+1: + return DirY + case b.Y2 == y || b.Y2 == y-1 || b.Y2 == y+1: + return DirY2 + } + return DirNone +} + +func (ib *ImageViewBox) resizeToDirection(b *ImageBox, x, y int) { + switch ib.resize { + case DirX: + b.X = x + case DirY: + b.Y = y + case DirX2: + b.X2 = x + case DirY2: + b.Y2 = y + } +} + +func (ib *ImageViewBox) drag(b *ImageBox, x, y int) { + w, h := b.X2-b.X, b.Y2-b.Y + + nx := ib.dragStartX - b.X + ny := ib.dragStartY - b.Y + + b.X = x - nx + b.Y = y - ny + b.X2 = b.X + w + b.Y2 = b.Y + h + + ib.dragStartX, ib.dragStartY = x, y +} + +func (iv *ImageViewBox) DrawImageFile(filepath string) (err error) { + iv.bmp, err = NewBitmapFromFile(filepath, RGB(255, 255, 0)) + iv.selBox = nil + iv.modified = false + iv.onSelectedChange.Fire(NewEvent(iv, nil)) + iv.onModify.Fire(NewEvent(iv, nil)) + return +} + +func (iv *ImageViewBox) DrawImage(bmp *Bitmap) { + iv.bmp = bmp + iv.selBox = nil + iv.modified = false + iv.onSelectedChange.Fire(NewEvent(iv, nil)) + iv.onModify.Fire(NewEvent(iv, nil)) +} + +func (iv *ImageViewBox) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_SIZE, w32.WM_SIZING: + iv.Invalidate(true) + + case w32.WM_ERASEBKGND: + return 1 // important + + case w32.WM_CREATE: + internalTrackMouseEvent(iv.hwnd) + + case w32.WM_PAINT: + if iv.bmp != nil { + canvas := NewCanvasFromHwnd(iv.hwnd) + defer canvas.Dispose() + iv.SetSize(iv.bmp.Size()) + canvas.DrawBitmap(iv.bmp, 0, 0) + + for _, b := range iv.Boxes { + // old code used NewSystemColorBrush(w32.COLOR_BTNFACE) w32.COLOR_WINDOW + pen := ImageBoxPen + if b.underMouse { + pen = ImageBoxHiPen + } + canvas.DrawRect(b.Rect(), pen) + + if b == iv.selBox { + x1 := []int{b.X, b.X2, b.X2, b.X} + y1 := []int{b.Y, b.Y, b.Y2, b.Y2} + + for i := 0; i < len(x1); i++ { + r := NewRect(x1[i]-2, y1[i]-2, x1[i]+2, y1[i]+2) + canvas.DrawFillRect(r, ImageBoxMarkPen, ImageBoxMarkBrush) + } + + } + } + } + + case w32.WM_MOUSEMOVE: + x, y := genPoint(lparam) + + if iv.dragBox != nil { + if iv.resize == DirNone { + iv.drag(iv.dragBox, x, y) + iv.wasModified() + } else { + iv.resizeToDirection(iv.dragBox, x, y) + iv.wasModified() + } + iv.Invalidate(true) + + } else { + if !iv.add { + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(iv.getCursor(x, y)))) + } + // do not call repaint if underMouse item did not change. + if iv.updateHighlight(x, y) { + iv.Invalidate(true) + } + } + + if iv.mouseLeft { + internalTrackMouseEvent(iv.hwnd) + iv.mouseLeft = false + } + + case w32.WM_MOUSELEAVE: + iv.dragBox = nil + iv.mouseLeft = true + iv.updateHighlight(-1, -1) + iv.Invalidate(true) + + case w32.WM_LBUTTONUP: + iv.dragBox = nil + + case w32.WM_LBUTTONDOWN: + x, y := genPoint(lparam) + if iv.add { + now := time.Now() + s := fmt.Sprintf("field%s", now.Format("020405")) + b := &ImageBox{Name: s, underMouse: true, X: x, Y: y, X2: x + 150, Y2: y + 30} + iv.Boxes = append(iv.Boxes, b) + iv.selBox = b + iv.wasModified() + iv.onAdd.Fire(NewEvent(iv, nil)) + } else { + iv.dragBox = iv.isUnderMouse(x, y) + iv.selBox = iv.dragBox + iv.dragStartX, iv.dragStartY = x, y + iv.resize = iv.resizingDirection(iv.dragBox, x, y) + } + iv.Invalidate(true) + iv.onSelectedChange.Fire(NewEvent(iv, nil)) + + case w32.WM_RBUTTONDOWN: + + } + return w32.DefWindowProc(iv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/init.go b/v2/internal/frontend/desktop/windows/winc/init.go new file mode 100644 index 000000000..8ec9e80c0 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/init.go @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +func init() { + gControllerRegistry = make(map[w32.HWND]Controller) + gRegisteredClasses = make([]string, 0) + + var si w32.GdiplusStartupInput + si.GdiplusVersion = 1 + w32.GdiplusStartup(&si, nil) +} diff --git a/v2/internal/frontend/desktop/windows/winc/keyboard.go b/v2/internal/frontend/desktop/windows/winc/keyboard.go new file mode 100644 index 000000000..ea38fd986 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/keyboard.go @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "bytes" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Key uint16 + +func (k Key) String() string { + return key2string[k] +} + +const ( + KeyLButton Key = w32.VK_LBUTTON + KeyRButton Key = w32.VK_RBUTTON + KeyCancel Key = w32.VK_CANCEL + KeyMButton Key = w32.VK_MBUTTON + KeyXButton1 Key = w32.VK_XBUTTON1 + KeyXButton2 Key = w32.VK_XBUTTON2 + KeyBack Key = w32.VK_BACK + KeyTab Key = w32.VK_TAB + KeyClear Key = w32.VK_CLEAR + KeyReturn Key = w32.VK_RETURN + KeyShift Key = w32.VK_SHIFT + KeyControl Key = w32.VK_CONTROL + KeyAlt Key = w32.VK_MENU + KeyMenu Key = w32.VK_MENU + KeyPause Key = w32.VK_PAUSE + KeyCapital Key = w32.VK_CAPITAL + KeyKana Key = w32.VK_KANA + KeyHangul Key = w32.VK_HANGUL + KeyJunja Key = w32.VK_JUNJA + KeyFinal Key = w32.VK_FINAL + KeyHanja Key = w32.VK_HANJA + KeyKanji Key = w32.VK_KANJI + KeyEscape Key = w32.VK_ESCAPE + KeyConvert Key = w32.VK_CONVERT + KeyNonconvert Key = w32.VK_NONCONVERT + KeyAccept Key = w32.VK_ACCEPT + KeyModeChange Key = w32.VK_MODECHANGE + KeySpace Key = w32.VK_SPACE + KeyPrior Key = w32.VK_PRIOR + KeyNext Key = w32.VK_NEXT + KeyEnd Key = w32.VK_END + KeyHome Key = w32.VK_HOME + KeyLeft Key = w32.VK_LEFT + KeyUp Key = w32.VK_UP + KeyRight Key = w32.VK_RIGHT + KeyDown Key = w32.VK_DOWN + KeySelect Key = w32.VK_SELECT + KeyPrint Key = w32.VK_PRINT + KeyExecute Key = w32.VK_EXECUTE + KeySnapshot Key = w32.VK_SNAPSHOT + KeyInsert Key = w32.VK_INSERT + KeyDelete Key = w32.VK_DELETE + KeyHelp Key = w32.VK_HELP + Key0 Key = 0x30 + Key1 Key = 0x31 + Key2 Key = 0x32 + Key3 Key = 0x33 + Key4 Key = 0x34 + Key5 Key = 0x35 + Key6 Key = 0x36 + Key7 Key = 0x37 + Key8 Key = 0x38 + Key9 Key = 0x39 + KeyA Key = 0x41 + KeyB Key = 0x42 + KeyC Key = 0x43 + KeyD Key = 0x44 + KeyE Key = 0x45 + KeyF Key = 0x46 + KeyG Key = 0x47 + KeyH Key = 0x48 + KeyI Key = 0x49 + KeyJ Key = 0x4A + KeyK Key = 0x4B + KeyL Key = 0x4C + KeyM Key = 0x4D + KeyN Key = 0x4E + KeyO Key = 0x4F + KeyP Key = 0x50 + KeyQ Key = 0x51 + KeyR Key = 0x52 + KeyS Key = 0x53 + KeyT Key = 0x54 + KeyU Key = 0x55 + KeyV Key = 0x56 + KeyW Key = 0x57 + KeyX Key = 0x58 + KeyY Key = 0x59 + KeyZ Key = 0x5A + KeyLWIN Key = w32.VK_LWIN + KeyRWIN Key = w32.VK_RWIN + KeyApps Key = w32.VK_APPS + KeySleep Key = w32.VK_SLEEP + KeyNumpad0 Key = w32.VK_NUMPAD0 + KeyNumpad1 Key = w32.VK_NUMPAD1 + KeyNumpad2 Key = w32.VK_NUMPAD2 + KeyNumpad3 Key = w32.VK_NUMPAD3 + KeyNumpad4 Key = w32.VK_NUMPAD4 + KeyNumpad5 Key = w32.VK_NUMPAD5 + KeyNumpad6 Key = w32.VK_NUMPAD6 + KeyNumpad7 Key = w32.VK_NUMPAD7 + KeyNumpad8 Key = w32.VK_NUMPAD8 + KeyNumpad9 Key = w32.VK_NUMPAD9 + KeyMultiply Key = w32.VK_MULTIPLY + KeyAdd Key = w32.VK_ADD + KeySeparator Key = w32.VK_SEPARATOR + KeySubtract Key = w32.VK_SUBTRACT + KeyDecimal Key = w32.VK_DECIMAL + KeyDivide Key = w32.VK_DIVIDE + KeyF1 Key = w32.VK_F1 + KeyF2 Key = w32.VK_F2 + KeyF3 Key = w32.VK_F3 + KeyF4 Key = w32.VK_F4 + KeyF5 Key = w32.VK_F5 + KeyF6 Key = w32.VK_F6 + KeyF7 Key = w32.VK_F7 + KeyF8 Key = w32.VK_F8 + KeyF9 Key = w32.VK_F9 + KeyF10 Key = w32.VK_F10 + KeyF11 Key = w32.VK_F11 + KeyF12 Key = w32.VK_F12 + KeyF13 Key = w32.VK_F13 + KeyF14 Key = w32.VK_F14 + KeyF15 Key = w32.VK_F15 + KeyF16 Key = w32.VK_F16 + KeyF17 Key = w32.VK_F17 + KeyF18 Key = w32.VK_F18 + KeyF19 Key = w32.VK_F19 + KeyF20 Key = w32.VK_F20 + KeyF21 Key = w32.VK_F21 + KeyF22 Key = w32.VK_F22 + KeyF23 Key = w32.VK_F23 + KeyF24 Key = w32.VK_F24 + KeyNumlock Key = w32.VK_NUMLOCK + KeyScroll Key = w32.VK_SCROLL + KeyLShift Key = w32.VK_LSHIFT + KeyRShift Key = w32.VK_RSHIFT + KeyLControl Key = w32.VK_LCONTROL + KeyRControl Key = w32.VK_RCONTROL + KeyLAlt Key = w32.VK_LMENU + KeyLMenu Key = w32.VK_LMENU + KeyRAlt Key = w32.VK_RMENU + KeyRMenu Key = w32.VK_RMENU + KeyBrowserBack Key = w32.VK_BROWSER_BACK + KeyBrowserForward Key = w32.VK_BROWSER_FORWARD + KeyBrowserRefresh Key = w32.VK_BROWSER_REFRESH + KeyBrowserStop Key = w32.VK_BROWSER_STOP + KeyBrowserSearch Key = w32.VK_BROWSER_SEARCH + KeyBrowserFavorites Key = w32.VK_BROWSER_FAVORITES + KeyBrowserHome Key = w32.VK_BROWSER_HOME + KeyVolumeMute Key = w32.VK_VOLUME_MUTE + KeyVolumeDown Key = w32.VK_VOLUME_DOWN + KeyVolumeUp Key = w32.VK_VOLUME_UP + KeyMediaNextTrack Key = w32.VK_MEDIA_NEXT_TRACK + KeyMediaPrevTrack Key = w32.VK_MEDIA_PREV_TRACK + KeyMediaStop Key = w32.VK_MEDIA_STOP + KeyMediaPlayPause Key = w32.VK_MEDIA_PLAY_PAUSE + KeyLaunchMail Key = w32.VK_LAUNCH_MAIL + KeyLaunchMediaSelect Key = w32.VK_LAUNCH_MEDIA_SELECT + KeyLaunchApp1 Key = w32.VK_LAUNCH_APP1 + KeyLaunchApp2 Key = w32.VK_LAUNCH_APP2 + KeyOEM1 Key = w32.VK_OEM_1 + KeyOEMPlus Key = w32.VK_OEM_PLUS + KeyOEMComma Key = w32.VK_OEM_COMMA + KeyOEMMinus Key = w32.VK_OEM_MINUS + KeyOEMPeriod Key = w32.VK_OEM_PERIOD + KeyOEM2 Key = w32.VK_OEM_2 + KeyOEM3 Key = w32.VK_OEM_3 + KeyOEM4 Key = w32.VK_OEM_4 + KeyOEM5 Key = w32.VK_OEM_5 + KeyOEM6 Key = w32.VK_OEM_6 + KeyOEM7 Key = w32.VK_OEM_7 + KeyOEM8 Key = w32.VK_OEM_8 + KeyOEM102 Key = w32.VK_OEM_102 + KeyProcessKey Key = w32.VK_PROCESSKEY + KeyPacket Key = w32.VK_PACKET + KeyAttn Key = w32.VK_ATTN + KeyCRSel Key = w32.VK_CRSEL + KeyEXSel Key = w32.VK_EXSEL + KeyErEOF Key = w32.VK_EREOF + KeyPlay Key = w32.VK_PLAY + KeyZoom Key = w32.VK_ZOOM + KeyNoName Key = w32.VK_NONAME + KeyPA1 Key = w32.VK_PA1 + KeyOEMClear Key = w32.VK_OEM_CLEAR +) + +var key2string = map[Key]string{ + KeyLButton: "LButton", + KeyRButton: "RButton", + KeyCancel: "Cancel", + KeyMButton: "MButton", + KeyXButton1: "XButton1", + KeyXButton2: "XButton2", + KeyBack: "Back", + KeyTab: "Tab", + KeyClear: "Clear", + KeyReturn: "Return", + KeyShift: "Shift", + KeyControl: "Control", + KeyAlt: "Alt / Menu", + KeyPause: "Pause", + KeyCapital: "Capital", + KeyKana: "Kana / Hangul", + KeyJunja: "Junja", + KeyFinal: "Final", + KeyHanja: "Hanja / Kanji", + KeyEscape: "Escape", + KeyConvert: "Convert", + KeyNonconvert: "Nonconvert", + KeyAccept: "Accept", + KeyModeChange: "ModeChange", + KeySpace: "Space", + KeyPrior: "Prior", + KeyNext: "Next", + KeyEnd: "End", + KeyHome: "Home", + KeyLeft: "Left", + KeyUp: "Up", + KeyRight: "Right", + KeyDown: "Down", + KeySelect: "Select", + KeyPrint: "Print", + KeyExecute: "Execute", + KeySnapshot: "Snapshot", + KeyInsert: "Insert", + KeyDelete: "Delete", + KeyHelp: "Help", + Key0: "0", + Key1: "1", + Key2: "2", + Key3: "3", + Key4: "4", + Key5: "5", + Key6: "6", + Key7: "7", + Key8: "8", + Key9: "9", + KeyA: "A", + KeyB: "B", + KeyC: "C", + KeyD: "D", + KeyE: "E", + KeyF: "F", + KeyG: "G", + KeyH: "H", + KeyI: "I", + KeyJ: "J", + KeyK: "K", + KeyL: "L", + KeyM: "M", + KeyN: "N", + KeyO: "O", + KeyP: "P", + KeyQ: "Q", + KeyR: "R", + KeyS: "S", + KeyT: "T", + KeyU: "U", + KeyV: "V", + KeyW: "W", + KeyX: "X", + KeyY: "Y", + KeyZ: "Z", + KeyLWIN: "LWIN", + KeyRWIN: "RWIN", + KeyApps: "Apps", + KeySleep: "Sleep", + KeyNumpad0: "Numpad0", + KeyNumpad1: "Numpad1", + KeyNumpad2: "Numpad2", + KeyNumpad3: "Numpad3", + KeyNumpad4: "Numpad4", + KeyNumpad5: "Numpad5", + KeyNumpad6: "Numpad6", + KeyNumpad7: "Numpad7", + KeyNumpad8: "Numpad8", + KeyNumpad9: "Numpad9", + KeyMultiply: "Multiply", + KeyAdd: "Add", + KeySeparator: "Separator", + KeySubtract: "Subtract", + KeyDecimal: "Decimal", + KeyDivide: "Divide", + KeyF1: "F1", + KeyF2: "F2", + KeyF3: "F3", + KeyF4: "F4", + KeyF5: "F5", + KeyF6: "F6", + KeyF7: "F7", + KeyF8: "F8", + KeyF9: "F9", + KeyF10: "F10", + KeyF11: "F11", + KeyF12: "F12", + KeyF13: "F13", + KeyF14: "F14", + KeyF15: "F15", + KeyF16: "F16", + KeyF17: "F17", + KeyF18: "F18", + KeyF19: "F19", + KeyF20: "F20", + KeyF21: "F21", + KeyF22: "F22", + KeyF23: "F23", + KeyF24: "F24", + KeyNumlock: "Numlock", + KeyScroll: "Scroll", + KeyLShift: "LShift", + KeyRShift: "RShift", + KeyLControl: "LControl", + KeyRControl: "RControl", + KeyLMenu: "LMenu", + KeyRMenu: "RMenu", + KeyBrowserBack: "BrowserBack", + KeyBrowserForward: "BrowserForward", + KeyBrowserRefresh: "BrowserRefresh", + KeyBrowserStop: "BrowserStop", + KeyBrowserSearch: "BrowserSearch", + KeyBrowserFavorites: "BrowserFavorites", + KeyBrowserHome: "BrowserHome", + KeyVolumeMute: "VolumeMute", + KeyVolumeDown: "VolumeDown", + KeyVolumeUp: "VolumeUp", + KeyMediaNextTrack: "MediaNextTrack", + KeyMediaPrevTrack: "MediaPrevTrack", + KeyMediaStop: "MediaStop", + KeyMediaPlayPause: "MediaPlayPause", + KeyLaunchMail: "LaunchMail", + KeyLaunchMediaSelect: "LaunchMediaSelect", + KeyLaunchApp1: "LaunchApp1", + KeyLaunchApp2: "LaunchApp2", + KeyOEM1: "OEM1", + KeyOEMPlus: "OEMPlus", + KeyOEMComma: "OEMComma", + KeyOEMMinus: "OEMMinus", + KeyOEMPeriod: "OEMPeriod", + KeyOEM2: "OEM2", + KeyOEM3: "OEM3", + KeyOEM4: "OEM4", + KeyOEM5: "OEM5", + KeyOEM6: "OEM6", + KeyOEM7: "OEM7", + KeyOEM8: "OEM8", + KeyOEM102: "OEM102", + KeyProcessKey: "ProcessKey", + KeyPacket: "Packet", + KeyAttn: "Attn", + KeyCRSel: "CRSel", + KeyEXSel: "EXSel", + KeyErEOF: "ErEOF", + KeyPlay: "Play", + KeyZoom: "Zoom", + KeyNoName: "NoName", + KeyPA1: "PA1", + KeyOEMClear: "OEMClear", +} + +type Modifiers byte + +func (m Modifiers) String() string { + return modifiers2string[m] +} + +var modifiers2string = map[Modifiers]string{ + ModShift: "Shift", + ModControl: "Ctrl", + ModControl | ModShift: "Ctrl+Shift", + ModAlt: "Alt", + ModAlt | ModShift: "Alt+Shift", + ModAlt | ModControl | ModShift: "Alt+Ctrl+Shift", +} + +const ( + ModShift Modifiers = 1 << iota + ModControl + ModAlt +) + +func ModifiersDown() Modifiers { + var m Modifiers + + if ShiftDown() { + m |= ModShift + } + if ControlDown() { + m |= ModControl + } + if AltDown() { + m |= ModAlt + } + + return m +} + +type Shortcut struct { + Modifiers Modifiers + Key Key +} + +func (s Shortcut) String() string { + m := s.Modifiers.String() + if m == "" { + return s.Key.String() + } + + b := new(bytes.Buffer) + + b.WriteString(m) + b.WriteRune('+') + b.WriteString(s.Key.String()) + + return b.String() +} + +func AltDown() bool { + return w32.GetKeyState(int32(KeyAlt))>>15 != 0 +} + +func ControlDown() bool { + return w32.GetKeyState(int32(KeyControl))>>15 != 0 +} + +func ShiftDown() bool { + return w32.GetKeyState(int32(KeyShift))>>15 != 0 +} diff --git a/v2/internal/frontend/desktop/windows/winc/label.go b/v2/internal/frontend/desktop/windows/winc/label.go new file mode 100644 index 000000000..b866ea7b6 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/label.go @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Label struct { + ControlBase +} + +func NewLabel(parent Controller) *Label { + lb := new(Label) + + lb.InitControl("STATIC", parent, 0, w32.WS_CHILD|w32.WS_VISIBLE|w32.SS_LEFTNOWORDWRAP) + RegMsgHandler(lb) + + lb.SetFont(DefaultFont) + lb.SetText("Label") + lb.SetSize(100, 25) + return lb +} + +func (lb *Label) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + return w32.DefWindowProc(lb.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/layout.go b/v2/internal/frontend/desktop/windows/winc/layout.go new file mode 100644 index 000000000..b16f041c3 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/layout.go @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "encoding/json" + "fmt" + "io" + "os" + "sort" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +// Dockable component must satisfy interface to be docked. +type Dockable interface { + Handle() w32.HWND + + Pos() (x, y int) + Width() int + Height() int + Visible() bool + + SetPos(x, y int) + SetSize(width, height int) + + OnMouseMove() *EventManager + OnLBUp() *EventManager +} + +// DockAllow is window, panel or other component that satisfies interface. +type DockAllow interface { + Handle() w32.HWND + ClientWidth() int + ClientHeight() int + SetLayout(mng LayoutManager) +} + +// Various layout managers +type Direction int + +const ( + Top Direction = iota + Bottom + Left + Right + Fill +) + +type LayoutControl struct { + child Dockable + dir Direction +} + +type LayoutControls []*LayoutControl + +type SimpleDock struct { + parent DockAllow + layoutCtl LayoutControls + loadedState bool +} + +// DockState gets saved and loaded from json +type CtlState struct { + X, Y, Width, Height int +} + +type LayoutState struct { + WindowState string + Controls []*CtlState +} + +func (lc LayoutControls) Len() int { return len(lc) } +func (lc LayoutControls) Swap(i, j int) { lc[i], lc[j] = lc[j], lc[i] } +func (lc LayoutControls) Less(i, j int) bool { return lc[i].dir < lc[j].dir } + +func NewSimpleDock(parent DockAllow) *SimpleDock { + d := &SimpleDock{parent: parent} + parent.SetLayout(d) + return d +} + +// Layout management for the child controls. +func (sd *SimpleDock) Dock(child Dockable, dir Direction) { + sd.layoutCtl = append(sd.layoutCtl, &LayoutControl{child, dir}) +} + +// SaveState of the layout. Only works for Docks with parent set to main form. +func (sd *SimpleDock) SaveState(w io.Writer) error { + var ls LayoutState + + var wp w32.WINDOWPLACEMENT + wp.Length = uint32(unsafe.Sizeof(wp)) + if !w32.GetWindowPlacement(sd.parent.Handle(), &wp) { + return fmt.Errorf("GetWindowPlacement failed") + } + + ls.WindowState = fmt.Sprint( + wp.Flags, wp.ShowCmd, + wp.PtMinPosition.X, wp.PtMinPosition.Y, + wp.PtMaxPosition.X, wp.PtMaxPosition.Y, + wp.RcNormalPosition.Left, wp.RcNormalPosition.Top, + wp.RcNormalPosition.Right, wp.RcNormalPosition.Bottom) + + for _, c := range sd.layoutCtl { + x, y := c.child.Pos() + w, h := c.child.Width(), c.child.Height() + + ctl := &CtlState{X: x, Y: y, Width: w, Height: h} + ls.Controls = append(ls.Controls, ctl) + } + + if err := json.NewEncoder(w).Encode(ls); err != nil { + return err + } + + return nil +} + +// LoadState of the layout. Only works for Docks with parent set to main form. +func (sd *SimpleDock) LoadState(r io.Reader) error { + var ls LayoutState + + if err := json.NewDecoder(r).Decode(&ls); err != nil { + return err + } + + var wp w32.WINDOWPLACEMENT + if _, err := fmt.Sscan(ls.WindowState, + &wp.Flags, &wp.ShowCmd, + &wp.PtMinPosition.X, &wp.PtMinPosition.Y, + &wp.PtMaxPosition.X, &wp.PtMaxPosition.Y, + &wp.RcNormalPosition.Left, &wp.RcNormalPosition.Top, + &wp.RcNormalPosition.Right, &wp.RcNormalPosition.Bottom); err != nil { + return err + } + wp.Length = uint32(unsafe.Sizeof(wp)) + + if !w32.SetWindowPlacement(sd.parent.Handle(), &wp) { + return fmt.Errorf("SetWindowPlacement failed") + } + + // if number of controls in the saved layout does not match + // current number on screen - something changed and we do not reload + // rest of control sizes from json + if len(sd.layoutCtl) != len(ls.Controls) { + return nil + } + + for i, c := range sd.layoutCtl { + c.child.SetPos(ls.Controls[i].X, ls.Controls[i].Y) + c.child.SetSize(ls.Controls[i].Width, ls.Controls[i].Height) + } + return nil +} + +// SaveStateFile convenience function. +func (sd *SimpleDock) SaveStateFile(file string) error { + f, err := os.Create(file) + if err != nil { + return err + } + return sd.SaveState(f) +} + +// LoadStateFile loads state ignores error if file is not found. +func (sd *SimpleDock) LoadStateFile(file string) error { + f, err := os.Open(file) + if err != nil { + return nil // if file is not found or not accessible ignore it + } + return sd.LoadState(f) +} + +// Update is called to resize child items based on layout directions. +func (sd *SimpleDock) Update() { + sort.Stable(sd.layoutCtl) + + x, y := 0, 0 + w, h := sd.parent.ClientWidth(), sd.parent.ClientHeight() + winw, winh := w, h + + for _, c := range sd.layoutCtl { + // Non visible controls do not preserve space. + if !c.child.Visible() { + continue + } + + switch c.dir { + case Top: + c.child.SetPos(x, y) + c.child.SetSize(w, c.child.Height()) + h -= c.child.Height() + y += c.child.Height() + case Bottom: + c.child.SetPos(x, winh-c.child.Height()) + c.child.SetSize(w, c.child.Height()) + h -= c.child.Height() + winh -= c.child.Height() + case Left: + c.child.SetPos(x, y) + c.child.SetSize(c.child.Width(), h) + w -= c.child.Width() + x += c.child.Width() + case Right: + c.child.SetPos(winw-c.child.Width(), y) + c.child.SetSize(c.child.Width(), h) + w -= c.child.Width() + winw -= c.child.Width() + case Fill: + // fill available space + c.child.SetPos(x, y) + c.child.SetSize(w, h) + } + //c.child.Invalidate(true) + } +} diff --git a/v2/internal/frontend/desktop/windows/winc/listview.go b/v2/internal/frontend/desktop/windows/winc/listview.go new file mode 100644 index 000000000..a138b55f9 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/listview.go @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "errors" + "fmt" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +// ListItem represents an item in a ListView widget. +type ListItem interface { + Text() []string // Text returns the text of the multi-column item. + ImageIndex() int // ImageIndex is used only if SetImageList is called on the listview +} + +// ListItemChecker is used for checkbox support in ListView. +type ListItemChecker interface { + Checked() bool + SetChecked(checked bool) +} + +// ListItemSetter is used in OnEndLabelEdit event. +type ListItemSetter interface { + SetText(s string) // set first item in the array via LabelEdit event +} + +// StringListItem is helper for basic string lists. +type StringListItem struct { + ID int + Data string + Check bool +} + +func (s StringListItem) Text() []string { return []string{s.Data} } +func (s StringListItem) Checked() bool { return s.Check } +func (s StringListItem) SetChecked(checked bool) { s.Check = checked } +func (s StringListItem) ImageIndex() int { return 0 } + +type ListView struct { + ControlBase + + iml *ImageList + lastIndex int + cols int // count of columns + + item2Handle map[ListItem]uintptr + handle2Item map[uintptr]ListItem + + onEndLabelEdit EventManager + onDoubleClick EventManager + onClick EventManager + onKeyDown EventManager + onItemChanging EventManager + onItemChanged EventManager + onCheckChanged EventManager + onViewChange EventManager + onEndScroll EventManager +} + +func NewListView(parent Controller) *ListView { + lv := new(ListView) + + lv.InitControl("SysListView32", parent /*w32.WS_EX_CLIENTEDGE*/, 0, + w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.LVS_REPORT|w32.LVS_EDITLABELS|w32.LVS_SHOWSELALWAYS) + + lv.item2Handle = make(map[ListItem]uintptr) + lv.handle2Item = make(map[uintptr]ListItem) + + RegMsgHandler(lv) + + lv.SetFont(DefaultFont) + lv.SetSize(200, 400) + + if err := lv.SetTheme("Explorer"); err != nil { + // theme error is ignored + } + return lv +} + +// FIXME: Changes the state of an item in a list-view control. Refer LVM_SETITEMSTATE message. +func (lv *ListView) setItemState(i int, state, mask uint) { + var item w32.LVITEM + item.State, item.StateMask = uint32(state), uint32(mask) + w32.SendMessage(lv.hwnd, w32.LVM_SETITEMSTATE, uintptr(i), uintptr(unsafe.Pointer(&item))) +} + +func (lv *ListView) EnableSingleSelect(enable bool) { + SetStyle(lv.hwnd, enable, w32.LVS_SINGLESEL) +} + +func (lv *ListView) EnableSortHeader(enable bool) { + SetStyle(lv.hwnd, enable, w32.LVS_NOSORTHEADER) +} + +func (lv *ListView) EnableSortAscending(enable bool) { + SetStyle(lv.hwnd, enable, w32.LVS_SORTASCENDING) +} + +func (lv *ListView) EnableEditLabels(enable bool) { + SetStyle(lv.hwnd, enable, w32.LVS_EDITLABELS) +} + +func (lv *ListView) EnableFullRowSelect(enable bool) { + if enable { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, w32.LVS_EX_FULLROWSELECT) + } else { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, w32.LVS_EX_FULLROWSELECT, 0) + } +} + +func (lv *ListView) EnableDoubleBuffer(enable bool) { + if enable { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, w32.LVS_EX_DOUBLEBUFFER) + } else { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, w32.LVS_EX_DOUBLEBUFFER, 0) + } +} + +func (lv *ListView) EnableHotTrack(enable bool) { + if enable { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, w32.LVS_EX_TRACKSELECT) + } else { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, w32.LVS_EX_TRACKSELECT, 0) + } +} + +func (lv *ListView) SetItemCount(count int) bool { + return w32.SendMessage(lv.hwnd, w32.LVM_SETITEMCOUNT, uintptr(count), 0) != 0 +} + +func (lv *ListView) ItemCount() int { + return int(w32.SendMessage(lv.hwnd, w32.LVM_GETITEMCOUNT, 0, 0)) +} + +func (lv *ListView) ItemAt(x, y int) ListItem { + hti := w32.LVHITTESTINFO{Pt: w32.POINT{int32(x), int32(y)}} + w32.SendMessage(lv.hwnd, w32.LVM_HITTEST, 0, uintptr(unsafe.Pointer(&hti))) + return lv.findItemByIndex(int(hti.IItem)) +} + +func (lv *ListView) Items() (list []ListItem) { + for item := range lv.item2Handle { + list = append(list, item) + } + return list +} + +func (lv *ListView) AddColumn(caption string, width int) { + var lc w32.LVCOLUMN + lc.Mask = w32.LVCF_TEXT + if width != 0 { + lc.Mask = lc.Mask | w32.LVCF_WIDTH + lc.Cx = int32(width) + } + lc.PszText = syscall.StringToUTF16Ptr(caption) + lv.insertLvColumn(&lc, lv.cols) + lv.cols++ +} + +// StretchLastColumn makes the last column take up all remaining horizontal +// space of the *ListView. +// The effect of this is not persistent. +func (lv *ListView) StretchLastColumn() error { + if lv.cols == 0 { + return nil + } + if w32.SendMessage(lv.hwnd, w32.LVM_SETCOLUMNWIDTH, uintptr(lv.cols-1), w32.LVSCW_AUTOSIZE_USEHEADER) == 0 { + //panic("LVM_SETCOLUMNWIDTH failed") + } + return nil +} + +// CheckBoxes returns if the *TableView has check boxes. +func (lv *ListView) CheckBoxes() bool { + return w32.SendMessage(lv.hwnd, w32.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)&w32.LVS_EX_CHECKBOXES > 0 +} + +// SetCheckBoxes sets if the *TableView has check boxes. +func (lv *ListView) SetCheckBoxes(value bool) { + exStyle := w32.SendMessage(lv.hwnd, w32.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) + oldStyle := exStyle + if value { + exStyle |= w32.LVS_EX_CHECKBOXES + } else { + exStyle &^= w32.LVS_EX_CHECKBOXES + } + if exStyle != oldStyle { + w32.SendMessage(lv.hwnd, w32.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, exStyle) + } + + mask := w32.SendMessage(lv.hwnd, w32.LVM_GETCALLBACKMASK, 0, 0) + if value { + mask |= w32.LVIS_STATEIMAGEMASK + } else { + mask &^= w32.LVIS_STATEIMAGEMASK + } + + if w32.SendMessage(lv.hwnd, w32.LVM_SETCALLBACKMASK, mask, 0) == w32.FALSE { + panic("SendMessage(LVM_SETCALLBACKMASK)") + } +} + +func (lv *ListView) applyImage(lc *w32.LVITEM, imIndex int) { + if lv.iml != nil { + lc.Mask |= w32.LVIF_IMAGE + lc.IImage = int32(imIndex) + } +} + +func (lv *ListView) AddItem(item ListItem) { + lv.InsertItem(item, lv.ItemCount()) +} + +func (lv *ListView) InsertItem(item ListItem, index int) { + text := item.Text() + li := &w32.LVITEM{ + Mask: w32.LVIF_TEXT | w32.LVIF_PARAM, + PszText: syscall.StringToUTF16Ptr(text[0]), + IItem: int32(index), + } + + lv.lastIndex++ + ix := new(int) + *ix = lv.lastIndex + li.LParam = uintptr(*ix) + lv.handle2Item[li.LParam] = item + lv.item2Handle[item] = li.LParam + + lv.applyImage(li, item.ImageIndex()) + lv.insertLvItem(li) + + for i := 1; i < len(text); i++ { + li.Mask = w32.LVIF_TEXT + li.PszText = syscall.StringToUTF16Ptr(text[i]) + li.ISubItem = int32(i) + lv.setLvItem(li) + } +} + +func (lv *ListView) UpdateItem(item ListItem) bool { + lparam, ok := lv.item2Handle[item] + if !ok { + return false + } + + index := lv.findIndexByItem(item) + if index == -1 { + return false + } + + text := item.Text() + li := &w32.LVITEM{ + Mask: w32.LVIF_TEXT | w32.LVIF_PARAM, + PszText: syscall.StringToUTF16Ptr(text[0]), + LParam: lparam, + IItem: int32(index), + } + + lv.applyImage(li, item.ImageIndex()) + lv.setLvItem(li) + + for i := 1; i < len(text); i++ { + li.Mask = w32.LVIF_TEXT + li.PszText = syscall.StringToUTF16Ptr(text[i]) + li.ISubItem = int32(i) + lv.setLvItem(li) + } + return true +} + +func (lv *ListView) insertLvColumn(lvColumn *w32.LVCOLUMN, iCol int) { + w32.SendMessage(lv.hwnd, w32.LVM_INSERTCOLUMN, uintptr(iCol), uintptr(unsafe.Pointer(lvColumn))) +} + +func (lv *ListView) insertLvItem(lvItem *w32.LVITEM) { + w32.SendMessage(lv.hwnd, w32.LVM_INSERTITEM, 0, uintptr(unsafe.Pointer(lvItem))) +} + +func (lv *ListView) setLvItem(lvItem *w32.LVITEM) { + w32.SendMessage(lv.hwnd, w32.LVM_SETITEM, 0, uintptr(unsafe.Pointer(lvItem))) +} + +func (lv *ListView) DeleteAllItems() bool { + if w32.SendMessage(lv.hwnd, w32.LVM_DELETEALLITEMS, 0, 0) == w32.TRUE { + lv.item2Handle = make(map[ListItem]uintptr) + lv.handle2Item = make(map[uintptr]ListItem) + return true + } + return false +} + +func (lv *ListView) DeleteItem(item ListItem) error { + index := lv.findIndexByItem(item) + if index == -1 { + return errors.New("item not found") + } + + if w32.SendMessage(lv.hwnd, w32.LVM_DELETEITEM, uintptr(index), 0) == 0 { + return errors.New("SendMessage(TVM_DELETEITEM) failed") + } + + h := lv.item2Handle[item] + delete(lv.item2Handle, item) + delete(lv.handle2Item, h) + return nil +} + +func (lv *ListView) findIndexByItem(item ListItem) int { + lparam, ok := lv.item2Handle[item] + if !ok { + return -1 + } + + it := &w32.LVFINDINFO{ + Flags: w32.LVFI_PARAM, + LParam: lparam, + } + var i int = -1 + return int(w32.SendMessage(lv.hwnd, w32.LVM_FINDITEM, uintptr(i), uintptr(unsafe.Pointer(it)))) +} + +func (lv *ListView) findItemByIndex(i int) ListItem { + it := &w32.LVITEM{ + Mask: w32.LVIF_PARAM, + IItem: int32(i), + } + + if w32.SendMessage(lv.hwnd, w32.LVM_GETITEM, 0, uintptr(unsafe.Pointer(it))) == w32.TRUE { + if item, ok := lv.handle2Item[it.LParam]; ok { + return item + } + } + return nil +} + +func (lv *ListView) EnsureVisible(item ListItem) bool { + if i := lv.findIndexByItem(item); i != -1 { + return w32.SendMessage(lv.hwnd, w32.LVM_ENSUREVISIBLE, uintptr(i), 1) == 0 + } + return false +} + +func (lv *ListView) SelectedItem() ListItem { + if items := lv.SelectedItems(); len(items) > 0 { + return items[0] + } + return nil +} + +func (lv *ListView) SetSelectedItem(item ListItem) bool { + if i := lv.findIndexByItem(item); i > -1 { + lv.SetSelectedIndex(i) + return true + } + return false +} + +// mask is used to set the LVITEM.Mask for ListView.GetItem which indicates which attributes you'd like to receive +// of LVITEM. +func (lv *ListView) SelectedItems() []ListItem { + var items []ListItem + + var i int = -1 + for { + if i = int(w32.SendMessage(lv.hwnd, w32.LVM_GETNEXTITEM, uintptr(i), uintptr(w32.LVNI_SELECTED))); i == -1 { + break + } + + if item := lv.findItemByIndex(i); item != nil { + items = append(items, item) + } + } + return items +} + +func (lv *ListView) SelectedCount() uint { + return uint(w32.SendMessage(lv.hwnd, w32.LVM_GETSELECTEDCOUNT, 0, 0)) +} + +// GetSelectedIndex first selected item index. Returns -1 if no item is selected. +func (lv *ListView) SelectedIndex() int { + var i int = -1 + return int(w32.SendMessage(lv.hwnd, w32.LVM_GETNEXTITEM, uintptr(i), uintptr(w32.LVNI_SELECTED))) +} + +// Set i to -1 to select all items. +func (lv *ListView) SetSelectedIndex(i int) { + lv.setItemState(i, w32.LVIS_SELECTED, w32.LVIS_SELECTED) +} + +func (lv *ListView) SetImageList(imageList *ImageList) { + w32.SendMessage(lv.hwnd, w32.LVM_SETIMAGELIST, w32.LVSIL_SMALL, uintptr(imageList.Handle())) + lv.iml = imageList +} + +// Event publishers +func (lv *ListView) OnEndLabelEdit() *EventManager { + return &lv.onEndLabelEdit +} + +func (lv *ListView) OnDoubleClick() *EventManager { + return &lv.onDoubleClick +} + +func (lv *ListView) OnClick() *EventManager { + return &lv.onClick +} + +func (lv *ListView) OnKeyDown() *EventManager { + return &lv.onKeyDown +} + +func (lv *ListView) OnItemChanging() *EventManager { + return &lv.onItemChanging +} + +func (lv *ListView) OnItemChanged() *EventManager { + return &lv.onItemChanged +} + +func (lv *ListView) OnCheckChanged() *EventManager { + return &lv.onCheckChanged +} + +func (lv *ListView) OnViewChange() *EventManager { + return &lv.onViewChange +} + +func (lv *ListView) OnEndScroll() *EventManager { + return &lv.onEndScroll +} + +// Message processer +func (lv *ListView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + /*case w32.WM_ERASEBKGND: + lv.StretchLastColumn() + println("case w32.WM_ERASEBKGND") + return 1*/ + + case w32.WM_NOTIFY: + nm := (*w32.NMHDR)(unsafe.Pointer(lparam)) + code := int32(nm.Code) + + switch code { + case w32.LVN_BEGINLABELEDITW: + // println("Begin label edit") + case w32.LVN_ENDLABELEDITW: + nmdi := (*w32.NMLVDISPINFO)(unsafe.Pointer(lparam)) + if nmdi.Item.PszText != nil { + fmt.Println(nmdi.Item.PszText, nmdi.Item) + if item, ok := lv.handle2Item[nmdi.Item.LParam]; ok { + lv.onEndLabelEdit.Fire(NewEvent(lv, + &LabelEditEventData{Item: item, + Text: w32.UTF16PtrToString(nmdi.Item.PszText)})) + } + return w32.TRUE + } + case w32.NM_DBLCLK: + lv.onDoubleClick.Fire(NewEvent(lv, nil)) + + case w32.NM_CLICK: + ac := (*w32.NMITEMACTIVATE)(unsafe.Pointer(lparam)) + var hti w32.LVHITTESTINFO + hti.Pt = w32.POINT{ac.PtAction.X, ac.PtAction.Y} + w32.SendMessage(lv.hwnd, w32.LVM_HITTEST, 0, uintptr(unsafe.Pointer(&hti))) + + if hti.Flags == w32.LVHT_ONITEMSTATEICON { + if item := lv.findItemByIndex(int(hti.IItem)); item != nil { + if item, ok := item.(ListItemChecker); ok { + checked := !item.Checked() + item.SetChecked(checked) + lv.onCheckChanged.Fire(NewEvent(lv, item)) + + if w32.SendMessage(lv.hwnd, w32.LVM_UPDATE, uintptr(hti.IItem), 0) == w32.FALSE { + panic("SendMessage(LVM_UPDATE)") + } + } + } + } + + hti.Pt = w32.POINT{ac.PtAction.X, ac.PtAction.Y} + w32.SendMessage(lv.hwnd, w32.LVM_SUBITEMHITTEST, 0, uintptr(unsafe.Pointer(&hti))) + lv.onClick.Fire(NewEvent(lv, hti.ISubItem)) + + case w32.LVN_KEYDOWN: + nmkey := (*w32.NMLVKEYDOWN)(unsafe.Pointer(lparam)) + if nmkey.WVKey == w32.VK_SPACE && lv.CheckBoxes() { + if item := lv.SelectedItem(); item != nil { + if item, ok := item.(ListItemChecker); ok { + checked := !item.Checked() + item.SetChecked(checked) + lv.onCheckChanged.Fire(NewEvent(lv, item)) + } + + index := lv.findIndexByItem(item) + if w32.SendMessage(lv.hwnd, w32.LVM_UPDATE, uintptr(index), 0) == w32.FALSE { + panic("SendMessage(LVM_UPDATE)") + } + } + } + lv.onKeyDown.Fire(NewEvent(lv, nmkey.WVKey)) + key := nmkey.WVKey + w32.SendMessage(lv.Parent().Handle(), w32.WM_KEYDOWN, uintptr(key), 0) + + case w32.LVN_ITEMCHANGING: + // This event also fires when listview has changed via code. + nmlv := (*w32.NMLISTVIEW)(unsafe.Pointer(lparam)) + item := lv.findItemByIndex(int(nmlv.IItem)) + lv.onItemChanging.Fire(NewEvent(lv, item)) + + case w32.LVN_ITEMCHANGED: + // This event also fires when listview has changed via code. + nmlv := (*w32.NMLISTVIEW)(unsafe.Pointer(lparam)) + item := lv.findItemByIndex(int(nmlv.IItem)) + lv.onItemChanged.Fire(NewEvent(lv, item)) + + case w32.LVN_GETDISPINFO: + nmdi := (*w32.NMLVDISPINFO)(unsafe.Pointer(lparam)) + if nmdi.Item.StateMask&w32.LVIS_STATEIMAGEMASK > 0 { + if item, ok := lv.handle2Item[nmdi.Item.LParam]; ok { + if item, ok := item.(ListItemChecker); ok { + + checked := item.Checked() + if checked { + nmdi.Item.State = 0x2000 + } else { + nmdi.Item.State = 0x1000 + } + } + } + } + + lv.onViewChange.Fire(NewEvent(lv, nil)) + + case w32.LVN_ENDSCROLL: + lv.onEndScroll.Fire(NewEvent(lv, nil)) + } + } + return w32.DefWindowProc(lv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/menu.go b/v2/internal/frontend/desktop/windows/winc/menu.go new file mode 100644 index 000000000..bbfdefade --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/menu.go @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +var ( + nextMenuItemID uint16 = 3 + actionsByID = make(map[uint16]*MenuItem) + shortcut2Action = make(map[Shortcut]*MenuItem) + menuItems = make(map[w32.HMENU][]*MenuItem) + radioGroups = make(map[*MenuItem]*RadioGroup) + initialised bool +) + +var NoShortcut = Shortcut{} + +// Menu for main window and context menus on controls. +// Most methods used for both main window menu and context menu. +type Menu struct { + hMenu w32.HMENU + hwnd w32.HWND // hwnd might be nil if it is context menu. +} + +type MenuItem struct { + hMenu w32.HMENU + hSubMenu w32.HMENU // Non zero if this item is in itself a submenu. + + text string + toolTip string + image *Bitmap + shortcut Shortcut + enabled bool + + checkable bool + checked bool + isRadio bool + + id uint16 + + onClick EventManager +} + +type RadioGroup struct { + members []*MenuItem + hwnd w32.HWND +} + +func NewContextMenu() *MenuItem { + hMenu := w32.CreatePopupMenu() + if hMenu == 0 { + panic("failed CreateMenu") + } + + item := &MenuItem{ + hMenu: hMenu, + hSubMenu: hMenu, + } + return item +} + +func (m *Menu) Dispose() { + if m.hMenu != 0 { + w32.DestroyMenu(m.hMenu) + m.hMenu = 0 + } +} + +func (m *Menu) IsDisposed() bool { + return m.hMenu == 0 +} + +func initMenuItemInfoFromAction(mii *w32.MENUITEMINFO, a *MenuItem) { + mii.CbSize = uint32(unsafe.Sizeof(*mii)) + mii.FMask = w32.MIIM_FTYPE | w32.MIIM_ID | w32.MIIM_STATE | w32.MIIM_STRING + if a.image != nil { + mii.FMask |= w32.MIIM_BITMAP + mii.HbmpItem = a.image.handle + } + if a.IsSeparator() { + mii.FType = w32.MFT_SEPARATOR + } else { + mii.FType = w32.MFT_STRING + var text string + if s := a.shortcut; s.Key != 0 { + text = fmt.Sprintf("%s\t%s", a.text, s.String()) + shortcut2Action[a.shortcut] = a + } else { + text = a.text + } + mii.DwTypeData = syscall.StringToUTF16Ptr(text) + mii.Cch = uint32(len([]rune(a.text))) + } + mii.WID = uint32(a.id) + + if a.Enabled() { + mii.FState &^= w32.MFS_DISABLED + } else { + mii.FState |= w32.MFS_DISABLED + } + + if a.Checkable() { + mii.FMask |= w32.MIIM_CHECKMARKS + } + if a.Checked() { + mii.FState |= w32.MFS_CHECKED + } + + if a.hSubMenu != 0 { + mii.FMask |= w32.MIIM_SUBMENU + mii.HSubMenu = a.hSubMenu + } +} + +// Show menu on the main window. +func (m *Menu) Show() { + initialised = true + updateRadioGroups() + if !w32.DrawMenuBar(m.hwnd) { + panic("DrawMenuBar failed") + } +} + +// AddSubMenu returns item that is used as submenu to perform AddItem(s). +func (m *Menu) AddSubMenu(text string) *MenuItem { + hSubMenu := w32.CreateMenu() + if hSubMenu == 0 { + panic("failed CreateMenu") + } + return addMenuItem(m.hMenu, hSubMenu, text, Shortcut{}, nil, false) +} + +// This method will iterate through the menu items, group radio items together, build a +// quick access map and set the initial items +func updateRadioGroups() { + + if !initialised { + return + } + + radioItemsChecked := []*MenuItem{} + radioGroups = make(map[*MenuItem]*RadioGroup) + var currentRadioGroupMembers []*MenuItem + // Iterate the menus + for _, menu := range menuItems { + menuLength := len(menu) + for index, menuItem := range menu { + if menuItem.isRadio { + currentRadioGroupMembers = append(currentRadioGroupMembers, menuItem) + if menuItem.checked { + radioItemsChecked = append(radioItemsChecked, menuItem) + } + + // If end of menu + if index == menuLength-1 { + radioGroup := &RadioGroup{ + members: currentRadioGroupMembers, + hwnd: menuItem.hMenu, + } + // Save the group to each member iin the radiomap + for _, member := range currentRadioGroupMembers { + radioGroups[member] = radioGroup + } + currentRadioGroupMembers = []*MenuItem{} + } + continue + } + + // Not a radio item + if len(currentRadioGroupMembers) > 0 { + radioGroup := &RadioGroup{ + members: currentRadioGroupMembers, + hwnd: menuItem.hMenu, + } + // Save the group to each member iin the radiomap + for _, member := range currentRadioGroupMembers { + radioGroups[member] = radioGroup + } + currentRadioGroupMembers = []*MenuItem{} + } + } + } + + // Enable the checked items + for _, item := range radioItemsChecked { + radioGroup := radioGroups[item] + startID := radioGroup.members[0].id + endID := radioGroup.members[len(radioGroup.members)-1].id + w32.SelectRadioMenuItem(item.id, startID, endID, radioGroup.hwnd) + } + +} + +func (mi *MenuItem) OnClick() *EventManager { + return &mi.onClick +} + +func (mi *MenuItem) AddSeparator() { + addMenuItem(mi.hSubMenu, 0, "-", Shortcut{}, nil, false) +} + +// AddItem adds plain menu item. +func (mi *MenuItem) AddItem(text string, shortcut Shortcut) *MenuItem { + return addMenuItem(mi.hSubMenu, 0, text, shortcut, nil, false) +} + +// AddItemCheckable adds plain menu item that can have a checkmark. +func (mi *MenuItem) AddItemCheckable(text string, shortcut Shortcut) *MenuItem { + return addMenuItem(mi.hSubMenu, 0, text, shortcut, nil, true) +} + +// AddItemRadio adds plain menu item that can have a checkmark and is part of a radio group. +func (mi *MenuItem) AddItemRadio(text string, shortcut Shortcut) *MenuItem { + menuItem := addMenuItem(mi.hSubMenu, 0, text, shortcut, nil, true) + menuItem.isRadio = true + return menuItem +} + +// AddItemWithBitmap adds menu item with shortcut and bitmap. +func (mi *MenuItem) AddItemWithBitmap(text string, shortcut Shortcut, image *Bitmap) *MenuItem { + return addMenuItem(mi.hSubMenu, 0, text, shortcut, image, false) +} + +// AddSubMenu adds a submenu. +func (mi *MenuItem) AddSubMenu(text string) *MenuItem { + hSubMenu := w32.CreatePopupMenu() + if hSubMenu == 0 { + panic("failed CreatePopupMenu") + } + return addMenuItem(mi.hSubMenu, hSubMenu, text, Shortcut{}, nil, false) +} + +// AddItem to the menu, set text to "-" for separators. +func addMenuItem(hMenu, hSubMenu w32.HMENU, text string, shortcut Shortcut, image *Bitmap, checkable bool) *MenuItem { + item := &MenuItem{ + hMenu: hMenu, + hSubMenu: hSubMenu, + text: text, + shortcut: shortcut, + image: image, + enabled: true, + id: nextMenuItemID, + checkable: checkable, + isRadio: false, + //visible: true, + } + nextMenuItemID++ + actionsByID[item.id] = item + menuItems[hMenu] = append(menuItems[hMenu], item) + + var mii w32.MENUITEMINFO + initMenuItemInfoFromAction(&mii, item) + + index := -1 + if !w32.InsertMenuItem(hMenu, uint32(index), true, &mii) { + panic("InsertMenuItem failed") + } + return item +} + +func indexInObserver(a *MenuItem) int { + var idx int + for _, mi := range menuItems[a.hMenu] { + if mi == a { + return idx + } + idx++ + } + return -1 +} + +func findMenuItemByID(id int) *MenuItem { + return actionsByID[uint16(id)] +} + +func (mi *MenuItem) update() { + var mii w32.MENUITEMINFO + initMenuItemInfoFromAction(&mii, mi) + + if !w32.SetMenuItemInfo(mi.hMenu, uint32(indexInObserver(mi)), true, &mii) { + panic("SetMenuItemInfo failed") + } + if mi.isRadio { + mi.updateRadioGroup() + } +} + +func (mi *MenuItem) IsSeparator() bool { return mi.text == "-" } +func (mi *MenuItem) SetSeparator() { mi.text = "-" } + +func (mi *MenuItem) Enabled() bool { return mi.enabled } +func (mi *MenuItem) SetEnabled(b bool) { mi.enabled = b; mi.update() } + +func (mi *MenuItem) Checkable() bool { return mi.checkable } +func (mi *MenuItem) SetCheckable(b bool) { mi.checkable = b; mi.update() } + +func (mi *MenuItem) Checked() bool { return mi.checked } +func (mi *MenuItem) SetChecked(b bool) { + if mi.isRadio { + radioGroup := radioGroups[mi] + if radioGroup != nil { + for _, member := range radioGroup.members { + member.checked = false + } + } + + } + mi.checked = b + mi.update() +} + +func (mi *MenuItem) Text() string { return mi.text } +func (mi *MenuItem) SetText(s string) { mi.text = s; mi.update() } + +func (mi *MenuItem) Image() *Bitmap { return mi.image } +func (mi *MenuItem) SetImage(b *Bitmap) { mi.image = b; mi.update() } + +func (mi *MenuItem) ToolTip() string { return mi.toolTip } +func (mi *MenuItem) SetToolTip(s string) { mi.toolTip = s; mi.update() } + +func (mi *MenuItem) updateRadioGroup() { + radioGroup := radioGroups[mi] + if radioGroup == nil { + return + } + startID := radioGroup.members[0].id + endID := radioGroup.members[len(radioGroup.members)-1].id + w32.SelectRadioMenuItem(mi.id, startID, endID, radioGroup.hwnd) +} diff --git a/v2/internal/frontend/desktop/windows/winc/mousecontrol.go b/v2/internal/frontend/desktop/windows/winc/mousecontrol.go new file mode 100644 index 000000000..12cf634c1 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/mousecontrol.go @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +// MouseControl used for creating custom controls that need mouse hover or mouse leave events. +type MouseControl struct { + ControlBase + isMouseLeft bool +} + +func (cc *MouseControl) Init(parent Controller, className string, exStyle, style uint) { + RegClassOnlyOnce(className) + cc.hwnd = CreateWindow(className, parent, exStyle, style) + cc.parent = parent + RegMsgHandler(cc) + + cc.isMouseLeft = true + cc.SetFont(DefaultFont) +} + +func (cc *MouseControl) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + sender := GetMsgHandler(cc.hwnd) + switch msg { + case w32.WM_CREATE: + internalTrackMouseEvent(cc.hwnd) + cc.onCreate.Fire(NewEvent(sender, nil)) + case w32.WM_CLOSE: + cc.onClose.Fire(NewEvent(sender, nil)) + case w32.WM_MOUSEMOVE: + //if cc.isMouseLeft { + + cc.onMouseHover.Fire(NewEvent(sender, nil)) + //internalTrackMouseEvent(cc.hwnd) + cc.isMouseLeft = false + + //} + case w32.WM_MOUSELEAVE: + cc.onMouseLeave.Fire(NewEvent(sender, nil)) + cc.isMouseLeft = true + } + return w32.DefWindowProc(cc.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/msghandlerregistry.go b/v2/internal/frontend/desktop/windows/winc/msghandlerregistry.go new file mode 100644 index 000000000..a7b61631b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/msghandlerregistry.go @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +func RegMsgHandler(controller Controller) { + gControllerRegistry[controller.Handle()] = controller +} + +func UnRegMsgHandler(hwnd w32.HWND) { + delete(gControllerRegistry, hwnd) +} + +func GetMsgHandler(hwnd w32.HWND) Controller { + if controller, isExists := gControllerRegistry[hwnd]; isExists { + return controller + } + + return nil +} diff --git a/v2/internal/frontend/desktop/windows/winc/panel.go b/v2/internal/frontend/desktop/windows/winc/panel.go new file mode 100644 index 000000000..4bdf92b9b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/panel.go @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Panel struct { + ControlBase + layoutMng LayoutManager +} + +func NewPanel(parent Controller) *Panel { + pa := new(Panel) + + RegClassOnlyOnce("winc_Panel") + pa.hwnd = CreateWindow("winc_Panel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + pa.parent = parent + RegMsgHandler(pa) + + pa.SetFont(DefaultFont) + pa.SetText("") + pa.SetSize(200, 65) + return pa +} + +// SetLayout panel implements DockAllow interface. +func (pa *Panel) SetLayout(mng LayoutManager) { + pa.layoutMng = mng +} + +func (pa *Panel) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_SIZE, w32.WM_PAINT: + if pa.layoutMng != nil { + pa.layoutMng.Update() + } + } + return w32.DefWindowProc(pa.hwnd, msg, wparam, lparam) +} + +var errorPanelPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(255, 128, 128))) +var errorPanelOkPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(220, 220, 220))) + +// ErrorPanel shows errors or important messages. +// It is meant to stand out of other on screen controls. +type ErrorPanel struct { + ControlBase + pen *Pen + margin int +} + +// NewErrorPanel. +func NewErrorPanel(parent Controller) *ErrorPanel { + f := new(ErrorPanel) + f.init(parent) + + f.SetFont(DefaultFont) + f.SetText("No errors") + f.SetSize(200, 65) + f.margin = 5 + f.pen = errorPanelOkPen + return f +} + +func (epa *ErrorPanel) init(parent Controller) { + RegClassOnlyOnce("winc_ErrorPanel") + + epa.hwnd = CreateWindow("winc_ErrorPanel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + epa.parent = parent + + RegMsgHandler(epa) +} + +func (epa *ErrorPanel) SetMargin(margin int) { + epa.margin = margin +} + +func (epa *ErrorPanel) Printf(format string, v ...interface{}) { + epa.SetText(fmt.Sprintf(format, v...)) + epa.ShowAsError(false) +} + +func (epa *ErrorPanel) Errorf(format string, v ...interface{}) { + epa.SetText(fmt.Sprintf(format, v...)) + epa.ShowAsError(true) +} + +func (epa *ErrorPanel) ShowAsError(show bool) { + if show { + epa.pen = errorPanelPen + } else { + epa.pen = errorPanelOkPen + } + epa.Invalidate(true) +} + +func (epa *ErrorPanel) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_ERASEBKGND: + canvas := NewCanvasFromHDC(w32.HDC(wparam)) + r := epa.Bounds() + r.rect.Left += int32(epa.margin) + r.rect.Right -= int32(epa.margin) + r.rect.Top += int32(epa.margin) + r.rect.Bottom -= int32(epa.margin) + // old code used NewSystemColorBrush(w32.COLOR_BTNFACE) + canvas.DrawFillRect(r, epa.pen, NewSystemColorBrush(w32.COLOR_WINDOW)) + + r.rect.Left += 5 + canvas.DrawText(epa.Text(), r, 0, epa.Font(), RGB(0, 0, 0)) + canvas.Dispose() + return 1 + } + return w32.DefWindowProc(epa.hwnd, msg, wparam, lparam) +} + +// MultiPanel contains other panels and only makes one of them visible. +type MultiPanel struct { + ControlBase + current int + panels []*Panel +} + +func NewMultiPanel(parent Controller) *MultiPanel { + mpa := new(MultiPanel) + + RegClassOnlyOnce("winc_MultiPanel") + mpa.hwnd = CreateWindow("winc_MultiPanel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + mpa.parent = parent + RegMsgHandler(mpa) + + mpa.SetFont(DefaultFont) + mpa.SetText("") + mpa.SetSize(300, 200) + mpa.current = -1 + return mpa +} + +func (mpa *MultiPanel) Count() int { return len(mpa.panels) } + +// AddPanel adds panels to the internal list, first panel is visible all others are hidden. +func (mpa *MultiPanel) AddPanel(panel *Panel) { + if len(mpa.panels) > 0 { + panel.Hide() + } + mpa.current = 0 + mpa.panels = append(mpa.panels, panel) +} + +// ReplacePanel replaces panel, useful for refreshing controls on screen. +func (mpa *MultiPanel) ReplacePanel(index int, panel *Panel) { + mpa.panels[index] = panel +} + +// DeletePanel removed panel. +func (mpa *MultiPanel) DeletePanel(index int) { + mpa.panels = append(mpa.panels[:index], mpa.panels[index+1:]...) +} + +func (mpa *MultiPanel) Current() int { + return mpa.current +} + +func (mpa *MultiPanel) SetCurrent(index int) { + if index >= len(mpa.panels) { + panic("index greater than number of panels") + } + if mpa.current == -1 { + panic("no current panel, add panels first") + } + for i := range mpa.panels { + if i != index { + mpa.panels[i].Hide() + mpa.panels[i].Invalidate(true) + } + } + mpa.panels[index].Show() + mpa.panels[index].Invalidate(true) + mpa.current = index +} + +func (mpa *MultiPanel) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_SIZE: + // resize contained panels + for _, p := range mpa.panels { + p.SetPos(0, 0) + p.SetSize(mpa.Size()) + } + } + return w32.DefWindowProc(mpa.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/path.go b/v2/internal/frontend/desktop/windows/winc/path.go new file mode 100644 index 000000000..99f1829e7 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/path.go @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +func knownFolderPath(id w32.CSIDL) (string, error) { + var buf [w32.MAX_PATH]uint16 + + if !w32.SHGetSpecialFolderPath(0, &buf[0], id, false) { + return "", fmt.Errorf("SHGetSpecialFolderPath failed") + } + + return syscall.UTF16ToString(buf[0:]), nil +} + +func AppDataPath() (string, error) { + return knownFolderPath(w32.CSIDL_APPDATA) +} + +func CommonAppDataPath() (string, error) { + return knownFolderPath(w32.CSIDL_COMMON_APPDATA) +} + +func LocalAppDataPath() (string, error) { + return knownFolderPath(w32.CSIDL_LOCAL_APPDATA) +} + +// EnsureAppDataPath uses AppDataPath to ensure storage for local settings and databases. +func EnsureAppDataPath(company, product string) (string, error) { + path, err := AppDataPath() + if err != nil { + return path, err + } + p := filepath.Join(path, company, product) + + if _, err := os.Stat(p); os.IsNotExist(err) { + // path/to/whatever does not exist + if err := os.MkdirAll(p, os.ModePerm); err != nil { + return p, err + } + } + return p, nil +} + +func DriveNames() ([]string, error) { + bufLen := w32.GetLogicalDriveStrings(0, nil) + if bufLen == 0 { + return nil, fmt.Errorf("GetLogicalDriveStrings failed") + } + buf := make([]uint16, bufLen+1) + + bufLen = w32.GetLogicalDriveStrings(bufLen+1, &buf[0]) + if bufLen == 0 { + return nil, fmt.Errorf("GetLogicalDriveStrings failed") + } + + var names []string + for i := 0; i < len(buf)-2; { + name := syscall.UTF16ToString(buf[i:]) + names = append(names, name) + i += len(name) + 1 + } + return names, nil +} diff --git a/v2/internal/frontend/desktop/windows/winc/pen.go b/v2/internal/frontend/desktop/windows/winc/pen.go new file mode 100644 index 000000000..c8091186a --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/pen.go @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Pen struct { + hPen w32.HPEN + style uint + brush *Brush +} + +func NewPen(style uint, width uint, brush *Brush) *Pen { + if brush == nil { + panic("Brush cannot be nil") + } + + hPen := w32.ExtCreatePen(style, width, brush.GetLOGBRUSH(), 0, nil) + if hPen == 0 { + panic("Failed to create pen") + } + + return &Pen{hPen, style, brush} +} + +func NewNullPen() *Pen { + lb := w32.LOGBRUSH{LbStyle: w32.BS_NULL} + + hPen := w32.ExtCreatePen(w32.PS_COSMETIC|w32.PS_NULL, 1, &lb, 0, nil) + if hPen == 0 { + panic("failed to create null brush") + } + + return &Pen{hPen: hPen} +} + +func (pen *Pen) Style() uint { + return pen.style +} + +func (pen *Pen) Brush() *Brush { + return pen.brush +} + +func (pen *Pen) GetHPEN() w32.HPEN { + return pen.hPen +} + +func (pen *Pen) Dispose() { + if pen.hPen != 0 { + w32.DeleteObject(w32.HGDIOBJ(pen.hPen)) + pen.hPen = 0 + } +} diff --git a/v2/internal/frontend/desktop/windows/winc/progressbar.go b/v2/internal/frontend/desktop/windows/winc/progressbar.go new file mode 100644 index 000000000..19f3c51f4 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/progressbar.go @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ProgressBar struct { + ControlBase +} + +func NewProgressBar(parent Controller) *ProgressBar { + pb := new(ProgressBar) + + pb.InitControl(w32.PROGRESS_CLASS, parent, 0, w32.WS_CHILD|w32.WS_VISIBLE) + RegMsgHandler(pb) + + pb.SetSize(200, 22) + return pb +} + +func (pr *ProgressBar) Value() int { + ret := w32.SendMessage(pr.hwnd, w32.PBM_GETPOS, 0, 0) + return int(ret) +} + +func (pr *ProgressBar) SetValue(v int) { + w32.SendMessage(pr.hwnd, w32.PBM_SETPOS, uintptr(v), 0) +} + +func (pr *ProgressBar) Range() (min, max uint) { + min = uint(w32.SendMessage(pr.hwnd, w32.PBM_GETRANGE, uintptr(w32.BoolToBOOL(true)), 0)) + max = uint(w32.SendMessage(pr.hwnd, w32.PBM_GETRANGE, uintptr(w32.BoolToBOOL(false)), 0)) + return +} + +func (pr *ProgressBar) SetRange(min, max int) { + w32.SendMessage(pr.hwnd, w32.PBM_SETRANGE32, uintptr(min), uintptr(max)) +} + +func (pr *ProgressBar) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + return w32.DefWindowProc(pr.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/rect.go b/v2/internal/frontend/desktop/windows/winc/rect.go new file mode 100644 index 000000000..43daa7537 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/rect.go @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Rect struct { + rect w32.RECT +} + +func NewEmptyRect() *Rect { + var newRect Rect + w32.SetRectEmpty(&newRect.rect) + + return &newRect +} + +func NewRect(left, top, right, bottom int) *Rect { + var newRect Rect + w32.SetRectEmpty(&newRect.rect) + newRect.Set(left, top, right, bottom) + + return &newRect +} + +func (re *Rect) Data() (left, top, right, bottom int32) { + left = re.rect.Left + top = re.rect.Top + right = re.rect.Right + bottom = re.rect.Bottom + return +} + +func (re *Rect) Width() int { + return int(re.rect.Right - re.rect.Left) +} + +func (re *Rect) Height() int { + return int(re.rect.Bottom - re.rect.Top) +} + +func (re *Rect) GetW32Rect() *w32.RECT { + return &re.rect +} + +func (re *Rect) Set(left, top, right, bottom int) { + w32.SetRect(&re.rect, left, top, right, bottom) +} + +func (re *Rect) IsEqual(rect *Rect) bool { + return w32.EqualRect(&re.rect, &rect.rect) +} + +func (re *Rect) Inflate(x, y int) { + w32.InflateRect(&re.rect, x, y) +} + +func (re *Rect) Intersect(src *Rect) { + w32.IntersectRect(&re.rect, &re.rect, &src.rect) +} + +func (re *Rect) IsEmpty() bool { + return w32.IsRectEmpty(&re.rect) +} + +func (re *Rect) Offset(x, y int) { + w32.OffsetRect(&re.rect, x, y) +} + +func (re *Rect) IsPointIn(x, y int) bool { + return w32.PtInRect(&re.rect, x, y) +} + +func (re *Rect) Substract(src *Rect) { + w32.SubtractRect(&re.rect, &re.rect, &src.rect) +} + +func (re *Rect) Union(src *Rect) { + w32.UnionRect(&re.rect, &re.rect, &src.rect) +} diff --git a/v2/internal/frontend/desktop/windows/winc/resizer.go b/v2/internal/frontend/desktop/windows/winc/resizer.go new file mode 100644 index 000000000..9c0ac1f78 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/resizer.go @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type VResizer struct { + ControlBase + + control1 Dockable + control2 Dockable + dir Direction + + mouseLeft bool + drag bool +} + +func NewVResizer(parent Controller) *VResizer { + sp := new(VResizer) + + RegClassOnlyOnce("winc_VResizer") + sp.hwnd = CreateWindow("winc_VResizer", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + sp.parent = parent + sp.mouseLeft = true + RegMsgHandler(sp) + + sp.SetFont(DefaultFont) + sp.SetText("") + sp.SetSize(20, 100) + return sp +} + +func (sp *VResizer) SetControl(control1, control2 Dockable, dir Direction, minSize int) { + sp.control1 = control1 + sp.control2 = control2 + if dir != Left && dir != Right { + panic("invalid direction") + } + sp.dir = dir + + // TODO(vi): ADDED + /*internalTrackMouseEvent(control1.Handle()) + internalTrackMouseEvent(control2.Handle()) + + control1.OnMouseMove().Bind(func(e *Event) { + if sp.drag { + x := e.Data.(*MouseEventData).X + sp.update(x) + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_SIZEWE))) + + } + fmt.Println("control1.OnMouseMove") + }) + + control2.OnMouseMove().Bind(func(e *Event) { + if sp.drag { + x := e.Data.(*MouseEventData).X + sp.update(x) + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_SIZEWE))) + + } + fmt.Println("control2.OnMouseMove") + }) + + control1.OnLBUp().Bind(func(e *Event) { + sp.drag = false + sp.mouseLeft = true + fmt.Println("control1.OnLBUp") + }) + + control2.OnLBUp().Bind(func(e *Event) { + sp.drag = false + sp.mouseLeft = true + fmt.Println("control2.OnLBUp") + })*/ + + // ---- finish ADDED + +} + +func (sp *VResizer) update(x int) { + pos := x - 10 + + w1, h1 := sp.control1.Width(), sp.control1.Height() + if sp.dir == Left { + w1 += pos + } else { + w1 -= pos + } + sp.control1.SetSize(w1, h1) + fm := sp.parent.(*Form) + fm.UpdateLayout() + + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_ARROW))) +} + +func (sp *VResizer) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_CREATE: + internalTrackMouseEvent(sp.hwnd) + + case w32.WM_MOUSEMOVE: + if sp.drag { + x, _ := genPoint(lparam) + sp.update(x) + } else { + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_SIZEWE))) + } + + if sp.mouseLeft { + internalTrackMouseEvent(sp.hwnd) + sp.mouseLeft = false + } + + case w32.WM_MOUSELEAVE: + sp.drag = false + sp.mouseLeft = true + + case w32.WM_LBUTTONUP: + sp.drag = false + + case w32.WM_LBUTTONDOWN: + sp.drag = true + } + return w32.DefWindowProc(sp.hwnd, msg, wparam, lparam) +} + +type HResizer struct { + ControlBase + + control1 Dockable + control2 Dockable + dir Direction + mouseLeft bool + drag bool +} + +func NewHResizer(parent Controller) *HResizer { + sp := new(HResizer) + + RegClassOnlyOnce("winc_HResizer") + sp.hwnd = CreateWindow("winc_HResizer", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE) + sp.parent = parent + sp.mouseLeft = true + RegMsgHandler(sp) + + sp.SetFont(DefaultFont) + sp.SetText("") + sp.SetSize(100, 20) + + return sp +} + +func (sp *HResizer) SetControl(control1, control2 Dockable, dir Direction, minSize int) { + sp.control1 = control1 + sp.control2 = control2 + if dir != Top && dir != Bottom { + panic("invalid direction") + } + sp.dir = dir + +} + +func (sp *HResizer) update(y int) { + pos := y - 10 + + w1, h1 := sp.control1.Width(), sp.control1.Height() + if sp.dir == Top { + h1 += pos + } else { + h1 -= pos + } + sp.control1.SetSize(w1, h1) + + fm := sp.parent.(*Form) + fm.UpdateLayout() + + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_ARROW))) +} + +func (sp *HResizer) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_CREATE: + internalTrackMouseEvent(sp.hwnd) + + case w32.WM_MOUSEMOVE: + if sp.drag { + _, y := genPoint(lparam) + sp.update(y) + } else { + w32.SetCursor(w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_SIZENS))) + } + + if sp.mouseLeft { + internalTrackMouseEvent(sp.hwnd) + sp.mouseLeft = false + } + + case w32.WM_MOUSELEAVE: + sp.drag = false + sp.mouseLeft = true + + case w32.WM_LBUTTONUP: + sp.drag = false + + case w32.WM_LBUTTONDOWN: + sp.drag = true + } + return w32.DefWindowProc(sp.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/scrollview.go b/v2/internal/frontend/desktop/windows/winc/scrollview.go new file mode 100644 index 000000000..395dfed68 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/scrollview.go @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ScrollView struct { + ControlBase + child Dockable +} + +func NewScrollView(parent Controller) *ScrollView { + sv := new(ScrollView) + + RegClassOnlyOnce("winc_ScrollView") + sv.hwnd = CreateWindow("winc_ScrollView", parent, w32.WS_EX_CONTROLPARENT, + w32.WS_CHILD|w32.WS_HSCROLL|w32.WS_VISIBLE|w32.WS_VSCROLL) + sv.parent = parent + RegMsgHandler(sv) + + sv.SetFont(DefaultFont) + sv.SetText("") + sv.SetSize(200, 200) + return sv +} + +func (sv *ScrollView) SetChild(child Dockable) { + sv.child = child +} + +func (sv *ScrollView) UpdateScrollBars() { + w, h := sv.child.Width(), sv.child.Height() + sw, sh := sv.Size() + + var si w32.SCROLLINFO + si.CbSize = uint32(unsafe.Sizeof(si)) + si.FMask = w32.SIF_PAGE | w32.SIF_RANGE + + si.NMax = int32(w - 1) + si.NPage = uint32(sw) + w32.SetScrollInfo(sv.hwnd, w32.SB_HORZ, &si, true) + x := sv.scroll(w32.SB_HORZ, w32.SB_THUMBPOSITION) + + si.NMax = int32(h) + si.NPage = uint32(sh) + w32.SetScrollInfo(sv.hwnd, w32.SB_VERT, &si, true) + y := sv.scroll(w32.SB_VERT, w32.SB_THUMBPOSITION) + + sv.child.SetPos(x, y) +} + +func (sv *ScrollView) scroll(sb int32, cmd uint16) int { + var pos int32 + var si w32.SCROLLINFO + si.CbSize = uint32(unsafe.Sizeof(si)) + si.FMask = w32.SIF_PAGE | w32.SIF_POS | w32.SIF_RANGE | w32.SIF_TRACKPOS + + w32.GetScrollInfo(sv.hwnd, sb, &si) + pos = si.NPos + + switch cmd { + case w32.SB_LINELEFT: // == win.SB_LINEUP + pos -= 20 + + case w32.SB_LINERIGHT: // == win.SB_LINEDOWN + pos += 20 + + case w32.SB_PAGELEFT: // == win.SB_PAGEUP + pos -= int32(si.NPage) + + case w32.SB_PAGERIGHT: // == win.SB_PAGEDOWN + pos += int32(si.NPage) + + case w32.SB_THUMBTRACK: + pos = si.NTrackPos + } + + if pos < 0 { + pos = 0 + } + if pos > si.NMax+1-int32(si.NPage) { + pos = si.NMax + 1 - int32(si.NPage) + } + + si.FMask = w32.SIF_POS + si.NPos = pos + w32.SetScrollInfo(sv.hwnd, sb, &si, true) + + return -int(pos) +} + +func (sv *ScrollView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + if sv.child != nil { + switch msg { + case w32.WM_PAINT: + sv.UpdateScrollBars() + + case w32.WM_HSCROLL: + x, y := sv.child.Pos() + x = sv.scroll(w32.SB_HORZ, w32.LOWORD(uint32(wparam))) + sv.child.SetPos(x, y) + + case w32.WM_VSCROLL: + x, y := sv.child.Pos() + y = sv.scroll(w32.SB_VERT, w32.LOWORD(uint32(wparam))) + sv.child.SetPos(x, y) + + case w32.WM_SIZE, w32.WM_SIZING: + sv.UpdateScrollBars() + } + } + return w32.DefWindowProc(sv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/slider.go b/v2/internal/frontend/desktop/windows/winc/slider.go new file mode 100644 index 000000000..2a1e55030 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/slider.go @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + +type Slider struct { + ControlBase + prevPos int + + onScroll EventManager +} + +func NewSlider(parent Controller) *Slider { + tb := new(Slider) + + tb.InitControl("msctls_trackbar32", parent, 0, w32.WS_TABSTOP|w32.WS_VISIBLE|w32.WS_CHILD /*|w32.TBS_AUTOTICKS*/) + RegMsgHandler(tb) + + tb.SetFont(DefaultFont) + tb.SetText("Slider") + tb.SetSize(200, 32) + + tb.SetRange(0, 100) + tb.SetPage(10) + return tb +} + +func (tb *Slider) OnScroll() *EventManager { + return &tb.onScroll +} + +func (tb *Slider) Value() int { + ret := w32.SendMessage(tb.hwnd, w32.TBM_GETPOS, 0, 0) + return int(ret) +} + +func (tb *Slider) SetValue(v int) { + tb.prevPos = v + w32.SendMessage(tb.hwnd, w32.TBM_SETPOS, uintptr(w32.BoolToBOOL(true)), uintptr(v)) +} + +func (tb *Slider) Range() (min, max int) { + min = int(w32.SendMessage(tb.hwnd, w32.TBM_GETRANGEMIN, 0, 0)) + max = int(w32.SendMessage(tb.hwnd, w32.TBM_GETRANGEMAX, 0, 0)) + return min, max +} + +func (tb *Slider) SetRange(min, max int) { + w32.SendMessage(tb.hwnd, w32.TBM_SETRANGE, uintptr(w32.BoolToBOOL(true)), uintptr(w32.MAKELONG(uint16(min), uint16(max)))) +} + +func (tb *Slider) SetPage(pagesize int) { + w32.SendMessage(tb.hwnd, w32.TBM_SETPAGESIZE, 0, uintptr(pagesize)) +} + +func (tb *Slider) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + /* + // REMOVE: + // following code did not work, used workaround below + code := w32.LOWORD(uint32(wparam)) + + switch code { + case w32.TB_ENDTRACK: + tb.onScroll.Fire(NewEvent(tb, nil)) + }*/ + + newPos := tb.Value() + if newPos != tb.prevPos { + tb.onScroll.Fire(NewEvent(tb, nil)) + tb.prevPos = newPos + } + + return w32.DefWindowProc(tb.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/tabview.go b/v2/internal/frontend/desktop/windows/winc/tabview.go new file mode 100644 index 000000000..161877119 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/tabview.go @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +// TabView creates MultiPanel internally and manages tabs as panels. +type TabView struct { + ControlBase + + panels *MultiPanel + onSelectedChange EventManager +} + +func NewTabView(parent Controller) *TabView { + tv := new(TabView) + + tv.InitControl("SysTabControl32", parent, 0, + w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.WS_CLIPSIBLINGS) + RegMsgHandler(tv) + + tv.panels = NewMultiPanel(parent) + + tv.SetFont(DefaultFont) + tv.SetSize(200, 24) + return tv +} + +func (tv *TabView) Panels() *MultiPanel { + return tv.panels +} + +func (tv *TabView) tcitemFromPage(panel *Panel) *w32.TCITEM { + text := syscall.StringToUTF16(panel.Text()) + item := &w32.TCITEM{ + Mask: w32.TCIF_TEXT, + PszText: &text[0], + CchTextMax: int32(len(text)), + } + return item +} + +func (tv *TabView) AddPanel(text string) *Panel { + panel := NewPanel(tv.panels) + panel.SetText(text) + + item := tv.tcitemFromPage(panel) + index := tv.panels.Count() + idx := int(w32.SendMessage(tv.hwnd, w32.TCM_INSERTITEM, uintptr(index), uintptr(unsafe.Pointer(item)))) + if idx == -1 { + panic("SendMessage(TCM_INSERTITEM) failed") + } + + tv.panels.AddPanel(panel) + tv.SetCurrent(idx) + return panel +} + +func (tv *TabView) DeletePanel(index int) { + w32.SendMessage(tv.hwnd, w32.TCM_DELETEITEM, uintptr(index), 0) + tv.panels.DeletePanel(index) + switch { + case tv.panels.Count() > index: + tv.SetCurrent(index) + case tv.panels.Count() == 0: + tv.SetCurrent(0) + } +} + +func (tv *TabView) Current() int { + return tv.panels.Current() +} + +func (tv *TabView) SetCurrent(index int) { + if index < 0 || index >= tv.panels.Count() { + panic("invalid index") + } + if ret := int(w32.SendMessage(tv.hwnd, w32.TCM_SETCURSEL, uintptr(index), 0)); ret == -1 { + panic("SendMessage(TCM_SETCURSEL) failed") + } + tv.panels.SetCurrent(index) +} + +func (tv *TabView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_NOTIFY: + nmhdr := (*w32.NMHDR)(unsafe.Pointer(lparam)) + + switch int32(nmhdr.Code) { + case w32.TCN_SELCHANGE: + cur := int(w32.SendMessage(tv.hwnd, w32.TCM_GETCURSEL, 0, 0)) + tv.SetCurrent(cur) + + tv.onSelectedChange.Fire(NewEvent(tv, nil)) + } + } + return w32.DefWindowProc(tv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/toolbar.go b/v2/internal/frontend/desktop/windows/winc/toolbar.go new file mode 100644 index 000000000..ae1fe393d --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/toolbar.go @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type Toolbar struct { + ControlBase + iml *ImageList + + buttons []*ToolButton +} + +type ToolButton struct { + tb *Toolbar + + text string + enabled bool + checkable bool + checked bool + image int + + onClick EventManager +} + +func (bt *ToolButton) OnClick() *EventManager { + return &bt.onClick +} + +func (bt *ToolButton) update() { bt.tb.update(bt) } + +func (bt *ToolButton) IsSeparator() bool { return bt.text == "-" } +func (bt *ToolButton) SetSeparator() { bt.text = "-" } + +func (bt *ToolButton) Enabled() bool { return bt.enabled } +func (bt *ToolButton) SetEnabled(b bool) { bt.enabled = b; bt.update() } + +func (bt *ToolButton) Checkable() bool { return bt.checkable } +func (bt *ToolButton) SetCheckable(b bool) { bt.checkable = b; bt.update() } + +func (bt *ToolButton) Checked() bool { return bt.checked } +func (bt *ToolButton) SetChecked(b bool) { bt.checked = b; bt.update() } + +func (bt *ToolButton) Text() string { return bt.text } +func (bt *ToolButton) SetText(s string) { bt.text = s; bt.update() } + +func (bt *ToolButton) Image() int { return bt.image } +func (bt *ToolButton) SetImage(i int) { bt.image = i; bt.update() } + +// NewHToolbar creates horizontal toolbar with text on same line as image. +func NewHToolbar(parent Controller) *Toolbar { + return newToolbar(parent, w32.CCS_NODIVIDER|w32.TBSTYLE_FLAT|w32.TBSTYLE_TOOLTIPS|w32.TBSTYLE_WRAPABLE| + w32.WS_CHILD|w32.TBSTYLE_LIST) +} + +// NewToolbar creates toolbar with text below the image. +func NewToolbar(parent Controller) *Toolbar { + return newToolbar(parent, w32.CCS_NODIVIDER|w32.TBSTYLE_FLAT|w32.TBSTYLE_TOOLTIPS|w32.TBSTYLE_WRAPABLE| + w32.WS_CHILD /*|w32.TBSTYLE_TRANSPARENT*/) +} + +func newToolbar(parent Controller, style uint) *Toolbar { + tb := new(Toolbar) + + tb.InitControl("ToolbarWindow32", parent, 0, style) + + exStyle := w32.SendMessage(tb.hwnd, w32.TB_GETEXTENDEDSTYLE, 0, 0) + exStyle |= w32.TBSTYLE_EX_DRAWDDARROWS | w32.TBSTYLE_EX_MIXEDBUTTONS + w32.SendMessage(tb.hwnd, w32.TB_SETEXTENDEDSTYLE, 0, exStyle) + RegMsgHandler(tb) + + tb.SetFont(DefaultFont) + tb.SetPos(0, 0) + tb.SetSize(200, 40) + + return tb +} + +func (tb *Toolbar) SetImageList(imageList *ImageList) { + w32.SendMessage(tb.hwnd, w32.TB_SETIMAGELIST, 0, uintptr(imageList.Handle())) + tb.iml = imageList +} + +func (tb *Toolbar) initButton(btn *ToolButton, state, style *byte, image *int32, text *uintptr) { + *style |= w32.BTNS_AUTOSIZE + + if btn.checked { + *state |= w32.TBSTATE_CHECKED + } + + if btn.enabled { + *state |= w32.TBSTATE_ENABLED + } + + if btn.checkable { + *style |= w32.BTNS_CHECK + } + + if len(btn.Text()) > 0 { + *style |= w32.BTNS_SHOWTEXT + } + + if btn.IsSeparator() { + *style = w32.BTNS_SEP + } + + *image = int32(btn.Image()) + *text = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(btn.Text()))) +} + +func (tb *Toolbar) update(btn *ToolButton) { + tbbi := w32.TBBUTTONINFO{ + DwMask: w32.TBIF_IMAGE | w32.TBIF_STATE | w32.TBIF_STYLE | w32.TBIF_TEXT, + } + + tbbi.CbSize = uint32(unsafe.Sizeof(tbbi)) + + var i int + for i = range tb.buttons { + if tb.buttons[i] == btn { + break + } + } + + tb.initButton(btn, &tbbi.FsState, &tbbi.FsStyle, &tbbi.IImage, &tbbi.PszText) + if w32.SendMessage(tb.hwnd, w32.TB_SETBUTTONINFO, uintptr(i), uintptr(unsafe.Pointer(&tbbi))) == 0 { + panic("SendMessage(TB_SETBUTTONINFO) failed") + } +} + +func (tb *Toolbar) AddSeparator() { + tb.AddButton("-", 0) +} + +// AddButton creates and adds button to the toolbar. Use returned toolbutton to setup OnClick event. +func (tb *Toolbar) AddButton(text string, image int) *ToolButton { + bt := &ToolButton{ + tb: tb, // points to parent + text: text, + image: image, + enabled: true, + } + tb.buttons = append(tb.buttons, bt) + index := len(tb.buttons) - 1 + + tbb := w32.TBBUTTON{ + IdCommand: int32(index), + } + + tb.initButton(bt, &tbb.FsState, &tbb.FsStyle, &tbb.IBitmap, &tbb.IString) + w32.SendMessage(tb.hwnd, w32.TB_BUTTONSTRUCTSIZE, uintptr(unsafe.Sizeof(tbb)), 0) + + if w32.SendMessage(tb.hwnd, w32.TB_INSERTBUTTON, uintptr(index), uintptr(unsafe.Pointer(&tbb))) == w32.FALSE { + panic("SendMessage(TB_ADDBUTTONS)") + } + + w32.SendMessage(tb.hwnd, w32.TB_AUTOSIZE, 0, 0) + return bt +} + +func (tb *Toolbar) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_COMMAND: + switch w32.HIWORD(uint32(wparam)) { + case w32.BN_CLICKED: + id := uint16(w32.LOWORD(uint32(wparam))) + btn := tb.buttons[id] + btn.onClick.Fire(NewEvent(tb, nil)) + } + } + return w32.DefWindowProc(tb.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/tooltip.go b/v2/internal/frontend/desktop/windows/winc/tooltip.go new file mode 100644 index 000000000..f18ba1cda --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/tooltip.go @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +type ToolTip struct { + ControlBase +} + +func NewToolTip(parent Controller) *ToolTip { + tp := new(ToolTip) + + tp.InitControl("tooltips_class32", parent, w32.WS_EX_TOPMOST, w32.WS_POPUP|w32.TTS_NOPREFIX|w32.TTS_ALWAYSTIP) + w32.SetWindowPos(tp.Handle(), w32.HWND_TOPMOST, 0, 0, 0, 0, w32.SWP_NOMOVE|w32.SWP_NOSIZE|w32.SWP_NOACTIVATE) + + return tp +} + +func (tp *ToolTip) SetTip(tool Controller, tip string) bool { + var ti w32.TOOLINFO + ti.CbSize = uint32(unsafe.Sizeof(ti)) + if tool.Parent() != nil { + ti.Hwnd = tool.Parent().Handle() + } + ti.UFlags = w32.TTF_IDISHWND | w32.TTF_SUBCLASS /* | TTF_ABSOLUTE */ + ti.UId = uintptr(tool.Handle()) + ti.LpszText = syscall.StringToUTF16Ptr(tip) + + return w32.SendMessage(tp.Handle(), w32.TTM_ADDTOOL, 0, uintptr(unsafe.Pointer(&ti))) != w32.FALSE +} + +func (tp *ToolTip) WndProc(msg uint, wparam, lparam uintptr) uintptr { + return w32.DefWindowProc(tp.hwnd, uint32(msg), wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/treeview.go b/v2/internal/frontend/desktop/windows/winc/treeview.go new file mode 100644 index 000000000..4976fa65d --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/treeview.go @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + */ + +package winc + +import ( + "errors" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +// TreeItem represents an item in a TreeView widget. +type TreeItem interface { + Text() string // Text returns the text of the item. + ImageIndex() int // ImageIndex is used only if SetImageList is called on the treeview +} + +type treeViewItemInfo struct { + handle w32.HTREEITEM + child2Handle map[TreeItem]w32.HTREEITEM +} + +// StringTreeItem is helper for basic string lists. +type StringTreeItem struct { + Data string + Image int +} + +func (s StringTreeItem) Text() string { return s.Data } +func (s StringTreeItem) ImageIndex() int { return s.Image } + +type TreeView struct { + ControlBase + + iml *ImageList + item2Info map[TreeItem]*treeViewItemInfo + handle2Item map[w32.HTREEITEM]TreeItem + currItem TreeItem + + onSelectedChange EventManager + onExpand EventManager + onCollapse EventManager + onViewChange EventManager +} + +func NewTreeView(parent Controller) *TreeView { + tv := new(TreeView) + + tv.InitControl("SysTreeView32", parent, 0, w32.WS_CHILD|w32.WS_VISIBLE| + w32.WS_BORDER|w32.TVS_HASBUTTONS|w32.TVS_LINESATROOT|w32.TVS_SHOWSELALWAYS| + w32.TVS_TRACKSELECT /*|w32.WS_EX_CLIENTEDGE*/) + + tv.item2Info = make(map[TreeItem]*treeViewItemInfo) + tv.handle2Item = make(map[w32.HTREEITEM]TreeItem) + + RegMsgHandler(tv) + + tv.SetFont(DefaultFont) + tv.SetSize(200, 400) + + if err := tv.SetTheme("Explorer"); err != nil { + // theme error is ignored + } + return tv +} + +func (tv *TreeView) EnableDoubleBuffer(enable bool) { + if enable { + w32.SendMessage(tv.hwnd, w32.TVM_SETEXTENDEDSTYLE, 0, w32.TVS_EX_DOUBLEBUFFER) + } else { + w32.SendMessage(tv.hwnd, w32.TVM_SETEXTENDEDSTYLE, w32.TVS_EX_DOUBLEBUFFER, 0) + } +} + +// SelectedItem is current selected item after OnSelectedChange event. +func (tv *TreeView) SelectedItem() TreeItem { + return tv.currItem +} + +func (tv *TreeView) SetSelectedItem(item TreeItem) bool { + var handle w32.HTREEITEM + if item != nil { + if info := tv.item2Info[item]; info == nil { + return false // invalid item + } else { + handle = info.handle + } + } + + if w32.SendMessage(tv.hwnd, w32.TVM_SELECTITEM, w32.TVGN_CARET, uintptr(handle)) == 0 { + return false // set selected failed + } + tv.currItem = item + return true +} + +func (tv *TreeView) ItemAt(x, y int) TreeItem { + hti := w32.TVHITTESTINFO{Pt: w32.POINT{int32(x), int32(y)}} + w32.SendMessage(tv.hwnd, w32.TVM_HITTEST, 0, uintptr(unsafe.Pointer(&hti))) + if item, ok := tv.handle2Item[hti.HItem]; ok { + return item + } + return nil +} + +func (tv *TreeView) Items() (list []TreeItem) { + for item := range tv.item2Info { + list = append(list, item) + } + return list +} + +func (tv *TreeView) InsertItem(item, parent, insertAfter TreeItem) error { + var tvins w32.TVINSERTSTRUCT + tvi := &tvins.Item + + tvi.Mask = w32.TVIF_TEXT // w32.TVIF_CHILDREN | w32.TVIF_TEXT + tvi.PszText = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(item.Text()))) // w32.LPSTR_TEXTCALLBACK + tvi.CChildren = 0 // w32.I_CHILDRENCALLBACK + + if parent == nil { + tvins.HParent = w32.TVI_ROOT + } else { + info := tv.item2Info[parent] + if info == nil { + return errors.New("winc: invalid parent") + } + tvins.HParent = info.handle + } + + if insertAfter == nil { + tvins.HInsertAfter = w32.TVI_LAST + } else { + info := tv.item2Info[insertAfter] + if info == nil { + return errors.New("winc: invalid prev item") + } + tvins.HInsertAfter = info.handle + } + + tv.applyImage(tvi, item) + + hItem := w32.HTREEITEM(w32.SendMessage(tv.hwnd, w32.TVM_INSERTITEM, 0, uintptr(unsafe.Pointer(&tvins)))) + if hItem == 0 { + return errors.New("winc: TVM_INSERTITEM failed") + } + tv.item2Info[item] = &treeViewItemInfo{hItem, make(map[TreeItem]w32.HTREEITEM)} + tv.handle2Item[hItem] = item + return nil +} + +func (tv *TreeView) UpdateItem(item TreeItem) bool { + it := tv.item2Info[item] + if it == nil { + return false + } + + tvi := &w32.TVITEM{ + Mask: w32.TVIF_TEXT, + HItem: it.handle, + PszText: uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(item.Text()))), + } + tv.applyImage(tvi, item) + + if w32.SendMessage(tv.hwnd, w32.TVM_SETITEM, 0, uintptr(unsafe.Pointer(tvi))) == 0 { + return false + } + return true +} + +func (tv *TreeView) DeleteItem(item TreeItem) bool { + it := tv.item2Info[item] + if it == nil { + return false + } + + if w32.SendMessage(tv.hwnd, w32.TVM_DELETEITEM, 0, uintptr(it.handle)) == 0 { + return false + } + + delete(tv.item2Info, item) + delete(tv.handle2Item, it.handle) + return true +} + +func (tv *TreeView) DeleteAllItems() bool { + if w32.SendMessage(tv.hwnd, w32.TVM_DELETEITEM, 0, 0) == 0 { + return false + } + + tv.item2Info = make(map[TreeItem]*treeViewItemInfo) + tv.handle2Item = make(map[w32.HTREEITEM]TreeItem) + return true +} + +func (tv *TreeView) Expand(item TreeItem) bool { + if w32.SendMessage(tv.hwnd, w32.TVM_EXPAND, w32.TVE_EXPAND, uintptr(tv.item2Info[item].handle)) == 0 { + return false + } + return true +} + +func (tv *TreeView) Collapse(item TreeItem) bool { + if w32.SendMessage(tv.hwnd, w32.TVM_EXPAND, w32.TVE_COLLAPSE, uintptr(tv.item2Info[item].handle)) == 0 { + return false + } + return true +} + +func (tv *TreeView) EnsureVisible(item TreeItem) bool { + if info := tv.item2Info[item]; info != nil { + return w32.SendMessage(tv.hwnd, w32.TVM_ENSUREVISIBLE, 0, uintptr(info.handle)) != 0 + } + return false +} + +func (tv *TreeView) SetImageList(imageList *ImageList) { + w32.SendMessage(tv.hwnd, w32.TVM_SETIMAGELIST, 0, uintptr(imageList.Handle())) + tv.iml = imageList +} + +func (tv *TreeView) applyImage(tc *w32.TVITEM, item TreeItem) { + if tv.iml != nil { + tc.Mask |= w32.TVIF_IMAGE | w32.TVIF_SELECTEDIMAGE + tc.IImage = int32(item.ImageIndex()) + tc.ISelectedImage = int32(item.ImageIndex()) + } +} + +func (tv *TreeView) OnSelectedChange() *EventManager { + return &tv.onSelectedChange +} + +func (tv *TreeView) OnExpand() *EventManager { + return &tv.onExpand +} + +func (tv *TreeView) OnCollapse() *EventManager { + return &tv.onCollapse +} + +func (tv *TreeView) OnViewChange() *EventManager { + return &tv.onViewChange +} + +// Message processer +func (tv *TreeView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { + switch msg { + case w32.WM_NOTIFY: + nm := (*w32.NMHDR)(unsafe.Pointer(lparam)) + + switch nm.Code { + case w32.TVN_ITEMEXPANDED: + nmtv := (*w32.NMTREEVIEW)(unsafe.Pointer(lparam)) + + switch nmtv.Action { + case w32.TVE_COLLAPSE: + tv.onCollapse.Fire(NewEvent(tv, nil)) + + case w32.TVE_COLLAPSERESET: + + case w32.TVE_EXPAND: + tv.onExpand.Fire(NewEvent(tv, nil)) + + case w32.TVE_EXPANDPARTIAL: + + case w32.TVE_TOGGLE: + } + + case w32.TVN_SELCHANGED: + nmtv := (*w32.NMTREEVIEW)(unsafe.Pointer(lparam)) + tv.currItem = tv.handle2Item[nmtv.ItemNew.HItem] + tv.onSelectedChange.Fire(NewEvent(tv, nil)) + + case w32.TVN_GETDISPINFO: + tv.onViewChange.Fire(NewEvent(tv, nil)) + } + + } + return w32.DefWindowProc(tv.hwnd, msg, wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/winc/utils.go b/v2/internal/frontend/desktop/windows/winc/utils.go new file mode 100644 index 000000000..aa4304a1c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/utils.go @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "fmt" + "syscall" + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +func internalTrackMouseEvent(hwnd w32.HWND) { + var tme w32.TRACKMOUSEEVENT + tme.CbSize = uint32(unsafe.Sizeof(tme)) + tme.DwFlags = w32.TME_LEAVE + tme.HwndTrack = hwnd + tme.DwHoverTime = w32.HOVER_DEFAULT + + w32.TrackMouseEvent(&tme) +} + +func SetStyle(hwnd w32.HWND, b bool, style int) { + originalStyle := int(w32.GetWindowLongPtr(hwnd, w32.GWL_STYLE)) + if originalStyle != 0 { + if b { + originalStyle |= style + } else { + originalStyle &^= style + } + w32.SetWindowLongPtr(hwnd, w32.GWL_STYLE, uintptr(originalStyle)) + } +} + +func SetExStyle(hwnd w32.HWND, b bool, style int) { + originalStyle := int(w32.GetWindowLongPtr(hwnd, w32.GWL_EXSTYLE)) + if originalStyle != 0 { + if b { + originalStyle |= style + } else { + originalStyle &^= style + } + w32.SetWindowLongPtr(hwnd, w32.GWL_EXSTYLE, uintptr(originalStyle)) + } +} + +func CreateWindow(className string, parent Controller, exStyle, style uint) w32.HWND { + instance := GetAppInstance() + var parentHwnd w32.HWND + if parent != nil { + parentHwnd = parent.Handle() + } + var hwnd w32.HWND + hwnd = w32.CreateWindowEx( + exStyle, + syscall.StringToUTF16Ptr(className), + nil, + style, + w32.CW_USEDEFAULT, + w32.CW_USEDEFAULT, + w32.CW_USEDEFAULT, + w32.CW_USEDEFAULT, + parentHwnd, + 0, + instance, + nil) + + if hwnd == 0 { + errStr := fmt.Sprintf("Error occurred in CreateWindow(%s, %v, %d, %d)", className, parent, exStyle, style) + panic(errStr) + } + + return hwnd +} + +func RegisterClass(className string, wndproc uintptr) { + instance := GetAppInstance() + icon := w32.LoadIcon(instance, w32.MakeIntResource(w32.IDI_APPLICATION)) + + var wc w32.WNDCLASSEX + wc.Size = uint32(unsafe.Sizeof(wc)) + wc.Style = w32.CS_HREDRAW | w32.CS_VREDRAW + wc.WndProc = wndproc + wc.Instance = instance + wc.Background = w32.COLOR_BTNFACE + 1 + wc.Icon = icon + wc.Cursor = w32.LoadCursor(0, w32.MakeIntResource(w32.IDC_ARROW)) + wc.ClassName = syscall.StringToUTF16Ptr(className) + wc.MenuName = nil + wc.IconSm = icon + + if ret := w32.RegisterClassEx(&wc); ret == 0 { + panic(syscall.GetLastError()) + } +} + +func RegisterWindowMessage(name string) uint32 { + n := syscall.StringToUTF16Ptr(name) + + ret := w32.RegisterWindowMessage(n) + if ret == 0 { + panic(syscall.GetLastError()) + } + return ret +} + +func getMonitorInfo(hwnd w32.HWND) *w32.MONITORINFO { + currentMonitor := w32.MonitorFromWindow(hwnd, w32.MONITOR_DEFAULTTONEAREST) + var info w32.MONITORINFO + info.CbSize = uint32(unsafe.Sizeof(info)) + w32.GetMonitorInfo(currentMonitor, &info) + return &info +} +func getWindowInfo(hwnd w32.HWND) *w32.WINDOWINFO { + var info w32.WINDOWINFO + info.CbSize = uint32(unsafe.Sizeof(info)) + w32.GetWindowInfo(hwnd, &info) + return &info +} + +func RegClassOnlyOnce(className string) { + isExists := false + for _, class := range gRegisteredClasses { + if class == className { + isExists = true + break + } + } + + if !isExists { + RegisterClass(className, GeneralWndprocCallBack) + gRegisteredClasses = append(gRegisteredClasses, className) + } +} + +func ScreenToClientRect(hwnd w32.HWND, rect *w32.RECT) *Rect { + l, t, r, b := rect.Left, rect.Top, rect.Right, rect.Bottom + l1, t1, _ := w32.ScreenToClient(hwnd, int(l), int(t)) + r1, b1, _ := w32.ScreenToClient(hwnd, int(r), int(b)) + return NewRect(l1, t1, r1, b1) +} + +// ScaleWithDPI scales the pixels from the default DPI-Space (96) to the target DPI-Space. +func ScaleWithDPI(pixels int, dpi uint) int { + return (pixels * int(dpi)) / 96 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/comctl32.go b/v2/internal/frontend/desktop/windows/winc/w32/comctl32.go new file mode 100644 index 000000000..0f37403a0 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/comctl32.go @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modcomctl32 = syscall.NewLazyDLL("comctl32.dll") + + procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx") + procImageList_Create = modcomctl32.NewProc("ImageList_Create") + procImageList_Destroy = modcomctl32.NewProc("ImageList_Destroy") + procImageList_GetImageCount = modcomctl32.NewProc("ImageList_GetImageCount") + procImageList_SetImageCount = modcomctl32.NewProc("ImageList_SetImageCount") + procImageList_Add = modcomctl32.NewProc("ImageList_Add") + procImageList_ReplaceIcon = modcomctl32.NewProc("ImageList_ReplaceIcon") + procImageList_Remove = modcomctl32.NewProc("ImageList_Remove") + procTrackMouseEvent = modcomctl32.NewProc("_TrackMouseEvent") +) + +func InitCommonControlsEx(lpInitCtrls *INITCOMMONCONTROLSEX) bool { + ret, _, _ := procInitCommonControlsEx.Call( + uintptr(unsafe.Pointer(lpInitCtrls))) + + return ret != 0 +} + +func ImageList_Create(cx, cy int, flags uint, cInitial, cGrow int) HIMAGELIST { + ret, _, _ := procImageList_Create.Call( + uintptr(cx), + uintptr(cy), + uintptr(flags), + uintptr(cInitial), + uintptr(cGrow)) + + if ret == 0 { + panic("Create image list failed") + } + + return HIMAGELIST(ret) +} + +func ImageList_Destroy(himl HIMAGELIST) bool { + ret, _, _ := procImageList_Destroy.Call( + uintptr(himl)) + + return ret != 0 +} + +func ImageList_GetImageCount(himl HIMAGELIST) int { + ret, _, _ := procImageList_GetImageCount.Call( + uintptr(himl)) + + return int(ret) +} + +func ImageList_SetImageCount(himl HIMAGELIST, uNewCount uint) bool { + ret, _, _ := procImageList_SetImageCount.Call( + uintptr(himl), + uintptr(uNewCount)) + + return ret != 0 +} + +func ImageList_Add(himl HIMAGELIST, hbmImage, hbmMask HBITMAP) int { + ret, _, _ := procImageList_Add.Call( + uintptr(himl), + uintptr(hbmImage), + uintptr(hbmMask)) + + return int(ret) +} + +func ImageList_ReplaceIcon(himl HIMAGELIST, i int, hicon HICON) int { + ret, _, _ := procImageList_ReplaceIcon.Call( + uintptr(himl), + uintptr(i), + uintptr(hicon)) + + return int(ret) +} + +func ImageList_AddIcon(himl HIMAGELIST, hicon HICON) int { + return ImageList_ReplaceIcon(himl, -1, hicon) +} + +func ImageList_Remove(himl HIMAGELIST, i int) bool { + ret, _, _ := procImageList_Remove.Call( + uintptr(himl), + uintptr(i)) + + return ret != 0 +} + +func ImageList_RemoveAll(himl HIMAGELIST) bool { + return ImageList_Remove(himl, -1) +} + +func TrackMouseEvent(tme *TRACKMOUSEEVENT) bool { + ret, _, _ := procTrackMouseEvent.Call( + uintptr(unsafe.Pointer(tme))) + + return ret != 0 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/comdlg32.go b/v2/internal/frontend/desktop/windows/winc/w32/comdlg32.go new file mode 100644 index 000000000..936bcf33b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/comdlg32.go @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modcomdlg32 = syscall.NewLazyDLL("comdlg32.dll") + + procGetSaveFileName = modcomdlg32.NewProc("GetSaveFileNameW") + procGetOpenFileName = modcomdlg32.NewProc("GetOpenFileNameW") + procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError") +) + +func GetOpenFileName(ofn *OPENFILENAME) bool { + ret, _, _ := procGetOpenFileName.Call( + uintptr(unsafe.Pointer(ofn))) + + return ret != 0 +} + +func GetSaveFileName(ofn *OPENFILENAME) bool { + ret, _, _ := procGetSaveFileName.Call( + uintptr(unsafe.Pointer(ofn))) + + return ret != 0 +} + +func CommDlgExtendedError() uint { + ret, _, _ := procCommDlgExtendedError.Call() + + return uint(ret) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/constants.go b/v2/internal/frontend/desktop/windows/winc/w32/constants.go new file mode 100644 index 000000000..c8191ad5c --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/constants.go @@ -0,0 +1,3525 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +const ( + FALSE = 0 + TRUE = 1 +) + +const ( + NO_ERROR = 0 + ERROR_SUCCESS = 0 + ERROR_FILE_NOT_FOUND = 2 + ERROR_PATH_NOT_FOUND = 3 + ERROR_ACCESS_DENIED = 5 + ERROR_INVALID_HANDLE = 6 + ERROR_BAD_FORMAT = 11 + ERROR_INVALID_NAME = 123 + ERROR_MORE_DATA = 234 + ERROR_NO_MORE_ITEMS = 259 + ERROR_INVALID_SERVICE_CONTROL = 1052 + ERROR_SERVICE_REQUEST_TIMEOUT = 1053 + ERROR_SERVICE_NO_THREAD = 1054 + ERROR_SERVICE_DATABASE_LOCKED = 1055 + ERROR_SERVICE_ALREADY_RUNNING = 1056 + ERROR_SERVICE_DISABLED = 1058 + ERROR_SERVICE_DOES_NOT_EXIST = 1060 + ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061 + ERROR_SERVICE_NOT_ACTIVE = 1062 + ERROR_DATABASE_DOES_NOT_EXIST = 1065 + ERROR_SERVICE_DEPENDENCY_FAIL = 1068 + ERROR_SERVICE_LOGON_FAILED = 1069 + ERROR_SERVICE_MARKED_FOR_DELETE = 1072 + ERROR_SERVICE_DEPENDENCY_DELETED = 1075 +) + +const ( + SE_ERR_FNF = 2 + SE_ERR_PNF = 3 + SE_ERR_ACCESSDENIED = 5 + SE_ERR_OOM = 8 + SE_ERR_DLLNOTFOUND = 32 + SE_ERR_SHARE = 26 + SE_ERR_ASSOCINCOMPLETE = 27 + SE_ERR_DDETIMEOUT = 28 + SE_ERR_DDEFAIL = 29 + SE_ERR_DDEBUSY = 30 + SE_ERR_NOASSOC = 31 +) + +const ( + CW_USEDEFAULT = ^0x7fffffff +) + +const ( + IMAGE_BITMAP = 0 + IMAGE_ICON = 1 + IMAGE_CURSOR = 2 + IMAGE_ENHMETAFILE = 3 +) + +// ShowWindow constants +const ( + SW_HIDE = 0 + SW_NORMAL = 1 + SW_SHOWNORMAL = 1 + SW_SHOWMINIMIZED = 2 + SW_MAXIMIZE = 3 + SW_SHOWMAXIMIZED = 3 + SW_SHOWNOACTIVATE = 4 + SW_SHOW = 5 + SW_MINIMIZE = 6 + SW_SHOWMINNOACTIVE = 7 + SW_SHOWNA = 8 + SW_RESTORE = 9 + SW_SHOWDEFAULT = 10 + SW_FORCEMINIMIZE = 11 +) + +// Window class styles +const ( + CS_VREDRAW = 0x00000001 + CS_HREDRAW = 0x00000002 + CS_KEYCVTWINDOW = 0x00000004 + CS_DBLCLKS = 0x00000008 + CS_OWNDC = 0x00000020 + CS_CLASSDC = 0x00000040 + CS_PARENTDC = 0x00000080 + CS_NOKEYCVT = 0x00000100 + CS_NOCLOSE = 0x00000200 + CS_SAVEBITS = 0x00000800 + CS_BYTEALIGNCLIENT = 0x00001000 + CS_BYTEALIGNWINDOW = 0x00002000 + CS_GLOBALCLASS = 0x00004000 + CS_IME = 0x00010000 + CS_DROPSHADOW = 0x00020000 +) + +// Predefined cursor constants +const ( + IDC_ARROW = 32512 + IDC_IBEAM = 32513 + IDC_WAIT = 32514 + IDC_CROSS = 32515 + IDC_UPARROW = 32516 + IDC_SIZENWSE = 32642 + IDC_SIZENESW = 32643 + IDC_SIZEWE = 32644 + IDC_SIZENS = 32645 + IDC_SIZEALL = 32646 + IDC_NO = 32648 + IDC_HAND = 32649 + IDC_APPSTARTING = 32650 + IDC_HELP = 32651 + IDC_ICON = 32641 + IDC_SIZE = 32640 +) + +// Predefined icon constants +const ( + IDI_APPLICATION = 32512 + IDI_HAND = 32513 + IDI_QUESTION = 32514 + IDI_EXCLAMATION = 32515 + IDI_ASTERISK = 32516 + IDI_WINLOGO = 32517 + IDI_WARNING = IDI_EXCLAMATION + IDI_ERROR = IDI_HAND + IDI_INFORMATION = IDI_ASTERISK +) + +// Button style constants +const ( + BS_3STATE = 5 + BS_AUTO3STATE = 6 + BS_AUTOCHECKBOX = 3 + BS_AUTORADIOBUTTON = 9 + BS_BITMAP = 128 + BS_BOTTOM = 0x800 + BS_CENTER = 0x300 + BS_CHECKBOX = 2 + BS_DEFPUSHBUTTON = 1 + BS_GROUPBOX = 7 + BS_ICON = 64 + BS_LEFT = 256 + BS_LEFTTEXT = 32 + BS_MULTILINE = 0x2000 + BS_NOTIFY = 0x4000 + BS_OWNERDRAW = 0xB + BS_PUSHBUTTON = 0 + BS_PUSHLIKE = 4096 + BS_RADIOBUTTON = 4 + BS_RIGHT = 512 + BS_RIGHTBUTTON = 32 + BS_TEXT = 0 + BS_TOP = 0x400 + BS_USERBUTTON = 8 + BS_VCENTER = 0xC00 + BS_FLAT = 0x8000 + BS_SPLITBUTTON = 0x000C // >= Vista + BS_DEFSPLITBUTTON = 0x000D // >= Vista +) + +// Button state constants +const ( + BST_CHECKED = 1 + BST_INDETERMINATE = 2 + BST_UNCHECKED = 0 + BST_FOCUS = 8 + BST_PUSHED = 4 +) + +// Predefined brushes constants +const ( + COLOR_3DDKSHADOW = 21 + COLOR_3DFACE = 15 + COLOR_3DHILIGHT = 20 + COLOR_3DHIGHLIGHT = 20 + COLOR_3DLIGHT = 22 + COLOR_BTNHILIGHT = 20 + COLOR_3DSHADOW = 16 + COLOR_ACTIVEBORDER = 10 + COLOR_ACTIVECAPTION = 2 + COLOR_APPWORKSPACE = 12 + COLOR_BACKGROUND = 1 + COLOR_DESKTOP = 1 + COLOR_BTNFACE = 15 + COLOR_BTNHIGHLIGHT = 20 + COLOR_BTNSHADOW = 16 + COLOR_BTNTEXT = 18 + COLOR_CAPTIONTEXT = 9 + COLOR_GRAYTEXT = 17 + COLOR_HIGHLIGHT = 13 + COLOR_HIGHLIGHTTEXT = 14 + COLOR_INACTIVEBORDER = 11 + COLOR_INACTIVECAPTION = 3 + COLOR_INACTIVECAPTIONTEXT = 19 + COLOR_INFOBK = 24 + COLOR_INFOTEXT = 23 + COLOR_MENU = 4 + COLOR_MENUTEXT = 7 + COLOR_SCROLLBAR = 0 + COLOR_WINDOW = 5 + COLOR_WINDOWFRAME = 6 + COLOR_WINDOWTEXT = 8 + COLOR_HOTLIGHT = 26 + COLOR_GRADIENTACTIVECAPTION = 27 + COLOR_GRADIENTINACTIVECAPTION = 28 +) + +// Button message constants +const ( + BM_CLICK = 245 + BM_GETCHECK = 240 + BM_GETIMAGE = 246 + BM_GETSTATE = 242 + BM_SETCHECK = 241 + BM_SETIMAGE = 247 + BM_SETSTATE = 243 + BM_SETSTYLE = 244 +) + +// Button notifications +const ( + BN_CLICKED = 0 + BN_PAINT = 1 + BN_HILITE = 2 + BN_PUSHED = BN_HILITE + BN_UNHILITE = 3 + BN_UNPUSHED = BN_UNHILITE + BN_DISABLE = 4 + BN_DOUBLECLICKED = 5 + BN_DBLCLK = BN_DOUBLECLICKED + BN_SETFOCUS = 6 + BN_KILLFOCUS = 7 +) + +// TrackPopupMenu[Ex] flags +const ( + TPM_CENTERALIGN = 0x0004 + TPM_LEFTALIGN = 0x0000 + TPM_RIGHTALIGN = 0x0008 + TPM_BOTTOMALIGN = 0x0020 + TPM_TOPALIGN = 0x0000 + TPM_VCENTERALIGN = 0x0010 + TPM_NONOTIFY = 0x0080 + TPM_RETURNCMD = 0x0100 + TPM_LEFTBUTTON = 0x0000 + TPM_RIGHTBUTTON = 0x0002 + TPM_HORNEGANIMATION = 0x0800 + TPM_HORPOSANIMATION = 0x0400 + TPM_NOANIMATION = 0x4000 + TPM_VERNEGANIMATION = 0x2000 + TPM_VERPOSANIMATION = 0x1000 + TPM_HORIZONTAL = 0x0000 + TPM_VERTICAL = 0x0040 +) + +// GetWindowLong and GetWindowLongPtr constants +const ( + GWL_EXSTYLE = -20 + GWL_STYLE = -16 + GWL_WNDPROC = -4 + GWLP_WNDPROC = -4 + GWL_HINSTANCE = -6 + GWLP_HINSTANCE = -6 + GWL_HWNDPARENT = -8 + GWLP_HWNDPARENT = -8 + GWL_ID = -12 + GWLP_ID = -12 + GWL_USERDATA = -21 + GWLP_USERDATA = -21 +) + +// Window style constants +const ( + WS_OVERLAPPED = 0x00000000 + WS_POPUP = 0x80000000 + WS_CHILD = 0x40000000 + WS_MINIMIZE = 0x20000000 + WS_VISIBLE = 0x10000000 + WS_DISABLED = 0x08000000 + WS_CLIPSIBLINGS = 0x04000000 + WS_CLIPCHILDREN = 0x02000000 + WS_MAXIMIZE = 0x01000000 + WS_CAPTION = 0x00C00000 + WS_BORDER = 0x00800000 + WS_DLGFRAME = 0x00400000 + WS_VSCROLL = 0x00200000 + WS_HSCROLL = 0x00100000 + WS_SYSMENU = 0x00080000 + WS_THICKFRAME = 0x00040000 + WS_GROUP = 0x00020000 + WS_TABSTOP = 0x00010000 + WS_MINIMIZEBOX = 0x00020000 + WS_MAXIMIZEBOX = 0x00010000 + WS_TILED = 0x00000000 + WS_ICONIC = 0x20000000 + WS_SIZEBOX = 0x00040000 + WS_OVERLAPPEDWINDOW = 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000 | 0x00020000 | 0x00010000 + WS_POPUPWINDOW = 0x80000000 | 0x00800000 | 0x00080000 + WS_CHILDWINDOW = 0x40000000 +) + +// Extended window style constants +const ( + WS_EX_DLGMODALFRAME = 0x00000001 + WS_EX_NOPARENTNOTIFY = 0x00000004 + WS_EX_TOPMOST = 0x00000008 + WS_EX_ACCEPTFILES = 0x00000010 + WS_EX_TRANSPARENT = 0x00000020 + WS_EX_MDICHILD = 0x00000040 + WS_EX_TOOLWINDOW = 0x00000080 + WS_EX_WINDOWEDGE = 0x00000100 + WS_EX_CLIENTEDGE = 0x00000200 + WS_EX_CONTEXTHELP = 0x00000400 + WS_EX_RIGHT = 0x00001000 + WS_EX_LEFT = 0x00000000 + WS_EX_RTLREADING = 0x00002000 + WS_EX_LTRREADING = 0x00000000 + WS_EX_LEFTSCROLLBAR = 0x00004000 + WS_EX_RIGHTSCROLLBAR = 0x00000000 + WS_EX_CONTROLPARENT = 0x00010000 + WS_EX_STATICEDGE = 0x00020000 + WS_EX_APPWINDOW = 0x00040000 + WS_EX_OVERLAPPEDWINDOW = 0x00000100 | 0x00000200 + WS_EX_PALETTEWINDOW = 0x00000100 | 0x00000080 | 0x00000008 + WS_EX_LAYERED = 0x00080000 + WS_EX_NOINHERITLAYOUT = 0x00100000 + WS_EX_NOREDIRECTIONBITMAP = 0x00200000 + WS_EX_LAYOUTRTL = 0x00400000 + WS_EX_NOACTIVATE = 0x08000000 +) + +// Window message constants +const ( + WM_APP = 32768 + WM_ACTIVATE = 6 + WM_ACTIVATEAPP = 28 + WM_AFXFIRST = 864 + WM_AFXLAST = 895 + WM_ASKCBFORMATNAME = 780 + WM_CANCELJOURNAL = 75 + WM_CANCELMODE = 31 + WM_CAPTURECHANGED = 533 + WM_CHANGECBCHAIN = 781 + WM_CHAR = 258 + WM_CHARTOITEM = 47 + WM_CHILDACTIVATE = 34 + WM_CLEAR = 771 + WM_CLOSE = 16 + WM_COMMAND = 273 + WM_COMMNOTIFY = 68 /* OBSOLETE */ + WM_COMPACTING = 65 + WM_COMPAREITEM = 57 + WM_CONTEXTMENU = 123 + WM_COPY = 769 + WM_COPYDATA = 74 + WM_CREATE = 1 + WM_CTLCOLORBTN = 309 + WM_CTLCOLORDLG = 310 + WM_CTLCOLOREDIT = 307 + WM_CTLCOLORLISTBOX = 308 + WM_CTLCOLORMSGBOX = 306 + WM_CTLCOLORSCROLLBAR = 311 + WM_CTLCOLORSTATIC = 312 + WM_CUT = 768 + WM_DEADCHAR = 259 + WM_DELETEITEM = 45 + WM_DESTROY = 2 + WM_DESTROYCLIPBOARD = 775 + WM_DEVICECHANGE = 537 + WM_DEVMODECHANGE = 27 + WM_DISPLAYCHANGE = 126 + WM_DRAWCLIPBOARD = 776 + WM_DRAWITEM = 43 + WM_DROPFILES = 563 + WM_ENABLE = 10 + WM_ENDSESSION = 22 + WM_ENTERIDLE = 289 + WM_ENTERMENULOOP = 529 + WM_ENTERSIZEMOVE = 561 + WM_ERASEBKGND = 20 + WM_EXITMENULOOP = 530 + WM_EXITSIZEMOVE = 562 + WM_FONTCHANGE = 29 + WM_GETDLGCODE = 135 + WM_GETFONT = 49 + WM_GETHOTKEY = 51 + WM_GETICON = 127 + WM_GETMINMAXINFO = 36 + WM_GETTEXT = 13 + WM_GETTEXTLENGTH = 14 + WM_HANDHELDFIRST = 856 + WM_HANDHELDLAST = 863 + WM_HELP = 83 + WM_HOTKEY = 786 + WM_HSCROLL = 276 + WM_HSCROLLCLIPBOARD = 782 + WM_ICONERASEBKGND = 39 + WM_INITDIALOG = 272 + WM_INITMENU = 278 + WM_INITMENUPOPUP = 279 + WM_INPUT = 0x00FF + WM_INPUTLANGCHANGE = 81 + WM_INPUTLANGCHANGEREQUEST = 80 + WM_KEYDOWN = 256 + WM_KEYUP = 257 + WM_KILLFOCUS = 8 + WM_MDIACTIVATE = 546 + WM_MDICASCADE = 551 + WM_MDICREATE = 544 + WM_MDIDESTROY = 545 + WM_MDIGETACTIVE = 553 + WM_MDIICONARRANGE = 552 + WM_MDIMAXIMIZE = 549 + WM_MDINEXT = 548 + WM_MDIREFRESHMENU = 564 + WM_MDIRESTORE = 547 + WM_MDISETMENU = 560 + WM_MDITILE = 550 + WM_MEASUREITEM = 44 + WM_GETOBJECT = 0x003D + WM_CHANGEUISTATE = 0x0127 + WM_UPDATEUISTATE = 0x0128 + WM_QUERYUISTATE = 0x0129 + WM_UNINITMENUPOPUP = 0x0125 + WM_MENURBUTTONUP = 290 + WM_MENUCOMMAND = 0x0126 + WM_MENUGETOBJECT = 0x0124 + WM_MENUDRAG = 0x0123 + WM_APPCOMMAND = 0x0319 + WM_MENUCHAR = 288 + WM_MENUSELECT = 287 + WM_MOVE = 3 + WM_MOVING = 534 + WM_NCACTIVATE = 134 + WM_NCCALCSIZE = 131 + WM_NCCREATE = 129 + WM_NCDESTROY = 130 + WM_NCHITTEST = 132 + WM_NCLBUTTONDBLCLK = 163 + WM_NCLBUTTONDOWN = 161 + WM_NCLBUTTONUP = 162 + WM_NCMBUTTONDBLCLK = 169 + WM_NCMBUTTONDOWN = 167 + WM_NCMBUTTONUP = 168 + WM_NCXBUTTONDOWN = 171 + WM_NCXBUTTONUP = 172 + WM_NCXBUTTONDBLCLK = 173 + WM_NCMOUSEHOVER = 0x02A0 + WM_NCMOUSELEAVE = 0x02A2 + WM_NCMOUSEMOVE = 160 + WM_NCPAINT = 133 + WM_NCRBUTTONDBLCLK = 166 + WM_NCRBUTTONDOWN = 164 + WM_NCRBUTTONUP = 165 + WM_NEXTDLGCTL = 40 + WM_NEXTMENU = 531 + WM_NOTIFY = 78 + WM_NOTIFYFORMAT = 85 + WM_NULL = 0 + WM_PAINT = 15 + WM_PAINTCLIPBOARD = 777 + WM_PAINTICON = 38 + WM_PALETTECHANGED = 785 + WM_PALETTEISCHANGING = 784 + WM_PARENTNOTIFY = 528 + WM_PASTE = 770 + WM_PENWINFIRST = 896 + WM_PENWINLAST = 911 + WM_POWER = 72 + WM_POWERBROADCAST = 536 + WM_PRINT = 791 + WM_PRINTCLIENT = 792 + WM_QUERYDRAGICON = 55 + WM_QUERYENDSESSION = 17 + WM_QUERYNEWPALETTE = 783 + WM_QUERYOPEN = 19 + WM_QUEUESYNC = 35 + WM_QUIT = 18 + WM_RENDERALLFORMATS = 774 + WM_RENDERFORMAT = 773 + WM_SETCURSOR = 32 + WM_SETFOCUS = 7 + WM_SETFONT = 48 + WM_SETHOTKEY = 50 + WM_SETICON = 128 + WM_SETREDRAW = 11 + WM_SETTEXT = 12 + WM_SETTINGCHANGE = 26 + WM_SHOWWINDOW = 24 + WM_SIZE = 5 + WM_SIZECLIPBOARD = 779 + WM_SIZING = 532 + WM_SPOOLERSTATUS = 42 + WM_STYLECHANGED = 125 + WM_STYLECHANGING = 124 + WM_SYSCHAR = 262 + WM_SYSCOLORCHANGE = 21 + WM_SYSCOMMAND = 274 + WM_SYSDEADCHAR = 263 + WM_SYSKEYDOWN = 260 + WM_SYSKEYUP = 261 + WM_TCARD = 82 + WM_THEMECHANGED = 794 + WM_TIMECHANGE = 30 + WM_TIMER = 275 + WM_UNDO = 772 + WM_USER = 1024 + WM_USERCHANGED = 84 + WM_VKEYTOITEM = 46 + WM_VSCROLL = 277 + WM_VSCROLLCLIPBOARD = 778 + WM_WINDOWPOSCHANGED = 71 + WM_WINDOWPOSCHANGING = 70 + WM_WININICHANGE = 26 + WM_KEYFIRST = 256 + WM_KEYLAST = 264 + WM_SYNCPAINT = 136 + WM_MOUSEACTIVATE = 33 + WM_MOUSEMOVE = 512 + WM_LBUTTONDOWN = 513 + WM_LBUTTONUP = 514 + WM_LBUTTONDBLCLK = 515 + WM_RBUTTONDOWN = 516 + WM_RBUTTONUP = 517 + WM_RBUTTONDBLCLK = 518 + WM_MBUTTONDOWN = 519 + WM_MBUTTONUP = 520 + WM_MBUTTONDBLCLK = 521 + WM_MOUSEWHEEL = 522 + WM_MOUSEFIRST = 512 + WM_XBUTTONDOWN = 523 + WM_XBUTTONUP = 524 + WM_XBUTTONDBLCLK = 525 + WM_MOUSELAST = 525 + WM_MOUSEHOVER = 0x2A1 + WM_MOUSELEAVE = 0x2A3 + WM_CLIPBOARDUPDATE = 0x031D +) + +// WM_ACTIVATE +const ( + WA_INACTIVE = 0 + WA_ACTIVE = 1 + WA_CLICKACTIVE = 2 +) + +const LF_FACESIZE = 32 + +// Font weight constants +const ( + FW_DONTCARE = 0 + FW_THIN = 100 + FW_EXTRALIGHT = 200 + FW_ULTRALIGHT = FW_EXTRALIGHT + FW_LIGHT = 300 + FW_NORMAL = 400 + FW_REGULAR = 400 + FW_MEDIUM = 500 + FW_SEMIBOLD = 600 + FW_DEMIBOLD = FW_SEMIBOLD + FW_BOLD = 700 + FW_EXTRABOLD = 800 + FW_ULTRABOLD = FW_EXTRABOLD + FW_HEAVY = 900 + FW_BLACK = FW_HEAVY +) + +// Charset constants +const ( + ANSI_CHARSET = 0 + DEFAULT_CHARSET = 1 + SYMBOL_CHARSET = 2 + SHIFTJIS_CHARSET = 128 + HANGEUL_CHARSET = 129 + HANGUL_CHARSET = 129 + GB2312_CHARSET = 134 + CHINESEBIG5_CHARSET = 136 + GREEK_CHARSET = 161 + TURKISH_CHARSET = 162 + HEBREW_CHARSET = 177 + ARABIC_CHARSET = 178 + BALTIC_CHARSET = 186 + RUSSIAN_CHARSET = 204 + THAI_CHARSET = 222 + EASTEUROPE_CHARSET = 238 + OEM_CHARSET = 255 + JOHAB_CHARSET = 130 + VIETNAMESE_CHARSET = 163 + MAC_CHARSET = 77 +) + +// Font output precision constants +const ( + OUT_DEFAULT_PRECIS = 0 + OUT_STRING_PRECIS = 1 + OUT_CHARACTER_PRECIS = 2 + OUT_STROKE_PRECIS = 3 + OUT_TT_PRECIS = 4 + OUT_DEVICE_PRECIS = 5 + OUT_RASTER_PRECIS = 6 + OUT_TT_ONLY_PRECIS = 7 + OUT_OUTLINE_PRECIS = 8 + OUT_PS_ONLY_PRECIS = 10 +) + +// Font clipping precision constants +const ( + CLIP_DEFAULT_PRECIS = 0 + CLIP_CHARACTER_PRECIS = 1 + CLIP_STROKE_PRECIS = 2 + CLIP_MASK = 15 + CLIP_LH_ANGLES = 16 + CLIP_TT_ALWAYS = 32 + CLIP_EMBEDDED = 128 +) + +// Font output quality constants +const ( + DEFAULT_QUALITY = 0 + DRAFT_QUALITY = 1 + PROOF_QUALITY = 2 + NONANTIALIASED_QUALITY = 3 + ANTIALIASED_QUALITY = 4 + CLEARTYPE_QUALITY = 5 +) + +// Font pitch constants +const ( + DEFAULT_PITCH = 0 + FIXED_PITCH = 1 + VARIABLE_PITCH = 2 +) + +// Font family constants +const ( + FF_DECORATIVE = 80 + FF_DONTCARE = 0 + FF_MODERN = 48 + FF_ROMAN = 16 + FF_SCRIPT = 64 + FF_SWISS = 32 +) + +// DeviceCapabilities capabilities +const ( + DC_FIELDS = 1 + DC_PAPERS = 2 + DC_PAPERSIZE = 3 + DC_MINEXTENT = 4 + DC_MAXEXTENT = 5 + DC_BINS = 6 + DC_DUPLEX = 7 + DC_SIZE = 8 + DC_EXTRA = 9 + DC_VERSION = 10 + DC_DRIVER = 11 + DC_BINNAMES = 12 + DC_ENUMRESOLUTIONS = 13 + DC_FILEDEPENDENCIES = 14 + DC_TRUETYPE = 15 + DC_PAPERNAMES = 16 + DC_ORIENTATION = 17 + DC_COPIES = 18 + DC_BINADJUST = 19 + DC_EMF_COMPLIANT = 20 + DC_DATATYPE_PRODUCED = 21 + DC_COLLATE = 22 + DC_MANUFACTURER = 23 + DC_MODEL = 24 + DC_PERSONALITY = 25 + DC_PRINTRATE = 26 + DC_PRINTRATEUNIT = 27 + DC_PRINTERMEM = 28 + DC_MEDIAREADY = 29 + DC_STAPLE = 30 + DC_PRINTRATEPPM = 31 + DC_COLORDEVICE = 32 + DC_NUP = 33 + DC_MEDIATYPENAMES = 34 + DC_MEDIATYPES = 35 +) + +// GetDeviceCaps index constants +const ( + DRIVERVERSION = 0 + TECHNOLOGY = 2 + HORZSIZE = 4 + VERTSIZE = 6 + HORZRES = 8 + VERTRES = 10 + LOGPIXELSX = 88 + LOGPIXELSY = 90 + BITSPIXEL = 12 + PLANES = 14 + NUMBRUSHES = 16 + NUMPENS = 18 + NUMFONTS = 22 + NUMCOLORS = 24 + NUMMARKERS = 20 + ASPECTX = 40 + ASPECTY = 42 + ASPECTXY = 44 + PDEVICESIZE = 26 + CLIPCAPS = 36 + SIZEPALETTE = 104 + NUMRESERVED = 106 + COLORRES = 108 + PHYSICALWIDTH = 110 + PHYSICALHEIGHT = 111 + PHYSICALOFFSETX = 112 + PHYSICALOFFSETY = 113 + SCALINGFACTORX = 114 + SCALINGFACTORY = 115 + VREFRESH = 116 + DESKTOPHORZRES = 118 + DESKTOPVERTRES = 117 + BLTALIGNMENT = 119 + SHADEBLENDCAPS = 120 + COLORMGMTCAPS = 121 + RASTERCAPS = 38 + CURVECAPS = 28 + LINECAPS = 30 + POLYGONALCAPS = 32 + TEXTCAPS = 34 +) + +// GetDeviceCaps TECHNOLOGY constants +const ( + DT_PLOTTER = 0 + DT_RASDISPLAY = 1 + DT_RASPRINTER = 2 + DT_RASCAMERA = 3 + DT_CHARSTREAM = 4 + DT_METAFILE = 5 + DT_DISPFILE = 6 +) + +// GetDeviceCaps SHADEBLENDCAPS constants +const ( + SB_NONE = 0x00 + SB_CONST_ALPHA = 0x01 + SB_PIXEL_ALPHA = 0x02 + SB_PREMULT_ALPHA = 0x04 + SB_GRAD_RECT = 0x10 + SB_GRAD_TRI = 0x20 +) + +// GetDeviceCaps COLORMGMTCAPS constants +const ( + CM_NONE = 0x00 + CM_DEVICE_ICM = 0x01 + CM_GAMMA_RAMP = 0x02 + CM_CMYK_COLOR = 0x04 +) + +// GetDeviceCaps RASTERCAPS constants +const ( + RC_BANDING = 2 + RC_BITBLT = 1 + RC_BITMAP64 = 8 + RC_DI_BITMAP = 128 + RC_DIBTODEV = 512 + RC_FLOODFILL = 4096 + RC_GDI20_OUTPUT = 16 + RC_PALETTE = 256 + RC_SCALING = 4 + RC_STRETCHBLT = 2048 + RC_STRETCHDIB = 8192 + RC_DEVBITS = 0x8000 + RC_OP_DX_OUTPUT = 0x4000 +) + +// GetDeviceCaps CURVECAPS constants +const ( + CC_NONE = 0 + CC_CIRCLES = 1 + CC_PIE = 2 + CC_CHORD = 4 + CC_ELLIPSES = 8 + CC_WIDE = 16 + CC_STYLED = 32 + CC_WIDESTYLED = 64 + CC_INTERIORS = 128 + CC_ROUNDRECT = 256 +) + +// GetDeviceCaps LINECAPS constants +const ( + LC_NONE = 0 + LC_POLYLINE = 2 + LC_MARKER = 4 + LC_POLYMARKER = 8 + LC_WIDE = 16 + LC_STYLED = 32 + LC_WIDESTYLED = 64 + LC_INTERIORS = 128 +) + +// GetDeviceCaps POLYGONALCAPS constants +const ( + PC_NONE = 0 + PC_POLYGON = 1 + PC_POLYPOLYGON = 256 + PC_PATHS = 512 + PC_RECTANGLE = 2 + PC_WINDPOLYGON = 4 + PC_SCANLINE = 8 + PC_TRAPEZOID = 4 + PC_WIDE = 16 + PC_STYLED = 32 + PC_WIDESTYLED = 64 + PC_INTERIORS = 128 +) + +// GetDeviceCaps TEXTCAPS constants +const ( + TC_OP_CHARACTER = 1 + TC_OP_STROKE = 2 + TC_CP_STROKE = 4 + TC_CR_90 = 8 + TC_CR_ANY = 16 + TC_SF_X_YINDEP = 32 + TC_SA_DOUBLE = 64 + TC_SA_INTEGER = 128 + TC_SA_CONTIN = 256 + TC_EA_DOUBLE = 512 + TC_IA_ABLE = 1024 + TC_UA_ABLE = 2048 + TC_SO_ABLE = 4096 + TC_RA_ABLE = 8192 + TC_VA_ABLE = 16384 + TC_RESERVED = 32768 + TC_SCROLLBLT = 65536 +) + +// Static control styles +const ( + SS_BITMAP = 14 + SS_BLACKFRAME = 7 + SS_BLACKRECT = 4 + SS_CENTER = 1 + SS_CENTERIMAGE = 512 + SS_EDITCONTROL = 0x2000 + SS_ENHMETAFILE = 15 + SS_ETCHEDFRAME = 18 + SS_ETCHEDHORZ = 16 + SS_ETCHEDVERT = 17 + SS_GRAYFRAME = 8 + SS_GRAYRECT = 5 + SS_ICON = 3 + SS_LEFT = 0 + SS_LEFTNOWORDWRAP = 0xc + SS_NOPREFIX = 128 + SS_NOTIFY = 256 + SS_OWNERDRAW = 0xd + SS_REALSIZECONTROL = 0x040 + SS_REALSIZEIMAGE = 0x800 + SS_RIGHT = 2 + SS_RIGHTJUST = 0x400 + SS_SIMPLE = 11 + SS_SUNKEN = 4096 + SS_WHITEFRAME = 9 + SS_WHITERECT = 6 + SS_USERITEM = 10 + SS_TYPEMASK = 0x0000001F + SS_ENDELLIPSIS = 0x00004000 + SS_PATHELLIPSIS = 0x00008000 + SS_WORDELLIPSIS = 0x0000C000 + SS_ELLIPSISMASK = 0x0000C000 +) + +// Edit styles +const ( + ES_LEFT = 0x0000 + ES_CENTER = 0x0001 + ES_RIGHT = 0x0002 + ES_MULTILINE = 0x0004 + ES_UPPERCASE = 0x0008 + ES_LOWERCASE = 0x0010 + ES_PASSWORD = 0x0020 + ES_AUTOVSCROLL = 0x0040 + ES_AUTOHSCROLL = 0x0080 + ES_NOHIDESEL = 0x0100 + ES_OEMCONVERT = 0x0400 + ES_READONLY = 0x0800 + ES_WANTRETURN = 0x1000 + ES_NUMBER = 0x2000 +) + +// Edit notifications +const ( + EN_SETFOCUS = 0x0100 + EN_KILLFOCUS = 0x0200 + EN_CHANGE = 0x0300 + EN_UPDATE = 0x0400 + EN_ERRSPACE = 0x0500 + EN_MAXTEXT = 0x0501 + EN_HSCROLL = 0x0601 + EN_VSCROLL = 0x0602 + EN_ALIGN_LTR_EC = 0x0700 + EN_ALIGN_RTL_EC = 0x0701 +) + +// Edit messages +const ( + EM_GETSEL = 0x00B0 + EM_SETSEL = 0x00B1 + EM_GETRECT = 0x00B2 + EM_SETRECT = 0x00B3 + EM_SETRECTNP = 0x00B4 + EM_SCROLL = 0x00B5 + EM_LINESCROLL = 0x00B6 + EM_SCROLLCARET = 0x00B7 + EM_GETMODIFY = 0x00B8 + EM_SETMODIFY = 0x00B9 + EM_GETLINECOUNT = 0x00BA + EM_LINEINDEX = 0x00BB + EM_SETHANDLE = 0x00BC + EM_GETHANDLE = 0x00BD + EM_GETTHUMB = 0x00BE + EM_LINELENGTH = 0x00C1 + EM_REPLACESEL = 0x00C2 + EM_GETLINE = 0x00C4 + EM_LIMITTEXT = 0x00C5 + EM_CANUNDO = 0x00C6 + EM_UNDO = 0x00C7 + EM_FMTLINES = 0x00C8 + EM_LINEFROMCHAR = 0x00C9 + EM_SETTABSTOPS = 0x00CB + EM_SETPASSWORDCHAR = 0x00CC + EM_EMPTYUNDOBUFFER = 0x00CD + EM_GETFIRSTVISIBLELINE = 0x00CE + EM_SETREADONLY = 0x00CF + EM_SETWORDBREAKPROC = 0x00D0 + EM_GETWORDBREAKPROC = 0x00D1 + EM_GETPASSWORDCHAR = 0x00D2 + EM_SETMARGINS = 0x00D3 + EM_GETMARGINS = 0x00D4 + EM_SETLIMITTEXT = EM_LIMITTEXT + EM_GETLIMITTEXT = 0x00D5 + EM_POSFROMCHAR = 0x00D6 + EM_CHARFROMPOS = 0x00D7 + EM_SETIMESTATUS = 0x00D8 + EM_GETIMESTATUS = 0x00D9 + EM_SETCUEBANNER = 0x1501 + EM_GETCUEBANNER = 0x1502 +) + +const ( + CCM_FIRST = 0x2000 + CCM_LAST = CCM_FIRST + 0x200 + CCM_SETBKCOLOR = 8193 + CCM_SETCOLORSCHEME = 8194 + CCM_GETCOLORSCHEME = 8195 + CCM_GETDROPTARGET = 8196 + CCM_SETUNICODEFORMAT = 8197 + CCM_GETUNICODEFORMAT = 8198 + CCM_SETVERSION = 0x2007 + CCM_GETVERSION = 0x2008 + CCM_SETNOTIFYWINDOW = 0x2009 + CCM_SETWINDOWTHEME = 0x200b + CCM_DPISCALE = 0x200c +) + +// Common controls styles +const ( + CCS_TOP = 1 + CCS_NOMOVEY = 2 + CCS_BOTTOM = 3 + CCS_NORESIZE = 4 + CCS_NOPARENTALIGN = 8 + CCS_ADJUSTABLE = 32 + CCS_NODIVIDER = 64 + CCS_VERT = 128 + CCS_LEFT = 129 + CCS_NOMOVEX = 130 + CCS_RIGHT = 131 +) + +// ProgressBar messages +const ( + PROGRESS_CLASS = "msctls_progress32" + PBM_SETPOS = WM_USER + 2 + PBM_DELTAPOS = WM_USER + 3 + PBM_SETSTEP = WM_USER + 4 + PBM_STEPIT = WM_USER + 5 + PBM_SETRANGE32 = 1030 + PBM_GETRANGE = 1031 + PBM_GETPOS = 1032 + PBM_SETBARCOLOR = 1033 + PBM_SETBKCOLOR = CCM_SETBKCOLOR + PBS_SMOOTH = 1 + PBS_VERTICAL = 4 +) + +// Trackbar messages and constants +const ( + TBS_AUTOTICKS = 1 + TBS_VERT = 2 + TBS_HORZ = 0 + TBS_TOP = 4 + TBS_BOTTOM = 0 + TBS_LEFT = 4 + TBS_RIGHT = 0 + TBS_BOTH = 8 + TBS_NOTICKS = 16 + TBS_ENABLESELRANGE = 32 + TBS_FIXEDLENGTH = 64 + TBS_NOTHUMB = 128 + TBS_TOOLTIPS = 0x0100 +) + +const ( + TBM_GETPOS = (WM_USER) + TBM_GETRANGEMIN = (WM_USER + 1) + TBM_GETRANGEMAX = (WM_USER + 2) + TBM_GETTIC = (WM_USER + 3) + TBM_SETTIC = (WM_USER + 4) + TBM_SETPOS = (WM_USER + 5) + TBM_SETRANGE = (WM_USER + 6) + TBM_SETRANGEMIN = (WM_USER + 7) + TBM_SETRANGEMAX = (WM_USER + 8) + TBM_CLEARTICS = (WM_USER + 9) + TBM_SETSEL = (WM_USER + 10) + TBM_SETSELSTART = (WM_USER + 11) + TBM_SETSELEND = (WM_USER + 12) + TBM_GETPTICS = (WM_USER + 14) + TBM_GETTICPOS = (WM_USER + 15) + TBM_GETNUMTICS = (WM_USER + 16) + TBM_GETSELSTART = (WM_USER + 17) + TBM_GETSELEND = (WM_USER + 18) + TBM_CLEARSEL = (WM_USER + 19) + TBM_SETTICFREQ = (WM_USER + 20) + TBM_SETPAGESIZE = (WM_USER + 21) + TBM_GETPAGESIZE = (WM_USER + 22) + TBM_SETLINESIZE = (WM_USER + 23) + TBM_GETLINESIZE = (WM_USER + 24) + TBM_GETTHUMBRECT = (WM_USER + 25) + TBM_GETCHANNELRECT = (WM_USER + 26) + TBM_SETTHUMBLENGTH = (WM_USER + 27) + TBM_GETTHUMBLENGTH = (WM_USER + 28) + TBM_SETTOOLTIPS = (WM_USER + 29) + TBM_GETTOOLTIPS = (WM_USER + 30) + TBM_SETTIPSIDE = (WM_USER + 31) + TBM_SETBUDDY = (WM_USER + 32) + TBM_GETBUDDY = (WM_USER + 33) +) + +const ( + TB_LINEUP = 0 + TB_LINEDOWN = 1 + TB_PAGEUP = 2 + TB_PAGEDOWN = 3 + TB_THUMBPOSITION = 4 + TB_THUMBTRACK = 5 + TB_TOP = 6 + TB_BOTTOM = 7 + TB_ENDTRACK = 8 +) + +// GetOpenFileName and GetSaveFileName extended flags +const ( + OFN_EX_NOPLACESBAR = 0x00000001 +) + +// GetOpenFileName and GetSaveFileName flags +const ( + OFN_ALLOWMULTISELECT = 0x00000200 + OFN_CREATEPROMPT = 0x00002000 + OFN_DONTADDTORECENT = 0x02000000 + OFN_ENABLEHOOK = 0x00000020 + OFN_ENABLEINCLUDENOTIFY = 0x00400000 + OFN_ENABLESIZING = 0x00800000 + OFN_ENABLETEMPLATE = 0x00000040 + OFN_ENABLETEMPLATEHANDLE = 0x00000080 + OFN_EXPLORER = 0x00080000 + OFN_EXTENSIONDIFFERENT = 0x00000400 + OFN_FILEMUSTEXIST = 0x00001000 + OFN_FORCESHOWHIDDEN = 0x10000000 + OFN_HIDEREADONLY = 0x00000004 + OFN_LONGNAMES = 0x00200000 + OFN_NOCHANGEDIR = 0x00000008 + OFN_NODEREFERENCELINKS = 0x00100000 + OFN_NOLONGNAMES = 0x00040000 + OFN_NONETWORKBUTTON = 0x00020000 + OFN_NOREADONLYRETURN = 0x00008000 + OFN_NOTESTFILECREATE = 0x00010000 + OFN_NOVALIDATE = 0x00000100 + OFN_OVERWRITEPROMPT = 0x00000002 + OFN_PATHMUSTEXIST = 0x00000800 + OFN_READONLY = 0x00000001 + OFN_SHAREAWARE = 0x00004000 + OFN_SHOWHELP = 0x00000010 +) + +//SHBrowseForFolder flags +const ( + BIF_RETURNONLYFSDIRS = 0x00000001 + BIF_DONTGOBELOWDOMAIN = 0x00000002 + BIF_STATUSTEXT = 0x00000004 + BIF_RETURNFSANCESTORS = 0x00000008 + BIF_EDITBOX = 0x00000010 + BIF_VALIDATE = 0x00000020 + BIF_NEWDIALOGSTYLE = 0x00000040 + BIF_BROWSEINCLUDEURLS = 0x00000080 + BIF_USENEWUI = BIF_EDITBOX | BIF_NEWDIALOGSTYLE + BIF_UAHINT = 0x00000100 + BIF_NONEWFOLDERBUTTON = 0x00000200 + BIF_NOTRANSLATETARGETS = 0x00000400 + BIF_BROWSEFORCOMPUTER = 0x00001000 + BIF_BROWSEFORPRINTER = 0x00002000 + BIF_BROWSEINCLUDEFILES = 0x00004000 + BIF_SHAREABLE = 0x00008000 + BIF_BROWSEFILEJUNCTIONS = 0x00010000 +) + +//MessageBox flags +const ( + MB_OK = 0x00000000 + MB_OKCANCEL = 0x00000001 + MB_ABORTRETRYIGNORE = 0x00000002 + MB_YESNOCANCEL = 0x00000003 + MB_YESNO = 0x00000004 + MB_RETRYCANCEL = 0x00000005 + MB_CANCELTRYCONTINUE = 0x00000006 + MB_ICONHAND = 0x00000010 + MB_ICONQUESTION = 0x00000020 + MB_ICONEXCLAMATION = 0x00000030 + MB_ICONASTERISK = 0x00000040 + MB_USERICON = 0x00000080 + MB_ICONWARNING = MB_ICONEXCLAMATION + MB_ICONERROR = MB_ICONHAND + MB_ICONINFORMATION = MB_ICONASTERISK + MB_ICONSTOP = MB_ICONHAND + MB_DEFBUTTON1 = 0x00000000 + MB_DEFBUTTON2 = 0x00000100 + MB_DEFBUTTON3 = 0x00000200 + MB_DEFBUTTON4 = 0x00000300 +) + +//COM +const ( + E_INVALIDARG = 0x80070057 + E_OUTOFMEMORY = 0x8007000E + E_UNEXPECTED = 0x8000FFFF +) + +const ( + S_OK = 0 + S_FALSE = 0x0001 + RPC_E_CHANGED_MODE = 0x80010106 +) + +// GetSystemMetrics constants +const ( + SM_CXSCREEN = 0 + SM_CYSCREEN = 1 + SM_CXVSCROLL = 2 + SM_CYHSCROLL = 3 + SM_CYCAPTION = 4 + SM_CXBORDER = 5 + SM_CYBORDER = 6 + SM_CXDLGFRAME = 7 + SM_CYDLGFRAME = 8 + SM_CYVTHUMB = 9 + SM_CXHTHUMB = 10 + SM_CXICON = 11 + SM_CYICON = 12 + SM_CXCURSOR = 13 + SM_CYCURSOR = 14 + SM_CYMENU = 15 + SM_CXFULLSCREEN = 16 + SM_CYFULLSCREEN = 17 + SM_CYKANJIWINDOW = 18 + SM_MOUSEPRESENT = 19 + SM_CYVSCROLL = 20 + SM_CXHSCROLL = 21 + SM_DEBUG = 22 + SM_SWAPBUTTON = 23 + SM_RESERVED1 = 24 + SM_RESERVED2 = 25 + SM_RESERVED3 = 26 + SM_RESERVED4 = 27 + SM_CXMIN = 28 + SM_CYMIN = 29 + SM_CXSIZE = 30 + SM_CYSIZE = 31 + SM_CXFRAME = 32 + SM_CYFRAME = 33 + SM_CXMINTRACK = 34 + SM_CYMINTRACK = 35 + SM_CXDOUBLECLK = 36 + SM_CYDOUBLECLK = 37 + SM_CXICONSPACING = 38 + SM_CYICONSPACING = 39 + SM_MENUDROPALIGNMENT = 40 + SM_PENWINDOWS = 41 + SM_DBCSENABLED = 42 + SM_CMOUSEBUTTONS = 43 + SM_CXFIXEDFRAME = SM_CXDLGFRAME + SM_CYFIXEDFRAME = SM_CYDLGFRAME + SM_CXSIZEFRAME = SM_CXFRAME + SM_CYSIZEFRAME = SM_CYFRAME + SM_SECURE = 44 + SM_CXEDGE = 45 + SM_CYEDGE = 46 + SM_CXMINSPACING = 47 + SM_CYMINSPACING = 48 + SM_CXSMICON = 49 + SM_CYSMICON = 50 + SM_CYSMCAPTION = 51 + SM_CXSMSIZE = 52 + SM_CYSMSIZE = 53 + SM_CXMENUSIZE = 54 + SM_CYMENUSIZE = 55 + SM_ARRANGE = 56 + SM_CXMINIMIZED = 57 + SM_CYMINIMIZED = 58 + SM_CXMAXTRACK = 59 + SM_CYMAXTRACK = 60 + SM_CXMAXIMIZED = 61 + SM_CYMAXIMIZED = 62 + SM_NETWORK = 63 + SM_CLEANBOOT = 67 + SM_CXDRAG = 68 + SM_CYDRAG = 69 + SM_SHOWSOUNDS = 70 + SM_CXMENUCHECK = 71 + SM_CYMENUCHECK = 72 + SM_SLOWMACHINE = 73 + SM_MIDEASTENABLED = 74 + SM_MOUSEWHEELPRESENT = 75 + SM_XVIRTUALSCREEN = 76 + SM_YVIRTUALSCREEN = 77 + SM_CXVIRTUALSCREEN = 78 + SM_CYVIRTUALSCREEN = 79 + SM_CMONITORS = 80 + SM_SAMEDISPLAYFORMAT = 81 + SM_IMMENABLED = 82 + SM_CXFOCUSBORDER = 83 + SM_CYFOCUSBORDER = 84 + SM_TABLETPC = 86 + SM_MEDIACENTER = 87 + SM_STARTER = 88 + SM_SERVERR2 = 89 + SM_CMETRICS = 91 + SM_REMOTESESSION = 0x1000 + SM_SHUTTINGDOWN = 0x2000 + SM_REMOTECONTROL = 0x2001 + SM_CARETBLINKINGENABLED = 0x2002 +) + +const ( + CLSCTX_INPROC_SERVER = 1 + CLSCTX_INPROC_HANDLER = 2 + CLSCTX_LOCAL_SERVER = 4 + CLSCTX_INPROC_SERVER16 = 8 + CLSCTX_REMOTE_SERVER = 16 + CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER + CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER + CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER +) + +const ( + COINIT_APARTMENTTHREADED = 0x2 + COINIT_MULTITHREADED = 0x0 + COINIT_DISABLE_OLE1DDE = 0x4 + COINIT_SPEED_OVER_MEMORY = 0x8 +) + +const ( + DISPATCH_METHOD = 1 + DISPATCH_PROPERTYGET = 2 + DISPATCH_PROPERTYPUT = 4 + DISPATCH_PROPERTYPUTREF = 8 +) + +const ( + CC_FASTCALL = iota + CC_CDECL + CC_MSCPASCAL + CC_PASCAL = CC_MSCPASCAL + CC_MACPASCAL + CC_STDCALL + CC_FPFASTCALL + CC_SYSCALL + CC_MPWCDECL + CC_MPWPASCAL + CC_MAX = CC_MPWPASCAL +) + +const ( + VT_EMPTY = 0x0 + VT_NULL = 0x1 + VT_I2 = 0x2 + VT_I4 = 0x3 + VT_R4 = 0x4 + VT_R8 = 0x5 + VT_CY = 0x6 + VT_DATE = 0x7 + VT_BSTR = 0x8 + VT_DISPATCH = 0x9 + VT_ERROR = 0xa + VT_BOOL = 0xb + VT_VARIANT = 0xc + VT_UNKNOWN = 0xd + VT_DECIMAL = 0xe + VT_I1 = 0x10 + VT_UI1 = 0x11 + VT_UI2 = 0x12 + VT_UI4 = 0x13 + VT_I8 = 0x14 + VT_UI8 = 0x15 + VT_INT = 0x16 + VT_UINT = 0x17 + VT_VOID = 0x18 + VT_HRESULT = 0x19 + VT_PTR = 0x1a + VT_SAFEARRAY = 0x1b + VT_CARRAY = 0x1c + VT_USERDEFINED = 0x1d + VT_LPSTR = 0x1e + VT_LPWSTR = 0x1f + VT_RECORD = 0x24 + VT_INT_PTR = 0x25 + VT_UINT_PTR = 0x26 + VT_FILETIME = 0x40 + VT_BLOB = 0x41 + VT_STREAM = 0x42 + VT_STORAGE = 0x43 + VT_STREAMED_OBJECT = 0x44 + VT_STORED_OBJECT = 0x45 + VT_BLOB_OBJECT = 0x46 + VT_CF = 0x47 + VT_CLSID = 0x48 + VT_BSTR_BLOB = 0xfff + VT_VECTOR = 0x1000 + VT_ARRAY = 0x2000 + VT_BYREF = 0x4000 + VT_RESERVED = 0x8000 + VT_ILLEGAL = 0xffff + VT_ILLEGALMASKED = 0xfff + VT_TYPEMASK = 0xfff +) + +const ( + DISPID_UNKNOWN = -1 + DISPID_VALUE = 0 + DISPID_PROPERTYPUT = -3 + DISPID_NEWENUM = -4 + DISPID_EVALUATE = -5 + DISPID_CONSTRUCTOR = -6 + DISPID_DESTRUCTOR = -7 + DISPID_COLLECT = -8 +) + +const ( + MONITOR_DEFAULTTONULL = 0x00000000 + MONITOR_DEFAULTTOPRIMARY = 0x00000001 + MONITOR_DEFAULTTONEAREST = 0x00000002 + + MONITORINFOF_PRIMARY = 0x00000001 +) + +const ( + CCHDEVICENAME = 32 + CCHFORMNAME = 32 +) + +const ( + IDOK = 1 + IDCANCEL = 2 + IDABORT = 3 + IDRETRY = 4 + IDIGNORE = 5 + IDYES = 6 + IDNO = 7 + IDCLOSE = 8 + IDHELP = 9 + IDTRYAGAIN = 10 + IDCONTINUE = 11 + IDTIMEOUT = 32000 +) + +// Generic WM_NOTIFY notification codes +const ( + NM_FIRST = 0 + NM_OUTOFMEMORY = NM_FIRST - 1 + NM_CLICK = NM_FIRST - 2 + NM_DBLCLK = NM_FIRST - 3 + NM_RETURN = NM_FIRST - 4 + NM_RCLICK = NM_FIRST - 5 + NM_RDBLCLK = NM_FIRST - 6 + NM_SETFOCUS = NM_FIRST - 7 + NM_KILLFOCUS = NM_FIRST - 8 + NM_CUSTOMDRAW = NM_FIRST - 12 + NM_HOVER = NM_FIRST - 13 + NM_NCHITTEST = NM_FIRST - 14 + NM_KEYDOWN = NM_FIRST - 15 + NM_RELEASEDCAPTURE = NM_FIRST - 16 + NM_SETCURSOR = NM_FIRST - 17 + NM_CHAR = NM_FIRST - 18 + NM_TOOLTIPSCREATED = NM_FIRST - 19 + NM_LAST = NM_FIRST - 99 +) + +// ListView messages +const ( + LVM_FIRST = 0x1000 + LVM_GETITEMCOUNT = LVM_FIRST + 4 + LVM_SETIMAGELIST = LVM_FIRST + 3 + LVM_GETIMAGELIST = LVM_FIRST + 2 + LVM_GETITEM = LVM_FIRST + 75 + LVM_SETITEM = LVM_FIRST + 76 + LVM_INSERTITEM = LVM_FIRST + 77 + LVM_DELETEITEM = LVM_FIRST + 8 + LVM_DELETEALLITEMS = LVM_FIRST + 9 + LVM_GETCALLBACKMASK = LVM_FIRST + 10 + LVM_SETCALLBACKMASK = LVM_FIRST + 11 + LVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT + LVM_GETNEXTITEM = LVM_FIRST + 12 + LVM_FINDITEM = LVM_FIRST + 83 + LVM_GETITEMRECT = LVM_FIRST + 14 + LVM_GETSTRINGWIDTH = LVM_FIRST + 87 + LVM_HITTEST = LVM_FIRST + 18 + LVM_ENSUREVISIBLE = LVM_FIRST + 19 + LVM_SCROLL = LVM_FIRST + 20 + LVM_REDRAWITEMS = LVM_FIRST + 21 + LVM_ARRANGE = LVM_FIRST + 22 + LVM_EDITLABEL = LVM_FIRST + 118 + LVM_GETEDITCONTROL = LVM_FIRST + 24 + LVM_GETCOLUMN = LVM_FIRST + 95 + LVM_SETCOLUMN = LVM_FIRST + 96 + LVM_INSERTCOLUMN = LVM_FIRST + 97 + LVM_DELETECOLUMN = LVM_FIRST + 28 + LVM_GETCOLUMNWIDTH = LVM_FIRST + 29 + LVM_SETCOLUMNWIDTH = LVM_FIRST + 30 + LVM_GETHEADER = LVM_FIRST + 31 + LVM_CREATEDRAGIMAGE = LVM_FIRST + 33 + LVM_GETVIEWRECT = LVM_FIRST + 34 + LVM_GETTEXTCOLOR = LVM_FIRST + 35 + LVM_SETTEXTCOLOR = LVM_FIRST + 36 + LVM_GETTEXTBKCOLOR = LVM_FIRST + 37 + LVM_SETTEXTBKCOLOR = LVM_FIRST + 38 + LVM_GETTOPINDEX = LVM_FIRST + 39 + LVM_GETCOUNTPERPAGE = LVM_FIRST + 40 + LVM_GETORIGIN = LVM_FIRST + 41 + LVM_UPDATE = LVM_FIRST + 42 + LVM_SETITEMSTATE = LVM_FIRST + 43 + LVM_GETITEMSTATE = LVM_FIRST + 44 + LVM_GETITEMTEXT = LVM_FIRST + 115 + LVM_SETITEMTEXT = LVM_FIRST + 116 + LVM_SETITEMCOUNT = LVM_FIRST + 47 + LVM_SORTITEMS = LVM_FIRST + 48 + LVM_SETITEMPOSITION32 = LVM_FIRST + 49 + LVM_GETSELECTEDCOUNT = LVM_FIRST + 50 + LVM_GETITEMSPACING = LVM_FIRST + 51 + LVM_GETISEARCHSTRING = LVM_FIRST + 117 + LVM_SETICONSPACING = LVM_FIRST + 53 + LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54 + LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55 + LVM_GETSUBITEMRECT = LVM_FIRST + 56 + LVM_SUBITEMHITTEST = LVM_FIRST + 57 + LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58 + LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59 + LVM_SETHOTITEM = LVM_FIRST + 60 + LVM_GETHOTITEM = LVM_FIRST + 61 + LVM_SETHOTCURSOR = LVM_FIRST + 62 + LVM_GETHOTCURSOR = LVM_FIRST + 63 + LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64 + LVM_SETWORKAREAS = LVM_FIRST + 65 + LVM_GETWORKAREAS = LVM_FIRST + 70 + LVM_GETNUMBEROFWORKAREAS = LVM_FIRST + 73 + LVM_GETSELECTIONMARK = LVM_FIRST + 66 + LVM_SETSELECTIONMARK = LVM_FIRST + 67 + LVM_SETHOVERTIME = LVM_FIRST + 71 + LVM_GETHOVERTIME = LVM_FIRST + 72 + LVM_SETTOOLTIPS = LVM_FIRST + 74 + LVM_GETTOOLTIPS = LVM_FIRST + 78 + LVM_SORTITEMSEX = LVM_FIRST + 81 + LVM_SETBKIMAGE = LVM_FIRST + 138 + LVM_GETBKIMAGE = LVM_FIRST + 139 + LVM_SETSELECTEDCOLUMN = LVM_FIRST + 140 + LVM_SETVIEW = LVM_FIRST + 142 + LVM_GETVIEW = LVM_FIRST + 143 + LVM_INSERTGROUP = LVM_FIRST + 145 + LVM_SETGROUPINFO = LVM_FIRST + 147 + LVM_GETGROUPINFO = LVM_FIRST + 149 + LVM_REMOVEGROUP = LVM_FIRST + 150 + LVM_MOVEGROUP = LVM_FIRST + 151 + LVM_GETGROUPCOUNT = LVM_FIRST + 152 + LVM_GETGROUPINFOBYINDEX = LVM_FIRST + 153 + LVM_MOVEITEMTOGROUP = LVM_FIRST + 154 + LVM_GETGROUPRECT = LVM_FIRST + 98 + LVM_SETGROUPMETRICS = LVM_FIRST + 155 + LVM_GETGROUPMETRICS = LVM_FIRST + 156 + LVM_ENABLEGROUPVIEW = LVM_FIRST + 157 + LVM_SORTGROUPS = LVM_FIRST + 158 + LVM_INSERTGROUPSORTED = LVM_FIRST + 159 + LVM_REMOVEALLGROUPS = LVM_FIRST + 160 + LVM_HASGROUP = LVM_FIRST + 161 + LVM_GETGROUPSTATE = LVM_FIRST + 92 + LVM_GETFOCUSEDGROUP = LVM_FIRST + 93 + LVM_SETTILEVIEWINFO = LVM_FIRST + 162 + LVM_GETTILEVIEWINFO = LVM_FIRST + 163 + LVM_SETTILEINFO = LVM_FIRST + 164 + LVM_GETTILEINFO = LVM_FIRST + 165 + LVM_SETINSERTMARK = LVM_FIRST + 166 + LVM_GETINSERTMARK = LVM_FIRST + 167 + LVM_INSERTMARKHITTEST = LVM_FIRST + 168 + LVM_GETINSERTMARKRECT = LVM_FIRST + 169 + LVM_SETINSERTMARKCOLOR = LVM_FIRST + 170 + LVM_GETINSERTMARKCOLOR = LVM_FIRST + 171 + LVM_SETINFOTIP = LVM_FIRST + 173 + LVM_GETSELECTEDCOLUMN = LVM_FIRST + 174 + LVM_ISGROUPVIEWENABLED = LVM_FIRST + 175 + LVM_GETOUTLINECOLOR = LVM_FIRST + 176 + LVM_SETOUTLINECOLOR = LVM_FIRST + 177 + LVM_CANCELEDITLABEL = LVM_FIRST + 179 + LVM_MAPINDEXTOID = LVM_FIRST + 180 + LVM_MAPIDTOINDEX = LVM_FIRST + 181 + LVM_ISITEMVISIBLE = LVM_FIRST + 182 + LVM_GETNEXTITEMINDEX = LVM_FIRST + 211 +) + +// ListView notifications +const ( + LVN_FIRST = -100 + + LVN_ITEMCHANGING = LVN_FIRST - 0 + LVN_ITEMCHANGED = LVN_FIRST - 1 + LVN_INSERTITEM = LVN_FIRST - 2 + LVN_DELETEITEM = LVN_FIRST - 3 + LVN_DELETEALLITEMS = LVN_FIRST - 4 + LVN_BEGINLABELEDITA = LVN_FIRST - 5 + LVN_BEGINLABELEDITW = LVN_FIRST - 75 + LVN_ENDLABELEDITA = LVN_FIRST - 6 + LVN_ENDLABELEDITW = LVN_FIRST - 76 + LVN_COLUMNCLICK = LVN_FIRST - 8 + LVN_BEGINDRAG = LVN_FIRST - 9 + LVN_BEGINRDRAG = LVN_FIRST - 11 + LVN_ODCACHEHINT = LVN_FIRST - 13 + LVN_ODFINDITEMA = LVN_FIRST - 52 + LVN_ODFINDITEMW = LVN_FIRST - 79 + LVN_ITEMACTIVATE = LVN_FIRST - 14 + LVN_ODSTATECHANGED = LVN_FIRST - 15 + LVN_HOTTRACK = LVN_FIRST - 21 + LVN_GETDISPINFO = LVN_FIRST - 77 + LVN_SETDISPINFO = LVN_FIRST - 78 + LVN_KEYDOWN = LVN_FIRST - 55 + LVN_MARQUEEBEGIN = LVN_FIRST - 56 + LVN_GETINFOTIP = LVN_FIRST - 58 + LVN_INCREMENTALSEARCH = LVN_FIRST - 63 + LVN_BEGINSCROLL = LVN_FIRST - 80 + LVN_ENDSCROLL = LVN_FIRST - 81 +) + +const ( + LVSCW_AUTOSIZE = ^uintptr(0) + LVSCW_AUTOSIZE_USEHEADER = ^uintptr(1) +) + +// ListView LVNI constants +const ( + LVNI_ALL = 0 + LVNI_FOCUSED = 1 + LVNI_SELECTED = 2 + LVNI_CUT = 4 + LVNI_DROPHILITED = 8 + LVNI_ABOVE = 256 + LVNI_BELOW = 512 + LVNI_TOLEFT = 1024 + LVNI_TORIGHT = 2048 +) + +// ListView styles +const ( + LVS_ICON = 0x0000 + LVS_REPORT = 0x0001 + LVS_SMALLICON = 0x0002 + LVS_LIST = 0x0003 + LVS_TYPEMASK = 0x0003 + LVS_SINGLESEL = 0x0004 + LVS_SHOWSELALWAYS = 0x0008 + LVS_SORTASCENDING = 0x0010 + LVS_SORTDESCENDING = 0x0020 + LVS_SHAREIMAGELISTS = 0x0040 + LVS_NOLABELWRAP = 0x0080 + LVS_AUTOARRANGE = 0x0100 + LVS_EDITLABELS = 0x0200 + LVS_OWNERDATA = 0x1000 + LVS_NOSCROLL = 0x2000 + LVS_TYPESTYLEMASK = 0xfc00 + LVS_ALIGNTOP = 0x0000 + LVS_ALIGNLEFT = 0x0800 + LVS_ALIGNMASK = 0x0c00 + LVS_OWNERDRAWFIXED = 0x0400 + LVS_NOCOLUMNHEADER = 0x4000 + LVS_NOSORTHEADER = 0x8000 +) + +// ListView extended styles +const ( + LVS_EX_GRIDLINES = 0x00000001 + LVS_EX_SUBITEMIMAGES = 0x00000002 + LVS_EX_CHECKBOXES = 0x00000004 + LVS_EX_TRACKSELECT = 0x00000008 + LVS_EX_HEADERDRAGDROP = 0x00000010 + LVS_EX_FULLROWSELECT = 0x00000020 + LVS_EX_ONECLICKACTIVATE = 0x00000040 + LVS_EX_TWOCLICKACTIVATE = 0x00000080 + LVS_EX_FLATSB = 0x00000100 + LVS_EX_REGIONAL = 0x00000200 + LVS_EX_INFOTIP = 0x00000400 + LVS_EX_UNDERLINEHOT = 0x00000800 + LVS_EX_UNDERLINECOLD = 0x00001000 + LVS_EX_MULTIWORKAREAS = 0x00002000 + LVS_EX_LABELTIP = 0x00004000 + LVS_EX_BORDERSELECT = 0x00008000 + LVS_EX_DOUBLEBUFFER = 0x00010000 + LVS_EX_HIDELABELS = 0x00020000 + LVS_EX_SINGLEROW = 0x00040000 + LVS_EX_SNAPTOGRID = 0x00080000 + LVS_EX_SIMPLESELECT = 0x00100000 +) + +// ListView column flags +const ( + LVCF_FMT = 0x0001 + LVCF_WIDTH = 0x0002 + LVCF_TEXT = 0x0004 + LVCF_SUBITEM = 0x0008 + LVCF_IMAGE = 0x0010 + LVCF_ORDER = 0x0020 +) + +// ListView column format constants +const ( + LVCFMT_LEFT = 0x0000 + LVCFMT_RIGHT = 0x0001 + LVCFMT_CENTER = 0x0002 + LVCFMT_JUSTIFYMASK = 0x0003 + LVCFMT_IMAGE = 0x0800 + LVCFMT_BITMAP_ON_RIGHT = 0x1000 + LVCFMT_COL_HAS_IMAGES = 0x8000 +) + +// ListView item flags +const ( + LVIF_TEXT = 0x00000001 + LVIF_IMAGE = 0x00000002 + LVIF_PARAM = 0x00000004 + LVIF_STATE = 0x00000008 + LVIF_INDENT = 0x00000010 + LVIF_NORECOMPUTE = 0x00000800 + LVIF_GROUPID = 0x00000100 + LVIF_COLUMNS = 0x00000200 +) + +const LVFI_PARAM = 0x0001 + +// ListView item states +const ( + LVIS_FOCUSED = 1 + LVIS_SELECTED = 2 + LVIS_CUT = 4 + LVIS_DROPHILITED = 8 + LVIS_OVERLAYMASK = 0xF00 + LVIS_STATEIMAGEMASK = 0xF000 +) + +// ListView hit test constants +const ( + LVHT_NOWHERE = 0x00000001 + LVHT_ONITEMICON = 0x00000002 + LVHT_ONITEMLABEL = 0x00000004 + LVHT_ONITEMSTATEICON = 0x00000008 + LVHT_ONITEM = LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON + + LVHT_ABOVE = 0x00000008 + LVHT_BELOW = 0x00000010 + LVHT_TORIGHT = 0x00000020 + LVHT_TOLEFT = 0x00000040 +) + +// ListView image list types +const ( + LVSIL_NORMAL = 0 + LVSIL_SMALL = 1 + LVSIL_STATE = 2 + LVSIL_GROUPHEADER = 3 +) + +// InitCommonControlsEx flags +const ( + ICC_LISTVIEW_CLASSES = 1 + ICC_TREEVIEW_CLASSES = 2 + ICC_BAR_CLASSES = 4 + ICC_TAB_CLASSES = 8 + ICC_UPDOWN_CLASS = 16 + ICC_PROGRESS_CLASS = 32 + ICC_HOTKEY_CLASS = 64 + ICC_ANIMATE_CLASS = 128 + ICC_WIN95_CLASSES = 255 + ICC_DATE_CLASSES = 256 + ICC_USEREX_CLASSES = 512 + ICC_COOL_CLASSES = 1024 + ICC_INTERNET_CLASSES = 2048 + ICC_PAGESCROLLER_CLASS = 4096 + ICC_NATIVEFNTCTL_CLASS = 8192 + INFOTIPSIZE = 1024 + ICC_STANDARD_CLASSES = 0x00004000 + ICC_LINK_CLASS = 0x00008000 +) + +// Dialog Codes +const ( + DLGC_WANTARROWS = 0x0001 + DLGC_WANTTAB = 0x0002 + DLGC_WANTALLKEYS = 0x0004 + DLGC_WANTMESSAGE = 0x0004 + DLGC_HASSETSEL = 0x0008 + DLGC_DEFPUSHBUTTON = 0x0010 + DLGC_UNDEFPUSHBUTTON = 0x0020 + DLGC_RADIOBUTTON = 0x0040 + DLGC_WANTCHARS = 0x0080 + DLGC_STATIC = 0x0100 + DLGC_BUTTON = 0x2000 +) + +// Get/SetWindowWord/Long offsets for use with WC_DIALOG windows +const ( + DWL_MSGRESULT = 0 + DWL_DLGPROC = 4 + DWL_USER = 8 +) + +// Registry predefined keys +const ( + HKEY_CLASSES_ROOT HKEY = 0x80000000 + HKEY_CURRENT_USER HKEY = 0x80000001 + HKEY_LOCAL_MACHINE HKEY = 0x80000002 + HKEY_USERS HKEY = 0x80000003 + HKEY_PERFORMANCE_DATA HKEY = 0x80000004 + HKEY_CURRENT_CONFIG HKEY = 0x80000005 + HKEY_DYN_DATA HKEY = 0x80000006 +) + +// Registry Key Security and Access Rights +const ( + KEY_ALL_ACCESS = 0xF003F + KEY_CREATE_SUB_KEY = 0x0004 + KEY_ENUMERATE_SUB_KEYS = 0x0008 + KEY_NOTIFY = 0x0010 + KEY_QUERY_VALUE = 0x0001 + KEY_SET_VALUE = 0x0002 + KEY_READ = 0x20019 + KEY_WRITE = 0x20006 +) + +const ( + NFR_ANSI = 1 + NFR_UNICODE = 2 + NF_QUERY = 3 + NF_REQUERY = 4 +) + +// Registry value types +const ( + RRF_RT_REG_NONE = 0x00000001 + RRF_RT_REG_SZ = 0x00000002 + RRF_RT_REG_EXPAND_SZ = 0x00000004 + RRF_RT_REG_BINARY = 0x00000008 + RRF_RT_REG_DWORD = 0x00000010 + RRF_RT_REG_MULTI_SZ = 0x00000020 + RRF_RT_REG_QWORD = 0x00000040 + RRF_RT_DWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD) + RRF_RT_QWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD) + RRF_RT_ANY = 0x0000ffff + RRF_NOEXPAND = 0x10000000 + RRF_ZEROONFAILURE = 0x20000000 + REG_PROCESS_APPKEY = 0x00000001 + REG_MUI_STRING_TRUNCATE = 0x00000001 +) + +// PeekMessage wRemoveMsg value +const ( + PM_NOREMOVE = 0x000 + PM_REMOVE = 0x001 + PM_NOYIELD = 0x002 +) + +// ImageList flags +const ( + ILC_MASK = 0x00000001 + ILC_COLOR = 0x00000000 + ILC_COLORDDB = 0x000000FE + ILC_COLOR4 = 0x00000004 + ILC_COLOR8 = 0x00000008 + ILC_COLOR16 = 0x00000010 + ILC_COLOR24 = 0x00000018 + ILC_COLOR32 = 0x00000020 + ILC_PALETTE = 0x00000800 + ILC_MIRROR = 0x00002000 + ILC_PERITEMMIRROR = 0x00008000 + ILC_ORIGINALSIZE = 0x00010000 + ILC_HIGHQUALITYSCALE = 0x00020000 +) + +// Keystroke Message Flags +const ( + KF_EXTENDED = 0x0100 + KF_DLGMODE = 0x0800 + KF_MENUMODE = 0x1000 + KF_ALTDOWN = 0x2000 + KF_REPEAT = 0x4000 + KF_UP = 0x8000 +) + +// Virtual-Key Codes +/* +const ( + VK_LBUTTON = 0x01 + VK_RBUTTON = 0x02 + VK_CANCEL = 0x03 + VK_MBUTTON = 0x04 + VK_XBUTTON1 = 0x05 + VK_XBUTTON2 = 0x06 + VK_BACK = 0x08 + VK_TAB = 0x09 + VK_CLEAR = 0x0C + VK_RETURN = 0x0D + VK_SHIFT = 0x10 + VK_CONTROL = 0x11 + VK_MENU = 0x12 + VK_PAUSE = 0x13 + VK_CAPITAL = 0x14 + VK_KANA = 0x15 + VK_HANGEUL = 0x15 + VK_HANGUL = 0x15 + VK_JUNJA = 0x17 + VK_FINAL = 0x18 + VK_HANJA = 0x19 + VK_KANJI = 0x19 + VK_ESCAPE = 0x1B + VK_CONVERT = 0x1C + VK_NONCONVERT = 0x1D + VK_ACCEPT = 0x1E + VK_MODECHANGE = 0x1F + VK_SPACE = 0x20 + VK_PRIOR = 0x21 + VK_NEXT = 0x22 + VK_END = 0x23 + VK_HOME = 0x24 + VK_LEFT = 0x25 + VK_UP = 0x26 + VK_RIGHT = 0x27 + VK_DOWN = 0x28 + VK_SELECT = 0x29 + VK_PRINT = 0x2A + VK_EXECUTE = 0x2B + VK_SNAPSHOT = 0x2C + VK_INSERT = 0x2D + VK_DELETE = 0x2E + VK_HELP = 0x2F + VK_LWIN = 0x5B + VK_RWIN = 0x5C + VK_APPS = 0x5D + VK_SLEEP = 0x5F + VK_NUMPAD0 = 0x60 + VK_NUMPAD1 = 0x61 + VK_NUMPAD2 = 0x62 + VK_NUMPAD3 = 0x63 + VK_NUMPAD4 = 0x64 + VK_NUMPAD5 = 0x65 + VK_NUMPAD6 = 0x66 + VK_NUMPAD7 = 0x67 + VK_NUMPAD8 = 0x68 + VK_NUMPAD9 = 0x69 + VK_MULTIPLY = 0x6A + VK_ADD = 0x6B + VK_SEPARATOR = 0x6C + VK_SUBTRACT = 0x6D + VK_DECIMAL = 0x6E + VK_DIVIDE = 0x6F + VK_F1 = 0x70 + VK_F2 = 0x71 + VK_F3 = 0x72 + VK_F4 = 0x73 + VK_F5 = 0x74 + VK_F6 = 0x75 + VK_F7 = 0x76 + VK_F8 = 0x77 + VK_F9 = 0x78 + VK_F10 = 0x79 + VK_F11 = 0x7A + VK_F12 = 0x7B + VK_F13 = 0x7C + VK_F14 = 0x7D + VK_F15 = 0x7E + VK_F16 = 0x7F + VK_F17 = 0x80 + VK_F18 = 0x81 + VK_F19 = 0x82 + VK_F20 = 0x83 + VK_F21 = 0x84 + VK_F22 = 0x85 + VK_F23 = 0x86 + VK_F24 = 0x87 + VK_NUMLOCK = 0x90 + VK_SCROLL = 0x91 + VK_OEM_NEC_EQUAL = 0x92 + VK_OEM_FJ_JISHO = 0x92 + VK_OEM_FJ_MASSHOU = 0x93 + VK_OEM_FJ_TOUROKU = 0x94 + VK_OEM_FJ_LOYA = 0x95 + VK_OEM_FJ_ROYA = 0x96 + VK_LSHIFT = 0xA0 + VK_RSHIFT = 0xA1 + VK_LCONTROL = 0xA2 + VK_RCONTROL = 0xA3 + VK_LMENU = 0xA4 + VK_RMENU = 0xA5 + VK_BROWSER_BACK = 0xA6 + VK_BROWSER_FORWARD = 0xA7 + VK_BROWSER_REFRESH = 0xA8 + VK_BROWSER_STOP = 0xA9 + VK_BROWSER_SEARCH = 0xAA + VK_BROWSER_FAVORITES = 0xAB + VK_BROWSER_HOME = 0xAC + VK_VOLUME_MUTE = 0xAD + VK_VOLUME_DOWN = 0xAE + VK_VOLUME_UP = 0xAF + VK_MEDIA_NEXT_TRACK = 0xB0 + VK_MEDIA_PREV_TRACK = 0xB1 + VK_MEDIA_STOP = 0xB2 + VK_MEDIA_PLAY_PAUSE = 0xB3 + VK_LAUNCH_MAIL = 0xB4 + VK_LAUNCH_MEDIA_SELECT = 0xB5 + VK_LAUNCH_APP1 = 0xB6 + VK_LAUNCH_APP2 = 0xB7 + VK_OEM_1 = 0xBA + VK_OEM_PLUS = 0xBB + VK_OEM_COMMA = 0xBC + VK_OEM_MINUS = 0xBD + VK_OEM_PERIOD = 0xBE + VK_OEM_2 = 0xBF + VK_OEM_3 = 0xC0 + VK_OEM_4 = 0xDB + VK_OEM_5 = 0xDC + VK_OEM_6 = 0xDD + VK_OEM_7 = 0xDE + VK_OEM_8 = 0xDF + VK_OEM_AX = 0xE1 + VK_OEM_102 = 0xE2 + VK_ICO_HELP = 0xE3 + VK_ICO_00 = 0xE4 + VK_PROCESSKEY = 0xE5 + VK_ICO_CLEAR = 0xE6 + VK_OEM_RESET = 0xE9 + VK_OEM_JUMP = 0xEA + VK_OEM_PA1 = 0xEB + VK_OEM_PA2 = 0xEC + VK_OEM_PA3 = 0xED + VK_OEM_WSCTRL = 0xEE + VK_OEM_CUSEL = 0xEF + VK_OEM_ATTN = 0xF0 + VK_OEM_FINISH = 0xF1 + VK_OEM_COPY = 0xF2 + VK_OEM_AUTO = 0xF3 + VK_OEM_ENLW = 0xF4 + VK_OEM_BACKTAB = 0xF5 + VK_ATTN = 0xF6 + VK_CRSEL = 0xF7 + VK_EXSEL = 0xF8 + VK_EREOF = 0xF9 + VK_PLAY = 0xFA + VK_ZOOM = 0xFB + VK_NONAME = 0xFC + VK_PA1 = 0xFD + VK_OEM_CLEAR = 0xFE +)*/ + +// Registry Value Types +const ( + REG_NONE = 0 + REG_SZ = 1 + REG_EXPAND_SZ = 2 + REG_BINARY = 3 + REG_DWORD = 4 + REG_DWORD_LITTLE_ENDIAN = 4 + REG_DWORD_BIG_ENDIAN = 5 + REG_LINK = 6 + REG_MULTI_SZ = 7 + REG_RESOURCE_LIST = 8 + REG_FULL_RESOURCE_DESCRIPTOR = 9 + REG_RESOURCE_REQUIREMENTS_LIST = 10 + REG_QWORD = 11 + REG_QWORD_LITTLE_ENDIAN = 11 +) + +// Tooltip styles +const ( + TTS_ALWAYSTIP = 0x01 + TTS_NOPREFIX = 0x02 + TTS_NOANIMATE = 0x10 + TTS_NOFADE = 0x20 + TTS_BALLOON = 0x40 + TTS_CLOSE = 0x80 + TTS_USEVISUALSTYLE = 0x100 +) + +// Tooltip messages +const ( + TTM_ACTIVATE = (WM_USER + 1) + TTM_SETDELAYTIME = (WM_USER + 3) + TTM_ADDTOOL = (WM_USER + 50) + TTM_DELTOOL = (WM_USER + 51) + TTM_NEWTOOLRECT = (WM_USER + 52) + TTM_RELAYEVENT = (WM_USER + 7) + TTM_GETTOOLINFO = (WM_USER + 53) + TTM_SETTOOLINFO = (WM_USER + 54) + TTM_HITTEST = (WM_USER + 55) + TTM_GETTEXT = (WM_USER + 56) + TTM_UPDATETIPTEXT = (WM_USER + 57) + TTM_GETTOOLCOUNT = (WM_USER + 13) + TTM_ENUMTOOLS = (WM_USER + 58) + TTM_GETCURRENTTOOL = (WM_USER + 59) + TTM_WINDOWFROMPOINT = (WM_USER + 16) + TTM_TRACKACTIVATE = (WM_USER + 17) + TTM_TRACKPOSITION = (WM_USER + 18) + TTM_SETTIPBKCOLOR = (WM_USER + 19) + TTM_SETTIPTEXTCOLOR = (WM_USER + 20) + TTM_GETDELAYTIME = (WM_USER + 21) + TTM_GETTIPBKCOLOR = (WM_USER + 22) + TTM_GETTIPTEXTCOLOR = (WM_USER + 23) + TTM_SETMAXTIPWIDTH = (WM_USER + 24) + TTM_GETMAXTIPWIDTH = (WM_USER + 25) + TTM_SETMARGIN = (WM_USER + 26) + TTM_GETMARGIN = (WM_USER + 27) + TTM_POP = (WM_USER + 28) + TTM_UPDATE = (WM_USER + 29) + TTM_GETBUBBLESIZE = (WM_USER + 30) + TTM_ADJUSTRECT = (WM_USER + 31) + TTM_SETTITLE = (WM_USER + 33) + TTM_POPUP = (WM_USER + 34) + TTM_GETTITLE = (WM_USER + 35) +) + +// Tooltip icons +const ( + TTI_NONE = 0 + TTI_INFO = 1 + TTI_WARNING = 2 + TTI_ERROR = 3 + TTI_INFO_LARGE = 4 + TTI_WARNING_LARGE = 5 + TTI_ERROR_LARGE = 6 +) + +// Tooltip notifications +const ( + TTN_FIRST = -520 + TTN_LAST = -549 + TTN_GETDISPINFO = (TTN_FIRST - 10) + TTN_SHOW = (TTN_FIRST - 1) + TTN_POP = (TTN_FIRST - 2) + TTN_LINKCLICK = (TTN_FIRST - 3) + TTN_NEEDTEXT = TTN_GETDISPINFO +) + +const ( + TTF_IDISHWND = 0x0001 + TTF_CENTERTIP = 0x0002 + TTF_RTLREADING = 0x0004 + TTF_SUBCLASS = 0x0010 + TTF_TRACK = 0x0020 + TTF_ABSOLUTE = 0x0080 + TTF_TRANSPARENT = 0x0100 + TTF_PARSELINKS = 0x1000 + TTF_DI_SETITEM = 0x8000 +) + +const ( + SWP_NOSIZE = 0x0001 + SWP_NOMOVE = 0x0002 + SWP_NOZORDER = 0x0004 + SWP_NOREDRAW = 0x0008 + SWP_NOACTIVATE = 0x0010 + SWP_FRAMECHANGED = 0x0020 + SWP_SHOWWINDOW = 0x0040 + SWP_HIDEWINDOW = 0x0080 + SWP_NOCOPYBITS = 0x0100 + SWP_NOOWNERZORDER = 0x0200 + SWP_NOSENDCHANGING = 0x0400 + SWP_DRAWFRAME = SWP_FRAMECHANGED + SWP_NOREPOSITION = SWP_NOOWNERZORDER + SWP_DEFERERASE = 0x2000 + SWP_ASYNCWINDOWPOS = 0x4000 +) + +// Predefined window handles +const ( + HWND_BROADCAST = HWND(0xFFFF) + HWND_BOTTOM = HWND(1) + HWND_NOTOPMOST = ^HWND(1) // -2 + HWND_TOP = HWND(0) + HWND_TOPMOST = ^HWND(0) // -1 + HWND_DESKTOP = HWND(0) + HWND_MESSAGE = ^HWND(2) // -3 +) + +// Pen types +const ( + PS_COSMETIC = 0x00000000 + PS_GEOMETRIC = 0x00010000 + PS_TYPE_MASK = 0x000F0000 +) + +// Pen styles +const ( + PS_SOLID = 0 + PS_DASH = 1 + PS_DOT = 2 + PS_DASHDOT = 3 + PS_DASHDOTDOT = 4 + PS_NULL = 5 + PS_INSIDEFRAME = 6 + PS_USERSTYLE = 7 + PS_ALTERNATE = 8 + PS_STYLE_MASK = 0x0000000F +) + +// Pen cap types +const ( + PS_ENDCAP_ROUND = 0x00000000 + PS_ENDCAP_SQUARE = 0x00000100 + PS_ENDCAP_FLAT = 0x00000200 + PS_ENDCAP_MASK = 0x00000F00 +) + +// Pen join types +const ( + PS_JOIN_ROUND = 0x00000000 + PS_JOIN_BEVEL = 0x00001000 + PS_JOIN_MITER = 0x00002000 + PS_JOIN_MASK = 0x0000F000 +) + +// Hatch styles +const ( + HS_HORIZONTAL = 0 + HS_VERTICAL = 1 + HS_FDIAGONAL = 2 + HS_BDIAGONAL = 3 + HS_CROSS = 4 + HS_DIAGCROSS = 5 +) + +// Stock Logical Objects +const ( + WHITE_BRUSH = 0 + LTGRAY_BRUSH = 1 + GRAY_BRUSH = 2 + DKGRAY_BRUSH = 3 + BLACK_BRUSH = 4 + NULL_BRUSH = 5 + HOLLOW_BRUSH = NULL_BRUSH + WHITE_PEN = 6 + BLACK_PEN = 7 + NULL_PEN = 8 + OEM_FIXED_FONT = 10 + ANSI_FIXED_FONT = 11 + ANSI_VAR_FONT = 12 + SYSTEM_FONT = 13 + DEVICE_DEFAULT_FONT = 14 + DEFAULT_PALETTE = 15 + SYSTEM_FIXED_FONT = 16 + DEFAULT_GUI_FONT = 17 + DC_BRUSH = 18 + DC_PEN = 19 +) + +// Brush styles +const ( + BS_SOLID = 0 + BS_NULL = 1 + BS_HOLLOW = BS_NULL + BS_HATCHED = 2 + BS_PATTERN = 3 + BS_INDEXED = 4 + BS_DIBPATTERN = 5 + BS_DIBPATTERNPT = 6 + BS_PATTERN8X8 = 7 + BS_DIBPATTERN8X8 = 8 + BS_MONOPATTERN = 9 +) + +// TRACKMOUSEEVENT flags +const ( + TME_HOVER = 0x00000001 + TME_LEAVE = 0x00000002 + TME_NONCLIENT = 0x00000010 + TME_QUERY = 0x40000000 + TME_CANCEL = 0x80000000 + + HOVER_DEFAULT = 0xFFFFFFFF +) + +// WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes +const ( + HTERROR = (-2) + HTTRANSPARENT = (-1) + HTNOWHERE = 0 + HTCLIENT = 1 + HTCAPTION = 2 + HTSYSMENU = 3 + HTGROWBOX = 4 + HTSIZE = HTGROWBOX + HTMENU = 5 + HTHSCROLL = 6 + HTVSCROLL = 7 + HTMINBUTTON = 8 + HTMAXBUTTON = 9 + HTLEFT = 10 + HTRIGHT = 11 + HTTOP = 12 + HTTOPLEFT = 13 + HTTOPRIGHT = 14 + HTBOTTOM = 15 + HTBOTTOMLEFT = 16 + HTBOTTOMRIGHT = 17 + HTBORDER = 18 + HTREDUCE = HTMINBUTTON + HTZOOM = HTMAXBUTTON + HTSIZEFIRST = HTLEFT + HTSIZELAST = HTBOTTOMRIGHT + HTOBJECT = 19 + HTCLOSE = 20 + HTHELP = 21 +) + +// DrawText[Ex] format flags +const ( + DT_TOP = 0x00000000 + DT_LEFT = 0x00000000 + DT_CENTER = 0x00000001 + DT_RIGHT = 0x00000002 + DT_VCENTER = 0x00000004 + DT_BOTTOM = 0x00000008 + DT_WORDBREAK = 0x00000010 + DT_SINGLELINE = 0x00000020 + DT_EXPANDTABS = 0x00000040 + DT_TABSTOP = 0x00000080 + DT_NOCLIP = 0x00000100 + DT_EXTERNALLEADING = 0x00000200 + DT_CALCRECT = 0x00000400 + DT_NOPREFIX = 0x00000800 + DT_INTERNAL = 0x00001000 + DT_EDITCONTROL = 0x00002000 + DT_PATH_ELLIPSIS = 0x00004000 + DT_END_ELLIPSIS = 0x00008000 + DT_MODIFYSTRING = 0x00010000 + DT_RTLREADING = 0x00020000 + DT_WORD_ELLIPSIS = 0x00040000 + DT_NOFULLWIDTHCHARBREAK = 0x00080000 + DT_HIDEPREFIX = 0x00100000 + DT_PREFIXONLY = 0x00200000 +) + +const CLR_INVALID = 0xFFFFFFFF + +// Background Modes +const ( + TRANSPARENT = 1 + OPAQUE = 2 + BKMODE_LAST = 2 +) + +// Global Memory Flags +const ( + GMEM_FIXED = 0x0000 + GMEM_MOVEABLE = 0x0002 + GMEM_NOCOMPACT = 0x0010 + GMEM_NODISCARD = 0x0020 + GMEM_ZEROINIT = 0x0040 + GMEM_MODIFY = 0x0080 + GMEM_DISCARDABLE = 0x0100 + GMEM_NOT_BANKED = 0x1000 + GMEM_SHARE = 0x2000 + GMEM_DDESHARE = 0x2000 + GMEM_NOTIFY = 0x4000 + GMEM_LOWER = GMEM_NOT_BANKED + GMEM_VALID_FLAGS = 0x7F72 + GMEM_INVALID_HANDLE = 0x8000 + GHND = (GMEM_MOVEABLE | GMEM_ZEROINIT) + GPTR = (GMEM_FIXED | GMEM_ZEROINIT) +) + +// Ternary raster operations +const ( + SRCCOPY = 0x00CC0020 + SRCPAINT = 0x00EE0086 + SRCAND = 0x008800C6 + SRCINVERT = 0x00660046 + SRCERASE = 0x00440328 + NOTSRCCOPY = 0x00330008 + NOTSRCERASE = 0x001100A6 + MERGECOPY = 0x00C000CA + MERGEPAINT = 0x00BB0226 + PATCOPY = 0x00F00021 + PATPAINT = 0x00FB0A09 + PATINVERT = 0x005A0049 + DSTINVERT = 0x00550009 + BLACKNESS = 0x00000042 + WHITENESS = 0x00FF0062 + NOMIRRORBITMAP = 0x80000000 + CAPTUREBLT = 0x40000000 +) + +// Clipboard formats +const ( + CF_TEXT = 1 + CF_BITMAP = 2 + CF_METAFILEPICT = 3 + CF_SYLK = 4 + CF_DIF = 5 + CF_TIFF = 6 + CF_OEMTEXT = 7 + CF_DIB = 8 + CF_PALETTE = 9 + CF_PENDATA = 10 + CF_RIFF = 11 + CF_WAVE = 12 + CF_UNICODETEXT = 13 + CF_ENHMETAFILE = 14 + CF_HDROP = 15 + CF_LOCALE = 16 + CF_DIBV5 = 17 + CF_MAX = 18 + CF_OWNERDISPLAY = 0x0080 + CF_DSPTEXT = 0x0081 + CF_DSPBITMAP = 0x0082 + CF_DSPMETAFILEPICT = 0x0083 + CF_DSPENHMETAFILE = 0x008E + CF_PRIVATEFIRST = 0x0200 + CF_PRIVATELAST = 0x02FF + CF_GDIOBJFIRST = 0x0300 + CF_GDIOBJLAST = 0x03FF +) + +// Bitmap compression formats +const ( + BI_RGB = 0 + BI_RLE8 = 1 + BI_RLE4 = 2 + BI_BITFIELDS = 3 + BI_JPEG = 4 + BI_PNG = 5 +) + +// SetDIBitsToDevice fuColorUse +const ( + DIB_PAL_COLORS = 1 + DIB_RGB_COLORS = 0 +) + +const ( + STANDARD_RIGHTS_REQUIRED = 0x000F +) + +// Service Control Manager object specific access types +const ( + SC_MANAGER_CONNECT = 0x0001 + SC_MANAGER_CREATE_SERVICE = 0x0002 + SC_MANAGER_ENUMERATE_SERVICE = 0x0004 + SC_MANAGER_LOCK = 0x0008 + SC_MANAGER_QUERY_LOCK_STATUS = 0x0010 + SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020 + SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG +) + +// Service Types (Bit Mask) +const ( + SERVICE_KERNEL_DRIVER = 0x00000001 + SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 + SERVICE_ADAPTER = 0x00000004 + SERVICE_RECOGNIZER_DRIVER = 0x00000008 + SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER + SERVICE_WIN32_OWN_PROCESS = 0x00000010 + SERVICE_WIN32_SHARE_PROCESS = 0x00000020 + SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS + SERVICE_INTERACTIVE_PROCESS = 0x00000100 + SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS +) + +// Service State -- for CurrentState +const ( + SERVICE_STOPPED = 0x00000001 + SERVICE_START_PENDING = 0x00000002 + SERVICE_STOP_PENDING = 0x00000003 + SERVICE_RUNNING = 0x00000004 + SERVICE_CONTINUE_PENDING = 0x00000005 + SERVICE_PAUSE_PENDING = 0x00000006 + SERVICE_PAUSED = 0x00000007 +) + +// Controls Accepted (Bit Mask) +const ( + SERVICE_ACCEPT_STOP = 0x00000001 + SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002 + SERVICE_ACCEPT_SHUTDOWN = 0x00000004 + SERVICE_ACCEPT_PARAMCHANGE = 0x00000008 + SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010 + SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020 + SERVICE_ACCEPT_POWEREVENT = 0x00000040 + SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080 + SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100 + SERVICE_ACCEPT_TIMECHANGE = 0x00000200 + SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400 +) + +// Service object specific access type +const ( + SERVICE_QUERY_CONFIG = 0x0001 + SERVICE_CHANGE_CONFIG = 0x0002 + SERVICE_QUERY_STATUS = 0x0004 + SERVICE_ENUMERATE_DEPENDENTS = 0x0008 + SERVICE_START = 0x0010 + SERVICE_STOP = 0x0020 + SERVICE_PAUSE_CONTINUE = 0x0040 + SERVICE_INTERROGATE = 0x0080 + SERVICE_USER_DEFINED_CONTROL = 0x0100 + + SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | + SERVICE_QUERY_CONFIG | + SERVICE_CHANGE_CONFIG | + SERVICE_QUERY_STATUS | + SERVICE_ENUMERATE_DEPENDENTS | + SERVICE_START | + SERVICE_STOP | + SERVICE_PAUSE_CONTINUE | + SERVICE_INTERROGATE | + SERVICE_USER_DEFINED_CONTROL +) + +// MapVirtualKey maptypes +const ( + MAPVK_VK_TO_CHAR = 2 + MAPVK_VK_TO_VSC = 0 + MAPVK_VSC_TO_VK = 1 + MAPVK_VSC_TO_VK_EX = 3 +) + +// ReadEventLog Flags +const ( + EVENTLOG_SEEK_READ = 0x0002 + EVENTLOG_SEQUENTIAL_READ = 0x0001 + EVENTLOG_FORWARDS_READ = 0x0004 + EVENTLOG_BACKWARDS_READ = 0x0008 +) + +// CreateToolhelp32Snapshot flags +const ( + TH32CS_SNAPHEAPLIST = 0x00000001 + TH32CS_SNAPPROCESS = 0x00000002 + TH32CS_SNAPTHREAD = 0x00000004 + TH32CS_SNAPMODULE = 0x00000008 + TH32CS_SNAPMODULE32 = 0x00000010 + TH32CS_INHERIT = 0x80000000 + TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPMODULE | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD +) + +const ( + MAX_MODULE_NAME32 = 255 + MAX_PATH = 260 +) + +const ( + FOREGROUND_BLUE = 0x0001 + FOREGROUND_GREEN = 0x0002 + FOREGROUND_RED = 0x0004 + FOREGROUND_INTENSITY = 0x0008 + BACKGROUND_BLUE = 0x0010 + BACKGROUND_GREEN = 0x0020 + BACKGROUND_RED = 0x0040 + BACKGROUND_INTENSITY = 0x0080 + COMMON_LVB_LEADING_BYTE = 0x0100 + COMMON_LVB_TRAILING_BYTE = 0x0200 + COMMON_LVB_GRID_HORIZONTAL = 0x0400 + COMMON_LVB_GRID_LVERTICAL = 0x0800 + COMMON_LVB_GRID_RVERTICAL = 0x1000 + COMMON_LVB_REVERSE_VIDEO = 0x4000 + COMMON_LVB_UNDERSCORE = 0x8000 +) + +// Flags used by the DWM_BLURBEHIND structure to indicate +// which of its members contain valid information. +const ( + DWM_BB_ENABLE = 0x00000001 // A value for the fEnable member has been specified. + DWM_BB_BLURREGION = 0x00000002 // A value for the hRgnBlur member has been specified. + DWM_BB_TRANSITIONONMAXIMIZED = 0x00000004 // A value for the fTransitionOnMaximized member has been specified. +) + +// Flags used by the DwmEnableComposition function +// to change the state of Desktop Window Manager (DWM) composition. +const ( + DWM_EC_DISABLECOMPOSITION = 0 // Disable composition + DWM_EC_ENABLECOMPOSITION = 1 // Enable composition +) + +// enum-lite implementation for the following constant structure +type DWM_SHOWCONTACT int32 + +const ( + DWMSC_DOWN = 0x00000001 + DWMSC_UP = 0x00000002 + DWMSC_DRAG = 0x00000004 + DWMSC_HOLD = 0x00000008 + DWMSC_PENBARREL = 0x00000010 + DWMSC_NONE = 0x00000000 + DWMSC_ALL = 0xFFFFFFFF +) + +// enum-lite implementation for the following constant structure +type DWM_SOURCE_FRAME_SAMPLING int32 + +// TODO: need to verify this construction +// Flags used by the DwmSetPresentParameters function +// to specify the frame sampling type +const ( + DWM_SOURCE_FRAME_SAMPLING_POINT = iota + 1 + DWM_SOURCE_FRAME_SAMPLING_COVERAGE + DWM_SOURCE_FRAME_SAMPLING_LAST +) + +// Flags used by the DWM_THUMBNAIL_PROPERTIES structure to +// indicate which of its members contain valid information. +const ( + DWM_TNP_RECTDESTINATION = 0x00000001 // A value for the rcDestination member has been specified + DWM_TNP_RECTSOURCE = 0x00000002 // A value for the rcSource member has been specified + DWM_TNP_OPACITY = 0x00000004 // A value for the opacity member has been specified + DWM_TNP_VISIBLE = 0x00000008 // A value for the fVisible member has been specified + DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010 // A value for the fSourceClientAreaOnly member has been specified +) + +// enum-lite implementation for the following constant structure +type DWMFLIP3DWINDOWPOLICY int32 + +// TODO: need to verify this construction +// Flags used by the DwmSetWindowAttribute function +// to specify the Flip3D window policy +const ( + DWMFLIP3D_DEFAULT = iota + 1 + DWMFLIP3D_EXCLUDEBELOW + DWMFLIP3D_EXCLUDEABOVE + DWMFLIP3D_LAST +) + +// enum-lite implementation for the following constant structure +type DWMNCRENDERINGPOLICY int32 + +// TODO: need to verify this construction +// Flags used by the DwmSetWindowAttribute function +// to specify the non-client area rendering policy +const ( + DWMNCRP_USEWINDOWSTYLE = iota + 1 + DWMNCRP_DISABLED + DWMNCRP_ENABLED + DWMNCRP_LAST +) + +// enum-lite implementation for the following constant structure +type DWMTRANSITION_OWNEDWINDOW_TARGET int32 + +const ( + DWMTRANSITION_OWNEDWINDOW_NULL = -1 + DWMTRANSITION_OWNEDWINDOW_REPOSITION = 0 +) + +// enum-lite implementation for the following constant structure +type DWMWINDOWATTRIBUTE int32 + +// TODO: need to verify this construction +// Flags used by the DwmGetWindowAttribute and DwmSetWindowAttribute functions +// to specify window attributes for non-client rendering +const ( + DWMWA_NCRENDERING_ENABLED = iota + 1 + DWMWA_NCRENDERING_POLICY + DWMWA_TRANSITIONS_FORCEDISABLED + DWMWA_ALLOW_NCPAINT + DWMWA_CAPTION_BUTTON_BOUNDS + DWMWA_NONCLIENT_RTL_LAYOUT + DWMWA_FORCE_ICONIC_REPRESENTATION + DWMWA_FLIP3D_POLICY + DWMWA_EXTENDED_FRAME_BOUNDS + DWMWA_HAS_ICONIC_BITMAP + DWMWA_DISALLOW_PEEK + DWMWA_EXCLUDED_FROM_PEEK + DWMWA_CLOAK + DWMWA_CLOAKED + DWMWA_FREEZE_REPRESENTATION + DWMWA_LAST +) + +// enum-lite implementation for the following constant structure +type GESTURE_TYPE int32 + +// TODO: use iota? +// Identifies the gesture type +const ( + GT_PEN_TAP = 0 + GT_PEN_DOUBLETAP = 1 + GT_PEN_RIGHTTAP = 2 + GT_PEN_PRESSANDHOLD = 3 + GT_PEN_PRESSANDHOLDABORT = 4 + GT_TOUCH_TAP = 5 + GT_TOUCH_DOUBLETAP = 6 + GT_TOUCH_RIGHTTAP = 7 + GT_TOUCH_PRESSANDHOLD = 8 + GT_TOUCH_PRESSANDHOLDABORT = 9 + GT_TOUCH_PRESSANDTAP = 10 +) + +// Icons +const ( + ICON_SMALL = 0 + ICON_BIG = 1 + ICON_SMALL2 = 2 +) + +const ( + SIZE_RESTORED = 0 + SIZE_MINIMIZED = 1 + SIZE_MAXIMIZED = 2 + SIZE_MAXSHOW = 3 + SIZE_MAXHIDE = 4 +) + +// XButton values +const ( + XBUTTON1 = 1 + XBUTTON2 = 2 +) + +// Devmode +const ( + DM_SPECVERSION = 0x0401 + + DM_ORIENTATION = 0x00000001 + DM_PAPERSIZE = 0x00000002 + DM_PAPERLENGTH = 0x00000004 + DM_PAPERWIDTH = 0x00000008 + DM_SCALE = 0x00000010 + DM_POSITION = 0x00000020 + DM_NUP = 0x00000040 + DM_DISPLAYORIENTATION = 0x00000080 + DM_COPIES = 0x00000100 + DM_DEFAULTSOURCE = 0x00000200 + DM_PRINTQUALITY = 0x00000400 + DM_COLOR = 0x00000800 + DM_DUPLEX = 0x00001000 + DM_YRESOLUTION = 0x00002000 + DM_TTOPTION = 0x00004000 + DM_COLLATE = 0x00008000 + DM_FORMNAME = 0x00010000 + DM_LOGPIXELS = 0x00020000 + DM_BITSPERPEL = 0x00040000 + DM_PELSWIDTH = 0x00080000 + DM_PELSHEIGHT = 0x00100000 + DM_DISPLAYFLAGS = 0x00200000 + DM_DISPLAYFREQUENCY = 0x00400000 + DM_ICMMETHOD = 0x00800000 + DM_ICMINTENT = 0x01000000 + DM_MEDIATYPE = 0x02000000 + DM_DITHERTYPE = 0x04000000 + DM_PANNINGWIDTH = 0x08000000 + DM_PANNINGHEIGHT = 0x10000000 + DM_DISPLAYFIXEDOUTPUT = 0x20000000 +) + +// ChangeDisplaySettings +const ( + CDS_UPDATEREGISTRY = 0x00000001 + CDS_TEST = 0x00000002 + CDS_FULLSCREEN = 0x00000004 + CDS_GLOBAL = 0x00000008 + CDS_SET_PRIMARY = 0x00000010 + CDS_VIDEOPARAMETERS = 0x00000020 + CDS_RESET = 0x40000000 + CDS_NORESET = 0x10000000 + + DISP_CHANGE_SUCCESSFUL = 0 + DISP_CHANGE_RESTART = 1 + DISP_CHANGE_FAILED = -1 + DISP_CHANGE_BADMODE = -2 + DISP_CHANGE_NOTUPDATED = -3 + DISP_CHANGE_BADFLAGS = -4 + DISP_CHANGE_BADPARAM = -5 + DISP_CHANGE_BADDUALVIEW = -6 +) + +const ( + ENUM_CURRENT_SETTINGS = 0xFFFFFFFF + ENUM_REGISTRY_SETTINGS = 0xFFFFFFFE +) + +// PIXELFORMATDESCRIPTOR +const ( + PFD_TYPE_RGBA = 0 + PFD_TYPE_COLORINDEX = 1 + + PFD_MAIN_PLANE = 0 + PFD_OVERLAY_PLANE = 1 + PFD_UNDERLAY_PLANE = -1 + + PFD_DOUBLEBUFFER = 0x00000001 + PFD_STEREO = 0x00000002 + PFD_DRAW_TO_WINDOW = 0x00000004 + PFD_DRAW_TO_BITMAP = 0x00000008 + PFD_SUPPORT_GDI = 0x00000010 + PFD_SUPPORT_OPENGL = 0x00000020 + PFD_GENERIC_FORMAT = 0x00000040 + PFD_NEED_PALETTE = 0x00000080 + PFD_NEED_SYSTEM_PALETTE = 0x00000100 + PFD_SWAP_EXCHANGE = 0x00000200 + PFD_SWAP_COPY = 0x00000400 + PFD_SWAP_LAYER_BUFFERS = 0x00000800 + PFD_GENERIC_ACCELERATED = 0x00001000 + PFD_SUPPORT_DIRECTDRAW = 0x00002000 + PFD_DIRECT3D_ACCELERATED = 0x00004000 + PFD_SUPPORT_COMPOSITION = 0x00008000 + + PFD_DEPTH_DONTCARE = 0x20000000 + PFD_DOUBLEBUFFER_DONTCARE = 0x40000000 + PFD_STEREO_DONTCARE = 0x80000000 +) + +const ( + INPUT_MOUSE = 0 + INPUT_KEYBOARD = 1 + INPUT_HARDWARE = 2 +) + +const ( + MOUSEEVENTF_ABSOLUTE = 0x8000 + MOUSEEVENTF_HWHEEL = 0x01000 + MOUSEEVENTF_MOVE = 0x0001 + MOUSEEVENTF_MOVE_NOCOALESCE = 0x2000 + MOUSEEVENTF_LEFTDOWN = 0x0002 + MOUSEEVENTF_LEFTUP = 0x0004 + MOUSEEVENTF_RIGHTDOWN = 0x0008 + MOUSEEVENTF_RIGHTUP = 0x0010 + MOUSEEVENTF_MIDDLEDOWN = 0x0020 + MOUSEEVENTF_MIDDLEUP = 0x0040 + MOUSEEVENTF_VIRTUALDESK = 0x4000 + MOUSEEVENTF_WHEEL = 0x0800 + MOUSEEVENTF_XDOWN = 0x0080 + MOUSEEVENTF_XUP = 0x0100 +) + +// Windows Hooks (WH_*) +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx +const ( + WH_CALLWNDPROC = 4 + WH_CALLWNDPROCRET = 12 + WH_CBT = 5 + WH_DEBUG = 9 + WH_FOREGROUNDIDLE = 11 + WH_GETMESSAGE = 3 + WH_JOURNALPLAYBACK = 1 + WH_JOURNALRECORD = 0 + WH_KEYBOARD = 2 + WH_KEYBOARD_LL = 13 + WH_MOUSE = 7 + WH_MOUSE_LL = 14 + WH_MSGFILTER = -1 + WH_SHELL = 10 + WH_SYSMSGFILTER = 6 +) + +// ComboBox return values +const ( + CB_OKAY = 0 + CB_ERR = ^uintptr(0) // -1 + CB_ERRSPACE = ^uintptr(1) // -2 +) + +// ComboBox notifications +const ( + CBN_ERRSPACE = -1 + CBN_SELCHANGE = 1 + CBN_DBLCLK = 2 + CBN_SETFOCUS = 3 + CBN_KILLFOCUS = 4 + CBN_EDITCHANGE = 5 + CBN_EDITUPDATE = 6 + CBN_DROPDOWN = 7 + CBN_CLOSEUP = 8 + CBN_SELENDOK = 9 + CBN_SELENDCANCEL = 10 +) + +// ComboBox styles +const ( + CBS_SIMPLE = 0x0001 + CBS_DROPDOWN = 0x0002 + CBS_DROPDOWNLIST = 0x0003 + CBS_OWNERDRAWFIXED = 0x0010 + CBS_OWNERDRAWVARIABLE = 0x0020 + CBS_AUTOHSCROLL = 0x0040 + CBS_OEMCONVERT = 0x0080 + CBS_SORT = 0x0100 + CBS_HASSTRINGS = 0x0200 + CBS_NOINTEGRALHEIGHT = 0x0400 + CBS_DISABLENOSCROLL = 0x0800 + CBS_UPPERCASE = 0x2000 + CBS_LOWERCASE = 0x4000 +) + +// ComboBox messages +const ( + CB_GETEDITSEL = 0x0140 + CB_LIMITTEXT = 0x0141 + CB_SETEDITSEL = 0x0142 + CB_ADDSTRING = 0x0143 + CB_DELETESTRING = 0x0144 + CB_DIR = 0x0145 + CB_GETCOUNT = 0x0146 + CB_GETCURSEL = 0x0147 + CB_GETLBTEXT = 0x0148 + CB_GETLBTEXTLEN = 0x0149 + CB_INSERTSTRING = 0x014A + CB_RESETCONTENT = 0x014B + CB_FINDSTRING = 0x014C + CB_SELECTSTRING = 0x014D + CB_SETCURSEL = 0x014E + CB_SHOWDROPDOWN = 0x014F + CB_GETITEMDATA = 0x0150 + CB_SETITEMDATA = 0x0151 + CB_GETDROPPEDCONTROLRECT = 0x0152 + CB_SETITEMHEIGHT = 0x0153 + CB_GETITEMHEIGHT = 0x0154 + CB_SETEXTENDEDUI = 0x0155 + CB_GETEXTENDEDUI = 0x0156 + CB_GETDROPPEDSTATE = 0x0157 + CB_FINDSTRINGEXACT = 0x0158 + CB_SETLOCALE = 0x0159 + CB_GETLOCALE = 0x015A + CB_GETTOPINDEX = 0x015b + CB_SETTOPINDEX = 0x015c + CB_GETHORIZONTALEXTENT = 0x015d + CB_SETHORIZONTALEXTENT = 0x015e + CB_GETDROPPEDWIDTH = 0x015f + CB_SETDROPPEDWIDTH = 0x0160 + CB_INITSTORAGE = 0x0161 + CB_MULTIPLEADDSTRING = 0x0163 + CB_GETCOMBOBOXINFO = 0x0164 +) + +// TreeView styles +const ( + TVS_HASBUTTONS = 0x0001 + TVS_HASLINES = 0x0002 + TVS_LINESATROOT = 0x0004 + TVS_EDITLABELS = 0x0008 + TVS_DISABLEDRAGDROP = 0x0010 + TVS_SHOWSELALWAYS = 0x0020 + TVS_RTLREADING = 0x0040 + TVS_NOTOOLTIPS = 0x0080 + TVS_CHECKBOXES = 0x0100 + TVS_TRACKSELECT = 0x0200 + TVS_SINGLEEXPAND = 0x0400 + TVS_INFOTIP = 0x0800 + TVS_FULLROWSELECT = 0x1000 + TVS_NOSCROLL = 0x2000 + TVS_NONEVENHEIGHT = 0x4000 + TVS_NOHSCROLL = 0x8000 +) + +const ( + TVS_EX_NOSINGLECOLLAPSE = 0x0001 + TVS_EX_MULTISELECT = 0x0002 + TVS_EX_DOUBLEBUFFER = 0x0004 + TVS_EX_NOINDENTSTATE = 0x0008 + TVS_EX_RICHTOOLTIP = 0x0010 + TVS_EX_AUTOHSCROLL = 0x0020 + TVS_EX_FADEINOUTEXPANDOS = 0x0040 + TVS_EX_PARTIALCHECKBOXES = 0x0080 + TVS_EX_EXCLUSIONCHECKBOXES = 0x0100 + TVS_EX_DIMMEDCHECKBOXES = 0x0200 + TVS_EX_DRAWIMAGEASYNC = 0x0400 +) + +const ( + TVIF_TEXT = 0x0001 + TVIF_IMAGE = 0x0002 + TVIF_PARAM = 0x0004 + TVIF_STATE = 0x0008 + TVIF_HANDLE = 0x0010 + TVIF_SELECTEDIMAGE = 0x0020 + TVIF_CHILDREN = 0x0040 + TVIF_INTEGRAL = 0x0080 + TVIF_STATEEX = 0x0100 + TVIF_EXPANDEDIMAGE = 0x0200 +) + +const ( + TVIS_SELECTED = 0x0002 + TVIS_CUT = 0x0004 + TVIS_DROPHILITED = 0x0008 + TVIS_BOLD = 0x0010 + TVIS_EXPANDED = 0x0020 + TVIS_EXPANDEDONCE = 0x0040 + TVIS_EXPANDPARTIAL = 0x0080 + TVIS_OVERLAYMASK = 0x0F00 + TVIS_STATEIMAGEMASK = 0xF000 + TVIS_USERMASK = 0xF000 +) + +const ( + TVIS_EX_FLAT = 0x0001 + TVIS_EX_DISABLED = 0x0002 + TVIS_EX_ALL = 0x0002 +) + +const ( + TVI_ROOT = ^HTREEITEM(0xffff) + TVI_FIRST = ^HTREEITEM(0xfffe) + TVI_LAST = ^HTREEITEM(0xfffd) + TVI_SORT = ^HTREEITEM(0xfffc) +) + +// TVM_EXPAND action flags +const ( + TVE_COLLAPSE = 0x0001 + TVE_EXPAND = 0x0002 + TVE_TOGGLE = 0x0003 + TVE_EXPANDPARTIAL = 0x4000 + TVE_COLLAPSERESET = 0x8000 +) + +const ( + TVGN_CARET = 9 +) + +// TreeView messages +const ( + TV_FIRST = 0x1100 + + TVM_INSERTITEM = TV_FIRST + 50 + TVM_DELETEITEM = TV_FIRST + 1 + TVM_EXPAND = TV_FIRST + 2 + TVM_GETITEMRECT = TV_FIRST + 4 + TVM_GETCOUNT = TV_FIRST + 5 + TVM_GETINDENT = TV_FIRST + 6 + TVM_SETINDENT = TV_FIRST + 7 + TVM_GETIMAGELIST = TV_FIRST + 8 + TVM_SETIMAGELIST = TV_FIRST + 9 + TVM_GETNEXTITEM = TV_FIRST + 10 + TVM_SELECTITEM = TV_FIRST + 11 + TVM_GETITEM = TV_FIRST + 62 + TVM_SETITEM = TV_FIRST + 63 + TVM_EDITLABEL = TV_FIRST + 65 + TVM_GETEDITCONTROL = TV_FIRST + 15 + TVM_GETVISIBLECOUNT = TV_FIRST + 16 + TVM_HITTEST = TV_FIRST + 17 + TVM_CREATEDRAGIMAGE = TV_FIRST + 18 + TVM_SORTCHILDREN = TV_FIRST + 19 + TVM_ENSUREVISIBLE = TV_FIRST + 20 + TVM_SORTCHILDRENCB = TV_FIRST + 21 + TVM_ENDEDITLABELNOW = TV_FIRST + 22 + TVM_GETISEARCHSTRING = TV_FIRST + 64 + TVM_SETTOOLTIPS = TV_FIRST + 24 + TVM_GETTOOLTIPS = TV_FIRST + 25 + TVM_SETINSERTMARK = TV_FIRST + 26 + TVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT + TVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT + TVM_SETITEMHEIGHT = TV_FIRST + 27 + TVM_GETITEMHEIGHT = TV_FIRST + 28 + TVM_SETBKCOLOR = TV_FIRST + 29 + TVM_SETTEXTCOLOR = TV_FIRST + 30 + TVM_GETBKCOLOR = TV_FIRST + 31 + TVM_GETTEXTCOLOR = TV_FIRST + 32 + TVM_SETSCROLLTIME = TV_FIRST + 33 + TVM_GETSCROLLTIME = TV_FIRST + 34 + TVM_SETINSERTMARKCOLOR = TV_FIRST + 37 + TVM_GETINSERTMARKCOLOR = TV_FIRST + 38 + TVM_GETITEMSTATE = TV_FIRST + 39 + TVM_SETLINECOLOR = TV_FIRST + 40 + TVM_GETLINECOLOR = TV_FIRST + 41 + TVM_MAPACCIDTOHTREEITEM = TV_FIRST + 42 + TVM_MAPHTREEITEMTOACCID = TV_FIRST + 43 + TVM_SETEXTENDEDSTYLE = TV_FIRST + 44 + TVM_GETEXTENDEDSTYLE = TV_FIRST + 45 + TVM_SETAUTOSCROLLINFO = TV_FIRST + 59 +) + +// TreeView notifications +const ( + TVN_FIRST = ^uint32(399) + + TVN_SELCHANGING = TVN_FIRST - 50 + TVN_SELCHANGED = TVN_FIRST - 51 + TVN_GETDISPINFO = TVN_FIRST - 52 + TVN_ITEMEXPANDING = TVN_FIRST - 54 + TVN_ITEMEXPANDED = TVN_FIRST - 55 + TVN_BEGINDRAG = TVN_FIRST - 56 + TVN_BEGINRDRAG = TVN_FIRST - 57 + TVN_DELETEITEM = TVN_FIRST - 58 + TVN_BEGINLABELEDIT = TVN_FIRST - 59 + TVN_ENDLABELEDIT = TVN_FIRST - 60 + TVN_KEYDOWN = TVN_FIRST - 12 + TVN_GETINFOTIP = TVN_FIRST - 14 + TVN_SINGLEEXPAND = TVN_FIRST - 15 + TVN_ITEMCHANGING = TVN_FIRST - 17 + TVN_ITEMCHANGED = TVN_FIRST - 19 + TVN_ASYNCDRAW = TVN_FIRST - 20 +) + +// TreeView hit test constants +const ( + TVHT_NOWHERE = 1 + TVHT_ONITEMICON = 2 + TVHT_ONITEMLABEL = 4 + TVHT_ONITEM = TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON + TVHT_ONITEMINDENT = 8 + TVHT_ONITEMBUTTON = 16 + TVHT_ONITEMRIGHT = 32 + TVHT_ONITEMSTATEICON = 64 + TVHT_ABOVE = 256 + TVHT_BELOW = 512 + TVHT_TORIGHT = 1024 + TVHT_TOLEFT = 2048 +) + +type HTREEITEM HANDLE + +type TVITEM struct { + Mask uint32 + HItem HTREEITEM + State uint32 + StateMask uint32 + PszText uintptr + CchTextMax int32 + IImage int32 + ISelectedImage int32 + CChildren int32 + LParam uintptr +} + +/*type TVITEMEX struct { + mask UINT + hItem HTREEITEM + state UINT + stateMask UINT + pszText LPWSTR + cchTextMax int + iImage int + iSelectedImage int + cChildren int + lParam LPARAM + iIntegral int + uStateEx UINT + hwnd HWND + iExpandedImage int +}*/ + +type TVINSERTSTRUCT struct { + HParent HTREEITEM + HInsertAfter HTREEITEM + Item TVITEM + // itemex TVITEMEX +} + +type NMTREEVIEW struct { + Hdr NMHDR + Action uint32 + ItemOld TVITEM + ItemNew TVITEM + PtDrag POINT +} + +type NMTVDISPINFO struct { + Hdr NMHDR + Item TVITEM +} + +type NMTVKEYDOWN struct { + Hdr NMHDR + WVKey uint16 + Flags uint32 +} + +type TVHITTESTINFO struct { + Pt POINT + Flags uint32 + HItem HTREEITEM +} + +// TabPage support + +const TCM_FIRST = 0x1300 +const TCN_FIRST = -550 + +const ( + TCS_SCROLLOPPOSITE = 0x0001 + TCS_BOTTOM = 0x0002 + TCS_RIGHT = 0x0002 + TCS_MULTISELECT = 0x0004 + TCS_FLATBUTTONS = 0x0008 + TCS_FORCEICONLEFT = 0x0010 + TCS_FORCELABELLEFT = 0x0020 + TCS_HOTTRACK = 0x0040 + TCS_VERTICAL = 0x0080 + TCS_TABS = 0x0000 + TCS_BUTTONS = 0x0100 + TCS_SINGLELINE = 0x0000 + TCS_MULTILINE = 0x0200 + TCS_RIGHTJUSTIFY = 0x0000 + TCS_FIXEDWIDTH = 0x0400 + TCS_RAGGEDRIGHT = 0x0800 + TCS_FOCUSONBUTTONDOWN = 0x1000 + TCS_OWNERDRAWFIXED = 0x2000 + TCS_TOOLTIPS = 0x4000 + TCS_FOCUSNEVER = 0x8000 +) + +const ( + TCS_EX_FLATSEPARATORS = 0x00000001 + TCS_EX_REGISTERDROP = 0x00000002 +) + +const ( + TCM_GETIMAGELIST = TCM_FIRST + 2 + TCM_SETIMAGELIST = TCM_FIRST + 3 + TCM_GETITEMCOUNT = TCM_FIRST + 4 + TCM_GETITEM = TCM_FIRST + 60 + TCM_SETITEM = TCM_FIRST + 61 + TCM_INSERTITEM = TCM_FIRST + 62 + TCM_DELETEITEM = TCM_FIRST + 8 + TCM_DELETEALLITEMS = TCM_FIRST + 9 + TCM_GETITEMRECT = TCM_FIRST + 10 + TCM_GETCURSEL = TCM_FIRST + 11 + TCM_SETCURSEL = TCM_FIRST + 12 + TCM_HITTEST = TCM_FIRST + 13 + TCM_SETITEMEXTRA = TCM_FIRST + 14 + TCM_ADJUSTRECT = TCM_FIRST + 40 + TCM_SETITEMSIZE = TCM_FIRST + 41 + TCM_REMOVEIMAGE = TCM_FIRST + 42 + TCM_SETPADDING = TCM_FIRST + 43 + TCM_GETROWCOUNT = TCM_FIRST + 44 + TCM_GETTOOLTIPS = TCM_FIRST + 45 + TCM_SETTOOLTIPS = TCM_FIRST + 46 + TCM_GETCURFOCUS = TCM_FIRST + 47 + TCM_SETCURFOCUS = TCM_FIRST + 48 + TCM_SETMINTABWIDTH = TCM_FIRST + 49 + TCM_DESELECTALL = TCM_FIRST + 50 + TCM_HIGHLIGHTITEM = TCM_FIRST + 51 + TCM_SETEXTENDEDSTYLE = TCM_FIRST + 52 + TCM_GETEXTENDEDSTYLE = TCM_FIRST + 53 + TCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT + TCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +) + +const ( + TCIF_TEXT = 0x0001 + TCIF_IMAGE = 0x0002 + TCIF_RTLREADING = 0x0004 + TCIF_PARAM = 0x0008 + TCIF_STATE = 0x0010 +) + +const ( + TCIS_BUTTONPRESSED = 0x0001 + TCIS_HIGHLIGHTED = 0x0002 +) + +const ( + TCHT_NOWHERE = 0x0001 + TCHT_ONITEMICON = 0x0002 + TCHT_ONITEMLABEL = 0x0004 + TCHT_ONITEM = TCHT_ONITEMICON | TCHT_ONITEMLABEL +) + +const ( + TCN_KEYDOWN = TCN_FIRST - 0 + TCN_SELCHANGE = TCN_FIRST - 1 + TCN_SELCHANGING = TCN_FIRST - 2 + TCN_GETOBJECT = TCN_FIRST - 3 + TCN_FOCUSCHANGE = TCN_FIRST - 4 +) + +type TCITEMHEADER struct { + Mask uint32 + LpReserved1 uint32 + LpReserved2 uint32 + PszText *uint16 + CchTextMax int32 + IImage int32 +} + +type TCITEM struct { + Mask uint32 + DwState uint32 + DwStateMask uint32 + PszText *uint16 + CchTextMax int32 + IImage int32 + LParam uintptr +} + +type TCHITTESTINFO struct { + Pt POINT + flags uint32 +} + +type NMTCKEYDOWN struct { + Hdr NMHDR + WVKey uint16 + Flags uint32 +} + +// Menu support constants + +// Constants for MENUITEMINFO.fMask +const ( + MIIM_STATE = 1 + MIIM_ID = 2 + MIIM_SUBMENU = 4 + MIIM_CHECKMARKS = 8 + MIIM_TYPE = 16 + MIIM_DATA = 32 + MIIM_STRING = 64 + MIIM_BITMAP = 128 + MIIM_FTYPE = 256 +) + +// Constants for MENUITEMINFO.fType +const ( + MFT_BITMAP = 4 + MFT_MENUBARBREAK = 32 + MFT_MENUBREAK = 64 + MFT_OWNERDRAW = 256 + MFT_RADIOCHECK = 512 + MFT_RIGHTJUSTIFY = 0x4000 + MFT_SEPARATOR = 0x800 + MFT_RIGHTORDER = 0x2000 + MFT_STRING = 0 +) + +// Constants for MENUITEMINFO.fState +const ( + MFS_CHECKED = 8 + MFS_DEFAULT = 4096 + MFS_DISABLED = 3 + MFS_ENABLED = 0 + MFS_GRAYED = 3 + MFS_HILITE = 128 + MFS_UNCHECKED = 0 + MFS_UNHILITE = 0 +) + +// Constants for MENUITEMINFO.hbmp* +const ( + HBMMENU_CALLBACK = -1 + HBMMENU_SYSTEM = 1 + HBMMENU_MBAR_RESTORE = 2 + HBMMENU_MBAR_MINIMIZE = 3 + HBMMENU_MBAR_CLOSE = 5 + HBMMENU_MBAR_CLOSE_D = 6 + HBMMENU_MBAR_MINIMIZE_D = 7 + HBMMENU_POPUP_CLOSE = 8 + HBMMENU_POPUP_RESTORE = 9 + HBMMENU_POPUP_MAXIMIZE = 10 + HBMMENU_POPUP_MINIMIZE = 11 +) + +// MENUINFO mask constants +const ( + MIM_APPLYTOSUBMENUS = 0x80000000 + MIM_BACKGROUND = 0x00000002 + MIM_HELPID = 0x00000004 + MIM_MAXHEIGHT = 0x00000001 + MIM_MENUDATA = 0x00000008 + MIM_STYLE = 0x00000010 +) + +// MENUINFO style constants +const ( + MNS_AUTODISMISS = 0x10000000 + MNS_CHECKORBMP = 0x04000000 + MNS_DRAGDROP = 0x20000000 + MNS_MODELESS = 0x40000000 + MNS_NOCHECK = 0x80000000 + MNS_NOTIFYBYPOS = 0x08000000 +) + +const ( + MF_BYCOMMAND = 0x00000000 + MF_BYPOSITION = 0x00000400 +) + +type MENUITEMINFO struct { + CbSize uint32 + FMask uint32 + FType uint32 + FState uint32 + WID uint32 + HSubMenu HMENU + HbmpChecked HBITMAP + HbmpUnchecked HBITMAP + DwItemData uintptr + DwTypeData *uint16 + Cch uint32 + HbmpItem HBITMAP +} + +type MENUINFO struct { + CbSize uint32 + FMask uint32 + DwStyle uint32 + CyMax uint32 + HbrBack HBRUSH + DwContextHelpID uint32 + DwMenuData uintptr +} + +// UI state constants +const ( + UIS_SET = 1 + UIS_CLEAR = 2 + UIS_INITIALIZE = 3 +) + +// UI state constants +const ( + UISF_HIDEFOCUS = 0x1 + UISF_HIDEACCEL = 0x2 + UISF_ACTIVE = 0x4 +) + +// Virtual key codes +const ( + VK_LBUTTON = 1 + VK_RBUTTON = 2 + VK_CANCEL = 3 + VK_MBUTTON = 4 + VK_XBUTTON1 = 5 + VK_XBUTTON2 = 6 + VK_BACK = 8 + VK_TAB = 9 + VK_CLEAR = 12 + VK_RETURN = 13 + VK_SHIFT = 16 + VK_CONTROL = 17 + VK_MENU = 18 + VK_PAUSE = 19 + VK_CAPITAL = 20 + VK_KANA = 0x15 + VK_HANGEUL = 0x15 + VK_HANGUL = 0x15 + VK_JUNJA = 0x17 + VK_FINAL = 0x18 + VK_HANJA = 0x19 + VK_KANJI = 0x19 + VK_ESCAPE = 0x1B + VK_CONVERT = 0x1C + VK_NONCONVERT = 0x1D + VK_ACCEPT = 0x1E + VK_MODECHANGE = 0x1F + VK_SPACE = 32 + VK_PRIOR = 33 + VK_NEXT = 34 + VK_END = 35 + VK_HOME = 36 + VK_LEFT = 37 + VK_UP = 38 + VK_RIGHT = 39 + VK_DOWN = 40 + VK_SELECT = 41 + VK_PRINT = 42 + VK_EXECUTE = 43 + VK_SNAPSHOT = 44 + VK_INSERT = 45 + VK_DELETE = 46 + VK_HELP = 47 + VK_LWIN = 0x5B + VK_RWIN = 0x5C + VK_APPS = 0x5D + VK_SLEEP = 0x5F + VK_NUMPAD0 = 0x60 + VK_NUMPAD1 = 0x61 + VK_NUMPAD2 = 0x62 + VK_NUMPAD3 = 0x63 + VK_NUMPAD4 = 0x64 + VK_NUMPAD5 = 0x65 + VK_NUMPAD6 = 0x66 + VK_NUMPAD7 = 0x67 + VK_NUMPAD8 = 0x68 + VK_NUMPAD9 = 0x69 + VK_MULTIPLY = 0x6A + VK_ADD = 0x6B + VK_SEPARATOR = 0x6C + VK_SUBTRACT = 0x6D + VK_DECIMAL = 0x6E + VK_DIVIDE = 0x6F + VK_F1 = 0x70 + VK_F2 = 0x71 + VK_F3 = 0x72 + VK_F4 = 0x73 + VK_F5 = 0x74 + VK_F6 = 0x75 + VK_F7 = 0x76 + VK_F8 = 0x77 + VK_F9 = 0x78 + VK_F10 = 0x79 + VK_F11 = 0x7A + VK_F12 = 0x7B + VK_F13 = 0x7C + VK_F14 = 0x7D + VK_F15 = 0x7E + VK_F16 = 0x7F + VK_F17 = 0x80 + VK_F18 = 0x81 + VK_F19 = 0x82 + VK_F20 = 0x83 + VK_F21 = 0x84 + VK_F22 = 0x85 + VK_F23 = 0x86 + VK_F24 = 0x87 + VK_NUMLOCK = 0x90 + VK_SCROLL = 0x91 + VK_LSHIFT = 0xA0 + VK_RSHIFT = 0xA1 + VK_LCONTROL = 0xA2 + VK_RCONTROL = 0xA3 + VK_LMENU = 0xA4 + VK_RMENU = 0xA5 + VK_BROWSER_BACK = 0xA6 + VK_BROWSER_FORWARD = 0xA7 + VK_BROWSER_REFRESH = 0xA8 + VK_BROWSER_STOP = 0xA9 + VK_BROWSER_SEARCH = 0xAA + VK_BROWSER_FAVORITES = 0xAB + VK_BROWSER_HOME = 0xAC + VK_VOLUME_MUTE = 0xAD + VK_VOLUME_DOWN = 0xAE + VK_VOLUME_UP = 0xAF + VK_MEDIA_NEXT_TRACK = 0xB0 + VK_MEDIA_PREV_TRACK = 0xB1 + VK_MEDIA_STOP = 0xB2 + VK_MEDIA_PLAY_PAUSE = 0xB3 + VK_LAUNCH_MAIL = 0xB4 + VK_LAUNCH_MEDIA_SELECT = 0xB5 + VK_LAUNCH_APP1 = 0xB6 + VK_LAUNCH_APP2 = 0xB7 + VK_OEM_1 = 0xBA + VK_OEM_PLUS = 0xBB + VK_OEM_COMMA = 0xBC + VK_OEM_MINUS = 0xBD + VK_OEM_PERIOD = 0xBE + VK_OEM_2 = 0xBF + VK_OEM_3 = 0xC0 + VK_OEM_4 = 0xDB + VK_OEM_5 = 0xDC + VK_OEM_6 = 0xDD + VK_OEM_7 = 0xDE + VK_OEM_8 = 0xDF + VK_OEM_102 = 0xE2 + VK_PROCESSKEY = 0xE5 + VK_PACKET = 0xE7 + VK_ATTN = 0xF6 + VK_CRSEL = 0xF7 + VK_EXSEL = 0xF8 + VK_EREOF = 0xF9 + VK_PLAY = 0xFA + VK_ZOOM = 0xFB + VK_NONAME = 0xFC + VK_PA1 = 0xFD + VK_OEM_CLEAR = 0xFE +) + +// ScrollBar constants +const ( + SB_HORZ = 0 + SB_VERT = 1 + SB_CTL = 2 + SB_BOTH = 3 +) + +// ScrollBar commands +const ( + SB_LINEUP = 0 + SB_LINELEFT = 0 + SB_LINEDOWN = 1 + SB_LINERIGHT = 1 + SB_PAGEUP = 2 + SB_PAGELEFT = 2 + SB_PAGEDOWN = 3 + SB_PAGERIGHT = 3 + SB_THUMBPOSITION = 4 + SB_THUMBTRACK = 5 + SB_TOP = 6 + SB_LEFT = 6 + SB_BOTTOM = 7 + SB_RIGHT = 7 + SB_ENDSCROLL = 8 +) + +// [Get|Set]ScrollInfo mask constants +const ( + SIF_RANGE = 1 + SIF_PAGE = 2 + SIF_POS = 4 + SIF_DISABLENOSCROLL = 8 + SIF_TRACKPOS = 16 + SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS +) diff --git a/v2/internal/frontend/desktop/windows/winc/w32/dwmapi.go b/v2/internal/frontend/desktop/windows/winc/w32/dwmapi.go new file mode 100644 index 000000000..56545a943 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/dwmapi.go @@ -0,0 +1,18 @@ +package w32 + +import "syscall" + +var ( + moddwmapi = syscall.NewLazyDLL("dwmapi.dll") + + procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") +) + +func DwmSetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute LPCVOID, cbAttribute uint32) HRESULT { + ret, _, _ := procDwmSetWindowAttribute.Call( + hwnd, + uintptr(dwAttribute), + uintptr(pvAttribute), + uintptr(cbAttribute)) + return HRESULT(ret) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/gdi32.go b/v2/internal/frontend/desktop/windows/winc/w32/gdi32.go new file mode 100644 index 000000000..f54c0b536 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/gdi32.go @@ -0,0 +1,525 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modgdi32 = syscall.NewLazyDLL("gdi32.dll") + + procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps") + procDeleteObject = modgdi32.NewProc("DeleteObject") + procCreateFontIndirect = modgdi32.NewProc("CreateFontIndirectW") + procAbortDoc = modgdi32.NewProc("AbortDoc") + procBitBlt = modgdi32.NewProc("BitBlt") + procPatBlt = modgdi32.NewProc("PatBlt") + procCloseEnhMetaFile = modgdi32.NewProc("CloseEnhMetaFile") + procCopyEnhMetaFile = modgdi32.NewProc("CopyEnhMetaFileW") + procCreateBrushIndirect = modgdi32.NewProc("CreateBrushIndirect") + procCreateCompatibleDC = modgdi32.NewProc("CreateCompatibleDC") + procCreateDC = modgdi32.NewProc("CreateDCW") + procCreateDIBSection = modgdi32.NewProc("CreateDIBSection") + procCreateEnhMetaFile = modgdi32.NewProc("CreateEnhMetaFileW") + procCreateIC = modgdi32.NewProc("CreateICW") + procDeleteDC = modgdi32.NewProc("DeleteDC") + procDeleteEnhMetaFile = modgdi32.NewProc("DeleteEnhMetaFile") + procEllipse = modgdi32.NewProc("Ellipse") + procEndDoc = modgdi32.NewProc("EndDoc") + procEndPage = modgdi32.NewProc("EndPage") + procExtCreatePen = modgdi32.NewProc("ExtCreatePen") + procGetEnhMetaFile = modgdi32.NewProc("GetEnhMetaFileW") + procGetEnhMetaFileHeader = modgdi32.NewProc("GetEnhMetaFileHeader") + procGetObject = modgdi32.NewProc("GetObjectW") + procGetStockObject = modgdi32.NewProc("GetStockObject") + procGetTextExtentExPoint = modgdi32.NewProc("GetTextExtentExPointW") + procGetTextExtentPoint32 = modgdi32.NewProc("GetTextExtentPoint32W") + procGetTextMetrics = modgdi32.NewProc("GetTextMetricsW") + procLineTo = modgdi32.NewProc("LineTo") + procMoveToEx = modgdi32.NewProc("MoveToEx") + procPlayEnhMetaFile = modgdi32.NewProc("PlayEnhMetaFile") + procRectangle = modgdi32.NewProc("Rectangle") + procResetDC = modgdi32.NewProc("ResetDCW") + procSelectObject = modgdi32.NewProc("SelectObject") + procSetBkMode = modgdi32.NewProc("SetBkMode") + procSetBrushOrgEx = modgdi32.NewProc("SetBrushOrgEx") + procSetStretchBltMode = modgdi32.NewProc("SetStretchBltMode") + procSetTextColor = modgdi32.NewProc("SetTextColor") + procSetBkColor = modgdi32.NewProc("SetBkColor") + procStartDoc = modgdi32.NewProc("StartDocW") + procStartPage = modgdi32.NewProc("StartPage") + procStretchBlt = modgdi32.NewProc("StretchBlt") + procSetDIBitsToDevice = modgdi32.NewProc("SetDIBitsToDevice") + procChoosePixelFormat = modgdi32.NewProc("ChoosePixelFormat") + procDescribePixelFormat = modgdi32.NewProc("DescribePixelFormat") + procGetEnhMetaFilePixelFormat = modgdi32.NewProc("GetEnhMetaFilePixelFormat") + procGetPixelFormat = modgdi32.NewProc("GetPixelFormat") + procSetPixelFormat = modgdi32.NewProc("SetPixelFormat") + procSwapBuffers = modgdi32.NewProc("SwapBuffers") +) + +func GetDeviceCaps(hdc HDC, index int) int { + ret, _, _ := procGetDeviceCaps.Call( + uintptr(hdc), + uintptr(index)) + + return int(ret) +} + +func DeleteObject(hObject HGDIOBJ) bool { + ret, _, _ := procDeleteObject.Call( + uintptr(hObject)) + + return ret != 0 +} + +func CreateFontIndirect(logFont *LOGFONT) HFONT { + ret, _, _ := procCreateFontIndirect.Call( + uintptr(unsafe.Pointer(logFont))) + + return HFONT(ret) +} + +func AbortDoc(hdc HDC) int { + ret, _, _ := procAbortDoc.Call( + uintptr(hdc)) + + return int(ret) +} + +func BitBlt(hdcDest HDC, nXDest, nYDest, nWidth, nHeight int, hdcSrc HDC, nXSrc, nYSrc int, dwRop uint) { + ret, _, _ := procBitBlt.Call( + uintptr(hdcDest), + uintptr(nXDest), + uintptr(nYDest), + uintptr(nWidth), + uintptr(nHeight), + uintptr(hdcSrc), + uintptr(nXSrc), + uintptr(nYSrc), + uintptr(dwRop)) + + if ret == 0 { + panic("BitBlt failed") + } +} + +func PatBlt(hdc HDC, nXLeft, nYLeft, nWidth, nHeight int, dwRop uint) { + ret, _, _ := procPatBlt.Call( + uintptr(hdc), + uintptr(nXLeft), + uintptr(nYLeft), + uintptr(nWidth), + uintptr(nHeight), + uintptr(dwRop)) + + if ret == 0 { + panic("PatBlt failed") + } +} + +func CloseEnhMetaFile(hdc HDC) HENHMETAFILE { + ret, _, _ := procCloseEnhMetaFile.Call( + uintptr(hdc)) + + return HENHMETAFILE(ret) +} + +func CopyEnhMetaFile(hemfSrc HENHMETAFILE, lpszFile *uint16) HENHMETAFILE { + ret, _, _ := procCopyEnhMetaFile.Call( + uintptr(hemfSrc), + uintptr(unsafe.Pointer(lpszFile))) + + return HENHMETAFILE(ret) +} + +func CreateBrushIndirect(lplb *LOGBRUSH) HBRUSH { + ret, _, _ := procCreateBrushIndirect.Call( + uintptr(unsafe.Pointer(lplb))) + + return HBRUSH(ret) +} + +func CreateCompatibleDC(hdc HDC) HDC { + ret, _, _ := procCreateCompatibleDC.Call( + uintptr(hdc)) + + if ret == 0 { + panic("Create compatible DC failed") + } + + return HDC(ret) +} + +func CreateDC(lpszDriver, lpszDevice, lpszOutput *uint16, lpInitData *DEVMODE) HDC { + ret, _, _ := procCreateDC.Call( + uintptr(unsafe.Pointer(lpszDriver)), + uintptr(unsafe.Pointer(lpszDevice)), + uintptr(unsafe.Pointer(lpszOutput)), + uintptr(unsafe.Pointer(lpInitData))) + + return HDC(ret) +} + +func CreateDIBSection(hdc HDC, pbmi *BITMAPINFO, iUsage uint, ppvBits *unsafe.Pointer, hSection HANDLE, dwOffset uint) HBITMAP { + ret, _, _ := procCreateDIBSection.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(pbmi)), + uintptr(iUsage), + uintptr(unsafe.Pointer(ppvBits)), + uintptr(hSection), + uintptr(dwOffset)) + + return HBITMAP(ret) +} + +func CreateEnhMetaFile(hdcRef HDC, lpFilename *uint16, lpRect *RECT, lpDescription *uint16) HDC { + ret, _, _ := procCreateEnhMetaFile.Call( + uintptr(hdcRef), + uintptr(unsafe.Pointer(lpFilename)), + uintptr(unsafe.Pointer(lpRect)), + uintptr(unsafe.Pointer(lpDescription))) + + return HDC(ret) +} + +func CreateIC(lpszDriver, lpszDevice, lpszOutput *uint16, lpdvmInit *DEVMODE) HDC { + ret, _, _ := procCreateIC.Call( + uintptr(unsafe.Pointer(lpszDriver)), + uintptr(unsafe.Pointer(lpszDevice)), + uintptr(unsafe.Pointer(lpszOutput)), + uintptr(unsafe.Pointer(lpdvmInit))) + + return HDC(ret) +} + +func DeleteDC(hdc HDC) bool { + ret, _, _ := procDeleteDC.Call( + uintptr(hdc)) + + return ret != 0 +} + +func DeleteEnhMetaFile(hemf HENHMETAFILE) bool { + ret, _, _ := procDeleteEnhMetaFile.Call( + uintptr(hemf)) + + return ret != 0 +} + +func Ellipse(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int32) bool { + ret, _, _ := procEllipse.Call( + uintptr(hdc), + uintptr(nLeftRect), + uintptr(nTopRect), + uintptr(nRightRect), + uintptr(nBottomRect)) + + return ret != 0 +} + +func EndDoc(hdc HDC) int { + ret, _, _ := procEndDoc.Call( + uintptr(hdc)) + + return int(ret) +} + +func EndPage(hdc HDC) int { + ret, _, _ := procEndPage.Call( + uintptr(hdc)) + + return int(ret) +} + +func ExtCreatePen(dwPenStyle, dwWidth uint, lplb *LOGBRUSH, dwStyleCount uint, lpStyle *uint) HPEN { + ret, _, _ := procExtCreatePen.Call( + uintptr(dwPenStyle), + uintptr(dwWidth), + uintptr(unsafe.Pointer(lplb)), + uintptr(dwStyleCount), + uintptr(unsafe.Pointer(lpStyle))) + + return HPEN(ret) +} + +func GetEnhMetaFile(lpszMetaFile *uint16) HENHMETAFILE { + ret, _, _ := procGetEnhMetaFile.Call( + uintptr(unsafe.Pointer(lpszMetaFile))) + + return HENHMETAFILE(ret) +} + +func GetEnhMetaFileHeader(hemf HENHMETAFILE, cbBuffer uint, lpemh *ENHMETAHEADER) uint { + ret, _, _ := procGetEnhMetaFileHeader.Call( + uintptr(hemf), + uintptr(cbBuffer), + uintptr(unsafe.Pointer(lpemh))) + + return uint(ret) +} + +func GetObject(hgdiobj HGDIOBJ, cbBuffer uintptr, lpvObject unsafe.Pointer) int { + ret, _, _ := procGetObject.Call( + uintptr(hgdiobj), + uintptr(cbBuffer), + uintptr(lpvObject)) + + return int(ret) +} + +func GetStockObject(fnObject int) HGDIOBJ { + ret, _, _ := procGetDeviceCaps.Call( + uintptr(fnObject)) + + return HGDIOBJ(ret) +} + +func GetTextExtentExPoint(hdc HDC, lpszStr *uint16, cchString, nMaxExtent int, lpnFit, alpDx *int, lpSize *SIZE) bool { + ret, _, _ := procGetTextExtentExPoint.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(lpszStr)), + uintptr(cchString), + uintptr(nMaxExtent), + uintptr(unsafe.Pointer(lpnFit)), + uintptr(unsafe.Pointer(alpDx)), + uintptr(unsafe.Pointer(lpSize))) + + return ret != 0 +} + +func GetTextExtentPoint32(hdc HDC, lpString *uint16, c int, lpSize *SIZE) bool { + ret, _, _ := procGetTextExtentPoint32.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(lpString)), + uintptr(c), + uintptr(unsafe.Pointer(lpSize))) + + return ret != 0 +} + +func GetTextMetrics(hdc HDC, lptm *TEXTMETRIC) bool { + ret, _, _ := procGetTextMetrics.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(lptm))) + + return ret != 0 +} + +func LineTo(hdc HDC, nXEnd, nYEnd int32) bool { + ret, _, _ := procLineTo.Call( + uintptr(hdc), + uintptr(nXEnd), + uintptr(nYEnd)) + + return ret != 0 +} + +func MoveToEx(hdc HDC, x, y int, lpPoint *POINT) bool { + ret, _, _ := procMoveToEx.Call( + uintptr(hdc), + uintptr(x), + uintptr(y), + uintptr(unsafe.Pointer(lpPoint))) + + return ret != 0 +} + +func PlayEnhMetaFile(hdc HDC, hemf HENHMETAFILE, lpRect *RECT) bool { + ret, _, _ := procPlayEnhMetaFile.Call( + uintptr(hdc), + uintptr(hemf), + uintptr(unsafe.Pointer(lpRect))) + + return ret != 0 +} + +func Rectangle(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int32) bool { + ret, _, _ := procRectangle.Call( + uintptr(hdc), + uintptr(nLeftRect), + uintptr(nTopRect), + uintptr(nRightRect), + uintptr(nBottomRect)) + + return ret != 0 +} + +func ResetDC(hdc HDC, lpInitData *DEVMODE) HDC { + ret, _, _ := procResetDC.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(lpInitData))) + + return HDC(ret) +} + +func SelectObject(hdc HDC, hgdiobj HGDIOBJ) HGDIOBJ { + ret, _, _ := procSelectObject.Call( + uintptr(hdc), + uintptr(hgdiobj)) + + if ret == 0 { + panic("SelectObject failed") + } + + return HGDIOBJ(ret) +} + +func SetBkMode(hdc HDC, iBkMode int) int { + ret, _, _ := procSetBkMode.Call( + uintptr(hdc), + uintptr(iBkMode)) + + if ret == 0 { + panic("SetBkMode failed") + } + + return int(ret) +} + +func SetBrushOrgEx(hdc HDC, nXOrg, nYOrg int, lppt *POINT) bool { + ret, _, _ := procSetBrushOrgEx.Call( + uintptr(hdc), + uintptr(nXOrg), + uintptr(nYOrg), + uintptr(unsafe.Pointer(lppt))) + + return ret != 0 +} + +func SetStretchBltMode(hdc HDC, iStretchMode int) int { + ret, _, _ := procSetStretchBltMode.Call( + uintptr(hdc), + uintptr(iStretchMode)) + + return int(ret) +} + +func SetTextColor(hdc HDC, crColor COLORREF) COLORREF { + ret, _, _ := procSetTextColor.Call( + uintptr(hdc), + uintptr(crColor)) + + if ret == CLR_INVALID { + panic("SetTextColor failed") + } + + return COLORREF(ret) +} + +func SetBkColor(hdc HDC, crColor COLORREF) COLORREF { + ret, _, _ := procSetBkColor.Call( + uintptr(hdc), + uintptr(crColor)) + + if ret == CLR_INVALID { + panic("SetBkColor failed") + } + + return COLORREF(ret) +} + +func StartDoc(hdc HDC, lpdi *DOCINFO) int { + ret, _, _ := procStartDoc.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(lpdi))) + + return int(ret) +} + +func StartPage(hdc HDC) int { + ret, _, _ := procStartPage.Call( + uintptr(hdc)) + + return int(ret) +} + +func StretchBlt(hdcDest HDC, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest int, hdcSrc HDC, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc int, dwRop uint) { + ret, _, _ := procStretchBlt.Call( + uintptr(hdcDest), + uintptr(nXOriginDest), + uintptr(nYOriginDest), + uintptr(nWidthDest), + uintptr(nHeightDest), + uintptr(hdcSrc), + uintptr(nXOriginSrc), + uintptr(nYOriginSrc), + uintptr(nWidthSrc), + uintptr(nHeightSrc), + uintptr(dwRop)) + + if ret == 0 { + panic("StretchBlt failed") + } +} + +func SetDIBitsToDevice(hdc HDC, xDest, yDest, dwWidth, dwHeight, xSrc, ySrc int, uStartScan, cScanLines uint, lpvBits []byte, lpbmi *BITMAPINFO, fuColorUse uint) int { + ret, _, _ := procSetDIBitsToDevice.Call( + uintptr(hdc), + uintptr(xDest), + uintptr(yDest), + uintptr(dwWidth), + uintptr(dwHeight), + uintptr(xSrc), + uintptr(ySrc), + uintptr(uStartScan), + uintptr(cScanLines), + uintptr(unsafe.Pointer(&lpvBits[0])), + uintptr(unsafe.Pointer(lpbmi)), + uintptr(fuColorUse)) + + return int(ret) +} + +func ChoosePixelFormat(hdc HDC, pfd *PIXELFORMATDESCRIPTOR) int { + ret, _, _ := procChoosePixelFormat.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(pfd)), + ) + return int(ret) +} + +func DescribePixelFormat(hdc HDC, iPixelFormat int, nBytes uint, pfd *PIXELFORMATDESCRIPTOR) int { + ret, _, _ := procDescribePixelFormat.Call( + uintptr(hdc), + uintptr(iPixelFormat), + uintptr(nBytes), + uintptr(unsafe.Pointer(pfd)), + ) + return int(ret) +} + +func GetEnhMetaFilePixelFormat(hemf HENHMETAFILE, cbBuffer uint32, pfd *PIXELFORMATDESCRIPTOR) uint { + ret, _, _ := procGetEnhMetaFilePixelFormat.Call( + uintptr(hemf), + uintptr(cbBuffer), + uintptr(unsafe.Pointer(pfd)), + ) + return uint(ret) +} + +func GetPixelFormat(hdc HDC) int { + ret, _, _ := procGetPixelFormat.Call( + uintptr(hdc), + ) + return int(ret) +} + +func SetPixelFormat(hdc HDC, iPixelFormat int, pfd *PIXELFORMATDESCRIPTOR) bool { + ret, _, _ := procSetPixelFormat.Call( + uintptr(hdc), + uintptr(iPixelFormat), + uintptr(unsafe.Pointer(pfd)), + ) + return ret == TRUE +} + +func SwapBuffers(hdc HDC) bool { + ret, _, _ := procSwapBuffers.Call(uintptr(hdc)) + return ret == TRUE +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/gdiplus.go b/v2/internal/frontend/desktop/windows/winc/w32/gdiplus.go new file mode 100644 index 000000000..a8d7daffa --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/gdiplus.go @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "errors" + "fmt" + "syscall" + "unsafe" +) + +const ( + Ok = 0 + GenericError = 1 + InvalidParameter = 2 + OutOfMemory = 3 + ObjectBusy = 4 + InsufficientBuffer = 5 + NotImplemented = 6 + Win32Error = 7 + WrongState = 8 + Aborted = 9 + FileNotFound = 10 + ValueOverflow = 11 + AccessDenied = 12 + UnknownImageFormat = 13 + FontFamilyNotFound = 14 + FontStyleNotFound = 15 + NotTrueTypeFont = 16 + UnsupportedGdiplusVersion = 17 + GdiplusNotInitialized = 18 + PropertyNotFound = 19 + PropertyNotSupported = 20 + ProfileNotFound = 21 +) + +func GetGpStatus(s int32) string { + switch s { + case Ok: + return "Ok" + case GenericError: + return "GenericError" + case InvalidParameter: + return "InvalidParameter" + case OutOfMemory: + return "OutOfMemory" + case ObjectBusy: + return "ObjectBusy" + case InsufficientBuffer: + return "InsufficientBuffer" + case NotImplemented: + return "NotImplemented" + case Win32Error: + return "Win32Error" + case WrongState: + return "WrongState" + case Aborted: + return "Aborted" + case FileNotFound: + return "FileNotFound" + case ValueOverflow: + return "ValueOverflow" + case AccessDenied: + return "AccessDenied" + case UnknownImageFormat: + return "UnknownImageFormat" + case FontFamilyNotFound: + return "FontFamilyNotFound" + case FontStyleNotFound: + return "FontStyleNotFound" + case NotTrueTypeFont: + return "NotTrueTypeFont" + case UnsupportedGdiplusVersion: + return "UnsupportedGdiplusVersion" + case GdiplusNotInitialized: + return "GdiplusNotInitialized" + case PropertyNotFound: + return "PropertyNotFound" + case PropertyNotSupported: + return "PropertyNotSupported" + case ProfileNotFound: + return "ProfileNotFound" + } + return "Unknown Status Value" +} + +var ( + token uintptr + + modgdiplus = syscall.NewLazyDLL("gdiplus.dll") + + procGdipCreateBitmapFromFile = modgdiplus.NewProc("GdipCreateBitmapFromFile") + procGdipCreateBitmapFromHBITMAP = modgdiplus.NewProc("GdipCreateBitmapFromHBITMAP") + procGdipCreateHBITMAPFromBitmap = modgdiplus.NewProc("GdipCreateHBITMAPFromBitmap") + procGdipCreateBitmapFromResource = modgdiplus.NewProc("GdipCreateBitmapFromResource") + procGdipCreateBitmapFromStream = modgdiplus.NewProc("GdipCreateBitmapFromStream") + procGdipDisposeImage = modgdiplus.NewProc("GdipDisposeImage") + procGdiplusShutdown = modgdiplus.NewProc("GdiplusShutdown") + procGdiplusStartup = modgdiplus.NewProc("GdiplusStartup") +) + +func GdipCreateBitmapFromFile(filename string) (*uintptr, error) { + var bitmap *uintptr + ret, _, _ := procGdipCreateBitmapFromFile.Call( + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))), + uintptr(unsafe.Pointer(&bitmap))) + + if ret != Ok { + return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromFile failed with status '%s' for file '%s'", GetGpStatus(int32(ret)), filename)) + } + + return bitmap, nil +} + +func GdipCreateBitmapFromResource(instance HINSTANCE, resId *uint16) (*uintptr, error) { + var bitmap *uintptr + ret, _, _ := procGdipCreateBitmapFromResource.Call( + uintptr(instance), + uintptr(unsafe.Pointer(resId)), + uintptr(unsafe.Pointer(&bitmap))) + + if ret != Ok { + return nil, errors.New(fmt.Sprintf("GdiCreateBitmapFromResource failed with status '%s'", GetGpStatus(int32(ret)))) + } + + return bitmap, nil +} + +func GdipCreateBitmapFromStream(stream *IStream) (*uintptr, error) { + var bitmap *uintptr + ret, _, _ := procGdipCreateBitmapFromStream.Call( + uintptr(unsafe.Pointer(stream)), + uintptr(unsafe.Pointer(&bitmap))) + + if ret != Ok { + return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromStream failed with status '%s'", GetGpStatus(int32(ret)))) + } + + return bitmap, nil +} + +func GdipCreateHBITMAPFromBitmap(bitmap *uintptr, background uint32) (HBITMAP, error) { + var hbitmap HBITMAP + ret, _, _ := procGdipCreateHBITMAPFromBitmap.Call( + uintptr(unsafe.Pointer(bitmap)), + uintptr(unsafe.Pointer(&hbitmap)), + uintptr(background)) + + if ret != Ok { + return 0, errors.New(fmt.Sprintf("GdipCreateHBITMAPFromBitmap failed with status '%s'", GetGpStatus(int32(ret)))) + } + + return hbitmap, nil +} + +func GdipDisposeImage(image *uintptr) { + procGdipDisposeImage.Call(uintptr(unsafe.Pointer(image))) +} + +func GdiplusShutdown() { + procGdiplusShutdown.Call(token) +} + +func GdiplusStartup(input *GdiplusStartupInput, output *GdiplusStartupOutput) { + ret, _, _ := procGdiplusStartup.Call( + uintptr(unsafe.Pointer(&token)), + uintptr(unsafe.Pointer(input)), + uintptr(unsafe.Pointer(output))) + + if ret != Ok { + panic("GdiplusStartup failed with status " + GetGpStatus(int32(ret))) + } +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/idispatch.go b/v2/internal/frontend/desktop/windows/winc/w32/idispatch.go new file mode 100644 index 000000000..2396c9c10 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/idispatch.go @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "unsafe" +) + +type pIDispatchVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr + pGetTypeInfoCount uintptr + pGetTypeInfo uintptr + pGetIDsOfNames uintptr + pInvoke uintptr +} + +type IDispatch struct { + lpVtbl *pIDispatchVtbl +} + +func (this *IDispatch) QueryInterface(id *GUID) *IDispatch { + return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id) +} + +func (this *IDispatch) AddRef() int32 { + return ComAddRef((*IUnknown)(unsafe.Pointer(this))) +} + +func (this *IDispatch) Release() int32 { + return ComRelease((*IUnknown)(unsafe.Pointer(this))) +} + +func (this *IDispatch) GetIDsOfName(names []string) []int32 { + return ComGetIDsOfName(this, names) +} + +func (this *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) *VARIANT { + return ComInvoke(this, dispid, dispatch, params...) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/istream.go b/v2/internal/frontend/desktop/windows/winc/w32/istream.go new file mode 100644 index 000000000..a937c7ac8 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/istream.go @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "unsafe" +) + +type pIStreamVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr +} + +type IStream struct { + lpVtbl *pIStreamVtbl +} + +func (this *IStream) QueryInterface(id *GUID) *IDispatch { + return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id) +} + +func (this *IStream) AddRef() int32 { + return ComAddRef((*IUnknown)(unsafe.Pointer(this))) +} + +func (this *IStream) Release() int32 { + return ComRelease((*IUnknown)(unsafe.Pointer(this))) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/iunknown.go b/v2/internal/frontend/desktop/windows/winc/w32/iunknown.go new file mode 100644 index 000000000..388cf10ab --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/iunknown.go @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +type pIUnknownVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr +} + +type IUnknown struct { + lpVtbl *pIUnknownVtbl +} + +func (this *IUnknown) QueryInterface(id *GUID) *IDispatch { + return ComQueryInterface(this, id) +} + +func (this *IUnknown) AddRef() int32 { + return ComAddRef(this) +} + +func (this *IUnknown) Release() int32 { + return ComRelease(this) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/kernel32.go b/v2/internal/frontend/desktop/windows/winc/w32/kernel32.go new file mode 100644 index 000000000..66a9b5f64 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/kernel32.go @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + procGetModuleHandle = modkernel32.NewProc("GetModuleHandleW") + procMulDiv = modkernel32.NewProc("MulDiv") + procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") + procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") + procGetLogicalDriveStrings = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetUserDefaultLCID = modkernel32.NewProc("GetUserDefaultLCID") + procLstrlen = modkernel32.NewProc("lstrlenW") + procLstrcpy = modkernel32.NewProc("lstrcpyW") + procGlobalAlloc = modkernel32.NewProc("GlobalAlloc") + procGlobalFree = modkernel32.NewProc("GlobalFree") + procGlobalLock = modkernel32.NewProc("GlobalLock") + procGlobalUnlock = modkernel32.NewProc("GlobalUnlock") + procMoveMemory = modkernel32.NewProc("RtlMoveMemory") + procFindResource = modkernel32.NewProc("FindResourceW") + procSizeofResource = modkernel32.NewProc("SizeofResource") + procLockResource = modkernel32.NewProc("LockResource") + procLoadResource = modkernel32.NewProc("LoadResource") + procGetLastError = modkernel32.NewProc("GetLastError") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procModule32First = modkernel32.NewProc("Module32FirstW") + procModule32Next = modkernel32.NewProc("Module32NextW") + procGetSystemTimes = modkernel32.NewProc("GetSystemTimes") + procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") + procSetConsoleTextAttribute = modkernel32.NewProc("SetConsoleTextAttribute") + procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procSetSystemTime = modkernel32.NewProc("SetSystemTime") + procGetSystemTime = modkernel32.NewProc("GetSystemTime") +) + +func GetModuleHandle(modulename string) HINSTANCE { + var mn uintptr + if modulename == "" { + mn = 0 + } else { + mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename))) + } + ret, _, _ := procGetModuleHandle.Call(mn) + return HINSTANCE(ret) +} + +func MulDiv(number, numerator, denominator int) int { + ret, _, _ := procMulDiv.Call( + uintptr(number), + uintptr(numerator), + uintptr(denominator)) + + return int(ret) +} + +func GetConsoleWindow() HWND { + ret, _, _ := procGetConsoleWindow.Call() + + return HWND(ret) +} + +func GetCurrentThread() HANDLE { + ret, _, _ := procGetCurrentThread.Call() + + return HANDLE(ret) +} + +func GetCurrentThreadId() HANDLE { + ret, _, _ := procGetCurrentThreadId.Call() + + return HANDLE(ret) +} + +func GetLogicalDrives() uint32 { + ret, _, _ := procGetLogicalDrives.Call() + + return uint32(ret) +} + +func GetUserDefaultLCID() uint32 { + ret, _, _ := procGetUserDefaultLCID.Call() + + return uint32(ret) +} + +func Lstrlen(lpString *uint16) int { + ret, _, _ := procLstrlen.Call(uintptr(unsafe.Pointer(lpString))) + + return int(ret) +} + +func Lstrcpy(buf []uint16, lpString *uint16) { + procLstrcpy.Call( + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(lpString))) +} + +func GlobalAlloc(uFlags uint, dwBytes uint32) HGLOBAL { + ret, _, _ := procGlobalAlloc.Call( + uintptr(uFlags), + uintptr(dwBytes)) + + if ret == 0 { + panic("GlobalAlloc failed") + } + + return HGLOBAL(ret) +} + +func GlobalFree(hMem HGLOBAL) { + ret, _, _ := procGlobalFree.Call(uintptr(hMem)) + + if ret != 0 { + panic("GlobalFree failed") + } +} + +func GlobalLock(hMem HGLOBAL) unsafe.Pointer { + ret, _, _ := procGlobalLock.Call(uintptr(hMem)) + + if ret == 0 { + panic("GlobalLock failed") + } + + return unsafe.Pointer(ret) +} + +func GlobalUnlock(hMem HGLOBAL) bool { + ret, _, _ := procGlobalUnlock.Call(uintptr(hMem)) + + return ret != 0 +} + +func MoveMemory(destination, source unsafe.Pointer, length uint32) { + procMoveMemory.Call( + uintptr(unsafe.Pointer(destination)), + uintptr(source), + uintptr(length)) +} + +func FindResource(hModule HMODULE, lpName, lpType *uint16) (HRSRC, error) { + ret, _, _ := procFindResource.Call( + uintptr(hModule), + uintptr(unsafe.Pointer(lpName)), + uintptr(unsafe.Pointer(lpType))) + + if ret == 0 { + return 0, syscall.GetLastError() + } + + return HRSRC(ret), nil +} + +func SizeofResource(hModule HMODULE, hResInfo HRSRC) uint32 { + ret, _, _ := procSizeofResource.Call( + uintptr(hModule), + uintptr(hResInfo)) + + if ret == 0 { + panic("SizeofResource failed") + } + + return uint32(ret) +} + +func LockResource(hResData HGLOBAL) unsafe.Pointer { + ret, _, _ := procLockResource.Call(uintptr(hResData)) + + if ret == 0 { + panic("LockResource failed") + } + + return unsafe.Pointer(ret) +} + +func LoadResource(hModule HMODULE, hResInfo HRSRC) HGLOBAL { + ret, _, _ := procLoadResource.Call( + uintptr(hModule), + uintptr(hResInfo)) + + if ret == 0 { + panic("LoadResource failed") + } + + return HGLOBAL(ret) +} + +func GetLastError() uint32 { + ret, _, _ := procGetLastError.Call() + return uint32(ret) +} + +func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) HANDLE { + inherit := 0 + if inheritHandle { + inherit = 1 + } + + ret, _, _ := procOpenProcess.Call( + uintptr(desiredAccess), + uintptr(inherit), + uintptr(processId)) + return HANDLE(ret) +} + +func TerminateProcess(hProcess HANDLE, uExitCode uint) bool { + ret, _, _ := procTerminateProcess.Call( + uintptr(hProcess), + uintptr(uExitCode)) + return ret != 0 +} + +func CloseHandle(object HANDLE) bool { + ret, _, _ := procCloseHandle.Call( + uintptr(object)) + return ret != 0 +} + +func CreateToolhelp32Snapshot(flags, processId uint32) HANDLE { + ret, _, _ := procCreateToolhelp32Snapshot.Call( + uintptr(flags), + uintptr(processId)) + + if ret <= 0 { + return HANDLE(0) + } + + return HANDLE(ret) +} + +func Module32First(snapshot HANDLE, me *MODULEENTRY32) bool { + ret, _, _ := procModule32First.Call( + uintptr(snapshot), + uintptr(unsafe.Pointer(me))) + + return ret != 0 +} + +func Module32Next(snapshot HANDLE, me *MODULEENTRY32) bool { + ret, _, _ := procModule32Next.Call( + uintptr(snapshot), + uintptr(unsafe.Pointer(me))) + + return ret != 0 +} + +func GetSystemTimes(lpIdleTime, lpKernelTime, lpUserTime *FILETIME) bool { + ret, _, _ := procGetSystemTimes.Call( + uintptr(unsafe.Pointer(lpIdleTime)), + uintptr(unsafe.Pointer(lpKernelTime)), + uintptr(unsafe.Pointer(lpUserTime))) + + return ret != 0 +} + +func GetProcessTimes(hProcess HANDLE, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime *FILETIME) bool { + ret, _, _ := procGetProcessTimes.Call( + uintptr(hProcess), + uintptr(unsafe.Pointer(lpCreationTime)), + uintptr(unsafe.Pointer(lpExitTime)), + uintptr(unsafe.Pointer(lpKernelTime)), + uintptr(unsafe.Pointer(lpUserTime))) + + return ret != 0 +} + +func GetConsoleScreenBufferInfo(hConsoleOutput HANDLE) *CONSOLE_SCREEN_BUFFER_INFO { + var csbi CONSOLE_SCREEN_BUFFER_INFO + ret, _, _ := procGetConsoleScreenBufferInfo.Call( + uintptr(hConsoleOutput), + uintptr(unsafe.Pointer(&csbi))) + if ret == 0 { + return nil + } + return &csbi +} + +func SetConsoleTextAttribute(hConsoleOutput HANDLE, wAttributes uint16) bool { + ret, _, _ := procSetConsoleTextAttribute.Call( + uintptr(hConsoleOutput), + uintptr(wAttributes)) + return ret != 0 +} + +func GetDiskFreeSpaceEx(dirName string) (r bool, + freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64) { + ret, _, _ := procGetDiskFreeSpaceEx.Call( + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(dirName))), + uintptr(unsafe.Pointer(&freeBytesAvailable)), + uintptr(unsafe.Pointer(&totalNumberOfBytes)), + uintptr(unsafe.Pointer(&totalNumberOfFreeBytes))) + return ret != 0, + freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes +} + +func GetSystemTime() *SYSTEMTIME { + var time SYSTEMTIME + procGetSystemTime.Call( + uintptr(unsafe.Pointer(&time))) + return &time +} + +func SetSystemTime(time *SYSTEMTIME) bool { + ret, _, _ := procSetSystemTime.Call( + uintptr(unsafe.Pointer(time))) + return ret != 0 +} + +func GetLogicalDriveStrings(nBufferLength uint32, lpBuffer *uint16) uint32 { + ret, _, _ := procGetLogicalDriveStrings.Call( + uintptr(nBufferLength), + uintptr(unsafe.Pointer(lpBuffer)), + 0) + + return uint32(ret) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/ole32.go b/v2/internal/frontend/desktop/windows/winc/w32/ole32.go new file mode 100644 index 000000000..d5cc0df45 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/ole32.go @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modole32 = syscall.NewLazyDLL("ole32.dll") + + procCoInitializeEx = modole32.NewProc("CoInitializeEx") + procCoInitialize = modole32.NewProc("CoInitialize") + procCoUninitialize = modole32.NewProc("CoUninitialize") + procCreateStreamOnHGlobal = modole32.NewProc("CreateStreamOnHGlobal") +) + +func CoInitializeEx(coInit uintptr) HRESULT { + ret, _, _ := procCoInitializeEx.Call( + 0, + coInit) + + switch uint32(ret) { + case E_INVALIDARG: + panic("CoInitializeEx failed with E_INVALIDARG") + case E_OUTOFMEMORY: + panic("CoInitializeEx failed with E_OUTOFMEMORY") + case E_UNEXPECTED: + panic("CoInitializeEx failed with E_UNEXPECTED") + } + + return HRESULT(ret) +} + +func CoInitialize() { + procCoInitialize.Call(0) +} + +func CoUninitialize() { + procCoUninitialize.Call() +} + +func CreateStreamOnHGlobal(hGlobal HGLOBAL, fDeleteOnRelease bool) *IStream { + stream := new(IStream) + ret, _, _ := procCreateStreamOnHGlobal.Call( + uintptr(hGlobal), + uintptr(BoolToBOOL(fDeleteOnRelease)), + uintptr(unsafe.Pointer(&stream))) + + switch uint32(ret) { + case E_INVALIDARG: + panic("CreateStreamOnHGlobal failed with E_INVALIDARG") + case E_OUTOFMEMORY: + panic("CreateStreamOnHGlobal failed with E_OUTOFMEMORY") + case E_UNEXPECTED: + panic("CreateStreamOnHGlobal failed with E_UNEXPECTED") + } + + return stream +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/oleaut32.go b/v2/internal/frontend/desktop/windows/winc/w32/oleaut32.go new file mode 100644 index 000000000..35cc8833d --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/oleaut32.go @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modoleaut32 = syscall.NewLazyDLL("oleaut32") + + procVariantInit = modoleaut32.NewProc("VariantInit") + procSysAllocString = modoleaut32.NewProc("SysAllocString") + procSysFreeString = modoleaut32.NewProc("SysFreeString") + procSysStringLen = modoleaut32.NewProc("SysStringLen") + procCreateDispTypeInfo = modoleaut32.NewProc("CreateDispTypeInfo") + procCreateStdDispatch = modoleaut32.NewProc("CreateStdDispatch") +) + +func VariantInit(v *VARIANT) { + hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + panic("Invoke VariantInit error.") + } + return +} + +func SysAllocString(v string) (ss *int16) { + pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +func SysFreeString(v *int16) { + hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + panic("Invoke SysFreeString error.") + } + return +} + +func SysStringLen(v *int16) uint { + l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) + return uint(l) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/shcore.go b/v2/internal/frontend/desktop/windows/winc/w32/shcore.go new file mode 100644 index 000000000..1d23ac1fe --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/shcore.go @@ -0,0 +1,27 @@ +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modshcore = syscall.NewLazyDLL("shcore.dll") + + procGetDpiForMonitor = modshcore.NewProc("GetDpiForMonitor") +) + +func HasGetDPIForMonitorFunc() bool { + err := procGetDpiForMonitor.Find() + return err == nil +} + +func GetDPIForMonitor(hmonitor HMONITOR, dpiType MONITOR_DPI_TYPE, dpiX *UINT, dpiY *UINT) uintptr { + ret, _, _ := procGetDpiForMonitor.Call( + hmonitor, + uintptr(dpiType), + uintptr(unsafe.Pointer(dpiX)), + uintptr(unsafe.Pointer(dpiY))) + + return ret +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/shell32.go b/v2/internal/frontend/desktop/windows/winc/w32/shell32.go new file mode 100644 index 000000000..4584a959e --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/shell32.go @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "errors" + "fmt" + "syscall" + "unsafe" +) + +type CSIDL uint32 + +const ( + CSIDL_DESKTOP = 0x00 + CSIDL_INTERNET = 0x01 + CSIDL_PROGRAMS = 0x02 + CSIDL_CONTROLS = 0x03 + CSIDL_PRINTERS = 0x04 + CSIDL_PERSONAL = 0x05 + CSIDL_FAVORITES = 0x06 + CSIDL_STARTUP = 0x07 + CSIDL_RECENT = 0x08 + CSIDL_SENDTO = 0x09 + CSIDL_BITBUCKET = 0x0A + CSIDL_STARTMENU = 0x0B + CSIDL_MYDOCUMENTS = 0x0C + CSIDL_MYMUSIC = 0x0D + CSIDL_MYVIDEO = 0x0E + CSIDL_DESKTOPDIRECTORY = 0x10 + CSIDL_DRIVES = 0x11 + CSIDL_NETWORK = 0x12 + CSIDL_NETHOOD = 0x13 + CSIDL_FONTS = 0x14 + CSIDL_TEMPLATES = 0x15 + CSIDL_COMMON_STARTMENU = 0x16 + CSIDL_COMMON_PROGRAMS = 0x17 + CSIDL_COMMON_STARTUP = 0x18 + CSIDL_COMMON_DESKTOPDIRECTORY = 0x19 + CSIDL_APPDATA = 0x1A + CSIDL_PRINTHOOD = 0x1B + CSIDL_LOCAL_APPDATA = 0x1C + CSIDL_ALTSTARTUP = 0x1D + CSIDL_COMMON_ALTSTARTUP = 0x1E + CSIDL_COMMON_FAVORITES = 0x1F + CSIDL_INTERNET_CACHE = 0x20 + CSIDL_COOKIES = 0x21 + CSIDL_HISTORY = 0x22 + CSIDL_COMMON_APPDATA = 0x23 + CSIDL_WINDOWS = 0x24 + CSIDL_SYSTEM = 0x25 + CSIDL_PROGRAM_FILES = 0x26 + CSIDL_MYPICTURES = 0x27 + CSIDL_PROFILE = 0x28 + CSIDL_SYSTEMX86 = 0x29 + CSIDL_PROGRAM_FILESX86 = 0x2A + CSIDL_PROGRAM_FILES_COMMON = 0x2B + CSIDL_PROGRAM_FILES_COMMONX86 = 0x2C + CSIDL_COMMON_TEMPLATES = 0x2D + CSIDL_COMMON_DOCUMENTS = 0x2E + CSIDL_COMMON_ADMINTOOLS = 0x2F + CSIDL_ADMINTOOLS = 0x30 + CSIDL_CONNECTIONS = 0x31 + CSIDL_COMMON_MUSIC = 0x35 + CSIDL_COMMON_PICTURES = 0x36 + CSIDL_COMMON_VIDEO = 0x37 + CSIDL_RESOURCES = 0x38 + CSIDL_RESOURCES_LOCALIZED = 0x39 + CSIDL_COMMON_OEM_LINKS = 0x3A + CSIDL_CDBURN_AREA = 0x3B + CSIDL_COMPUTERSNEARME = 0x3D + CSIDL_FLAG_CREATE = 0x8000 + CSIDL_FLAG_DONT_VERIFY = 0x4000 + CSIDL_FLAG_NO_ALIAS = 0x1000 + CSIDL_FLAG_PER_USER_INIT = 0x8000 + CSIDL_FLAG_MASK = 0xFF00 +) + +var ( + modshell32 = syscall.NewLazyDLL("shell32.dll") + + procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolderW") + procSHGetPathFromIDList = modshell32.NewProc("SHGetPathFromIDListW") + procDragAcceptFiles = modshell32.NewProc("DragAcceptFiles") + procDragQueryFile = modshell32.NewProc("DragQueryFileW") + procDragQueryPoint = modshell32.NewProc("DragQueryPoint") + procDragFinish = modshell32.NewProc("DragFinish") + procShellExecute = modshell32.NewProc("ShellExecuteW") + procExtractIcon = modshell32.NewProc("ExtractIconW") + procGetSpecialFolderPath = modshell32.NewProc("SHGetSpecialFolderPathW") +) + +func SHBrowseForFolder(bi *BROWSEINFO) uintptr { + ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi))) + + return ret +} + +func SHGetPathFromIDList(idl uintptr) string { + buf := make([]uint16, 1024) + procSHGetPathFromIDList.Call( + idl, + uintptr(unsafe.Pointer(&buf[0]))) + + return syscall.UTF16ToString(buf) +} + +func DragAcceptFiles(hwnd HWND, accept bool) { + procDragAcceptFiles.Call( + uintptr(hwnd), + uintptr(BoolToBOOL(accept))) +} + +func DragQueryFile(hDrop HDROP, iFile uint) (fileName string, fileCount uint) { + ret, _, _ := procDragQueryFile.Call( + uintptr(hDrop), + uintptr(iFile), + 0, + 0) + + fileCount = uint(ret) + + if iFile != 0xFFFFFFFF { + buf := make([]uint16, fileCount+1) + + ret, _, _ := procDragQueryFile.Call( + uintptr(hDrop), + uintptr(iFile), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(fileCount+1)) + + if ret == 0 { + panic("Invoke DragQueryFile error.") + } + + fileName = syscall.UTF16ToString(buf) + } + + return +} + +func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) { + var pt POINT + ret, _, _ := procDragQueryPoint.Call( + uintptr(hDrop), + uintptr(unsafe.Pointer(&pt))) + + return int(pt.X), int(pt.Y), (ret == 1) +} + +func DragFinish(hDrop HDROP) { + procDragFinish.Call(uintptr(hDrop)) +} + +func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error { + var op, param, directory uintptr + if len(lpOperation) != 0 { + op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation))) + } + if len(lpParameters) != 0 { + param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters))) + } + if len(lpDirectory) != 0 { + directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory))) + } + + ret, _, _ := procShellExecute.Call( + uintptr(hwnd), + op, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))), + param, + directory, + uintptr(nShowCmd)) + + errorMsg := "" + if ret != 0 && ret <= 32 { + switch int(ret) { + case ERROR_FILE_NOT_FOUND: + errorMsg = "The specified file was not found." + case ERROR_PATH_NOT_FOUND: + errorMsg = "The specified path was not found." + case ERROR_BAD_FORMAT: + errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)." + case SE_ERR_ACCESSDENIED: + errorMsg = "The operating system denied access to the specified file." + case SE_ERR_ASSOCINCOMPLETE: + errorMsg = "The file name association is incomplete or invalid." + case SE_ERR_DDEBUSY: + errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed." + case SE_ERR_DDEFAIL: + errorMsg = "The DDE transaction failed." + case SE_ERR_DDETIMEOUT: + errorMsg = "The DDE transaction could not be completed because the request timed out." + case SE_ERR_DLLNOTFOUND: + errorMsg = "The specified DLL was not found." + case SE_ERR_NOASSOC: + errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable." + case SE_ERR_OOM: + errorMsg = "There was not enough memory to complete the operation." + case SE_ERR_SHARE: + errorMsg = "A sharing violation occurred." + default: + errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret) + } + } else { + return nil + } + + return errors.New(errorMsg) +} + +func ExtractIcon(lpszExeFileName string, nIconIndex int) HICON { + ret, _, _ := procExtractIcon.Call( + 0, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszExeFileName))), + uintptr(nIconIndex)) + + return HICON(ret) +} + +func SHGetSpecialFolderPath(hwndOwner HWND, lpszPath *uint16, csidl CSIDL, fCreate bool) bool { + ret, _, _ := procGetSpecialFolderPath.Call( + uintptr(hwndOwner), + uintptr(unsafe.Pointer(lpszPath)), + uintptr(csidl), + uintptr(BoolToBOOL(fCreate)), + 0, + 0) + + return ret != 0 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/shlwapi.go b/v2/internal/frontend/desktop/windows/winc/w32/shlwapi.go new file mode 100644 index 000000000..eb7aaeea6 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/shlwapi.go @@ -0,0 +1,24 @@ +package w32 + +import ( + "syscall" + "unsafe" +) + +var ( + modshlwapi = syscall.NewLazyDLL("shlwapi.dll") + + procSHCreateMemStream = modshlwapi.NewProc("SHCreateMemStream") +) + +func SHCreateMemStream(data []byte) (uintptr, error) { + ret, _, err := procSHCreateMemStream.Call( + uintptr(unsafe.Pointer(&data[0])), + uintptr(len(data)), + ) + if ret == 0 { + return 0, err + } + + return ret, nil +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/toolbar.go b/v2/internal/frontend/desktop/windows/winc/w32/toolbar.go new file mode 100644 index 000000000..9c0c9ffee --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/toolbar.go @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +// ToolBar messages +const ( + TB_ENABLEBUTTON = WM_USER + 1 + TB_CHECKBUTTON = WM_USER + 2 + TB_PRESSBUTTON = WM_USER + 3 + TB_HIDEBUTTON = WM_USER + 4 + TB_INDETERMINATE = WM_USER + 5 + TB_MARKBUTTON = WM_USER + 6 + TB_ISBUTTONENABLED = WM_USER + 9 + TB_ISBUTTONCHECKED = WM_USER + 10 + TB_ISBUTTONPRESSED = WM_USER + 11 + TB_ISBUTTONHIDDEN = WM_USER + 12 + TB_ISBUTTONINDETERMINATE = WM_USER + 13 + TB_ISBUTTONHIGHLIGHTED = WM_USER + 14 + TB_SETSTATE = WM_USER + 17 + TB_GETSTATE = WM_USER + 18 + TB_ADDBITMAP = WM_USER + 19 + TB_DELETEBUTTON = WM_USER + 22 + TB_GETBUTTON = WM_USER + 23 + TB_BUTTONCOUNT = WM_USER + 24 + TB_COMMANDTOINDEX = WM_USER + 25 + TB_SAVERESTORE = WM_USER + 76 + TB_CUSTOMIZE = WM_USER + 27 + TB_ADDSTRING = WM_USER + 77 + TB_GETITEMRECT = WM_USER + 29 + TB_BUTTONSTRUCTSIZE = WM_USER + 30 + TB_SETBUTTONSIZE = WM_USER + 31 + TB_SETBITMAPSIZE = WM_USER + 32 + TB_AUTOSIZE = WM_USER + 33 + TB_GETTOOLTIPS = WM_USER + 35 + TB_SETTOOLTIPS = WM_USER + 36 + TB_SETPARENT = WM_USER + 37 + TB_SETROWS = WM_USER + 39 + TB_GETROWS = WM_USER + 40 + TB_GETBITMAPFLAGS = WM_USER + 41 + TB_SETCMDID = WM_USER + 42 + TB_CHANGEBITMAP = WM_USER + 43 + TB_GETBITMAP = WM_USER + 44 + TB_GETBUTTONTEXT = WM_USER + 75 + TB_REPLACEBITMAP = WM_USER + 46 + TB_GETBUTTONSIZE = WM_USER + 58 + TB_SETBUTTONWIDTH = WM_USER + 59 + TB_SETINDENT = WM_USER + 47 + TB_SETIMAGELIST = WM_USER + 48 + TB_GETIMAGELIST = WM_USER + 49 + TB_LOADIMAGES = WM_USER + 50 + TB_GETRECT = WM_USER + 51 + TB_SETHOTIMAGELIST = WM_USER + 52 + TB_GETHOTIMAGELIST = WM_USER + 53 + TB_SETDISABLEDIMAGELIST = WM_USER + 54 + TB_GETDISABLEDIMAGELIST = WM_USER + 55 + TB_SETSTYLE = WM_USER + 56 + TB_GETSTYLE = WM_USER + 57 + TB_SETMAXTEXTROWS = WM_USER + 60 + TB_GETTEXTROWS = WM_USER + 61 + TB_GETOBJECT = WM_USER + 62 + TB_GETBUTTONINFO = WM_USER + 63 + TB_SETBUTTONINFO = WM_USER + 64 + TB_INSERTBUTTON = WM_USER + 67 + TB_ADDBUTTONS = WM_USER + 68 + TB_HITTEST = WM_USER + 69 + TB_SETDRAWTEXTFLAGS = WM_USER + 70 + TB_GETHOTITEM = WM_USER + 71 + TB_SETHOTITEM = WM_USER + 72 + TB_SETANCHORHIGHLIGHT = WM_USER + 73 + TB_GETANCHORHIGHLIGHT = WM_USER + 74 + TB_GETINSERTMARK = WM_USER + 79 + TB_SETINSERTMARK = WM_USER + 80 + TB_INSERTMARKHITTEST = WM_USER + 81 + TB_MOVEBUTTON = WM_USER + 82 + TB_GETMAXSIZE = WM_USER + 83 + TB_SETEXTENDEDSTYLE = WM_USER + 84 + TB_GETEXTENDEDSTYLE = WM_USER + 85 + TB_GETPADDING = WM_USER + 86 + TB_SETPADDING = WM_USER + 87 + TB_SETINSERTMARKCOLOR = WM_USER + 88 + TB_GETINSERTMARKCOLOR = WM_USER + 89 + TB_MAPACCELERATOR = WM_USER + 90 + TB_GETSTRING = WM_USER + 91 + TB_SETCOLORSCHEME = CCM_SETCOLORSCHEME + TB_GETCOLORSCHEME = CCM_GETCOLORSCHEME + TB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT + TB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +) + +// ToolBar notifications +const ( + TBN_FIRST = -700 + TBN_DROPDOWN = TBN_FIRST - 10 +) + +// TBN_DROPDOWN return codes +const ( + TBDDRET_DEFAULT = 0 + TBDDRET_NODEFAULT = 1 + TBDDRET_TREATPRESSED = 2 +) + +// ToolBar state constants +const ( + TBSTATE_CHECKED = 1 + TBSTATE_PRESSED = 2 + TBSTATE_ENABLED = 4 + TBSTATE_HIDDEN = 8 + TBSTATE_INDETERMINATE = 16 + TBSTATE_WRAP = 32 + TBSTATE_ELLIPSES = 0x40 + TBSTATE_MARKED = 0x0080 +) + +// ToolBar style constants +const ( + TBSTYLE_BUTTON = 0 + TBSTYLE_SEP = 1 + TBSTYLE_CHECK = 2 + TBSTYLE_GROUP = 4 + TBSTYLE_CHECKGROUP = TBSTYLE_GROUP | TBSTYLE_CHECK + TBSTYLE_DROPDOWN = 8 + TBSTYLE_AUTOSIZE = 16 + TBSTYLE_NOPREFIX = 32 + TBSTYLE_TOOLTIPS = 256 + TBSTYLE_WRAPABLE = 512 + TBSTYLE_ALTDRAG = 1024 + TBSTYLE_FLAT = 2048 + TBSTYLE_LIST = 4096 + TBSTYLE_CUSTOMERASE = 8192 + TBSTYLE_REGISTERDROP = 0x4000 + TBSTYLE_TRANSPARENT = 0x8000 +) + +// ToolBar extended style constants +const ( + TBSTYLE_EX_DRAWDDARROWS = 0x00000001 + TBSTYLE_EX_MIXEDBUTTONS = 8 + TBSTYLE_EX_HIDECLIPPEDBUTTONS = 16 + TBSTYLE_EX_DOUBLEBUFFER = 0x80 +) + +// ToolBar button style constants +const ( + BTNS_BUTTON = TBSTYLE_BUTTON + BTNS_SEP = TBSTYLE_SEP + BTNS_CHECK = TBSTYLE_CHECK + BTNS_GROUP = TBSTYLE_GROUP + BTNS_CHECKGROUP = TBSTYLE_CHECKGROUP + BTNS_DROPDOWN = TBSTYLE_DROPDOWN + BTNS_AUTOSIZE = TBSTYLE_AUTOSIZE + BTNS_NOPREFIX = TBSTYLE_NOPREFIX + BTNS_WHOLEDROPDOWN = 0x0080 + BTNS_SHOWTEXT = 0x0040 +) + +// TBBUTTONINFO mask flags +const ( + TBIF_IMAGE = 0x00000001 + TBIF_TEXT = 0x00000002 + TBIF_STATE = 0x00000004 + TBIF_STYLE = 0x00000008 + TBIF_LPARAM = 0x00000010 + TBIF_COMMAND = 0x00000020 + TBIF_SIZE = 0x00000040 + TBIF_BYINDEX = 0x80000000 +) + +type NMMOUSE struct { + Hdr NMHDR + DwItemSpec uintptr + DwItemData uintptr + Pt POINT + DwHitInfo uintptr +} + +type NMTOOLBAR struct { + Hdr NMHDR + IItem int32 + TbButton TBBUTTON + CchText int32 + PszText *uint16 + RcButton RECT +} + +type TBBUTTON struct { + IBitmap int32 + IdCommand int32 + FsState byte + FsStyle byte + //#ifdef _WIN64 + // BYTE bReserved[6] // padding for alignment + //#elif defined(_WIN32) + BReserved [2]byte // padding for alignment + //#endif + DwData uintptr + IString uintptr +} + +type TBBUTTONINFO struct { + CbSize uint32 + DwMask uint32 + IdCommand int32 + IImage int32 + FsState byte + FsStyle byte + Cx uint16 + LParam uintptr + PszText uintptr + CchText int32 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/typedef.go b/v2/internal/frontend/desktop/windows/winc/w32/typedef.go new file mode 100644 index 000000000..c9f38161e --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/typedef.go @@ -0,0 +1,1079 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "fmt" + "unsafe" +) + +// From MSDN: Windows Data Types +// http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx +// ATOM WORD +// BOOL int32 +// BOOLEAN byte +// BYTE byte +// CCHAR int8 +// CHAR int8 +// COLORREF DWORD +// DWORD uint32 +// DWORDLONG ULONGLONG +// DWORD_PTR ULONG_PTR +// DWORD32 uint32 +// DWORD64 uint64 +// FLOAT float32 +// HACCEL HANDLE +// HALF_PTR struct{} // ??? +// HANDLE PVOID +// HBITMAP HANDLE +// HBRUSH HANDLE +// HCOLORSPACE HANDLE +// HCONV HANDLE +// HCONVLIST HANDLE +// HCURSOR HANDLE +// HDC HANDLE +// HDDEDATA HANDLE +// HDESK HANDLE +// HDROP HANDLE +// HDWP HANDLE +// HENHMETAFILE HANDLE +// HFILE HANDLE +// HFONT HANDLE +// HGDIOBJ HANDLE +// HGLOBAL HANDLE +// HHOOK HANDLE +// HICON HANDLE +// HINSTANCE HANDLE +// HKEY HANDLE +// HKL HANDLE +// HLOCAL HANDLE +// HMENU HANDLE +// HMETAFILE HANDLE +// HMODULE HANDLE +// HPALETTE HANDLE +// HPEN HANDLE +// HRESULT int32 +// HRGN HANDLE +// HSZ HANDLE +// HWINSTA HANDLE +// HWND HANDLE +// INT int32 +// INT_PTR uintptr +// INT8 int8 +// INT16 int16 +// INT32 int32 +// INT64 int64 +// LANGID WORD +// LCID DWORD +// LCTYPE DWORD +// LGRPID DWORD +// LONG int32 +// LONGLONG int64 +// LONG_PTR uintptr +// LONG32 int32 +// LONG64 int64 +// LPARAM LONG_PTR +// LPBOOL *BOOL +// LPBYTE *BYTE +// LPCOLORREF *COLORREF +// LPCSTR *int8 +// LPCTSTR LPCWSTR +// LPCVOID unsafe.Pointer +// LPCWSTR *WCHAR +// LPDWORD *DWORD +// LPHANDLE *HANDLE +// LPINT *INT +// LPLONG *LONG +// LPSTR *CHAR +// LPTSTR LPWSTR +// LPVOID unsafe.Pointer +// LPWORD *WORD +// LPWSTR *WCHAR +// LRESULT LONG_PTR +// PBOOL *BOOL +// PBOOLEAN *BOOLEAN +// PBYTE *BYTE +// PCHAR *CHAR +// PCSTR *CHAR +// PCTSTR PCWSTR +// PCWSTR *WCHAR +// PDWORD *DWORD +// PDWORDLONG *DWORDLONG +// PDWORD_PTR *DWORD_PTR +// PDWORD32 *DWORD32 +// PDWORD64 *DWORD64 +// PFLOAT *FLOAT +// PHALF_PTR *HALF_PTR +// PHANDLE *HANDLE +// PHKEY *HKEY +// PINT_PTR *INT_PTR +// PINT8 *INT8 +// PINT16 *INT16 +// PINT32 *INT32 +// PINT64 *INT64 +// PLCID *LCID +// PLONG *LONG +// PLONGLONG *LONGLONG +// PLONG_PTR *LONG_PTR +// PLONG32 *LONG32 +// PLONG64 *LONG64 +// POINTER_32 struct{} // ??? +// POINTER_64 struct{} // ??? +// POINTER_SIGNED uintptr +// POINTER_UNSIGNED uintptr +// PSHORT *SHORT +// PSIZE_T *SIZE_T +// PSSIZE_T *SSIZE_T +// PSTR *CHAR +// PTBYTE *TBYTE +// PTCHAR *TCHAR +// PTSTR PWSTR +// PUCHAR *UCHAR +// PUHALF_PTR *UHALF_PTR +// PUINT *UINT +// PUINT_PTR *UINT_PTR +// PUINT8 *UINT8 +// PUINT16 *UINT16 +// PUINT32 *UINT32 +// PUINT64 *UINT64 +// PULONG *ULONG +// PULONGLONG *ULONGLONG +// PULONG_PTR *ULONG_PTR +// PULONG32 *ULONG32 +// PULONG64 *ULONG64 +// PUSHORT *USHORT +// PVOID unsafe.Pointer +// PWCHAR *WCHAR +// PWORD *WORD +// PWSTR *WCHAR +// QWORD uint64 +// SC_HANDLE HANDLE +// SC_LOCK LPVOID +// SERVICE_STATUS_HANDLE HANDLE +// SHORT int16 +// SIZE_T ULONG_PTR +// SSIZE_T LONG_PTR +// TBYTE WCHAR +// TCHAR WCHAR +// UCHAR uint8 +// UHALF_PTR struct{} // ??? +// UINT uint32 +// UINT_PTR uintptr +// UINT8 uint8 +// UINT16 uint16 +// UINT32 uint32 +// UINT64 uint64 +// ULONG uint32 +// ULONGLONG uint64 +// ULONG_PTR uintptr +// ULONG32 uint32 +// ULONG64 uint64 +// USHORT uint16 +// USN LONGLONG +// WCHAR uint16 +// WORD uint16 +// WPARAM UINT_PTR +type ( + ATOM = uint16 + BOOL = int32 + COLORREF = uint32 + DWM_FRAME_COUNT = uint64 + WORD = uint16 + DWORD = uint32 + HACCEL = HANDLE + HANDLE = uintptr + HBITMAP = HANDLE + HBRUSH = HANDLE + HCURSOR = HANDLE + HDC = HANDLE + HDROP = HANDLE + HDWP = HANDLE + HENHMETAFILE = HANDLE + HFONT = HANDLE + HGDIOBJ = HANDLE + HGLOBAL = HANDLE + HGLRC = HANDLE + HHOOK = HANDLE + HICON = HANDLE + HIMAGELIST = HANDLE + HINSTANCE = HANDLE + HKEY = HANDLE + HKL = HANDLE + HMENU = HANDLE + HMODULE = HANDLE + HMONITOR = HANDLE + HPEN = HANDLE + HRESULT = int32 + HRGN = HANDLE + HRSRC = HANDLE + HTHUMBNAIL = HANDLE + HWND = HANDLE + LPARAM = uintptr + LPCVOID = unsafe.Pointer + LRESULT = uintptr + PVOID = unsafe.Pointer + QPC_TIME = uint64 + ULONG_PTR = uintptr + SIZE_T = ULONG_PTR + WPARAM = uintptr + UINT = uint +) + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805.aspx +type POINT struct { + X, Y int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897.aspx +type RECT struct { + Left, Top, Right, Bottom int32 +} + +func (r *RECT) String() string { + return fmt.Sprintf("RECT (%p): Left: %d, Top: %d, Right: %d, Bottom: %d", r, r.Left, r.Top, r.Right, r.Bottom) +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633577.aspx +type WNDCLASSEX struct { + Size uint32 + Style uint32 + WndProc uintptr + ClsExtra int32 + WndExtra int32 + Instance HINSTANCE + Icon HICON + Cursor HCURSOR + Background HBRUSH + MenuName *uint16 + ClassName *uint16 + IconSm HICON +} + +type TPMPARAMS struct { + CbSize uint32 + RcExclude RECT +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644958.aspx +type MSG struct { + Hwnd HWND + Message uint32 + WParam uintptr + LParam uintptr + Time uint32 + Pt POINT +} + +// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-minmaxinfo +type MINMAXINFO struct { + PtReserved POINT + PtMaxSize POINT + PtMaxPosition POINT + PtMinTrackSize POINT + PtMaxTrackSize POINT +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145037.aspx +type LOGFONT struct { + Height int32 + Width int32 + Escapement int32 + Orientation int32 + Weight int32 + Italic byte + Underline byte + StrikeOut byte + CharSet byte + OutPrecision byte + ClipPrecision byte + Quality byte + PitchAndFamily byte + FaceName [LF_FACESIZE]uint16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839.aspx +type OPENFILENAME struct { + StructSize uint32 + Owner HWND + Instance HINSTANCE + Filter *uint16 + CustomFilter *uint16 + MaxCustomFilter uint32 + FilterIndex uint32 + File *uint16 + MaxFile uint32 + FileTitle *uint16 + MaxFileTitle uint32 + InitialDir *uint16 + Title *uint16 + Flags uint32 + FileOffset uint16 + FileExtension uint16 + DefExt *uint16 + CustData uintptr + FnHook uintptr + TemplateName *uint16 + PvReserved unsafe.Pointer + DwReserved uint32 + FlagsEx uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773205.aspx +type BROWSEINFO struct { + Owner HWND + Root *uint16 + DisplayName *uint16 + Title *uint16 + Flags uint32 + CallbackFunc uintptr + LParam uintptr + Image int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221627.aspx +type VARIANT struct { + VT uint16 // 2 + WReserved1 uint16 // 4 + WReserved2 uint16 // 6 + WReserved3 uint16 // 8 + Val int64 // 16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221416.aspx +type DISPPARAMS struct { + Rgvarg uintptr + RgdispidNamedArgs uintptr + CArgs uint32 + CNamedArgs uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221133.aspx +type EXCEPINFO struct { + WCode uint16 + WReserved uint16 + BstrSource *uint16 + BstrDescription *uint16 + BstrHelpFile *uint16 + DwHelpContext uint32 + PvReserved uintptr + PfnDeferredFillIn uintptr + Scode int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145035.aspx +type LOGBRUSH struct { + LbStyle uint32 + LbColor COLORREF + LbHatch uintptr +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565.aspx +type DEVMODE struct { + DmDeviceName [CCHDEVICENAME]uint16 + DmSpecVersion uint16 + DmDriverVersion uint16 + DmSize uint16 + DmDriverExtra uint16 + DmFields uint32 + DmOrientation int16 + DmPaperSize int16 + DmPaperLength int16 + DmPaperWidth int16 + DmScale int16 + DmCopies int16 + DmDefaultSource int16 + DmPrintQuality int16 + DmColor int16 + DmDuplex int16 + DmYResolution int16 + DmTTOption int16 + DmCollate int16 + DmFormName [CCHFORMNAME]uint16 + DmLogPixels uint16 + DmBitsPerPel uint32 + DmPelsWidth uint32 + DmPelsHeight uint32 + DmDisplayFlags uint32 + DmDisplayFrequency uint32 + DmICMMethod uint32 + DmICMIntent uint32 + DmMediaType uint32 + DmDitherType uint32 + DmReserved1 uint32 + DmReserved2 uint32 + DmPanningWidth uint32 + DmPanningHeight uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx +type BITMAPINFOHEADER struct { + BiSize uint32 + BiWidth int32 + BiHeight int32 + BiPlanes uint16 + BiBitCount uint16 + BiCompression uint32 + BiSizeImage uint32 + BiXPelsPerMeter int32 + BiYPelsPerMeter int32 + BiClrUsed uint32 + BiClrImportant uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162938.aspx +type RGBQUAD struct { + RgbBlue byte + RgbGreen byte + RgbRed byte + RgbReserved byte +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183375.aspx +type BITMAPINFO struct { + BmiHeader BITMAPINFOHEADER + BmiColors *RGBQUAD +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183371.aspx +type BITMAP struct { + BmType int32 + BmWidth int32 + BmHeight int32 + BmWidthBytes int32 + BmPlanes uint16 + BmBitsPixel uint16 + BmBits unsafe.Pointer +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183567.aspx +type DIBSECTION struct { + DsBm BITMAP + DsBmih BITMAPINFOHEADER + DsBitfields [3]uint32 + DshSection HANDLE + DsOffset uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162607.aspx +type ENHMETAHEADER struct { + IType uint32 + NSize uint32 + RclBounds RECT + RclFrame RECT + DSignature uint32 + NVersion uint32 + NBytes uint32 + NRecords uint32 + NHandles uint16 + SReserved uint16 + NDescription uint32 + OffDescription uint32 + NPalEntries uint32 + SzlDevice SIZE + SzlMillimeters SIZE + CbPixelFormat uint32 + OffPixelFormat uint32 + BOpenGL uint32 + SzlMicrometers SIZE +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145106.aspx +type SIZE struct { + CX, CY int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145132.aspx +type TEXTMETRIC struct { + TmHeight int32 + TmAscent int32 + TmDescent int32 + TmInternalLeading int32 + TmExternalLeading int32 + TmAveCharWidth int32 + TmMaxCharWidth int32 + TmWeight int32 + TmOverhang int32 + TmDigitizedAspectX int32 + TmDigitizedAspectY int32 + TmFirstChar uint16 + TmLastChar uint16 + TmDefaultChar uint16 + TmBreakChar uint16 + TmItalic byte + TmUnderlined byte + TmStruckOut byte + TmPitchAndFamily byte + TmCharSet byte +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183574.aspx +type DOCINFO struct { + CbSize int32 + LpszDocName *uint16 + LpszOutput *uint16 + LpszDatatype *uint16 + FwType uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775514.aspx +type NMHDR struct { + HwndFrom HWND + IdFrom uintptr + Code uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774743.aspx +type LVCOLUMN struct { + Mask uint32 + Fmt int32 + Cx int32 + PszText *uint16 + CchTextMax int32 + ISubItem int32 + IImage int32 + IOrder int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774760.aspx +type LVITEM struct { + Mask uint32 + IItem int32 + ISubItem int32 + State uint32 + StateMask uint32 + PszText *uint16 + CchTextMax int32 + IImage int32 + LParam uintptr + IIndent int32 + IGroupId int32 + CColumns uint32 + PuColumns uint32 +} + +type LVFINDINFO struct { + Flags uint32 + PszText *uint16 + LParam uintptr + Pt POINT + VkDirection uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774754.aspx +type LVHITTESTINFO struct { + Pt POINT + Flags uint32 + IItem int32 + ISubItem int32 + IGroup int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774771.aspx +type NMITEMACTIVATE struct { + Hdr NMHDR + IItem int32 + ISubItem int32 + UNewState uint32 + UOldState uint32 + UChanged uint32 + PtAction POINT + LParam uintptr + UKeyFlags uint32 +} + +type NMLVKEYDOWN struct { + Hdr NMHDR + WVKey uint16 + Flags uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774773.aspx +type NMLISTVIEW struct { + Hdr NMHDR + IItem int32 + ISubItem int32 + UNewState uint32 + UOldState uint32 + UChanged uint32 + PtAction POINT + LParam uintptr +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774780.aspx +type NMLVDISPINFO struct { + Hdr NMHDR + Item LVITEM +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775507.aspx +type INITCOMMONCONTROLSEX struct { + DwSize uint32 + DwICC uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb760256.aspx +type TOOLINFO struct { + CbSize uint32 + UFlags uint32 + Hwnd HWND + UId uintptr + Rect RECT + Hinst HINSTANCE + LpszText *uint16 + LParam uintptr + LpReserved unsafe.Pointer +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms645604.aspx +type TRACKMOUSEEVENT struct { + CbSize uint32 + DwFlags uint32 + HwndTrack HWND + DwHoverTime uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms534067.aspx +type GdiplusStartupInput struct { + GdiplusVersion uint32 + DebugEventCallback uintptr + SuppressBackgroundThread BOOL + SuppressExternalCodecs BOOL +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms534068.aspx +type GdiplusStartupOutput struct { + NotificationHook uintptr + NotificationUnhook uintptr +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162768.aspx +type PAINTSTRUCT struct { + Hdc HDC + FErase BOOL + RcPaint RECT + FRestore BOOL + FIncUpdate BOOL + RgbReserved [32]byte +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363646.aspx +type EVENTLOGRECORD struct { + Length uint32 + Reserved uint32 + RecordNumber uint32 + TimeGenerated uint32 + TimeWritten uint32 + EventID uint32 + EventType uint16 + NumStrings uint16 + EventCategory uint16 + ReservedFlags uint16 + ClosingRecordNumber uint32 + StringOffset uint32 + UserSidLength uint32 + UserSidOffset uint32 + DataLength uint32 + DataOffset uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms685996.aspx +type SERVICE_STATUS struct { + DwServiceType uint32 + DwCurrentState uint32 + DwControlsAccepted uint32 + DwWin32ExitCode uint32 + DwServiceSpecificExitCode uint32 + DwCheckPoint uint32 + DwWaitHint uint32 +} + +/* ------------------------- + Undocumented API +------------------------- */ + +type ACCENT_STATE DWORD + +const ( + ACCENT_DISABLED ACCENT_STATE = 0 + ACCENT_ENABLE_GRADIENT ACCENT_STATE = 1 + ACCENT_ENABLE_TRANSPARENTGRADIENT ACCENT_STATE = 2 + ACCENT_ENABLE_BLURBEHIND ACCENT_STATE = 3 + ACCENT_ENABLE_ACRYLICBLURBEHIND ACCENT_STATE = 4 // RS4 1803 + ACCENT_ENABLE_HOSTBACKDROP ACCENT_STATE = 5 // RS5 1809 + ACCENT_INVALID_STATE ACCENT_STATE = 6 +) + +type ACCENT_POLICY struct { + AccentState ACCENT_STATE + AccentFlags DWORD + GradientColor DWORD + AnimationId DWORD +} + +type WINDOWCOMPOSITIONATTRIBDATA struct { + Attrib WINDOWCOMPOSITIONATTRIB + PvData PVOID + CbData SIZE_T +} + +type WINDOWCOMPOSITIONATTRIB DWORD + +const ( + WCA_UNDEFINED WINDOWCOMPOSITIONATTRIB = 0 + WCA_NCRENDERING_ENABLED WINDOWCOMPOSITIONATTRIB = 1 + WCA_NCRENDERING_POLICY WINDOWCOMPOSITIONATTRIB = 2 + WCA_TRANSITIONS_FORCEDISABLED WINDOWCOMPOSITIONATTRIB = 3 + WCA_ALLOW_NCPAINT WINDOWCOMPOSITIONATTRIB = 4 + WCA_CAPTION_BUTTON_BOUNDS WINDOWCOMPOSITIONATTRIB = 5 + WCA_NONCLIENT_RTL_LAYOUT WINDOWCOMPOSITIONATTRIB = 6 + WCA_FORCE_ICONIC_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 7 + WCA_EXTENDED_FRAME_BOUNDS WINDOWCOMPOSITIONATTRIB = 8 + WCA_HAS_ICONIC_BITMAP WINDOWCOMPOSITIONATTRIB = 9 + WCA_THEME_ATTRIBUTES WINDOWCOMPOSITIONATTRIB = 10 + WCA_NCRENDERING_EXILED WINDOWCOMPOSITIONATTRIB = 11 + WCA_NCADORNMENTINFO WINDOWCOMPOSITIONATTRIB = 12 + WCA_EXCLUDED_FROM_LIVEPREVIEW WINDOWCOMPOSITIONATTRIB = 13 + WCA_VIDEO_OVERLAY_ACTIVE WINDOWCOMPOSITIONATTRIB = 14 + WCA_FORCE_ACTIVEWINDOW_APPEARANCE WINDOWCOMPOSITIONATTRIB = 15 + WCA_DISALLOW_PEEK WINDOWCOMPOSITIONATTRIB = 16 + WCA_CLOAK WINDOWCOMPOSITIONATTRIB = 17 + WCA_CLOAKED WINDOWCOMPOSITIONATTRIB = 18 + WCA_ACCENT_POLICY WINDOWCOMPOSITIONATTRIB = 19 + WCA_FREEZE_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 20 + WCA_EVER_UNCLOAKED WINDOWCOMPOSITIONATTRIB = 21 + WCA_VISUAL_OWNER WINDOWCOMPOSITIONATTRIB = 22 + WCA_HOLOGRAPHIC WINDOWCOMPOSITIONATTRIB = 23 + WCA_EXCLUDED_FROM_DDA WINDOWCOMPOSITIONATTRIB = 24 + WCA_PASSIVEUPDATEMODE WINDOWCOMPOSITIONATTRIB = 25 + WCA_USEDARKMODECOLORS WINDOWCOMPOSITIONATTRIB = 26 + WCA_CORNER_STYLE WINDOWCOMPOSITIONATTRIB = 27 + WCA_PART_COLOR WINDOWCOMPOSITIONATTRIB = 28 + WCA_DISABLE_MOVESIZE_FEEDBACK WINDOWCOMPOSITIONATTRIB = 29 + WCA_LAST WINDOWCOMPOSITIONATTRIB = 30 +) + +// ------------------------- + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684225.aspx +type MODULEENTRY32 struct { + Size uint32 + ModuleID uint32 + ProcessID uint32 + GlblcntUsage uint32 + ProccntUsage uint32 + ModBaseAddr *uint8 + ModBaseSize uint32 + HModule HMODULE + SzModule [MAX_MODULE_NAME32 + 1]uint16 + SzExePath [MAX_PATH]uint16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx +type FILETIME struct { + DwLowDateTime uint32 + DwHighDateTime uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119.aspx +type COORD struct { + X, Y int16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311.aspx +type SMALL_RECT struct { + Left, Top, Right, Bottom int16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093.aspx +type CONSOLE_SCREEN_BUFFER_INFO struct { + DwSize COORD + DwCursorPosition COORD + WAttributes uint16 + SrWindow SMALL_RECT + DwMaximumWindowSize COORD +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773244.aspx +type MARGINS struct { + CxLeftWidth, CxRightWidth, CyTopHeight, CyBottomHeight int32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969500.aspx +type DWM_BLURBEHIND struct { + DwFlags uint32 + fEnable BOOL + hRgnBlur HRGN + fTransitionOnMaximized BOOL +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969501.aspx +type DWM_PRESENT_PARAMETERS struct { + cbSize uint32 + fQueue BOOL + cRefreshStart DWM_FRAME_COUNT + cBuffer uint32 + fUseSourceRate BOOL + rateSource UNSIGNED_RATIO + cRefreshesPerFrame uint32 + eSampling DWM_SOURCE_FRAME_SAMPLING +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969502.aspx +type DWM_THUMBNAIL_PROPERTIES struct { + dwFlags uint32 + rcDestination RECT + rcSource RECT + opacity byte + fVisible BOOL + fSourceClientAreaOnly BOOL +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969503.aspx +type DWM_TIMING_INFO struct { + cbSize uint32 + rateRefresh UNSIGNED_RATIO + qpcRefreshPeriod QPC_TIME + rateCompose UNSIGNED_RATIO + qpcVBlank QPC_TIME + cRefresh DWM_FRAME_COUNT + cDXRefresh uint32 + qpcCompose QPC_TIME + cFrame DWM_FRAME_COUNT + cDXPresent uint32 + cRefreshFrame DWM_FRAME_COUNT + cFrameSubmitted DWM_FRAME_COUNT + cDXPresentSubmitted uint32 + cFrameConfirmed DWM_FRAME_COUNT + cDXPresentConfirmed uint32 + cRefreshConfirmed DWM_FRAME_COUNT + cDXRefreshConfirmed uint32 + cFramesLate DWM_FRAME_COUNT + cFramesOutstanding uint32 + cFrameDisplayed DWM_FRAME_COUNT + qpcFrameDisplayed QPC_TIME + cRefreshFrameDisplayed DWM_FRAME_COUNT + cFrameComplete DWM_FRAME_COUNT + qpcFrameComplete QPC_TIME + cFramePending DWM_FRAME_COUNT + qpcFramePending QPC_TIME + cFramesDisplayed DWM_FRAME_COUNT + cFramesComplete DWM_FRAME_COUNT + cFramesPending DWM_FRAME_COUNT + cFramesAvailable DWM_FRAME_COUNT + cFramesDropped DWM_FRAME_COUNT + cFramesMissed DWM_FRAME_COUNT + cRefreshNextDisplayed DWM_FRAME_COUNT + cRefreshNextPresented DWM_FRAME_COUNT + cRefreshesDisplayed DWM_FRAME_COUNT + cRefreshesPresented DWM_FRAME_COUNT + cRefreshStarted DWM_FRAME_COUNT + cPixelsReceived uint64 + cPixelsDrawn uint64 + cBuffersEmpty DWM_FRAME_COUNT +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd389402.aspx +type MilMatrix3x2D struct { + S_11, S_12, S_21, S_22 float64 + DX, DY float64 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969505.aspx +type UNSIGNED_RATIO struct { + uiNumerator uint32 + uiDenominator uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms632603.aspx +type CREATESTRUCT struct { + CreateParams uintptr + Instance HINSTANCE + Menu HMENU + Parent HWND + Cy, Cx int32 + Y, X int32 + Style int32 + Name *uint16 + Class *uint16 + dwExStyle uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145065.aspx +type MONITORINFO struct { + CbSize uint32 + RcMonitor RECT + RcWork RECT + DwFlags uint32 +} + +type WINDOWINFO struct { + CbSize DWORD + RcWindow RECT + RcClient RECT + DwStyle DWORD + DwExStyle DWORD + DwWindowStatus DWORD + CxWindowBorders UINT + CyWindowBorders UINT + AtomWindowType ATOM + WCreatorVersion WORD +} + +type MONITOR_DPI_TYPE int32 + +const ( + MDT_EFFECTIVE_DPI MONITOR_DPI_TYPE = 0 + MDT_ANGULAR_DPI MONITOR_DPI_TYPE = 1 + MDT_RAW_DPI MONITOR_DPI_TYPE = 2 + MDT_DEFAULT MONITOR_DPI_TYPE = 0 +) + +func (w *WINDOWINFO) isStyle(style DWORD) bool { + return w.DwStyle&style == style +} + +func (w *WINDOWINFO) IsPopup() bool { + return w.isStyle(WS_POPUP) +} + +func (m *MONITORINFO) Dump() { + fmt.Printf("MONITORINFO (%p)\n", m) + fmt.Printf(" CbSize : %d\n", m.CbSize) + fmt.Printf(" RcMonitor: %s\n", &m.RcMonitor) + fmt.Printf(" RcWork : %s\n", &m.RcWork) + fmt.Printf(" DwFlags : %d\n", m.DwFlags) +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145066.aspx +type MONITORINFOEX struct { + MONITORINFO + SzDevice [CCHDEVICENAME]uint16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826.aspx +type PIXELFORMATDESCRIPTOR struct { + Size uint16 + Version uint16 + DwFlags uint32 + IPixelType byte + ColorBits byte + RedBits, RedShift byte + GreenBits, GreenShift byte + BlueBits, BlueShift byte + AlphaBits, AlphaShift byte + AccumBits byte + AccumRedBits byte + AccumGreenBits byte + AccumBlueBits byte + AccumAlphaBits byte + DepthBits, StencilBits byte + AuxBuffers byte + ILayerType byte + Reserved byte + DwLayerMask uint32 + DwVisibleMask uint32 + DwDamageMask uint32 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx +type INPUT struct { + Type uint32 + Mi MOUSEINPUT + Ki KEYBDINPUT + Hi HARDWAREINPUT +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx +type MOUSEINPUT struct { + Dx int32 + Dy int32 + MouseData uint32 + DwFlags uint32 + Time uint32 + DwExtraInfo uintptr +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646271(v=vs.85).aspx +type KEYBDINPUT struct { + WVk uint16 + WScan uint16 + DwFlags uint32 + Time uint32 + DwExtraInfo uintptr +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646269(v=vs.85).aspx +type HARDWAREINPUT struct { + UMsg uint32 + WParamL uint16 + WParamH uint16 +} + +type KbdInput struct { + typ uint32 + ki KEYBDINPUT +} + +type MouseInput struct { + typ uint32 + mi MOUSEINPUT +} + +type HardwareInput struct { + typ uint32 + hi HARDWAREINPUT +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx +type SYSTEMTIME struct { + Year uint16 + Month uint16 + DayOfWeek uint16 + Day uint16 + Hour uint16 + Minute uint16 + Second uint16 + Milliseconds uint16 +} + +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx +type KBDLLHOOKSTRUCT struct { + VkCode DWORD + ScanCode DWORD + Flags DWORD + Time DWORD + DwExtraInfo ULONG_PTR +} + +type HOOKPROC func(int, WPARAM, LPARAM) LRESULT + +type WINDOWPLACEMENT struct { + Length uint32 + Flags uint32 + ShowCmd uint32 + PtMinPosition POINT + PtMaxPosition POINT + RcNormalPosition RECT +} + +type SCROLLINFO struct { + CbSize uint32 + FMask uint32 + NMin int32 + NMax int32 + NPage uint32 + NPos int32 + NTrackPos int32 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/user32.go b/v2/internal/frontend/desktop/windows/winc/w32/user32.go new file mode 100644 index 000000000..a6a744d19 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/user32.go @@ -0,0 +1,1260 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "fmt" + "runtime" + "syscall" + "unsafe" +) + +var ( + moduser32 = syscall.NewLazyDLL("user32.dll") + + procRegisterClassEx = moduser32.NewProc("RegisterClassExW") + procLoadIcon = moduser32.NewProc("LoadIconW") + procLoadCursor = moduser32.NewProc("LoadCursorW") + procShowWindow = moduser32.NewProc("ShowWindow") + procShowWindowAsync = moduser32.NewProc("ShowWindowAsync") + procUpdateWindow = moduser32.NewProc("UpdateWindow") + procCreateWindowEx = moduser32.NewProc("CreateWindowExW") + procAdjustWindowRect = moduser32.NewProc("AdjustWindowRect") + procAdjustWindowRectEx = moduser32.NewProc("AdjustWindowRectEx") + procDestroyWindow = moduser32.NewProc("DestroyWindow") + procDefWindowProc = moduser32.NewProc("DefWindowProcW") + procDefDlgProc = moduser32.NewProc("DefDlgProcW") + procPostQuitMessage = moduser32.NewProc("PostQuitMessage") + procGetMessage = moduser32.NewProc("GetMessageW") + procTranslateMessage = moduser32.NewProc("TranslateMessage") + procDispatchMessage = moduser32.NewProc("DispatchMessageW") + procSendMessage = moduser32.NewProc("SendMessageW") + procPostMessage = moduser32.NewProc("PostMessageW") + procWaitMessage = moduser32.NewProc("WaitMessage") + procSetWindowText = moduser32.NewProc("SetWindowTextW") + procGetWindowTextLength = moduser32.NewProc("GetWindowTextLengthW") + procGetWindowText = moduser32.NewProc("GetWindowTextW") + procGetWindowRect = moduser32.NewProc("GetWindowRect") + procGetWindowInfo = moduser32.NewProc("GetWindowInfo") + procSetWindowCompositionAttribute = moduser32.NewProc("SetWindowCompositionAttribute") + procMoveWindow = moduser32.NewProc("MoveWindow") + procScreenToClient = moduser32.NewProc("ScreenToClient") + procCallWindowProc = moduser32.NewProc("CallWindowProcW") + procSetWindowLong = moduser32.NewProc("SetWindowLongW") + procSetWindowLongPtr = moduser32.NewProc("SetWindowLongW") + procGetWindowLong = moduser32.NewProc("GetWindowLongW") + procGetWindowLongPtr = moduser32.NewProc("GetWindowLongW") + procEnableWindow = moduser32.NewProc("EnableWindow") + procIsWindowEnabled = moduser32.NewProc("IsWindowEnabled") + procIsWindowVisible = moduser32.NewProc("IsWindowVisible") + procSetFocus = moduser32.NewProc("SetFocus") + procGetFocus = moduser32.NewProc("GetFocus") + procSetActiveWindow = moduser32.NewProc("SetActiveWindow") + procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow") + procBringWindowToTop = moduser32.NewProc("BringWindowToTop") + procInvalidateRect = moduser32.NewProc("InvalidateRect") + procGetClientRect = moduser32.NewProc("GetClientRect") + procGetDC = moduser32.NewProc("GetDC") + procReleaseDC = moduser32.NewProc("ReleaseDC") + procSetCapture = moduser32.NewProc("SetCapture") + procReleaseCapture = moduser32.NewProc("ReleaseCapture") + procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") + procMessageBox = moduser32.NewProc("MessageBoxW") + procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics") + procPostThreadMessageW = moduser32.NewProc("PostThreadMessageW") + procRegisterWindowMessageA = moduser32.NewProc("RegisterWindowMessageA") + //procSysColorBrush = moduser32.NewProc("GetSysColorBrush") + procCopyRect = moduser32.NewProc("CopyRect") + procEqualRect = moduser32.NewProc("EqualRect") + procInflateRect = moduser32.NewProc("InflateRect") + procIntersectRect = moduser32.NewProc("IntersectRect") + procIsRectEmpty = moduser32.NewProc("IsRectEmpty") + procOffsetRect = moduser32.NewProc("OffsetRect") + procPtInRect = moduser32.NewProc("PtInRect") + procSetRect = moduser32.NewProc("SetRect") + procSetRectEmpty = moduser32.NewProc("SetRectEmpty") + procSubtractRect = moduser32.NewProc("SubtractRect") + procUnionRect = moduser32.NewProc("UnionRect") + procCreateDialogParam = moduser32.NewProc("CreateDialogParamW") + procDialogBoxParam = moduser32.NewProc("DialogBoxParamW") + procGetDlgItem = moduser32.NewProc("GetDlgItem") + procDrawIcon = moduser32.NewProc("DrawIcon") + procCreateMenu = moduser32.NewProc("CreateMenu") + //procSetMenu = moduser32.NewProc("SetMenu") + procDestroyMenu = moduser32.NewProc("DestroyMenu") + procCreatePopupMenu = moduser32.NewProc("CreatePopupMenu") + procCheckMenuRadioItem = moduser32.NewProc("CheckMenuRadioItem") + //procDrawMenuBar = moduser32.NewProc("DrawMenuBar") + //procInsertMenuItem = moduser32.NewProc("InsertMenuItemW") // FIXIT: + + procClientToScreen = moduser32.NewProc("ClientToScreen") + procIsDialogMessage = moduser32.NewProc("IsDialogMessageW") + procIsWindow = moduser32.NewProc("IsWindow") + procEndDialog = moduser32.NewProc("EndDialog") + procPeekMessage = moduser32.NewProc("PeekMessageW") + procTranslateAccelerator = moduser32.NewProc("TranslateAcceleratorW") + procSetWindowPos = moduser32.NewProc("SetWindowPos") + procFillRect = moduser32.NewProc("FillRect") + procDrawText = moduser32.NewProc("DrawTextW") + procAddClipboardFormatListener = moduser32.NewProc("AddClipboardFormatListener") + procRemoveClipboardFormatListener = moduser32.NewProc("RemoveClipboardFormatListener") + procOpenClipboard = moduser32.NewProc("OpenClipboard") + procCloseClipboard = moduser32.NewProc("CloseClipboard") + procEnumClipboardFormats = moduser32.NewProc("EnumClipboardFormats") + procGetClipboardData = moduser32.NewProc("GetClipboardData") + procSetClipboardData = moduser32.NewProc("SetClipboardData") + procEmptyClipboard = moduser32.NewProc("EmptyClipboard") + procGetClipboardFormatName = moduser32.NewProc("GetClipboardFormatNameW") + procIsClipboardFormatAvailable = moduser32.NewProc("IsClipboardFormatAvailable") + procBeginPaint = moduser32.NewProc("BeginPaint") + procEndPaint = moduser32.NewProc("EndPaint") + procGetKeyboardState = moduser32.NewProc("GetKeyboardState") + procMapVirtualKey = moduser32.NewProc("MapVirtualKeyExW") + procGetAsyncKeyState = moduser32.NewProc("GetAsyncKeyState") + procToAscii = moduser32.NewProc("ToAscii") + procSwapMouseButton = moduser32.NewProc("SwapMouseButton") + procGetCursorPos = moduser32.NewProc("GetCursorPos") + procSetCursorPos = moduser32.NewProc("SetCursorPos") + procSetCursor = moduser32.NewProc("SetCursor") + procCreateIcon = moduser32.NewProc("CreateIcon") + procDestroyIcon = moduser32.NewProc("DestroyIcon") + procMonitorFromPoint = moduser32.NewProc("MonitorFromPoint") + procMonitorFromRect = moduser32.NewProc("MonitorFromRect") + procMonitorFromWindow = moduser32.NewProc("MonitorFromWindow") + procGetMonitorInfo = moduser32.NewProc("GetMonitorInfoW") + procGetDpiForSystem = moduser32.NewProc("GetDpiForSystem") + procGetDpiForWindow = moduser32.NewProc("GetDpiForWindow") + procEnumDisplayMonitors = moduser32.NewProc("EnumDisplayMonitors") + procEnumDisplaySettingsEx = moduser32.NewProc("EnumDisplaySettingsExW") + procChangeDisplaySettingsEx = moduser32.NewProc("ChangeDisplaySettingsExW") + procSendInput = moduser32.NewProc("SendInput") + procSetWindowsHookEx = moduser32.NewProc("SetWindowsHookExW") + procUnhookWindowsHookEx = moduser32.NewProc("UnhookWindowsHookEx") + procCallNextHookEx = moduser32.NewProc("CallNextHookEx") + + libuser32, _ = syscall.LoadLibrary("user32.dll") + insertMenuItem, _ = syscall.GetProcAddress(libuser32, "InsertMenuItemW") + setMenuItemInfo, _ = syscall.GetProcAddress(libuser32, "SetMenuItemInfoW") + setMenu, _ = syscall.GetProcAddress(libuser32, "SetMenu") + drawMenuBar, _ = syscall.GetProcAddress(libuser32, "DrawMenuBar") + trackPopupMenuEx, _ = syscall.GetProcAddress(libuser32, "TrackPopupMenuEx") + getKeyState, _ = syscall.GetProcAddress(libuser32, "GetKeyState") + getSysColorBrush, _ = syscall.GetProcAddress(libuser32, "GetSysColorBrush") + + getWindowPlacement, _ = syscall.GetProcAddress(libuser32, "GetWindowPlacement") + setWindowPlacement, _ = syscall.GetProcAddress(libuser32, "SetWindowPlacement") + + setScrollInfo, _ = syscall.GetProcAddress(libuser32, "SetScrollInfo") + getScrollInfo, _ = syscall.GetProcAddress(libuser32, "GetScrollInfo") + + mainThread HANDLE +) + +func init() { + runtime.LockOSThread() + mainThread = GetCurrentThreadId() +} + +func GET_X_LPARAM(lp uintptr) int32 { + return int32(int16(LOWORD(uint32(lp)))) +} + +func GET_Y_LPARAM(lp uintptr) int32 { + return int32(int16(HIWORD(uint32(lp)))) +} + +func RegisterClassEx(wndClassEx *WNDCLASSEX) ATOM { + ret, _, _ := procRegisterClassEx.Call(uintptr(unsafe.Pointer(wndClassEx))) + return ATOM(ret) +} + +func LoadIcon(instance HINSTANCE, iconName *uint16) HICON { + ret, _, _ := procLoadIcon.Call( + uintptr(instance), + uintptr(unsafe.Pointer(iconName))) + + return HICON(ret) +} + +func LoadCursor(instance HINSTANCE, cursorName *uint16) HCURSOR { + ret, _, _ := procLoadCursor.Call( + uintptr(instance), + uintptr(unsafe.Pointer(cursorName))) + + return HCURSOR(ret) + +} + +func ShowWindow(hwnd HWND, cmdshow int) bool { + ret, _, _ := procShowWindow.Call( + uintptr(hwnd), + uintptr(cmdshow)) + + return ret != 0 +} + +func ShowWindowAsync(hwnd HWND, cmdshow int) bool { + ret, _, _ := procShowWindowAsync.Call( + uintptr(hwnd), + uintptr(cmdshow)) + + return ret != 0 +} + +func UpdateWindow(hwnd HWND) bool { + ret, _, _ := procUpdateWindow.Call( + uintptr(hwnd)) + return ret != 0 +} + +func PostThreadMessage(threadID HANDLE, msg int, wp, lp uintptr) { + procPostThreadMessageW.Call(threadID, uintptr(msg), wp, lp) +} + +func RegisterWindowMessage(name *uint16) uint32 { + ret, _, _ := procRegisterWindowMessageA.Call( + uintptr(unsafe.Pointer(name))) + + return uint32(ret) +} + +func PostMainThreadMessage(msg uint32, wp, lp uintptr) bool { + ret, _, _ := procPostThreadMessageW.Call(mainThread, uintptr(msg), wp, lp) + return ret != 0 +} + +func CreateWindowEx(exStyle uint, className, windowName *uint16, + style uint, x, y, width, height int, parent HWND, menu HMENU, + instance HINSTANCE, param unsafe.Pointer) HWND { + ret, _, _ := procCreateWindowEx.Call( + uintptr(exStyle), + uintptr(unsafe.Pointer(className)), + uintptr(unsafe.Pointer(windowName)), + uintptr(style), + uintptr(x), + uintptr(y), + uintptr(width), + uintptr(height), + uintptr(parent), + uintptr(menu), + uintptr(instance), + uintptr(param)) + + return HWND(ret) +} + +func AdjustWindowRectEx(rect *RECT, style uint, menu bool, exStyle uint) bool { + ret, _, _ := procAdjustWindowRectEx.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(style), + uintptr(BoolToBOOL(menu)), + uintptr(exStyle)) + + return ret != 0 +} + +func AdjustWindowRect(rect *RECT, style uint, menu bool) bool { + ret, _, _ := procAdjustWindowRect.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(style), + uintptr(BoolToBOOL(menu))) + + return ret != 0 +} + +func DestroyWindow(hwnd HWND) bool { + ret, _, _ := procDestroyWindow.Call(hwnd) + return ret != 0 +} + +func HasGetDpiForWindowFunc() bool { + err := procGetDpiForWindow.Find() + return err == nil +} + +func GetDpiForWindow(hwnd HWND) UINT { + dpi, _, _ := procGetDpiForWindow.Call(hwnd) + return uint(dpi) +} + +func SetWindowCompositionAttribute(hwnd HWND, data *WINDOWCOMPOSITIONATTRIBDATA) bool { + if procSetWindowCompositionAttribute != nil { + ret, _, _ := procSetWindowCompositionAttribute.Call( + hwnd, + uintptr(unsafe.Pointer(data)), + ) + return ret != 0 + } + return false +} + +func DefWindowProc(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr { + ret, _, _ := procDefWindowProc.Call( + uintptr(hwnd), + uintptr(msg), + wParam, + lParam) + + return ret +} + +func DefDlgProc(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr { + ret, _, _ := procDefDlgProc.Call( + uintptr(hwnd), + uintptr(msg), + wParam, + lParam) + + return ret +} + +func PostQuitMessage(exitCode int) { + procPostQuitMessage.Call( + uintptr(exitCode)) +} + +func GetMessage(msg *MSG, hwnd HWND, msgFilterMin, msgFilterMax uint32) int { + ret, _, _ := procGetMessage.Call( + uintptr(unsafe.Pointer(msg)), + uintptr(hwnd), + uintptr(msgFilterMin), + uintptr(msgFilterMax)) + + return int(ret) +} + +func TranslateMessage(msg *MSG) bool { + ret, _, _ := procTranslateMessage.Call( + uintptr(unsafe.Pointer(msg))) + + return ret != 0 + +} + +func DispatchMessage(msg *MSG) uintptr { + ret, _, _ := procDispatchMessage.Call( + uintptr(unsafe.Pointer(msg))) + + return ret + +} + +func SendMessage(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr { + ret, _, _ := procSendMessage.Call( + uintptr(hwnd), + uintptr(msg), + wParam, + lParam) + + return ret +} + +func PostMessage(hwnd HWND, msg uint32, wParam, lParam uintptr) bool { + ret, _, _ := procPostMessage.Call( + uintptr(hwnd), + uintptr(msg), + wParam, + lParam) + + return ret != 0 +} + +func WaitMessage() bool { + ret, _, _ := procWaitMessage.Call() + return ret != 0 +} + +func SetWindowText(hwnd HWND, text string) { + procSetWindowText.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text)))) +} + +func GetWindowTextLength(hwnd HWND) int { + ret, _, _ := procGetWindowTextLength.Call( + uintptr(hwnd)) + + return int(ret) +} + +func GetWindowInfo(hwnd HWND, info *WINDOWINFO) int { + ret, _, _ := procGetWindowInfo.Call( + hwnd, + uintptr(unsafe.Pointer(info)), + ) + return int(ret) +} + +func GetWindowText(hwnd HWND) string { + textLen := GetWindowTextLength(hwnd) + 1 + + buf := make([]uint16, textLen) + procGetWindowText.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(textLen)) + + return syscall.UTF16ToString(buf) +} + +func GetWindowRect(hwnd HWND) *RECT { + var rect RECT + procGetWindowRect.Call( + hwnd, + uintptr(unsafe.Pointer(&rect))) + + return &rect +} + +func MoveWindow(hwnd HWND, x, y, width, height int, repaint bool) bool { + ret, _, _ := procMoveWindow.Call( + uintptr(hwnd), + uintptr(x), + uintptr(y), + uintptr(width), + uintptr(height), + uintptr(BoolToBOOL(repaint))) + + return ret != 0 + +} + +func ScreenToClient(hwnd HWND, x, y int) (X, Y int, ok bool) { + pt := POINT{X: int32(x), Y: int32(y)} + ret, _, _ := procScreenToClient.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&pt))) + + return int(pt.X), int(pt.Y), ret != 0 +} + +func CallWindowProc(preWndProc uintptr, hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr { + ret, _, _ := procCallWindowProc.Call( + preWndProc, + uintptr(hwnd), + uintptr(msg), + wParam, + lParam) + + return ret +} + +func SetWindowLong(hwnd HWND, index int, value uint32) uint32 { + ret, _, _ := procSetWindowLong.Call( + uintptr(hwnd), + uintptr(index), + uintptr(value)) + + return uint32(ret) +} + +func SetWindowLongPtr(hwnd HWND, index int, value uintptr) uintptr { + ret, _, _ := procSetWindowLongPtr.Call( + uintptr(hwnd), + uintptr(index), + value) + + return ret +} + +func GetWindowLong(hwnd HWND, index int) int32 { + ret, _, _ := procGetWindowLong.Call( + uintptr(hwnd), + uintptr(index)) + + return int32(ret) +} + +func GetWindowLongPtr(hwnd HWND, index int) uintptr { + ret, _, _ := procGetWindowLongPtr.Call( + uintptr(hwnd), + uintptr(index)) + + return ret +} + +func EnableWindow(hwnd HWND, b bool) bool { + ret, _, _ := procEnableWindow.Call( + uintptr(hwnd), + uintptr(BoolToBOOL(b))) + return ret != 0 +} + +func IsWindowEnabled(hwnd HWND) bool { + ret, _, _ := procIsWindowEnabled.Call( + uintptr(hwnd)) + + return ret != 0 +} + +func IsWindowVisible(hwnd HWND) bool { + ret, _, _ := procIsWindowVisible.Call( + uintptr(hwnd)) + + return ret != 0 +} + +func SetFocus(hwnd HWND) HWND { + ret, _, _ := procSetFocus.Call( + uintptr(hwnd)) + + return HWND(ret) +} + +func SetActiveWindow(hwnd HWND) HWND { + ret, _, _ := procSetActiveWindow.Call( + uintptr(hwnd)) + + return HWND(ret) +} + +func BringWindowToTop(hwnd HWND) bool { + ret, _, _ := procBringWindowToTop.Call(uintptr(hwnd)) + return ret != 0 +} + +func SetForegroundWindow(hwnd HWND) HWND { + ret, _, _ := procSetForegroundWindow.Call( + uintptr(hwnd)) + + return HWND(ret) +} + +func GetFocus() HWND { + ret, _, _ := procGetFocus.Call() + return HWND(ret) +} + +func InvalidateRect(hwnd HWND, rect *RECT, erase bool) bool { + ret, _, _ := procInvalidateRect.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(rect)), + uintptr(BoolToBOOL(erase))) + + return ret != 0 +} + +func GetClientRect(hwnd HWND) *RECT { + var rect RECT + ret, _, _ := procGetClientRect.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&rect))) + + if ret == 0 { + panic(fmt.Sprintf("GetClientRect(%d) failed", hwnd)) + } + + return &rect +} + +func GetDC(hwnd HWND) HDC { + ret, _, _ := procGetDC.Call( + uintptr(hwnd)) + + return HDC(ret) +} + +func ReleaseDC(hwnd HWND, hDC HDC) bool { + ret, _, _ := procReleaseDC.Call( + uintptr(hwnd), + uintptr(hDC)) + + return ret != 0 +} + +func SetCapture(hwnd HWND) HWND { + ret, _, _ := procSetCapture.Call( + uintptr(hwnd)) + + return HWND(ret) +} + +func ReleaseCapture() bool { + ret, _, _ := procReleaseCapture.Call() + + return ret != 0 +} + +func GetWindowThreadProcessId(hwnd HWND) (HANDLE, int) { + var processId int + ret, _, _ := procGetWindowThreadProcessId.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&processId))) + + return HANDLE(ret), processId +} + +func MessageBox(hwnd HWND, title, caption string, flags uint) int { + ret, _, _ := procMessageBox.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))), + uintptr(flags)) + + return int(ret) +} + +func GetSystemMetrics(index int) int { + ret, _, _ := procGetSystemMetrics.Call( + uintptr(index)) + + return int(ret) +} + +func GetSysColorBrush(nIndex int) HBRUSH { + /* + ret, _, _ := procSysColorBrush.Call(1, + uintptr(nIndex), + 0, + 0) + + return HBRUSH(ret) + */ + ret, _, _ := syscall.Syscall(getSysColorBrush, 1, + uintptr(nIndex), + 0, + 0) + + return HBRUSH(ret) +} + +func CopyRect(dst, src *RECT) bool { + ret, _, _ := procCopyRect.Call( + uintptr(unsafe.Pointer(dst)), + uintptr(unsafe.Pointer(src))) + + return ret != 0 +} + +func EqualRect(rect1, rect2 *RECT) bool { + ret, _, _ := procEqualRect.Call( + uintptr(unsafe.Pointer(rect1)), + uintptr(unsafe.Pointer(rect2))) + + return ret != 0 +} + +func InflateRect(rect *RECT, dx, dy int) bool { + ret, _, _ := procInflateRect.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(dx), + uintptr(dy)) + + return ret != 0 +} + +func IntersectRect(dst, src1, src2 *RECT) bool { + ret, _, _ := procIntersectRect.Call( + uintptr(unsafe.Pointer(dst)), + uintptr(unsafe.Pointer(src1)), + uintptr(unsafe.Pointer(src2))) + + return ret != 0 +} + +func IsRectEmpty(rect *RECT) bool { + ret, _, _ := procIsRectEmpty.Call( + uintptr(unsafe.Pointer(rect))) + + return ret != 0 +} + +func OffsetRect(rect *RECT, dx, dy int) bool { + ret, _, _ := procOffsetRect.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(dx), + uintptr(dy)) + + return ret != 0 +} + +func PtInRect(rect *RECT, x, y int) bool { + pt := POINT{X: int32(x), Y: int32(y)} + ret, _, _ := procPtInRect.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(unsafe.Pointer(&pt))) + + return ret != 0 +} + +func SetRect(rect *RECT, left, top, right, bottom int) bool { + ret, _, _ := procSetRect.Call( + uintptr(unsafe.Pointer(rect)), + uintptr(left), + uintptr(top), + uintptr(right), + uintptr(bottom)) + + return ret != 0 +} + +func SetRectEmpty(rect *RECT) bool { + ret, _, _ := procSetRectEmpty.Call( + uintptr(unsafe.Pointer(rect))) + + return ret != 0 +} + +func SubtractRect(dst, src1, src2 *RECT) bool { + ret, _, _ := procSubtractRect.Call( + uintptr(unsafe.Pointer(dst)), + uintptr(unsafe.Pointer(src1)), + uintptr(unsafe.Pointer(src2))) + + return ret != 0 +} + +func UnionRect(dst, src1, src2 *RECT) bool { + ret, _, _ := procUnionRect.Call( + uintptr(unsafe.Pointer(dst)), + uintptr(unsafe.Pointer(src1)), + uintptr(unsafe.Pointer(src2))) + + return ret != 0 +} + +func CreateDialog(hInstance HINSTANCE, lpTemplate *uint16, hWndParent HWND, lpDialogProc uintptr) HWND { + ret, _, _ := procCreateDialogParam.Call( + uintptr(hInstance), + uintptr(unsafe.Pointer(lpTemplate)), + uintptr(hWndParent), + lpDialogProc, + 0) + + return HWND(ret) +} + +func DialogBox(hInstance HINSTANCE, lpTemplateName *uint16, hWndParent HWND, lpDialogProc uintptr) int { + ret, _, _ := procDialogBoxParam.Call( + uintptr(hInstance), + uintptr(unsafe.Pointer(lpTemplateName)), + uintptr(hWndParent), + lpDialogProc, + 0) + + return int(ret) +} + +func GetDlgItem(hDlg HWND, nIDDlgItem int) HWND { + ret, _, _ := procGetDlgItem.Call( + uintptr(unsafe.Pointer(hDlg)), + uintptr(nIDDlgItem)) + + return HWND(ret) +} + +func DrawIcon(hDC HDC, x, y int, hIcon HICON) bool { + ret, _, _ := procDrawIcon.Call( + uintptr(unsafe.Pointer(hDC)), + uintptr(x), + uintptr(y), + uintptr(unsafe.Pointer(hIcon))) + + return ret != 0 +} + +func CreateMenu() HMENU { + ret, _, _ := procCreateMenu.Call(0, + 0, + 0, + 0) + + return HMENU(ret) +} + +func SetMenu(hWnd HWND, hMenu HMENU) bool { + ret, _, _ := syscall.Syscall(setMenu, 2, + uintptr(hWnd), + uintptr(hMenu), + 0) + + return ret != 0 +} + +// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-checkmenuradioitem +func SelectRadioMenuItem(menuID uint16, startID uint16, endID uint16, hwnd HWND) bool { + ret, _, _ := procCheckMenuRadioItem.Call( + hwnd, + uintptr(startID), + uintptr(endID), + uintptr(menuID), + MF_BYCOMMAND) + return ret != 0 + +} + +func CreatePopupMenu() HMENU { + ret, _, _ := procCreatePopupMenu.Call(0, + 0, + 0, + 0) + + return HMENU(ret) +} + +func TrackPopupMenuEx(hMenu HMENU, fuFlags uint32, x, y int32, hWnd HWND, lptpm *TPMPARAMS) BOOL { + ret, _, _ := syscall.Syscall6(trackPopupMenuEx, 6, + uintptr(hMenu), + uintptr(fuFlags), + uintptr(x), + uintptr(y), + uintptr(hWnd), + uintptr(unsafe.Pointer(lptpm))) + + return BOOL(ret) +} + +func DrawMenuBar(hWnd HWND) bool { + ret, _, _ := syscall.Syscall(drawMenuBar, 1, + uintptr(hWnd), + 0, + 0) + + return ret != 0 +} + +func InsertMenuItem(hMenu HMENU, uItem uint32, fByPosition bool, lpmii *MENUITEMINFO) bool { + ret, _, _ := syscall.Syscall6(insertMenuItem, 4, + uintptr(hMenu), + uintptr(uItem), + uintptr(BoolToBOOL(fByPosition)), + uintptr(unsafe.Pointer(lpmii)), + 0, + 0) + + return ret != 0 +} + +func SetMenuItemInfo(hMenu HMENU, uItem uint32, fByPosition bool, lpmii *MENUITEMINFO) bool { + ret, _, _ := syscall.Syscall6(setMenuItemInfo, 4, + uintptr(hMenu), + uintptr(uItem), + uintptr(BoolToBOOL(fByPosition)), + uintptr(unsafe.Pointer(lpmii)), + 0, + 0) + + return ret != 0 +} + +func ClientToScreen(hwnd HWND, x, y int) (int, int) { + pt := POINT{X: int32(x), Y: int32(y)} + + procClientToScreen.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&pt))) + + return int(pt.X), int(pt.Y) +} + +func IsDialogMessage(hwnd HWND, msg *MSG) bool { + ret, _, _ := procIsDialogMessage.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(msg))) + + return ret != 0 +} + +func IsWindow(hwnd HWND) bool { + ret, _, _ := procIsWindow.Call( + uintptr(hwnd)) + + return ret != 0 +} + +func EndDialog(hwnd HWND, nResult uintptr) bool { + ret, _, _ := procEndDialog.Call( + uintptr(hwnd), + nResult) + + return ret != 0 +} + +func PeekMessage(lpMsg *MSG, hwnd HWND, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool { + ret, _, _ := procPeekMessage.Call( + uintptr(unsafe.Pointer(lpMsg)), + uintptr(hwnd), + uintptr(wMsgFilterMin), + uintptr(wMsgFilterMax), + uintptr(wRemoveMsg)) + + return ret != 0 +} + +func TranslateAccelerator(hwnd HWND, hAccTable HACCEL, lpMsg *MSG) bool { + ret, _, _ := procTranslateMessage.Call( + uintptr(hwnd), + uintptr(hAccTable), + uintptr(unsafe.Pointer(lpMsg))) + + return ret != 0 +} + +func SetWindowPos(hwnd, hWndInsertAfter HWND, x, y, cx, cy int, uFlags uint) bool { + ret, _, _ := procSetWindowPos.Call( + uintptr(hwnd), + uintptr(hWndInsertAfter), + uintptr(x), + uintptr(y), + uintptr(cx), + uintptr(cy), + uintptr(uFlags)) + + return ret != 0 +} + +func FillRect(hDC HDC, lprc *RECT, hbr HBRUSH) bool { + ret, _, _ := procFillRect.Call( + uintptr(hDC), + uintptr(unsafe.Pointer(lprc)), + uintptr(hbr)) + + return ret != 0 +} + +func DrawText(hDC HDC, text string, uCount int, lpRect *RECT, uFormat uint) int { + ret, _, _ := procDrawText.Call( + uintptr(hDC), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))), + uintptr(uCount), + uintptr(unsafe.Pointer(lpRect)), + uintptr(uFormat)) + + return int(ret) +} + +func AddClipboardFormatListener(hwnd HWND) bool { + ret, _, _ := procAddClipboardFormatListener.Call( + uintptr(hwnd)) + return ret != 0 +} + +func RemoveClipboardFormatListener(hwnd HWND) bool { + ret, _, _ := procRemoveClipboardFormatListener.Call( + uintptr(hwnd)) + return ret != 0 +} + +func OpenClipboard(hWndNewOwner HWND) bool { + ret, _, _ := procOpenClipboard.Call( + uintptr(hWndNewOwner)) + return ret != 0 +} + +func CloseClipboard() bool { + ret, _, _ := procCloseClipboard.Call() + return ret != 0 +} + +func EnumClipboardFormats(format uint) uint { + ret, _, _ := procEnumClipboardFormats.Call( + uintptr(format)) + return uint(ret) +} + +func GetClipboardData(uFormat uint) HANDLE { + ret, _, _ := procGetClipboardData.Call( + uintptr(uFormat)) + return HANDLE(ret) +} + +func SetClipboardData(uFormat uint, hMem HANDLE) HANDLE { + ret, _, _ := procSetClipboardData.Call( + uintptr(uFormat), + uintptr(hMem)) + return HANDLE(ret) +} + +func EmptyClipboard() bool { + ret, _, _ := procEmptyClipboard.Call() + return ret != 0 +} + +func GetClipboardFormatName(format uint) (string, bool) { + cchMaxCount := 255 + buf := make([]uint16, cchMaxCount) + ret, _, _ := procGetClipboardFormatName.Call( + uintptr(format), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(cchMaxCount)) + + if ret > 0 { + return syscall.UTF16ToString(buf), true + } + + return "Requested format does not exist or is predefined", false +} + +func IsClipboardFormatAvailable(format uint) bool { + ret, _, _ := procIsClipboardFormatAvailable.Call(uintptr(format)) + return ret != 0 +} + +func BeginPaint(hwnd HWND, paint *PAINTSTRUCT) HDC { + ret, _, _ := procBeginPaint.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(paint))) + return HDC(ret) +} + +func EndPaint(hwnd HWND, paint *PAINTSTRUCT) { + procEndPaint.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(paint))) +} + +func GetKeyboardState(lpKeyState *[]byte) bool { + ret, _, _ := procGetKeyboardState.Call( + uintptr(unsafe.Pointer(&(*lpKeyState)[0]))) + return ret != 0 +} + +func MapVirtualKeyEx(uCode, uMapType uint, dwhkl HKL) uint { + ret, _, _ := procMapVirtualKey.Call( + uintptr(uCode), + uintptr(uMapType), + uintptr(dwhkl)) + return uint(ret) +} + +func GetAsyncKeyState(vKey int) uint16 { + ret, _, _ := procGetAsyncKeyState.Call(uintptr(vKey)) + return uint16(ret) +} + +func ToAscii(uVirtKey, uScanCode uint, lpKeyState *byte, lpChar *uint16, uFlags uint) int { + ret, _, _ := procToAscii.Call( + uintptr(uVirtKey), + uintptr(uScanCode), + uintptr(unsafe.Pointer(lpKeyState)), + uintptr(unsafe.Pointer(lpChar)), + uintptr(uFlags)) + return int(ret) +} + +func SwapMouseButton(fSwap bool) bool { + ret, _, _ := procSwapMouseButton.Call( + uintptr(BoolToBOOL(fSwap))) + return ret != 0 +} + +func GetCursorPos() (x, y int, ok bool) { + pt := POINT{} + ret, _, _ := procGetCursorPos.Call(uintptr(unsafe.Pointer(&pt))) + return int(pt.X), int(pt.Y), ret != 0 +} + +func SetCursorPos(x, y int) bool { + ret, _, _ := procSetCursorPos.Call( + uintptr(x), + uintptr(y), + ) + return ret != 0 +} + +func SetCursor(cursor HCURSOR) HCURSOR { + ret, _, _ := procSetCursor.Call( + uintptr(cursor), + ) + return HCURSOR(ret) +} + +func CreateIcon(instance HINSTANCE, nWidth, nHeight int, cPlanes, cBitsPerPixel byte, ANDbits, XORbits *byte) HICON { + ret, _, _ := procCreateIcon.Call( + uintptr(instance), + uintptr(nWidth), + uintptr(nHeight), + uintptr(cPlanes), + uintptr(cBitsPerPixel), + uintptr(unsafe.Pointer(ANDbits)), + uintptr(unsafe.Pointer(XORbits)), + ) + return HICON(ret) +} + +func DestroyIcon(icon HICON) bool { + ret, _, _ := procDestroyIcon.Call( + uintptr(icon), + ) + return ret != 0 +} + +func MonitorFromPoint(x, y int, dwFlags uint32) HMONITOR { + ret, _, _ := procMonitorFromPoint.Call( + uintptr(x), + uintptr(y), + uintptr(dwFlags), + ) + return HMONITOR(ret) +} + +func MonitorFromRect(rc *RECT, dwFlags uint32) HMONITOR { + ret, _, _ := procMonitorFromRect.Call( + uintptr(unsafe.Pointer(rc)), + uintptr(dwFlags), + ) + return HMONITOR(ret) +} + +func MonitorFromWindow(hwnd HWND, dwFlags uint32) HMONITOR { + ret, _, _ := procMonitorFromWindow.Call( + uintptr(hwnd), + uintptr(dwFlags), + ) + return HMONITOR(ret) +} + +func GetMonitorInfo(hMonitor HMONITOR, lmpi *MONITORINFO) bool { + ret, _, _ := procGetMonitorInfo.Call( + uintptr(hMonitor), + uintptr(unsafe.Pointer(lmpi)), + ) + return ret != 0 +} + +func EnumDisplayMonitors(hdc HDC, clip *RECT, fnEnum, dwData uintptr) bool { + ret, _, _ := procEnumDisplayMonitors.Call( + uintptr(hdc), + uintptr(unsafe.Pointer(clip)), + fnEnum, + dwData, + ) + return ret != 0 +} + +func EnumDisplaySettingsEx(szDeviceName *uint16, iModeNum uint32, devMode *DEVMODE, dwFlags uint32) bool { + ret, _, _ := procEnumDisplaySettingsEx.Call( + uintptr(unsafe.Pointer(szDeviceName)), + uintptr(iModeNum), + uintptr(unsafe.Pointer(devMode)), + uintptr(dwFlags), + ) + return ret != 0 +} + +func ChangeDisplaySettingsEx(szDeviceName *uint16, devMode *DEVMODE, hwnd HWND, dwFlags uint32, lParam uintptr) int32 { + ret, _, _ := procChangeDisplaySettingsEx.Call( + uintptr(unsafe.Pointer(szDeviceName)), + uintptr(unsafe.Pointer(devMode)), + uintptr(hwnd), + uintptr(dwFlags), + lParam, + ) + return int32(ret) +} + +/* +func SendInput(inputs []INPUT) uint32 { + var validInputs []C.INPUT + + for _, oneInput := range inputs { + input := C.INPUT{_type: C.DWORD(oneInput.Type)} + + switch oneInput.Type { + case INPUT_MOUSE: + (*MouseInput)(unsafe.Pointer(&input)).mi = oneInput.Mi + case INPUT_KEYBOARD: + (*KbdInput)(unsafe.Pointer(&input)).ki = oneInput.Ki + case INPUT_HARDWARE: + (*HardwareInput)(unsafe.Pointer(&input)).hi = oneInput.Hi + default: + panic("unkown type") + } + + validInputs = append(validInputs, input) + } + + ret, _, _ := procSendInput.Call( + uintptr(len(validInputs)), + uintptr(unsafe.Pointer(&validInputs[0])), + uintptr(unsafe.Sizeof(C.INPUT{})), + ) + return uint32(ret) +}*/ + +func SetWindowsHookEx(idHook int, lpfn HOOKPROC, hMod HINSTANCE, dwThreadId DWORD) HHOOK { + ret, _, _ := procSetWindowsHookEx.Call( + uintptr(idHook), + uintptr(syscall.NewCallback(lpfn)), + uintptr(hMod), + uintptr(dwThreadId), + ) + return HHOOK(ret) +} + +func UnhookWindowsHookEx(hhk HHOOK) bool { + ret, _, _ := procUnhookWindowsHookEx.Call( + uintptr(hhk), + ) + return ret != 0 +} + +func CallNextHookEx(hhk HHOOK, nCode int, wParam WPARAM, lParam LPARAM) LRESULT { + ret, _, _ := procCallNextHookEx.Call( + uintptr(hhk), + uintptr(nCode), + uintptr(wParam), + uintptr(lParam), + ) + return LRESULT(ret) +} + +func GetKeyState(nVirtKey int32) int16 { + ret, _, _ := syscall.Syscall(getKeyState, 1, + uintptr(nVirtKey), + 0, + 0) + + return int16(ret) +} + +func DestroyMenu(hMenu HMENU) bool { + ret, _, _ := procDestroyMenu.Call(1, + uintptr(hMenu), + 0, + 0) + + return ret != 0 +} + +func GetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool { + ret, _, _ := syscall.Syscall(getWindowPlacement, 2, + uintptr(hWnd), + uintptr(unsafe.Pointer(lpwndpl)), + 0) + + return ret != 0 +} + +func SetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool { + ret, _, _ := syscall.Syscall(setWindowPlacement, 2, + uintptr(hWnd), + uintptr(unsafe.Pointer(lpwndpl)), + 0) + + return ret != 0 +} + +func SetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO, fRedraw bool) int32 { + ret, _, _ := syscall.Syscall6(setScrollInfo, 4, + hwnd, + uintptr(fnBar), + uintptr(unsafe.Pointer(lpsi)), + uintptr(BoolToBOOL(fRedraw)), + 0, + 0) + + return int32(ret) +} + +func GetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO) bool { + ret, _, _ := syscall.Syscall(getScrollInfo, 3, + hwnd, + uintptr(fnBar), + uintptr(unsafe.Pointer(lpsi))) + + return ret != 0 +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/utils.go b/v2/internal/frontend/desktop/windows/winc/w32/utils.go new file mode 100644 index 000000000..cb8d354d0 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/utils.go @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unicode/utf16" + "unsafe" +) + +func MustLoadLibrary(name string) uintptr { + lib, err := syscall.LoadLibrary(name) + if err != nil { + panic(err) + } + + return uintptr(lib) +} + +func MustGetProcAddress(lib uintptr, name string) uintptr { + addr, err := syscall.GetProcAddress(syscall.Handle(lib), name) + if err != nil { + panic(err) + } + + return uintptr(addr) +} + +func SUCCEEDED(hr HRESULT) bool { + return hr >= 0 +} + +func FAILED(hr HRESULT) bool { + return hr < 0 +} + +func MakeIntResource(id uint16) *uint16 { + return (*uint16)(unsafe.Pointer(uintptr(id))) +} + +func LOWORD(dw uint32) uint16 { + return uint16(dw) +} + +func HIWORD(dw uint32) uint16 { + return uint16(dw >> 16 & 0xffff) +} + +func MAKELONG(lo, hi uint16) uint32 { + return uint32(uint32(lo) | ((uint32(hi)) << 16)) +} + +func BoolToBOOL(value bool) BOOL { + if value { + return 1 + } + + return 0 +} + +func UTF16PtrToString(cstr *uint16) string { + if cstr != nil { + us := make([]uint16, 0, 256) + for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 { + u := *(*uint16)(unsafe.Pointer(p)) + if u == 0 { + return string(utf16.Decode(us)) + } + us = append(us, u) + } + } + + return "" +} + +func ComAddRef(unknown *IUnknown) int32 { + ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1, + uintptr(unsafe.Pointer(unknown)), + 0, + 0) + return int32(ret) +} + +func ComRelease(unknown *IUnknown) int32 { + ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1, + uintptr(unsafe.Pointer(unknown)), + 0, + 0) + return int32(ret) +} + +func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch { + var disp *IDispatch + hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3, + uintptr(unsafe.Pointer(unknown)), + uintptr(unsafe.Pointer(id)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + panic("Invoke QieryInterface error.") + } + return disp +} + +func ComGetIDsOfName(disp *IDispatch, names []string) []int32 { + wnames := make([]*uint16, len(names)) + dispid := make([]int32, len(names)) + for i := 0; i < len(names); i++ { + wnames[i] = syscall.StringToUTF16Ptr(names[i]) + } + hr, _, _ := syscall.Syscall6(disp.lpVtbl.pGetIDsOfNames, 6, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(unsafe.Pointer(&wnames[0])), + uintptr(len(names)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&dispid[0]))) + if hr != 0 { + panic("Invoke GetIDsOfName error.") + } + return dispid +} + +func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT) { + var dispparams DISPPARAMS + + if dispatch&DISPATCH_PROPERTYPUT != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.RgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.CNamedArgs = 1 + } + var vargs []VARIANT + if len(params) > 0 { + vargs = make([]VARIANT, len(params)) + for i, v := range params { + //n := len(params)-i-1 + n := len(params) - i - 1 + VariantInit(&vargs[n]) + switch v.(type) { + case bool: + if v.(bool) { + vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff} + } else { + vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0} + } + case *bool: + vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))} + case byte: + vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))} + case *byte: + vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))} + case int16: + vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))} + case *int16: + vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))} + case uint16: + vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))} + case *uint16: + vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))} + case int, int32: + vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))} + case *int, *int32: + vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))} + case uint, uint32: + vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))} + case *uint, *uint32: + vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))} + case int64: + vargs[n] = VARIANT{VT_I8, 0, 0, 0, v.(int64)} + case *int64: + vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))} + case uint64: + vargs[n] = VARIANT{VT_UI8, 0, 0, 0, int64(v.(uint64))} + case *uint64: + vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))} + case float32: + vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))} + case *float32: + vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))} + case float64: + vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))} + case *float64: + vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))} + case string: + vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))} + case *string: + vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))} + case *IDispatch: + vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))} + case **IDispatch: + vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))} + case nil: + vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0} + case *VARIANT: + vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))} + default: + panic("unknown type") + } + } + dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0])) + dispparams.CArgs = uint32(len(params)) + } + + var ret VARIANT + var excepInfo EXCEPINFO + VariantInit(&ret) + hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8, + uintptr(unsafe.Pointer(disp)), + uintptr(dispid), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(GetUserDefaultLCID()), + uintptr(dispatch), + uintptr(unsafe.Pointer(&dispparams)), + uintptr(unsafe.Pointer(&ret)), + uintptr(unsafe.Pointer(&excepInfo)), + 0) + if hr != 0 { + if excepInfo.BstrDescription != nil { + bs := UTF16PtrToString(excepInfo.BstrDescription) + panic(bs) + } + } + for _, varg := range vargs { + if varg.VT == VT_BSTR && varg.Val != 0 { + SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) + } + } + result = &ret + return +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go new file mode 100644 index 000000000..67b028722 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +import ( + "syscall" + "unsafe" +) + +// LISTVIEW parts +const ( + LVP_LISTITEM = 1 + LVP_LISTGROUP = 2 + LVP_LISTDETAIL = 3 + LVP_LISTSORTEDDETAIL = 4 + LVP_EMPTYTEXT = 5 + LVP_GROUPHEADER = 6 + LVP_GROUPHEADERLINE = 7 + LVP_EXPANDBUTTON = 8 + LVP_COLLAPSEBUTTON = 9 + LVP_COLUMNDETAIL = 10 +) + +// LVP_LISTITEM states +const ( + LISS_NORMAL = 1 + LISS_HOT = 2 + LISS_SELECTED = 3 + LISS_DISABLED = 4 + LISS_SELECTEDNOTFOCUS = 5 + LISS_HOTSELECTED = 6 +) + +// TREEVIEW parts +const ( + TVP_TREEITEM = 1 + TVP_GLYPH = 2 + TVP_BRANCH = 3 + TVP_HOTGLYPH = 4 +) + +// TVP_TREEITEM states +const ( + TREIS_NORMAL = 1 + TREIS_HOT = 2 + TREIS_SELECTED = 3 + TREIS_DISABLED = 4 + TREIS_SELECTEDNOTFOCUS = 5 + TREIS_HOTSELECTED = 6 +) + +type HTHEME HANDLE + +var ( + // Library + libuxtheme uintptr + + // Functions + closeThemeData uintptr + drawThemeBackground uintptr + drawThemeText uintptr + getThemeTextExtent uintptr + openThemeData uintptr + setWindowTheme uintptr +) + +func init() { + // Library + libuxtheme = MustLoadLibrary("uxtheme.dll") + + // Functions + closeThemeData = MustGetProcAddress(libuxtheme, "CloseThemeData") + drawThemeBackground = MustGetProcAddress(libuxtheme, "DrawThemeBackground") + drawThemeText = MustGetProcAddress(libuxtheme, "DrawThemeText") + getThemeTextExtent = MustGetProcAddress(libuxtheme, "GetThemeTextExtent") + openThemeData = MustGetProcAddress(libuxtheme, "OpenThemeData") + setWindowTheme = MustGetProcAddress(libuxtheme, "SetWindowTheme") +} + +func CloseThemeData(hTheme HTHEME) HRESULT { + ret, _, _ := syscall.Syscall(closeThemeData, 1, + uintptr(hTheme), + 0, + 0) + + return HRESULT(ret) +} + +func DrawThemeBackground(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pRect, pClipRect *RECT) HRESULT { + ret, _, _ := syscall.Syscall6(drawThemeBackground, 6, + uintptr(hTheme), + uintptr(hdc), + uintptr(iPartId), + uintptr(iStateId), + uintptr(unsafe.Pointer(pRect)), + uintptr(unsafe.Pointer(pClipRect))) + + return HRESULT(ret) +} + +func DrawThemeText(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText *uint16, iCharCount int32, dwTextFlags, dwTextFlags2 uint32, pRect *RECT) HRESULT { + ret, _, _ := syscall.Syscall9(drawThemeText, 9, + uintptr(hTheme), + uintptr(hdc), + uintptr(iPartId), + uintptr(iStateId), + uintptr(unsafe.Pointer(pszText)), + uintptr(iCharCount), + uintptr(dwTextFlags), + uintptr(dwTextFlags2), + uintptr(unsafe.Pointer(pRect))) + + return HRESULT(ret) +} + +func GetThemeTextExtent(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText *uint16, iCharCount int32, dwTextFlags uint32, pBoundingRect, pExtentRect *RECT) HRESULT { + ret, _, _ := syscall.Syscall9(getThemeTextExtent, 9, + uintptr(hTheme), + uintptr(hdc), + uintptr(iPartId), + uintptr(iStateId), + uintptr(unsafe.Pointer(pszText)), + uintptr(iCharCount), + uintptr(dwTextFlags), + uintptr(unsafe.Pointer(pBoundingRect)), + uintptr(unsafe.Pointer(pExtentRect))) + + return HRESULT(ret) +} + +func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME { + ret, _, _ := syscall.Syscall(openThemeData, 2, + uintptr(hwnd), + uintptr(unsafe.Pointer(pszClassList)), + 0) + + return HTHEME(ret) +} + +func SetWindowTheme(hwnd HWND, pszSubAppName, pszSubIdList *uint16) HRESULT { + ret, _, _ := syscall.Syscall(setWindowTheme, 3, + uintptr(hwnd), + uintptr(unsafe.Pointer(pszSubAppName)), + uintptr(unsafe.Pointer(pszSubIdList))) + + return HRESULT(ret) +} diff --git a/v2/internal/frontend/desktop/windows/winc/w32/vars.go b/v2/internal/frontend/desktop/windows/winc/w32/vars.go new file mode 100644 index 000000000..53bc6cb8b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/vars.go @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved. + * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved. + */ + +package w32 + +var ( + IID_NULL = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}} + IID_IUnknown = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} + IID_IDispatch = &GUID{0x00020400, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} + IID_IConnectionPointContainer = &GUID{0xB196B284, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}} + IID_IConnectionPoint = &GUID{0xB196B286, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}} +) diff --git a/v2/internal/frontend/desktop/windows/winc/wndproc.go b/v2/internal/frontend/desktop/windows/winc/wndproc.go new file mode 100644 index 000000000..24490d74b --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/wndproc.go @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2019 The Winc Authors. All Rights Reserved. + * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. + */ + +package winc + +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" +) + +var wmInvokeCallback uint32 + +func init() { + wmInvokeCallback = RegisterWindowMessage("WincV0.InvokeCallback") +} + +func genPoint(p uintptr) (x, y int) { + x = int(w32.LOWORD(uint32(p))) + y = int(w32.HIWORD(uint32(p))) + return +} + +func genMouseEventArg(wparam, lparam uintptr) *MouseEventData { + var data MouseEventData + data.Button = int(wparam) + data.X, data.Y = genPoint(lparam) + + return &data +} + +func genDropFilesEventArg(wparam uintptr) *DropFilesEventData { + hDrop := w32.HDROP(wparam) + + var data DropFilesEventData + _, fileCount := w32.DragQueryFile(hDrop, 0xFFFFFFFF) + data.Files = make([]string, fileCount) + + var i uint + for i = 0; i < fileCount; i++ { + data.Files[i], _ = w32.DragQueryFile(hDrop, i) + } + + data.X, data.Y, _ = w32.DragQueryPoint(hDrop) + w32.DragFinish(hDrop) + return &data +} + +func generalWndProc(hwnd w32.HWND, msg uint32, wparam, lparam uintptr) uintptr { + + switch msg { + case w32.WM_HSCROLL: + //println("case w32.WM_HSCROLL") + + case w32.WM_VSCROLL: + //println("case w32.WM_VSCROLL") + } + + if controller := GetMsgHandler(hwnd); controller != nil { + ret := controller.WndProc(msg, wparam, lparam) + + switch msg { + case w32.WM_NOTIFY: //Reflect notification to control + nm := (*w32.NMHDR)(unsafe.Pointer(lparam)) + if controller := GetMsgHandler(nm.HwndFrom); controller != nil { + ret := controller.WndProc(msg, wparam, lparam) + if ret != 0 { + w32.SetWindowLong(hwnd, w32.DWL_MSGRESULT, uint32(ret)) + return w32.TRUE + } + } + case w32.WM_COMMAND: + if lparam != 0 { //Reflect message to control + h := w32.HWND(lparam) + if controller := GetMsgHandler(h); controller != nil { + ret := controller.WndProc(msg, wparam, lparam) + if ret != 0 { + w32.SetWindowLong(hwnd, w32.DWL_MSGRESULT, uint32(ret)) + return w32.TRUE + } + } + } + case w32.WM_CLOSE: + controller.OnClose().Fire(NewEvent(controller, nil)) + case w32.WM_KILLFOCUS: + controller.OnKillFocus().Fire(NewEvent(controller, nil)) + case w32.WM_SETFOCUS: + controller.OnSetFocus().Fire(NewEvent(controller, nil)) + case w32.WM_DROPFILES: + controller.OnDropFiles().Fire(NewEvent(controller, genDropFilesEventArg(wparam))) + case w32.WM_CONTEXTMENU: + if wparam != 0 { //Reflect message to control + h := w32.HWND(wparam) + if controller := GetMsgHandler(h); controller != nil { + contextMenu := controller.ContextMenu() + x, y := genPoint(lparam) + + if contextMenu != nil { + id := w32.TrackPopupMenuEx( + contextMenu.hMenu, + w32.TPM_NOANIMATION|w32.TPM_RETURNCMD, + int32(x), + int32(y), + controller.Handle(), + nil) + + item := findMenuItemByID(int(id)) + if item != nil { + item.OnClick().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + } + return 0 + } + } + } + + case w32.WM_LBUTTONDOWN: + controller.OnLBDown().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_LBUTTONUP: + controller.OnLBUp().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_LBUTTONDBLCLK: + controller.OnLBDbl().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_MBUTTONDOWN: + controller.OnMBDown().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_MBUTTONUP: + controller.OnMBUp().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_RBUTTONDOWN: + controller.OnRBDown().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_RBUTTONUP: + controller.OnRBUp().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_RBUTTONDBLCLK: + controller.OnRBDbl().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_MOUSEMOVE: + controller.OnMouseMove().Fire(NewEvent(controller, genMouseEventArg(wparam, lparam))) + case w32.WM_PAINT: + canvas := NewCanvasFromHwnd(hwnd) + defer canvas.Dispose() + controller.OnPaint().Fire(NewEvent(controller, &PaintEventData{Canvas: canvas})) + case w32.WM_KEYUP: + controller.OnKeyUp().Fire(NewEvent(controller, &KeyUpEventData{int(wparam), int(lparam)})) + case w32.WM_SIZE: + x, y := genPoint(lparam) + controller.OnSize().Fire(NewEvent(controller, &SizeEventData{uint(wparam), x, y})) + case wmInvokeCallback: + controller.invokeCallbacks() + } + return ret + } + + return w32.DefWindowProc(hwnd, uint32(msg), wparam, lparam) +} diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go index 3d7b3c244..985a509a7 100644 --- a/v2/internal/frontend/desktop/windows/window.go +++ b/v2/internal/frontend/desktop/windows/window.go @@ -7,8 +7,8 @@ import ( "github.com/wailsapp/wails/v2/internal/system/operatingsystem" "unsafe" - "github.com/leaanthony/winc" - "github.com/leaanthony/winc/w32" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/options" ) diff --git a/v2/internal/gomod/gomod_test.go b/v2/internal/gomod/gomod_test.go index 01b001abf..a901da0e1 100644 --- a/v2/internal/gomod/gomod_test.go +++ b/v2/internal/gomod/gomod_test.go @@ -29,11 +29,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -92,11 +92,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -133,11 +133,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -173,11 +173,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -214,11 +214,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -255,11 +255,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -298,11 +298,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -342,11 +342,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -444,11 +444,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -485,11 +485,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -526,11 +526,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect @@ -570,11 +570,11 @@ require ( github.com/leaanthony/debme v1.2.1 // indirect github.com/leaanthony/go-ansi-parser v1.0.1 // indirect github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect - github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.5.0 // indirect github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect - github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect + github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc v0.0.0-20210921073452-54963136bf18 // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect diff --git a/v2/internal/system/system_windows.go b/v2/internal/system/system_windows.go index ce8c90028..4bb6d6707 100644 --- a/v2/internal/system/system_windows.go +++ b/v2/internal/system/system_windows.go @@ -4,7 +4,7 @@ package system import ( - "github.com/leaanthony/go-webview2/webviewloader" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader" "github.com/wailsapp/wails/v2/internal/system/operatingsystem" "github.com/wailsapp/wails/v2/internal/system/packagemanager" ) diff --git a/v2/pkg/commands/build/base.go b/v2/pkg/commands/build/base.go index 6e7b9caf5..6c5b09ffa 100644 --- a/v2/pkg/commands/build/base.go +++ b/v2/pkg/commands/build/base.go @@ -13,7 +13,6 @@ import ( "github.com/wailsapp/wails/v2/internal/system" "github.com/leaanthony/gosod" - wailsRuntime "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/frontend/runtime/wrapper" "github.com/pkg/errors" @@ -436,16 +435,6 @@ func generateRuntimeWrapper(options *Options) error { return err } - //ipcdev.js - err = os.WriteFile(filepath.Join(wrapperDir, "ipcdev.js"), wailsRuntime.DesktopIPC, 0755) - if err != nil { - return err - } - //runtimedev.js - err = os.WriteFile(filepath.Join(wrapperDir, "runtimedev.js"), wailsRuntime.RuntimeDesktopJS, 0755) - if err != nil { - return err - } return nil } diff --git a/website/docs/reference/cli.mdx b/website/docs/reference/cli.mdx index 13b0bae00..30a6466c3 100644 --- a/website/docs/reference/cli.mdx +++ b/website/docs/reference/cli.mdx @@ -173,9 +173,8 @@ Your system is ready for Wails development! | -devserverurl "url" | Use 3rd party dev server url, EG Vite | "http://localhost:34115" | | -appargs "args" | Arguments passed to the application in shell style | | | -platform "platform" | Platform/Arch to target | `runtime.GOOS` | - -If the `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce` or `devserverurl` flags are provided on the command line, they are saved in -`wails.json`, and become the defaults for subsequent invocations. +| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce` and `devserverurl` flags in + `wails.json` to become the defaults for subsequent invocations. | | Example: