Page 1 of 3

XYplorer Messenger (using AHK language)

Posted: 10 Feb 2013 06:52
by binocular222

Change log:
Version 1.0 dated: 10-Feb-2013 Add ability to send message to XYplorer
Version 2.0 dated: 24-Apr-2013 Add ability to receive message from XYplorer (require XYplorer
12.30.0103)
Version 2.1 dated: 2-Jun-2014 Global Datareceived allow AHK to do more things with the message received from XYplorer

-------------------------
[Part 1: Send message to XYplorer]
If you need to control XYplorer from 3rd party software, Macro made one using AutoIT here: http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=9216.
However, I would publish another one using Autohotkey because I'm experienced with this language and can customize/fix bug thouroughly. My code does these things:
+ Send message to XYplorer (such as ::load script.xys)
+ If XYplorer is not running, then run XYplorer, wait for the program to start then send the message
Here is the code:

Code: Select all

#notrayicon
MessagetoXYplorer = %1%

SetTitleMatchMode, 2
Ifwinexist XYplorer ahk_class ThunderRT6FormDC
FunctionMessagetoXYplorer(MessagetoXYplorer)
Else
{
Run E:\7Utilities\XYplorer\XYplorer.exe
winwait, XYplorer ahk_class ThunderRT6FormDC
FunctionMessagetoXYplorer(MessagetoXYplorer)
return
}

FunctionMessagetoXYplorer(MessagetoXYplorer)          ;Send message to XYplorer
{
SetTitleMatchMode, 2
HWND := WinExist("XYplorer ahk_class ThunderRT6FormDC")
Size := StrLen(MessagetoXYplorer)
  If !(A_IsUnicode)
  {
  VarSetCapacity(Data, Size * 2, 0)
  StrPut(MessagetoXYplorer, &Data, Size, "UTF-16")
  }
  Else
  Data := MessagetoXYplorer

VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
NumPut(4194305, COPYDATA, 0, "Ptr")
NumPut(Size * 2, COPYDATA, A_PtrSize, "UInt")
NumPut(&Data, COPYDATA, A_PtrSize * 2, "Ptr")
SendMessage, 0x4a, 0, &COPYDATA, , ahk_id %HWND%
}
How to use:
- Scenario A: You need to pass command-line parameter to XYplorer
+ Modify Run E:\7Utilities\XYplorer\XYplorer.exe
+ Save as .ahk file
+ Compile to exe using attached AHK complier
+ Create a shortcut pointing to the newly created exe with a parameter, which should look like this:

Code: Select all

"C:\path\xyplorer_messenger.exe" ::msg Hello
+ Using this method, you can have multiple shortcuts poiting to 1 exe, each shortcut contain 1 command to pass to XYplorer
- Scenario B: The complied exe carries the command itself
+ Modify the second-line-code above to MessagetoXYplorer := "::msg Hello"
+ Save as .ahk file
+ Complied using attached AHK complier
- Scenario C: You need to keep this tiny code running in the background and send message every 0.5 second
+ Save the following code as .ahk file:

Code: Select all

#notrayicon
#Persistent
Settimer, RenameXYplorer, 500
return
RenameXYplorer:
SetTitleMatchMode, 2
Ifwinactive XYplorer ahk_class ThunderRT6FormDC
{
MessagetoXYplorer := "::msg Hello"
HWND := WinExist("XYplorer ahk_class ThunderRT6FormDC")
Size := StrLen(MessagetoXYplorer)
If !(A_IsUnicode)
  {
  VarSetCapacity(Data, Size * 2, 0)
  StrPut(MessagetoXYplorer, &Data, Size, "UTF-16")
  }
  Else
  Data := MessagetoXYplorer

VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
NumPut(4194305, COPYDATA, 0, "Ptr")
NumPut(Size * 2, COPYDATA, A_PtrSize, "UInt")
NumPut(&Data, COPYDATA, A_PtrSize * 2, "Ptr")
SendMessage, 0x4a, 0, &COPYDATA, , ahk_id %HWND%
}
+ Modify MessagetoXYplorer := "::load Rename2"
+ Modify Settimer, RenameXYplorer, 500
+ Complie to exe using attached AHK complier

