1. Vincent Van Gogh
  2. PowerBuilder
  3. Tuesday, 27 October 2020 10:36 AM UTC

Hi,

I have a lot of singlineedit and dw controls on a window, I need to catch up with KeyTab! When the user presses the TAB key.


I try to use key events on the window to capture, but I can only capture all keys except the tab key. All keys in datawinow cannot be captured either.

what should I do?

 

Thanks

Accepted Answer
Andrew Barnes Accepted Answer Pending Moderation
  1. Thursday, 29 October 2020 15:59 PM UTC
  2. PowerBuilder
  3. # Permalink

Normal PowerBuilder keyboard processing will trap a number of key combinations such that they cannot be accessed using normal PowerBuilder methods such as using Key events or trying to tap into the underlying WM_KEYDOWN message using the Other event.

Fortunately, Windows API provides raw keyboard input processing.  It is not excessively difficult to do.  The main idea is that a Window wishing to get raw keyboard input, registers with Windows that it wants raw input.  Then Windows sends WM_INPUT messages when a key is pressed.  I had an app where I needed to trap for the Tab and Alt keys as well as determine if the key pressed was extended from within a Multiline edit. 

Here is the code I used:

You need some structures

type str_rawinputdevice from structure
 unsignedinteger  ususagepage
 unsignedinteger  ususage
 unsignedlong  dwflags
 unsignedlong  hwndtarget
end type

type str_rawinputheader from structure
 unsignedlong  dwtype
 unsignedlong  dwsize
 unsignedlong  hdevice
 unsignedlong  wparam
end type

type str_rawkeyboard from structure
 unsignedinteger  makecode
 unsignedinteger  flags
 unsignedinteger  reserved
 unsignedinteger  vkey
 unsignedlong  message
 unsignedlong  extrainformation
end type

type str_rawinput from structure
 str_rawinputheader  header
 str_rawkeyboard  keyboard
end type

and some external function declarations:

// Registers the devices that supply the raw input data so that the application may receive WM_INPUT messages.
FUNCTION Boolean WinAPI_RegisterRawInputDevices(     &
    READONLY str_rawinputdevice pRawInputDevices[],  &
    uLong uiNumDevices,            &
    ulong cbSize             &
    )                 &
    LIBRARY "USER32.DLL" ALIAS FOR "RegisterRawInputDevices"

// Retrieves the raw input from the specified device.
FUNCTION uLong WinAPI_GetRawInputData(         &
    uLong hRawInput,             &
    uLong uiCommand,            &
    REF str_rawinput rawinput,         &
    REF uLong pcbSize,           &
    uLong cbSizeHeader           &
    )                 &
    LIBRARY "USER32.DLL" ALIAS FOR "GetRawInputData"


// Calls the default raw input procedure to provide default processing for any raw input messages that an
// application does not process. This function ensures that every message is processed. DefRawInputProc is
// called with the same parameters received by the window procedure.
FUNCTION uLong WinAPI_DefRawInputProc(         &
    READONLY str_rawinput rawinput,       &
    Long nInput,             &  
    uLong cbSizeHeader           &
    )                 &
    LIBRARY "USER32.DLL" ALIAS FOR "DefRawInputProc"

 

In the Open event of your window, you need to register to receive raw keyboard input:

str_rawinputdevice pRawInputDevices[]

pRawInputDevices[1].usUsagePage = 1     // 1 for Keyboard input
pRawInputDevices[1].usUsage = 6      // 6 for Keyboard input
pRawInputDevices[1].dwflags = 0      // 0 for default flags
pRawInputDevices[1].hwndTarget = Handle(THIS) // handle of window to receive WM_INPUT messages

// register this window to recieve WM_INPUT messages with raw keyboard input,
WinAPI_RegisterRawInputDevices(pRawInputDevices[], UpperBound(pRawInputDevices[]), 2+2+4+4) // size is two 2-byte uInts and two 4-byte uLongs

You catch the input in your window's other event:  Note the ib_raw_keyboard_input_active flag.  I found that my window received WM_INPUT messages even when it did not have focus.  To get around that, I made a Boolean flag that I set in the Window's Activate event and cleared in the Window's Deactivate event

CHOOSE CASE Message.Number

 CASE 255  // WM_INPUT
  IF ib_raw_keyboard_input_active = TRUE THEN
   // Process the raw keyboard input.
   RETURN EVENT ue_Input(Message.LongParm)
  END IF
