delphidelphi-4

(NOT) Validate 'any key' + DELETE pressed on Delphi 4


I can't figure out how to capture the 'any key'(except for CTRL) + 'Deletekey' press. I found out how to validate if CTRL + 'Deletekey'.

The reason is because I need to make 2 actions:

  1. if 'CTRL' + 'Deletekey' is pressed. (Already achieved this one)
  2. ONLY if 'Deletekey' is pressed. (Got problems with it, because I can combine 'any key'(except for CTRL) + Deletekey and it keeps making action 2), but I need to make this action IF AND ONLY IF 'Deletekey' is pressed.

Thanks

EDIT: Thank for your replies, I will show how I accomplished the point 1:

Context first: I have an event called DPaint1KeyUp, what it should do? remove graphically a painted element (if DELETE is pressed) or remove graphically and from the database if CTRL + DELETE pressed Simultaneously.

procedure TfMyClass.DPaint1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  inherited;
  if (Shift = [ssctrl]) and (key = VK_DELETE) then
    //Going to delete graphically and from database

  if (Shift = []) and (key = VK_DELETE) then
    //Going to delete just Graphically
end;

If I press simultaneosly CTRL + DELETE it works perfectly (Delete graphically and from Database.

BUT, if I press simultaneosly whichever combination with DELETE (except for CTRL), it deletes Graphically, WRONG, because if I only need to delete graphically I just need to press DELETE, not any other combination

For example:

@fpiette "A key and DeleteKey simultaneously pressed"


Solution

  • If you want to make sure that combination of pressed keys does not contain an undesired key you first need to get state of every key using GetKeyboardState function.

    The above mentioned function returns an array with 256 items representing state of any possible key in Windows.

    You can then iterate through the mentioned array checking if certain unwanted key is being pressed down using

    if (KeyState[I] and $80) <> 0 then
    

    Since each key state is stored at position in the above mentioned array that corresponds with Virtual Key value for that specific key you can use Virtual key designations to red the desired key from the above mentioned array.

    And since key states are stored in high-order bit we use and logical operator with $80as its second parameter in order to read only the high-order bit value.

    If the key is being pressed down such value will be 1 otherwise it will be 0.

    So your code would look something like this:

    type
      //Define set for all possible keys
      TAllKeys = set of 0..255;
    
    ...
    
    implementation
    
    ...
    
    procedure TfMyClass.DPaint1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    var KeyState: TKeyboardState;
        I: Integer;
        DesiredKeys: TAllKeys;
        UndesiredKeys: TAllKeys;
    begin
      //Use desired keys to set all the keys you want to respoond to
      DesiredKeys := [VK_DELETE, VK_CONTROL, VK_LCONTROL, VK_RCONTROL, VK_MENU, VK_LMENU, VK_RMENU, VK_SHIFT, VK_LSHIFT, VK_RSHIFT];
      //Set undesired keys set as all posible keys substracted by desired keys
      UndesiredKeys := [0..255] - DesiredKeys;
    
      //Retzrieve keyboard state so we can check if one of undesired keys is being pressed down
      GetKeyboardState(KeyState);
      //Loop through all keys
      //NOTE: In modern delphi versions it is possible to loop through elements of individual set using for..in loop
      //      This would allow looping only through undesired keys and not checking every key tro se if it is amongst undesired keys
      for I := 0 to 255 do
      begin
        //If certain key is in undesired keys set check its status
        if I in UndesiredKeys then
        begin
          //If undesired key is pressed down exit the procedure
          if (KeyState[I] and $80) <> 0 then
          begin
            //ShowMessage('Non-desired key pressed');
            Exit;
          end;
        end;
      end;
    
      //If no undesired key is pressed continue with your old code
      if (Shift = [ssctrl]) and (key = VK_DELETE) then ShowMessage('Ctrl + Delete');
        //Going to delete graphically and from database
    
      if (Shift = []) and (key = VK_DELETE) then ShowMessage('Delete only');
        //Going to delete just Graphically
    end;
    

    While this is probably not most efficient code it will get the job done. Just don't forget to add all desired keys that you do want to react to into DesiredKeys set so them being pressed down wont exit the OnKeyUp procedure.