Microsoft KB Archive/67293

{|
 * width="100%"|

INFO: Some CTRL Accelerator Keys Conflict with Edit Controls

 * }

Q67293

-

The information in this article applies to:


 * Microsoft Windows Software Development Kit (SDK)
 * Microsoft Win32 Software Development Kit (SDK)

-

SUMMARY
Some keys produce the same ASCII values as CTRL+key combinations. These keys conflict with edit controls if one of the CTRL+key combinations is used as a keyboard accelerator.

The following table lists some of the conflicting keys.

  ASCII Value  Key Combination  Equivalent  Windows Virtual Key --- ---  --  ---   0x08         CTRL+H           BACKSPACE   VK_BACK 0x09        CTRL+I           TAB         VK_TAB 0x0D        CTRL+M           RETURN      VK_RETURN For example, consider the following scenario:


 * 1) CTRL+H has been assigned as an accelerator keystroke to invoke Help
 * 2) An edit control has the focus
 * 3) BACKSPACE is pressed to erase the previous character in the edit control

This results in Help being invoked because pressing BACKSPACE is equivalent to pressing CTRL+H. The edit control does not receive the BACKSPACE key press that it requires because TranslateAccelerator encounters the 0x08 ASCII value and invokes the action assigned to that accelerator. This limitation is caused by the use of the ASCII key code for accelerators instead of the system-dependent virtual key code.

MORE INFORMATION
When messages for the edit control are processed in a message loop that translates accelerators, this translation conflict will occur. Child windows and modeless dialog boxes are the most common situations where this happens.

The affected keystrokes are translated during the processing of the WM_KEYDOWN message for the letter. For example, when the user types CTRL+H, a WM_KEYDOWN is processed for the CTRL key, then another WM_KEYDOWN is processed for the letter &quot;H&quot;. In response to this message, TranslateAccelerator posts a WM_COMMAND message to the owner of the CTRL+H accelerator. Similarly, when the user presses the BACKSPACE key, a WM_KEYDOWN is generated with VK_BACK as the key code. Because the ASCII value of BACKSPACE is the same as that for CTRL+H, TranslateAccelerator treats them as the same character. Either sequence will cause a WM_COMMAND message to be sent to the owner of the CTRL+H accelerator, which deprives the child window with the input focus of the BACKSPACE key message.

Because this conflict is inherent to ASCII, the safest way to avoid the difficulty is to avoid using the conflicting sequences as accelerators. Any other ways around the problem may be version dependent rather than a permanent fix.

A second way around the situation is to subclass each edit control that is affected. In the subclass procedure, watch for the desired key sequence(s). The following code sample demonstrates this procedure:

  /* This code subclasses a child window edit control to allow it to    * process the RETURN and BACKSPACE keys without interfering with the * parent window's reception of WM_COMMAND messages for its CTRL+H * and CTRL+M accelerator keys. */

/* forward declaration */ long FAR PASCAL NewEditProc(HWND, unsigned, WORD, LONG);

/* required global variables */ FARPROC lpfnOldEditProc; HWND   hWndOwner;

/* edit control creation in MainWndProc */

TEXTMETRIC tm; HDC hDC; HWND hWndEdit; FARPROC lpProcEdit;

...

case WM_CREATE:

hDC = GetDC(hWnd); GetTextMetrics(hDC, &tm); ReleaseDC(hWnd, hDC);

hWndEdit = CreateWindow(&quot;Edit&quot;, NULL,          WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER,           50, 50, 50 * tm.tmAveCharWidth, 1.5 * tm.tmHeight,           hWnd, 1, hInst, NULL);

lpfnOldEditProc = (FARPROC) GetWindowLong (hWndEdit, GWL_WNDPROC); lpProcEdit = MakeProcInstance ((FARPROC) NewEditProc, hInst); SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG) lpProcEdit); break;

...  /* subclass procedure */

long FAR PASCAL NewEditProc(HWND hWndEditCtrl, unsigned iMessage,                              WORD wParam, LONG lParam ) {    MSG  msg;

switch (iMessage) {    case WM_KEYDOWN: switch (wParam) {      case VK_BACK: // This assumes that the next message in the queue will be a          // WM_COMMAND for the window which owns the accelerators. If          // this edit control were in a modeless dialog box, hWndOwner // should be set to NULL. It may also be NULL in this case. PeekMessage(&amp;msg, hWndOwner, 0, 0, PM_REMOVE);

// Since TranslateAccelerator processed this message as an          // accelerator, a WM_CHAR message must be supplied manually to           // the edit control. SendMessage(hWndEditCtrl, WM_CHAR, wParam, MAKELONG(1, 14)); return 0L;

case VK_RETURN: // Same procedures here. PeekMessage(&msg, hWndOwner, 0, 0, PM_REMOVE); SendMessage(hWndEditCtrl, WM_CHAR, wParam, MAKELONG(1, 28)); return 0L; }          break; }      return CallWindowProc(lpfnOldEditProc, hWndEditCtrl, iMessage,                             wParam, lParam); } NOTE: Be sure to export the subclass function in the DEF file.

Additional query words:

Keywords : _IK kbCtrl kbEditCtrl kbOSWinNT kbOSWin2000 kbSDKWin32 kbGrpDSUser kbOSWin kbWndw kbWndwMsg

Issue type : kbinfo

Technology : kbWin32SDKSearch kbAudDeveloper kbSDKSearch kbWin32sSearch kbWinSDKSearch