-------------------------
[Part 2: Receive message from XYplorer]
To receive message from XYplorer (i.e: retrieve full path of <curiem>):

Code: Select all

#notrayicon

SenderHWND := A_ScriptHwnd + 0  ;Return this script's hidden hwdn id.  +0 to convert from Hex to Dec
MessagetoXYplorer := "::CopyData " SenderHWND ", ""<curitem>"", 2"    ;resolved to sth like this:   ::CopyData 7409230, "<curitem>",2

Global Datareceived
OnMessage(0x4a, "Function_Receive_WM_COPYDATA")  ; 0x4a is WM_COPYDATA. This onhold and wait for the WM_Copydata from XYplorer then execute Function_Receive_WM_COPYDATA(wParam, lParam) below
FunctionMessagetoXYplorer(MessagetoXYplorer)
msgbox %Datareceived%

FunctionMessagetoXYplorer(MessagetoXYplorer)          ;Send message to XYplorer
{
	SetTitleMatchMode, 2
	HWND := WinExist("XYplorer ahk_class ThunderRT6FormDC")
	Size := StrLen(MessagetoXYplorer)
		If !(A_IsUnicode)
		{
			VarSetCapacity(Data, Size * 2, 0)
			StrPut(MessagetoXYplorer, &Data, Size, "UTF-16")
		}
		Else
			Data := MessagetoXYplorer

	VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
	NumPut(4194305, COPYDATA, 0, "Ptr")
	NumPut(Size * 2, COPYDATA, A_PtrSize, "UInt")
	NumPut(&Data, COPYDATA, A_PtrSize * 2, "Ptr")
	SendMessage, 0x4a, 0, &COPYDATA, , ahk_id %HWND%
}

Function_Receive_WM_COPYDATA(wParam, lParam)
{
	StringAddress := NumGet(lParam + 2*A_PtrSize) ;lParam+8 is the address of CopyDataStruct's lpData member.
	CopyOfData := StrGet(StringAddress)    ;May also specify CP0 (default) or UTF-8 or UTF-16:   StrGet(StringAddress, NumGet(lParam+A_PtrSize), "UTF-16")
	cbData := NumGet(lParam+A_PtrSize)/2  ;cbData/2 = String length
	StringLeft, Datareceived, CopyOfData, cbData
}
For more info on how to retrieve message from XYplorer, visit here: http://www.xyplorer.com/xyfc/viewtopic. ... 550#p84864

Re: XYplorer Messenger (using AHK language)

Posted: 10 Feb 2013 14:57
by klownboy
Hey Binocular222,
I mentioned previously about the hour glass raising it's ugly head whether I used your "XYplorer_messenger.ahk" or the "D:\Tools\XYplorer\XYplorer.exe /script=script name.xys /flg=2" method to run a Windows shortcut. I tweaked the ahk code a bit, essentially just to ensure XYplorer is "active" and not just "exists" and that has eliminated the hour glass completely, at least for my situation or scripts that I'm calling.

Code: Select all

;#notrayicon
MessagetoXYplorer = %1%

SetTitleMatchMode, 2

If ( HWND := WinExist("ahk_class ThunderRT6FormDC") )
  {
    IfWinActive, ahk_id %HWND%
    {
    TrayTip, , XYplorer (HWND %HWND%) is already active,1
    SendFunction(MessagetoXYplorer)
    }
    else
    {
    WinActivate, ahk_id %HWND%
    TrayTip, , Activating XYplorer (HWND %HWND%),1
    SendFunction(MessagetoXYplorer)
    }
  return
 }
 else
  {
  Run, D:\Tools\XYplorer\XYplorer.exe
  winwait, XYplorer ahk_class ThunderRT6FormDC
  SendFunction(MessagetoXYplorer)
  return
  }

