浏览器有没有用后退键关闭新窗口的插件

在浏览网页时,有的链接点开是在本页面打开,而有的链接会新建窗口 。
这就导致我在使用后退快捷键(鼠标侧键、Backspace、Alt+←键)操作时变得很不确定。
因为如果是新建窗口打开页面无法使用后退键关闭,而我不可能时时去关注是不是新窗口。
我希望浏览器有统一的操作逻辑,如果是新窗口打开的页面,也能用后退键直接关闭。
请问各位大佬,有没有类似的插件呢?

用autohotkey可以做到
全部代码见下一楼,主要是通过判断当前网页地址来实现
按下快捷键后,首先发送一个返回指令,如果500ms内,网页地址没有改变,再发送一个关闭当前标签的指令。

关键代码

#IfWinActive , ahk_exe msedge.exe
;这里以edge浏览器为例,修改msedge.exe为你的浏览器exe名即可

$Browser_Back::
;此处以浏览器后退键为例,鼠标侧键可改为xbutton1,退格键Backspace,Alt+←为!left
{
	old_sURL := GetActiveBrowserURL()
	Send,{Browser_Back}
	Sleep,500
;此处为500ms,根据你的忍受范围设置,数字越大误杀网页几率越小
	new_sURL := GetActiveBrowserURL()
	if (old_sURL = new_sURL)
	sendinput,^w
}
Return
1 个赞

全部代码

; AutoHotkey Version: AutoHotkey 1.1
; Language:           English
; Platform:           Win7 SP1 / Win8.1 / Win10
; Author:             Antonio Bueno <user atnbueno of Google's popular e-mail service>
; Short description:  Gets the URL of the current (active) browser tab for most modern browsers
; Last Mod:           2016-05-19

Menu, Tray, Icon, % A_WinDir "\system32\netshell.dll", 86 ; Shows a world icon in the system tray

ModernBrowsers := "ApplicationFrameWindow,Chrome_WidgetWin_0,Chrome_WidgetWin_1,Maxthon3Cls_MainFrm,MozillaWindowClass,Slimjet_WidgetWin_1"
LegacyBrowsers := "IEFrame,OperaWindowClass"


#IfWinActive , ahk_exe msedge.exe

$Browser_Back::
{
	old_sURL := GetActiveBrowserURL()
	Send,{Browser_Back}
	Sleep,500
	new_sURL := GetActiveBrowserURL()
	if (old_sURL = new_sURL)
	sendinput,^w
}
Return

GetActiveBrowserURL() {
	global ModernBrowsers, LegacyBrowsers
	WinGetClass, sClass, A
	If sClass In % ModernBrowsers
		Return GetBrowserURL_ACC(sClass)
	Else If sClass In % LegacyBrowsers
		Return GetBrowserURL_DDE(sClass) ; empty string if DDE not supported (or not a browser)
	Else
		Return ""
}

; "GetBrowserURL_DDE" adapted from DDE code by Sean, (AHK_L version by maraskan_user)
; Found at http://autohotkey.com/board/topic/17633-/?p=434518

