Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Floating clipboard


  • Please log in to reply
No replies to this topic
maxand
  • Members
  • 166 posts
  • Last active: Apr 15 2014 12:58 PM
  • Joined: 03 Apr 2009
(The original post of 2010-05-31 has been completely overhauled with the addition of a fourth button (Copy), so please update your code.)

This is a semitransparent resizable GUI window containing a vertically scrolling Edit control with four buttons underneath. When created, the GUI is positioned centrally on the screen but there are keyboard shortcuts (Ctrl+Shift+L/R/Up/Dn) for pushing it out of the way vertically or horizontally, resulting in 9 locations for it (like the number pad, with 5 at its center).

Additionally there are 3 extra preset sizes to cycle through by pressing Ctrl+Shift+("[" or "]"). The code is commented throughout, enabling beginners to edit sizes and locations to suit.

Opacity is increased/decreased by pressing Ctrl+Shift+Plus/Minus.

The clipboard is not destroyed while the script is running, only hidden. When first created it is hidden and can be displayed/hidden by pressing Ctrl+Shift+Enter. Clicking the Close (X) button or pressing Esc hides the window and does not lose its contents.

When the clipboard window is visible it may be activated or deactivated (in which case the focus is on the window beneath). The clipboard window has been designed to spend most of its time deactivated, enabling the user to maintain focus on the text application underneath and control copying/pasting/clearing of the window solely by the keyboard if he/she wishes, without needing to reach for the mouse, though clicking buttons may be more convenient at other times. There is a hotkey for each button. The order of the hotkeys (Home, PgUp, PgDn, End) parallels the order of buttons on the GUI.

Buttons:

Clear (Ctrl+Shift+Home)- clears contents of the floating clipboard (does not affect Windows clipboard).

Copy (Ctrl+Shift+PgUp) - copies text from the current application to the floating clipboard (does not affect Windows clipboard).

Paste (Ctrl+Shift+PgDn) - clicking in an edit field in another application, then clicking Paste pastes the contents of the Edit control into the other application. (you could change the code here to copy contents into the Windows clipboard ready for pasting, but doing it this way saves you the trouble of pasting.)

Direct (Ctrl+Shift+End) - does the same as Paste but seeks out (activates) a selected application (in this example, Notepad) and pastes into it at its cursor position. Substitute your favorite repository app for Notepad.

After clicking any of the buttons the clipboard is re-displayed deactivated, the focus going to the app underneath to permit editing of the pasted text. Click the clipboard or press Ctrl+Shift +[\] to toggle the focus.

There is no provision to save the contents of the clipboard to a text file, since this is intended to be temporary storage only.

Big thanks to Icarus for his GuiGetPos() function, used here, also to the guys in the #ahk chat room for their invaluable advice.

Enjoy.

; Floating Clipboard
; By Maxand aka Dyslucksia 2010-06-01
;
; Keys: Shift+Ctrl+Enter: Show/Hide clipboard
;       Shift+Ctrl+\: Activate/Deactivate clipboard
;       Shift+Ctrl+[Plus|Minus]: Decrease/Increase transparency
;       Shift+Ctrl+Left|Right|Up|Down: Move clipboard L/R/Up/Dn
;       Shift+Ctrl+[LSqBrkt|RSqBrkt]: Cycle through preset sizes/positions
;       Shift+Ctrl+Home: Button 1 (Clear) clears text in floating clipboard
;       Shift+Ctrl+PgUp: Button 2 (Copy) copies text from application to clipboard
;       Shift+Ctrl+PgDn: Button 3 (Paste) pastes contents to cursor in any application
;       Shift+Ctrl+End:  Button 4 (Direct) pastes contents directly to a selected application*
;              (*which must be loaded, though its window may be hidden)
; Calls GuiGetPos() function

