Solved

Keboard input

Posted on 1997-12-19
19
198 Views
Last Modified: 2011-09-20
How can I tell the difference between when the user presses the left shift key as opposed to the right shift key.
0
Comment
Question by:vaguemax
  • 10
  • 8
19 Comments
 
LVL 7

Expert Comment

by:ahalya
ID: 1354226
Use GetkeyboardState WinAPI.

here is part of the help file:

This gives the status of the SHIFT, CTRL, or ALT keys without distinguishing between left and right. An application can also use the following virtual-key code constants as indices to distinguish between the left and right instances of those keys:

VK_LSHIFT      VK_RSHIFT
VK_LCONTROL      VK_RCONTROL
VK_LMENU      VK_RMENU

0
 

Author Comment

by:vaguemax
ID: 1354227
Key codes don't go with getkeyboardstate, they go with getKeyState(Version 1 does not have VK_LSHIFT)  
getkeyboardstate does return an array of values but I can't tell which ones go with the shift & control keys
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354228
This sample is from the Borland Technical help file:


Title      : Handling Special Keys and Direct Memory AccessProduct      
{
Toggle Controls: -- allow you to check to see if a certain key
was pressed or to turn off or on a certain key, such as
activating the Num-Lock key.

MemW[0000:$0417]
number   bit
    1     0  - Right Shift
    2     1  - Left Shift
    4     2  - Ctrl
    8     3  - Alt
   16     4  - Scroll Lock
   32     5  - Num Lock
   64     6  - Caps Lock
  128     7  - Insert
  256     8  -
  512     9  -
 1024    10  - Sys Req
 2048    11  -
 4096    12  - Scroll Lock Pressed

 8192    13  - Num Lock Pressed
16384    14  - Caps Lock Pressed
32768    15  - Insert Pressed

Other memory locations that can be accessed to get/put
information.

Clock ticks: MemW[$0040:$006C] updates every 58ms.
Clear Key Buffer: MemW[0000:$041A] := MemW[0000:$041C].

Color Address: $B800:0000; Mono Address: $B000:0000.

Print Screen: inline ($CD/$05).
}

{ example }
program TrapAlt;
 Uses
   Dos, Crt;
 Var
   i:char;
 Function alt:boolean;
 Begin

   if MemW[0000:$0417] and 8<>0 then
     begin
      alt:=true;
      repeat
       if keypressed then
         begin
           alt:=false;
           exit;
         end;
      until MemW[0000:$0417] and 8=0;
     end
     else
      alt:=false;
  End;

