37371ca9d6
- primo rilascio
431 lines
17 KiB
VB.net
431 lines
17 KiB
VB.net
' Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
|
|
'
|
|
' Step 1a) Using this custom control in a XAML file that exists in the current project.
|
|
' Add this XmlNamespace attribute to the root element of the markup file where it is
|
|
' to be used:
|
|
'
|
|
' xmlns:MyNamespace="clr-namespace:EgtWPFLib5"
|
|
'
|
|
'
|
|
' Step 1b) Using this custom control in a XAML file that exists in a different project.
|
|
' Add this XmlNamespace attribute to the root element of the markup file where it is
|
|
' to be used:
|
|
'
|
|
' xmlns:MyNamespace="clr-namespace:EgtWPFLib5;assembly=EgtWPFLib5"
|
|
'
|
|
' You will also need to add a project reference from the project where the XAML file lives
|
|
' to this project and Rebuild to avoid compilation errors:
|
|
'
|
|
' Right click on the target project in the Solution Explorer and
|
|
' "Add Reference"->"Projects"->[Browse to and select this project]
|
|
'
|
|
'
|
|
' Step 2)
|
|
' Go ahead and use your control in the XAML file. Note that Intellisense in the
|
|
' XML editor does not currently work on custom controls and its child elements.
|
|
'
|
|
' <MyNamespace:EgtMainWindow/>
|
|
'
|
|
|
|
Imports Microsoft.Win32
|
|
Imports System
|
|
Imports System.Collections.Generic
|
|
Imports System.Drawing
|
|
Imports System.Linq
|
|
Imports System.Text
|
|
Imports System.Threading.Tasks
|
|
Imports System.Windows
|
|
Imports System.Windows.Controls
|
|
Imports System.Windows.Forms
|
|
Imports System.Windows.Input
|
|
Imports System.Windows.Interop
|
|
|
|
Public Class EgtMainWindow
|
|
Inherits Window
|
|
|
|
Private _hwndSource As HwndSource
|
|
Private isMouseButtonDown As Boolean
|
|
Private isManualDrag As Boolean
|
|
Private mouseDownPosition As System.Windows.Point
|
|
Private positionBeforeDrag As System.Windows.Point
|
|
Private previousScreenBounds As System.Windows.Point
|
|
Public Property WindowRoot As Grid
|
|
Public Property LayoutRoot As Grid
|
|
Public Property MinimizeButton As System.Windows.Controls.Button
|
|
Public Property MaximizeButton As System.Windows.Controls.Button
|
|
Public Property RestoreButton As System.Windows.Controls.Button
|
|
Public Property CloseButton As System.Windows.Controls.Button
|
|
Public Property HeaderBar As Grid
|
|
Public Property HeightBeforeMaximize As Double
|
|
Public Property WidthBeforeMaximize As Double
|
|
Public Property PreviousState As WindowState
|
|
|
|
Shared Sub New()
|
|
'This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
|
|
'This style is defined in themes\generic.xaml
|
|
DefaultStyleKeyProperty.OverrideMetadata(GetType(EgtMainWindow), New FrameworkPropertyMetadata(GetType(EgtMainWindow)))
|
|
End Sub
|
|
|
|
Public Sub New()
|
|
Dim currentDPIScaleFactor As Double = CDbl(SystemHelper.GetCurrentDPIScaleFactor())
|
|
Dim screen As Screen = Screen.FromHandle((New WindowInteropHelper(Me)).Handle)
|
|
AddHandler MyBase.SizeChanged, AddressOf Me.OnSizeChanged
|
|
AddHandler MyBase.StateChanged, AddressOf Me.OnStateChanged
|
|
AddHandler MyBase.Loaded, AddressOf Me.OnLoaded
|
|
Dim workingArea As Rectangle = screen.WorkingArea
|
|
MyBase.MaxHeight = CDbl((workingArea.Height + 16)) / currentDPIScaleFactor
|
|
AddHandler SystemEvents.DisplaySettingsChanged, AddressOf Me.SystemEvents_DisplaySettingsChanged
|
|
Me.AddHandler(Window.MouseLeftButtonUpEvent, New MouseButtonEventHandler(AddressOf Me.OnMouseButtonUp), True)
|
|
Me.AddHandler(Window.MouseMoveEvent, New System.Windows.Input.MouseEventHandler(AddressOf Me.OnMouseMove))
|
|
End Sub
|
|
|
|
Public Sub New(Owner As Window)
|
|
Me.New()
|
|
Me.Owner = Owner
|
|
End Sub
|
|
|
|
Public Function GetRequiredTemplateChild(Of T As DependencyObject)(ByVal childName As String) As T
|
|
Return CType(MyBase.GetTemplateChild(childName), T)
|
|
End Function
|
|
|
|
Public Overrides Sub OnApplyTemplate()
|
|
Me.WindowRoot = Me.GetRequiredTemplateChild(Of Grid)("WindowRoot")
|
|
Me.LayoutRoot = Me.GetRequiredTemplateChild(Of Grid)("LayoutRoot")
|
|
Me.MinimizeButton = Me.GetRequiredTemplateChild(Of System.Windows.Controls.Button)("MinimizeButton")
|
|
Me.MaximizeButton = Me.GetRequiredTemplateChild(Of System.Windows.Controls.Button)("MaximizeButton")
|
|
Me.RestoreButton = Me.GetRequiredTemplateChild(Of System.Windows.Controls.Button)("RestoreButton")
|
|
Me.CloseButton = Me.GetRequiredTemplateChild(Of System.Windows.Controls.Button)("CloseButton")
|
|
Me.HeaderBar = Me.GetRequiredTemplateChild(Of Grid)("PART_HeaderBar")
|
|
|
|
If Me.LayoutRoot IsNot Nothing AndAlso Me.WindowState = WindowState.Maximized Then
|
|
Me.LayoutRoot.Margin = GetDefaultMarginForDpi()
|
|
End If
|
|
|
|
If Me.CloseButton IsNot Nothing Then
|
|
AddHandler Me.CloseButton.Click, AddressOf CloseButton_Click
|
|
End If
|
|
|
|
If Me.MinimizeButton IsNot Nothing Then
|
|
AddHandler Me.MinimizeButton.Click, AddressOf MinimizeButton_Click
|
|
End If
|
|
|
|
If Me.RestoreButton IsNot Nothing Then
|
|
AddHandler Me.RestoreButton.Click, AddressOf RestoreButton_Click
|
|
End If
|
|
|
|
If Me.MaximizeButton IsNot Nothing Then
|
|
AddHandler Me.MaximizeButton.Click, AddressOf MaximizeButton_Click
|
|
End If
|
|
|
|
If Me.HeaderBar IsNot Nothing Then
|
|
Me.HeaderBar.[AddHandler](Grid.MouseLeftButtonDownEvent, New MouseButtonEventHandler(AddressOf Me.OnHeaderBarMouseLeftButtonDown))
|
|
End If
|
|
|
|
MyBase.OnApplyTemplate()
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnInitialized(ByVal e As EventArgs)
|
|
AddHandler SourceInitialized, AddressOf OnSourceInitialized
|
|
MyBase.OnInitialized(e)
|
|
End Sub
|
|
|
|
' Proprietà che permette di impostare il nome del progetto
|
|
Public Shared ReadOnly ProjectNameProperty As DependencyProperty = DependencyProperty.Register("ProjectName", GetType(String), GetType(EgtMainWindow), New PropertyMetadata(""))
|
|
Public Property ProjectName() As Double
|
|
Get
|
|
Return CType(GetValue(ProjectNameProperty), Double)
|
|
End Get
|
|
Set(ByVal value As Double)
|
|
SetValue(ProjectNameProperty, value)
|
|
End Set
|
|
End Property
|
|
|
|
' Proprietà che permette di impostare la path del progetto
|
|
Public Shared ReadOnly ProjectPathProperty As DependencyProperty = DependencyProperty.Register("ProjectPath", GetType(String), GetType(EgtMainWindow), New PropertyMetadata(""))
|
|
Public Property ProjectPath() As Double
|
|
Get
|
|
Return CType(GetValue(ProjectPathProperty), Double)
|
|
End Get
|
|
Set(ByVal value As Double)
|
|
SetValue(ProjectPathProperty, value)
|
|
End Set
|
|
End Property
|
|
|
|
' Proprietà che permette di impostare uno UserControl per aggiungere elementi alla TitleBar
|
|
Public Shared ReadOnly TitlePanelProperty As DependencyProperty = DependencyProperty.Register("TitlePanel", GetType(Controls.Panel), GetType(EgtMainWindow), New PropertyMetadata(Nothing))
|
|
Public Property TitlePanel() As Controls.Panel
|
|
Get
|
|
Return DirectCast(GetValue(TitlePanelProperty), Controls.Panel)
|
|
End Get
|
|
Set(ByVal value As Controls.Panel)
|
|
SetValue(TitlePanelProperty, value)
|
|
End Set
|
|
End Property
|
|
|
|
' Proprietà che permette di impostare l'altezza della TitleBar
|
|
Public Shared ReadOnly CloseCommandProperty As DependencyProperty = DependencyProperty.Register("CloseCommand", GetType(ICommand), GetType(EgtMainWindow), New PropertyMetadata(Nothing))
|
|
Public Property CloseCommand() As ICommand
|
|
Get
|
|
Return DirectCast(GetValue(CloseCommandProperty), ICommand)
|
|
End Get
|
|
Set(ByVal value As ICommand)
|
|
SetValue(CloseCommandProperty, value)
|
|
End Set
|
|
End Property
|
|
|
|
Protected Overridable Sub OnHeaderBarMouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
|
|
If isManualDrag Then
|
|
Return
|
|
End If
|
|
|
|
Dim position As System.Windows.Point = e.GetPosition(Me)
|
|
Dim headerBarHeight As Integer = 36
|
|
Dim leftmostClickableOffset As Integer = 50
|
|
|
|
If position.X - Me.LayoutRoot.Margin.Left <= leftmostClickableOffset AndAlso position.Y <= headerBarHeight Then
|
|
|
|
If e.ClickCount <> 2 Then
|
|
Me.OpenSystemContextMenu(e)
|
|
Else
|
|
MyBase.Close()
|
|
End If
|
|
|
|
e.Handled = True
|
|
Return
|
|
End If
|
|
|
|
If e.ClickCount = 2 AndAlso MyBase.ResizeMode = ResizeMode.CanResize Then
|
|
Me.ToggleWindowState()
|
|
Return
|
|
End If
|
|
|
|
If MyBase.WindowState = WindowState.Maximized Then
|
|
Me.isMouseButtonDown = True
|
|
Me.mouseDownPosition = position
|
|
Else
|
|
|
|
Try
|
|
Me.positionBeforeDrag = New System.Windows.Point(MyBase.Left, MyBase.Top)
|
|
Me.DragMove()
|
|
Catch
|
|
End Try
|
|
End If
|
|
End Sub
|
|
|
|
Protected Sub ToggleWindowState()
|
|
If MyBase.WindowState <> WindowState.Maximized Then
|
|
MyBase.WindowState = WindowState.Maximized
|
|
Else
|
|
MyBase.WindowState = WindowState.Normal
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub MaximizeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
|
|
Me.ToggleWindowState()
|
|
End Sub
|
|
|
|
Private Sub RestoreButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
|
|
Me.ToggleWindowState()
|
|
End Sub
|
|
|
|
Private Sub MinimizeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
|
|
Me.WindowState = WindowState.Minimized
|
|
End Sub
|
|
|
|
Private Sub CloseButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
|
|
If IsNothing(CloseCommand) Then
|
|
Me.Close()
|
|
End If
|
|
End Sub
|
|
|
|
Private Shadows Sub OnSourceInitialized(ByVal sender As Object, ByVal e As EventArgs)
|
|
_hwndSource = CType(PresentationSource.FromVisual(Me), HwndSource)
|
|
End Sub
|
|
|
|
Private Sub SetMaximizeButtonsVisibility(ByVal maximizeButtonVisibility As Visibility, ByVal reverseMaximizeButtonVisiility As Visibility)
|
|
If Me.MaximizeButton IsNot Nothing Then
|
|
Me.MaximizeButton.Visibility = maximizeButtonVisibility
|
|
End If
|
|
|
|
If Me.RestoreButton IsNot Nothing Then
|
|
Me.RestoreButton.Visibility = reverseMaximizeButtonVisiility
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub OpenSystemContextMenu(ByVal e As MouseButtonEventArgs)
|
|
Dim position As System.Windows.Point = e.GetPosition(Me)
|
|
Dim screen As System.Windows.Point = Me.PointToScreen(position)
|
|
Dim num As Integer = 36
|
|
|
|
If position.Y < CDbl(num) Then
|
|
Dim handle As IntPtr = (New WindowInteropHelper(Me)).Handle
|
|
Dim systemMenu As IntPtr = NativeUtils.GetSystemMenu(handle, False)
|
|
|
|
If MyBase.WindowState <> WindowState.Maximized Then
|
|
NativeUtils.EnableMenuItem(systemMenu, 61488, 0)
|
|
Else
|
|
NativeUtils.EnableMenuItem(systemMenu, 61488, 1)
|
|
End If
|
|
|
|
Dim num1 As Integer = NativeUtils.TrackPopupMenuEx(systemMenu, NativeUtils.TPM_LEFTALIGN Or NativeUtils.TPM_RETURNCMD, Convert.ToInt32(screen.X + 2), Convert.ToInt32(screen.Y + 2), handle, IntPtr.Zero)
|
|
|
|
If num1 = 0 Then
|
|
Return
|
|
End If
|
|
|
|
NativeUtils.PostMessage(handle, 274, New IntPtr(num1), IntPtr.Zero)
|
|
End If
|
|
End Sub
|
|
|
|
Protected Overridable Function GetDefaultMarginForDpi() As Thickness
|
|
Dim currentDPI As Integer = SystemHelper.GetCurrentDPI()
|
|
Dim thickness As Thickness = New Thickness(8, 8, 8, 8)
|
|
If currentDPI = 120 Then
|
|
thickness = New Thickness(7, 7, 7, 6)
|
|
ElseIf currentDPI = 144 Then
|
|
thickness = New Thickness(7, 7, 7, 3)
|
|
ElseIf currentDPI = 168 Then
|
|
thickness = New Thickness(7, 7, 7, 2)
|
|
ElseIf currentDPI = 192 Then
|
|
thickness = New Thickness(6, 6, 0, 0)
|
|
ElseIf currentDPI = 240 Then
|
|
thickness = New Thickness(6, 6, 0, 0)
|
|
End If
|
|
|
|
Return thickness
|
|
End Function
|
|
|
|
Protected Overridable Function GetFromMinimizedMarginForDpi() As Thickness
|
|
Dim currentDPI As Integer = SystemHelper.GetCurrentDPI()
|
|
Dim thickness As Thickness = New Thickness(7, 7, 5, 7)
|
|
If currentDPI = 96 Then
|
|
thickness = New Thickness(8, 8, 8, 8)
|
|
ElseIf currentDPI = 120 Then
|
|
thickness = New Thickness(7, 7, 7, 6)
|
|
ElseIf currentDPI = 144 Then
|
|
thickness = New Thickness(7, 7, 7, 3)
|
|
ElseIf currentDPI = 168 Then
|
|
thickness = New Thickness(7, 7, 7, 2)
|
|
ElseIf currentDPI = 192 Then
|
|
thickness = New Thickness(6, 6, 2, 2)
|
|
ElseIf currentDPI = 240 Then
|
|
thickness = New Thickness(6, 6, 0, 0)
|
|
End If
|
|
|
|
Return thickness
|
|
End Function
|
|
|
|
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
|
|
Dim MyHandle As IntPtr = (New WindowInteropHelper(Me)).Handle
|
|
'If Environment.OSVersion.Version.Major >= 6 Then
|
|
' DwmSetWindowAttribute(MyHandle, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 1, 4)
|
|
'End If
|
|
Dim screen As Screen = Screen.FromHandle(MyHandle)
|
|
Dim width As Double = CDbl(screen.WorkingArea.Width)
|
|
Dim workingArea As Rectangle = screen.WorkingArea
|
|
Me.previousScreenBounds = New System.Windows.Point(width, CDbl(workingArea.Height))
|
|
End Sub
|
|
|
|
Private Sub SystemEvents_DisplaySettingsChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
Dim screen As Screen = Screen.FromHandle((New WindowInteropHelper(Me)).Handle)
|
|
Dim width As Double = CDbl(screen.WorkingArea.Width)
|
|
Dim workingArea As Rectangle = screen.WorkingArea
|
|
Me.previousScreenBounds = New System.Windows.Point(width, CDbl(workingArea.Height))
|
|
Me.RefreshWindowState()
|
|
End Sub
|
|
|
|
Private Sub OnSizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs)
|
|
If MyBase.WindowState = WindowState.Normal Then
|
|
Me.HeightBeforeMaximize = MyBase.ActualHeight
|
|
Me.WidthBeforeMaximize = MyBase.ActualWidth
|
|
Return
|
|
End If
|
|
|
|
If MyBase.WindowState = WindowState.Maximized Then
|
|
Dim screen As Screen = Screen.FromHandle((New WindowInteropHelper(Me)).Handle)
|
|
|
|
If Me.previousScreenBounds.X <> CDbl(screen.WorkingArea.Width) OrElse Me.previousScreenBounds.Y <> CDbl(screen.WorkingArea.Height) Then
|
|
Dim width As Double = CDbl(screen.WorkingArea.Width)
|
|
Dim workingArea As Rectangle = screen.WorkingArea
|
|
Me.previousScreenBounds = New System.Windows.Point(width, CDbl(workingArea.Height))
|
|
Me.RefreshWindowState()
|
|
End If
|
|
End If
|
|
End Sub
|
|
|
|
Private Shadows Sub OnStateChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
Dim screen As Screen = Screen.FromHandle((New WindowInteropHelper(Me)).Handle)
|
|
Dim thickness As Thickness = New Thickness(0)
|
|
|
|
If Me.WindowState <> WindowState.Maximized Then
|
|
Dim currentDPIScaleFactor As Double = CDbl(SystemHelper.GetCurrentDPIScaleFactor())
|
|
Dim workingArea As Rectangle = screen.WorkingArea
|
|
Me.MaxHeight = CDbl((workingArea.Height + 16)) / currentDPIScaleFactor
|
|
Me.MaxWidth = Double.PositiveInfinity
|
|
|
|
If Me.WindowState <> WindowState.Maximized Then
|
|
Me.SetMaximizeButtonsVisibility(Visibility.Visible, Visibility.Collapsed)
|
|
End If
|
|
Else
|
|
thickness = Me.GetDefaultMarginForDpi()
|
|
|
|
If Me.PreviousState = WindowState.Minimized OrElse Me.Left = Me.positionBeforeDrag.X AndAlso Me.Top = Me.positionBeforeDrag.Y Then
|
|
thickness = Me.GetFromMinimizedMarginForDpi()
|
|
End If
|
|
|
|
Me.SetMaximizeButtonsVisibility(Visibility.Collapsed, Visibility.Visible)
|
|
End If
|
|
|
|
Me.LayoutRoot.Margin = thickness
|
|
Me.PreviousState = Me.WindowState
|
|
End Sub
|
|
|
|
Private Shadows Sub OnMouseMove(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs)
|
|
If Not Me.isMouseButtonDown Then
|
|
Return
|
|
End If
|
|
|
|
Dim currentDPIScaleFactor As Double = CDbl(SystemHelper.GetCurrentDPIScaleFactor())
|
|
Dim position As System.Windows.Point = e.GetPosition(Me)
|
|
System.Diagnostics.Debug.WriteLine(position)
|
|
Dim screen As System.Windows.Point = MyBase.PointToScreen(position)
|
|
Dim x As Double = Me.mouseDownPosition.X - position.X
|
|
Dim y As Double = Me.mouseDownPosition.Y - position.Y
|
|
|
|
If Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2)) > 1 Then
|
|
Dim actualWidth As Double = Me.mouseDownPosition.X
|
|
|
|
If Me.mouseDownPosition.X <= 0 Then
|
|
actualWidth = 0
|
|
ElseIf Me.mouseDownPosition.X >= MyBase.ActualWidth Then
|
|
actualWidth = Me.WidthBeforeMaximize
|
|
End If
|
|
|
|
If MyBase.WindowState = WindowState.Maximized Then
|
|
Me.ToggleWindowState()
|
|
Me.Top = (screen.Y - position.Y) / currentDPIScaleFactor
|
|
Me.Left = (screen.X - actualWidth) / currentDPIScaleFactor
|
|
Me.CaptureMouse()
|
|
End If
|
|
|
|
Me.isManualDrag = True
|
|
Me.Top = (screen.Y - Me.mouseDownPosition.Y) / currentDPIScaleFactor
|
|
Me.Left = (screen.X - actualWidth) / currentDPIScaleFactor
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub OnMouseButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
|
|
Me.isMouseButtonDown = False
|
|
Me.isManualDrag = False
|
|
Me.ReleaseMouseCapture()
|
|
End Sub
|
|
|
|
Private Sub RefreshWindowState()
|
|
If MyBase.WindowState = WindowState.Maximized Then
|
|
Me.ToggleWindowState()
|
|
Me.ToggleWindowState()
|
|
End If
|
|
End Sub
|
|
|
|
End Class
|