using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class User32 { /// Flags used by . [PInvokeData("winuser.h")] [Flags] public enum FVIRT : byte { /// /// The key member specifies a virtual-key code. If this flag is not specified, key is assumed to specify a character code. /// FVIRTKEY = 0x01, /// /// 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. This attribute is obsolete and retained only for backward /// compatibility with resource files designed for 16-bit Windows. /// FNOINVERT = 0x02, /// The SHIFT key must be held down when the accelerator key is pressed. FSHIFT = 0x04, /// The CTRL key must be held down when the accelerator key is pressed. FCONTROL = 0x08, /// The ALT key must be held down when the accelerator key is pressed. FALT = 0x10, } /// /// Copies the specified accelerator table. This function is used to obtain the accelerator-table data that corresponds to an /// accelerator-table handle, or to determine the size of the accelerator-table data. /// /// /// Type: HACCEL /// A handle to the accelerator table to copy. /// /// /// Type: LPACCEL /// An array of ACCEL structures that receives the accelerator-table information. /// /// /// Type: int /// The number of ACCEL structures to copy to the buffer pointed to by the lpAccelDst parameter. /// /// /// Type: int /// /// If lpAccelDst is NULL, the return value specifies the number of accelerator-table entries in the original table. /// Otherwise, it specifies the number of accelerator-table entries that were copied. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-copyacceleratortablea int CopyAcceleratorTableA( HACCEL // hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries ); [DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public static extern int CopyAcceleratorTable(HACCEL hAccelSrc, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] ACCEL[] lpAccelDst, int cAccelEntries); /// Creates an accelerator table. /// /// Type: LPACCEL /// An array of ACCEL structures that describes the accelerator table. /// /// /// Type: int /// The number of ACCEL structures in the array. This must be within the range 1 to 32767 or the function will fail. /// /// /// Type: HACCEL /// /// If the function succeeds, the return value is the handle to the created accelerator table; otherwise, it is NULL. To get /// extended error information, call GetLastError. /// /// /// /// /// Before an application closes, it can use the DestroyAcceleratorTable function to destroy any accelerator tables that it created /// by using the CreateAcceleratorTable function. /// /// Examples /// For an example, see Creating User Editable Accelerators. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createacceleratortablea HACCEL CreateAcceleratorTableA( // LPACCEL paccel, int cAccel ); [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public static extern SafeHACCEL CreateAcceleratorTable([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ACCEL[] paccel, int cAccel); /// Destroys an accelerator table. /// /// Type: HACCEL /// /// A handle to the accelerator table to be destroyed. This handle must have been created by a call to the CreateAcceleratorTable or /// LoadAccelerators function. /// /// /// /// Type: BOOL /// /// If the function succeeds, the return value is nonzero. However, if the table has been loaded more than one call to /// LoadAccelerators, the function will return a nonzero value only when DestroyAcceleratorTable has been called an equal /// number of times. /// /// If the function fails, the return value is zero. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-destroyacceleratortable BOOL DestroyAcceleratorTable( // HACCEL hAccel ); [DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winuser.h")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DestroyAcceleratorTable(HACCEL hAccel); /// Loads the specified accelerator table. /// /// Type: HINSTANCE /// A handle to the module whose executable file contains the accelerator table to be loaded. /// /// /// Type: LPCTSTR /// /// The name of the accelerator table to be loaded. Alternatively, this parameter can specify the resource identifier of an /// accelerator-table resource in the low-order word and zero in the high-order word. To create this value, use the MAKEINTRESOURCE macro. /// /// /// /// Type: HACCEL /// If the function succeeds, the return value is a handle to the loaded accelerator table. /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. /// /// /// If the accelerator table has not yet been loaded, the function loads it from the specified executable file. /// Accelerator tables loaded from resources are freed automatically when the application terminates. /// Examples /// For an example, see Creating Accelerators for Font Attributes. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-loadacceleratorsa HACCEL LoadAcceleratorsA( HINSTANCE // hInstance, LPCSTR lpTableName ); [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public static extern HACCEL LoadAccelerators(HINSTANCE hInstance, string lpTableName); /// /// Processes accelerator keys for menu commands. The function translates a WM_KEYDOWN or WM_SYSKEYDOWN message to a WM_COMMAND or /// WM_SYSCOMMAND message (if there is an entry for the key in the specified accelerator table) and then sends the WM_COMMAND /// or WM_SYSCOMMAND message directly to the specified window procedure. TranslateAccelerator does not return until the /// window procedure has processed the message. /// /// /// Type: HWND /// A handle to the window whose messages are to be translated. /// /// /// Type: HACCEL /// /// A handle to the accelerator table. The accelerator table must have been loaded by a call to the LoadAccelerators function or /// created by a call to the CreateAcceleratorTable function. /// /// /// /// Type: LPMSG /// /// A pointer to an MSG structure that contains message information retrieved from the calling thread's message queue using the /// GetMessage or PeekMessage function. /// /// /// /// Type: int /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// To differentiate the message that this function sends from messages sent by menus or controls, the high-order word of the wParam /// parameter of the WM_COMMAND or WM_SYSCOMMAND message contains the value 1. /// /// /// Accelerator key combinations used to select items from the window menu are translated into WM_SYSCOMMAND messages; all /// other accelerator key combinations are translated into WM_COMMAND messages. /// /// /// When TranslateAccelerator returns a nonzero value and the message is translated, the application should not use the /// TranslateMessage function to process the message again. /// /// An accelerator need not correspond to a menu command. /// /// If the accelerator command corresponds to a menu item, the application is sent WM_INITMENU and WM_INITMENUPOPUP messages, as if /// the user were trying to display the menu. However, these messages are not sent if any of the following conditions exist: /// /// /// /// The window is disabled. /// /// /// The accelerator key combination does not correspond to an item on the window menu and the window is minimized. /// /// /// A mouse capture is in effect. For information about mouse capture, see the SetCapture function. /// /// /// /// If the specified window is the active window and no window has the keyboard focus (which is generally the case if the window is /// minimized), TranslateAccelerator translates WM_SYSKEYUP and WM_SYSKEYDOWN messages instead of WM_KEYUP and WM_KEYDOWN messages. /// /// /// If an accelerator keystroke occurs that corresponds to a menu item when the window that owns the menu is minimized, /// TranslateAccelerator does not send a WM_COMMAND message. However, if an accelerator keystroke occurs that does not match /// any of the items in the window's menu or in the window menu, the function sends a WM_COMMAND message, even if the /// window is minimized. /// /// Examples /// For an example, see Creating Accelerators for Font Attributes. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-translateacceleratora int TranslateAcceleratorA( HWND // hWnd, HACCEL hAccTable, LPMSG lpMsg ); [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public static extern int TranslateAccelerator(HWND hWnd, HACCEL hAccTable, in MSG lpMsg); /// /// Defines an accelerator key used in an accelerator table. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagaccel typedef struct tagACCEL { #if ... BYTE fVirt; // WORD key; #if ... WORD cmd; #else WORD fVirt; #endif #else DWORD cmd; #endif } ACCEL, *LPACCEL; [PInvokeData("winuser.h")] [StructLayout(LayoutKind.Sequential)] public struct ACCEL { /// The accelerator behavior. This member can be one or more of the following values. public FVIRT fVirt; /// /// Type: WORD /// The accelerator key. This member can be either a virtual-key code or a character code. /// public ushort key; /// /// 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. /// public ushort cmd; } /// Provides a for that is disposed using . public class SafeHACCEL : SafeHANDLE, IUserHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHACCEL(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHACCEL() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HACCEL(SafeHACCEL h) => h.handle; /// protected override bool InternalReleaseHandle() => DestroyAcceleratorTable(this); } } }