Begin
 clrscr;
  repeat
   if keypressed then
     begin
       writeln('non alt');
       i:=readkey;
     end;
   if alt then writeln('Alt key pressed');
  until (i=#13);
End.
0
 

Author Comment

by:vaguemax
ID: 1354229
I don't want to use DOS mode functions.  They are rarely reliable.
0
 

Author Comment

by:vaguemax
ID: 1354230
I also want to detect left and right CTRL keys
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354231
procedure TForm1.Button1Click(Sender: TObject);
var FKey: TkeyboardState;
begin
GetkeyboardState(FKey);
if (FKey[VK_LSHIFT]=128) or (FKey[VK_LSHIFT]=129) then
  showmessage('Left Shift is pressed now');

if (FKey[VK_RSHIFT]=128) or (FKey[VK_RSHIFT]=129) then
  showmessage('Right Shift is pressed now');

if (FKey[VK_LCONTROL]=128) or (FKey[VK_LCONTROL]=129) then
  showmessage('Left Control is pressed now');

if (FKey[VK_RCONTROL]=128) or (FKey[VK_RCONTROL]=129) then
  showmessage('Right Control is pressed now');

end;

0
 

Author Comment

by:vaguemax
ID: 1354232
VK_LSHIFT, VK_RSHIFT, VK_LCONTROL and VK_RCONTROL are not available for Delphi 1.0.  This may work if I could get the Hex codes for these constants.
0
 

Author Comment

by:vaguemax
ID: 1354233
I have tried a routine that on keypress did getkeyboardstate, then looped through all of the positions.  The only one with a high order bit was 16.  This occurs with both left and right shift keys.
0
 
LVL 5

Accepted Solution

by:
ronit051397 earned 200 total points
ID: 1354234
1. Copy the attached code, Activate the from, Press CONTROL or
   SHIFT and see what happens.
2. This code was tested with Delphi3 but should work also with
   Delphi1.
3. Both CONTROL and SHIFT have worked in my test. As for your
   case, I am almost sure that the CONTROL test will work. As for
   the SHIFT test, I am not sure.

unit Unit1;

interface

uses
  WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
  private
    procedure WMKey(var Message: TWMKey); message WM_KEYDOWN;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.WMKey(var Message: TWMKey);
 function Power(FBasis, FDegree: Word): LongInt;
  begin
    Result:=Round(Exp(FDegree*Ln(FBasis)));
  end;
 begin
   if Message.CharCode=VK_CONTROL then
   begin
    if (Message.keydata) and (Power(2,24))<>0 then
      showmessage('Right Control is pressed')
    else
      showmessage('Left Control is pressed')
   end;

   if Message.CharCode=VK_SHIFT then
   begin
    if (Message.keydata) and (Power(2,18))<>0 then
      showmessage('Right Shift is pressed')
    else
      showmessage('Left Shift is pressed')
   end;
 end;
end.

0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:vaguemax
ID: 1354235
It works, but I don't know what its doing.  I am having trouble integrating this into my existing program.  Probably because I'm using the KeyDown and KeyPress events.
0
 

Author Comment

by:vaguemax
ID: 1354236
This will not work with any other input control.

0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354237
I don't understand the comment.
0
 

Author Comment

by:vaguemax
ID: 1354238
If you add a combobox or textbox onto the form this code does not execute, even with keypreview on.
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354239
The reason for this behavior is that when the focus is on a control that can be focused such as TEdit (not such as TLabel), then this control is receiving the keyboard messages and not the form. Notice that this code refers to the form's messages
only.(TForm.somthing...)
However, If you need to refer to these messages in the application level, that is to have the ability to handle any massages that are sent to your application, then write the
following code instead.
This code is using TApplication.something and is solving the 'focused controls' problem.

unit Unit1;

interface

uses
  WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
function Power(FBasis, FDegree: Word): LongInt;
begin
  Result:=Round(Exp(FDegree*Ln(FBasis)));
end;
begin
  with Msg do
  if Message=WM_KEYDOWN then
  begin
    if wParam=VK_CONTROL then
    begin
      if (lParam) and (Power(2,24))<>0 then
        showmessage('Right Control is pressed')
      else
        showmessage('Left Control is pressed')
    end;

    if wParam=VK_SHIFT then
    begin
      if (lParam) and (Power(2,18))<>0 then
        showmessage('Right Shift is pressed')
      else
        showmessage('Left Shift is pressed')
    end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMessage;
end;

end.

0
 

Author Comment

by:vaguemax
ID: 1354240
I have tried using this code as well as several permutations and I can not get it to work at all.  The form does absoulutely nothing.  Probably a programmer density problem, but I cant help it.
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354241
This code is working. I tested it after I put several controls on the form. Test on a new form without extra code.
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354242
Now, This is very bizzar:
When you copy and paste the code as it is, the OnMessage event doesn't work at all, not just for this case, but for any other messages.
In order to get this to work, write (not copy and paste!!!) every thing that is needed from the above code, except the code inside the onMessage event, This code you can copy and paste.
This should work cause I tested it. Let me know weather it's working or not.
Probabely, sometimes when you copy and paste, some code is getting 'dirty'. Years ago, I have had the same problem with
Microsoft Access. I couldn't copy and paste and I had to rewrite the code.
0
 

Author Comment

by:vaguemax
ID: 1354243
I typed the code instead of copying and it works great now.  Thanks for the help.
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1354244
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now