Modify the specified program and hotkey:
Code: Select all
program := "D:\Tools\BandiView\BandiView.exe" ; Specify the path of the program to run
myHotkey := "space" ; Specify the toggle hotkey as SpaceCode: Select all
;============================
;Function : Link XY (track selection) to run the specified program to open the current item (toggle with Space key)
;Created : 2024-05-28
;Version : v1.6 (2026-01-15 Ken)
;============================
#Requires AutoHotkey v2
#SingleInstance Force
Persistent
program := "D:\Tools\BandiView\BandiView.exe" ; Specify the path of the program to run
myHotkey := "space" ; Specify the toggle hotkey as Space
;myHotkey := "f11"
if !fileExist(program) {
trayTip("Please modify the program path in the script!`n" program, "Program does not exist")
exitApp
}
splitPath program, &programName
HotIfWinActive('ahk_class ThunderRT6FormDC')
Hotkey myHotkey, ViewerOpen
HotIfWinActive("ahk_exe " programName)
Hotkey myHotkey, ViewerClose
; Receive the message returned by XYplorer
OnMessage(0x4a, Receive_WM_COPYDATA)
dataReceived := "", pictureBox := "", xyWin := ""
ViewerOpen(*)
{
isPictureBox
if (winExist("ahk_exe " programName) && pictureBox)
winClose("ahk_exe " programName)
else if pictureBox {
LinkProgram
} else send "{" . myHotkey . "}"
}
ViewerClose(*)
{
if winActive("ahk_exe " programName)
winClose("ahk_exe " programName)
}
ViewerActivate()
{
if winExist("ahk_exe " programName)
winActivate("ahk_exe " programName)
}
#HotIf winActive(xyWin) && winExist("ahk_exe " programName) ; When the XY window is active and the specified program window exists, track selection on the following key presses
up::LinkProgram
down::LinkProgram
left::LinkProgram
right::LinkProgram
~LButton::isPictureBox(), LinkProgram() ; Do not alter left mouse button behavior
home::LinkProgram
end::LinkProgram
#HotIf
#HotIf winExist(xyWin) && winActive("ahk_exe " programName) ; When the specified program window is active and the XY window exists, track selection on the following key presses
up::LinkProgram
down::LinkProgram
left::LinkProgram
right::LinkProgram
~LButton::isPictureBox(), LinkProgram() ; Do not alter left mouse button behavior
home::LinkProgram
end::LinkProgram
#HotIf winExist(xyWin) && winExist("ahk_exe " programName) ; When both the specified program window and the XY window exist, track selection on the following key presses
~LButton::isPictureBox(), LinkProgram() ; Do not alter left mouse button behavior
#HotIf
LinkProgram(*) {
static lastItem := ""
try {
; Send the current key to XY
if !(A_ThisHotkey = myHotkey && myHotkey != "space") {
CreateHoleToWindow(xyWin) ; create hole
SendMessage(WM_ACTIVATE := 0x0006 , 1, xyWin,, xyWin)
if !(A_ThisHotkey = myHotkey && myHotkey != "space")
ControlSend('{' A_ThisHotkey '}', pictureBox, xyWin) ; In details mode no control is required, but in thumbnail mode it is required; unify by always specifying
CreateHoleToWindow() ; remove hole
}
}
sleep 1
if item := XY_Get() {
if !(item = lastItem && winExist("ahk_exe " programName))
try {
run '"' program '" "' item '"'
lastItem := item
setTimer(ViewerActivate.bind(), -1000)
} catch
trayTip("Please modify the program path in the script!`n" program, "Program does not exist")
}
}
isPictureBox() {
pictureBox := ""
if A_ThisHotkey = "~LButton" {
mouseGetPos ,, &win, &ctrl, 2
if winGetClass(win) != "ThunderRT6FormDC"
return
focusedCtrl := ctrl
xyWin := win
} else {
xyWin := winActive('ahk_class ThunderRT6FormDC')
focusedCtrl := ControlGetFocus(xyWin)
}
try pictureBox := RegExMatch(ControlGetClassNN(focusedCtrl, xyWin), "^ThunderRT6PictureBoxDC\d+$") ? focusedCtrl : ""
global pictureBox, xyWin
}
XY_Get()
{
xyQueryScript := '::$return = <curitem>`; copydata ' A_ScriptHwnd ', "$return", 2`;'
if xyHwnd := GetXYHWND()
Send_WM_COPYDATA(xyHwnd, xyQueryScript)
else return
global dataReceived
XYdataReceived := dataReceived
dataReceived := ""
return XYdataReceived
}
GetXYHWND() {
static xyClass := 'ahk_class ThunderRT6FormDC'
if WinExist(xyClass) {
for xyid in WinGetList(xyClass) {
focusedCtrl := ""
try focusedCtrl := ControlGetClassNN(ControlGetFocus(xyid))
if (WinGetControls(xyid).length > 10 && focusedCtrl != "ThunderRT6PictureBoxDC3" && RegExMatch(focusedCtrl, "^ThunderRT6PictureBoxDC\d+$"))
return xyid
}
}
}
Send_WM_COPYDATA(xyHwnd, message) {
size := StrLen(message) * 2 ; UTF-16 byte size
COPYDATA := Buffer(A_PtrSize * 3) ; Allocate COPYDATASTRUCT
NumPut("Ptr", 4194305, COPYDATA, 0) ; dwData: application-defined identifier
NumPut("UInt", size, COPYDATA, A_PtrSize) ; cbData: data size in bytes
NumPut("Ptr", StrPtr(message), COPYDATA, A_PtrSize * 2) ; lpData: pointer to UTF-16 string
return DllCall("User32.dll\SendMessageTimeout", "Ptr", xyHwnd, "UInt", 74, "Ptr", 0, "Ptr", COPYDATA, "UInt", 2, "UInt", TimeOut:=5000, "PtrP", Result:=0, "Ptr")
}
Receive_WM_COPYDATA(wParam, lParam, *) {
global dataReceived := StrGet(
NumGet(lParam + 2 * A_PtrSize, 'Ptr'), ; COPYDATASTRUCT.lpData, ptr to a str presumably
NumGet(lParam + A_PtrSize, 'UInt') / 2 ; COPYDATASTRUCT.cbData, count bytes of lpData, /2 to get count chars in unicode str
)
return true
}
; https://www.autohotkey.com/boards/viewtopic.php?p=576829#p576829
CreateHoleToWindow(WinTitle := "") {
static holed := []
if !WinTitle && holed.Length {
for hWnd in holed
WinSetRegion(, hWnd)
holed := []
return
}
if IsWindowPartiallyVisible(WinTitle)
return
local hWnd := IsInteger(WinTitle) ? WinTitle : WinExist(WinTitle)
WinGetPos(&X, &Y, &W, &H, hWnd), mX := X + W//2, mY := Y + H//2
while (thWnd := WindowFromPoint(mX, mY)) != hWnd {
WinGetPos(&tX, &tY, &tW, &tH, thWnd)
rX := mX - tX, rY := mY - tY
WinSetRegion("0-0 0-" tH " " tW "-" tH " " tW "-0 0-0 " rX "-" rY " " rX "-" (rY+1) " " (rX+1) "-" (rY+1) " " (rX+1) "-" rY " " rX "-" rY, thWnd)
holed.Push(thWnd)
}
}
IsWindowPartiallyVisible(WinTitle:="") {
local hWnd := IsInteger(WinTitle) ? WinTitle : WinExist(WinTitle)
WinGetPos(&X, &Y, &W, &H, hWnd)
return (hWnd == WindowFromPoint(X, Y)) || (hwnd == WindowFromPoint(X, Y+H-1)) || (hwnd == WindowFromPoint(X+W-1, Y)) || (hwnd == WindowFromPoint(X+W-1, Y+H-1))
}
WindowFromPoint(X, Y?) { ; by SKAN and Linear Spoon
return DllCall("GetAncestor", "Ptr", DllCall("user32.dll\WindowFromPoint", "Int64", IsSet(Y) ? (Y << 32 | (X & 0xFFFFFFFF)) : X), "UInt", 2, "Ptr")
}
XYplorer Beta Club