SendFunction(MessagetoXYplorer)
{
HWND := WinExist("ahk_class ThunderRT6FormDC")
Size := StrLen(MessagetoXYplorer)
If !(A_IsUnicode) {
   VarSetCapacity(Data, Size * 2, 0)
   StrPut(MessagetoXYplorer, &Data, "UTF-16")
} Else {
   Data := MessagetoXYplorer
}
VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
NumPut(4194305, COPYDATA, 0, "Ptr")
NumPut(Size * 2, COPYDATA, A_PtrSize, "UInt")
NumPut(&Data, COPYDATA, A_PtrSize * 2, "Ptr")
Result := DllCall("User32.dll\SendMessageW", "Ptr", HWND, "UInt", 74, "Ptr", 0, "Ptr", &COPYDATA, "Ptr")
}
As you know being an AHK coder, there are many many ways to check if a program exists or is active. I used another method here (though it's not important to the end result). I made a few other tweaks that are also unimportant to the outcome and are really just fluff (i.e., displaying a tray tip which has to have the trayicon enabled to work.
It's quite nice being able to set up a Windows Shortcut on the taskbar which will quickly open XYplorer and display, for example all your thumbnails in the the XY frame with no toolbars menu bar, address bars, etc. I have the shortcut bring up an XY menu with a long list of various photo folders which will display photo thumbs for different places I've visited.
Thanks again to you and Marco,
Ken

Re: XYplorer Messenger (using AHK language)

Posted: 10 Feb 2013 16:04
by binocular222
Hi klownboy,
I hate the hour glass too, therefore, I made a separate code for scenario C.
Hour glass appears due to loading of XYplorer_messenger.exe, it's not related to whether XYplorer window is active or not. Therefore, having XYplorer_messenger.exe constantly running in the background will certainly remove the hour glass.

But it seems you are using scenario A. I've never seen hour glass in this scenario (due to good computer hardware?). Anyway, you made the winactivate correctly. My script intended to let XYplorer do dirty things without activating it!

Re: XYplorer Messenger (using AHK language)

Posted: 10 Feb 2013 16:24
by klownboy
Yes, Binocular I am using scenario A (as an ahk file - not compiled) and since I'm using it in a Windows Shortcut to display menus and large numbers of photo thumbnails in XY, I do want XYplorer active. Maybe I'd gain even more speed if I compiled it since I'm sending a command line paramenter (script) anyway.

By the way, my newest computer that I just finished building last week, screams with a I7-3770K processor.

Thanks again,
Ken

Re: XYplorer Messenger (using AHK language)

Posted: 24 Apr 2013 11:16
by binocular222
Updated the first post.
Version 2 added the ability to receive message from XYplorer.
You will need some AHK scripting ability to do meaningful things with the message received

Re: XYplorer Messenger (using AHK language)

Posted: 24 Apr 2013 15:49
by klownboy
Hi binocular222, Great job! I've been experimenting with your new versions of XYplorer messenger. I haven't used your "receive" function yet, but I will. As before, in your previous versions, you can send an XYplorer script to the uncompiled version of the ahk file simply by having the script name as a quoted paramenter to the XYplorer messenger.ahk (i.e., the "/script=" part of the parameter is not reguired). So for a taskbar shortcut, it would look like this as an example:

Code: Select all

"D:\Tools\AutoHotkey\AHK scripts\XYplorer_messenger.ahk" "D:\Tools\Xyplorer\Scripts\ThumbnailViewer_exec.xys"
I'm not sure why the "/script=" is not required as part of the paramenter sent to XY, but it certainly works without it.
Nice work and thanks again for sharing,
Ken

Re: XYplorer Messenger (using AHK language)

Posted: 24 Apr 2013 16:46
by binocular222
When sending message to XYplorer, all you need to do is
1) Giving some value to the variable MessagetoXYplorer (such as ::msg Hello)
2) Call the function FunctionMessagetoXYplorer(MessagetoXYplorer)

