diff --git a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableCheckBox.cs b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableCheckBox.cs index eef5eb7..1f5e30d 100644 --- a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableCheckBox.cs +++ b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableCheckBox.cs @@ -56,7 +56,7 @@ protected override void OnPaint(PaintEventArgs pevent) protected override void WndProc(ref Message m) { // Filter out the WM_ERASEBKGND message since we do that on our own with foreground painting - if (m.Msg == NativeMethods.WM_ERASEBKGND) + if (m.Msg == NativeConstants.Messages.WM_ERASEBKGND) { // return 0 (no erasing) m.Result = (IntPtr)1; diff --git a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableComboBox.cs b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableComboBox.cs index e15e846..8e7f869 100644 --- a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableComboBox.cs +++ b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableComboBox.cs @@ -141,7 +141,7 @@ private void wndProcInternal(ref Message m) switch (m.Msg) { //disabled box - case NativeMethods.WM_CTLCOLORSTATIC: + case NativeConstants.Messages.WM_CTLCOLORSTATIC: NativeMethods.SetBkColorInternal(m.WParam, ColorTranslator.ToWin32(Color.Orange)); IntPtr brush = NativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(Color.BlueViolet)); @@ -149,7 +149,7 @@ private void wndProcInternal(ref Message m) return; case 0x133: //coloredit, for the edit area of editable comboboxes - NativeMethods.SetBkModeInternal(m.WParam, NativeMethods.BKM_OPAQUE); + NativeMethods.SetBkModeInternal(m.WParam, NativeConstants.BKM_OPAQUE); NativeMethods.SetTextColorInternal(m.WParam, ColorTranslator.ToWin32(ForeColor)); NativeMethods.SetBkColorInternal(m.WParam, ColorTranslator.ToWin32(BackColor)); @@ -158,7 +158,7 @@ private void wndProcInternal(ref Message m) return; case 0x134: //colorlistbox - NativeMethods.SetBkModeInternal(m.WParam, NativeMethods.BKM_OPAQUE); + NativeMethods.SetBkModeInternal(m.WParam, NativeConstants.BKM_OPAQUE); NativeMethods.SetTextColorInternal(m.WParam, ColorTranslator.ToWin32(ForeColor)); NativeMethods.SetBkColorInternal(m.WParam, ColorTranslator.ToWin32(BackColor)); diff --git a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableListView.cs b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableListView.cs index c8da598..e32c186 100644 --- a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableListView.cs +++ b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableListView.cs @@ -95,7 +95,7 @@ protected override void Dispose(bool disposing) protected override void OnNotifyMessage(Message m) { //Filter out the WM_ERASEBKGND message - if (m.Msg != NativeMethods.WM_ERASEBKGND) + if (m.Msg != NativeConstants.Messages.WM_ERASEBKGND) { base.OnNotifyMessage(m); } @@ -107,9 +107,9 @@ protected override void WndProc(ref Message m) } private void wndProcInternal(ref Message m) { - if (m.Msg != NativeMethods.WM_REFLECT + NativeMethods.WM_NOFITY) + if (m.Msg != NativeConstants.Messages.WM_REFLECT + NativeConstants.Messages.WM_NOFITY) { - if (m.Msg == NativeMethods.WM_LBUTTONUP) + if (m.Msg == NativeConstants.Messages.WM_LBUTTONUP) { base.DefWndProc(ref m); return; @@ -127,7 +127,7 @@ private void wndProcInternal(ref Message m) } NativeMethods.NMHDR pnmhdr = (NativeMethods.NMHDR)nmhdrParam; - if (pnmhdr.code != NativeMethods.NM_CUSTOMDRAW) + if (pnmhdr.code != NativeConstants.NM_CUSTOMDRAW) { base.WndProc(ref m); return; @@ -147,7 +147,7 @@ private void wndProcInternal(ref Message m) { m.Result = pnmlv.dwItemType switch { - NativeMethods.LVCDI_GROUP => drawGroupHeader(m.HWnd, pnmlv), + NativeConstants.LVCDI_GROUP => drawGroupHeader(m.HWnd, pnmlv), _ => new IntPtr((int)NativeMethods.CDRF.NotifyItemDraw) }; @@ -157,7 +157,7 @@ private void wndProcInternal(ref Message m) { switch (pnmlv.dwItemType) { - case NativeMethods.LVCDI_ITEM: + case NativeConstants.LVCDI_ITEM: int itemIndex = (int)pnmlv.nmcd.dwItemSpec; // skip items that are not selected as they are already drawn correctly @@ -194,7 +194,7 @@ private IntPtr drawItem(IntPtr mHWnd, int itemIndex, NativeMethods.NMLVCUSTOMDRA left = (int)ItemBoundsPortion.Entire }; - NativeMethods.SendMessageInternal(mHWnd, NativeMethods.LVM_GETITEMRECT, itemIndex, ref rectHeader); + NativeMethods.SendMessageInternal(mHWnd, NativeConstants.Messages.LVM_GETITEMRECT, itemIndex, ref rectHeader); using (Graphics g = Graphics.FromHdc(pnmlv.nmcd.hdc)) { // background color @@ -229,12 +229,12 @@ private IntPtr drawGroupHeader(IntPtr mHWnd, NativeMethods.NMLVCUSTOMDRAW pnmlv) { NativeMethods.RECT rectHeader = new() { - top = NativeMethods.LVGGR_HEADER + top = NativeConstants.LVGGR_HEADER }; int groupIndex = (int)pnmlv.nmcd.dwItemSpec; - NativeMethods.SendMessageInternal(mHWnd, NativeMethods.LVM_GETGROUPRECT, groupIndex, + NativeMethods.SendMessageInternal(mHWnd, NativeConstants.Messages.LVM_GETGROUPRECT, groupIndex, ref rectHeader); using (Graphics g = Graphics.FromHdc(pnmlv.nmcd.hdc)) { @@ -246,11 +246,11 @@ private IntPtr drawGroupHeader(IntPtr mHWnd, NativeMethods.NMLVCUSTOMDRAW pnmlv) // Group header text NativeMethods.LVGROUP listviewGroup = new(); listviewGroup.cbSize = (uint)Marshal.SizeOf(listviewGroup); - listviewGroup.mask = NativeMethods.LVGF_GROUPID | NativeMethods.LVGF_HEADER; + listviewGroup.mask = NativeConstants.LVGF_GROUPID | NativeConstants.LVGF_HEADER; NativeMethods.SendMessageInternal( mHWnd, - NativeMethods.LVM_GETGROUPINFO, + NativeConstants.Messages.LVM_GETGROUPINFO, groupIndex, ref listviewGroup); diff --git a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableTabControl.cs b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableTabControl.cs index fa882b4..a020b1f 100644 --- a/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableTabControl.cs +++ b/StylableWinFormsControls/StylableWinFormsControls/Controls/StylableTabControl.cs @@ -459,7 +459,7 @@ private void findUpDown() bool bFound = false; // find the UpDown control - IntPtr pWnd = NativeMethods.GetWindow(Handle, NativeMethods.GW_CHILD); + IntPtr pWnd = NativeMethods.GetWindow(Handle, NativeConstants.GW_CHILD); while (pWnd != IntPtr.Zero) { @@ -486,7 +486,7 @@ private void findUpDown() break; } - pWnd = NativeMethods.GetWindow(pWnd, NativeMethods.GW_HWNDNEXT); + pWnd = NativeMethods.GetWindow(pWnd, NativeConstants.GW_HWNDNEXT); } if (!bFound && _bUpDown) @@ -519,7 +519,7 @@ private int scUpDown_SubClassedWndProc(ref Message m) switch (m.Msg) { - case NativeMethods.WM_PAINT: + case NativeConstants.Messages.WM_PAINT: //------------------------ // redraw IntPtr hDc = NativeMethods.GetWindowDC(_scUpDown.Handle); diff --git a/StylableWinFormsControls/StylableWinFormsControls/Native/NativeConstants.cs b/StylableWinFormsControls/StylableWinFormsControls/Native/NativeConstants.cs new file mode 100644 index 0000000..67f0098 --- /dev/null +++ b/StylableWinFormsControls/StylableWinFormsControls/Native/NativeConstants.cs @@ -0,0 +1,212 @@ +using System.Globalization; +using System.Reflection; + +namespace StylableWinFormsControls.Native +{ + /// + /// contains constants required for native calls + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Roslynator", + "RCS1181:Convert comment to documentation comment.", + Justification = "Most of the comments are not documentation, but internal notes.")] + internal static class NativeConstants + { + /// + /// Background is filled with the current background color before the text, hatched brush, or pen is drawn. + /// + internal const int BKM_OPAQUE = 2; + + /// + /// Background remains untouched. + /// + internal const int BKM_TRANSPARENT = 1; + /// + /// constant to define dark mode option + /// + internal const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; + + /// + /// constant to define dark mode option + /// + internal const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20_H1 = 19; + + internal const int GW_CHILD = 5; + internal const int GW_HWNDFIRST = 0; + internal const int GW_HWNDLAST = 1; + internal const int GW_HWNDNEXT = 2; + internal const int GW_HWNDPREV = 3; + internal const int GW_OWNER = 4; + internal const int LVCDI_GROUP = 0x1; + internal const int LVCDI_ITEM = 0x0; + internal const int LVCDI_ITEMSLIST = 0x2; + + internal const int LVGA_FOOTER_CENTER = 0x10; + internal const int LVGA_FOOTER_LEFT = 0x8; + // Don't forget to validate exclusivity + internal const int LVGA_FOOTER_RIGHT = 0x20; + + internal const int LVGA_HEADER_CENTER = 0x2; + internal const int LVGA_HEADER_LEFT = 0x1; + // Don't forget to validate exclusivity + internal const int LVGA_HEADER_RIGHT = 0x4; + + internal const int LVGF_ALIGN = 0x8; + // pszDescriptionBottom is valid + internal const int LVGF_DESCRIPTIONBOTTOM = 0x800; + + // pszDescriptionTop is valid + internal const int LVGF_DESCRIPTIONTOP = 0x400; + + // iExtendedImage is valid + internal const int LVGF_EXTENDEDIMAGE = 0x2000; + + internal const int LVGF_FOOTER = 0x2; + internal const int LVGF_GROUPID = 0x10; + internal const int LVGF_HEADER = 0x1; + // iFirstItem and cItems are valid + internal const int LVGF_ITEMS = 0x4000; + + // Listview group specific flags + internal const int LVGF_NONE = 0x0; + + internal const int LVGF_STATE = 0x4; + // pszSubsetTitle is valid + internal const int LVGF_SUBSET = 0x8000; + + // readonly, cItems holds count of items in visible subset, iFirstItem is valid + internal const int LVGF_SUBSETITEMS = 0x10000; + + // pszSubtitle is valid + internal const int LVGF_SUBTITLE = 0x100; + + // pszTask is valid + internal const int LVGF_TASK = 0x200; + + // iTitleImage is valid + internal const int LVGF_TITLEIMAGE = 0x1000; + + // Entire expanded group + internal const int LVGGR_GROUP = 0; + + // Header only (collapsed group) + internal const int LVGGR_HEADER = 1; + + // Label only + internal const int LVGGR_LABEL = 2; + + // subset link only + internal const int LVGGR_SUBSETLINK = 3; + + internal const int LVGS_COLLAPSED = 0x1; + internal const int LVGS_COLLAPSIBLE = 0x8; + internal const int LVGS_FOCUSED = 0x10; + internal const int LVGS_HIDDEN = 0x2; + internal const int LVGS_NOHEADER = 0x4; + // Listview group styles + internal const int LVGS_NORMAL = 0x0; + + internal const int LVGS_SELECTED = 0x20; + internal const int LVGS_SUBSETED = 0x40; + internal const int LVGS_SUBSETLINKFOCUSED = 0x80; + internal const int LVM_FIRST = 0x1000; + /// + /// Return value from : Activates the window, and does not discard the mouse message + /// + internal const uint MA_ACTIVATE = 1; + + /// + /// Return value from : Activates the window, and discards the mouse message + /// + internal const uint MA_ACTIVATEANDEAT = 2; + + internal const int NM_CLICK = NM_FIRST - 2; + internal const int NM_CUSTOMDRAW = NM_FIRST - 12; + internal const int NM_FIRST = 0; + /* + * GetWindow() Constants + */ + internal static class Messages + { + internal const int LVM_GETGROUPINFO = LVM_FIRST + 149; + internal const int LVM_GETGROUPRECT = LVM_FIRST + 98; + internal const int LVM_GETITEMRECT = LVM_FIRST + 14; + /// + /// A static control, or an edit control that is read-only or disabled, + /// sends the WM_CTLCOLORSTATIC message to its parent window when the control is about to be drawn. + /// By responding to this message, the parent window can use the specified device context handle to set the text and + /// background colors of the static control. + /// + internal const int WM_CTLCOLORSTATIC = 0x138; + /// + /// Sent when the window background must be erased (for example, when a window is resized). + /// The message is sent to prepare an invalidated portion of a window for painting. + /// + internal const int WM_ERASEBKGND = 0x14; + + /// + /// Posted when the user releases the left mouse button while the cursor is in the client area of a window. + /// + internal const int WM_LBUTTONUP = 0x202; + /// + /// Sent when the cursor is in an inactive window and the user presses a mouse button. + /// + internal const uint WM_MOUSEACTIVATE = 0x21; + + /// + /// Sent by a common control to its parent window when an event has occurred or the control requires some information. + /// + internal const int WM_NOFITY = 0x4E; + + /// + /// The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. + /// + internal const int WM_PAINT = 0xF; + + /// + /// MFC Message Reflection + /// + /// See more: https://learn.microsoft.com/en-us/cpp/mfc/tn062-message-reflection-for-windows-controls + internal const int WM_REFLECT = 0x2000; + + /// + /// Sent to a window to allow changes in that window to be redrawn, or to prevent changes in that window from being redrawn + /// + internal const int WM_SETREDRAW = 11; + + #region reverse msg value logic + private static readonly Dictionary MESSAGE_NAME_DICT = new(); + private static void initMessageNameFromValue() + { + //get all constants + FieldInfo[] fieldInfos = typeof(Messages).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + List constants = (from f in fieldInfos where f.IsLiteral && !f.IsInitOnly && (typeof(int).IsAssignableFrom(f.FieldType) || typeof(uint).IsAssignableFrom(f.FieldType)) select f).ToList(); + + + //add all constants to the messageNameDict + constants.ForEach(f => + { + object? value = f.GetValue(null); + if (value is not null) + { + MESSAGE_NAME_DICT.Add(Convert.ToInt64(value, CultureInfo.InvariantCulture), f.Name); + } + } + ); + } + public static string Reverse(int value) + { + if (MESSAGE_NAME_DICT.Count == 0) + { + initMessageNameFromValue(); + } + if (MESSAGE_NAME_DICT.ContainsKey(value)) + { + return MESSAGE_NAME_DICT[value]; + } + return $"Unknown Value({value})"; + } + #endregion + } + } +} diff --git a/StylableWinFormsControls/StylableWinFormsControls/Native/NativeMethods.cs b/StylableWinFormsControls/StylableWinFormsControls/Native/NativeMethods.cs index 61321d6..21e16f7 100644 --- a/StylableWinFormsControls/StylableWinFormsControls/Native/NativeMethods.cs +++ b/StylableWinFormsControls/StylableWinFormsControls/Native/NativeMethods.cs @@ -1,5 +1,3 @@ -using System.Drawing; -using System.Reflection; using System.Runtime.InteropServices; namespace StylableWinFormsControls.Native; @@ -16,10 +14,6 @@ namespace StylableWinFormsControls.Native; "Roslynator", "RCS1135:Declare enum member with zero value (when enum has FlagsAttribute).", Justification = "Naming of structures is defined by the native methods that use them.")] -[System.Diagnostics.CodeAnalysis.SuppressMessage( - "Roslynator", - "RCS1181:Convert comment to documentation comment.", - Justification = "Most of the comments are not documentation, but internal notes.")] internal class NativeMethods { public const int TRUE_VALUE = 1; @@ -69,7 +63,7 @@ internal static void SendMessageInternal(IntPtr hWnd, int msg, int wParam, ref L bool success = SendMessage(hWnd, msg, wParam, ref lParam) == TRUE_VALUE; if (!success) { - throw new NativeException($"failed to do native call 'SendMessage' (msg = {MessageNameFromValue(msg)}, wParam = {wParam})", Marshal.GetLastWin32Error()); + throw new NativeException($"failed to do native call 'SendMessage' (msg = {NativeConstants.Messages.Reverse(msg)}, wParam = {wParam})", Marshal.GetLastWin32Error()); } } @@ -80,7 +74,7 @@ internal static void SendMessageInternal(IntPtr hWnd, int msg, int wParam, ref R bool success = SendMessage(hWnd, msg, wParam, ref lParam) == TRUE_VALUE; if (!success) { - throw new NativeException($"failed to do native call 'SendMessage' (msg = {MessageNameFromValue(msg)}, wParam = {wParam})", Marshal.GetLastWin32Error()); + throw new NativeException($"failed to do native call 'SendMessage' (msg = {NativeConstants.Messages.Reverse(msg)}, wParam = {wParam})", Marshal.GetLastWin32Error()); } } @@ -137,7 +131,7 @@ internal static void SetBkColorInternal(IntPtr hdc, int color) internal static void SetBkModeInternal(IntPtr hdc, int bkMode) { int oldValue = SetBkMode(hdc, bkMode); - bool success = oldValue is BKM_OPAQUE or BKM_TRANSPARENT; + bool success = oldValue is NativeConstants.BKM_OPAQUE or NativeConstants.BKM_TRANSPARENT; if (!success) { throw new NativeException($"failed to do native call 'SetBkMode' (bkMode = {bkMode})", Marshal.GetLastWin32Error()); @@ -168,30 +162,6 @@ internal static void SetTextColorInternal(IntPtr hdc, int color) } } - /// - /// Background remains untouched. - /// - internal const int BKM_TRANSPARENT = 1; - - /// - /// Background is filled with the current background color before the text, hatched brush, or pen is drawn. - /// - internal const int BKM_OPAQUE = 2; - - internal const int LVCDI_ITEM = 0x0; - internal const int LVCDI_GROUP = 0x1; - internal const int LVCDI_ITEMSLIST = 0x2; - - internal const int LVM_FIRST = 0x1000; - internal const int LVM_GETITEMRECT = LVM_FIRST + 14; - internal const int LVM_GETGROUPRECT = LVM_FIRST + 98; - internal const int LVM_GETGROUPINFO = LVM_FIRST + 149; - - /// - /// Posted when the user releases the left mouse button while the cursor is in the client area of a window. - /// - internal const int WM_LBUTTONUP = 0x202; - [StructLayout(LayoutKind.Sequential)] internal struct NMHDR { @@ -312,156 +282,4 @@ public struct PAINTSTRUCT [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] rgbReserved; } - - // Listview group specific flags - internal const int LVGF_NONE = 0x0; - - internal const int LVGF_HEADER = 0x1; - internal const int LVGF_FOOTER = 0x2; - internal const int LVGF_STATE = 0x4; - internal const int LVGF_ALIGN = 0x8; - internal const int LVGF_GROUPID = 0x10; - - internal const int LVGF_SUBTITLE = 0x100; // pszSubtitle is valid - internal const int LVGF_TASK = 0x200; // pszTask is valid - internal const int LVGF_DESCRIPTIONTOP = 0x400; // pszDescriptionTop is valid - internal const int LVGF_DESCRIPTIONBOTTOM = 0x800; // pszDescriptionBottom is valid - internal const int LVGF_TITLEIMAGE = 0x1000; // iTitleImage is valid - internal const int LVGF_EXTENDEDIMAGE = 0x2000; // iExtendedImage is valid - internal const int LVGF_ITEMS = 0x4000; // iFirstItem and cItems are valid - internal const int LVGF_SUBSET = 0x8000; // pszSubsetTitle is valid - internal const int LVGF_SUBSETITEMS = 0x10000; // readonly, cItems holds count of items in visible subset, iFirstItem is valid - - // Listview group styles - internal const int LVGS_NORMAL = 0x0; - - internal const int LVGS_COLLAPSED = 0x1; - internal const int LVGS_HIDDEN = 0x2; - internal const int LVGS_NOHEADER = 0x4; - internal const int LVGS_COLLAPSIBLE = 0x8; - internal const int LVGS_FOCUSED = 0x10; - internal const int LVGS_SELECTED = 0x20; - internal const int LVGS_SUBSETED = 0x40; - internal const int LVGS_SUBSETLINKFOCUSED = 0x80; - - internal const int LVGA_HEADER_LEFT = 0x1; - internal const int LVGA_HEADER_CENTER = 0x2; - internal const int LVGA_HEADER_RIGHT = 0x4; // Don't forget to validate exclusivity - internal const int LVGA_FOOTER_LEFT = 0x8; - internal const int LVGA_FOOTER_CENTER = 0x10; - internal const int LVGA_FOOTER_RIGHT = 0x20; // Don't forget to validate exclusivity - - internal const int LVGGR_GROUP = 0; // Entire expanded group - internal const int LVGGR_HEADER = 1; // Header only (collapsed group) - internal const int LVGGR_LABEL = 2; // Label only - internal const int LVGGR_SUBSETLINK = 3; // subset link only - - /// - /// constant to define dark mode option - /// - internal const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20_H1 = 19; - - /// - /// constant to define dark mode option - /// - internal const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; - - /// - /// Sent to a window to allow changes in that window to be redrawn, or to prevent changes in that window from being redrawn - /// - internal const int WM_SETREDRAW = 11; - - /// - /// Sent when the window background must be erased (for example, when a window is resized). - /// The message is sent to prepare an invalidated portion of a window for painting. - /// - internal const int WM_ERASEBKGND = 0x14; - - /// - /// The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. - /// - internal const int WM_PAINT = 0xF; - - /// - /// A static control, or an edit control that is read-only or disabled, - /// sends the WM_CTLCOLORSTATIC message to its parent window when the control is about to be drawn. - /// By responding to this message, the parent window can use the specified device context handle to set the text and - /// background colors of the static control. - /// - internal const int WM_CTLCOLORSTATIC = 0x138; - - internal const int NM_FIRST = 0; - internal const int NM_CLICK = NM_FIRST - 2; - internal const int NM_CUSTOMDRAW = NM_FIRST - 12; - - /// - /// MFC Message Reflection - /// - /// See more: https://learn.microsoft.com/en-us/cpp/mfc/tn062-message-reflection-for-windows-controls - internal const int WM_REFLECT = 0x2000; - - /// - /// Sent by a common control to its parent window when an event has occurred or the control requires some information. - /// - internal const int WM_NOFITY = 0x4E; - - /// - /// Sent when the cursor is in an inactive window and the user presses a mouse button. - /// - internal const uint WM_MOUSEACTIVATE = 0x21; - - /// - /// Return value from : Activates the window, and does not discard the mouse message - /// - internal const uint MA_ACTIVATE = 1; - - /// - /// Return value from : Activates the window, and discards the mouse message - /// - internal const uint MA_ACTIVATEANDEAT = 2; - - /* - * GetWindow() Constants - */ - internal const int GW_HWNDFIRST = 0; - internal const int GW_HWNDLAST = 1; - internal const int GW_HWNDNEXT = 2; - internal const int GW_HWNDPREV = 3; - internal const int GW_OWNER = 4; - internal const int GW_CHILD = 5; - - #region reverse msg value logic - private static readonly Dictionary messageNameDict = new(); - private static void InitMessageNameFromValue() - { - //get all constants - FieldInfo[] fieldInfos = typeof(NativeMethods).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - List constants = (from f in fieldInfos where f.IsLiteral && !f.IsInitOnly && f.FieldType.IsAssignableFrom(typeof(int)) select f).ToList(); - - //add all constants to the messageNameDict - constants.ForEach(f => - { - object? value = f.GetValue(null); - if (value is not null && f.Name != nameof(TRUE_VALUE) && f.Name != nameof(FALSE_VALUE) - //TODO: separate Message values to a separate constant class - && !messageNameDict.ContainsKey((int)value)) - { - messageNameDict.Add((int)value, f.Name); - } - } - ); - } - public static string MessageNameFromValue(int value) - { - if (messageNameDict.Count == 0) - { - InitMessageNameFromValue(); - } - if (messageNameDict.ContainsKey(value)) - { - return messageNameDict[value]; - } - return $"Unknown Value({value})"; - } - #endregion }