2 clipboards ahk script - clipboard

I'm trying to have 2 clipboards (or more), with an ahk script.
Desired behaviour is working with the standard ^v plus !v so it will be 2 clipboards. ^v being the usual one, !v will be the previous content that ^v had.
If I copy 'text1' on clipboard, I will have this as ^v. If I copy 'text2' I will have 'text2' on clipboard with ^v, plus the old 'text1' available with !v, and so on.
This is so far:
lastclip = %clipboard%
!v::
global lastclip
sendclip(lastclip)
return
ClipWaitChange()
ClipWaitChange()
{
While changed=0 {
global lastclip
lastclip = %clipboard%
Sleep 10
}
OnClipboardChange:
changed = 1
return
}
But it returns a blank clipboard or maybe ^v stops working.
Any hints how to do that?
sendclip is just a custom func to send the clipboard contents by keyboard
I tried put lastclip = %clipboard% inside onclipboardchange but it copies the current changed clipboard, so has to be done before that.

I assume your question is of an academic nature. If not, I recommend one of the many Clipboard Managers already out there.
Here's a solution with comments:
lastClip := ""
bufferedClip := Clipboard
OnClipboardChange("clipChangeHandler")
; Note that the ALT key can change focus, better use WIN+V
#v::
; Since we temporarily switch Clipboard's contents,
; we want to ignore the event it will fire
OnClipboardChange("clipChangeHandler", 0)
; I recommend pasting rather than sending
tmpClip := Clipboard
Clipboard := lastClip
Send, ^v
Clipboard := tmpClip
tmpClip := ""
OnClipboardChange("clipChangeHandler")
return
clipChangeHandler(evtInfo) {
global lastClip, bufferedClip
; Check if Clipboard contains actual text
if(evtInfo = 1) {
lastClip := bufferedClip
bufferedClip := Clipboard
}
}
See also OnClipboardChange in AHK docs.
A few remarks:
The event function checks for the event type being (partially) real text, ignoring pure non-text like images and also empty clipboards
clipBuffer always stores the current clipboard and lastClip contains the previous clipboard. You need the buffer variable, since the event doesn't offer something like a previous clipboard
ALT + v can be problematic when working with windows that have a classic menu bar. Hitting ALT (even before releasing it) will often switch focus away from the current control.
I recommend pasting rather than sending. E.g. when there's large text in the clipboard with thousands of words (maybe even put there by another program or simply by mistake), sending each character one by one can take a long time or may even come with other side effects. If you want to Send regardless, at least use SendRaw so that certain characters won't be mistreated as control sequences (e.g. sending #e will open Windows Explorer).
Always consider security aspects of your application. If you (our your password safe e.g.) empty your clipboard to delete sensitive data, your script will still keep an (unencrypted) copy of it, for every other process to see.

Related

How to detect focus into Microsoft Outlook Search field with AutoHotKey

Question
How do I program AutoHotKey to detect the Microsoft Outlook Search field at the top of the window, so as to only enable hotkeys when outside of that window? That search field looks like this:
Details
I'm intending to add single-character hotkeys similar to what gmail has: https://support.google.com/mail/answer/6594?hl=en#zippy=%2Cactions , notably the # keybinding for deletion. I'm basing my experimentation with AutoHotKey scripts such as this one:
https://github.com/pimlottc-gov/gmailkeys/blob/master/gmailkeys-2013.ahk#L37
That script limits its hotkeys to the main Outlook window using #IfWinActive:
#IfWinActive, - Outlook ahk_class rctrl_renwnd32, NUIDocumentWindow ;for Outlook 2013, uncomment this line
However, if I do not change the above #IfWinActive statement, and then add the # hotkey via:
+3::Send {Delete} ; Means "#" key: Delete selected message(s)
then when running the script, then clicking in the above Search field, then typing #, then of course it sends the Delete key into that field, instead of just passing the # into the search field.
I've hacked around this by rebinding both Ctrl+e and / (the latter being the Gmail binding for searching/filtering) to a temporary input popup where I type in the search expression, and then let AutoHotKey type it into the field. But this of course is a hack:
; Search for some expression
;
; Hack: We have to popup an input dialog box, prompt for the
; search expression, and then when done, type it into the
; underlying search field. This is needed to avoid having other
; single-key bindings get "eaten" when needing to type into the
; Outlook search field, as as of 2021-05-23 I could not find a way
; to detect that specific input field.
;
^e::
/::
; Save current active (Outlook) window so we can return to after prompting for the search expression:
WinGet, winid ,, A ; <-- need to identify window A = active
; Prompt for the search expression:
InputBox, search_expr, Search Expression, Enter the search expression.
; Return to the Outlook window:
WinActivate ahk_id %winid%
; If the user presses Escape or clicks on the Cancel button, do nothing:
if (!ErrorLevel) {
; but if we are doing the search:
; Get into the search field:
Send ^e
; Select all prior text so we can wipe it out:
Send ^a
; ... by typing in all of the expression:
Send %search_expr%
; then do the search:
Send {Enter}
}
return
No matter where I click around in the main Outlook window, Window Spy (app that comes with AutoHotKey), the class always stays the same.
AutoHotkey version: 1.1.33.08
Note that Shift+3 only happens to produce a # on your keyboard layout. It would be more correct to actually use the # key as the hotkey.
Also, the code you're referencing is very legacy AHK. Quite a few things in there that don't belong to modern AHK.
I'd maybe also recommend just doing this with a context sensitive hotkey.
This way you'll retain the # key's native functionality.
The context sensitive hotkey could be done like this:
SetTitleMatchMode, 2
#If, WinActive("A") == WinExist("- Outlook ahk_exe OUTLOOK.EXE") && !SearchBarFocused()
#::SendInput, {Delete}
#If
SearchBarFocused()
{
ControlGetFocus, ctrl
return InStr("RICHEDIT60W1,RichEdit20WPT1", ctrl)
}
I'm also checking if Outlook is actually the active window first. Might be kind of redundant, but makes it so the remap couldn't be active in some other window that could have a control by that name.
I found the solution after some experimentation (including simplification from per 0x464e's answer), and essentially reversing the logic, somewhat, at https://github.com/pimlottc-gov/gmailkeys/blob/master/gmailkeys-2013.ahk#L76 via this:
; Outlook-specific Hotkeys:
;
; Reference material used in this implementation:
; https://autohotkey.com/board/topic/38389-archiving-email-in-outlook-with-a-single-keystroke/
;
; As best I can tell, the window text 'NUIDocumentWindow' is not present
; on any other items except the main window. Also, I look for the phrase
; ' - Outlook' in the title, which will not appear in the title (unless
; a user types this string into the subject of a message or task).
#IfWinActive - Outlook ahk_class rctrl_renwnd32, NUIDocumentWindow
#::
if (SentNormalKeyInOutlookEditControl("#"))
{
return
}
Send {Delete} ; Delete selected message(s)
return
#IfWinActive
SentNormalKeyInOutlookEditControl(normal_key)
{
; Find out which control in Outlook has focus
ControlGetFocus, currentCtrl
; ; set list of controls that should respond to specialKey. Controls are the list of emails and the main (and minor) controls of the reading pane, including controls when viewing certain attachments.
; ; The control 'RichEdit20WPT1' (email subject line) is used extensively for inline editing. Thus it had to be included in bad_ctrl_list.
; ctrlList = Acrobat Preview Window1,AfxWndW5,AfxWndW6,EXCEL71,MsoCommandBar1,OlkPicturePreviewer1,paneClassDC1, RichEdit20WPT2,RichEdit20WPT4,RichEdit20WPT5,RICHEDIT50W1,SUPERGRID1,_WwG1
bad_ctrl_list = RICHEDIT60W1,RichEdit20WPT1
; RICHEDIT60W1 is the search field at the top of the window
if currentCtrl in %bad_ctrl_list%
{
; MsgBox, BAD Control with focus = %currentCtrl% normal_key = %normal_key%
Send %normal_key%
return 1
}
return 0
}
Edit 2021-05-25 06:58:23: Replace legacy "+3" with "#" per 0x464e's answer.
Edit 2021-05-25 08:20:09: Prevent " - Message" windows from receiving the hotkeys (separate message windows, not main window)

Activate hotstring when text is pasted from clipboard

I have an Autohotkey Hotstring which displays a notification any time a job code is typed with capital letters.
:*B0C:ASSOC::
:*B0C:COORD::
:*B0C:PRACPHYS::
MsgBox Reminder - Set indirect pay to 100
return
While this works fine when manually typing out a job code, I also want these notifications to display when a job code is copy-pasted from the clipboard.
; non-functional pseudo-code
^v:: ; paste
if (pasted text == ASSOC or COORD or PRACPHYS)
MsgBox Reminder - Set indirect pay to 100
return
How can I make my script run whenever a matching string is pasted from the clipboard?
This checks the contents of the clipboard when pasting without interfering with the paste operation
~^v::
if ( clipboard == "ASSOC" || clipboard == "COORD" || clipboard == "PRACPHYS" )
MsgBox Reminder - Set indirect pay to 100
return
Notes
~ key's native function will not be blocked
clipboard contents of the clipboard in text-only format
== case sensitive string comparison
Ref
Autohotkey documentation for Hotkeys

Replace any keyboard character(s) with keyboard shortcut or different keystroke

For a project using a barcode scanner I need to know if it is possible to replace a special character like
!
"
ยง
$
%
=
with different keyboard strokes like
arrow down or arrow up or even shortcuts like
ctrl+a or ctrl+v?
Would be also possible if a specific series of characters resulted in a keystroke/keyboardshortcut,
for instance this text InsertArrowLeftHere would result in this keypress arrow left
Is there any way to make something like this work?
A bar-code scanner (unless is used with special hardware in-between) just reads the data, and sends keystrokes to the computer as keyboard interrupts. How the bar-code "string" is interpreted depends on software that, at that moment, has the focus. If you open a Notepad and read something with the barcode scanner, the number will be printed in notepad. In many cases no software comes with the scanner because there is no need for that.
But your software (the program that receives the data from the scanner) can catch anything typed in the textbox (or other control that has the focus, for example the whole form can catch the keystrokes). Maybe you can also identify where the keystrokes come from, (means: from which keyboard-input device: keyboard1, keyboard2, barcodescanner etc.) and act accordingly (if from keyboard1 or keyboard2 do nothing, if from barcodescanner then do this).

Need a "one-click" webdev hotkey workflow solution

Question for all you webdev guys/gals who have found a minimal-hassle development environment.
OS: Win7
Editor: JEdit
Task: Previewing work in a web browser
I would like to program a single hotkey to pack the following series of hotkeys into one. I use this sequence many times a day to preview my work in a browser.
The key commands are:
(from JEdit) ctrl + e ctrl + s [save all files]
(win) alt + tab [switch me over to browser]
(browser) ctrl + r [reload page]
I have not used Dreamweaver or flash in years but I remember punching f12 or ctrl + enter and having a browser pull up previewing the current work file. I am looking for a similar workflow but I cannot simply link to the saved file on disk. I need to look at the file through a local webserver. Typically I just have the browser open to the page I need and refresh it when I need to preview what I have done.
Another issue is the alt+tab step is not explicit enough. Often times the browser is not correctly sequenced in the open apps list to get to it without multiple tabs.
Thanks for any suggestions, workflow tips, etc.
Use this answer to create a command line method of refreshing a webpage ( it will work for any browser).
Next, create a baseline macro in JEdit for activating that script that you created:
In JEdit, you can record macros with Macros->Record Macro.
Do ctrl + e + s
Stop recording the macro with Macros->Stop Recording.
Open the JEdit browser tab with the newly created macro buffer that is now open in JEdit and add a system call at the end of it to run your visual basic script for refreshing the browser tab:
Runtime.getRuntime().exec("c:/PATH/TO/VB_SCRIPT AND ARGS IF YOU NEED THEM");
Save the macro.
Create a JEdit keyboard shortcut with utilities->global options, select "Shortcuts" then search for you macro and create a new keyboard binding.
Note that the Java beanshell exec command is non-blocking, so if you want to do anything else after executing the command, you may have to insert a sleep like:
Thread.currentThread().sleep(2000);
Just Press Alt + F5 and get it done!
To accomplish that, install AutoHotKey and run the script below (copy in a text file and change extension to .ahk). There is a portable version here. It was tested with AutoHotKey version is 1.0.48.05
This solution is pretty flexible since you can change Keys, Editors, Browsers and everything else. It works with Firefox and IE but you can easily customize.
The varTextEditor and varBrowsers where discovered using "WindowSpy" utility that comes bundled into AutoHotKey.
;###############################################################################
; Save all unsaved documents, refresh all opened browsers and return to text editor
;###############################################################################
!F5::
;Configuration vars. Edit here the settings of this script
; jEdit Eclipse
varTextEditor = SunAwtFrame,SWT_Window0
;varBrowsers = MozillaUIWindowClass,MozillaWindowClass,Chrome_WidgetWin_0,IEFrame,OpWindow,{1C03B488-D53B-4a81-97F8-754559640193}
; Firefox3 Firefox4 Chrome IEca Opera Safari
varBrowsers = MozillaWindowClass,IEFrame
;End of configuration vars.
WinGetClass, thisWindowClass, A ;Get the active window class
if (InStr(varTextEditor, thisWindowClass, true, 1) > 0) { ;true = case sensitive
varTextEditorClass = ahk_class %thisWindowClass%
if (thisWindowClass = "SunAwtFrame") {
OutputDebug, ...Saving everything
; SetKeyDelay, 100, 100, Play
Send ^+s ;Ctrl + Shift + S = Save all
} else if (thisWindowClass = "SWT_Window0") {
SendPlay ^s ;Ctrl + S = Save
}
Sleep, 500 ;Give some time to the data be recorded on hard disk
} else {
MsgBox, 0, Ops!, You must be in on these text editors: (%varTextEditor%) to get this script running, 5
return
}
;Refresh all opened (and maximized) browsers
Loop, parse, varBrowsers, `,
{
varClasseBrowser = ahk_class %A_LoopField%
if WinExist(varClasseBrowser) {
WinGet, winState, MinMax, %varClasseBrowser% ;get window state. -1 = minimized
if (winState != -1) {
WinActivate, %varClasseBrowser%
OutputDebug, ...Refresh browser %A_LoopField%
Send, {F5}
}
}
}
;Return to text editor
WinActivate, %varTextEditorClass%
return

How to hijack the Caps Lock key for Cut, Copy, Paste keyboard operations

Here is what I am trying to accomplish:
To Copy, press and release Caps Lock ONCE
To Paste, press and release Caps Lock TWICE, quickly
To Cut, press Ctrl+Caps Lock
The reason I want to do this is often times i find my self looking down to press the correct X/C/V key, since they're all next to each other (atleast on a QWERTY keyboard).
How can I do this on a standard keyboard (using Windows), so that it applies to the entire system and is transparent to all applications, including to Windows Explorer? If not possible with a standard keyboard, can any of the "programmable numeric keypads" do this you think?
In the above, by "transparent" I mean "the application should never know that this keystroke was translated. It only gets the regular Ctrl+X/C/V code, so it behaves without any problems".
Ps. Not sure of all the tags that are appropriate for this question, so feel free to add more tags.
SOLVED. UPDATE:
Thank you to #Jonno_FTW for introducing me to AutoHotKey.
I managed all three requirements by adding the following AHK script in the default AutoHotKey.ahk file in My Documents folder:
Ctrl & CapsLock::
Send ^x
Return
CapsLock::
If (A_PriorHotKey = A_ThisHotKey and A_TimeSincePriorHotkey < 1000)
Send ^v
Else
Send ^c
Return
That was easy!
NOT COMPLETELY SOLVED. UPDATE:
The above works in Notepad, but NOT in Explorer (copying files for example) or MS Office (even text copying does not work). So, I need to dig around a bit more into AutoHotKey or other solutions. Will post a solution here when I find one.
In the meantime, if someone can make AutoHotKey work for everything I need, please reply!
ALL SOLVED. UPDATE:
All I had to do was to change the capital "C"/X/Z to lowercase "c"/x/z. So Send ^C became Send ^c. It now works in ALL programs inlcuding Windows Explorer! Fixed code above to reflect this change.
I believe the program you are looking for is AutoHotkey.
You need a Global Keyboard Hook.
Very nice! Been looking for something like this for a while.
My script is slightly different, making use of shift or control combinations for cut/copy, then CapsLock on its own is always paste.
Ctrl & CapsLock::
Send ^x
Return
Shift & CapsLock::
Send ^c
Return
CapsLock::
Send ^v
Return
If you wanted to retain the option of retaining the Caps Lock function, I presume you could always remap e.g. Alt-CapsLock for this. I couldn't get it to toggle correctly when I tried it though.

Resources