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.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 29 October 2020 16:12 PM UTC
  2. PowerBuilder
  3. # 1

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.
René Ullrich Accepted Answer Pending Moderation
  1. Tuesday, 27 October 2020 12:06 PM UTC
  2. PowerBuilder
  3. # 2

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.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.
We use cookies which are necessary for the proper functioning of our websites. We also use cookies to analyze our traffic, improve your experience and provide social media features. If you continue to use this site, you consent to our use of cookies.