Description of the mnemonic differences between MFC 4.0 and Visual Basic 4.0 (145698)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++, 32-bit Editions 4.0
- Microsoft Visual C++, 32-bit Enterprise Edition 5.0
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 5.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
- Microsoft OLE Control Developer's Kit (CDK)
- Microsoft Visual C++ 2005 Express Edition
- Microsoft Visual C++ .NET (2003)
- Microsoft Visual C++ .NET (2002)
This article was previously published under Q145698 Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. Microsoft Visual C++ 2005 supports
both the managed code model that is provided by the Microsoft .NET Framework and the
unmanaged native Microsoft Windows code model. SYMPTOMS An accelerator table provided by way of
COleControl::OnGetControlInfo that describes an OLE control's mnemonic keys
does not work in both MFC 4.0 and Visual Basic 4.0 OLE control containers.
CAUSE Visual Basic 4.0 and MFC 4.0 provide different mnemonic
handling implementations, so they require different accelerator table entries.
RESOLUTION Create accelerator table entries that will allow a
control's mnemonics to be handled in both a Visual Basic 4.0 and MFC 4.0 OLE
control container. STATUS This behavior is by design. MORE INFORMATION An OLE control overrides the virtual
COleControl::OnGetControlInfo method to allow its container to get a
description of the control's mnemonic keys. The OnGetControlInfo method returns
a filled-out structure of type CONTROLINFO that contains, among other things, a
handle to an accelerator table. This accelerator table is used by the container
to do checks for mnemonic keys. When the container determines that a control's
mnemonic key was pressed, it calls the control's IOleControl::OnMnemonic
method. This causes the MFC framework to call the virtual
COleControl::OnMnemonic method, which the control can override to do special
processing. The Visual Basic 4.0 and MFC 4.0 OLE control mnemonic
handling implementations have different requirements for the entries in the
accelerator table returned by way of OnGetControlInfo. An accelerator
key used in an accelerator table is defined by the ACCEL structure. The ACCEL
structure has the following definition:
typedef struct tagACCEL
{
BYTE fVirt;
WORD key;
WORD cmd;
} ACCEL;
The fVirt member specifies the accelerator flags. This member can be a
combination of the following values:
Value Meaning
---------------------------------------------------------------------
FALT The ALT key must be held down when the accelerator key is
pressed.
FCONTROL The CTRL key must be held down when the accelerator key
is pressed.
FNOINVERT Specifies that no top-level menu item is highlighted when
the accelerator is used. If this flag is not specified, a
top-level menu item will be highlighted, if possible,
when the accelerator is used.
FSHIFT The SHIFT key must be held down when the accelerator key
is pressed.
FVIRTKEY The key member specifies a virtual-key code. If this flag
is not specified, key is assumed to specify an ASCII
character code.
The key member specifies the accelerator key. This member can be
either a virtual-key code or an ASCII character code. The cmd member
specifies the accelerator identifier. This value is placed in the low-order
word of the wParam parameter of the WM_COMMAND or WM_SYSCOMMAND message when
the accelerator is pressed. Visual Basic 4.0 has the following
requirements for accelerator table entries used for mnemonic
handling: - The fVirt member must be a combination of (FVIRTKEY | FALT)
or (FVIRTKEY | FALT | FSHIFT).
- The key member must be uppercase.
- The cmd member must not be equal to 0.
MFC 4.0 has the following requirements for accelerator table
entries used for mnemonic handling: - The fVirt member must be FALT or 0.
- The key member must be lowercase.
- The cmd member is ignored.
MFC 4.0 OLE control containers also differ from Visual Basic
4.0 in the way they handle mnemonic processing when a control is UI active.
When handling keyboard input MFC containers, first check to see if an OLE
control has the focus. If it does, the framework calls its
IOleInPlaceActiveObject::TranslateAccelerator method. In the COleControl
implementation of this method the control's PreTranslateMessage function is
called. In order for an OLE control to have its mnemonics function correctly
when the control is UI active, the OLE control must override
PreTranslateMessage and check for its special key combinations. NOTE: Overriding PreTranslateMessage is not necessary if the control
is generated with Visual C++ 5.0 or above because OnMnemonic will be called
when the control is UI active by way of SendMnemonic in
COccManager::IsDialogMessage. The following sample code shows an
overridden OnGetControlInfo, PreTranslateMessage, and OnMnemonic that allow a
control's mnemonics to work correctly in both an MFC 4.0 OLE control container
as well as a Visual Basic 4.0 container. Sample Code
/* Compile options needed: None
*/
#define NUM_ENTRIES 4
void CMnemonicCtrl::OnGetControlInfo(LPCONTROLINFO lpi)
{
HACCEL hAccel = NULL;
TCHAR ch = 'm'; // Hard code the mnemonic key to 'm' for this
// example.
ACCEL accKey[NUM_ENTRIES];
// Accel table entries 0 and 1 are to work with Visual Basic 4.0 as a
// container. Visual Basic 4.0 has the following requirements for
// accel table entries for a control's mnemonics:
//
// (fVirt == FVIRTKEY | FALT) || (fVirt == FVIRTKEY | FALT | FSHIFT)
// key must be uppercase
// (cmd != 0)
accKey[0].fVirt = FVIRTKEY | FALT;
accKey[1].fVirt = FVIRTKEY | FALT | FSHIFT;
accKey[0].key = accKey[1].key = LOBYTE(VkKeyScan(ch));
accKey[0].cmd = accKey[1].cmd = 1;
// Accel table entries 2 and 3 are to work with MFC 4.0 containers.
// MFC containers have the following requirements for accel table
// entries for a control's mnemonics:
//
// (fVirt == FALT) || (fVirt == 0)
// key should be lowercase
// cmd is ignored
accKey[2].fVirt = FALT;
accKey[3].fVirt = 0;
accKey[2].key = accKey[3].key = ch;
accKey[2].cmd = accKey[3].cmd = 1;
// Create the accel table.
hAccel = CreateAcceleratorTable(accKey, NUM_ENTRIES);
if (hAccel != NULL)
{
// Fill in the CONTROLINFO structure passed in.
lpi -> hAccel = hAccel;
lpi -> cAccel = NUM_ENTRIES;
lpi -> dwFlags = 0;
}
else
COleControl::OnGetControlInfo(lpi);
}
// NO need to override PreTranslateMessage if the control is generated in
// Visual C++ 5.0 or above.
BOOL CMnemonicCtrl::PreTranslateMessage( MSG * pMsg )
{
// Check for ALT-M key combination.
if(pMsg->message == WM_SYSKEYDOWN) {
if((pMsg->wParam == 'm')||(pMsg->wParam == 'M'))
{
// Do mnemonic key processing here.
return TRUE;
}
}
return COleControl::PreTranslateMessage(pMsg);
}
void CMnemonicCtrl::OnMnemonic(LPMSG pMsg)
{
if ((pMsg->message == WM_SYSKEYDOWN)||
(pMsg->message == WM_SYSCHAR))
{
if ((pMsg->wParam == 'm')||(pMsg->wParam == 'M'))
{
// Do mnemonic key processing here.
return;
}
}
COleControl::OnMnemonic(pMsg);
}
Modification Type: | Major | Last Reviewed: | 1/9/2006 |
---|
Keywords: | kbinfo kbhowto kbtshoot kbAcceleratorKey kbcode kbCtrlCreate kbKeyAccel kbprb KB145698 kbAudDeveloper |
---|
|