END CHOOSE

Lastly here is my event in which I process the WM_INPUT messages.  This could be simply coded in the Other event, programmer's choice.

event type long ue_input(unsignedlong ah_rawinput);// Process the raw keyboard input.  This allows us to bypass the limitations of normal PowerBuilder
// keyboard processing via the built-in Key event such as Tab keystrokes and Alt-key combinations being
// intercepted and thus not available as well as not being able to distinguish between keypad keys and
// non-keypad keys.  For example, if numberlock is not down, KeyHome! is sent to the Key event regardless
// of which Home key was pressed.
//
// INPUTS: ah_RawInput - A handle to the RAWINPUT structure. This comes from the lParam in WM_INPUT

str_RawInput lRawInput
uInt li_key_flags
uLong lul_command
uLong lul_header_size
uLong lul_data_size
Long ll_result
Boolean lb_E0, lb_control, lb_alt, lb_shift
KeyCode l_keycode
Long ll_command_code = 0

// Bit masks for the raw input keyboard flags
CONSTANT uInt RI_KEY_MAKE = 0  // The key is down.
CONSTANT uInt RI_KEY_BREAK = 1  // The key is up.
CONSTANT uInt RI_KEY_E0 = 2   // The scan code has the E0 prefix.
CONSTANT uInt RI_KEY_E1 = 4  // The scan code has the E1 prefix.

lul_command = 268435459  /* RID_INPUT = 0x10000003 = 268435459 */
lul_header_size = 4 * 4  // str_RawInputHeader has four 4-byte uLongs
lul_data_size = lul_header_size + 4 * 2 + 2 * 4  // str_RawKeyboard has four 2-byte uInts and two 4-byte uLongs

ll_result = WinAPI_GetRawInputData(ah_RawInput, lul_command, REF lRawInput, REF lul_data_size, lul_header_size)

// check the least signifcant bit in the flags and process only when the key is not up i.e. handle KeyDown and not KeyUp
li_key_flags = lRawInput.KeyBoard.Flags
IF Mod(li_key_flags, 2) <> RI_KEY_BREAK THEN
 // shift the flag bits 1 bit to the right and check the new least signifcant bit to see if the key has the E0 prefix.
 // The Keypad Enter has E0 set, for the other keypad navigation keys, the E0 is clear
 li_key_flags /= 2
 IF Mod(li_key_flags, 2) = 1 THEN
  lb_E0 = TRUE
 ELSE
  lb_E0 = FALSE
 END IF
 
 lb_control = KeyDown(KeyControl!)
 lb_alt = KeyDown(KeyAlt!)
 lb_shift = KeyDown(KeyShift!)

IF lRawInput.KeyBoard.vKey =  9 THEN
 // do something with the Tab key press
ELSE
 WinAPI_DefRawInputProc(lRawInput, 1, lul_header_size)
END IF

RETURN 0

end event

Comment
There are no comments made yet.
René Ullrich Accepted Answer Pending Moderation
  1. Tuesday, 27 October 2020 12:06 PM UTC
  2. PowerBuilder
  3. # 1

Hi,

you could use a multilineedit control. There you can enter a Tab key with CTRL+TAB.

In singlelineedits or datawindows I don't know a way. I only know a workaround: Add o button or menu item to insert a Tab using the ReplaceText function.

HTH,

René

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 29 October 2020 16:12 PM UTC
  2. PowerBuilder
  3. # 2

Hi Vincent;

   Have you tried mapping this DW Control User Event ...

HTH

Regards ... Chris

Comment
  1. Andrew Barnes
  2. Friday, 30 October 2020 23:29 PM UTC
Good catch Chris. My overly complicated solution for this specific problem was based on my experience attempting and failing to catch the tab key when pressed from within a MultiLineEdit using the using the pbm_keydown event..
  1. Helpful
  1. Chris Pollach @Appeon
  2. Tuesday, 3 November 2020 18:33 PM UTC
Thanks Andrew ... Yes, I like the KISS approach wherever possible! ;-)

You also have to remember that the DWO "steals" the messages off the O/S message queue and processes them within its own queue. That is why PowerSoft added the "pbm_DWxxxxxxx" user events to allow the PB App developer to the DWO's own MQ. HTH
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.