; Initialize variables used here
  GuiID := ""           ;To store ID of this macro's GUI when created
  GuiTrsprncy := "200"  ;(0 = invisible, 255 = opaque)165
  GuiTitle    := "My Clipboard"
    ;Script uses Gui's HWND (in GuiID), not window title, to locate GUI
  GuiVisible  := "0"    ;Is GUI visible?     

  ;X,Y coordinates for fixed positions
  GuiLeftX   := "120"
  GuiRightX  := "800"
  GuiUpperY  := "140"
  GuiLowerY  := "600"

  PresetNum  := "1"  ;Preset location & size
  MaxPresets := "4"  ;Max. no. of presets
    ;This value must match no. of presets, below

  ;Presets
  ;Use Window Spy to help you create more

  ;Preset #1 (default)
  ;When first created, the GUI is positioned centrally and has these x,y,w,h values
  ;x,y are coordinates of top LH corner of GUI's "client window area"; w and h are width & height
  ;Normally x and y would precede w and h, but here x and y are determined by w and h respectively
  GuiW1 := "400"
  GuiH1 := "140"
  GuiX1 := (A_ScreenWidth //2) - (GuiW1 //2)    ;GUI x,y coordinates when created
  GuiY1 := (A_ScreenHeight //2) - (GuiH1 //2)

  ;Preset #2 - "Tiny"
  GuiX2 := "850"
  GuiY2 := "150"
  GuiW2 := "200"
  GuiH2 := "175"

  ;Preset #3 - "Deep"
  GuiX3 := "935"
  GuiY3 := "160"
  GuiW3 := "265"
  GuiH3 := "425"

  ;Preset #4 - "LH Box"
  GuiX4 := "250"
  GuiY4 := "300"
  GuiW4 := "240"
  GuiH4 := "220"

  /*
  This GUI contains 4 buttons in its button bar, from L to R Btn1-Btn4.
  Btns 1 and 4 are near the L and R ends of the button bar, Btns 2 and 3
  between them. Both pairs move with the bar as it stretches, by fixed
  percentages (Btn14CInd, Btn23CInd) of the total GUI width.
  */
  BtnBarHt    := "25" ;Vertical thickness of buttons bar
  EditHeight  := GuiH1 - BtnBarHt
                            ;Height remaining above buttons bar

  Btn14CInd   := "5"    ;Common Indent ("CInd") for buttons 1 & 4
                              ;from L & R GUI borders as % of GUI width 
  Btn23CInd   := "28"    ;Common Indent ("CInd") for buttons 2 & 3
                              ;from L & R GUI borders as % of GUI width 

  Btn1Width   := "50"  ;Button 1 width
  Btn1XPosn   := Round((Btn14CInd/100)*GuiW1) ;x value

  Btn2Width   := "50"  ;Button 2 width
  Btn2XPosn   := Round((Btn23CInd/100)*GuiW1) ;x value

  Btn3Width   := "50"  ;Button 2 width
  Btn3XPosn   := GuiW1 - Btn2XPosn - Btn3Width ;x value

  Btn4Width   := "50"  ;Button 4 width
  Btn4XPosn   := GuiW1 - Btn1XPosn - Btn4Width ;x value

  BtnsYPosn   := "118" ;Top of buttons, down from top of GUI (common y value)
  BtnsYThck   := "20"  ;Vertical thickness (h value) of buttons
  BtnsHtBtm   := GuiH1 - BtnsYPosn 
                                     ;Height of Buttons above GUI *bottom*

  ;Create clipboard GUI, then hide it until displayed by pressing hotkey
  #SingleInstance Force
  CtrlColor := "EEEEEE"   ;light gray
  ;Gui,last (marks most recently added GUI)
  Gui, +AlwaysOnTop +Resize -MaximizeBox +Minsize200x080 +ToolWindow +LabelGui +LastFound
  Gui, Margin, 0, 0
  Gui, Color,,%CtrlColor%  ;The last parameter is ControlColor, i.e., background color for all controls

  ;Set degree of semi-transparency
  ;Comment-out this block if you prefer GUI to be opaque
  Gui, +LastFound  ; Make the GUI window the last found window for use by the line below.
  WinSet, Transparent, %GuiTrsprncy% ;Do not use 'A' (Active) parameter here

  Gui, font, s10, Tahoma  ; Set 10-point Tahoma or edit this to your preferred font 
  Gui, Add, Edit, vMyEdit VScroll w%GuiW1% h%EditHeight%

  Gui, Add, Button, x%Btn1XPosn% y%BtnsYPosn% w%Btn1Width% h%BtnsYThck% Center vBtn1 gClear, Clear
  Gui, Add, Button, x%Btn2XPosn% y%BtnsYPosn% w%Btn2Width% h%BtnsYThck% Center vBtn2 gCopy, Copy
  Gui, Add, Button, x%Btn3XPosn% y%BtnsYPosn% w%Btn3Width% h%BtnsYThck% Center vBtn3 gPaste, Paste
  Gui, Add, Button, x%Btn4XPosn% y%BtnsYPosn% w%Btn4Width% h%BtnsYThck% Center vBtn4 gDirect, Direct

  Gui, Show, x%GuiX1% y%GuiY1% w%GuiW1% h%GuiH1% Hide, %GuiTitle% ;Create and hide, recentered in screen
  GuiID := WinExist() ;Store this GUI's Window ID, even when hidden
Return 

;If GUI moved or resized, adjust Edit control and buttons to match 
GuiSize:
  If A_EventInfo = 1  ; The window has been minimized.  No action needed.
    Return
  ;Otherwise, the window has been resized
  GuiControl, Move, MyEdit, % "w" A_GuiWidth " h" A_GuiHeight - BtnBarHt

  Btn1XPosn := Round((Btn14CInd/100)*A_GuiWidth)
  GuiControl, Move, Btn1, % "x" Btn1XPosn  "y" A_GuiHeight - BtnsHtBtm

  Btn2XPosn := Round((Btn23CInd/100)*A_GuiWidth)
  GuiControl, Move, Btn2, % "x" Btn2XPosn  "y" A_GuiHeight - BtnsHtBtm

  Btn3XPosn := A_GuiWidth - Btn2XPosn - Btn3Width
  GuiControl, Move, Btn3, % "x" Btn3XPosn  "y" A_GuiHeight - BtnsHtBtm

  Btn4XPosn := A_GuiWidth - Btn1XPosn - Btn4Width
  GuiControl, Move, Btn4, % "x" Btn4XPosn  "y" A_GuiHeight - BtnsHtBtm
Return

;Clicking the Close button (X) or pressing Esc only hide this window, which
;continues to exist until script terminates. There is no Cancel button.
GuiClose: 
GuiEscape:
  Gui, Hide
  GuiVisible := "0"  ;reset flag
Return

;End of initialization section

              ;----------------

#IfWinActive ;not window-specific
DetectHiddenWindows, On

;Show/hide Floating Clipboard
;If hidden, this makes clipboard visible but inactive
;If visible, it hides clipboard whether or not active
^+Enter:: ;Ctrl+Shift+Enter
  If GuiVisible
    Gui, Show, Hide
  Else
    Gui, Show, NA
  GuiVisible := !GuiVisible
Return         


;Activate/deactivate Floating Clipboard
;This toggles between the two states when clipboard is visible
^+\::  ;Ctrl+Shift+Backslash
  ;(This key is located just above my Enter key;
  ;if this does not suit you, please choose another key.)
  IfWinActive, ahk_id %GuiID% ;If clipboard is on top
    {
    Gui, Show, Hide
    Gui, Show, NA        ;Make visible but not active
    }
  Else  ;Clipboard window may be visible but is not foremost
    Gui, Show            ;Make visible and active
  GuiVisible := "1"
Return 

              ;----------------

;Make GUI more transparent
^+-:: ;Ctrl+Shift+Minus
  If GuiTrsprncy >= 60 ;must remain visible!
    {
    GuiTrsprncy -= 20
    Gosub, SetTrsprncy
    }
Return 

              ;----------------

;Make GUI more opaque (less transparent)
^++:: ;Ctrl+Shift+Plus
  If GuiTrsprncy <= 235
    {
    GuiTrsprncy += 20
    Gosub, SetTrsprncy
    }
Return 

SetTrsprncy:
  WinSet, Transparent, %GuiTrsprncy%, ahk_id %GuiID%
Return


              ;----------------

;On my notebook keyboard, the Home, PgUp, PgDn and End keys are arranged
;in a vertical line, which corresponds nicely with the arrangement of buttons
;from left to right in the GUI.

;Clear Floating Clipboard
^+Home:: ;Ctrl+Shift+Home
Clear:
  GuiControlGet, MyEdit       ;Get Edit contents into MyEdit
  MyEdit := ""                ;Clear Edit ctrl contents
  GuiControl,, MyEdit, %MyEdit%  ;Update Edit view, now clear
  Gui, Hide       ;Focus should stay on app underneath clipboard, so first
  Gui, Show, NA   ;hide Gui to clear button focus then show but don't activate (NA)
  GuiVisible := "1"
  ;This will cause nothing more than a brief flicker
Return

              ;----------------

;Copy to Floating Clipboard
^+PgUp:: ;Ctrl+Shift+PgUp
Copy:
  GuiControlGet, MyEdit        ;Get Edit contents into MyEdit
  Gui, Hide                      ;Focus will now be on window underneath
  Sleep 300
  SendInput ^c                      ;Copy highlighted text to Windows clipboard
  ClipWait                          ;Wait for Win clipboard to contain data
  Gui, Show, NA                  ;Redisplay floating clipboard but don't activate it
  GuiVisible := "1"
  If (StrLen(MyEdit) = 0)      ;If floating clipboard is empty
    MyEdit .= Clipboard ;Append contents of Win clipboard
  Else
    MyEdit .= "`r`n" . Clipboard ;Append CR/LF + Win clipboard
  GuiControl,, MyEdit, %MyEdit%  ;Update Edit view
Return

              ;----------------

;Paste to Cursor (position in any application)
^+PgDn:: ;Ctrl+Shift+PgDn
Paste:
  GuiControlGet, MyEdit       ;Get Edit contents into MyEdit
  Clipboard := MyEdit         ;Copy to Windows Clipboard
   ClipWait
  Gui, Hide
  StringReplace, Clipboard, Clipboard,`n,`r`n, All ;See Note 1* below
  WinWaitNotActive               ;Uses "Last found" window
  SendInput ^v                   ;Paste to cursor position
  SendInput {enter}              ;Optionally add line break
  ;Optionally redisplay floating clipboard
  Gui, Show, NA  ;Redisplay floating clipboard but don't activate it
  ;Gui, Show       ;Redisplay floating clipboard, activating it
  GuiVisible := "1"
Return

              ;----------------

;Paste directly to a selected application (in this example, Notepad,
;which must be loaded though may be hidden)
;Adapt this to any other application with an edit field
^+End:: ;Ctrl+Shift+End
Direct:
  GuiControlGet, MyEdit       ;Get Edit contents into MyEdit
  Clipboard := MyEdit         ;Copy to Windows Clipboard
  ClipWait
  Gui, Hide
  StringReplace, Clipboard, Clipboard,`n,`r`n, All ;See Note 1* below
  WinWaitNotActive               ;Uses "Last found" window
  WinActivate, ahk_class Notepad ;Use Window Spy to find AHK class
   ;Or "WinActivate, Notepad" if relying on window title
  Sleep 500                      ;shorten as required
  ;(Do anything else required to move focus into target editor window)
  SendInput ^v                   ;Paste into selected application
  SendInput {enter}              ;Optionally add line break
  ;Optionally redisplay floating clipboard
  Gui, Show, NA  ;Redisplay floating clipboard but don't activate it
  ;Gui, Show       ;Redisplay floating clipboard, activating it
  GuiVisible := "1"
Return

/*
*Note 1: Ensures that line breaks are formatted strictly.
 Not all applications require it but Notepad does and won't
 break lines unless it sees CR+LF.
*/

              ;----------------

;Move Clipboard left/right/up/down
;Have to use GuiGetPos(), not WinGetPos here since WinGetPos returns
;*outer* window dimensions, not (inner) GUI client area dimensions :(
;See http://www.autohotkey.com/forum/viewtopic.php?t=47906
^+Left:: ;Ctrl+Shift+Left
  GuiGetPos(xPos,yPos,wGui,hGui,1) ;1 = Gui # in script; default = 1
  midGuiX := xPos + (wGui //2)         ;Calculate x coord of middle of GUI
  GuiX1 := (A_ScreenWidth //2) - (wGui //2) ;Calculate where it would be if midscreen
  If (midGuiX > (A_ScreenWidth //2))   ;If to the R of middle
    Gui, Show, x%GuiX1% NA    ;Move to middle position
  Else                                 ;GUI is to L of middle
    Gui, Show, x%GuiLeftX% NA ;Move all the way to L position
  GuiVisible := "1"
Return

^+Right:: ;Ctrl+Shift+Right
  GuiGetPos(xPos,yPos,wGui,hGui,1)
  midGuiX := xPos + (wGui //2)
  GuiX1 := (A_ScreenWidth //2) - (wGui //2)
  If (midGuiX < (A_ScreenWidth //2))
    Gui, Show, x%GuiX1% NA
  Else
    Gui, Show, x%GuiRightX% NA
  GuiVisible := "1"
Return

^+Up:: ;Ctrl+Shift+Up
  GuiGetPos(xPos,yPos,wGui,hGui,1)
  midGuiY := yPos + (hGui //2)
  GuiY1 := (A_ScreenHeight //2) - (hGui //2)
  If (midGuiY > (A_ScreenHeight //2))
    Gui, Show, y%GuiY1% NA
  Else
    Gui, Show, y%GuiUpperY% NA
  GuiVisible := "1"
Return

^+Down:: ;Ctrl+Shift+Down
  GuiGetPos(xPos,yPos,wGui,hGui,1)
  midGuiY := yPos + (hGui //2)
  GuiY1 := (A_ScreenHeight //2) - (hGui //2)
  If (midGuiY < (A_ScreenHeight //2))
    Gui, Show, y%GuiY1% NA
  Else
    Gui, Show, y%GuiLowerY% NA
  GuiVisible := "1"
Return

              ;----------------

;Cycle between presets (#1 is default)

;Cycle in increasing preset number
^+]:: ;Ctrl+Shift+RSqBrkt 
  PresetNum++ ;Next preset
  If (PresetNum > MaxPresets)
    PresetNum := "1"
  Gosub, DisplayPreset
Return  

;Cycle in decreasing preset number
^+[:: ;Ctrl+Shift+LSqBrkt
  PresetNum-- ;Previous preset
  If (PresetNum = 0)
    PresetNum := MaxPresets  
  Gosub, DisplayPreset
Return  

DisplayPreset:
  SetXName := "GuiX" . PresetNum
  SetYName := "GuiY" . PresetNum
  SetWName := "GuiW" . PresetNum
  SetHName := "GuiH" . PresetNum

  SetX := %SetXName%
  SetY := %SetYName%
  SetW := %SetWName%
  SetH := %SetHName%

  Gui, Show, x%SetX% y%SetY% w%SetW% h%SetH%
  GuiVisible := "1"
Return


;---------------------------------------
;FUNCTIONS used here
;GuiGetPos function by Icarus
;http://www.autohotkey.com/forum/viewtopic.php?t=47906
GuiGetPos( ByRef X, ByRef Y, ByRef W, ByRef H, GuiID=1 ) {
   Gui %GuiID%:+LastFoundExist
   IfWinExist
   {
      WinGetPos X, Y
      VarSetCapacity( rect, 16, 0 )
      DllCall("GetClientRect", uint, MyGuiHWND := WinExist(), uint, &rect )
      W := NumGet( rect, 8, "int" )
      H := NumGet( rect, 12, "int" )
   }
}
;---------------------------------------


(Added) Had to add this line:
StringReplace, Clipboard, Clipboard,`n,`r`n, All
to the Paste and Special blocks to ensure target edit field formats line breaks correctly. See discussion here:
http://www.autohotke...ic.php?p=359674