home *** CD-ROM | disk | FTP | other *** search
- /*
- AutoHotkey
-
- Copyright 2003-2007 Chris Mallett (support@autohotkey.com)
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
-
- #ifndef keyboard_h
- #define keyboard_h
-
- #include "defines.h"
-
- // The max number of keystrokes to Send prior to taking a break to pump messages:
- #define MAX_LUMP_KEYS 50
-
- // Logging keys to a file is disabled in the main version in an effort to prevent
- // AutoHotkey from being branded as a key logger or trojan by various security firms and
- // security software. Uncomment this line to re-enabled logging of keys to a file:
- // #define ENABLE_KEY_HISTORY_FILE
-
- // Maybe define more of these later, perhaps with ifndef (since they should be in the normal header, and probably
- // will be eventually):
- // ALREADY DEFINED: #define VK_HELP 0x2F
- // In case a compiler with a non-updated header file is used:
- #ifndef VK_BROWSER_BACK
- #define VK_BROWSER_BACK 0xA6
- #define VK_BROWSER_FORWARD 0xA7
- #define VK_BROWSER_REFRESH 0xA8
- #define VK_BROWSER_STOP 0xA9
- #define VK_BROWSER_SEARCH 0xAA
- #define VK_BROWSER_FAVORITES 0xAB
- #define VK_BROWSER_HOME 0xAC
- #define VK_VOLUME_MUTE 0xAD
- #define VK_VOLUME_DOWN 0xAE
- #define VK_VOLUME_UP 0xAF
- #define VK_MEDIA_NEXT_TRACK 0xB0
- #define VK_MEDIA_PREV_TRACK 0xB1
- #define VK_MEDIA_STOP 0xB2
- #define VK_MEDIA_PLAY_PAUSE 0xB3
- #define VK_LAUNCH_MAIL 0xB4
- #define VK_LAUNCH_MEDIA_SELECT 0xB5
- #define VK_LAUNCH_APP1 0xB6
- #define VK_LAUNCH_APP2 0xB7
- #endif
-
- // Create some "fake" virtual keys to simplify sections of the code.
- // According to winuser.h, the following ranges (among others)
- // are considered "unassigned" rather than "reserved", so should be
- // fairly safe to use for the foreseeable future. 0xFF should probably
- // be avoided since it's sometimes used as a failure indictor by API
- // calls. And 0x00 should definitely be avoided because it is used
- // to indicate failure by many functions that deal with virtual keys.
- // 0x88 - 0x8F : unassigned
- // 0x97 - 0x9F : unassigned (this range seems less likely to be used)
- #define VK_NEW_MOUSE_FIRST 0x9C
- #define VK_LBUTTON_LOGICAL 0x9C // v1.0.43: Added to support swapping of left/right mouse buttons in Control Panel.
- #define VK_RBUTTON_LOGICAL 0x9D //
- #define VK_WHEEL_DOWN 0x9E
- #define VK_WHEEL_UP 0x9F
- #define VK_NEW_MOUSE_LAST 0x9F
-
- // These are the only keys for which another key with the same VK exists. Therefore, use scan code for these.
- // If use VK for some of these (due to them being more likely to be used as hotkeys, thus minimizing the
- // use of the keyboard hook), be sure to use SC for its counterpart.
- // Always use the compressed version of scancode, i.e. 0x01 for the high-order byte rather than vs. 0xE0.
- #define SC_NUMPADENTER 0x11C
- #define SC_INSERT 0x152
- #define SC_DELETE 0x153
- #define SC_HOME 0x147
- #define SC_END 0x14F
- #define SC_UP 0x148
- #define SC_DOWN 0x150
- #define SC_LEFT 0x14B
- #define SC_RIGHT 0x14D
- #define SC_PGUP 0x149
- #define SC_PGDN 0x151
-
- // These are the same scan codes as their counterpart except the extended flag is 0 rather than
- // 1 (0xE0 uncompressed):
- #define SC_ENTER 0x1C
- // In addition, the below dual-state numpad keys share the same scan code (but different vk's)
- // regardless of the state of numlock:
- #define SC_NUMPADDEL 0x53
- #define SC_NUMPADINS 0x52
- #define SC_NUMPADEND 0x4F
- #define SC_NUMPADHOME 0x47
- #define SC_NUMPADCLEAR 0x4C
- #define SC_NUMPADUP 0x48
- #define SC_NUMPADDOWN 0x50
- #define SC_NUMPADLEFT 0x4B
- #define SC_NUMPADRIGHT 0x4D
- #define SC_NUMPADPGUP 0x49
- #define SC_NUMPADPGDN 0x51
-
- #define SC_NUMPADDOT SC_NUMPADDEL
- #define SC_NUMPAD0 SC_NUMPADINS
- #define SC_NUMPAD1 SC_NUMPADEND
- #define SC_NUMPAD2 SC_NUMPADDOWN
- #define SC_NUMPAD3 SC_NUMPADPGDN
- #define SC_NUMPAD4 SC_NUMPADLEFT
- #define SC_NUMPAD5 SC_NUMPADCLEAR
- #define SC_NUMPAD6 SC_NUMPADRIGHT
- #define SC_NUMPAD7 SC_NUMPADHOME
- #define SC_NUMPAD8 SC_NUMPADUP
- #define SC_NUMPAD9 SC_NUMPADPGUP
-
- // These both have a unique vk and a unique sc (on most keyboards?), but they're listed here because
- // MapVirtualKey doesn't support them under Win9x (except maybe NumLock itself):
- #define SC_NUMLOCK 0x145
- #define SC_NUMPADDIV 0x135
- #define SC_NUMPADMULT 0x037
- #define SC_NUMPADSUB 0x04A
- #define SC_NUMPADADD 0x04E
-
- // Note: A KeyboardProc() (hook) actually receives 0x36 for RSHIFT under both WinXP and Win98se, not 0x136.
- // All the below have been verified to be accurate under Win98se and XP (except rctrl and ralt in XP).
- #define SC_LCONTROL 0x01D
- #define SC_RCONTROL 0x11D
- #define SC_LSHIFT 0x02A
- #define SC_RSHIFT 0x136 // Must be extended, at least on WinXP, or there will be problems, e.g. SetModifierLRState().
- #define SC_LALT 0x038
- #define SC_RALT 0x138
- #define SC_LWIN 0x15B
- #define SC_RWIN 0x15C
-
- // UPDATE for v1.0.39: Changed sc_type to USHORT vs. UINT to save memory in structs such as sc_hotkey.
- // This saves 60K of memory in one place, and possibly there are other large savings too.
- // The following older comment dates back to 2003/inception and I don't remember its exact intent,
- // but there is no current storage of mouse message constants in scan code variables:
- // OLD: Although only need 9 bits for compressed and 16 for uncompressed scan code, use a full 32 bits
- // so that mouse messages (WPARAM) can be stored as scan codes. Formerly USHORT (which is always 16-bit).
- typedef USHORT sc_type; // Scan code.
- typedef UCHAR vk_type; // Virtual key.
- typedef UINT mod_type; // Standard Windows modifier type for storing MOD_CONTROL, MOD_WIN, MOD_ALT, MOD_SHIFT.
-
- // The maximum number of virtual keys and scan codes that can ever exist.
- // As of WinXP, these are absolute limits, except for scan codes for which there might conceivably
- // be more if any non-standard keyboard or keyboard drivers generate scan codes that don't start
- // with either 0x00 or 0xE0. UPDATE: Decided to allow all possible scancodes, rather than just 512,
- // since a lookup array for the 16-bit scan code value will only consume 64K of RAM if the element
- // size is one char. UPDATE: decided to go back to 512 scan codes, because WinAPI's KeyboardProc()
- // itself can only handle that many (a 9-bit value). 254 is the largest valid vk, according to the
- // WinAPI docs (I think 255 is value that is sometimes returned to indicate an invalid vk). But
- // just in case something ever tries to access such arrays using the largest 8-bit value (255), add
- // 1 to make it 0xFF, thus ensuring array indexes will always be in-bounds if they are 8-bit values.
- #define VK_MAX 0xFF
- #define SC_MAX 0x1FF
-
- typedef UCHAR modLR_type; // Only the left-right win/alt/ctrl/shift rather than their generic counterparts.
- #define MODLR_MAX 0xFF
- #define MODLR_COUNT 8
- #define MOD_LCONTROL 0x01
- #define MOD_RCONTROL 0x02
- #define MOD_LALT 0x04
- #define MOD_RALT 0x08
- #define MOD_LSHIFT 0x10
- #define MOD_RSHIFT 0x20
- #define MOD_LWIN 0x40
- #define MOD_RWIN 0x80
-
-
- struct CachedLayoutType
- {
- HKL hkl;
- ResultType has_altgr;
- };
-
- struct key_to_vk_type // Map key names to virtual keys.
- {
- char *key_name;
- vk_type vk;
- };
-
- struct key_to_sc_type // Map key names to scan codes.
- {
- char *key_name;
- sc_type sc;
- };
-
- enum KeyStateTypes {KEYSTATE_LOGICAL, KEYSTATE_PHYSICAL, KEYSTATE_TOGGLE}; // For use with GetKeyJoyState(), etc.
- enum KeyEventTypes {KEYDOWN, KEYUP, KEYDOWNANDUP};
-
- void SendKeys(char *aKeys, bool aSendRaw, SendModes aSendModeOrig, HWND aTargetWindow = NULL);
- void SendKey(vk_type aVK, sc_type aSC, modLR_type aModifiersLR, modLR_type aModifiersLRPersistent
- , int aRepeatCount, KeyEventTypes aEventType, modLR_type aKeyAsModifiersLR, HWND aTargetWindow
- , int aX = COORD_UNSPECIFIED, int aY = COORD_UNSPECIFIED, bool aMoveOffset = false);
- void SendKeySpecial(char aChar, int aRepeatCount);
- void SendASC(char *aAscii);
-
- struct PlaybackEvent
- {
- UINT message;
- union
- {
- struct
- {
- sc_type sc; // Placed above vk for possibly better member stacking/alignment.
- vk_type vk;
- };
- struct
- {
- // Screen coordinates, which can be negative. SHORT vs. INT is used because the likelihood
- // have having a virtual display surface wider or taller than 32,767 seems too remote to
- // justify increasing the struct size, which would impact the stack space and dynamic memory
- // used by every script every time it uses the playback method to send keystrokes or clicks.
- // Note: WM_LBUTTONDOWN uses WORDs vs. SHORTs, but they're not really comparable because
- // journal playback/record both use screen coordinates but WM_LBUTTONDOWN et. al. use client
- // coordinates.
- SHORT x;
- SHORT y;
- };
- DWORD time_to_wait; // This member is present only when message==0; otherwise, a struct is present.
- };
- };
- LRESULT CALLBACK PlaybackProc(int aCode, WPARAM wParam, LPARAM lParam);
- //#define JOURNAL_RECORD_MODE // Uncomment this line to debug/analyze via a crude journal record feature in place of SendPlay.
- #ifdef JOURNAL_RECORD_MODE
- LRESULT CALLBACK RecordProc(int aCode, WPARAM wParam, LPARAM lParam);
- #endif
-
-
- // Below uses a pseudo-random value. It's best that this be constant so that if multiple instances
- // of the app are running, they will all ignore each other's keyboard & mouse events. Also, a value
- // close to UINT_MAX might be a little better since it's might be less likely to be used as a pointer
- // value by any apps that send keybd events whose ExtraInfo is really a pointer value:
- #define KEY_IGNORE 0xFFC3D44F
- #define KEY_PHYS_IGNORE (KEY_IGNORE - 1) // Same as above but marked as physical for other instances of the hook.
- #define KEY_IGNORE_ALL_EXCEPT_MODIFIER (KEY_IGNORE - 2) // Non-physical and ignored only if it's not a modifier.
-
- // The default in the below is KEY_IGNORE_ALL_EXCEPT_MODIFIER, which causes standard calls to
- // KeyEvent() to update g_modifiersLR_logical_non_ignored the same way it updates g_modifiersLR_logical.
- // This is done because only the Send command has a realistic chance of interfering with (or being
- // interfered with by) hook hotkeys (namely the modifiers used to decide whether to trigger them).
- // There are two types of problems:
- // 1) Hotkeys not firing due to Send having temporarily released one of that hotkey's modifiers that
- // the user is still holding down. This causes the hotkey's suffix to flow through to the system,
- // which is usually undesirable. This happens when the user is holding down a hotkey to auto-repeat
- // it, and perhaps other times.
- // 2) The wrong hotkey firing because Send has temporarily put a modifier into effect and (once again)
- // the user is holding down the hotkey to auto-repeat it. If the Send's temp-down modifier happens
- // to make the hotkey suffix match a different set of modifiers, the wrong hotkey would fire.
- void KeyEvent(KeyEventTypes aEventType, vk_type aVK, sc_type aSC = 0, HWND aTargetWindow = NULL
- , bool aDoKeyDelay = false, DWORD aExtraInfo = KEY_IGNORE_ALL_EXCEPT_MODIFIER);
-
- ResultType PerformClick(char *aOptions);
- void ParseClickOptions(char *aOptions, int &aX, int &aY, vk_type &aVK, KeyEventTypes &aEventType
- , int &aRepeatCount, bool &aMoveOffset);
- ResultType PerformMouse(ActionTypeType aActionType, char *aButton, char *aX1, char *aY1, char *aX2, char *aY2
- , char *aSpeed, char *aOffsetMode, char *aRepeatCount = "", char *aDownUp = "");
- void PerformMouseCommon(ActionTypeType aActionType, vk_type aVK, int aX1, int aY1, int aX2, int aY2
- , int aRepeatCount, KeyEventTypes aEventType, int aSpeed, bool aMoveOffset);
-
- void MouseClickDrag(vk_type aVK // Which button.
- , int aX1, int aY1, int aX2, int aY2, int aSpeed, bool aMoveOffset);
- void MouseClick(vk_type aVK // Which button.
- , int aX, int aY, int aRepeatCount, int aSpeed, KeyEventTypes aEventType, bool aMoveOffset = false);
- void MouseMove(int &aX, int &aY, DWORD &aEventFlags, int aSpeed, bool aMoveOffset);
- void MouseEvent(DWORD aEventFlags, DWORD aData, DWORD aX = COORD_UNSPECIFIED, DWORD aY = COORD_UNSPECIFIED);
-
- #define MSG_OFFSET_MOUSE_MOVE 0x80000000 // Bitwise flag, should be near/at high-order bit to avoid overlap messages.
- void PutKeybdEventIntoArray(modLR_type aKeyAsModifiersLR, vk_type aVK, sc_type aSC, DWORD aEventFlags, DWORD aExtraInfo);
- void PutMouseEventIntoArray(DWORD aEventFlags, DWORD aData, DWORD aX, DWORD aY);
- ResultType ExpandEventArray();
- void InitEventArray(void *aMem, UINT aMaxEvents, modLR_type aModifiersLR);
- void SendEventArray(int &aFinalKeyDelay, modLR_type aModsDuringSend);
- void CleanupEventArray(int aFinalKeyDelay);
-
- EXTERN_G; // For the DoKeyDelay() prototype below.
- extern SendModes sSendMode;
- void DoKeyDelay(int aDelay = (sSendMode == SM_PLAY) ? g.KeyDelayPlay : g.KeyDelay);
- void DoMouseDelay();
- void UpdateKeyEventHistory(bool aKeyUp, vk_type aVK, sc_type aSC);
- #define KEYEVENT_PHYS(event_type, vk, sc) KeyEvent(event_type, vk, sc, NULL, false, KEY_PHYS_IGNORE)
-
- ToggleValueType ToggleKeyState(vk_type aVK, ToggleValueType aToggleValue);
- void ToggleNumlockWin9x();
- //void CapslockOffWin9x();
-
- #define STD_MODS_TO_DISGUISE (MOD_LALT|MOD_RALT|MOD_LWIN|MOD_RWIN)
- void SetModifierLRState(modLR_type aModifiersLRnew, modLR_type aModifiersLRnow, HWND aTargetWindow
- , bool aDisguiseDownWinAlt, bool aDisguiseUpWinAlt, DWORD aExtraInfo = KEY_IGNORE_ALL_EXCEPT_MODIFIER);
- modLR_type GetModifierLRState(bool aExplicitlyGet = false);
-
- // The IsKeyDown9xNT() method is needed because GetKeyState() does not return the proper
- // state under Win9x, at least for the modifier keys under certain conditions. The
- // AutoIt3 author indicates that GetAsyncKeyState() is also unreliable and he uses
- // this same method, so it seems best for now. Specify GetAsyncKeyState() first due
- // to performance of short-circuit boolean. v1.0.42.01: Fixed to use 0x8000 vs. 0x80000000
- // with GetAsyncKeyState (though luckily, because of the way a negative short gets promoted
- // to a negative int, the old way of using 0x80000000 worked too).
- #define IsKeyDown9xNT(vk) ( (GetAsyncKeyState(vk) & 0x8000) || ((GetKeyState(vk) & 0x8000)) )
- #define IsKeyDown2kXP(vk) (GetKeyState(vk) & 0x8000)
- #define IsKeyDownAsync(vk) (GetAsyncKeyState(vk) & 0x8000)
- #define IsKeyToggledOn(vk) (GetKeyState(vk) & 0x01)
-
- void AdjustKeyState(BYTE aKeyState[], modLR_type aModifiersLR);
- modLR_type KeyToModifiersLR(vk_type aVK, sc_type aSC = 0, bool *pIsNeutral = NULL);
- modLR_type ConvertModifiers(mod_type aModifiers);
- mod_type ConvertModifiersLR(modLR_type aModifiersLR);
- char *ModifiersLRToText(modLR_type aModifiersLR, char *aBuf);
-
- #define LAYOUT_UNDETERMINED FAIL
- bool ActiveWindowLayoutHasAltGr();
- ResultType LayoutHasAltGr(HKL aLayout, ResultType aHasAltGr = LAYOUT_UNDETERMINED);
-
- //---------------------------------------------------------------------
-
- char *SCtoKeyName(sc_type aSC, char *aBuf, int aBufSize);
- char *VKtoKeyName(vk_type aVK, sc_type aSC, char *aBuf, int aBufSize);
- sc_type TextToSC(char *aText);
- vk_type TextToVK(char *aText, modLR_type *pModifiersLR = NULL, bool aExcludeThoseHandledByScanCode = false
- , bool aAllowExplicitVK = true, HKL aKeybdLayout = GetKeyboardLayout(0));
- vk_type CharToVKAndModifiers(char aChar, modLR_type *pModifiersLR, HKL aKeybdLayout);
- vk_type TextToSpecial(char *aText, UINT aTextLength, KeyEventTypes &aEventTypem, modLR_type &aModifiersLR
- , bool aUpdatePersistent);
-
- #ifdef ENABLE_KEY_HISTORY_FILE
- ResultType KeyHistoryToFile(char *aFilespec = NULL, char aType = '\0', bool aKeyUp = false
- , vk_type aVK = 0, sc_type aSC = 0);
- #endif
-
- char *GetKeyName(vk_type aVK, sc_type aSC, char *aBuf, int aBufSize);
- sc_type vk_to_sc(vk_type aVK, bool aReturnSecondary = false);
- vk_type sc_to_vk(sc_type aSC);
-
- inline bool IsMouseVK(vk_type aVK)
- {
- return aVK >= VK_LBUTTON && aVK <= VK_XBUTTON2 && aVK != VK_CANCEL
- || aVK >= VK_NEW_MOUSE_FIRST && aVK <= VK_NEW_MOUSE_LAST;
- }
-
- #endif
-