The result is equivalent to pasting ::msg Hello to XYplorer's address bar and press enter. Therefore, you do not need /script=

the flag /script= is only required when you do not use Autohotkey at all, you just run XYplorer with a parameter (you can try windows > Run) such as this:
E:\7Utilities\XYplorer\XYplorer.exe /script=ScriptName.xys

Re: XYplorer Messenger (using AHK language)

Posted: 19 Jul 2013 07:47
by Brendon77
hi klownboy!

Specs are good of your system but you try right click on desktop...small icons.

Re: XYplorer Messenger (using AHK language)

Posted: 29 May 2014 10:20
by nerdweed
MessagetoXYplorer := "::CopyData " SenderHWND ", ""::<curitem>"", 2"
DataReceived := OnMessage(0x4a, "Function_Receive_WM_COPYDATA")

Rather than displaying <curitem> in the Function_Receive_WM_COPYDATA, I want to pass it back to a variable. How can I do that as this currently assigns the value Function_Receive_WM_COPYDATA to DataReceived rather than the value of <curitem>

Re: XYplorer Messenger (using AHK language)

Posted: 02 Jun 2014 05:05
by binocular222
If you want to pass some value to a XYplorer variable, mofidy a tiny bit of the code in my first post:

Code: Select all

#notrayicon
FunctionMessagetoXYplorer("::perm $var = something")

FunctionMessagetoXYplorer(MessagetoXYplorer)          ;Send message to XYplorer
{
SetTitleMatchMode, 2
HWND := WinExist("XYplorer ahk_class ThunderRT6FormDC")
Size := StrLen(MessagetoXYplorer)
  If !(A_IsUnicode)
  {
  VarSetCapacity(Data, Size * 2, 0)
  StrPut(MessagetoXYplorer, &Data, Size, "UTF-16")
  }
  Else
  Data := MessagetoXYplorer

VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
NumPut(4194305, COPYDATA, 0, "Ptr")
NumPut(Size * 2, COPYDATA, A_PtrSize, "UInt")
NumPut(&Data, COPYDATA, A_PtrSize * 2, "Ptr")
SendMessage, 0x4a, 0, &COPYDATA, , ahk_id %HWND%
}

Re: XYplorer Messenger (using AHK language)

Posted: 02 Jun 2014 09:00
by nerdweed
Sorry, if I wasn't very clear. I have managed to pass values to XYplorer.

I am able to send message to XY and assign it to variables in XY. I can even get XY to return the values. However; what I haven't managed to do is assign this value to another variable.

The functions FunctionMessagetoXYplorer and Function_Receive_WM_COPYDATA are working great. I call these functions from other functions passing context sensitive information. However; to make use of the data received by Function_Receive_WM_COPYDATA, I would want to store it in an AHK variable and pass it back to the calling function which knows what needs to be done.

Re: XYplorer Messenger (using AHK language)

Posted: 02 Jun 2014 10:22
by binocular222
I modified the first post. Using 1-line code is enough. Should have think of this solution sooner

Code: Select all

Global Datareceived

Re: XYplorer Messenger (using AHK language)

Posted: 02 Jun 2014 14:43
by nerdweed
Thanks. I will check that later in the evening. I used global but at the wrong place - I used it within the function while assigning value to it which wouldn't work.

Re: XYplorer Messenger (using AHK language)

Posted: 02 Jun 2014 21:03
by nerdweed
Thanks. Works great

Re: XYplorer Messenger (using AHK language)

Posted: 12 Jul 2014 14:48
by nerdweed
I am trying to do the following
With the hotkeys defined as 1-5, I want to rate the current image with appropriate ratings 1-5

I want to use these hotkeys only when Floating\Full Screen Preview is active. What would be the correct way to detect that it is active.