GetBrowserURL_DDE(sClass) {
	WinGet, sServer, ProcessName, % "ahk_class " sClass
	StringTrimRight, sServer, sServer, 4
	iCodePage := A_IsUnicode ? 0x04B0 : 0x03EC ; 0x04B0 = CP_WINUNICODE, 0x03EC = CP_WINANSI
	DllCall("DdeInitialize", "UPtrP", idInst, "Uint", 0, "Uint", 0, "Uint", 0)
	hServer := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", sServer, "int", iCodePage)
	hTopic := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "WWW_GetWindowInfo", "int", iCodePage)
	hItem := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "0xFFFFFFFF", "int", iCodePage)
	hConv := DllCall("DdeConnect", "UPtr", idInst, "UPtr", hServer, "UPtr", hTopic, "Uint", 0)
	hData := DllCall("DdeClientTransaction", "Uint", 0, "Uint", 0, "UPtr", hConv, "UPtr", hItem, "UInt", 1, "Uint", 0x20B0, "Uint", 10000, "UPtrP", nResult) ; 0x20B0 = XTYP_REQUEST, 10000 = 10s timeout
	sData := DllCall("DdeAccessData", "Uint", hData, "Uint", 0, "Str")
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hServer)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hTopic)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hItem)
	DllCall("DdeUnaccessData", "UPtr", hData)
	DllCall("DdeFreeDataHandle", "UPtr", hData)
	DllCall("DdeDisconnect", "UPtr", hConv)
	DllCall("DdeUninitialize", "UPtr", idInst)
	csvWindowInfo := StrGet(&sData, "CP0")
	StringSplit, sWindowInfo, csvWindowInfo, `" ;"; comment to avoid a syntax highlighting issue in autohotkey.com/boards
	Return sWindowInfo2
}

GetBrowserURL_ACC(sClass) {
	global nWindow, accAddressBar
	If (nWindow != WinExist("ahk_class " sClass)) ; reuses accAddressBar if it's the same window
	{
		nWindow := WinExist("ahk_class " sClass)
		accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindow))
	}
	Try sURL := accAddressBar.accValue(0)
	If (sURL == "") {
		WinGet, nWindows, List, % "ahk_class " sClass ; In case of a nested browser window as in the old CoolNovo (TO DO: check if still needed)
		If (nWindows > 1) {
			accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindows2))
			Try sURL := accAddressBar.accValue(0)
		}
	}
	If ((sURL != "") and (SubStr(sURL, 1, 4) != "http")) ; Modern browsers omit "http://"
		sURL := "http://" sURL
	If (sURL == "")
		nWindow := -1 ; Don't remember the window if there is no URL
	Return sURL
}

; "GetAddressBar" based in code by uname
; Found at http://autohotkey.com/board/topic/103178-/?p=637687

GetAddressBar(accObj) {
	Try If ((accObj.accRole(0) == 42) and IsURL(accObj.accValue(0)))
		Return accObj
	Try If ((accObj.accRole(0) == 42) and IsURL("http://" accObj.accValue(0))) ; Modern browsers omit "http://"
		Return accObj
	For nChild, accChild in Acc_Children(accObj)
		If IsObject(accAddressBar := GetAddressBar(accChild))
			Return accAddressBar
}

IsURL(sURL) {
	Return RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^:/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
}

; The code below is part of the Acc.ahk Standard Library by Sean (updated by jethrow)
; Found at http://autohotkey.com/board/topic/77303-/?p=491516

Acc_Init()
{
	static h
	If Not h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromWindow(hWnd, idObject = 0)
{
	Acc_Init()
	If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return ComObjEnwrap(9,pacc,1)
}
Acc_Query(Acc) {
	Try Return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Children(Acc) {
	If ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	Else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		If DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			Return Children.MaxIndex()?Children:
		} Else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
}
1 个赞

我觉得换一种思路可能体验比较好:

看看浏览器的返回按钮能不能按,或者js的history.length===1,然后分情况调用真正的返回或者关闭。

不过这个难度可能会高一些。

虽然但是,为啥要用后退键啊,ctrl + w 不是就能关新标签页吗。

另外按住 ctrl 再点链接不是会在新标签页打开链吗。这样不就统一让链接打开到新标签了。

如果是个人习惯用退格当我没说。

可以考虑用锁定标签页的扩展,防止打开新标签页

有此类扩展推荐吗
@heretic43

建议打开新窗口用鼠标中键点击
建议关闭窗口用鼠标手势,设置鼠标手势按住右键+左键关闭窗口

会给你不一样的体验

对的,如果能识别返回按钮应该会是最好的方案

鼠标中键默认就是打开新窗口,但是在后台打开,还需要切换过去。Edge浏览器好像不能改成中键前台打开新窗口。鼠标手势确实好用

那就改用拖拽打开新链接

@LinkLi
是个办法 :+1:
延伸一下,换个思路,有没有始终在当前页面打开链接的插件呢?这样后退键就能始终有效了

国外的网站大部分是当前页打开链接的。
国内好多网站是新建页面打开链接的,这个估计没法解决。
网站开发针对的用户习惯不同

close on back

这是脚本

浏览器扩展有
Always open in current tab

Link in Current Tab
https://chrome.google.com/webstore/detail/link-in-current-tab/cbkcdebbfbegnmbephalggnchfebihbl

我觉得楼主选择的解决方案可能不是最优。

如果想选择在新标签页还是在当前页面打开链接,推荐 target=“_blank”-toggler(这个扩展我用了很多年):
Firefox版: target="_blank"-toggler – Get this Extension for 🦊 Firefox (en-US)
Chromium版: target="_blank"-toggler - Chrome Web Store

点击“后退”以关闭标签并回到上一个激活标签页的扩展:
在Firefox上,Back to Close WE: Back to Close WE – Get this Extension for 🦊 Firefox (en-US)
在Chromium上,Close on Back: Close on Back - Chrome Web Store

我觉得上面这几个扩展可能和楼主的需求更贴切。

你可以考虑用 vimium 扩展,可用 x 键关闭网页,很顺手,用上就离不开了。
这是 Chrome 商店的地址。
类似的有 SurfingKeys
SurfingKeys: 一个更强的 Vimium 类 Chrome 插件