diff --git a/README.md b/README.md index db355f7..bbafd0e 100644 --- a/README.md +++ b/README.md @@ -115,8 +115,7 @@ Examples: ### Architecture -mpv.net is mostly written in C# 7.0 and runs on the .NET framework 4.7 or higher. -Few parts are written in VB.NET and Python. +mpv.net is written in C# 7.0 and runs on the .NET framework 4.7 or higher. The Add-on implementation is based on the Managed Extensibility Framework, the entire application code is accessible for add-ons and Python scripts. diff --git a/VBNET/My Project/Application.Designer.vb b/VBNET/My Project/Application.Designer.vb deleted file mode 100644 index 88dd01c..0000000 --- a/VBNET/My Project/Application.Designer.vb +++ /dev/null @@ -1,13 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:4.0.30319.42000 -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Option Explicit On - diff --git a/VBNET/My Project/Application.myapp b/VBNET/My Project/Application.myapp deleted file mode 100644 index 758895d..0000000 --- a/VBNET/My Project/Application.myapp +++ /dev/null @@ -1,10 +0,0 @@ - - - false - false - 0 - true - 0 - 1 - true - diff --git a/VBNET/My Project/AssemblyInfo.vb b/VBNET/My Project/AssemblyInfo.vb deleted file mode 100644 index 4c96c7a..0000000 --- a/VBNET/My Project/AssemblyInfo.vb +++ /dev/null @@ -1,35 +0,0 @@ -Imports System -Imports System.Reflection -Imports System.Runtime.InteropServices - -' General Information about an assembly is controlled through the following -' set of attributes. Change these attribute values to modify the information -' associated with an assembly. - -' Review the values of the assembly attributes - - - - - - - - - - -'The following GUID is for the ID of the typelib if this project is exposed to COM - - -' Version information for an assembly consists of the following four values: -' -' Major Version -' Minor Version -' Build Number -' Revision -' -' You can specify all the values or you can default the Build and Revision Numbers -' by using the '*' as shown below: -' - - - diff --git a/VBNET/My Project/Resources.Designer.vb b/VBNET/My Project/Resources.Designer.vb deleted file mode 100644 index e1d9bf8..0000000 --- a/VBNET/My Project/Resources.Designer.vb +++ /dev/null @@ -1,62 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:4.0.30319.42000 -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Option Explicit On - - -Namespace My.Resources - - 'This class was auto-generated by the StronglyTypedResourceBuilder - 'class via a tool like ResGen or Visual Studio. - 'To add or remove a member, edit your .ResX file then rerun ResGen - 'with the /str option, or rebuild your VS project. - ''' - ''' A strongly-typed resource class, for looking up localized strings, etc. - ''' - _ - Friend Module Resources - - Private resourceMan As Global.System.Resources.ResourceManager - - Private resourceCulture As Global.System.Globalization.CultureInfo - - ''' - ''' Returns the cached ResourceManager instance used by this class. - ''' - _ - Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager - Get - If Object.ReferenceEquals(resourceMan, Nothing) Then - Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("VBNET.Resources", GetType(Resources).Assembly) - resourceMan = temp - End If - Return resourceMan - End Get - End Property - - ''' - ''' Overrides the current thread's CurrentUICulture property for all - ''' resource lookups using this strongly typed resource class. - ''' - _ - Friend Property Culture() As Global.System.Globalization.CultureInfo - Get - Return resourceCulture - End Get - Set(ByVal value As Global.System.Globalization.CultureInfo) - resourceCulture = value - End Set - End Property - End Module -End Namespace diff --git a/VBNET/My Project/Resources.resx b/VBNET/My Project/Resources.resx deleted file mode 100644 index af7dbeb..0000000 --- a/VBNET/My Project/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/VBNET/My Project/Settings.Designer.vb b/VBNET/My Project/Settings.Designer.vb deleted file mode 100644 index 4042033..0000000 --- a/VBNET/My Project/Settings.Designer.vb +++ /dev/null @@ -1,73 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:4.0.30319.42000 -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Option Explicit On - - -Namespace My - - _ - Partial Friend NotInheritable Class MySettings - Inherits Global.System.Configuration.ApplicationSettingsBase - - Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) - -#Region "My.Settings Auto-Save Functionality" -#If _MyType = "WindowsForms" Then - Private Shared addedHandler As Boolean - - Private Shared addedHandlerLockObject As New Object - - _ - Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) - If My.Application.SaveMySettingsOnExit Then - My.Settings.Save() - End If - End Sub -#End If -#End Region - - Public Shared ReadOnly Property [Default]() As MySettings - Get - -#If _MyType = "WindowsForms" Then - If Not addedHandler Then - SyncLock addedHandlerLockObject - If Not addedHandler Then - AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings - addedHandler = True - End If - End SyncLock - End If -#End If - Return defaultInstance - End Get - End Property - End Class -End Namespace - -Namespace My - - _ - Friend Module MySettingsProperty - - _ - Friend ReadOnly Property Settings() As Global.VBNET.My.MySettings - Get - Return Global.VBNET.My.MySettings.Default - End Get - End Property - End Module -End Namespace diff --git a/VBNET/My Project/Settings.settings b/VBNET/My Project/Settings.settings deleted file mode 100644 index 85b890b..0000000 --- a/VBNET/My Project/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/VBNET/TaskDialog.vb b/VBNET/TaskDialog.vb deleted file mode 100644 index e2d6b18..0000000 --- a/VBNET/TaskDialog.vb +++ /dev/null @@ -1,678 +0,0 @@ -Imports System.IO -Imports System.Reflection -Imports System.Runtime.InteropServices -Imports System.Text -Imports System.Text.RegularExpressions -Imports System.Threading - -Public Delegate Function PFTASKDIALOGCALLBACK(hwnd As IntPtr, - msg As UInteger, - wParam As IntPtr, - lParam As IntPtr, - lpRefData As IntPtr) As Integer -Public Class Msg - Public Shared Property SupportURL As String - - Public Shared Sub Show(mainInstruction As String, Optional content As String = Nothing) - Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok) - End Sub - - Public Shared Sub ShowError(mainInstruction As String, Optional content As String = Nothing) - If mainInstruction = "" Then mainInstruction = content - If mainInstruction = "" Then Exit Sub - - Using td As New TaskDialog(Of String) - td.AllowCancel = False - - If content = "" Then - If mainInstruction.Length < 80 Then - td.MainInstruction = mainInstruction - Else - td.Content = mainInstruction - End If - Else - td.MainInstruction = mainInstruction - td.Content = content - End If - - td.MainIcon = MsgIcon.Error - td.Footer = "[copymsg Copy Message]" - If SupportURL <> "" Then td.Footer += $" [{SupportURL} Contact Support]" - td.Show() - End Using - End Sub - - Public Shared Sub ShowException(e As Exception) - Try - Using td As New TaskDialog(Of String) - td.MainInstruction = e.GetType.Name - td.Content = e.Message - td.MainIcon = MsgIcon.Error - td.ExpandedInformation = e.ToString - td.Footer = "[copymsg Copy Message]" - If SupportURL <> "" Then td.Footer += $" [{SupportURL} Contact Support]" - td.Show() - End Using - Catch - MsgBox(e.GetType.Name + vbCrLf + vbCrLf + e.Message + vbCrLf + vbCrLf + e.ToString, MsgBoxStyle.Critical) - End Try - End Sub - - Shared ShownMessages As String - - Public Shared Sub ShowWarning(mainInstruction As String, - Optional content As String = Nothing, - Optional onlyOnce As Boolean = False) - - If onlyOnce AndAlso ShownMessages?.Contains(mainInstruction + content) Then Exit Sub - Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok) - If onlyOnce Then ShownMessages += mainInstruction + content - End Sub - - Public Shared Function ShowQuestion(mainInstruction As String, - Optional buttons As MsgButtons = MsgButtons.OkCancel) As MsgResult - - Return Show(mainInstruction, Nothing, MsgIcon.None, buttons) - End Function - - Public Shared Function ShowQuestion(mainInstruction As String, - content As String, - Optional buttons As MsgButtons = MsgButtons.OkCancel) As MsgResult - Return Show(mainInstruction, content, MsgIcon.None, buttons) - End Function - - Public Shared Function Show(mainInstruction As String, - content As String, - icon As MsgIcon, - buttons As MsgButtons, - Optional defaultButton As MsgResult = MsgResult.None) As MsgResult - - If mainInstruction Is Nothing Then mainInstruction = "" - - Using td As New TaskDialog(Of MsgResult) - td.AllowCancel = False - td.DefaultButton = defaultButton - td.MainIcon = icon - - If content Is Nothing Then - If mainInstruction.Length < 80 Then - td.MainInstruction = mainInstruction - Else - td.Content = mainInstruction - End If - Else - td.MainInstruction = mainInstruction - td.Content = content - End If - - If buttons = MsgButtons.OkCancel Then - td.AddButton("OK", MsgResult.OK) - td.AddButton("Cancel", MsgResult.Cancel) 'don't use system language - Else - td.CommonButtons = buttons - End If - - Return td.Show() - End Using - End Function -End Class - -Public Class TaskDialog(Of T) - Inherits TaskDialogNative - Implements IDisposable - - Private IdValueDic As New Dictionary(Of Integer, T) - Private IdTextDic As New Dictionary(Of Integer, String) - Private CommandLinkShieldList As New List(Of Integer) - Private ButtonArray As IntPtr, RadioButtonArray As IntPtr - Private Buttons As New List(Of TASKDIALOG_BUTTON) - Private RadioButtons As New List(Of TASKDIALOG_BUTTON) - - Private Config As TASKDIALOGCONFIG - - Sub New() - Config = New TASKDIALOGCONFIG() - - Config.cbSize = CUInt(Marshal.SizeOf(Config)) - Config.hwndParent = GetHandle() - Config.hInstance = IntPtr.Zero - Config.dwFlags = TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION - Config.dwCommonButtons = MsgButtons.None - Config.MainIcon = New TASKDIALOGCONFIG_ICON_UNION(0) - Config.FooterIcon = New TASKDIALOGCONFIG_ICON_UNION(0) - Config.cxWidth = 0 - - Config.cButtons = 0 - Config.cRadioButtons = 0 - Config.pButtons = IntPtr.Zero - Config.pRadioButtons = IntPtr.Zero - Config.nDefaultButton = 0 - Config.nDefaultRadioButton = 0 - - Config.pszWindowTitle = DirectCast(Assembly.GetEntryAssembly().GetCustomAttributes(GetType(AssemblyProductAttribute), True)(0), AssemblyProductAttribute).Product - Config.pszMainInstruction = "" - Config.pszContent = "" - Config.pszVerificationText = Nothing - Config.pszExpandedInformation = Nothing - Config.pszExpandedControlText = Nothing - Config.pszCollapsedControlText = Nothing - Config.pszFooter = Nothing - - Config.pfCallback = New PFTASKDIALOGCALLBACK(AddressOf DialogProc) - End Sub - - Function GetHandle() As IntPtr - Dim sb As New StringBuilder(260) - Dim foregroundHandle = GetForegroundWindow() - GetWindowModuleFileName(foregroundHandle, sb, 260) - - If Path.GetFileName(sb.ToString.Replace(".vshost", "")) = - Path.GetFileName(System.Reflection.Assembly.GetEntryAssembly().Location) Then - - Return foregroundHandle - End If - End Function - -#Region "Constants" - Const TDE_CONTENT As Integer = 0 - Const TDE_EXPANDED_INFORMATION As Integer = 1 - Const TDE_FOOTER As Integer = 2 - Const TDE_MAIN_INSTRUCTION As Integer = 3 - - Const TDN_CREATED As Integer = 0 - Const TDN_NAVIGATED As Integer = 1 - Const TDN_BUTTON_CLICKED As Integer = 2 - Const TDN_HYPERLINK_CLICKED As Integer = 3 - Const TDN_TIMER As Integer = 4 - Const TDN_DESTROYED As Integer = 5 - Const TDN_RADIO_BUTTON_CLICKED As Integer = 6 - Const TDN_DIALOG_CONSTRUCTED As Integer = 7 - Const TDN_VERIFICATION_CLICKED As Integer = 8 - Const TDN_HELP As Integer = 9 - Const TDN_EXPANDO_BUTTON_CLICKED As Integer = 10 - - Const TDM_NAVIGATE_PAGE As Integer = &H400 + 101 - Const TDM_CLICK_BUTTON As Integer = &H400 + 102 'wParam = Button ID - Const TDM_SET_MARQUEE_PROGRESS_BAR As Integer = &H400 + 103 'wParam = 0 (nonMarque) wParam != 0 (Marquee) - Const TDM_SET_PROGRESS_BAR_STATE As Integer = &H400 + 104 'wParam = new progress state - Const TDM_SET_PROGRESS_BAR_RANGE As Integer = &H400 + 105 'lParam = MAKELPARAM(nMinRange, nMaxRange) - Const TDM_SET_PROGRESS_BAR_POS As Integer = &H400 + 106 'wParam = new position - Const TDM_SET_PROGRESS_BAR_MARQUEE As Integer = &H400 + 107 'wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints) - Const TDM_SET_ELEMENT_TEXT As Integer = &H400 + 108 'wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) - Const TDM_CLICK_RADIO_BUTTON As Integer = &H400 + 110 'wParam = Radio Button ID - Const TDM_ENABLE_BUTTON As Integer = &H400 + 111 'lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID - Const TDM_ENABLE_RADIO_BUTTON As Integer = &H400 + 112 'lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID - Const TDM_CLICK_VERIFICATION As Integer = &H400 + 113 'wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus) - Const TDM_UPDATE_ELEMENT_TEXT As Integer = &H400 + 114 'wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) - Const TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE As Integer = &H400 + 115 'wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required) - Const TDM_UPDATE_ICON As Integer = &H400 + 116 'wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise) -#End Region - -#Region "Properties" - - Private AllowCancelValue As Boolean - - WriteOnly Property AllowCancel() As Boolean - Set(Value As Boolean) - If Value Then - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION - ElseIf (Config.dwFlags And TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION) = TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION Then - Config.dwFlags = Config.dwFlags Xor TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION - End If - End Set - End Property - - Property MainInstruction() As String - Get - Return Config.pszMainInstruction - End Get - Set(Value As String) - Config.pszMainInstruction = Value - End Set - End Property - - Property Content() As String - Get - Return Config.pszContent - End Get - Set(Value As String) - Config.pszContent = ExpandWikiMarkup(Value) - End Set - End Property - - Property ExpandedInformation() As String - Get - Return Config.pszExpandedInformation - End Get - Set(Value As String) - Config.pszExpandedInformation = ExpandWikiMarkup(Value) - End Set - End Property - - Property VerificationText() As String - Get - Return Config.pszVerificationText - End Get - Set(Value As String) - Config.pszVerificationText = Value - End Set - End Property - - Property DefaultButton() As MsgResult - Get - Return CType(Config.nDefaultButton, MsgResult) - End Get - Set(Value As MsgResult) - Config.nDefaultButton = Value - End Set - End Property - - Property Footer() As String - Get - Return Config.pszFooter - End Get - Set(Value As String) - Config.pszFooter = ExpandWikiMarkup(Value) - End Set - End Property - - WriteOnly Property MainIcon() As MsgIcon - Set(Value As MsgIcon) - Config.MainIcon = New TASKDIALOGCONFIG_ICON_UNION(Value) - End Set - End Property - - Private SelectedIDValue As Integer = -1 - - Property SelectedID As Integer - Get - Return SelectedIDValue - End Get - Set(value As Integer) - For Each i In IdValueDic - If i.Key = value Then SelectedIDValue = value - Next - End Set - End Property - - Private SelectedValueValue As T - - Property SelectedValue() As T - Get - If IdValueDic.ContainsKey(SelectedID) Then Return IdValueDic(SelectedID) - Return SelectedValueValue - End Get - Set(value As T) - SelectedValueValue = value - End Set - End Property - - Private SelectedTextValue As String - - Property SelectedText() As String - Get - If IdTextDic.ContainsKey(SelectedID) Then Return IdTextDic(SelectedID) - Return SelectedTextValue - End Get - Set(value As String) - SelectedTextValue = value - End Set - End Property - - Property CheckBoxChecked() As Boolean - Get - Return (Config.dwFlags And TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) = TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED - End Get - Set(value As Boolean) - If value Then - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED - ElseIf CheckBoxChecked Then - Config.dwFlags = Config.dwFlags Xor TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED - End If - End Set - End Property - - Private CommonButtonsValue As MsgButtons - - Property CommonButtons() As MsgButtons - Get - Return Config.dwCommonButtons - End Get - Set(Value As MsgButtons) - Config.dwCommonButtons = Value - End Set - End Property - - Private TimeoutValue As Integer - - Property Timeout As Integer - Get - Return CInt(TimeoutValue / 1000) - End Get - Set(Value As Integer) - TimeoutValue = Value * 1000 - - If Value > 0 Then - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER - End If - End Set - End Property -#End Region - -#Region "Methods" - - Sub AddButton(text As String, value As T) - Dim id = 1000 + IdValueDic.Count + 1 - IdValueDic(id) = value - Buttons.Add(New TASKDIALOG_BUTTON(id, text)) - End Sub - - Function ExpandWikiMarkup(value As String) As String - If value.Contains("[") Then - Dim re As New Regex("\[(.*?) (.+?)\]") - Dim m = re.Match(value) - - If m.Success Then - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS - value = re.Replace(value, "$2") - End If - End If - - Return value - End Function - - Sub AddCommandLink(text As String, Optional value As T = Nothing) - Dim id = 1000 + IdValueDic.Count + 1 - Dim temp As Object = text - IdValueDic(id) = If(value Is Nothing, CType(temp, T), value) - IdTextDic(id) = text - Buttons.Add(New TASKDIALOG_BUTTON(id, text)) - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS - End Sub - - Sub AddCommandLink(text As String, - description As String, - value As T, - Optional setShield As Boolean = False) - - Dim id = 1000 + IdValueDic.Count + 1 - IdValueDic(id) = value - If setShield Then CommandLinkShieldList.Add(id) - If description <> "" Then text = text + vbCrLf + description - Buttons.Add(New TASKDIALOG_BUTTON(id, text)) - Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS - End Sub - - Sub AddRadioButton(text As String, value As T) - Dim id = 1000 + IdValueDic.Count + 1 - IdValueDic(id) = value - RadioButtons.Add(New TASKDIALOG_BUTTON(id, text)) - End Sub - - Function Show() As T - MarshalDialogControlStructs() - Dim isChecked As Boolean - Dim hr = TaskDialogIndirect(Config, Nothing, Nothing, isChecked) - CheckBoxChecked = isChecked - If hr < 0 Then Marshal.ThrowExceptionForHR(hr) - If TypeOf SelectedValue Is MsgResult Then SelectedValue = DirectCast(CObj(SelectedID), T) - Return SelectedValue - End Function - - Private ExitTickCount As Integer - - Function DialogProc(hwnd As IntPtr, - msg As UInteger, - wParam As IntPtr, - lParam As IntPtr, - lpRefData As IntPtr) As Integer - Select Case msg - Case TDN_BUTTON_CLICKED, TDN_RADIO_BUTTON_CLICKED - If TypeOf SelectedValue Is MsgResult Then - SelectedIDValue = wParam.ToInt32 - Else - SelectedID = wParam.ToInt32 - End If - Case TDN_TIMER - If ExitTickCount = 0 Then - ExitTickCount = Environment.TickCount + Timeout * 1000 - End If - - If Environment.TickCount > ExitTickCount Then - SendMessage(hwnd, TDM_CLICK_BUTTON, New IntPtr(MsgResult.OK), IntPtr.Zero) - End If - Case TDN_HYPERLINK_CLICKED - Dim url = Marshal.PtrToStringUni(lParam) - - If url.StartsWith("mailto") OrElse url.StartsWith("http") Then - Process.Start(url) - ElseIf url = "copymsg" Then - Dim thread As New Thread( - New ThreadStart(Sub() - System.Windows.Forms.Clipboard.SetText(MainInstruction + vbCrLf + vbCrLf + Content + vbCrLf + vbCrLf + ExpandedInformation) - MsgBox("Message was copied to clipboard.", - MsgBoxStyle.Information, - DirectCast(Assembly.GetEntryAssembly().GetCustomAttributes(GetType(AssemblyProductAttribute), True)(0), AssemblyProductAttribute).Product) - End Sub)) - thread.SetApartmentState(ApartmentState.STA) - thread.Start() - End If - Case TDN_CREATED - For Each i In CommandLinkShieldList - SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, New IntPtr(i), New IntPtr(1)) - Next - End Select - End Function - - Sub MarshalDialogControlStructs() - If Not Buttons Is Nothing AndAlso Buttons.Count > 0 Then - ButtonArray = AllocateAndMarshalButtons(Buttons) - Config.pButtons = ButtonArray - Config.cButtons = CUInt(Buttons.Count) - End If - - If Not RadioButtons Is Nothing AndAlso RadioButtons.Count > 0 Then - RadioButtonArray = AllocateAndMarshalButtons(RadioButtons) - Config.pRadioButtons = RadioButtonArray - Config.cRadioButtons = CUInt(RadioButtons.Count) - End If - End Sub - - Shared Function AllocateAndMarshalButtons(structs As List(Of TASKDIALOG_BUTTON)) As IntPtr - Dim initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(TASKDIALOG_BUTTON)) * structs.Count) - Dim currentPtr = initialPtr - - For Each button In structs - Marshal.StructureToPtr(button, currentPtr, False) - currentPtr = CType((currentPtr.ToInt64 + Marshal.SizeOf(button)), IntPtr) - Next - - Return initialPtr - End Function - -#End Region - -#Region "IDispose Pattern" - - Private disposed As Boolean - - Sub Dispose() Implements IDisposable.Dispose - Dispose(True) - GC.SuppressFinalize(Me) - End Sub - - Protected Overrides Sub Finalize() - Try - Dispose(False) - Finally - MyBase.Finalize() - End Try - End Sub - - Protected Sub Dispose(disposing As Boolean) - If Not disposed Then - disposed = True - - If ButtonArray <> IntPtr.Zero Then - Marshal.FreeHGlobal(ButtonArray) - ButtonArray = IntPtr.Zero - End If - - If RadioButtonArray <> IntPtr.Zero Then - Marshal.FreeHGlobal(RadioButtonArray) - RadioButtonArray = IntPtr.Zero - End If - - If disposing Then - End If - End If - End Sub - -#End Region - -End Class - -Public Class TaskDialogNative - - Shared Function TaskDialogIndirect(<[In]()> pTaskConfig As TASKDIALOGCONFIG, ByRef pnButton As Integer, ByRef pnRadioButton As Integer, ByRef pVerificationFlagChecked As Boolean) As Integer - End Function - - - Shared Function GetForegroundWindow() As IntPtr - End Function - - - Shared Function GetWindowModuleFileName(hwnd As IntPtr, - lpszFileName As StringBuilder, - cchFileNameMax As UInteger) As UInteger - End Function - - - Shared Function SendMessage(handle As IntPtr, - message As Int32, - wParam As IntPtr, - lParam As IntPtr) As IntPtr - End Function - - - Public Class TASKDIALOGCONFIG - Public cbSize As UInteger - Public hwndParent As IntPtr - Public hInstance As IntPtr - Public dwFlags As TASKDIALOG_FLAGS - Public dwCommonButtons As MsgButtons - - Public pszWindowTitle As String - Public MainIcon As TASKDIALOGCONFIG_ICON_UNION - - Public pszMainInstruction As String - - Public pszContent As String - Public cButtons As UInteger - Public pButtons As IntPtr - Public nDefaultButton As Integer - Public cRadioButtons As UInteger - Public pRadioButtons As IntPtr - Public nDefaultRadioButton As Integer - - Public pszVerificationText As String - - Public pszExpandedInformation As String - - Public pszExpandedControlText As String - - Public pszCollapsedControlText As String - Public FooterIcon As TASKDIALOGCONFIG_ICON_UNION - - Public pszFooter As String - Public pfCallback As PFTASKDIALOGCALLBACK - Public lpCallbackData As IntPtr - Public cxWidth As UInteger - End Class - - Public Enum TASKDIALOG_FLAGS - NONE = 0 - TDF_ENABLE_HYPERLINKS = &H1 - TDF_USE_HICON_MAIN = &H2 - TDF_USE_HICON_FOOTER = &H4 - TDF_ALLOW_DIALOG_CANCELLATION = &H8 - TDF_USE_COMMAND_LINKS = &H10 - TDF_USE_COMMAND_LINKS_NO_ICON = &H20 - TDF_EXPAND_FOOTER_AREA = &H40 - TDF_EXPANDED_BY_DEFAULT = &H80 - TDF_VERIFICATION_FLAG_CHECKED = &H100 - TDF_SHOW_PROGRESS_BAR = &H200 - TDF_SHOW_MARQUEE_PROGRESS_BAR = &H400 - TDF_CALLBACK_TIMER = &H800 - TDF_POSITION_RELATIVE_TO_WINDOW = &H1000 - TDF_RTL_LAYOUT = &H2000 - TDF_NO_DEFAULT_RADIO_BUTTON = &H4000 - End Enum - - - Public Structure TASKDIALOGCONFIG_ICON_UNION - Sub New(i As Integer) - spacer = IntPtr.Zero - pszIcon = 0 - hMainIcon = i - End Sub - - - Public hMainIcon As Integer - - Public pszIcon As Integer - - Public spacer As IntPtr - End Structure - - - Public Structure TASKDIALOG_BUTTON - Sub New(n As Integer, txt As String) - nButtonID = n - pszButtonText = txt - End Sub - - Public nButtonID As Integer - - Public pszButtonText As String - End Structure -End Class - -Public Enum MsgButtons - None = &H0 - Ok = &H1 - Yes = &H2 - No = &H4 - Cancel = &H8 - Retry = &H10 - RetryCancel = Retry Or Cancel - Close = &H20 - OkCancel = Ok Or Cancel - YesNo = Yes Or No - YesNoCancel = YesNo Or Cancel -End Enum - -Public Enum MsgIcon - None = 0 - Warning = 65535 'TD_WARNING_ICON - [Error] = 65534 'TD_ERROR_ICON - Info = 65533 'TD_INFORMATION_ICON - Shield = 65532 'TD_SHIELD_ICON - SecurityShieldBlue = 65531 - SecurityWarning = 65530 - SecurityError = 65529 - SecuritySuccess = 65528 - SecurityShieldGray = 65527 -End Enum - -Public Enum MsgResult - None = 0 - OK = 1 - Cancel = 2 - Abort = 3 - Retry = 4 - Ignore = 5 - Yes = 6 - No = 7 -End Enum \ No newline at end of file diff --git a/VBNET/VBNET.vbproj b/VBNET/VBNET.vbproj deleted file mode 100644 index a6b1589..0000000 --- a/VBNET/VBNET.vbproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - AnyCPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F} - Library - VBNET - VBNET - 512 - Windows - v4.7.2 - true - - - true - full - true - true - bin\Debug\ - - - 42353,42354,42355 - 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 - - - pdbonly - false - true - true - bin\Release\ - - - 42353,42354,42355 - 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 - - - On - - - Binary - - - On - - - On - - - - - - - - - - - - - - - - - - - - - - - - - - True - Application.myapp - - - True - True - Resources.resx - - - True - Settings.settings - True - - - - - - VbMyResourcesResXFileCodeGenerator - Resources.Designer.vb - My.Resources - Designer - - - - - MyApplicationCodeGenerator - Application.Designer.vb - - - SettingsSingleFileGenerator - My - Settings.Designer.vb - - - - \ No newline at end of file diff --git a/mpv.net.sln b/mpv.net.sln index 906e38c..26abd4e 100644 --- a/mpv.net.sln +++ b/mpv.net.sln @@ -9,8 +9,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "RatingAddon\ EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CSScriptAddon", "CSScriptAddon\CSScriptAddon.vbproj", "{71808A87-8B1C-4DF8-957C-D79C3B164CCA}" EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "VBNET", "VBNET\VBNET.vbproj", "{A1D11294-05BF-4D77-B008-AECF1AA93C9F}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,18 +55,6 @@ Global {71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x64.Build.0 = Release|Any CPU {71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.ActiveCfg = Release|Any CPU {71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.Build.0 = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x64.ActiveCfg = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x64.Build.0 = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x86.ActiveCfg = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x86.Build.0 = Debug|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|Any CPU.Build.0 = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x64.ActiveCfg = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x64.Build.0 = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x86.ActiveCfg = Release|Any CPU - {A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/mpv.net/Addon.cs b/mpv.net/Addon.cs index 269be0c..4c796bc 100644 --- a/mpv.net/Addon.cs +++ b/mpv.net/Addon.cs @@ -5,7 +5,7 @@ using System.ComponentModel.Composition.Hosting; using System.IO; using System.Windows.Forms; -using VBNET; +using Sys; namespace mpvnet { diff --git a/mpv.net/Command.cs b/mpv.net/Command.cs index 1ab4f3c..e1b6d49 100644 --- a/mpv.net/Command.cs +++ b/mpv.net/Command.cs @@ -6,7 +6,8 @@ using System.Linq; using System.Reflection; using System.Windows.Forms; using System.Windows.Interop; -using VBNET; + +using Sys; namespace mpvnet { diff --git a/mpv.net/MainForm.cs b/mpv.net/MainForm.cs index 8183462..3686263 100644 --- a/mpv.net/MainForm.cs +++ b/mpv.net/MainForm.cs @@ -7,11 +7,11 @@ using System.Windows.Forms; using System.Linq; using System.Collections.Generic; using System.ComponentModel; - -using VBNET; using System.Globalization; using System.Diagnostics; +using Sys; + namespace mpvnet { public partial class MainForm : Form diff --git a/mpv.net/PowerShellScript.cs b/mpv.net/PowerShellScript.cs index 728de9a..3ffe5f4 100644 --- a/mpv.net/PowerShellScript.cs +++ b/mpv.net/PowerShellScript.cs @@ -4,8 +4,8 @@ using System.Threading; using System.Management.Automation.Runspaces; using System.Reflection; using System.Threading.Tasks; -using System.Windows.Forms; -using VBNET; + +using Sys; namespace mpvnet { diff --git a/mpv.net/PythonScript.cs b/mpv.net/PythonScript.cs index 1e30cf7..b00869e 100644 --- a/mpv.net/PythonScript.cs +++ b/mpv.net/PythonScript.cs @@ -1,9 +1,9 @@ using System; using System.Reflection; -using System.Windows.Forms; -using IronPython.Hosting; + using Microsoft.Scripting.Hosting; -using VBNET; +using IronPython.Hosting; +using Sys; using PyRT = IronPython.Runtime; namespace mpvnet diff --git a/mpv.net/Sys/TaskDialog.cs b/mpv.net/Sys/TaskDialog.cs new file mode 100644 index 0000000..142a8df --- /dev/null +++ b/mpv.net/Sys/TaskDialog.cs @@ -0,0 +1,646 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using System.Windows.Forms; + +using Microsoft.VisualBasic.CompilerServices; + +namespace Sys +{ + public class Msg + { + private static string ShownMessages; + + public static string SupportURL { get; set; } + + public static void Show(string mainInstruction, string content = null) + { + Msg.Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok, MsgResult.None); + } + + public static void ShowError(string mainInstruction, string content = null) + { + using (TaskDialog td = new TaskDialog()) + { + td.AllowCancel = false; + + if (string.IsNullOrEmpty(content)) + { + if (mainInstruction.Length < 80) + td.MainInstruction = mainInstruction; + else + td.Content = mainInstruction; + } + else + { + td.MainInstruction = mainInstruction; + td.Content = content; + } + + td.MainIcon = MsgIcon.Error; + td.Footer = "[copymsg Copy Message]"; + + if (!string.IsNullOrEmpty(Msg.SupportURL)) + td.Footer += $" [{SupportURL} Contact Support]"; + + td.Show(); + } + } + + public static void ShowException(Exception e) + { + try + { + using (TaskDialog td = new TaskDialog()) + { + td.MainInstruction = e.GetType().Name; + td.Content = e.Message; + td.MainIcon = MsgIcon.Error; + td.ExpandedInformation = e.ToString(); + td.Footer = "[copymsg Copy Message]"; + + if (!string.IsNullOrEmpty(Msg.SupportURL)) + td.Footer += $" [{SupportURL} Contact Support]"; + + td.Show(); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.GetType().Name + "\n\n" + e.Message + "\n\n" + e.ToString(), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + public static void ShowWarning(string mainInstruction, + string content = null, + bool onlyOnce = false) + { + if (onlyOnce && Msg.ShownMessages != null && + Msg.ShownMessages.Contains(mainInstruction + content)) + return; + + Msg.Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok, MsgResult.None); + if (!onlyOnce) return; + Msg.ShownMessages += mainInstruction + content; + } + + public static MsgResult ShowQuestion(string mainInstruction, + MsgButtons buttons = MsgButtons.OkCancel) + { + return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None); + } + + public static MsgResult ShowQuestion(string mainInstruction, + string content, + MsgButtons buttons = MsgButtons.OkCancel) + { + return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None); + } + + public static MsgResult Show(string mainInstruction, + string content, + MsgIcon icon, + MsgButtons buttons, + MsgResult defaultButton = MsgResult.None) + { + using (TaskDialog td = new TaskDialog()) + { + td.AllowCancel = false; + td.DefaultButton = defaultButton; + td.MainIcon = icon; + + if (content == null) + { + if (mainInstruction.Length < 80) + td.MainInstruction = mainInstruction; + else + td.Content = mainInstruction; + } + else + { + td.MainInstruction = mainInstruction; + td.Content = content; + } + if (buttons == MsgButtons.OkCancel) + { + td.AddButton("OK", MsgResult.OK); + td.AddButton("Cancel", MsgResult.Cancel); + } + else + td.CommonButtons = buttons; + return td.Show(); + } + } + } + + public class TaskDialog : TaskDialogNative, IDisposable + { + private Dictionary IdValueDic; + private Dictionary IdTextDic; + private List CommandLinkShieldList; + private IntPtr ButtonArray; + private IntPtr RadioButtonArray; + private List Buttons; + private List RadioButtons; + private TaskDialogNative.TASKDIALOGCONFIG Config; + const int TDE_CONTENT = 0; + const int TDE_EXPANDED_INFORMATION = 1; + const int TDE_FOOTER = 2; + const int TDE_MAIN_INSTRUCTION = 3; + const int TDN_CREATED = 0; + const int TDN_NAVIGATED = 1; + const int TDN_BUTTON_CLICKED = 2; + const int TDN_HYPERLINK_CLICKED = 3; + const int TDN_TIMER = 4; + const int TDN_DESTROYED = 5; + const int TDN_RADIO_BUTTON_CLICKED = 6; + const int TDN_DIALOG_CONSTRUCTED = 7; + const int TDN_VERIFICATION_CLICKED = 8; + const int TDN_HELP = 9; + const int TDN_EXPANDO_BUTTON_CLICKED = 10; + const int TDM_NAVIGATE_PAGE = 1125; + const int TDM_CLICK_BUTTON = 1126; + const int TDM_SET_MARQUEE_PROGRESS_BAR = 1127; + const int TDM_SET_PROGRESS_BAR_STATE = 1128; + const int TDM_SET_PROGRESS_BAR_RANGE = 1129; + const int TDM_SET_PROGRESS_BAR_POS = 1130; + const int TDM_SET_PROGRESS_BAR_MARQUEE = 1131; + const int TDM_SET_ELEMENT_TEXT = 1132; + const int TDM_CLICK_RADIO_BUTTON = 1134; + const int TDM_ENABLE_BUTTON = 1135; + const int TDM_ENABLE_RADIO_BUTTON = 1136; + const int TDM_CLICK_VERIFICATION = 1137; + const int TDM_UPDATE_ELEMENT_TEXT = 1138; + const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139; + const int TDM_UPDATE_ICON = 1140; + private T SelectedValueValue; + private string SelectedTextValue; + private int TimeoutValue; + private int ExitTickCount; + private bool disposed; + + public TaskDialog() + { + IdValueDic = new Dictionary(); + IdTextDic = new Dictionary(); + CommandLinkShieldList = new List(); + Buttons = new List(); + RadioButtons = new List(); + _SelectedID = -1; + Config = new TaskDialogNative.TASKDIALOGCONFIG(); + Config.cbSize = (uint)Marshal.SizeOf(Config); + Config.hwndParent = GetHandle(); + Config.hInstance = IntPtr.Zero; + Config.dwFlags = TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION; + Config.dwCommonButtons = MsgButtons.None; + Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0); + Config.FooterIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0); + Config.cxWidth = 0U; + Config.cButtons = 0U; + Config.cRadioButtons = 0U; + Config.pButtons = IntPtr.Zero; + Config.pRadioButtons = IntPtr.Zero; + Config.nDefaultButton = 0; + Config.nDefaultRadioButton = 0; + Config.pszWindowTitle = ((AssemblyProductAttribute)Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0]).Product; + Config.pszMainInstruction = ""; + Config.pszContent = ""; + Config.pfCallback = new PFTASKDIALOGCALLBACK(this.DialogProc); + } + + public IntPtr GetHandle() + { + StringBuilder lpszFileName = new StringBuilder(260); + IntPtr foregroundWindow = TaskDialogNative.GetForegroundWindow(); + TaskDialogNative.GetWindowModuleFileName(foregroundWindow, lpszFileName, 260U); + + if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) == + Path.GetFileName(Assembly.GetEntryAssembly().Location)) + return foregroundWindow; + + return IntPtr.Zero; + } + + public bool AllowCancel { + set { + if (value) + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION; + else + Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION; + } + } + + public string MainInstruction { + get => Config.pszMainInstruction; + set => Config.pszMainInstruction = value; + } + + public string Content { + get => Config.pszContent; + set => Config.pszContent = ExpandWikiMarkup(value); + } + + public string ExpandedInformation { + get => Config.pszExpandedInformation; + set => Config.pszExpandedInformation = ExpandWikiMarkup(value); + } + + public string VerificationText { + get => Config.pszVerificationText; + set => Config.pszVerificationText = value; + } + + public MsgResult DefaultButton { + get => (MsgResult)Config.nDefaultButton; + set => Config.nDefaultButton = (int)value; + } + + public string Footer { + get => Config.pszFooter; + set => Config.pszFooter = ExpandWikiMarkup(value); + } + + public MsgIcon MainIcon { + set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value); + } + + private int _SelectedID; + + public int SelectedID { + get => _SelectedID; + set { + foreach (var i in IdValueDic) + if (i.Key == value) _SelectedID = value; + } + } + + public T SelectedValue { + get { + if (IdValueDic.ContainsKey(SelectedID)) + return IdValueDic[SelectedID]; + return SelectedValueValue; + } + set => SelectedValueValue = value; + } + + public string SelectedText { + get { + if (IdTextDic.ContainsKey(SelectedID)) + return IdTextDic[SelectedID]; + return SelectedTextValue; + } + set => SelectedTextValue = value; + } + + public bool CheckBoxChecked { + get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) == TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED; + set { + if (value) + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED; + else + Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED; + } + } + + public MsgButtons CommonButtons { + get => Config.dwCommonButtons; + set => Config.dwCommonButtons = value; + } + + public int Timeout { + get => Convert.ToInt32(TimeoutValue / 1000.0); + set { + TimeoutValue = value * 1000; + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER; + } + } + + public void AddButton(string text, T value) + { + int n = 1000 + IdValueDic.Count + 1; + IdValueDic[n] = value; + Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text)); + } + + public string ExpandWikiMarkup(string value) + { + if (value.Contains("[")) + { + Regex regex = new Regex("\\[(.*?) (.+?)\\]"); + + if (regex.Match(value).Success) + { + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS; + value = regex.Replace(value, "$2"); + } + } + return value; + } + + public void AddCommandLink(string text, T value) + { + int n = 1000 + IdValueDic.Count + 1; + IdValueDic[n] = value == null ? (T)(object)text : value; + IdTextDic[n] = text; + Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text)); + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS; + } + + public void AddCommandLink(string text, string description, T value, bool setShield = false) + { + int n = 1000 + IdValueDic.Count + 1; + IdValueDic[n] = value; + if (setShield) CommandLinkShieldList.Add(n); + if (!string.IsNullOrEmpty(description)) text += "\n" + description; + Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text)); + Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS; + } + + public void AddRadioButton(string text, T value) + { + int n = 1000 + IdValueDic.Count + 1; + IdValueDic[n] = value; + RadioButtons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text)); + } + + public T Show() + { + MarshalDialogControlStructs(); + TaskDialogNative.TASKDIALOGCONFIG config = Config; + int errorCode = TaskDialogNative.TaskDialogIndirect(config, out int dummy1, out int dummy2, out bool isChecked); + if (errorCode < 0) Marshal.ThrowExceptionForHR(errorCode); + CheckBoxChecked = isChecked; + if (SelectedValue is MsgResult) SelectedValue = (T)(object)SelectedID; + return SelectedValue; + } + + public int DialogProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData) + { + switch (msg) + { + case 0: //TDN_CREATED + foreach (var i in CommandLinkShieldList) + SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, new IntPtr(i), new IntPtr(1)); + break; + case 2: //TDN_BUTTON_CLICKED + case 6: //TDN_RADIO_BUTTON_CLICKED + if (SelectedValue is MsgResult) + _SelectedID = wParam.ToInt32(); + else + SelectedID = wParam.ToInt32(); + break; + case 3: //TDN_HYPERLINK_CLICKED + string stringUni = Marshal.PtrToStringUni(lParam); + + if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http")) + Process.Start(stringUni); + if (Operators.CompareString(stringUni, "copymsg", false) == 0) + { + Thread thread = new Thread((ThreadStart)(() => { + Clipboard.SetText(MainInstruction + "\r\n\r\n" + Content + "\r\n\r\n" + ExpandedInformation); + MessageBox.Show("Message was copied to clipboard.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); + })); + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + } + break; + case 4: //TDN_TIMER + if (ExitTickCount == 0) ExitTickCount = Environment.TickCount + Timeout * 1000; + if (Environment.TickCount > ExitTickCount) + TaskDialogNative.SendMessage(hwnd, 1126, new IntPtr(1), IntPtr.Zero); + break; + } + return 0; + } + + public void MarshalDialogControlStructs() + { + if (Buttons != null && Buttons.Count > 0) + { + ButtonArray = TaskDialog.AllocateAndMarshalButtons(Buttons); + Config.pButtons = ButtonArray; + Config.cButtons = (uint)Buttons.Count; + } + + if (RadioButtons == null || RadioButtons.Count <= 0) return; + RadioButtonArray = TaskDialog.AllocateAndMarshalButtons(RadioButtons); + Config.pRadioButtons = RadioButtonArray; + Config.cRadioButtons = (uint)RadioButtons.Count; + } + + public static IntPtr AllocateAndMarshalButtons(List structs) + { + var initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TASKDIALOG_BUTTON)) * structs.Count); + var currentPtr = initialPtr; + + foreach (var button in structs) + { + Marshal.StructureToPtr(button, currentPtr, false); + currentPtr = (IntPtr)(currentPtr.ToInt64() + Marshal.SizeOf(button)); + } + + return initialPtr; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~TaskDialog() + { + Dispose(false); + } + + protected void Dispose(bool disposing) + { + if (disposed) return; + disposed = true; + + if (ButtonArray != IntPtr.Zero) + { + Marshal.FreeHGlobal(ButtonArray); + ButtonArray = IntPtr.Zero; + } + + if (RadioButtonArray != IntPtr.Zero) + { + Marshal.FreeHGlobal(RadioButtonArray); + RadioButtonArray = IntPtr.Zero; + } + } + } + + public delegate int PFTASKDIALOGCALLBACK( + IntPtr hwnd, + uint msg, + IntPtr wParam, + IntPtr lParam, + IntPtr lpRefData); + + public class TaskDialogNative + { + [DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int TaskDialogIndirect( + [In] TaskDialogNative.TASKDIALOGCONFIG pTaskConfig, + out int pnButton, + out int pnRadioButton, + [MarshalAs(UnmanagedType.Bool)] out bool pVerificationFlagChecked); + + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern uint GetWindowModuleFileName( + IntPtr hwnd, + StringBuilder lpszFileName, + uint cchFileNameMax); + + [DllImport("user32.dll")] + public static extern IntPtr SendMessage( + IntPtr handle, + int message, + IntPtr wParam, + IntPtr lParam); + + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + public class TASKDIALOGCONFIG + { + public uint cbSize; + public IntPtr hwndParent; + public IntPtr hInstance; + public TaskDialogNative.TASKDIALOG_FLAGS dwFlags; + public MsgButtons dwCommonButtons; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszWindowTitle; + public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszMainInstruction; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszContent; + public uint cButtons; + public IntPtr pButtons; + public int nDefaultButton; + public uint cRadioButtons; + public IntPtr pRadioButtons; + public int nDefaultRadioButton; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszVerificationText; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszExpandedInformation; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszExpandedControlText; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszCollapsedControlText; + public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszFooter; + public PFTASKDIALOGCALLBACK pfCallback; + public IntPtr lpCallbackData; + public uint cxWidth; + } + + public enum TASKDIALOG_FLAGS + { + NONE = 0, + TDF_ENABLE_HYPERLINKS = 1, + TDF_USE_HICON_MAIN = 2, + TDF_USE_HICON_FOOTER = 4, + TDF_ALLOW_DIALOG_CANCELLATION = 8, + TDF_USE_COMMAND_LINKS = 16, + TDF_USE_COMMAND_LINKS_NO_ICON = 32, + TDF_EXPAND_FOOTER_AREA = 64, + TDF_EXPANDED_BY_DEFAULT = 128, + TDF_VERIFICATION_FLAG_CHECKED = 256, + TDF_SHOW_PROGRESS_BAR = 512, + TDF_SHOW_MARQUEE_PROGRESS_BAR = 1024, + TDF_CALLBACK_TIMER = 2048, + TDF_POSITION_RELATIVE_TO_WINDOW = 4096, + TDF_RTL_LAYOUT = 8192, + TDF_NO_DEFAULT_RADIO_BUTTON = 16384, + } + + [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] + public struct TASKDIALOGCONFIG_ICON_UNION + { + [FieldOffset(0)] + public int hMainIcon; + [FieldOffset(0)] + public int pszIcon; + [FieldOffset(0)] + public IntPtr spacer; + + public TASKDIALOGCONFIG_ICON_UNION(int i) + { + this = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(); + spacer = IntPtr.Zero; + pszIcon = 0; + hMainIcon = i; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + public struct TASKDIALOG_BUTTON + { + public int nButtonID; + [MarshalAs(UnmanagedType.LPWStr)] + public string pszButtonText; + + public TASKDIALOG_BUTTON(int n, string txt) + { + this = new TaskDialogNative.TASKDIALOG_BUTTON(); + nButtonID = n; + pszButtonText = txt; + } + } + } + + public enum MsgButtons + { + None = 0, + Ok = 1, + Yes = 2, + No = 4, + YesNo = 6, + Cancel = 8, + OkCancel = 9, + YesNoCancel = 14, + Retry = 16, + RetryCancel = 24, + Close = 32, + } + + public enum MsgResult + { + None, + OK, + Cancel, + Abort, + Retry, + Ignore, + Yes, + No, + } + + public enum MsgIcon + { + None = 0, + SecurityShieldGray = 65527, + SecuritySuccess = 65528, + SecurityError = 65529, + SecurityWarning = 65530, + SecurityShieldBlue = 65531, + Shield = 65532, + Info = 65533, + Error = 65534, + Warning = 65535, + } +} \ No newline at end of file diff --git a/mpv.net/mp.cs b/mpv.net/mp.cs index 3611be6..46eb6de 100644 --- a/mpv.net/mp.cs +++ b/mpv.net/mp.cs @@ -11,7 +11,8 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using VBNET; +using Sys; + using static mpvnet.libmpv; using static mpvnet.Native; @@ -85,8 +86,9 @@ namespace mpvnet { td.MainInstruction = "Choose a settings folder."; td.Content = "[https://mpv.io/manual/master/#files-on-windows MPV documentation about files on Windows.]"; - td.AddCommandLink("appdata", appdataFolder); - td.AddCommandLink("portable", portableFolder); + td.AddCommandLink("appdata", appdataFolder, appdataFolder); + td.AddCommandLink("portable", portableFolder, portableFolder); + td.AllowCancel = false; _MpvConfFolder = td.Show(); } } @@ -269,7 +271,6 @@ namespace mpvnet Message m = new Message() { Msg = 0x0202 }; // WM_LBUTTONUP Native.SendMessage(MainForm.Instance.Handle, m.Msg, m.WParam, m.LParam); })); - } } if (!found) diff --git a/mpv.net/mpv.net.csproj b/mpv.net/mpv.net.csproj index 98f714e..aeacfa6 100644 --- a/mpv.net/mpv.net.csproj +++ b/mpv.net/mpv.net.csproj @@ -185,6 +185,7 @@ + ConfWindow.xaml @@ -240,12 +241,6 @@ - - - {a1d11294-05bf-4d77-b008-aecf1aa93c9f} - VBNET - - MSBuild:Compile