anatolt

Date-n-time-inserter-v0.7

Jun 24th, 2015
985
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; HotkeyRequester.pbi
  2. ; Dec 1, 2014
  3. ; Windows Only
  4. ; Written in PB 5.31 x86
  5. ; Author: missile69
  6. ; http://www.purebasic.fr/english/memberlist.php?mode=viewprofile&u=7421
  7. ;
  8. ; License: Free to use, modify, or publish any way you wish. Credit appreciated,
  9. ;          not required.
  10. ;
  11. ; Main function: HotkeyRequester(WindowNumber.i, Title$, Instruction$, *funcToCall)
  12.                 ;WindowNumber = Window that will respond to #WM_Hotkey. Usually your main window as closed windows
  13.                 ;               can't respond to hotkey messages.
  14.                 ;Title$       = Title bar text
  15.                 ;Instruction$ =
  16.                 ;*funcToCall  = Pointer to the function you want called when this hotkey is triggered. Function
  17.                 ;               should not require parameters
  18.                 ;
  19.                 ;Return Value = ID number of hotkey if successfully set. Zero otherwise.
  20. ;
  21. ; Opens a simple window where your program's user can easily select pick a
  22. ; global hotkey. HotkeyRequester features "live" updating of their keypresses and
  23. ; color-based visual feedback to show the validity of their chosen Hotkey
  24. ;
  25. ; Global hotkeys, as opposed to PB's keyboard shortcuts, are
  26. ; available even when your program's window is not focused or is not visible.
  27.  
  28. EnableExplicit
  29.  
  30. Enumeration whk 100
  31.   #wndHKRequester
  32.   #tmrUpdate
  33.   #fntHKDisplay
  34.   ;Gadgets
  35.   #lblHKDisplay
  36.   #btnOk
  37.   #btnCancel
  38. EndEnumeration
  39.  
  40. Structure _UserHK
  41.   vkey.i
  42.   mods.i
  43.   hWnd.i
  44.   ID.i
  45.   *function
  46.   friendlyString.s
  47. EndStructure
  48.  
  49. NewList hkList._UserHK()
  50.  
  51. ;This flag ensures only one #WM_Hotkey message is received even if user keeps
  52. ;hotkey buttons pushed down.
  53. #MOD_NOREPEAT = 16384
  54. ;Colors
  55. #myGreen      = $37A537
  56. #myRed        = $BE3F3F
  57.  
  58. Procedure.i _whk_idExists(hkID.i)
  59.   Shared hkList()
  60.  
  61.   If hkID
  62.     ForEach hkList()
  63.       If hkList()\ID = hkID
  64.         ProcedureReturn @hkList()
  65.         Break
  66.       EndIf
  67.     Next
  68.   EndIf
  69.  
  70.   ProcedureReturn 0
  71. EndProcedure
  72.  
  73. Procedure.i _whk_isDuplicate(*UserHK._UserHK)
  74.   Shared hkList()
  75.   Protected r.i
  76.  
  77.     ForEach hkList()
  78.       If hkList()\mods = *UserHK\mods And hkList()\vkey = *UserHK\vkey
  79.         r = #True
  80.         Break
  81.       EndIf
  82.     Next
  83.  
  84.   ProcedureReturn r
  85. EndProcedure
  86.  
  87. Procedure WM_HOTKEY_Event(wParam.i, lParam.i)
  88.   ;This function should be called from your window callback when a
  89.   ;#WM_HOTKEY message is received.
  90.  
  91.   Shared hkList()
  92.  
  93.   ;Debug "WM_HOTKEY id = " + Str(wParam)
  94.   If _whk_idExists(wParam)
  95.     CallFunctionFast(hkList()\function)
  96.   EndIf
  97.  
  98. EndProcedure
  99.  
  100. Procedure RemoveHotkey(hkID.i)
  101.   ;Returns non-zero on success, else returns zero.
  102.   ;hkID = ID number associated with this hotkey. #PB_All can be used to unregister all
  103.   ;       hotkeys when your program ends.
  104.   Shared hkList()
  105.   Protected i.i
  106.   If hkID = #PB_All
  107.     ForEach hkList()
  108.       UnregisterHotKey_(hkList()\hWnd, hkList()\ID)
  109.       i + 1
  110.     Next
  111.     ClearList(hkList())
  112.     ;Debug "Unregistered " + Str(i) + " Hotkeys"
  113.   ElseIf hkID
  114.     ;If the given hotkey ID is valid, unregister it and delete from list.
  115.     If _whk_idExists(hkID)
  116.       UnregisterHotKey_(hkList()\hWnd, hkList()\ID)
  117.       DeleteElement(hkList())
  118.     EndIf
  119.   EndIf
  120.  
  121. EndProcedure
  122.  
  123. Procedure.i _whk_addHotkey(*UserHK._UserHK, Test.b = #False)
  124.   ;Hotkey       = Pointer to filled out _userHK-structured variable. \ID value is always auto-generated
  125.   ;               and the is the return value.
  126.   ;Test         = If true, unregisters the hotkey before exiting and doesn't add it to our hkList().
  127.   ;
  128.   ;Return Value = Hotkey ID on success. 0 on error (usually means that hotkey is already used by another program).
  129.  
  130.   Shared hkList()
  131.   Protected r.i
  132.   Static hkAutoID.i
  133.   hkAutoID + 1
  134.  
  135.   With *UserHK
  136.     If \friendlyString And \function And \mods And \vkey
  137.       \ID = hkAutoID
  138.      
  139.       If _whk_isDuplicate(*UserHK) = #False
  140.         r = RegisterHotKey_(\hWnd, \ID, \mods, \vKey)
  141.         If r
  142.           If Test
  143.             UnregisterHotKey_(\hWnd, \ID)
  144.             hkAutoID - 1
  145.           Else
  146.             AddElement(hkList())
  147.             hkList()\friendlyString = \friendlyString
  148.             hkList()\function       = \function
  149.             hkList()\hWnd           = \hWnd
  150.             hkList()\ID             = \ID
  151.             hkList()\mods           = \mods
  152.             hkList()\vkey           = \vkey
  153.           EndIf
  154.           r = \ID
  155.         Else
  156.           hkAutoID - 1
  157.         EndIf
  158.       Else
  159.         hkAutoID - 1
  160.       EndIf
  161.      
  162.     EndIf
  163.   EndWith
  164.  
  165.   ProcedureReturn r
  166. EndProcedure
  167.  
  168. Procedure.i HotkeyKeycode(hkID.i)
  169.   ;Returns the key code associated with given ID.
  170.  
  171.   Shared hkList()
  172.   If _whk_idExists(hkID)
  173.     ProcedureReturn hkList()\vkey
  174.   EndIf
  175.  
  176.   ProcedureReturn #Null
  177. EndProcedure
  178.  
  179. Procedure.i HotkeyModifiers(hkID.i)
  180.   ;Returns the modifiers associated with given ID. They can be any combination
  181.   ;of #MOD_ALT, #MOD_CONTROL, #MOD_SHIFT, and #MOD_NOREPEAT
  182.  
  183.   Shared hkList()
  184.   If _whk_idExists(hkID)
  185.     ProcedureReturn hkList()\mods
  186.   EndIf
  187.  
  188.   ProcedureReturn #Null
  189. EndProcedure
  190.  
  191. Procedure.s HotkeyFriendlyName(hkID.i)
  192.   ;Returns the user-friendly hotkey description associated with the given hkID
  193.   Shared hkList()
  194.   If hkID
  195.     If _whk_idExists(hkID)
  196.       ProcedureReturn hkList()\friendlyString
  197.     EndIf
  198.   EndIf
  199.   ProcedureReturn #NULL$
  200. EndProcedure
  201.  
  202. Procedure.i isHotkey(hkID.i)
  203.   ;Returns non-zero if this hotkey ID is valid and registered. Zero when not.
  204.  
  205.   If hkID
  206.     ProcedureReturn _whk_idExists(hkID)
  207.   EndIf
  208.  
  209.   ProcedureReturn 0
  210. EndProcedure
  211.  
  212.  
  213.  
  214. Procedure.i _whk_checkKB(*UserHK._UserHK)
  215.   ;Checks Ctrl, Alt, Shift and Keycodes 48-122 which correspond to all numbers and basic visible characters.
  216.   ;Since hotkeys can only have one vKey code associated with them, this function only returns the key code
  217.   ;for the first (lowest numbered on Ascii chart) pressed key it finds even if, for example, two letters
  218.   ;were pressed.
  219.   ;
  220.   ;Return value = Non-zero if keyboard state was successfully retrieved. The _UserHK structure passed by
  221.   ;               reference will have its mods, vKey, and friendlyString fields filled in if their
  222.   ;               corresponding keys were pressed.
  223.  
  224.   ClearStructure(*UserHK, _UserHK)
  225.   Protected r.i, i.i
  226.  
  227.   Dim kb.b(255)
  228.   r = GetKeyboardState_(@kb())
  229.   If r
  230.     With *UserHK
  231.      
  232.       If kb(#VK_CONTROL) & $ff > 1
  233.         \mods + #MOD_CONTROL
  234.         \friendlyString + "Ctrl + "
  235.       EndIf
  236.       If kb(#VK_MENU) & $ff > 1
  237.         \mods + #MOD_ALT
  238.         \friendlyString + "Alt + "
  239.       EndIf
  240.       If kb(#VK_SHIFT) & $ff > 1
  241.         \mods + #MOD_SHIFT
  242.         \friendlyString + "Shift + "
  243.       EndIf
  244.       If \mods
  245.         \mods + #MOD_NOREPEAT
  246.       EndIf
  247.      
  248.       For i = '0' To 'z'
  249.         If kb(i) & $ff > 1
  250.          
  251.           ;Debug Chr(i) + " pressed!"
  252.           \friendlyString + Chr(i)
  253.           \vKey = i
  254.           Break
  255.         EndIf
  256.       Next
  257.      
  258.     EndWith
  259.   EndIf
  260.  
  261.   ProcedureReturn r
  262. EndProcedure
  263.  
  264. Procedure.i HotkeyRequester(WindowNumber.i, Title$, Instruction$, *funcToCall)
  265.   ;WindowNumber = Window that will respond to #WM_Hotkey. Usually your main window as closed windows
  266.   ;               can't respond to hotkey messages.
  267.   ;Title$       = Title bar text
  268.   ;Instruction$ =
  269.   ;*funcToCall  = Pointer to the function you want called when this hotkey is triggered. Function
  270.   ;               should not require parameters
  271.   ;
  272.   ;Return Value = ID number of hotkey if successfully set. Zero otherwise.
  273.  
  274.   Protected._UserHK currKeys, prevKeys
  275.   Protected r.i, e.i, h.i, w.i, hkIsValid.i
  276.   Protected MaxHK$ = "Ctrl + Alt + Shift + W"
  277.  
  278.   If IsWindow(WindowNumber)
  279.     WindowNumber = WindowID(WindowNumber)
  280.    
  281.     If OpenWindow(#wndHKRequester, 0, 0, 400, 150, Title$, #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  282.       TextGadget(#PB_Any, 10, 10, WindowWidth(#wndHKRequester) - 20, 36, Instruction$, #PB_Text_Center)
  283.       ButtonGadget(#btnOk, 320, 105, 70, 35, "OK")
  284.       DisableGadget(#btnOk, #True)
  285.       ButtonGadget(#btnCancel, 240, 105, 70, 35, "Cancel")
  286.      
  287.       ;Set up hotkey display area
  288.       LoadFont(#fntHKDisplay, "Arial", 14, #PB_Font_Bold)
  289.       StartDrawing(WindowOutput(#wndHKRequester))
  290.       DrawingFont(FontID(#fntHKDisplay))
  291.       h = TextHeight(MaxHK$) + 20
  292.       w = TextWidth(MaxHK$) + 20
  293.       StopDrawing()
  294.      
  295.       TextGadget(#lblHKDisplay, (400-w)/2, 50, w, h, "None", #PB_Text_Center|#SS_CENTERIMAGE)
  296.       SetGadgetColor(#lblHKDisplay, #PB_Gadget_BackColor, #White)
  297.       SetGadgetFont(#lblHKDisplay, FontID(#fntHKDisplay))
  298.      
  299.       AddWindowTimer(#wndHKRequester, #tmrUpdate, 150)
  300.       Repeat
  301.         e = WaitWindowEvent()
  302.         Select e
  303.           Case #PB_Event_Timer
  304.             If _whk_checkKB(@currKeys)
  305.               With currKeys
  306.                 ;If keys were pressed
  307.                 If \friendlyString
  308.                   ;Show pressed keys to user
  309.                   SetGadgetText(#lblHKDisplay, \friendlyString)
  310.                   If \friendlyString <> prevKeys\friendlyString
  311.                     SetGadgetColor(#lblHKDisplay, #PB_Gadget_FrontColor, #Black)
  312.                   EndIf
  313.                   If \mods And \vkey
  314.                     If \mods <> prevKeys\mods Or \vkey <> prevKeys\vkey
  315.                      
  316.                       \function = *funcToCall
  317.                       \hWnd     = WindowNumber
  318.                       ;Test this hotkey combination.
  319.                       r = _whk_addHotkey(@currKeys, #True)
  320.                       If r
  321.                         ;Hotkey is good and able to be registered
  322.                         prevKeys = currKeys
  323.                         hkIsValid = #True
  324.                         SetGadgetColor(#lblHKDisplay, #PB_Gadget_FrontColor, #myGreen)
  325.                       Else
  326.                         hkIsValid = #False
  327.                         SetGadgetColor(#lblHKDisplay, #PB_Gadget_FrontColor, #myRed)
  328.                       EndIf
  329.                     EndIf
  330.                   EndIf  
  331.                  
  332.                 Else
  333.                   ;Keep showing previous valid hotkey if there is one
  334.                   If prevKeys\ID
  335.                     If GetGadgetData(#btnOk) = 0
  336.                       DisableGadget(#btnOk, #False)
  337.                       SetGadgetData(#btnOk, 1)
  338.                     EndIf
  339.                     SetGadgetText(#lblHKDisplay, prevKeys\friendlyString)
  340.                     SetGadgetColor(#lblHKDisplay, #PB_Gadget_FrontColor, #myGreen)
  341.                   Else
  342.                     If GetGadgetData(#btnOk)
  343.                       DisableGadget(#btnOk, #True)
  344.                       SetGadgetData(#btnOk, 0)
  345.                     EndIf
  346.                     SetGadgetText(#lblHKDisplay, "None")
  347.                     SetGadgetColor(#lblHKDisplay, #PB_Gadget_FrontColor, #Black)
  348.                   EndIf
  349.                 EndIf
  350.               EndWith
  351.             EndIf
  352.            
  353.           Case #PB_Event_Gadget
  354.             Select EventGadget()
  355.               Case #btnOk
  356.                 If prevKeys\ID
  357.                   ;Add hotkey for real this time.
  358.                   r = _whk_addHotkey(@prevKeys)
  359.                 EndIf
  360.                 Break
  361.                
  362.               Case #btnCancel
  363.                 r = 0
  364.                 Break
  365.                
  366.             EndSelect
  367.            
  368.           Case #PB_Event_CloseWindow
  369.             r = 0
  370.             Break
  371.            
  372.         EndSelect
  373.        
  374.       ForEver
  375.      
  376.       RemoveWindowTimer(#wndHKRequester, #tmrUpdate)
  377.       FreeFont(#fntHKDisplay)
  378.       CloseWindow(#wndHKRequester)
  379.      
  380.      
  381.     EndIf
  382.   EndIf
  383.  
  384.   ProcedureReturn r
  385. EndProcedure
  386.  
  387. #Myname = "Date-n-time-inserter-v0.7"
  388. Define appname.s = GetFilePart(ProgramFilename())
  389.  
  390. Enumeration
  391.   #Window
  392.   #SysTrayIcon
  393.   #Menu
  394.   #change_hk
  395.   #Exit
  396.   #icon
  397. EndEnumeration
  398.  
  399. Procedure myWinCallback(hWnd.i, uMsg.i, wParam.i, lParam.i)
  400.  
  401.   If uMsg = #WM_HOTKEY
  402.     WM_HOTKEY_Event(wParam, lParam)
  403.   EndIf
  404.  
  405.   ProcedureReturn #PB_ProcessPureBasicEvents
  406. EndProcedure
  407.  
  408. Procedure pasteStuff()
  409.   Protected i.i, txt$
  410.   ; continue if all keys are free
  411.   Repeat
  412.     For i = 0 To 1000
  413.       If GetKeyState_(i) <= -1
  414.         Break
  415.       ElseIf i = 1000
  416.         Debug "all keys are free"
  417.         Break 2
  418.       EndIf
  419.     Next
  420.     Delay(10)
  421.   ForEver
  422.   Define n.INPUT
  423.   n\type = #INPUT_KEYBOARD
  424.   txt$ = FormatDate("%yyyy.%mm.%dd %hh:%ii",Date())
  425.   SetClipboardText(txt$)
  426.   ;   AddGadgetItem(textField,-1,txt$)
  427.   n\ki\wVk = #VK_CONTROL : n\ki\dwFlags = 0
  428.   SendInput_(1,@n,SizeOf(n))
  429.   n\ki\wVk = #VK_V
  430.   SendInput_(1,@n,SizeOf(n))
  431.   n\ki\dwFlags = #KEYEVENTF_KEYUP
  432.   SendInput_(1,@n,SizeOf(n))
  433.   n\ki\wVk = #VK_CONTROL
  434.   SendInput_(1,@n,SizeOf(n))
  435. EndProcedure
  436.  
  437. Define ev.i, hkInsTimestamp.i, txt2.s = "Press the key combination you want To associate With this action", icon
  438. CreateImage(#icon,16,16)
  439. StartDrawing(ImageOutput(#icon))
  440.   Circle(8,8,7,$000000)
  441. StopDrawing()
  442. If OpenWindow(#Window, 0, 0, 500, 500, #Myname, #PB_Window_Invisible)
  443.   SetWindowCallback(@myWinCallback(), #Window)
  444. ;   icon = ExtractIcon_(WindowID(#Window),appname,0)
  445.   AddSysTrayIcon(#SysTrayIcon,WindowID(#Window),#icon)
  446.   SysTrayIconToolTip(#SysTrayIcon,#Myname)
  447.   CreatePopupMenu(#Menu)
  448.   MenuItem(1,#Myname)
  449.   DisableMenuItem(#Menu,1,1)
  450.   MenuBar()
  451.   MenuItem(#change_hk,"Change Hotkey")
  452.   MenuItem(#Exit,"Exit")
  453.   HotkeyRequester(#Window, #Myname, txt2, @pasteStuff())  
  454.  
  455.   Repeat
  456.     ev = WaitWindowEvent()
  457.   If ev = #PB_Event_SysTray And EventType() = #PB_EventType_RightClick
  458.     DisplayPopupMenu(#Menu,WindowID(#Window))
  459.   ElseIf ev = #PB_Event_Menu
  460.     Select EventMenu()
  461.       Case #change_hk
  462.         If isHotkey(hkInsTimestamp)
  463.           ;If the hotkey was already set, delete it before showing requester again
  464.           RemoveHotkey(hkInsTimestamp)
  465.         EndIf
  466.        
  467.         hkInsTimestamp = HotkeyRequester(#Window, #Myname, txt2, @pasteStuff())
  468.        
  469.         If hkInsTimestamp
  470.           SetMenuItemText(#Menu,#change_hk, "Hotkey: "+HotkeyFriendlyName(hkInsTimestamp))
  471.         Else
  472.           SetMenuItemText(#Menu,#change_hk, "Hotkey: None")
  473.         EndIf
  474.        
  475.       Case #Exit
  476.         Break
  477.     EndSelect
  478.   EndIf
  479.    
  480.   Until ev = #PB_Event_CloseWindow
  481. EndIf
  482. RemoveHotkey(#PB_All)
  483. End
RAW Paste Data