I placed a RichTextBox control on a new form and launched the project. So the RichTextBox.Text = \"\";
Each time I press Up or Down keys I heard the annoying BEEP so
The following is a .Net implementation of using the ITextServices interface method described in @RbMm's answer. If you find this useful, please consider upvoting that answer.
This implementation exposes two extension methods (EnableBeep
and DisableBeep
) for the Winform RichTextBox. Both a C# and Vb.Net version are provided.
As we are only interested in using the OnTxPropertyBitsChange
function defined in the ITextServices interface, an abbreviated implementation of the interface is used similar to those created when "Embed Interop Types" is used for a COM reference. If you have installed the Windows SDK, you should find the "TextServ.h" file at a path similar to "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\TextServ.h". This file defines the full ITextServices class interface.
C# version
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
//----
public static class RTBBeepExtensions
{
public static void EnableBeep(this RichTextBox rtb)
{
SetBeepInternal(rtb, true);
}
public static void DisableBeep(this RichTextBox rtb)
{
SetBeepInternal(rtb, false);
}
private static void SetBeepInternal(RichTextBox rtb, bool beepOn)
{
const Int32 WM_USER = 0x400;
const Int32 EM_GETOLEINTERFACE = WM_USER + 60;
const Int32 COMFalse = 0;
const Int32 COMTrue = ~COMFalse; // -1
ITextServices textServices = null;
// retrieve the rtb's OLEINTERFACE using the Interop Marshaller to cast it as an ITextServices
// The control calls the AddRef method for the object before returning, so the calling application must call the Release method when it is done with the object.
SendMessage(new HandleRef(rtb, rtb.Handle), EM_GETOLEINTERFACE, IntPtr.Zero, ref textServices);
textServices.OnTxPropertyBitsChange(TXTBIT.ALLOWBEEP, beepOn ? COMTrue : COMFalse));
Marshal.ReleaseComObject(textServices);
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private extern static IntPtr SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, ref ITextServices lParam);
#region ITextServices // From TextServ.h
[ComImport(), Guid("8d33f740-cf58-11ce-a89d-00aa006cadc5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ITextServices
{
//see: Slots in the V-table
// https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/imetadataemit-definemethod-method#slots-in-the-v-table
void _VtblGap1_16();
Int32 OnTxPropertyBitsChange(TXTBIT dwMask, Int32 dwBits);
}
private enum TXTBIT : uint
{
/// If TRUE, beeping is enabled.
ALLOWBEEP = 0x800
}
#endregion
}
VB.Net version
Imports System
Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms
' -------
Public Module RTBBeepExtensions
Public Sub EnableBeep(rtb As RichTextBox)
SetBeepInternal(rtb, True)
End Sub
Public Sub DisableBeep(rtb As RichTextBox)
SetBeepInternal(rtb, False)
End Sub
Private Sub SetBeepInternal(rtb As RichTextBox, beepOn As Boolean)
Const WM_USER As Int32 = &H400
Const EM_GETOLEINTERFACE As Int32 = WM_USER + 60
Const COMFalse As Int32 = 0
Const COMTrue As Int32 = Not COMFalse ' -1
Dim textServices As ITextServices = Nothing
' retrieve the rtb's OLEINTERFACE using the Interop Marshaller to cast it as an ITextServices
' The control calls the AddRef method for the object before returning, so the calling application must call the Release method when it is done with the object.
SendMessage(New HandleRef(rtb, rtb.Handle), EM_GETOLEINTERFACE, IntPtr.Zero, textServices)
textServices.OnTxPropertyBitsChange(TXTBIT.ALLOWBEEP, If(beepOn, COMTrue, COMFalse))
Marshal.ReleaseComObject(textServices)
End Sub
Private Function SendMessage(ByVal hWnd As HandleRef, ByVal msg As Int32, ByVal wParam As IntPtr, ByRef lParam As ITextServices) As IntPtr
End Function
#Region "ITextServices" ' From TextServ.h
Private Interface ITextServices
'see: Slots in the V-table
' https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/imetadataemit-definemethod-method#slots-in-the-v-table
Sub _VtblGap1_16()
Function OnTxPropertyBitsChange(ByVal dwMask As TXTBIT, ByVal dwBits As Int32) As Int32
End Interface
Private Enum TXTBIT As UInt32
''' If TRUE, beeping is enabled.
ALLOWBEEP = &H800
End Enum
#End Region
End Module
If you are unfamiliar with using extension methods, please refer to the following documentation links.
Extension Methods (C# Programming Guide)
Extension Methods (Visual Basic)