Friday, August 7, 2015

notepad++ - How can I create an .ahk (or similar) hotkey to perform program-specific actions?


I'm an AHK user with no real computer programming background or education (I suppose Excel would be the closest thing I have to such knowledge/experience, excluding day-1 hello, world exposure here and there, or cmd/ VB6 waaay back in the day). For lots of my day-to-day tasks and workflows, I've adopted the use of AHK, but the manner I'm utilizing the scripts have always been input-literal; in other words, predominantly just emulated keystroke inputs that produce specific, superficial key input sequences.


In a sense, this works out in that I can utilize AHK with little to no learning curve -- among other such conveniences -- but there are obviously cons that come hand in hand with the pros. As such, I've become curious lately as to whether AHK is capable of directly interfacing and invoking actions specific to programs?


Conceptual Example
Let's take Notepad++, for example (we'll pretend it doesn't have any native functionality to achieve this, for the example's sake). I want to setup a hotkey to Copy, Cut and Paste Binary Content. How -- if at all possible -- should I approach creating the script?


Conjectural Concept
As part of my cursory information gathering, I did try running psr.exe to see if I might be able to capture any useful information. Unfortunately, I'm not knowledgeable enough to make any use of the results, but I was thinking there might be some method similar to capturing what's happening on the backend in the same way that one might use the keyboard hook to possibly capture non-standard key inputs. I've hosted the resultant data here, in case that can be utilized.


EDIT: To clarify any confusion, I am not referring to the conditional specificity in regards to the triggering conditions for a script (e.g., #winactive). It's a bit difficult to describe any further than I already have without causing more confusion and causing this to get too convoluted I think, but if I have to give an analogous example, then what I want to achieve can be loosely compared to executing a program with specific arguments example.exe -function -parameter as opposed to automating the process of running example.exe followed by pre-determined keystrokes to navigate to said example function Alt + F, F, P through the UI.


EDIT #2: Alright, apparently I'm still not properly conveying the meaning of my question. I'll make one more attempt before I give up on this.


Sample Objective:



  • Create hotkey that invokes this function:


Sample Command



  • The way I would currently do it:

    • Assign hotkey which triggers a send input sequence Alt + E, P, P, C, Enter


  • The way I want to do it:

    • Assign hotkey which directly calls on the Copy Binary Content function.


  • Challenges: identifying which AHK function achieves this (e.g., DllCall?), and enumerating the function's correct and available identifier/arguments

  • Using PSR.exe logs the following actions:



...Step 1: User left click on "Edit (menu item)" in "*ne" Program:
NOTEPAD++.EXE UI Elements: Edit, Application, *new 1 - Notepad++
[Administrator], Notepad++


Step 2: User left click on "Copy Binary Content (menu item)" Program:
NOTEPAD++.EXE UI Elements: Copy Binary Content, Paste Special, #32768,
*new 1 - Notepad++ [Administrator], Notepad++...



Notice the "#32768"! Is there a way to directly call on that function?


Answer



I understand the question as outlined and it makes a lot of sense as I have tried (and succeeded) at doing this to various degrees with different programs.


There are a few methods of doing what you're after, listed in increasing order of complexity below (in my opinion)...


WinMenuSelectItem


For starters, the less-than-ideal approach is with WinMenuSelectItem for programs that have standard Windows menus (vs. the ribbon for example).


This method can avoid having to send all the keystrokes just to trigger an existing menu option. Getting these WinMenuSelectItem commands to work is sometimes tricky however, and can be not-so-straightforward to debug if it's not working right (turns into trial and error). Sometimes I have just given up altogether trying to get this work and gone back to using keystrokes.


Once a given function is working with this method though, the window doesn't necessarily have to be active in order to execute it, which is nice.


PostMessage/SendMessage


The second method for standard Windows programs is using PostMessage or SendMessage. Using a windows inspector (Spy++? There are other popular ones also but I don't remember the name right off. Maybe one of the Sysinternals tools?), you can log these messages and see what the menu function triggers when you do it manually, and then send that message. You would basically log all the windows messages and then filter on just that window to see what gets sent, then try to replicate it in code.


This is probably a bad example, but a random code snippet utilizing SendMessage:


SendMessage, % TCM_SETCURFOCUS:=0x1330,1 ,          , SysTabControl321, % helpWinTitle
SendMessage, % WM_SETTEXT:=0x0C , , &HelpItem, Edit1, % helpWinTitle ; Edit1 = Search Tab search
SendMessage, % WM_KEYDOWN:=0x100 ,13, , Edit1, % helpWinTitle

COM Objects


For Microsoft Office type programs, the best way to get 'behind the scenes' is to connect via COM Objects, which then exposes essentially all of the object models that are already available in VBA. This is fantastic for doing whatever you need to in Word/Excel/etc. since you can just look up VBA code for it and then implement an equivalent in AutoHotkey just to get a particular task done. Another advantage is that it does not require macro privileges to be enabled in order to connect to the program and execute something, it [Word/Excel/etc.] just has to be running.


Accessibility


Last but not least, Accessibility can be utilized to find and execute functions that aren't in a standard menu but exist within the GUI layout of a program or toolbar. This is usually much more advanced and tedious but can find things "behind the scenes" that you might not be able to execute otherwise without just using keystrokes/mouse clicks.


Typically you need to use an Accessibility tree viewer to go digging into a particular GUI setup to find what you want to execute, and then pass a tree reference to the code that will go call that function, "press" or "click" the button, etc. This is most helpful in cases where the standard windows controls aren't used and you just get a NETUIHWND1 reference when mousing over a control while running Window Spy. Accessibility allows you to actually drill down into the construction of that NETUIHWND1 in order to find and/or execute something within it (text, buttons, etc.)


Summary


Can it be done? Yes. Obviously there's a lot of programming involved with some of these options, but these are the topics I would recommend starting with if you're going to go searching the AutoHotkey help files and forums.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...