2

I'm trying to accurately type a hash sign (number sign, pound sign, octothorpe, whatever you call it) using SendInput in user32.dll.

These are the possible options I see:

  1. Type the number-sign by simulating SHIFT+3 (SHFT_DN, 3_DN, 3_UP, SHFT_UP). My only concern would be US-layout keyboards. Is there a possibility of a system that is configured with non-US layouts to output an incorrect key?

  2. My other option would be to insert the character by the ascii code by simulating key press: ALT+035 (ALT_DN, NUMPAD0_DN, NUMPAD0_UP, NUMPAD3_DN, NUMPAD3_UP, NUMPAD5_DN, NUMPAD5_UP, ALT_UP). Are there any major downfalls to this method? Do all regions share the same ASCII codes and does Windows provide this ALT+### functionality in all regions? This is also going to generate a lot of keystrokes for a single simple character. I don't know if that's a potential problem.

  3. Ideally there would be a Virtual Key Code that was a hash symbol, but I don't see one. Am I missing it?

Any other possibilities that I'm not thinking of? I really need to continue using SendInput for a few reasons.

So my question is, how do I use SendInput to simulate a number/hash sign being typed, and make that be global and not-dependent on non-US keyboards with the least number of keystrokes possible?

Thank you

Adam Plocher
  • 13,994
  • 6
  • 46
  • 79
  • Even "qwerty" doesn't mean "US layout" - my UK layout qwerty keyboard has a pound (£) sign for Shift-3. – Jon Skeet May 06 '14 at 02:55
  • Do you need to use `SendInput` rather than `SendKeys`, btw? – Jon Skeet May 06 '14 at 02:55
  • @JonSkeet thank you. I updated my question to be more specific about US (not QWERTY) layouts. Regarding `SendKeys`, I wrote this library many years ago and based on my recollection, I started out using MS UIAuto, then `SendKeys`, then `SendInput`. The prob is I need to send keystrokes/populate input fields to many systems, some being Citrix and TermServices clients. I don't remember the exact problem I had back then, but I ended up using SendInput (I think for Citrix). I feel like I need a hybrid that supports all 3 options, based on customer requirements, maybe that's the answer... – Adam Plocher May 06 '14 at 04:50
  • @AdamPlocher i hope this can help : your 3rd question can solve your all problems, i think.. For CSharp, In your keyboard event (keypress or some else) you will see the parameter EventArgs e or KeyPressEventArgs e etc.. in your event codes handle this like var myNeedChar = e.KeyChar('#').. then you'll get the actual keyboard's ASCII / UTF-8 / UTF-16 -whatever OS uses which encoding- code equivelant..And do with keychar what you need in your project – sihirbazzz May 06 '14 at 07:45
  • @JonSkeet As an extra knowledge : even keyboard brands can change in their model types itself also..I had an old Logitech-TR (Turkish) keyboard..There Ctrl+3 was a Euro Sign (€), Shift+3 was Xor sign (^) and same brand with a newer one now Shift+3 still Xor but Ctrl+3 is now Sharp (#) – sihirbazzz May 06 '14 at 07:54

1 Answers1

2

You should be able to do this using SendInput with the KEYEVENTF_UNICODE flag. This bypasses the problems discussed in the comments about different keyboards using different scan codes to represent the number sign. It has a universally recognized Unicode representation.

The KEYEVENTF_UNICODE flag should be specified in the dwFlags member of the KEYBDINPUT structure that you pass to the SendInput function. When you use this flag, you set the wVk member to 0 and use the wScan member instead. The documentation for that structure contains more detailed information.

But it should be pretty simple. Any properly-designed app is going to obtain the message (using either GetMessage or PeekMessage), and then call TranslateMessage, which will cause a WM_CHAR message to be posted with the appropriate Unicode character value. It even handles the case where you're dealing with a legacy, non-Unicode application: if the message is posted to an ANSI window, the Unicode value will be automatically converted to the appropriate ANSI value. This shouldn't be a problem, all character sets I can think of include a number sign.

Alternatively, you could probably do the translation yourself using the VkKeyScanEx function to obtain the virtual-key code of the character, and then mapping this virtual-key code to a scan code using MapVirtualKeyEx. I can't say for sure if this will work, though, as I've never tried this approach.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Cody, thank you - I saw your response earlier today but have been pretty busy putting out other fires. I'm beginning to look into the `KEYEVENTF_UNICODE` flag right now and will let you know how it goes. This sounds very promising! – Adam Plocher May 06 '14 at 23:32
  • Worked, thank you! I'm a little confused, though. If I'm understanding this correctly, the `KEYEVENTF_UNICODE` flag causes `SendInput` to inject `WM_KEYUP`/`WM_KEYDOWN` messages to the target handle. Is that behavior different from when I use `wVk` and not use `KEYEVENTF_UNICODE`? I ended up using `SendInput` long ago due to some odd use-cases, such as simulating keystrokes through a Citrix/TermServ client. I'm just worried that this will be handled differently by these non-standardish forms. Still, answered. Thank you. This customer doesn't need the termsrv client functionality. – Adam Plocher May 07 '14 at 23:10
  • 1
    @Adam The purpose of the `KEYEVENTF_UNICODE` flag is to allow you to inject Unicode characters, as opposed to virtual key codes. This is particularly important for cases where you might want to synthesize handwriting or voice recognition as if it were text input. Technically, the `KEYEVENTF_UNICODE` flag works very much like when you do not use the flag and specify a virtual key code. `KEYEVENTF_UNICODE` actually sends keyboard messages that specify the virtual key code `VK_PACKET`. Those are then converted by `TranslateMessage` into `WM_CHAR` messages for the appropriate Unicode char. – Cody Gray - on strike May 08 '14 at 06:09
  • 1
    All of that to say, it should be exactly the same. Assuming that the application is correctly written and calls `TranslateMessage` instead of trying to do its own processing. Though admittedly, I know absolutely nothing about Citrix/etc. – Cody Gray - on strike May 08 '14 at 06:10