func NewWebView(parent Container) (*WebView, error) { if hr := win.OleInitialize(); hr != win.S_OK && hr != win.S_FALSE { return nil, newError(fmt.Sprint("OleInitialize Error: ", hr)) } wv := &WebView{ clientSite: webViewIOleClientSite{ IOleClientSite: win.IOleClientSite{ LpVtbl: webViewIOleClientSiteVtbl, }, inPlaceSite: webViewIOleInPlaceSite{ IOleInPlaceSite: win.IOleInPlaceSite{ LpVtbl: webViewIOleInPlaceSiteVtbl, }, inPlaceFrame: webViewIOleInPlaceFrame{ IOleInPlaceFrame: win.IOleInPlaceFrame{ LpVtbl: webViewIOleInPlaceFrameVtbl, }, }, }, docHostUIHandler: webViewIDocHostUIHandler{ IDocHostUIHandler: win.IDocHostUIHandler{ LpVtbl: webViewIDocHostUIHandlerVtbl, }, }, webBrowserEvents2: webViewDWebBrowserEvents2{ DWebBrowserEvents2: win.DWebBrowserEvents2{ LpVtbl: webViewDWebBrowserEvents2Vtbl, }, }, }, } if err := InitWidget( wv, parent, webViewWindowClass, win.WS_CLIPCHILDREN|win.WS_VISIBLE, 0); err != nil { return nil, err } wv.clientSite.inPlaceSite.inPlaceFrame.webView = wv succeeded := false defer func() { if !succeeded { wv.Dispose() } }() var classFactoryPtr unsafe.Pointer if hr := win.CoGetClassObject(&win.CLSID_WebBrowser, win.CLSCTX_INPROC_HANDLER|win.CLSCTX_INPROC_SERVER, nil, &win.IID_IClassFactory, &classFactoryPtr); win.FAILED(hr) { return nil, errorFromHRESULT("CoGetClassObject", hr) } classFactory := (*win.IClassFactory)(classFactoryPtr) defer classFactory.Release() var browserObjectPtr unsafe.Pointer if hr := classFactory.CreateInstance(nil, &win.IID_IOleObject, &browserObjectPtr); win.FAILED(hr) { return nil, errorFromHRESULT("IClassFactory.CreateInstance", hr) } browserObject := (*win.IOleObject)(browserObjectPtr) wv.browserObject = browserObject if hr := browserObject.SetClientSite((*win.IOleClientSite)(unsafe.Pointer(&wv.clientSite))); win.FAILED(hr) { return nil, errorFromHRESULT("IOleObject.SetClientSite", hr) } if hr := browserObject.SetHostNames(syscall.StringToUTF16Ptr("Walk.WebView"), nil); win.FAILED(hr) { return nil, errorFromHRESULT("IOleObject.SetHostNames", hr) } if hr := win.OleSetContainedObject((*win.IUnknown)(unsafe.Pointer(browserObject)), true); win.FAILED(hr) { return nil, errorFromHRESULT("OleSetContainedObject", hr) } var rect win.RECT win.GetClientRect(wv.hWnd, &rect) if hr := browserObject.DoVerb(win.OLEIVERB_SHOW, nil, (*win.IOleClientSite)(unsafe.Pointer(&wv.clientSite)), -1, wv.hWnd, &rect); win.FAILED(hr) { return nil, errorFromHRESULT("IOleObject.DoVerb", hr) } var cpcPtr unsafe.Pointer if hr := browserObject.QueryInterface(&win.IID_IConnectionPointContainer, &cpcPtr); win.FAILED(hr) { return nil, errorFromHRESULT("IOleObject.QueryInterface(IID_IConnectionPointContainer)", hr) } cpc := (*win.IConnectionPointContainer)(cpcPtr) defer cpc.Release() var cp *win.IConnectionPoint if hr := cpc.FindConnectionPoint(&win.DIID_DWebBrowserEvents2, &cp); win.FAILED(hr) { return nil, errorFromHRESULT("IConnectionPointContainer.FindConnectionPoint(DIID_DWebBrowserEvents2)", hr) } defer cp.Release() var cookie uint32 if hr := cp.Advise(unsafe.Pointer(&wv.clientSite.webBrowserEvents2), &cookie); win.FAILED(hr) { return nil, errorFromHRESULT("IConnectionPoint.Advise", hr) } wv.onResize() wv.MustRegisterProperty("URL", NewProperty( func() interface{} { url, _ := wv.URL() return url }, func(v interface{}) error { return wv.SetURL(v.(string)) }, wv.urlChangedPublisher.Event())) succeeded = true return wv, nil }
func (dlg *FileDialog) ShowBrowseFolder(owner Form) (accepted bool, err error) { // Calling OleInitialize (or similar) is required for BIF_NEWDIALOGSTYLE. if hr := win.OleInitialize(); hr != win.S_OK && hr != win.S_FALSE { return false, newError(fmt.Sprint("OleInitialize Error: ", hr)) } defer win.OleUninitialize() pathFromPIDL := func(pidl uintptr) (string, error) { var path [win.MAX_PATH]uint16 if !win.SHGetPathFromIDList(pidl, &path[0]) { return "", newError("SHGetPathFromIDList failed") } return syscall.UTF16ToString(path[:]), nil } // We use this callback to disable the OK button in case of "invalid" // selections. callback := func(hwnd win.HWND, msg uint32, lp, wp uintptr) uintptr { const BFFM_SELCHANGED = 2 if msg == BFFM_SELCHANGED { _, err := pathFromPIDL(lp) var enabled uintptr if err == nil { enabled = 1 } const BFFM_ENABLEOK = win.WM_USER + 101 win.SendMessage(hwnd, BFFM_ENABLEOK, 0, enabled) } return 0 } var ownerHwnd win.HWND if owner != nil { ownerHwnd = owner.Handle() } // We need to put the initial path into a buffer of at least MAX_LENGTH // length, or we may get random crashes. var buf [win.MAX_PATH]uint16 copy(buf[:], syscall.StringToUTF16(dlg.InitialDirPath)) const BIF_NEWDIALOGSTYLE = 0x00000040 bi := win.BROWSEINFO{ HwndOwner: ownerHwnd, PszDisplayName: &buf[0], LpszTitle: syscall.StringToUTF16Ptr(dlg.Title), UlFlags: BIF_NEWDIALOGSTYLE, Lpfn: syscall.NewCallback(callback), } pidl := win.SHBrowseForFolder(&bi) if pidl == 0 { return false, nil } defer win.CoTaskMemFree(pidl) dlg.FilePath, err = pathFromPIDL(pidl) accepted = dlg.FilePath != "" return }