| 1007 | |
| 1008 | |
| 1009 | void SendKey(vk_type aVK, sc_type aSC, modLR_type aModifiersLR, modLR_type aModifiersLRPersistent |
| 1010 | , int aRepeatCount, KeyEventTypes aEventType, modLR_type aKeyAsModifiersLR, HWND aTargetWindow |
| 1011 | , int aX, int aY, bool aMoveOffset) |
| 1012 | // Caller has ensured that: 1) vk or sc may be zero, but not both; 2) aRepeatCount > 0. |
| 1013 | // This function is responsible for first setting the correct state of the modifier keys |
| 1014 | // (as specified by the caller) before sending the key. After sending, it should put the |
| 1015 | // modifier keys back to the way they were originally (UPDATE: It does this only for Win/Alt |
| 1016 | // for the reasons described near the end of this function). |
| 1017 | { |
| 1018 | // Caller is now responsible for verifying this: |
| 1019 | // Avoid changing modifier states and other things if there is nothing to be sent. |
| 1020 | // Otherwise, menu bar might activated due to ALT keystrokes that don't modify any key, |
| 1021 | // the Start Menu might appear due to WIN keystrokes that don't modify anything, etc: |
| 1022 | //if ((!aVK && !aSC) || aRepeatCount < 1) |
| 1023 | // return; |
| 1024 | |
| 1025 | // I thought maybe it might be best not to release unwanted modifier keys that are already down |
| 1026 | // (perhaps via something like "Send, {altdown}{esc}{altup}"), but that harms the case where |
| 1027 | // modifier keys are down somehow, unintentionally: The send command wouldn't behave as expected. |
| 1028 | // e.g. "Send, abc" while the control key is held down by other means, would send ^a^b^c, |
| 1029 | // possibly dangerous. So it seems best to default to making sure all modifiers are in the |
| 1030 | // proper down/up position prior to sending any Keybd events. UPDATE: This has been changed |
| 1031 | // so that only modifiers that were actually used to trigger that hotkey are released during |
| 1032 | // the send. Other modifiers that are down may be down intentionally, e.g. due to a previous |
| 1033 | // call to Send such as: Send {ShiftDown}. |
| 1034 | // UPDATE: It seems best to save the initial state only once, prior to sending the key-group, |
| 1035 | // because only at the beginning can the original state be determined without having to |
| 1036 | // save and restore it in each loop iteration. |
| 1037 | // UPDATE: Not saving and restoring at all anymore, due to interference (side-effects) |
| 1038 | // caused by the extra keybd events. |
| 1039 | |
| 1040 | // The combination of aModifiersLR and aModifiersLRPersistent are the modifier keys that |
| 1041 | // should be down prior to sending the specified aVK/aSC. aModifiersLR are the modifiers |
| 1042 | // for this particular aVK keystroke, but aModifiersLRPersistent are the ones that will stay |
| 1043 | // in pressed down even after it's sent. |
| 1044 | modLR_type modifiersLR_specified = aModifiersLR | aModifiersLRPersistent; |
| 1045 | bool vk_is_mouse = IsMouseVK(aVK); // Caller has ensured that VK is non-zero when it wants a mouse click. |
| 1046 | |
| 1047 | LONG_OPERATION_INIT |
| 1048 | for (int i = 0; i < aRepeatCount; ++i) |
| 1049 | { |
| 1050 | if (!sSendMode) |
| 1051 | LONG_OPERATION_UPDATE_FOR_SENDKEYS // This does not measurably affect the performance of SendPlay/Event. |
| 1052 | // These modifiers above stay in effect for each of these keypresses. |
| 1053 | // Always on the first iteration, and thereafter only if the send won't be essentially |
| 1054 | // instantaneous. The modifiers are checked before every key is sent because |
| 1055 | // if a high repeat-count was specified, the user may have time to release one or more |
| 1056 | // of the modifier keys that were used to trigger a hotkey. That physical release |
| 1057 | // will cause a key-up event which will cause the state of the modifiers, as seen |
| 1058 | // by the system, to change. For example, if user releases control-key during the operation, |
| 1059 | // some of the D's won't be control-D's: |
| 1060 | // ^c::Send,^{d 15} |
| 1061 | // Also: Seems best to do SetModifierLRState() even if Keydelay < 0: |
| 1062 | // Update: If this key is itself a modifier, don't change the state of the other |
| 1063 | // modifier keys just for it, since most of the time that is unnecessary and in |
| 1064 | // some cases, the extra generated keystrokes would cause complications/side-effects. |
| 1065 | if (!aKeyAsModifiersLR) |
| 1066 | { |
no test coverage detected