Showing the Keyboard Navigation Indicators
Windows 2000 introduced a setting for hiding keyboard accelerator keys. If this setting is enabled, the shortcuts are not displayed in underlined font style.
There is no general managed way in .NET Framework 1.1 to show accelerator keys underlined automatically. To do that, a WM_CHANGEUISTATE
message with appropriate data must be sent to the window that should show its accelerator keys. One of the parameters passed with the message needs the MAKELONG
macro to combine two 16-bit integers to a 32-bit integer. In our sample, we use a trick with a structure to provide an easy and managed way to replace the MAKELONG
, LOWORD
, and HIWORD
macros:
Imports System.Runtime.InteropServices
Public Class WordConverter
<StructLayout(LayoutKind.Explicit)> _
Private Structure DWord
<FieldOffset(0)> Public LongValue As Integer
<FieldOffset(0)> Public LoWord As Short
<FieldOffset(2)> Public HiWord As Short
End Structure
Private Shared m_DWord As DWord
Public Shared Function MakeLong( _
ByVal LoWord As Short, _
ByVal HiWord As Short _
) As Integer
m_DWord.LoWord = LoWord
m_DWord.HiWord = HiWord
Return m_DWord.LongValue
End Function
Public Shared Function MakeLong( _
ByVal LoWord As Integer, _
ByVal HiWord As Integer _
) As Integer
Return MakeLong(CShort(LoWord), CShort(HiWord))
End Function
Public Shared Function LoWord(ByVal LongValue As Integer) As Short
m_DWord.LongValue = LongValue
Return m_DWord.LoWord
End Function
Public Shared Function HiWord(ByVal LongValue As Integer) As Short
m_DWord.LongValue = LongValue
Return m_DWord.HiWord
End Function
End Class
The procedure MakeAcceleratorsVisible
takes a controls and makes its accelerator keys visible:
Private Declare Auto Function SendMessage Lib "user32.dll" ( _
ByVal hWnd As IntPtr, _
ByVal wMsg As Int32, _
ByVal wParam As IntPtr, _
ByVal lParam As IntPtr _
) As IntPtr
Public Const WM_CHANGEUISTATE As Int32 = &H127
Public Const UIS_CLEAR As Int32 = 2
Public Const UISF_HIDEACCEL As Int16 = &H2
Public Sub MakeAcceleratorsVisible(ByVal Control As Control)
SendMessage( _
Control.Handle, _
WM_CHANGEUISTATE, _
New IntPtr(WordConverter.MakeLong(UIS_CLEAR, UISF_HIDEACCEL)), _
IntPtr.Zero _
)
End Sub
If accelerators should be made visible within a Windows Forms control class, the code below can be used instead of MakeAcceleratorsVisible
:
MyBase.WndProc( _
Message.Create( _
Me.Handle, _
WM_CHANGEUISTATE, _
New IntPtr(WordConverter.MakeLong(UIS_CLEAR, UISF_HIDEACCEL)), _
IntPtr.Zero _
) _
)