diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCGIF.cs b/src/Common/src/Interop/ComCtl32/Interop.MCGIF.cs new file mode 100644 index 00000000000..28581f27a5e --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCGIF.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar Control Grid Info Flags. + /// Copied form CommCtrl.h + /// + [Flags] + public enum MCGIF + { + /// + /// Represetns MCGIF_DATE const. + /// + DATE = 0x00000001, + + /// + /// Represents MCGIF_RECT cosnt. + /// + RECT = 0x00000002, + + /// + /// Represetns MCGIF_NAME const. + /// + NAME = 0x00000004 + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCGIP.cs b/src/Common/src/Interop/ComCtl32/Interop.MCGIP.cs new file mode 100644 index 00000000000..adffede8f8e --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCGIP.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar control part constants. + /// Copied form CommCtrl.h + /// + public enum MCGIP : uint + { + /// + /// Represents MCGIP_CALENDARCONTROL const. + /// + CALENDARCONTROL = 0, + + /// + /// Represents MCGIP_NEXT const. + /// + NEXT = 1, + + /// + /// Represents MCGIP_PREV const. + /// + PREV = 2, + + /// + /// Represents MCGIP_FOOTER const. + /// + FOOTER = 3, + + /// + /// Represents MCGIP_CALENDAR const. + /// + CALENDAR = 4, + + /// + /// Represents MCGIP_CALENDARHEADER const. + /// + CALENDARHEADER = 5, + + /// + /// Represents MCGIP_CALENDARBODY const. + /// + CALENDARBODY = 6, + + /// + /// Represents MCGIP_CALENDARROW const. + /// + CALENDARROW = 7, + + /// + /// Represents MCGIP_CALENDARCELL const. + /// + CALENDARCELL = 8 + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCGRIDINFO.cs b/src/Common/src/Interop/ComCtl32/Interop.MCGRIDINFO.cs new file mode 100644 index 00000000000..6406b870904 --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCGRIDINFO.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using static System.Windows.Forms.NativeMethods; + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// MonthCalendar grid info structure. + /// Copied form CommCtrl.h + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public unsafe struct MCGRIDINFO + { + public uint cbSize; + public MCGIP dwPart; + public MCGIF dwFlags; + public int iCalendar; + public int iRow; + public int iCol; + public bool bSelected; + public Kernel32.SYSTEMTIME stStart; + public Kernel32.SYSTEMTIME stEnd; + public RECT rc; + public string pszName; + public uint cchName; + } + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public extern static IntPtr SendMessage(HandleRef hWnd, int Msg, int wParam, [In, Out] ref MCGRIDINFO gridInfo); + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCHITTESTINFO.cs b/src/Common/src/Interop/ComCtl32/Interop.MCHITTESTINFO.cs new file mode 100644 index 00000000000..c266ab9865c --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCHITTESTINFO.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct MCHITTESTINFO + { + public int cbSize; + public POINT pt; + public int uHit; + public Kernel32.SYSTEMTIME st; + public RECT rc; + public int iOffset; + public int iRow; + public int iCol; + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCHT.cs b/src/Common/src/Interop/ComCtl32/Interop.MCHT.cs new file mode 100644 index 00000000000..78c666d79e7 --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCHT.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar Control HitTest values. + /// Copied form CommCtrl.h + /// + public enum MCHT + { + /// + /// MCHT_TITLE + /// + TITLE = 0x00010000, + + /// + /// Represents MCHT_CALENDAR const. + /// + CALENDAR = 0x00020000, + + /// + /// Represents MCHT_TODAYLINK const. + /// + TODAYLINK = 0x00030000, + + /// + /// Represents MCHT_CALENDARCONTROL const. + /// + CALENDARCONTROL = 0x00100000, + + /// + /// Represents MCHT_NEXT const. + /// + NEXT = 0x01000000, + + /// + /// Represents MCHT_PREV const. + /// + PREV = 0x02000000, + + /// + /// Represents MCHT_NOWHERE const. + /// + NOWHERE = 0x00000000, + + /// + /// Represents MCHT_TITLEBK const. + /// + TITLEBK = TITLE, + + /// + /// Represents MCHT_TITLEMONTH const. + /// + TITLEMONTH = TITLE | 0x0001, + + /// + /// Represents MCHT_TITLEYEAR const. + /// + TITLEYEAR = TITLE | 0x0002, + + /// + /// Represents MCHT_TITLEBTNNEXT const. + /// + TITLEBTNNEXT = TITLE | NEXT | 0x0003, + + /// + /// Represents MCHT_TITLEBTNPREV const. + /// + TITLEBTNPREV = TITLE | PREV | 0x0003, + + /// + /// Represents MCHT_CALENDARBK const. + /// + CALENDARBK = CALENDAR, + + /// + /// Represents MCHT_CALENDARDATE const. + /// + CALENDARDATE = CALENDAR | 0x0001, + + /// + /// Represents MCHT_CALENDARDATENEXT const. + /// + CALENDARDATENEXT = CALENDARDATE | NEXT, + + /// + /// Represents MCHT_CALENDARDATEPREV const. + /// + CALENDARDATEPREV = CALENDARDATE | PREV, + + /// + /// Represents MCHT_CALENDARDAY const. + /// + CALENDARDAY = CALENDAR | 0x0002, + + /// + /// Represents MCHT_CALENDARWEEKNUM const. + /// + CALENDARWEEKNUM = CALENDAR | 0x0003, + + /// + /// Represents MCHT_CALENDARDATEMIN const. + /// + CALENDARDATEMIN = CALENDAR | 0x0004, + + /// + /// Represents MCHT_CALENDARDATEMAX const. + /// + CALENDARDATEMAX = CALENDAR | 0x0005 + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCM.cs b/src/Common/src/Interop/ComCtl32/Interop.MCM.cs new file mode 100644 index 00000000000..9547c236941 --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCM.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar Control Messages. + /// Copied form CommCtrl.h + /// + public enum MCM + { + /// + /// Represents MCM_FIRST const. + /// + FIRST = 0x1000, + + /// + /// Represents MCM_GETCURSEL const. + /// + GETCURSEL = FIRST + 1, + + /// + /// Represents MCM_SETMAXSELCOUNT const. + /// + SETMAXSELCOUNT = FIRST + 4, + + /// + /// Represents MCM_GETSELRANGE const. + /// + GETSELRANGE = FIRST + 5, + + /// + /// Represents MCM_SETSELRANGE const. + /// + SETSELRANGE = FIRST + 6, + + /// + /// Represents MCM_GETMONTHRANGE const. + /// + GETMONTHRANGE = FIRST + 7, + + /// + /// Represents MCM_GETMINREQRECT const. + /// + GETMINREQRECT = FIRST + 9, + + /// + /// Represents MCM_SETCOLOR const. + /// + SETCOLOR = FIRST + 10, + + /// + /// Represents MCM_SETTODAY const. + /// + SETTODAY = FIRST + 12, + + /// + /// Represents MCM_GETTODAY const. + /// + GETTODAY = FIRST + 13, + + /// + /// Represents MCM_HITTEST const. + /// + HITTEST = FIRST + 14, + + /// + /// Represents MCM_SETFIRSTDAYOFWEEK const. + /// + SETFIRSTDAYOFWEEK = FIRST + 15, + + /// + /// Represents MCM_GETRANGE const. + /// + GETRANGE = FIRST + 17, + + /// + /// Represents MCM_SETRANGE const. + /// + SETRANGE = FIRST + 18, + + /// + /// Represents MCM_SETMONTHDELTA const. + /// + SETMONTHDELTA = FIRST + 20, + + /// + /// Represents MCM_GETMAXTODAYWIDTH const. + /// + GETMAXTODAYWIDTH = FIRST + 21, + + /// + /// Represents MCM_GETCALENDARGRIDINFO const. + /// + GETCALENDARGRIDINFO = FIRST + 24 + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCS.cs b/src/Common/src/Interop/ComCtl32/Interop.MCS.cs new file mode 100644 index 00000000000..78b739dfa22 --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCS.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar Control styles constatnts. + /// Copied form CommCtrl.h + /// + public enum MCS + { + /// + /// Represents MCS_DAYSTATE const. + /// + DAYSTATE = 0x0001, + + /// + /// Represents MCS_MULTISELECT const. + /// + MULTISELECT = 0x0002, + + /// + /// Represents MCS_WEEKNUMBERS const. + /// + WEEKNUMBERS = 0x0004, + + /// + /// Represents MCS_NOTODAYCIRCLE const. + /// + NOTODAYCIRCLE = 0x0008, + + /// + /// Represents MCS_NOTODAY const. + /// + NOTODAY = 0x0010 + } + } +} diff --git a/src/Common/src/Interop/ComCtl32/Interop.MCSC.cs b/src/Common/src/Interop/ComCtl32/Interop.MCSC.cs new file mode 100644 index 00000000000..e0a51e8c028 --- /dev/null +++ b/src/Common/src/Interop/ComCtl32/Interop.MCSC.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class ComCtl32 + { + /// + /// Represents MonthCalendar control size and color constants. + /// Copied form CommCtrl.h + /// + public enum MCSC + { + /// + /// Represents MCSC_BACKGROUND const. + /// + BACKGROUND = 0, + + /// + /// Represents MCSC_TEXT const. + /// + TEXT = 1, + + /// + /// Represents MCSC_TITLEBK const. + /// + TITLEBK = 2, + + /// + /// Represents MCSC_TITLETEXT const. + /// + TITLETEXT = 3, + + /// + /// Represents MCSC_MONTHBK const. + /// + MONTHBK = 4, + + /// + /// Represents MCSC_TRAILINGTEXT const. + /// + TRAILINGTEXT = 5 + } + } +} diff --git a/src/Common/src/Interop/Interop.POINT.cs b/src/Common/src/Interop/Interop.POINT.cs new file mode 100644 index 00000000000..4166f242fef --- /dev/null +++ b/src/Common/src/Interop/Interop.POINT.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + /// + /// Represetns the point structure. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct POINT + { + internal int x; + internal int y; + + internal POINT(int x, int y) + { + this.x = x; + this.y = y; + } + + static public explicit operator POINT(Point pt) + { + return checked(new POINT((int)pt.X, (int)pt.Y)); + } + } +} diff --git a/src/Common/src/Interop/Kernel32/Interop.SYSTEMTIME.cs b/src/Common/src/Interop/Kernel32/Interop.SYSTEMTIME.cs new file mode 100644 index 00000000000..965b081789d --- /dev/null +++ b/src/Common/src/Interop/Kernel32/Interop.SYSTEMTIME.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class Kernel32 + { + public struct SYSTEMTIME + { + public short wYear; + public short wMonth; + public short wDayOfWeek; + public short wDay; + public short wHour; + public short wMinute; + public short wSecond; + public short wMilliseconds; + } + } +} diff --git a/src/Common/src/Interop/User32/Interop.MOUSEEVENTF.cs b/src/Common/src/Interop/User32/Interop.MOUSEEVENTF.cs new file mode 100644 index 00000000000..40955b96df1 --- /dev/null +++ b/src/Common/src/Interop/User32/Interop.MOUSEEVENTF.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class User32 + { + [Flags] + public enum MOUSEEVENTF : uint + { + MOVE = 0x0001, + LEFTDOWN = 0x0002, + LEFTUP = 0x0004, + RIGHTDOWN = 0x0008, + RIGHTUP = 0x0010, + MIDDLEDOWN = 0x0020, + MIDDLEUP = 0x0040, + XDOWN = 0x0080, + XUP = 0x0100, + WHEEL = 0x0800, + HWHEEL = 0x1000, + MOVE_NOCOALESCE = 0x2000, + VIRTUALDESK = 0x4000, + ABSOLUTE = 0x8000, + } + } +} diff --git a/src/Common/src/NativeMethods.cs b/src/Common/src/NativeMethods.cs index c847ad317fc..51a7c0ef19b 100644 --- a/src/Common/src/NativeMethods.cs +++ b/src/Common/src/NativeMethods.cs @@ -852,48 +852,15 @@ public static int MAKELCID(int lgid, int sort) MDITILE_VERTICAL = 0x0000, MDITILE_HORIZONTAL = 0x0001, MDITILE_SKIPDISABLED = 0x0002, - MCM_SETMAXSELCOUNT = (0x1000 + 4), - MCM_SETSELRANGE = (0x1000 + 6), - MCM_GETMONTHRANGE = (0x1000 + 7), - MCM_GETMINREQRECT = (0x1000 + 9), - MCM_SETCOLOR = (0x1000 + 10), - MCM_SETTODAY = (0x1000 + 12), - MCM_GETTODAY = (0x1000 + 13), - MCM_HITTEST = (0x1000 + 14), - MCM_SETFIRSTDAYOFWEEK = (0x1000 + 15), - MCM_SETRANGE = (0x1000 + 18), - MCM_SETMONTHDELTA = (0x1000 + 20), - MCM_GETMAXTODAYWIDTH = (0x1000 + 21), - MCHT_TITLE = 0x00010000, - MCHT_CALENDAR = 0x00020000, - MCHT_TODAYLINK = 0x00030000, - MCHT_TITLEBK = (0x00010000), - MCHT_TITLEMONTH = (0x00010000 | 0x0001), - MCHT_TITLEYEAR = (0x00010000 | 0x0002), - MCHT_TITLEBTNNEXT = (0x00010000 | 0x01000000 | 0x0003), - MCHT_TITLEBTNPREV = (0x00010000 | 0x02000000 | 0x0003), - MCHT_CALENDARBK = (0x00020000), - MCHT_CALENDARDATE = (0x00020000 | 0x0001), - MCHT_CALENDARDATENEXT = ((0x00020000 | 0x0001) | 0x01000000), - MCHT_CALENDARDATEPREV = ((0x00020000 | 0x0001) | 0x02000000), - MCHT_CALENDARDAY = (0x00020000 | 0x0002), - MCHT_CALENDARWEEKNUM = (0x00020000 | 0x0003), - MCSC_TEXT = 1, - MCSC_TITLEBK = 2, - MCSC_TITLETEXT = 3, - MCSC_MONTHBK = 4, - MCSC_TRAILINGTEXT = 5, + MCN_VIEWCHANGE = (0 - 750), // MCN_SELECT -4 - give state of calendar view MCN_SELCHANGE = ((0 - 750) + 1), MCN_GETDAYSTATE = ((0 - 750) + 3), MCN_SELECT = ((0 - 750) + 4), - MCS_DAYSTATE = 0x0001, - MCS_MULTISELECT = 0x0002, - MCS_WEEKNUMBERS = 0x0004, - MCS_NOTODAYCIRCLE = 0x0008, - MCS_NOTODAY = 0x0010, + MSAA_MENU_SIG = (unchecked((int)0xAA0DF00D)); + public const int NIM_ADD = 0x00000000, NIM_MODIFY = 0x00000001, NIM_DELETE = 0x00000002, @@ -2707,27 +2674,6 @@ public class Ole public const int PICTYPE_ENHMETAFILE = 4; } - [StructLayout(LayoutKind.Sequential)] - public class SYSTEMTIME - { - public short wYear; - public short wMonth; - public short wDayOfWeek; - public short wDay; - public short wHour; - public short wMinute; - public short wSecond; - public short wMilliseconds; - - public override string ToString() - { - return "[SYSTEMTIME: " - + wDay.ToString(CultureInfo.InvariantCulture) + "/" + wMonth.ToString(CultureInfo.InvariantCulture) + "/" + wYear.ToString(CultureInfo.InvariantCulture) - + " " + wHour.ToString(CultureInfo.InvariantCulture) + ":" + wMinute.ToString(CultureInfo.InvariantCulture) + ":" + wSecond.ToString(CultureInfo.InvariantCulture) - + "]"; - } - } - [StructLayout(LayoutKind.Sequential)] public class COMRECT { @@ -3745,36 +3691,19 @@ public struct NMCUSTOMDRAW public IntPtr lItemlParam; } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public class MCHITTESTINFO - { - public int cbSize = Marshal.SizeOf(); - public int pt_x = 0; - public int pt_y = 0; - public int uHit = 0; - public short st_wYear = 0; - public short st_wMonth = 0; - public short st_wDayOfWeek = 0; - public short st_wDay = 0; - public short st_wHour = 0; - public short st_wMinute = 0; - public short st_wSecond = 0; - public short st_wMilliseconds = 0; - } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class NMSELCHANGE { public NMHDR nmhdr; - public SYSTEMTIME stSelStart = null; - public SYSTEMTIME stSelEnd = null; + public Interop.Kernel32.SYSTEMTIME stSelStart; + public Interop.Kernel32.SYSTEMTIME stSelEnd; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class NMDAYSTATE { public NMHDR nmhdr; - public SYSTEMTIME stStart = null; + public Interop.Kernel32.SYSTEMTIME stStart; public int cDayState = 0; public IntPtr prgDayState; } @@ -4033,7 +3962,7 @@ public class NMDATETIMECHANGE { public NMHDR nmhdr; public int dwFlags = 0; - public SYSTEMTIME st = null; + public Interop.Kernel32.SYSTEMTIME st; } [StructLayout(LayoutKind.Sequential)] @@ -4093,6 +4022,8 @@ public struct HARDWAREINPUT public short wParamH; } + public const int INPUT_MOUSE = 0; + [StructLayout(LayoutKind.Sequential)] public struct INPUT { diff --git a/src/Common/src/UnsafeNativeMethods.cs b/src/Common/src/UnsafeNativeMethods.cs index bcd7a32c855..a8c89992027 100644 --- a/src/Common/src/UnsafeNativeMethods.cs +++ b/src/Common/src/UnsafeNativeMethods.cs @@ -316,6 +316,9 @@ public static StringBuilder GetModuleFileNameLongPath(HandleRef hModule) [DllImport(ExternDll.User32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] public static extern uint SendInput(uint nInputs, NativeMethods.INPUT[] pInputs, int cbSize); + [DllImport(ExternDll.User32, SetLastError = true)] + internal static extern int SendInput(int nInputs, ref NativeMethods.INPUT input, int cbSize); + #endregion [DllImport(ExternDll.User32, ExactSpelling = true)] @@ -568,10 +571,10 @@ public static StringBuilder GetModuleFileNameLongPath(HandleRef hModule) // For MonthCalendar // [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, NativeMethods.MCHITTESTINFO lParam); + public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref Interop.ComCtl32.MCHITTESTINFO lParam); [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, NativeMethods.SYSTEMTIME lParam); + public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref Interop.Kernel32.SYSTEMTIME lParam); [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, NativeMethods.SYSTEMTIMEARRAY lParam); @@ -1110,8 +1113,8 @@ int GetExtendedControl( [PreserveSig] Interop.HRESULT TransformCoords( - Point *pPtlHimetric, - PointF *pPtfContainer, + Point* pPtlHimetric, + PointF* pPtfContainer, uint dwFlags); [PreserveSig] @@ -2832,7 +2835,7 @@ Interop.HRESULT GetExtent( uint dwDrawAspect, int lindex, NativeMethods.tagDVTARGETDEVICE ptd, - Size *lpsizel); + Size* lpsizel); } [ComImport(), Guid("0000010C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] @@ -4694,5 +4697,8 @@ public interface IScrollItemProvider /// void ScrollIntoView(); } + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)] + internal static extern bool GetPhysicalCursorPos([In, Out] ref Interop.POINT pt); } } diff --git a/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj b/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj index d935ace9788..372cdae3327 100644 --- a/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj +++ b/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj @@ -44,10 +44,15 @@ + + + + + @@ -55,6 +60,7 @@ + diff --git a/src/System.Windows.Forms/src/Resources/SR.resx b/src/System.Windows.Forms/src/Resources/SR.resx index c361074b762..8768e3d9f78 100644 --- a/src/System.Windows.Forms/src/Resources/SR.resx +++ b/src/System.Windows.Forms/src/Resources/SR.resx @@ -4511,6 +4511,9 @@ Stack trace where the illegal operation occurred was: Indicates which annual dates should be boldface. + + Calendar body + The number of rows and columns of months in a month calendar. @@ -4541,12 +4544,18 @@ Stack trace where the illegal operation occurred was: Indicates which monthly dates to bold. + + Next + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Occurs when the user selects a date or a range of dates. + + Previous + Unable to set the MonthCalendar range from {0} to {1}. @@ -4580,6 +4589,9 @@ Stack trace where the illegal operation occurred was: The color used to display text within the calendar's title. + + Today: {0} + The current day. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf index 86ea6478f3f..6d7fda9be24 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf @@ -7481,6 +7481,11 @@ Trasování zásobníku, kde došlo k neplatné operaci: Určuje, která data v rámci roku mají být zobrazena tučně. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Počet řádků a sloupců měsíců v měsíčním kalendáři. @@ -7531,6 +7536,11 @@ Trasování zásobníku, kde došlo k neplatné operaci: Určuje, která data v rámci měsíce mají být zobrazena tučně. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Vyvolá se v případě, že se rozsah dat změní z důvodu výběru uživatele nebo prostřednictvím přechodu na další nebo předchozí měsíc. @@ -7541,6 +7551,11 @@ Trasování zásobníku, kde došlo k neplatné operaci: Vyvolá se v případě, že uživatel vybere datum nebo rozsah dat. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Rozsah objektu MonthCalendar nelze nastavit od {0} do {1}. @@ -7616,6 +7631,11 @@ Trasování zásobníku, kde došlo k neplatné operaci: Barva pozadí použitá k zobrazení textu v nadpisu kalendáře. + + Today: {0} + Today: {0} + + The current day. Aktuální den diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf index e889c39c5f1..6ed0b5852f9 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf @@ -7481,6 +7481,11 @@ Stapelüberwachung, in der der unzulässige Vorgang auftrat: Gibt an, welche jährlichen Tage fett angezeigt werden sollen. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Die Anzahl der Spalten und Zeilen von Monaten in einem Monatskalender. @@ -7531,6 +7536,11 @@ Stapelüberwachung, in der der unzulässige Vorgang auftrat: Gibt an, welche monatlichen Daten fett angezeigt werden sollen. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Tritt ein, wenn sich der Datumsbereich aufgrund einer Benutzerauswahl oder einer Navigation zum nächsten oder vorherigen Monat ändert. @@ -7541,6 +7551,11 @@ Stapelüberwachung, in der der unzulässige Vorgang auftrat: Tritt ein, wenn der Benutzer ein Datum oder einen Datumsbereich auswählt. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Der MonthCalendar-Bereich kann nicht auf {0} bis {1} festgelegt werden. @@ -7616,6 +7631,11 @@ Stapelüberwachung, in der der unzulässige Vorgang auftrat: Die Farbe, in der der Text in der Kalenderüberschrift angezeigt wird. + + Today: {0} + Today: {0} + + The current day. Der aktuelle Tag. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf index 3a7e21ada46..22274f5b853 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf @@ -7481,6 +7481,11 @@ El seguimiento de la pila donde tuvo lugar la operación no válida fue: Indica qué fechas anuales se deben poner en negrita. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Número de filas y columnas de meses en un calendario mensual. @@ -7531,6 +7536,11 @@ El seguimiento de la pila donde tuvo lugar la operación no válida fue: Indica qué fechas mensuales deben aparecer en negrita. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Tiene lugar cuando cambia el intervalo de fechas debido a una selección del usuario, o por navegación al mes anterior o posterior. @@ -7541,6 +7551,11 @@ El seguimiento de la pila donde tuvo lugar la operación no válida fue: Tiene lugar cuando el usuario selecciona una fecha o intervalo de fechas. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. No se puede establecer el intervalo del elemento MonthCalendar entre {0} y {1}. @@ -7616,6 +7631,11 @@ El seguimiento de la pila donde tuvo lugar la operación no válida fue: Color utilizado para mostrar texto en el título del calendario. + + Today: {0} + Today: {0} + + The current day. Día actual. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf index 36e25c88ec6..1725c6476fb 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf @@ -7481,6 +7481,11 @@ Cette opération non conforme s'est produite sur la trace de la pile : Indique les dates annuelles à mettre en gras. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Le nombre de lignes et de colonnes de mois dans un calendrier mensuel. @@ -7531,6 +7536,11 @@ Cette opération non conforme s'est produite sur la trace de la pile : Indique les dates mensuelles à mettre en gras. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Se produit lorsque la plage de dates change en raison d'une sélection de l'utilisateur ou lors de l'utilisation de la navigation entre les mois. @@ -7541,6 +7551,11 @@ Cette opération non conforme s'est produite sur la trace de la pile : Se produit lorsqu'un utilisateur sélectionne une date ou une plage de dates. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Impossible de définir la plage MonthCalendar de {0} à {1}. @@ -7616,6 +7631,11 @@ Cette opération non conforme s'est produite sur la trace de la pile : La couleur utilisée pour afficher le texte dans le titre du calendrier. + + Today: {0} + Today: {0} + + The current day. Le jour actuel. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf index ac861493d42..a9eb773e9ce 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf @@ -7481,6 +7481,11 @@ Traccia dello stack da cui si è verificata l'operazione non valida: Indica le date dell'anno da visualizzare in grassetto. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Numero di righe e colonne dei mesi in un calendario mensile. @@ -7531,6 +7536,11 @@ Traccia dello stack da cui si è verificata l'operazione non valida: Indica le date mensili da visualizzare in grassetto. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Generato quando l'intervallo delle date cambia in seguito alla selezione dell'utente o alla navigazione al mese precedente o successivo. @@ -7541,6 +7551,11 @@ Traccia dello stack da cui si è verificata l'operazione non valida: Generato quando l'utente seleziona una data o un intervallo di date. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Impossibile impostare l'intervallo di MonthCalendar da {0} a {1}. @@ -7616,6 +7631,11 @@ Traccia dello stack da cui si è verificata l'operazione non valida: Colore utilizzato per visualizzare il testo del titolo del calendario. + + Today: {0} + Today: {0} + + The current day. La data odierna. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf index f9eb1adb976..16c293aeab7 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf @@ -7481,6 +7481,11 @@ Stack trace where the illegal operation occurred was: 年間のどの日付を太字にするかを示します。 + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. 月表示カレンダーの月の行と列の数です。 @@ -7531,6 +7536,11 @@ Stack trace where the illegal operation occurred was: 月ごとに太字で表示する日付を示します。 + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. ユーザーの選択、または翌/先月の変更により、日にちの範囲が変更されたときに発生します。 @@ -7541,6 +7551,11 @@ Stack trace where the illegal operation occurred was: ユーザーがある日付を選択したとき、または日数の範囲を指定したときに発生します。 + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. MonthCalendar の範囲を {0} から {1} に設定できません。 @@ -7616,6 +7631,11 @@ Stack trace where the illegal operation occurred was: カレンダーの表題内のテキストの色です。 + + Today: {0} + Today: {0} + + The current day. 現在の日です。 diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf index 3d56ca01edd..d35c34c5a4a 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf @@ -7481,6 +7481,11 @@ Stack trace where the illegal operation occurred was: 매년 굵게 표시할 날짜를 나타냅니다. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. 달력에서 달의 행 및 열 개수입니다. @@ -7531,6 +7536,11 @@ Stack trace where the illegal operation occurred was: 매월 굵게 표시할 날짜를 나타냅니다. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. 사용자 선택이나 달 탐색으로 인해 날짜 범위가 변경될 때 발생합니다. @@ -7541,6 +7551,11 @@ Stack trace where the illegal operation occurred was: 날짜 또는 날짜 범위를 선택할 때 발생합니다. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. MonthCalendar의 범위를 {0}에서 {1} 사이로 설정할 수 없습니다. @@ -7616,6 +7631,11 @@ Stack trace where the illegal operation occurred was: 달력 제목의 텍스트를 표시하는 데 사용할 색입니다. + + Today: {0} + Today: {0} + + The current day. 현재 날짜입니다. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf index 897c72a4910..b82077fa54b 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf @@ -7481,6 +7481,11 @@ Stos śledzenia, w którym wystąpiła zabroniona operacja: Wskazuje, które daty lat mają być pogrubione. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Liczba wierszy i kolumn miesięcy w kalendarzu miesięcznym. @@ -7531,6 +7536,11 @@ Stos śledzenia, w którym wystąpiła zabroniona operacja: Wskazuje, które dni miesiąca mają zostać pogrubione. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Występuje, gdy zakres dat zmieni się w wyniku zaznaczenia przez użytkownika lub przez nawigację do następnego/poprzedniego miesiąca. @@ -7541,6 +7551,11 @@ Stos śledzenia, w którym wystąpiła zabroniona operacja: Występuje, gdy użytkownik zaznaczy datę lub zakres dat. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Nie można ustawić zakresu formantu MonthCalendar od {0} do {1}. @@ -7616,6 +7631,11 @@ Stos śledzenia, w którym wystąpiła zabroniona operacja: Kolor używany do wyświetlania tekstu w tytule kalendarza. + + Today: {0} + Today: {0} + + The current day. Bieżący dzień. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf index ffc28652938..450da311f21 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf @@ -7481,6 +7481,11 @@ Rastreamento de pilha em que a operação ilegal ocorreu: Indica as datas do ano que devem ser exibidas em negrito. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. O número de linhas e colunas dos meses em um calendário mensal. @@ -7531,6 +7536,11 @@ Rastreamento de pilha em que a operação ilegal ocorreu: Indica as datas mensais que devem ser exibidas em negrito. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Ocorre quando o intervalo de datas é alterado devido à seleção de usuário ou através de navegação para o mês seguinte/anterior. @@ -7541,6 +7551,11 @@ Rastreamento de pilha em que a operação ilegal ocorreu: Ocorre quando o usuário seleciona uma data ou um intervalo de datas. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Não é possível definir o intervalo de MonthCalendar de {0} a {1}. @@ -7616,6 +7631,11 @@ Rastreamento de pilha em que a operação ilegal ocorreu: A cor usada para exibir texto no título do calendário. + + Today: {0} + Today: {0} + + The current day. O dia atual. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf index ad57689dd7d..6bdc33c51b0 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf @@ -7482,6 +7482,11 @@ Stack trace where the illegal operation occurred was: Показывает, будут ли даты отображаться жирным шрифтом. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Число строк и столбцов для месяца в месячном календаре. @@ -7532,6 +7537,11 @@ Stack trace where the illegal operation occurred was: Указывает, какие числа месяца выделять жирным шрифтом. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Происходит при изменении пользователем выбранного диапазона дат путем выделения или выбора предыдущего/следующего месяца. @@ -7542,6 +7552,11 @@ Stack trace where the illegal operation occurred was: Происходит при выборе пользователем даты или диапазона дат. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. Невозможно установить диапазон MonthCalendar от {0} до {1}. @@ -7617,6 +7632,11 @@ Stack trace where the illegal operation occurred was: Цвет для отображения текста в заглавии календаря. + + Today: {0} + Today: {0} + + The current day. Текущая дата. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf index 323556ca24b..5cef44e49f3 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf @@ -7481,6 +7481,11 @@ Geçersiz işlemin gerçekleştiği yığın izi: Yıl içinde hangi tarihlerin kalın görüntülenmesi gerektiğini gösterir. + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. Aylık takvimde ayların gösterileceği satır ve sütun sayısı. @@ -7531,6 +7536,11 @@ Geçersiz işlemin gerçekleştiği yığın izi: Ayın hangi günlerinin kalın görüntüleneceğini gösterir. + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. Kullanıcı seçimi veya takvimde önceki/sonraki aya gitme dolayısıyla tarih aralıkları değiştiğinde gerçekleşir. @@ -7541,6 +7551,11 @@ Geçersiz işlemin gerçekleştiği yığın izi: Kullanıcı bir tarih veya tarih aralığı seçtiğinde gerçekleşir. + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. MonthCalendar aralığı {0} değerinden {1} değerine ayarlanamıyor. @@ -7616,6 +7631,11 @@ Geçersiz işlemin gerçekleştiği yığın izi: Takvim başlığında metin görüntülemek için kullanılan renk. + + Today: {0} + Today: {0} + + The current day. Geçerli gün. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf index a6c1e634abf..063940c042d 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf @@ -7481,6 +7481,11 @@ Stack trace where the illegal operation occurred was: 指示一年中用粗体显示的日期。 + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. 月历中各月的行数和列数。 @@ -7531,6 +7536,11 @@ Stack trace where the illegal operation occurred was: 指示一月中要用粗体显示的日期。 + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. 在因用户选择或通过下个月/上个月导航而导致日期范围更改时发生。 @@ -7541,6 +7551,11 @@ Stack trace where the illegal operation occurred was: 在用户选择日期或日期范围时发生。 + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. 无法将 MonthCalendar 的范围设置为从 {0} 到 {1}。 @@ -7616,6 +7631,11 @@ Stack trace where the illegal operation occurred was: 用于显示日历标题中文本的颜色。 + + Today: {0} + Today: {0} + + The current day. 当前日期。 diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf index d4aa77b81b0..49c1c6f74c1 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf @@ -7481,6 +7481,11 @@ Stack trace where the illegal operation occurred was: 表示要以粗體表示一年之中的哪些日期。 + + Calendar body + Calendar body + + The number of rows and columns of months in a month calendar. 月曆中月份欄和列的數目。 @@ -7531,6 +7536,11 @@ Stack trace where the illegal operation occurred was: 要以粗體表示一月之中的哪些日期。 + + Next + Next + + Occurs when the range of dates changes due to user selection, or through next/previous month navigation. 當因為使用者選取或透過下個月/上個月巡覽所造成日期範圍變更時發生。 @@ -7541,6 +7551,11 @@ Stack trace where the illegal operation occurred was: 當使用者選取日期或日期範圍時發生。 + + Previous + Previous + + Unable to set the MonthCalendar range from {0} to {1}. 無法將 MonthCalendar 的範圍設為從 {0} 到 {1}。 @@ -7616,6 +7631,11 @@ Stack trace where the illegal operation occurred was: 用來顯示日曆標題內文字的色彩。 + + Today: {0} + Today: {0} + + The current day. 目前的日期。 diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs index 71aaffa9867..d474ae2eaf6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs @@ -221,7 +221,7 @@ public Color CalendarForeColor if (!value.Equals(calendarForeColor)) { calendarForeColor = value; - SetControlColor(NativeMethods.MCSC_TEXT, value); + SetControlColor(ComCtl32.MCSC.TEXT, value); } } } @@ -300,7 +300,7 @@ public Color CalendarTitleBackColor if (!value.Equals(calendarTitleBackColor)) { calendarTitleBackColor = value; - SetControlColor(NativeMethods.MCSC_TITLEBK, value); + SetControlColor(ComCtl32.MCSC.TITLEBK, value); } } } @@ -329,7 +329,7 @@ public Color CalendarTitleForeColor if (!value.Equals(calendarTitleForeColor)) { calendarTitleForeColor = value; - SetControlColor(NativeMethods.MCSC_TITLETEXT, value); + SetControlColor(ComCtl32.MCSC.TITLETEXT, value); } } } @@ -358,7 +358,7 @@ public Color CalendarTrailingForeColor if (!value.Equals(calendarTrailingText)) { calendarTrailingText = value; - SetControlColor(NativeMethods.MCSC_TRAILINGTEXT, value); + SetControlColor(ComCtl32.MCSC.TRAILINGTEXT, value); } } } @@ -387,7 +387,7 @@ public Color CalendarMonthBackground if (!value.Equals(calendarMonthBackground)) { calendarMonthBackground = value; - SetControlColor(NativeMethods.MCSC_MONTHBK, value); + SetControlColor(ComCtl32.MCSC.MONTHBK, value); } } } @@ -408,8 +408,8 @@ public bool Checked // the information from win32 DateTimePicker is reliable only when ShowCheckBoxes is True if (ShowCheckBox && IsHandleCreated) { - NativeMethods.SYSTEMTIME sys = new NativeMethods.SYSTEMTIME(); - int gdt = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_GETSYSTEMTIME, 0, sys); + Kernel32.SYSTEMTIME sys = new Kernel32.SYSTEMTIME(); + int gdt = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_GETSYSTEMTIME, 0, ref sys); return gdt == NativeMethods.GDT_VALID; } else @@ -427,14 +427,13 @@ public bool Checked if (value) { int gdt = NativeMethods.GDT_VALID; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(Value); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(Value); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, ref sys); } else { int gdt = NativeMethods.GDT_NONE; - NativeMethods.SYSTEMTIME sys = null; - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, IntPtr.Zero); } } // this.validTime is used when the DateTimePicker receives date time change notification @@ -1054,8 +1053,8 @@ public DateTime Value * get propagated to createHandle */ int gdt = NativeMethods.GDT_VALID; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(value); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(value); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, ref sys); } if (valueChanged) @@ -1151,14 +1150,13 @@ protected override void CreateHandle() * get propagated to setValue */ int gdt = NativeMethods.GDT_VALID; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(Value); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(Value); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, ref sys); } else if (!validTime) { int gdt = NativeMethods.GDT_NONE; - NativeMethods.SYSTEMTIME sys = null; - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, IntPtr.Zero); } if (format == DateTimePickerFormat.Custom) @@ -1386,8 +1384,8 @@ private void ResetValue() if (IsHandleCreated) { int gdt = NativeMethods.GDT_VALID; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(value); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, sys); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(value); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.DTM_SETSYSTEMTIME, gdt, ref sys); } // Updating Checked to false will set the control to "no date", @@ -1401,11 +1399,11 @@ private void ResetValue() /// /// If the handle has been created, this applies the color to the control /// - private void SetControlColor(int colorIndex, Color value) + private void SetControlColor(Interop.ComCtl32.MCSC colorIndex, Color value) { if (IsHandleCreated) { - SendMessage(NativeMethods.DTM_SETMCCOLOR, colorIndex, ColorTranslator.ToWin32(value)); + SendMessage(NativeMethods.DTM_SETMCCOLOR, (int)colorIndex, ColorTranslator.ToWin32(value)); } } @@ -1425,11 +1423,11 @@ private void SetControlCalendarFont() /// private void SetAllControlColors() { - SetControlColor(NativeMethods.MCSC_MONTHBK, calendarMonthBackground); - SetControlColor(NativeMethods.MCSC_TEXT, calendarForeColor); - SetControlColor(NativeMethods.MCSC_TITLEBK, calendarTitleBackColor); - SetControlColor(NativeMethods.MCSC_TITLETEXT, calendarTitleForeColor); - SetControlColor(NativeMethods.MCSC_TRAILINGTEXT, calendarTrailingText); + SetControlColor(ComCtl32.MCSC.MONTHBK, calendarMonthBackground); + SetControlColor(ComCtl32.MCSC.TEXT, calendarForeColor); + SetControlColor(ComCtl32.MCSC.TITLEBK, calendarTitleBackColor); + SetControlColor(ComCtl32.MCSC.TITLETEXT, calendarTitleForeColor); + SetControlColor(ComCtl32.MCSC.TRAILINGTEXT, calendarTrailingText); } /// @@ -1450,7 +1448,7 @@ private void SetRange(DateTime min, DateTime max) NativeMethods.SYSTEMTIMEARRAY sa = new NativeMethods.SYSTEMTIMEARRAY(); flags |= NativeMethods.GDTR_MIN | NativeMethods.GDTR_MAX; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(min); + Kernel32.SYSTEMTIME sys = DateTimeToSysTime(min); sa.wYear1 = sys.wYear; sa.wMonth1 = sys.wMonth; sa.wDayOfWeek1 = sys.wDayOfWeek; @@ -1459,7 +1457,7 @@ private void SetRange(DateTime min, DateTime max) sa.wMinute1 = sys.wMinute; sa.wSecond1 = sys.wSecond; sa.wMilliseconds1 = sys.wMilliseconds; - sys = DateTimePicker.DateTimeToSysTime(max); + sys = DateTimeToSysTime(max); sa.wYear2 = sys.wYear; sa.wMonth2 = sys.wMonth; sa.wDayOfWeek2 = sys.wDayOfWeek; @@ -1747,9 +1745,9 @@ protected override void WndProc(ref Message m) /// Takes a DateTime value and returns a SYSTEMTIME struct /// Note: 1 second granularity /// - internal static NativeMethods.SYSTEMTIME DateTimeToSysTime(DateTime time) + internal static Kernel32.SYSTEMTIME DateTimeToSysTime(DateTime time) { - NativeMethods.SYSTEMTIME sys = new NativeMethods.SYSTEMTIME + Kernel32.SYSTEMTIME sys = new Kernel32.SYSTEMTIME { wYear = (short)time.Year, wMonth = (short)time.Month, @@ -1767,7 +1765,7 @@ internal static NativeMethods.SYSTEMTIME DateTimeToSysTime(DateTime time) /// Takes a SYSTEMTIME struct and returns a DateTime value /// Note: 1 second granularity. /// - internal static DateTime SysTimeToDateTime(NativeMethods.SYSTEMTIME s) + internal static DateTime SysTimeToDateTime(Kernel32.SYSTEMTIME s) { return new DateTime(s.wYear, s.wMonth, s.wDay, s.wHour, s.wMinute, s.wSecond); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarBodyAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarBodyAccessibleObject.cs new file mode 100644 index 00000000000..eee7e774721 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarBodyAccessibleObject.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + /// + /// Represents the calendar body accessible object. + /// + internal class CalendarBodyAccessibleObject : CalendarChildAccessibleObject + { + private const int ChildId = 4; + + public CalendarBodyAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex) + : base(calendarAccessibleObject, calendarIndex, CalendarChildType.CalendarBody) + { + } + + protected override RECT CalculateBoundingRectangle() + { + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, ComCtl32.MCGIP.CALENDARBODY, 0, 0, out RECT calendarPartRectangle); + return calendarPartRectangle; + } + + internal override int GetChildId() => ChildId; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.NextSibling => new Func(() => + { + MonthCalendar owner = (MonthCalendar)_calendarAccessibleObject.Owner; + return owner.ShowToday ? _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.TodayLink) : null; + })(), + UnsafeNativeMethods.NavigateDirection.PreviousSibling => _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarHeader), + UnsafeNativeMethods.NavigateDirection.FirstChild => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, _calendarAccessibleObject.HasHeaderRow ? -1 : 0), + UnsafeNativeMethods.NavigateDirection.LastChild => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, _calendarAccessibleObject.RowCount - 1), + _ => base.FragmentNavigate(direction), + + }; + + public CalendarChildAccessibleObject GetFromPoint(ComCtl32.MCHITTESTINFO hitTestInfo) + { + switch ((ComCtl32.MCHT)hitTestInfo.uHit) + { + case ComCtl32.MCHT.CALENDARDAY: + case ComCtl32.MCHT.CALENDARWEEKNUM: + case ComCtl32.MCHT.CALENDARDATE: + AccessibleObject rowAccessibleObject = + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, hitTestInfo.iRow); + return _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, hitTestInfo.iCol); + } + + return this; + } + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_NamePropertyId => SR.MonthCalendarBodyAccessibleName, + NativeMethods.UIA_IsGridPatternAvailablePropertyId => true, + NativeMethods.UIA_IsTablePatternAvailablePropertyId => true, + _ => base.GetPropertyValue(propertyID) + }; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonAccessibleObject.cs new file mode 100644 index 00000000000..d6da1040dfb --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonAccessibleObject.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal abstract class CalendarButtonAccessibleObject : CalendarChildAccessibleObject + { + public CalendarButtonAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarButtonType buttonType) + : base(calendarAccessibleObject, calendarIndex, (CalendarChildType)buttonType) + { + } + + protected abstract CalendarButtonType ButtonType { get; } + + protected override RECT CalculateBoundingRectangle() + { + ComCtl32.MCGIP dwPart; + switch (ButtonType) + { + case CalendarButtonType.Previous: + dwPart = ComCtl32.MCGIP.PREV; + break; + + case CalendarButtonType.Next: + dwPart = ComCtl32.MCGIP.NEXT; + break; + + default: + return new RECT(); + } + + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, dwPart, -1, -1, out RECT rectangle); + return rectangle; + } + + internal override bool IsPatternSupported(int patternId) => + (patternId == NativeMethods.UIA_InvokePatternId) || base.IsPatternSupported(patternId); + + internal override void Invoke() => RaiseMouseClick(); + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonType.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonType.cs new file mode 100644 index 00000000000..f87c88e4633 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarButtonType.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal enum CalendarButtonType + { + Next = 1, + Previous = 2 + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarCellAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarCellAccessibleObject.cs new file mode 100644 index 00000000000..e59038a7032 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarCellAccessibleObject.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + /// + /// Represents the calendar cell accessible object. + /// + internal class CalendarCellAccessibleObject : CalendarGridChildAccessibleObject + { + private int _rowIndex; + private int _columnIndex; + private string _name; + + public CalendarCellAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, AccessibleObject parentAccessibleObject, int rowIndex, int columnIndex, string name) + : base(calendarAccessibleObject, calendarIndex, CalendarChildType.CalendarCell, parentAccessibleObject, rowIndex * columnIndex) + { + _rowIndex = rowIndex; + _columnIndex = columnIndex; + _name = name; + } + + public override string Name => _name; + + internal override int Row => _rowIndex; + + internal override int Column => _columnIndex; + + internal override UnsafeNativeMethods.IRawElementProviderSimple ContainingGrid => _calendarAccessibleObject; + + internal override int[] RuntimeId => + new int[5] + { + RuntimeIDFirstItem, + _calendarAccessibleObject.Owner.Handle.ToInt32(), + Parent.Parent.GetChildId(), + Parent.GetChildId(), + GetChildId() + }; + + protected override RECT CalculateBoundingRectangle() + { + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, ComCtl32.MCGIP.CALENDARCELL, _rowIndex, _columnIndex, out RECT rectangle); + return rectangle; + } + + internal override int GetChildId() => _columnIndex + 1; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.Parent => _parentAccessibleObject, + UnsafeNativeMethods.NavigateDirection.NextSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, _parentAccessibleObject, _columnIndex + 1), + UnsafeNativeMethods.NavigateDirection.PreviousSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, _parentAccessibleObject, _columnIndex - 1), + _ => base.FragmentNavigate(direction) + }; + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_ControlTypePropertyId => + (_rowIndex == -1) ? NativeMethods.UIA_HeaderControlTypeId : NativeMethods.UIA_DataItemControlTypeId, + NativeMethods.UIA_NamePropertyId => Name, + var p when + p == NativeMethods.UIA_HasKeyboardFocusPropertyId || + p == NativeMethods.UIA_IsGridItemPatternAvailablePropertyId || + p == NativeMethods.UIA_IsTableItemPatternAvailablePropertyId => true, + _ => base.GetPropertyValue(propertyID) + }; + + internal override bool IsPatternSupported(int patternId) => + patternId switch + { + var p when + p == NativeMethods.UIA_GridItemPatternId || + p == NativeMethods.UIA_InvokePatternId || + p == NativeMethods.UIA_TableItemPatternId => true, + _ => base.IsPatternSupported(patternId) + }; + + internal override void Invoke() + { + RaiseMouseClick(); + } + + internal override UnsafeNativeMethods.IRawElementProviderSimple[] GetRowHeaderItems() => null; + + internal override UnsafeNativeMethods.IRawElementProviderSimple[] GetColumnHeaderItems() + { + if (!_calendarAccessibleObject.HasHeaderRow) + { + return null; + } + + AccessibleObject headerRowAccessibleObject = + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, _parentAccessibleObject.Parent, -1); + AccessibleObject headerCellAccessibleObject = + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, headerRowAccessibleObject, _columnIndex); + + return new UnsafeNativeMethods.IRawElementProviderSimple[1] { headerCellAccessibleObject }; + } + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildAccessibleObject.cs new file mode 100644 index 00000000000..a601d49dc10 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildAccessibleObject.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Runtime.InteropServices; +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + /// + /// Represents the calendar child accessible object. + /// + internal abstract class CalendarChildAccessibleObject : AccessibleObject + { + protected MonthCalendarAccessibleObject _calendarAccessibleObject; + protected int _calendarIndex; + protected CalendarChildType _itemType; + + public CalendarChildAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarChildType itemType) + { + _calendarAccessibleObject = calendarAccessibleObject; + _calendarIndex = calendarIndex; + _itemType = itemType; + } + + internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRoot => _calendarAccessibleObject; + + public override AccessibleObject Parent => _calendarAccessibleObject; + + internal override Rectangle BoundingRectangle => CalculateBoundingRectangle(); + + protected virtual RECT CalculateBoundingRectangle() => new RECT(); + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.Parent => Parent, + _ => base.FragmentNavigate(direction) + }; + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_IsEnabledPropertyId => _calendarAccessibleObject.Enabled, + _ => base.GetPropertyValue(propertyID) + }; + + internal override int[] RuntimeId => + new int[] + { + RuntimeIDFirstItem, + _calendarAccessibleObject.Owner.Handle.ToInt32(), + GetChildId() + }; + + public void RaiseMouseClick() + { + // Make sure that the control is enabled. + if (!SafeNativeMethods.IsWindowEnabled(new HandleRef(null, _calendarAccessibleObject.Owner.Handle))) + { + return; + } + + var rectangle = CalculateBoundingRectangle(); + int x = rectangle.left + ((rectangle.right - rectangle.left) / 2); + int y = rectangle.top + ((rectangle.bottom - rectangle.top) / 2); + + _calendarAccessibleObject.RaiseMouseClick(x, y); + } + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildType.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildType.cs new file mode 100644 index 00000000000..f4f26546520 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildType.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal enum CalendarChildType + { + Undefined = -1, + NextButton = 1, + PreviousButton = 2, + Footer = 3, + Calendar = 4, + CalendarHeader = 5, + CalendarBody = 6, + CalendarRow = 7, + CalendarCell = 8, + TodayLink = 9 + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarGridChildAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarGridChildAccessibleObject.cs new file mode 100644 index 00000000000..d216e2ce86d --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarGridChildAccessibleObject.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + /// + /// Represents the calendar grid child accessible object. + /// + internal abstract class CalendarGridChildAccessibleObject : CalendarChildAccessibleObject + { + protected AccessibleObject _parentAccessibleObject; + + public CalendarGridChildAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarChildType itemType, + AccessibleObject parentAccessibleObject, int itemIndex) : base(calendarAccessibleObject, calendarIndex, itemType) + { + _parentAccessibleObject = parentAccessibleObject; + } + + public override AccessibleObject Parent => _parentAccessibleObject; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarHeaderAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarHeaderAccessibleObject.cs new file mode 100644 index 00000000000..0dc37df2732 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarHeaderAccessibleObject.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal class CalendarHeaderAccessibleObject : CalendarChildAccessibleObject + { + private const int ChildId = 3; + + public CalendarHeaderAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex) + : base(calendarAccessibleObject, calendarIndex, CalendarChildType.CalendarHeader) + { + } + + public override string Name => _calendarAccessibleObject.GetCalendarChildName(_calendarIndex, CalendarChildType.CalendarHeader); + + internal override int GetChildId() => ChildId; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.PreviousSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.NextButton), + UnsafeNativeMethods.NavigateDirection.NextSibling => _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody), + _ => base.FragmentNavigate(direction) + }; + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_ControlTypePropertyId => NativeMethods.UIA_ButtonControlTypeId, + NativeMethods.UIA_NamePropertyId => Name, + _ => base.GetPropertyValue(propertyID) + }; + + protected override RECT CalculateBoundingRectangle() + { + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, ComCtl32.MCGIP.CALENDARHEADER, -1, -1, out RECT rectangle); + return rectangle; + } + + internal override bool IsPatternSupported(int patternId) => (patternId == NativeMethods.UIA_InvokePatternId) || base.IsPatternSupported(patternId); + + internal override void Invoke() => RaiseMouseClick(); + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarNextButtonAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarNextButtonAccessibleObject.cs new file mode 100644 index 00000000000..08b103cb47c --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarNextButtonAccessibleObject.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal class CalendarNextButtonAccessibleObject : CalendarButtonAccessibleObject + { + private const int ChildId = 2; + + public CalendarNextButtonAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex) + : base(calendarAccessibleObject, calendarIndex, CalendarButtonType.Next) + { + } + + protected override CalendarButtonType ButtonType => CalendarButtonType.Next; + + internal override int GetChildId() => ChildId; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.PreviousSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.PreviousButton), + UnsafeNativeMethods.NavigateDirection.NextSibling => _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarHeader), + _ => base.FragmentNavigate(direction) + }; + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_BoundingRectanglePropertyId => BoundingRectangle, + NativeMethods.UIA_ControlTypePropertyId => NativeMethods.UIA_ButtonControlTypeId, + NativeMethods.UIA_NamePropertyId => SR.MonthCalendarNextButtonAccessibleName, + _ => base.GetPropertyValue(propertyID) + }; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarPreviousButtonAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarPreviousButtonAccessibleObject.cs new file mode 100644 index 00000000000..9da0575b570 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarPreviousButtonAccessibleObject.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal class CalendarPreviousButtonAccessibleObject : CalendarButtonAccessibleObject + { + private const int ChildId = 1; + + public CalendarPreviousButtonAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex) + : base(calendarAccessibleObject, calendarIndex, CalendarButtonType.Previous) + { + } + + protected override CalendarButtonType ButtonType => CalendarButtonType.Previous; + + internal override int GetChildId() => ChildId; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.NextSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.NextButton), + _ => base.FragmentNavigate(direction) + }; + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_BoundingRectanglePropertyId => BoundingRectangle, + NativeMethods.UIA_ControlTypePropertyId => NativeMethods.UIA_ButtonControlTypeId, + NativeMethods.UIA_NamePropertyId => SR.MonthCalendarPreviousButtonAccessibleName, + _ => base.GetPropertyValue(propertyID) + }; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarRowAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarRowAccessibleObject.cs new file mode 100644 index 00000000000..a901182ba32 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarRowAccessibleObject.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal class CalendarRowAccessibleObject : CalendarGridChildAccessibleObject + { + int _rowIndex; + + public CalendarRowAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarBodyAccessibleObject parentAccessibleObject, int rowIndex) + : base(calendarAccessibleObject, calendarIndex, CalendarChildType.CalendarRow, parentAccessibleObject, rowIndex) + { + _rowIndex = rowIndex; + } + + public int RowIndex => _rowIndex; + + internal override int[] RuntimeId => + new int[4] + { + RuntimeIDFirstItem, + _calendarAccessibleObject.Owner.Handle.ToInt32(), + Parent.GetChildId(), + GetChildId() + }; + + protected override RECT CalculateBoundingRectangle() + { + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, ComCtl32.MCGIP.CALENDARROW, _rowIndex, -1, out RECT calendarPartRectangle); + return calendarPartRectangle; + } + + internal override int GetChildId() => _rowIndex + 1; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.NextSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, _parentAccessibleObject, _rowIndex + 1), + UnsafeNativeMethods.NavigateDirection.PreviousSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, _parentAccessibleObject, _rowIndex - 1), + UnsafeNativeMethods.NavigateDirection.FirstChild => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, this, 0), + UnsafeNativeMethods.NavigateDirection.LastChild => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, this, _calendarAccessibleObject.ColumnCount - 1), + _ => base.FragmentNavigate(direction) + }; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarTodayLinkAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarTodayLinkAccessibleObject.cs new file mode 100644 index 00000000000..2ae48a135c6 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarTodayLinkAccessibleObject.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + internal class CalendarTodayLinkAccessibleObject : CalendarChildAccessibleObject + { + private const int ChildId = 5; + + public CalendarTodayLinkAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarChildType type) + : base(calendarAccessibleObject, calendarIndex, CalendarChildType.TodayLink) + { + } + + protected override RECT CalculateBoundingRectangle() + { + _calendarAccessibleObject.GetCalendarPartRectangle(_calendarIndex, ComCtl32.MCGIP.FOOTER, -1, -1, out RECT calendarPartRectangle); + return calendarPartRectangle; + } + + internal override int GetChildId() => ChildId; + + internal override bool IsPatternSupported(int patternId) => + (patternId == NativeMethods.UIA_InvokePatternId) || base.IsPatternSupported(patternId); + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_BoundingRectanglePropertyId => BoundingRectangle, + NativeMethods.UIA_ControlTypePropertyId => NativeMethods.UIA_ButtonControlTypeId, + NativeMethods.UIA_NamePropertyId => _calendarAccessibleObject.GetCalendarChildName(_calendarIndex, CalendarChildType.TodayLink), + _ => base.GetPropertyValue(propertyID) + }; + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) => + direction switch + { + UnsafeNativeMethods.NavigateDirection.PreviousSibling => + _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody), + _ => base.FragmentNavigate(direction) + }; + + internal override void Invoke() => RaiseMouseClick(); + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.MonthCalendarAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.MonthCalendarAccessibleObject.cs new file mode 100644 index 00000000000..711a616d12e --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.MonthCalendarAccessibleObject.cs @@ -0,0 +1,748 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Runtime.InteropServices; +using static Interop; + +namespace System.Windows.Forms +{ + public partial class MonthCalendar + { + [ComVisible(true)] + internal class MonthCalendarAccessibleObject : ControlAccessibleObject + { + internal const int MAX_DAYS = 7; + internal const int MAX_WEEKS = 6; + + private readonly MonthCalendar _owner; + private int _calendarIndex = 0; + private AccessibleObject _focused; + + public MonthCalendarAccessibleObject(Control owner) + : base(owner) + { + _owner = owner as MonthCalendar; + } + + public int ControlType => + string.IsNullOrEmpty(base.Name) ? NativeMethods.UIA_CalendarControlTypeId : NativeMethods.UIA_TableControlTypeId; + + public bool Enabled => _owner.Enabled; + + public bool HasHeaderRow + { + get + { + bool result = GetCalendarGridInfoText(ComCtl32.MCGIP.CALENDARCELL, _calendarIndex, -1, 0, out string text); + if (!result || string.IsNullOrEmpty(text)) + { + return false; + } + + return true; + } + } + + public override AccessibleRole Role => + (_owner?.AccessibleRole != AccessibleRole.Default) ? _owner.AccessibleRole : AccessibleRole.Table; + + public override string Help + { + get + { + var help = base.Help; + if (help != null) + { + return help; + } + else + { + if (_owner != null) + { + return _owner.GetType().Name + "(" + _owner.GetType().BaseType.Name + ")"; + } + } + return string.Empty; + } + } + + public override string Name + { + get + { + string name = base.Name; + if (name != null) + { + return name; + } + + name = string.Empty; + if (_owner == null) + { + return name; + } + + if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_MONTH) + { + if (DateTime.Equals(_owner.SelectionStart.Date, _owner.SelectionEnd.Date)) + { + return string.Format(SR.MonthCalendarSingleDateSelected, _owner.SelectionStart.ToLongDateString()); + } + else + { + return string.Format(SR.MonthCalendarRangeSelected, _owner.SelectionStart.ToLongDateString(), _owner.SelectionEnd.ToLongDateString()); + } + } + else if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_YEAR) + { + if (DateTime.Equals(_owner.SelectionStart.Month, _owner.SelectionEnd.Month)) + { + return string.Format(SR.MonthCalendarSingleDateSelected, _owner.SelectionStart.ToString("y")); + } + else + { + return string.Format(SR.MonthCalendarRangeSelected, _owner.SelectionStart.ToString("y"), _owner.SelectionEnd.ToString("y")); + } + } + else if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_DECADE) + { + if (DateTime.Equals(_owner.SelectionStart.Year, _owner.SelectionEnd.Year)) + { + return string.Format(SR.MonthCalendarSingleYearSelected, _owner.SelectionStart.ToString("yyyy")); + } + else + { + return string.Format(SR.MonthCalendarYearRangeSelected, _owner.SelectionStart.ToString("yyyy"), _owner.SelectionEnd.ToString("yyyy")); + } + } + else if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_CENTURY) + { + return string.Format(SR.MonthCalendarSingleDecadeSelected, _owner.SelectionStart.ToString("yyyy")); + } + + return name; + } + } + + public override string Value + { + get + { + var value = string.Empty; + if (_owner == null) + { + return value; + } + + try + { + if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_MONTH) + { + if (System.DateTime.Equals(_owner.SelectionStart.Date, _owner.SelectionEnd.Date)) + { + value = _owner.SelectionStart.ToLongDateString(); + } + else + { + value = string.Format("{0} - {1}", _owner.SelectionStart.ToLongDateString(), _owner.SelectionEnd.ToLongDateString()); + } + } + else if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_YEAR) + { + if (System.DateTime.Equals(_owner.SelectionStart.Month, _owner.SelectionEnd.Month)) + { + value = _owner.SelectionStart.ToString("y"); + } + else + { + value = string.Format("{0} - {1}", _owner.SelectionStart.ToString("y"), _owner.SelectionEnd.ToString("y")); + } + } + else + { + value = string.Format("{0} - {1}", _owner.SelectionRange.Start.ToString(), _owner.SelectionRange.End.ToString()); + } + } + catch + { + value = base.Value; + } + + return value; + } + set + { + base.Value = value; + } + } + + internal override int ColumnCount + { + get + { + GetCalendarGridInfo( + ComCtl32.MCGIF.RECT, + ComCtl32.MCGIP.CALENDARBODY, + _calendarIndex, + -1, + -1, + out RECT calendarBodyRectangle, + out Kernel32.SYSTEMTIME endDate, + out Kernel32.SYSTEMTIME startDate); + + int columnCount = 0; + bool success = true; + while (success) + { + success = GetCalendarGridInfo( + ComCtl32.MCGIF.RECT, + ComCtl32.MCGIP.CALENDARCELL, + _calendarIndex, + 0, + columnCount, + out RECT calendarPartRectangle, + out endDate, + out startDate); + + // Out of the body, so this is out of the grid column. + if (calendarPartRectangle.right > calendarBodyRectangle.right) + { + break; + } + + columnCount++; + } + + return columnCount; + } + } + + internal override int RowCount + { + get + { + GetCalendarGridInfo( + ComCtl32.MCGIF.RECT, + ComCtl32.MCGIP.CALENDARBODY, + _calendarIndex, + -1, + -1, + out RECT calendarBodyRectangle, + out Kernel32.SYSTEMTIME endDate, + out Kernel32.SYSTEMTIME startDate); + + int rowCount = 0; + bool success = true; + while (success) + { + success = GetCalendarGridInfo( + ComCtl32.MCGIF.RECT, + ComCtl32.MCGIP.CALENDARCELL, + _calendarIndex, + rowCount, + 0, + out RECT calendarPartRectangle, + out endDate, + out startDate); + + // Out of the body, so this is out of the grid row. + if (calendarPartRectangle.bottom > calendarBodyRectangle.bottom) + { + break; + } + + rowCount++; + } + + return rowCount; + } + } + + internal override UnsafeNativeMethods.RowOrColumnMajor RowOrColumnMajor => UnsafeNativeMethods.RowOrColumnMajor.RowOrColumnMajor_RowMajor; + + internal override UnsafeNativeMethods.IRawElementProviderSimple[] GetRowHeaderItems() => null; + + internal override UnsafeNativeMethods.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) + { + int innerX = (int)x; + int innerY = (int)y; + + ComCtl32.MCHITTESTINFO hitTestInfo = GetHitTestInfo(innerX, innerY); + switch ((ComCtl32.MCHT)hitTestInfo.uHit) + { + case ComCtl32.MCHT.TITLEBTNPREV: + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.PreviousButton); + + case ComCtl32.MCHT.TITLEBTNNEXT: + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.NextButton); + + case ComCtl32.MCHT.TITLE: + case ComCtl32.MCHT.TITLEMONTH: + case ComCtl32.MCHT.TITLEYEAR: + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarHeader); + + case ComCtl32.MCHT.CALENDARDAY: + case ComCtl32.MCHT.CALENDARWEEKNUM: + case ComCtl32.MCHT.CALENDARDATE: + // Get calendar body's child. + CalendarBodyAccessibleObject calendarBodyAccessibleObject = (CalendarBodyAccessibleObject)GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody); + return calendarBodyAccessibleObject.GetFromPoint(hitTestInfo); + + case ComCtl32.MCHT.TODAYLINK: + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.TodayLink); + } + + return base.ElementProviderFromPoint(x, y); + } + + internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) + { + switch (direction) + { + case UnsafeNativeMethods.NavigateDirection.FirstChild: + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.PreviousButton); + case UnsafeNativeMethods.NavigateDirection.LastChild: + return _owner.ShowTodayCircle + ? GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.TodayLink) + : GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody); + } + + return base.FragmentNavigate(direction); + } + + internal override UnsafeNativeMethods.IRawElementProviderFragment GetFocus() => _focused; + + public override AccessibleObject GetFocused() => _focused; + + public ComCtl32.MCHITTESTINFO GetHitTestInfo(int xScreen, int yScreen) + { + ComCtl32.MCHITTESTINFO hitTestInfo = new ComCtl32.MCHITTESTINFO(); + hitTestInfo.cbSize = (int)Marshal.SizeOf(hitTestInfo); + hitTestInfo.pt = new POINT(); + hitTestInfo.st = new Kernel32.SYSTEMTIME(); + + // NativeMethods.GetCursorPos(out Point pt); + Point point = new Point(xScreen, yScreen); + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, ref point, 1); + hitTestInfo.pt.x = point.X; + hitTestInfo.pt.y = point.Y; + + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.HITTEST, 0, ref hitTestInfo); + + return hitTestInfo; + } + + public CalendarChildAccessibleObject GetCalendarChildAccessibleObject(int calendarIndex, CalendarChildType calendarChildType, AccessibleObject parentAccessibleObject = null, int index = -1) => + calendarChildType switch + { + CalendarChildType.PreviousButton => new CalendarPreviousButtonAccessibleObject(this, _calendarIndex), + CalendarChildType.NextButton => new CalendarNextButtonAccessibleObject(this, _calendarIndex), + CalendarChildType.CalendarHeader => new CalendarHeaderAccessibleObject(this, _calendarIndex), + CalendarChildType.CalendarBody => new CalendarBodyAccessibleObject(this, _calendarIndex), + CalendarChildType.CalendarRow => GetCalendarRow(calendarIndex, parentAccessibleObject, index), + CalendarChildType.CalendarCell => GetCalendarCell(calendarIndex, parentAccessibleObject, index), + CalendarChildType.TodayLink => new CalendarTodayLinkAccessibleObject(this, (int)CalendarChildType.TodayLink, calendarChildType), + _ => null + }; + + public string GetCalendarChildName(int calendarIndex, CalendarChildType calendarChildType, AccessibleObject parentAccessibleObject = null, int index = -1) + { + switch (calendarChildType) + { + case CalendarChildType.CalendarHeader: + GetCalendarGridInfoText(ComCtl32.MCGIP.CALENDARHEADER, calendarIndex, 0, 0, out string text); + return text; + case CalendarChildType.TodayLink: + return string.Format(SR.MonthCalendarTodayButtonAccessibleName, _owner.TodayDate.ToShortDateString()); + }; + + return string.Empty; + } + + private CalendarCellAccessibleObject GetCalendarCell(int calendarIndex, AccessibleObject parentAccessibleObject, int columnIndex) + { + if (columnIndex < 0 || + columnIndex >= MAX_DAYS || + columnIndex >= ColumnCount) + { + return null; + } + + CalendarRowAccessibleObject parentRowAccessibleObject = (CalendarRowAccessibleObject)parentAccessibleObject; + int rowIndex = parentRowAccessibleObject.RowIndex; + bool getNameResult = GetCalendarGridInfoText(ComCtl32.MCGIP.CALENDARCELL, calendarIndex, rowIndex, columnIndex, out string text); + bool getDateResult = GetCalendarGridInfo(ComCtl32.MCGIF.DATE, ComCtl32.MCGIP.CALENDARCELL, + calendarIndex, + rowIndex, + columnIndex, + out RECT rectangle, + out Kernel32.SYSTEMTIME systemEndDate, + out Kernel32.SYSTEMTIME systemStartDate); + + DateTime endDate = DateTimePicker.SysTimeToDateTime(systemEndDate).Date; + DateTime startDate = DateTimePicker.SysTimeToDateTime(systemStartDate).Date; + + if (getNameResult && !string.IsNullOrEmpty(text)) + { + string cellName = GetCalendarCellName(endDate, startDate, text, rowIndex == -1); + + // The cell is present on the calendar, so create accessible object for it. + return new CalendarCellAccessibleObject(this, calendarIndex, parentAccessibleObject, rowIndex, columnIndex, cellName); + } + + return null; + } + + private string GetCalendarCellName(DateTime endDate, DateTime startDate, string defaultName, bool headerCell) + { + if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_MONTH) + { + if (headerCell) + { + return startDate.ToString("dddd"); + } + + return startDate.ToString("dddd, MMMM dd, yyyy"); + } + else if (_owner.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_YEAR) + { + return startDate.ToString("MMMM yyyy"); + } + + return defaultName; + } + + private CalendarRowAccessibleObject GetCalendarRow(int calendarIndex, AccessibleObject parentAccessibleObject, int rowIndex) + { + if ((HasHeaderRow ? rowIndex < -1 : rowIndex < 0) || + rowIndex >= RowCount) + { + return null; + } + + // Search name for the first cell in the row. + bool success = GetCalendarGridInfo( + ComCtl32.MCGIF.DATE, + ComCtl32.MCGIP.CALENDARCELL, + calendarIndex, + rowIndex, + 0, + out RECT calendarPartRectangle, + out Kernel32.SYSTEMTIME endDate, + out Kernel32.SYSTEMTIME startDate); + + if (!success) + { + // Not able to get cell date for the row. + return null; + } + + SelectionRange cellsRange = _owner.GetDisplayRange(false); + + if (cellsRange.Start > DateTimePicker.SysTimeToDateTime(endDate) || cellsRange.End < DateTimePicker.SysTimeToDateTime(startDate)) + { + // Do not create row if the row's first cell is out of the current calendar's view range. + return null; + } + + return new CalendarRowAccessibleObject(this, calendarIndex, (CalendarBodyAccessibleObject)parentAccessibleObject, rowIndex); + } + + private bool GetCalendarGridInfo( + ComCtl32.MCGIF dwFlags, + ComCtl32.MCGIP dwPart, + int calendarIndex, + int row, + int column, + out RECT rectangle, + out Kernel32.SYSTEMTIME endDate, + out Kernel32.SYSTEMTIME startDate) + { + Debug.Assert( + (dwFlags & ~(ComCtl32.MCGIF.DATE | ComCtl32.MCGIF.RECT)) == 0, + "GetCalendarGridInfo() should be used only to obtain Date and Rect," + + "dwFlags has flag bits other that MCGIF_DATE and MCGIF_RECT"); + + ComCtl32.MCGRIDINFO gridInfo = new ComCtl32.MCGRIDINFO(); + gridInfo.dwFlags = dwFlags; + gridInfo.cbSize = (uint)Marshal.SizeOf(gridInfo); + gridInfo.dwPart = dwPart; + gridInfo.iCalendar = calendarIndex; + gridInfo.iCol = column; + gridInfo.iRow = row; + bool result; + + try + { + result = GetCalendarGridInfo(ref gridInfo); + rectangle = gridInfo.rc; + endDate = gridInfo.stEnd; + startDate = gridInfo.stStart; + } + catch + { + rectangle = new RECT(); + endDate = new Kernel32.SYSTEMTIME(); + startDate = new Kernel32.SYSTEMTIME(); + result = false; + } + + return result; + } + + private bool GetCalendarGridInfo(ref ComCtl32.MCGRIDINFO gridInfo) + { + // Do not use this if gridInfo.dwFlags contains MCGIF_NAME; + // use GetCalendarGridInfoText() instead. + Debug.Assert( + (gridInfo.dwFlags & ComCtl32.MCGIF.NAME) == 0, + "Param dwFlags contains MCGIF_NAME, use GetCalendarGridInfoText() to retrieve the text of a calendar part."); + + gridInfo.dwFlags &= ~ComCtl32.MCGIF.NAME; + + return _owner.SendMessage((int)ComCtl32.MCM.GETCALENDARGRIDINFO, 0, ref gridInfo) != IntPtr.Zero; + } + + private bool GetCalendarGridInfoText(ComCtl32.MCGIP dwPart, int calendarIndex, int row, int column, out string text) + { + const int nameLength = 128; + + ComCtl32.MCGRIDINFO gridInfo = new ComCtl32.MCGRIDINFO(); + gridInfo.cbSize = (uint)Marshal.SizeOf(gridInfo); + gridInfo.dwPart = dwPart; + gridInfo.iCalendar = calendarIndex; + gridInfo.iCol = column; + gridInfo.iRow = row; + gridInfo.pszName = new string('\0', nameLength + 2); + gridInfo.cchName = (uint)gridInfo.pszName.Length - 1; + + bool result = GetCalendarGridInfoText(ref gridInfo); + text = gridInfo.pszName; + + return result; + } + + // Use to retrieve MCGIF_NAME only. + private bool GetCalendarGridInfoText(ref ComCtl32.MCGRIDINFO gridInfo) + { + Debug.Assert( + gridInfo.dwFlags == 0, + "gridInfo.dwFlags should be 0 when calling GetCalendarGridInfoText"); + + gridInfo.dwFlags = ComCtl32.MCGIF.NAME; + + return _owner.SendMessage((int)ComCtl32.MCM.GETCALENDARGRIDINFO, 0, ref gridInfo) != IntPtr.Zero; + } + + public bool GetCalendarPartRectangle(int calendarIndex, ComCtl32.MCGIP dwPart, int row, int column, out RECT calendarPartRectangle) + { + bool success = GetCalendarGridInfo( + ComCtl32.MCGIF.RECT, + dwPart, + calendarIndex, + row, + column, + out calendarPartRectangle, + out Kernel32.SYSTEMTIME endDate, out Kernel32.SYSTEMTIME startDate); + + if (success) + { + success = UnsafeNativeMethods.MapWindowPoints(new HandleRef(this, Owner.Handle), new HandleRef(null, IntPtr.Zero), ref calendarPartRectangle, 2) != 0; + } + + if (!success) + { + calendarPartRectangle = new RECT(); + } + + return success; + } + + internal override object GetPropertyValue(int propertyID) => + propertyID switch + { + NativeMethods.UIA_ControlTypePropertyId => ControlType, + NativeMethods.UIA_NamePropertyId => Name, + NativeMethods.UIA_IsGridPatternAvailablePropertyId => true, + NativeMethods.UIA_IsTablePatternAvailablePropertyId => true, + NativeMethods.UIA_IsLegacyIAccessiblePatternAvailablePropertyId => true, + _ => base.GetPropertyValue(propertyID) + }; + + internal override bool IsPatternSupported(int patternId) => + patternId switch + { + var p when + p == NativeMethods.UIA_ValuePatternId || + p == NativeMethods.UIA_GridPatternId || + p == NativeMethods.UIA_TablePatternId || + p == NativeMethods.UIA_LegacyIAccessiblePatternId => true, + _ => base.IsPatternSupported(patternId) + }; + + public void RaiseMouseClick(int x, int y) + { + POINT previousPosition = new POINT(); + bool setOldCursorPos = UnsafeNativeMethods.GetPhysicalCursorPos(ref previousPosition); + + bool mouseSwapped = User32.GetSystemMetrics(User32.SystemMetric.SM_SWAPBUTTON) != 0; + + SendMouseInput(x, y, User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.ABSOLUTE); + SendMouseInput(0, 0, mouseSwapped ? User32.MOUSEEVENTF.RIGHTDOWN : User32.MOUSEEVENTF.LEFTDOWN); + SendMouseInput(0, 0, mouseSwapped ? User32.MOUSEEVENTF.RIGHTUP : User32.MOUSEEVENTF.LEFTUP); + + Threading.Thread.Sleep(50); + + // Set back the mouse position where it was. + if (setOldCursorPos) + { + SendMouseInput(previousPosition.x, previousPosition.y, User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.ABSOLUTE); + } + } + + private void SendMouseInput(int x, int y, User32.MOUSEEVENTF flags) + { + if ((flags & User32.MOUSEEVENTF.ABSOLUTE) != 0) + { + int vscreenWidth = User32.GetSystemMetrics(User32.SystemMetric.SM_CXVIRTUALSCREEN); + int vscreenHeight = User32.GetSystemMetrics(User32.SystemMetric.SM_CYVIRTUALSCREEN); + int vscreenLeft = User32.GetSystemMetrics(User32.SystemMetric.SM_XVIRTUALSCREEN); + int vscreenTop = User32.GetSystemMetrics(User32.SystemMetric.SM_YVIRTUALSCREEN); + + const int DesktopNormilizedMax = 65536; + + // Absolute input requires that input is in 'normalized' coords - with the entire + // desktop being (0,0)...(65535,65536). Need to convert input x,y coords to this + // first. + // + // In this normalized world, any pixel on the screen corresponds to a block of values + // of normalized coords - eg. on a 1024x768 screen, + // y pixel 0 corresponds to range 0 to 85.333, + // y pixel 1 corresponds to range 85.333 to 170.666, + // y pixel 2 correpsonds to range 170.666 to 256 - and so on. + // Doing basic scaling math - (x-top)*65536/Width - gets us the start of the range. + // However, because int math is used, this can end up being rounded into the wrong + // pixel. For example, if we wanted pixel 1, we'd get 85.333, but that comes out as + // 85 as an int, which falls into pixel 0's range - and that's where the pointer goes. + // To avoid this, we add on half-a-"screen pixel"'s worth of normalized coords - to + // push us into the middle of any given pixel's range - that's the 65536/(Width*2) + // part of the formula. So now pixel 1 maps to 85+42 = 127 - which is comfortably + // in the middle of that pixel's block. + // The key ting here is that unlike points in coordinate geometry, pixels take up + // space, so are often better treated like rectangles - and if you want to target + // a particular pixel, target its rectangle's midpoint, not its edge. + x = ((x - vscreenLeft) * DesktopNormilizedMax) / vscreenWidth + DesktopNormilizedMax / (vscreenWidth * 2); + y = ((y - vscreenTop) * DesktopNormilizedMax) / vscreenHeight + DesktopNormilizedMax / (vscreenHeight * 2); + + flags |= User32.MOUSEEVENTF.VIRTUALDESK; + } + + NativeMethods.INPUT mouseInput = new NativeMethods.INPUT(); + mouseInput.type = NativeMethods.INPUT_MOUSE; + mouseInput.inputUnion.mi.dx = x; + mouseInput.inputUnion.mi.dy = y; + mouseInput.inputUnion.mi.mouseData = 0; + mouseInput.inputUnion.mi.dwFlags = (int)flags; + mouseInput.inputUnion.mi.time = 0; + mouseInput.inputUnion.mi.dwExtraInfo = new IntPtr(0); + + UnsafeNativeMethods.SendInput(1, ref mouseInput, Marshal.SizeOf(mouseInput)); + } + + public void RaiseAutomationEventForChild(int automationEventId, DateTime selectionStart, DateTime selectionEnd) + { + AccessibleObject calendarChildAccessibleObject = GetCalendarChildAccessibleObject(selectionStart, selectionEnd); + if (calendarChildAccessibleObject != null) + { + calendarChildAccessibleObject.RaiseAutomationEvent(automationEventId); + + if (automationEventId == NativeMethods.UIA_AutomationFocusChangedEventId) + { + _focused = calendarChildAccessibleObject; + } + } + } + + private AccessibleObject GetCalendarChildAccessibleObject(DateTime selectionStart, DateTime selectionEnd) + { + int columnCount = ColumnCount; + + AccessibleObject bodyAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody); + for (int row = 0; row < RowCount; row++) + { + AccessibleObject rowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, bodyAccessibleObject, row); + for (int column = 0; column < columnCount; column++) + { + bool success = GetCalendarGridInfo( + ComCtl32.MCGIF.DATE, + ComCtl32.MCGIP.CALENDARCELL, + _calendarIndex, + row, + column, + out RECT calendarPartRectangle, + out Kernel32.SYSTEMTIME systemEndDate, + out Kernel32.SYSTEMTIME systemStartDate); + + if (!success) + { + continue; + } + + AccessibleObject cellAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, column); + if (cellAccessibleObject == null) + { + continue; + } + + DateTime endDate = DateTimePicker.SysTimeToDateTime(systemEndDate); + DateTime startDate = DateTimePicker.SysTimeToDateTime(systemStartDate); + + if (DateTime.Compare(selectionEnd, endDate) <= 0 && + DateTime.Compare(selectionStart, startDate) >= 0) + { + return cellAccessibleObject; + } + } + } + + return null; + } + + internal override UnsafeNativeMethods.IRawElementProviderSimple[] GetRowHeaders() => null; + + internal override UnsafeNativeMethods.IRawElementProviderSimple[] GetColumnHeaderItems() + { + if (!HasHeaderRow) + { + return null; + } + + UnsafeNativeMethods.IRawElementProviderSimple[] headers = + new UnsafeNativeMethods.IRawElementProviderSimple[MonthCalendarAccessibleObject.MAX_DAYS]; + AccessibleObject headerRowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, -1); + for (int columnIndex = 0; columnIndex < MonthCalendarAccessibleObject.MAX_DAYS; columnIndex++) + { + headers[columnIndex] = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, headerRowAccessibleObject, columnIndex); + } + + return headers; + } + + internal override UnsafeNativeMethods.IRawElementProviderSimple GetItem(int row, int column) + { + AccessibleObject rowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, row); + + if (rowAccessibleObject == null) + { + return null; + } + + return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, column); + } + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs index 21e332d9b0c..0e0db38f6c3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs @@ -10,8 +10,9 @@ using System.Windows.Forms.Internal; using System.Windows.Forms.Layout; using Microsoft.Win32; -using ArrayList = System.Collections.ArrayList; + using static Interop; +using ArrayList = System.Collections.ArrayList; namespace System.Windows.Forms { @@ -62,7 +63,7 @@ namespace System.Windows.Forms Designer("System.Windows.Forms.Design.MonthCalendarDesigner, " + AssemblyRef.SystemDesign), SRDescription(nameof(SR.DescriptionMonthCalendar)) ] - public class MonthCalendar : Control + public partial class MonthCalendar : Control { const long DAYS_TO_1601 = 548229; const long DAYS_TO_10000 = 3615900; @@ -365,20 +366,20 @@ protected override CreateParams CreateParams { CreateParams cp = base.CreateParams; cp.ClassName = NativeMethods.WC_MONTHCAL; - cp.Style |= NativeMethods.MCS_MULTISELECT | NativeMethods.MCS_DAYSTATE; + cp.Style |= (int)ComCtl32.MCS.MULTISELECT | (int)ComCtl32.MCS.DAYSTATE; if (!showToday) { - cp.Style |= NativeMethods.MCS_NOTODAY; + cp.Style |= (int)ComCtl32.MCS.NOTODAY; } if (!showTodayCircle) { - cp.Style |= NativeMethods.MCS_NOTODAYCIRCLE; + cp.Style |= (int)ComCtl32.MCS.NOTODAYCIRCLE; } if (showWeekNumbers) { - cp.Style |= NativeMethods.MCS_WEEKNUMBERS; + cp.Style |= (int)ComCtl32.MCS.WEEKNUMBERS; } if (RightToLeft == RightToLeft.Yes && RightToLeftLayout == true) @@ -466,7 +467,7 @@ public Day FirstDayOfWeek } else { - SendMessage(NativeMethods.MCM_SETFIRSTDAYOFWEEK, 0, (int)value); + SendMessage((int)ComCtl32.MCM.SETFIRSTDAYOFWEEK, 0, (int)value); } } } @@ -569,7 +570,7 @@ public int MaxSelectionCount { if (IsHandleCreated) { - if (unchecked((int)(long)SendMessage(NativeMethods.MCM_SETMAXSELCOUNT, value, 0)) == 0) + if (unchecked((int)(long)SendMessage((int)ComCtl32.MCM.SETMAXSELCOUNT, value, 0)) == 0) { throw new ArgumentException(string.Format(SR.MonthCalendarMaxSelCount, value.ToString("D")), nameof(value)); } @@ -757,7 +758,7 @@ public int ScrollChange if (IsHandleCreated) { - SendMessage(NativeMethods.MCM_SETMONTHDELTA, value, 0); + SendMessage((int)ComCtl32.MCM.SETMONTHDELTA, value, 0); } scrollChange = value; } @@ -982,7 +983,7 @@ public Size SingleMonthSize if (IsHandleCreated) { - if (unchecked((int)(long)SendMessage(NativeMethods.MCM_GETMINREQRECT, 0, ref rect)) == 0) + if (unchecked((int)(long)SendMessage((int)ComCtl32.MCM.GETMINREQRECT, 0, ref rect)) == 0) { throw new InvalidOperationException(SR.InvalidSingleMonthSize); } @@ -1015,6 +1016,8 @@ public Size SingleMonthSize } } + internal override bool SupportsUiaProviders => true; + [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Bindable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public override string Text { @@ -1055,8 +1058,8 @@ public DateTime TodayDate if (IsHandleCreated) { - NativeMethods.SYSTEMTIME st = new NativeMethods.SYSTEMTIME(); - int res = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_GETTODAY, 0, st); + Kernel32.SYSTEMTIME st = new Kernel32.SYSTEMTIME(); + int res = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.GETTODAY, 0, ref st); Debug.Assert(res != 0, "MCM_GETTODAY failed"); return DateTimePicker.SysTimeToDateTime(st).Date; } @@ -1131,7 +1134,7 @@ public Color TitleBackColor "value")); } titleBackColor = value; - SetControlColor(NativeMethods.MCSC_TITLEBK, value); + SetControlColor(ComCtl32.MCSC.TITLEBK, value); } } @@ -1157,7 +1160,7 @@ public Color TitleForeColor "value")); } titleForeColor = value; - SetControlColor(NativeMethods.MCSC_TITLETEXT, value); + SetControlColor(ComCtl32.MCSC.TITLETEXT, value); } } @@ -1183,7 +1186,7 @@ public Color TrailingForeColor "value")); } trailingForeColor = value; - SetControlColor(NativeMethods.MCSC_TRAILINGTEXT, value); + SetControlColor(ComCtl32.MCSC.TRAILINGTEXT, value); } } @@ -1398,31 +1401,31 @@ public SelectionRange GetDisplayRange(bool visible) /// private HitArea GetHitArea(int hit) { - switch (hit) + switch ((ComCtl32.MCHT)hit) { - case NativeMethods.MCHT_TITLEBK: + case ComCtl32.MCHT.TITLEBK: return HitArea.TitleBackground; - case NativeMethods.MCHT_TITLEMONTH: + case ComCtl32.MCHT.TITLEMONTH: return HitArea.TitleMonth; - case NativeMethods.MCHT_TITLEYEAR: + case ComCtl32.MCHT.TITLEYEAR: return HitArea.TitleYear; - case NativeMethods.MCHT_TITLEBTNNEXT: + case ComCtl32.MCHT.TITLEBTNNEXT: return HitArea.NextMonthButton; - case NativeMethods.MCHT_TITLEBTNPREV: + case ComCtl32.MCHT.TITLEBTNPREV: return HitArea.PrevMonthButton; - case NativeMethods.MCHT_CALENDARBK: + case ComCtl32.MCHT.CALENDARBK: return HitArea.CalendarBackground; - case NativeMethods.MCHT_CALENDARDATE: + case ComCtl32.MCHT.CALENDARDATE: return HitArea.Date; - case NativeMethods.MCHT_CALENDARDATENEXT: + case ComCtl32.MCHT.CALENDARDATENEXT: return HitArea.NextMonthDate; - case NativeMethods.MCHT_CALENDARDATEPREV: + case ComCtl32.MCHT.CALENDARDATEPREV: return HitArea.PrevMonthDate; - case NativeMethods.MCHT_CALENDARDAY: + case ComCtl32.MCHT.CALENDARDAY: return HitArea.DayOfWeek; - case NativeMethods.MCHT_CALENDARWEEKNUM: + case ComCtl32.MCHT.CALENDARWEEKNUM: return HitArea.WeekNumbers; - case NativeMethods.MCHT_TODAYLINK: + case ComCtl32.MCHT.TODAYLINK: return HitArea.TodayLink; default: return HitArea.Nowhere; @@ -1439,9 +1442,10 @@ private Size GetMinReqRect() /// /// Used internally to get the minimum size needed to display the - /// MonthCalendar. This is needed because - /// NativeMethods.MCM_GETMINREQRECT returns an incorrect value if showToday - /// is set to false. If updateRows is true, then the + /// MonthCalendar. This is needed because + /// ComCtl32.MCM.GETMINREQRECT + /// returns an incorrect value if showToday + /// is set to false. If updateRows is true, then the /// number of rows will be updated according to height. /// private Size GetMinReqRect(int newDimensionLength, bool updateRows, bool updateCols) @@ -1487,7 +1491,7 @@ private Size GetMinReqRect(int newDimensionLength, bool updateRows, bool updateC // if (IsHandleCreated) { - int maxTodayWidth = unchecked((int)(long)SendMessage(NativeMethods.MCM_GETMAXTODAYWIDTH, 0, 0)); + int maxTodayWidth = unchecked((int)(long)SendMessage((int)ComCtl32.MCM.GETMAXTODAYWIDTH, 0, 0)); if (maxTodayWidth > minSize.Width) { minSize.Width = maxTodayWidth; @@ -1505,9 +1509,9 @@ private SelectionRange GetMonthRange(int flag) { NativeMethods.SYSTEMTIMEARRAY sa = new NativeMethods.SYSTEMTIMEARRAY(); SelectionRange range = new SelectionRange(); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_GETMONTHRANGE, flag, sa); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.GETMONTHRANGE, flag, sa); - NativeMethods.SYSTEMTIME st = new NativeMethods.SYSTEMTIME + Kernel32.SYSTEMTIME st = new Kernel32.SYSTEMTIME { wYear = sa.wYear1, wMonth = sa.wMonth1, @@ -1551,35 +1555,39 @@ private int GetPreferredWidth(int width, bool updateCols) /// public HitTestInfo HitTest(int x, int y) { - NativeMethods.MCHITTESTINFO mchi = new NativeMethods.MCHITTESTINFO + ComCtl32.MCHITTESTINFO mchi = new ComCtl32.MCHITTESTINFO { - pt_x = x, - pt_y = y, - cbSize = Marshal.SizeOf() + pt = new POINT + { + x = x, + y = y + }, + st = new Kernel32.SYSTEMTIME(), + cbSize = Marshal.SizeOf() }; - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_HITTEST, 0, mchi); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.HITTEST, 0, ref mchi); // If the hit area has an associated valid date, get it // HitArea hitArea = GetHitArea(mchi.uHit); if (HitTestInfo.HitAreaHasValidDateTime(hitArea)) { - NativeMethods.SYSTEMTIME sys = new NativeMethods.SYSTEMTIME + Kernel32.SYSTEMTIME sys = new Kernel32.SYSTEMTIME { - wYear = mchi.st_wYear, - wMonth = mchi.st_wMonth, - wDayOfWeek = mchi.st_wDayOfWeek, - wDay = mchi.st_wDay, - wHour = mchi.st_wHour, - wMinute = mchi.st_wMinute, - wSecond = mchi.st_wSecond, - wMilliseconds = mchi.st_wMilliseconds + wYear = mchi.st.wYear, + wMonth = mchi.st.wMonth, + wDayOfWeek = mchi.st.wDayOfWeek, + wDay = mchi.st.wDay, + wHour = mchi.st.wHour, + wMinute = mchi.st.wMinute, + wSecond = mchi.st.wSecond, + wMilliseconds = mchi.st.wMilliseconds }; - return new HitTestInfo(new Point(mchi.pt_x, mchi.pt_y), hitArea, DateTimePicker.SysTimeToDateTime(sys)); + return new HitTestInfo(new Point(mchi.pt.x, mchi.pt.y), hitArea, DateTimePicker.SysTimeToDateTime(sys)); } else { - return new HitTestInfo(new Point(mchi.pt_x, mchi.pt_y), hitArea); + return new HitTestInfo(new Point(mchi.pt.x, mchi.pt.y), hitArea); } } @@ -1622,21 +1630,21 @@ protected override void OnHandleCreated(EventArgs e) SetSelRange(selectionStart, selectionEnd); if (maxSelectionCount != DEFAULT_MAX_SELECTION_COUNT) { - SendMessage(NativeMethods.MCM_SETMAXSELCOUNT, maxSelectionCount, 0); + SendMessage((int)ComCtl32.MCM.SETMAXSELCOUNT, maxSelectionCount, 0); } AdjustSize(); if (todayDateSet) { - NativeMethods.SYSTEMTIME st = DateTimePicker.DateTimeToSysTime(todayDate); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_SETTODAY, 0, st); + Kernel32.SYSTEMTIME st = DateTimePicker.DateTimeToSysTime(todayDate); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.SETTODAY, 0, ref st); } - SetControlColor(NativeMethods.MCSC_TEXT, ForeColor); - SetControlColor(NativeMethods.MCSC_MONTHBK, BackColor); - SetControlColor(NativeMethods.MCSC_TITLEBK, titleBackColor); - SetControlColor(NativeMethods.MCSC_TITLETEXT, titleForeColor); - SetControlColor(NativeMethods.MCSC_TRAILINGTEXT, trailingForeColor); + SetControlColor(ComCtl32.MCSC.TEXT, ForeColor); + SetControlColor(ComCtl32.MCSC.MONTHBK, BackColor); + SetControlColor(ComCtl32.MCSC.TITLEBK, titleBackColor); + SetControlColor(ComCtl32.MCSC.TITLETEXT, titleForeColor); + SetControlColor(ComCtl32.MCSC.TRAILINGTEXT, trailingForeColor); int firstDay; if (firstDayOfWeek == Day.Default) @@ -1647,12 +1655,12 @@ protected override void OnHandleCreated(EventArgs e) { firstDay = (int)firstDayOfWeek; } - SendMessage(NativeMethods.MCM_SETFIRSTDAYOFWEEK, 0, firstDay); + SendMessage((int)ComCtl32.MCM.SETFIRSTDAYOFWEEK, 0, firstDay); SetRange(); if (scrollChange != DEFAULT_SCROLL_CHANGE) { - SendMessage(NativeMethods.MCM_SETMONTHDELTA, scrollChange, 0); + SendMessage((int)ComCtl32.MCM.SETMONTHDELTA, scrollChange, 0); } SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(MarshaledUserPreferenceChanged); @@ -1684,6 +1692,13 @@ protected virtual void OnDateSelected(DateRangeEventArgs drevent) onDateSelected?.Invoke(this, drevent); } + protected override void OnGotFocus(EventArgs e) + { + base.OnGotFocus(e); + + AccessibilityObject.RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); + } + protected override void OnFontChanged(EventArgs e) { base.OnFontChanged(e); @@ -1693,13 +1708,13 @@ protected override void OnFontChanged(EventArgs e) protected override void OnForeColorChanged(EventArgs e) { base.OnForeColorChanged(e); - SetControlColor(NativeMethods.MCSC_TEXT, ForeColor); + SetControlColor(ComCtl32.MCSC.TEXT, ForeColor); } protected override void OnBackColorChanged(EventArgs e) { base.OnBackColorChanged(e); - SetControlColor(NativeMethods.MCSC_MONTHBK, BackColor); + SetControlColor(ComCtl32.MCSC.MONTHBK, BackColor); } [EditorBrowsable(EditorBrowsableState.Advanced)] @@ -1938,6 +1953,13 @@ private IntPtr RequestBuffer(int reqSize) return mdsBuffer; } + /// + /// Sends a Win32 message to this control. If the control does not yet + /// have a handle, it will be created. + /// + private IntPtr SendMessage(int msg, int wparam, ref ComCtl32.MCGRIDINFO lparam) => + ComCtl32.SendMessage(new HandleRef(this, Handle), msg, wparam, ref lparam); + /// /// Overrides Control.SetBoundsCore to enforce auto-sizing. /// @@ -1974,11 +1996,11 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound /// /// If the handle has been created, this applies the color to the control /// - private void SetControlColor(int colorIndex, Color value) + private void SetControlColor(ComCtl32.MCSC colorIndex, Color value) { if (IsHandleCreated) { - SendMessage(NativeMethods.MCM_SETCOLOR, colorIndex, ColorTranslator.ToWin32(value)); + SendMessage((int)ComCtl32.MCM.SETCOLOR, (int)colorIndex, ColorTranslator.ToWin32(value)); } } @@ -2020,7 +2042,7 @@ private void SetRange(DateTime minDate, DateTime maxDate) NativeMethods.SYSTEMTIMEARRAY sa = new NativeMethods.SYSTEMTIMEARRAY(); flag |= NativeMethods.GDTR_MIN | NativeMethods.GDTR_MAX; - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(minDate); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(minDate); sa.wYear1 = sys.wYear; sa.wMonth1 = sys.wMonth; sa.wDayOfWeek1 = sys.wDayOfWeek; @@ -2031,7 +2053,7 @@ private void SetRange(DateTime minDate, DateTime maxDate) sa.wDayOfWeek2 = sys.wDayOfWeek; sa.wDay2 = sys.wDay; - if ((int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_SETRANGE, flag, sa) == 0) + if ((int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.SETRANGE, flag, sa) == 0) { throw new InvalidOperationException(string.Format(SR.MonthCalendarRange, minDate.ToShortDateString(), maxDate.ToShortDateString())); } @@ -2173,7 +2195,7 @@ private void SetSelRange(DateTime lower, DateTime upper) { NativeMethods.SYSTEMTIMEARRAY sa = new NativeMethods.SYSTEMTIMEARRAY(); - NativeMethods.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(lower); + Kernel32.SYSTEMTIME sys = DateTimePicker.DateTimeToSysTime(lower); sa.wYear1 = sys.wYear; sa.wMonth1 = sys.wMonth; sa.wDayOfWeek1 = sys.wDayOfWeek; @@ -2183,7 +2205,7 @@ private void SetSelRange(DateTime lower, DateTime upper) sa.wMonth2 = sys.wMonth; sa.wDayOfWeek2 = sys.wDayOfWeek; sa.wDay2 = sys.wDay; - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_SETSELRANGE, 0, sa); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.SETSELRANGE, 0, sa); } if (changed) @@ -2286,12 +2308,16 @@ private void UpdateTodayDate() { if (IsHandleCreated) { - NativeMethods.SYSTEMTIME st = null; + if (todayDateSet) { - st = DateTimePicker.DateTimeToSysTime(todayDate); + Kernel32.SYSTEMTIME st = DateTimePicker.DateTimeToSysTime(todayDate); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.SETTODAY, 0, ref st); + } + else + { + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), (int)ComCtl32.MCM.SETTODAY, 0, IntPtr.Zero); } - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_SETTODAY, 0, st); } } @@ -2328,6 +2354,9 @@ private void WmDateChanged(ref Message m) AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); + MonthCalendarAccessibleObject calendarAccessibleObject = (MonthCalendarAccessibleObject)AccessibilityObject; + calendarAccessibleObject.RaiseAutomationEventForChild(NativeMethods.UIA_AutomationFocusChangedEventId, selectionStart, selectionEnd); + //subhag if (start.Ticks < minDate.Ticks || end.Ticks < minDate.Ticks) { @@ -2629,159 +2658,5 @@ public enum HitArea /// TodayLink = 12, } - - [ComVisible(true)] - internal class MonthCalendarAccessibleObject : ControlAccessibleObject - { - private readonly MonthCalendar calendar; - - public MonthCalendarAccessibleObject(Control owner) - : base(owner) - { - calendar = owner as MonthCalendar; - } - - public override AccessibleRole Role - { - get - { - if (calendar != null) - { - AccessibleRole role = calendar.AccessibleRole; - if (role != AccessibleRole.Default) - { - return role; - } - } - return AccessibleRole.Table; - } - } - - public override string Help - { - get - { - var help = base.Help; - if (help != null) - { - return help; - } - else - { - if (calendar != null) - { - return calendar.GetType().Name + "(" + calendar.GetType().BaseType.Name + ")"; - } - } - return string.Empty; - } - } - - public override string Name - { - get - { - string name = base.Name; - if (name != null) - { - return name; - } - - if (calendar != null) - { - - if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_MONTH) - { - if (System.DateTime.Equals(calendar.SelectionStart.Date, calendar.SelectionEnd.Date)) - { - name = string.Format(SR.MonthCalendarSingleDateSelected, calendar.SelectionStart.ToLongDateString()); - } - else - { - name = string.Format(SR.MonthCalendarRangeSelected, calendar.SelectionStart.ToLongDateString(), calendar.SelectionEnd.ToLongDateString()); - } - } - else if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_YEAR) - { - if (System.DateTime.Equals(calendar.SelectionStart.Month, calendar.SelectionEnd.Month)) - { - name = string.Format(SR.MonthCalendarSingleDateSelected, calendar.SelectionStart.ToString("y")); - } - else - { - name = string.Format(SR.MonthCalendarRangeSelected, calendar.SelectionStart.ToString("y"), calendar.SelectionEnd.ToString("y")); - } - } - else if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_DECADE) - { - if (System.DateTime.Equals(calendar.SelectionStart.Year, calendar.SelectionEnd.Year)) - { - name = string.Format(SR.MonthCalendarSingleYearSelected, calendar.SelectionStart.ToString("yyyy")); - } - else - { - name = string.Format(SR.MonthCalendarYearRangeSelected, calendar.SelectionStart.ToString("yyyy"), calendar.SelectionEnd.ToString("yyyy")); - } - } - else if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_CENTURY) - { - name = string.Format(SR.MonthCalendarSingleDecadeSelected, calendar.SelectionStart.ToString("yyyy")); - } - } - return name; - } - } - - public override string Value - { - get - { - var value = string.Empty; - try - { - if (calendar != null) - { - if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_MONTH) - { - if (System.DateTime.Equals(calendar.SelectionStart.Date, calendar.SelectionEnd.Date)) - { - value = calendar.SelectionStart.ToLongDateString(); - } - else - { - value = string.Format("{0} - {1}", calendar.SelectionStart.ToLongDateString(), calendar.SelectionEnd.ToLongDateString()); - } - } - else if (calendar.mcCurView == NativeMethods.MONTCALENDAR_VIEW_MODE.MCMV_YEAR) - { - if (System.DateTime.Equals(calendar.SelectionStart.Month, calendar.SelectionEnd.Month)) - { - value = calendar.SelectionStart.ToString("y"); - } - else - { - value = string.Format("{0} - {1}", calendar.SelectionStart.ToString("y"), calendar.SelectionEnd.ToString("y")); - } - } - else - { - value = string.Format("{0} - {1}", calendar.SelectionRange.Start.ToString(), calendar.SelectionRange.End.ToString()); - } - } - } - catch - { - value = base.Value; - } - return value; - } - set - { - base.Value = value; - } - } - } - } // end class MonthCalendar } -