如何用golang远程控制浏览器
浏览器作为现代桌面UI应用已经成为一个强大的存在,网上有很多关于webview的,但是作为操作系统自带的浏览器也是一个很重要的应用场景,如何控制浏览器界面,还有一种思路,采用窗体句柄的方式(内部控制还在摸索中,目前通过子窗体遍历好像不能获取URL),获取窗体句柄后就可以对其发消息,设置窗体显示属性,实现控制
func (_this *UIWebExtern) Init(msg Message) *UIWebExtern {
OpenWithBrowser(msg.Noticeurl)
time.Sleep(1 * time.Second)
_this.c = make(chan int)
var hWnd win.HWND
for {
hwnd, err := GetWindowHwndByName("msedge.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
hwnd, err = GetWindowHwndByName("chrome.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
hwnd, err = GetWindowHwndByName("msedge.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
hwnd, err = GetWindowHwndByName("firfox.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
hwnd, err = GetWindowHwndByName("QQBrowser.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
hwnd, err = GetWindowHwndByName("360Browser.exe")
if err == nil {
hWnd = win.HWND(unsafe.Pointer(hwnd))
if IsMyWindowsHwnd(hWnd) {
_this.Hwnd = hWnd
break
}
}
time.Sleep(2 * time.Second)
}
style := win.GetWindowLong(_this.Hwnd, win.GWL_STYLE)
if msg.NoBorder {
style &= ^win.WS_SIZEBOX & ^win.WS_CAPTION
} else {
style |= win.WS_SIZEBOX | win.WS_CAPTION
}
win.MoveWindow(_this.Hwnd, int32(msg.UIpos.Startx), int32(msg.UIpos.Starty), int32(msg.UIpos.Width), int32(msg.UIpos.Height), true)
if msg.TopMost {
fmt.Print("TopMost\n")
_this.bTopMost = true
win.SetWindowPos(_this.Hwnd, win.HWND_TOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE)
} else {
win.SetWindowPos(_this.Hwnd, win.HWND_NOTOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE)
}
win.SetWindowLong(_this.Hwnd, win.GWL_STYLE, style)
if msg.FullScreen {
win.SendMessage(_this.Hwnd, win.WM_KEYDOWN, 0x0000007A, 0x20380001)
//time.Sleep(1 * time.Second)
win.SendMessage(_this.Hwnd, win.WM_KEYUP, 0x0000007A, 0x003C0001)
}
GetCurrentUrl(_this.Hwnd)
return _this
}
func OpenWithBrowser(url string) error {
switch runtime.GOOS {
case "linux":
return exec.Command("xdg-open", url).Start()
case "windows":
return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
return exec.Command("open", url).Start()
default:
return fmt.Errorf("runtime.GOOS %s is not supported", runtime.GOOS)
}
}
func GetWindowHwndByName(name string) (uintptr, error) {
proc, err := FindProcessByName(name)
if err != nil {
return 0, err
}
hwnd, err := GetWindowHwndByPID(proc.ProcessID)
if err != nil {
return 0, err
}
return hwnd, nil
}
func GetWindowHwndByPID(dwProcessID int) (uintptr, error) {
//func PostKey(key uint8) (uintptr, error) {
var user32 = syscall.NewLazyDLL("user32.dll")
//var p *os.Process
Pid := dwProcessID
EnumWindows := func(enumFunc uintptr, lparam uintptr) {
user32.NewProc("EnumWindows").Call(uintptr(enumFunc), uintptr(lparam))
}
var hwnd uintptr
cb := syscall.NewCallback(func(h uintptr, prm uintptr) uintptr {
var itr_pid uint32
itr_pid = 0x0001
user32.NewProc("GetWindowThreadProcessId").Call(uintptr(h), uintptr(unsafe.Pointer(&itr_pid)))
if int(itr_pid) == Pid {
hwnd = h
//return hwnd
//user32.NewProc("PostMessageW").Call(h, 0x0100, uintptr(key), 0)
return 0 // stop enumeration (commented to make sure all windows created by our process get's the message)
}
return 1 // continue enumeration
})
EnumWindows(cb, 0)
if hwnd == 0 {
return 0, fmt.Errorf("No window with pid %d found", Pid)
}
return hwnd, nil
}