mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Dec 2002
Posts: 252
T
Talon Offline OP
Fjord artisan
OP Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 252
I'm working on a Picwin game in mSL, my own version of a classic game, Pinball!

I wanted to utilize key presses to determine which flipper to operate, and mold this off of other PC pinball games I've played in the past. Games that I remember, like old MS-DOS Epic Pinball, you used the left and right shift keys to control your flippers, and space-bar to launch the ball. Also to keep a similar feel to a real pinball machine, which always had toggles on the side of the unit for your left and right hand to smack to make the flippers move.

Here's a screenshot:
[Linked Image from i.ibb.co]

The problem lies with both ON *:CHAR: and ON *:KEYDOWN, even $mouse.key. How do I tell which shift key is pressed?

ON *:CHAR: does nothing, there's no output for a shift key.
on *:KEYDOWN: tells me the same $keyval for both shift keys (16)
"if ($mouse.key & 4)" or "$and($mouse.key,4)" also just tells me "A" shift key is held, not "which" shift key is held...

Is there something I might be missing here? is it possible to assign an event to ANY key on the keyboard regardless of if they achieve the same function? I'm not familliar with many other keyboards but I think the only repetitive key (besides keypad numbers and number row) is shift....

Joined: Jul 2006
Posts: 4,145
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,145
mIRC is reporting the correct keypress, there's another extra check that need to be performed to get the left/right bit


Originally Posted by https://stackoverflow.com/questions/15966642/how-do-you-tell-lshift-apart-from-rshift-in-wm-keydown-events
To distinguish between the left and right versions of the Shift, Ctrl, or Alt keys, you have to use the MapVirtualKey() function or the 'extended key' bit in the lParam passed with the virtual key's message. The following function will perform that translation for you - just pass in the virtual keycode and the lParam from the message, and you'll get back the left/right specific virtual keycodes as appropriate:

WPARAM MapLeftRightKeys( WPARAM vk, LPARAM lParam)
{
WPARAM new_vk = vk;
UINT scancode = (lParam & 0x00ff0000) >> 16;
int extended = (lParam & 0x01000000) != 0;

switch (vk) {
case VK_SHIFT:
new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
break;
case VK_CONTROL:
new_vk = extended ? VK_RCONTROL : VK_LCONTROL;
break;
case VK_MENU:
new_vk = extended ? VK_RMENU : VK_LMENU;
break;
default:
// not a key we map from generic to left/right specialized
// just return it.
new_vk = vk;
break;
}

return new_vk;
}
If the virtual keycode passed in isn't one that maps to a left/right version, the original keycode is passed back unchanged. So you can just run the WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP message parameters through the function whenever you need to distinguish between the left and right variants.

By using MapVirtualKey() you don't need to know the lore about the left-shift and right-shift scancodes being 0x2a and 0x36 - the API takes care of that detail. And if they ever do happen to be different (not that that will ever really happen), Windows will be responsible for dealing with it, not you.

So in your WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP handlers you just have to add a line of code that looks like:

wparam = MapLeftRightKeys(wparam, lparam);
and the rest of your code can act on the left/right-specific VK codes as if the system message just gave them to you in the first place.
If this is implemented, which I'm all for, it would need to be a new identifier or maybe two properties for $keyval, $keyval.left would be $true if left shift/control/alt is pressed, same for $keyval.right


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Jul 2006
Posts: 4,145
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,145
Some feedback about this..

$keylparam was added to solve the problem of telling if right or left shift/control/alt was pressed (ignoring left alt, which does not trigger).
The problem, as shown in the code i posted above, is that the shift key does not use the the 'extended' 24th bit to tell for left/right, it uses the scan code and the function MapVirtualKey(), which we can't make use of, so for shift, it doesn't solve the problem.

I don't think it was good idea to report the lParam value to us but/and this shows its limit.

This is what it offers us:
  • bit         Explanation
  • 0-15      The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
  • 16-23    The scan code. The value depends on the OEM.
  • 24          Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
  • 25-28    Reserved; do not use.
  • 29         The context code. The value is 1 if the ALT key is held down while the key is pressed; otherwise, the value is 0.
  • 30         The previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
  • 31         The transition state. The value is 1 if the key is being released, or it is 0 if the key is being pressed.


0-15 is already there via $keyrpt
16-23 without accessing the window api, i'm not sure what we can do with it, same as what i described at the beginning of this post.
24 can help use telling between right alt and right control but not right shift.
29 is not applicable because if alt (left) is held down, nothing trigger
30 could be used but in most practical purpose knowing this information is not that useful i'd say
31 not sure if applicable.

So I don't think knowing lParam is that great for scripter, especially if it does not provide a way to tell for the shift key.

However, VK_RSHIFT/VK_LSHIFT are proper values we can check against the table here, same for control and alt.
The function I posted in my previous post should be used to report the correct keypress from the start imo. Yes it would change the value of $keyval, breaking compatibility, but it must be said that the 'recent' fix for on keydown with the addition of on char to correctly reports keypress and resulting characters means that on keydown's $keyval (and $keychar) were never working correctly to begin with, and there have been a couple of report regarding $keyval and $keychar not reporting the correct value anyway, so the idea there is a 'compatibility' for $keyval is a bit compromised.

If backward compatibility were to be preserved, well there is still the shift issue. $keylparam support can be kept, but i'd remove it if it were meant to solve the right shift/alt/control key as it does not fully solve that. And i'd just follow what i said in my previous post.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel

Link Copied to Clipboard