vb.net - किसी प्रोजेक्ट में सभी फ़ॉर्म में कोई ईवेंट जोड़ें




winforms events (2)

यदि मैं अपने प्रोजेक्ट में प्रत्येक Form का आकार Form के शीर्षक में प्रदर्शित करना चाहता हूं तो सबसे अच्छा तरीका क्या होगा?
मैं मैन्युअल रूप से हर Form में एक इवेंट हैंडलर नहीं डालना चाहता।
मैं चाहता हूं कि प्रक्रिया स्वचालित हो।
ओवरलोडेड Load() ईवेंट की तरह कुछ है जो रिसाइज़ इवेंट पर हैंडलर जोड़ता है।


आप ऑटोमैटिक का उपयोग कर सकते हैं जैसा कि @Jimi ने सुझाव दिया है।

आप My.Application.OpenForms का उपयोग करके सभी खोले गए फॉर्मों को पुन: व्यवस्थित कर सकते हैं, लेकिन नए फॉर्म को खोलने पर यह मदद नहीं करेगा।

आप कुछ ReportSizeForm वर्ग बना सकते हैं जो System.Forms.Form को विरासत में मिला है। और नियमित रूप से System.Windows.Forms.Form से अपने रूपों की विरासत बदलें।


यहां समस्या का Automation समाधान लागू करने का प्रयास किया गया है।

समस्या:
इन वर्गों के मौजूदा कोड को संपादित / संशोधित किए बिना, एक WinForms प्रोजेक्ट (या उनमें से एक सबसेट) में प्रत्येक मौजूदा Form में एक या अधिक इवेंट हैंडलर संलग्न करें।

एक संभावित समाधान Automation वर्ग से आता है, जो एक नई विंडो खोलने पर पता लगाने का साधन प्रदान करता है और अपने स्वयं के Automation.AddAutomationEventHandler के ग्राहकों को घटना की रिपोर्ट करता है। WindowPattern , जब इसके AutomationEvent का EventId एक WindowPattern पैटर्न पर सेट होता है।
TreeScope.SubTree मेम्बर को TreeScope.SubTree और Scope मेंबर से TreeScope.SubTree लिए सेट किया जाना चाहिए।

Automation , Automation के प्रत्येक AutomationElement लिए, जो AutomationElement को बढ़ाता है, रिपोर्ट करता है:
- Element.Name (Windows शीर्षक के अनुरूप)
- Process ID
- Window Handle (एक पूर्णांक मान के रूप में)

ये मान उस विंडो को पहचानने के लिए पर्याप्त हैं जो वर्तमान प्रक्रिया से संबंधित है; विंडो हैंडल, Application.OpenForms() संग्रह का परीक्षण करते हुए, खुले हुए Form पहचान करने की अनुमति देता है।

जब फ़ॉर्म को एकल कर दिया जाता है, तो एक नया Event Handler पसंद की Event में संलग्न किया जा सकता है।

इस अवधारणा को विस्तारित करके, इन घटनाओं को संलग्न करने के लिए पूर्व-परिभाषित सूची और घटनाओं की सूची बनाना संभव है।
संभवतः, जब आवश्यक हो, प्रोजेक्ट में शामिल करने के लिए एक क्लास फ़ाइल के साथ।

नोट के रूप में, कुछ घटनाएं इस परिदृश्य में सार्थक नहीं होंगी, क्योंकि Automation विंडो के खुलने की रिपोर्ट करता है जब यह पहले से ही दिखाया गया है, इस प्रकार Load() और Shown() घटनाएं अतीत की हैं।

मैंने इसे कुछ घटनाओं ( Form.Resize() और Form.Activate() ) के साथ परीक्षण किया है, लेकिन कोड में मैं सिर्फ सादगी के लिए .Resize() का उपयोग कर रहा हूं।

यह प्रक्रिया का एक ग्राफिक्स प्रतिनिधित्व है।
अनुप्रयोग प्रारंभ करना, ईवेंट हैंडलर .Resize() ईवेंट से संलग्न नहीं है।
यह सिर्फ इसलिए है क्योंकि एक Boolean फ़ील्ड False सेट है।
बटन पर क्लिक करने से, Boolean फ़ील्ड True सेट हो जाता है, जो ईवेंट हैंडलर के पंजीकरण को सक्षम करता है।
जब .Resize() ईवेंट पंजीकृत हो, तो सभी Forms Window Title के वर्तमान आकार की रिपोर्ट करेंगे।


पर्यावरण का परीक्षण :
Visual Studio 2017 pro 15.7.5
.Net FrameWork 4.7.1

आयातित नामस्थान:
System.Windows.Automation

संदर्भ असेंबली :
UIAutomationClient
UIAutomationTypes

MainForm कोड:

Imports System.Diagnostics
Imports System.Windows
Imports System.Windows.Automation

Public Class MainForm

    Friend GlobalHandlerEnabled As Boolean = False
    Protected Friend FormsHandler As List(Of Form) = New List(Of Form)
    Protected Friend ResizeHandler As EventHandler

    Public Sub New()

        InitializeComponent()

        ResizeHandler =
                Sub(obj, args)
                    Dim CurrentForm As Form = TryCast(obj, Form)
                    CurrentForm.Text = CurrentForm.Text.Split({" ("}, StringSplitOptions.None)(0) &
                                                               $" ({CurrentForm.Width}, {CurrentForm.Height})"
                End Sub

        Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
            AutomationElement.RootElement,
                TreeScope.Subtree,
                    Sub(UIElm, evt)
                        If Not GlobalHandlerEnabled Then Return
                        Dim element As AutomationElement = TryCast(UIElm, AutomationElement)
                        If element Is Nothing Then Return

                        Dim NativeHandle As IntPtr = CType(element.Current.NativeWindowHandle, IntPtr)
                        Dim ProcessId As Integer = element.Current.ProcessId
                        If ProcessId = Process.GetCurrentProcess().Id Then
                            Dim CurrentForm As Form = Nothing
                            Invoke(New MethodInvoker(
                                Sub()
                                    CurrentForm = Application.OpenForms.
                                           OfType(Of Form)().
                                           FirstOrDefault(Function(f) f.Handle = NativeHandle)
                                End Sub))

                            If CurrentForm IsNot Nothing Then
                                Dim FormName As String = FormsHandler.FirstOrDefault(Function(f) f?.Name = CurrentForm.Name)?.Name
                                If Not String.IsNullOrEmpty(FormName) Then
                                    RemoveHandler CurrentForm.Resize, ResizeHandler
                                    FormsHandler.Remove(FormsHandler.Where(Function(fn) fn.Name = FormName).First())
                                End If
                                Invoke(New MethodInvoker(
                                Sub()
                                    CurrentForm.Text = CurrentForm.Text & $" ({CurrentForm.Width}, {CurrentForm.Height})"
                                End Sub))

                                AddHandler CurrentForm.Resize, ResizeHandler
                                FormsHandler.Add(CurrentForm)
                            End If
                        End If
                    End Sub)
    End Sub


    Private Sub btnOpenForm_Click(sender As Object, e As EventArgs) Handles btnOpenForm.Click
        Form2.Show(Me)
    End Sub

    Private Sub btnEnableHandlers_Click(sender As Object, e As EventArgs) Handles btnEnableHandlers.Click
        GlobalHandlerEnabled = True
        Me.Hide()
        Me.Show()
    End Sub

    Private Sub btnDisableHandlers_Click(sender As Object, e As EventArgs) Handles btnDisableHandlers.Click
        GlobalHandlerEnabled = False
        If FormsHandler IsNot Nothing Then
            For Each Item As Form In FormsHandler
                RemoveHandler Item.Resize, ResizeHandler
                Item = Nothing
            Next
        End If
        FormsHandler = New List(Of Form)
        Me.Text = Me.Text.Split({" ("}, StringSplitOptions.RemoveEmptyEntries)(0)
    End Sub
End Class

ध्यान दें:
इस पिछले कोड को ऐप स्टार्टिंग फॉर्म (परीक्षण के लिए) के अंदर रखा गया है, लेकिन वर्तमान कोड को छूने के बिना, परियोजना में शामिल करने के लिए Module को शामिल करना बेहतर हो सकता है।

इसे काम करने के लिए, एक नया Module (नामांकित Program ) जोड़ें जिसमें एक Public Sub Main() , और एक Sub Main बजाय Sub Main से आवेदन शुरू करने के लिए परियोजना के गुणों को बदल दें।
"एप्लिकेशन फ्रेमवर्क का उपयोग करें" पर चेकमार्क निकालें और "स्टार्टअप ऑब्जेक्ट" कॉम्बो से "सब मेन" चुनें।

सभी कोड को कुछ संशोधनों के साथ Sub Main स्थानांतरित किया जा सकता है:

Imports System
Imports System.Diagnostics
Imports System.Windows
Imports System.Windows.Forms
Imports System.Windows.Automation

Module Program

    Friend GlobalHandlerEnabled As Boolean = True
    Friend FormsHandler As List(Of Form) = New List(Of Form)
    Friend ResizeHandler As EventHandler

    Public Sub Main()

        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)

        Dim MyMainForm As MainForm = New MainForm()

        ResizeHandler =
                Sub(obj, args)
                    Dim CurrentForm As Form = TryCast(obj, Form)
                    CurrentForm.Text = CurrentForm.Text.Split({" ("}, StringSplitOptions.None)(0) &
                                                               $" ({CurrentForm.Width}, {CurrentForm.Height})"
                End Sub

        Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
            AutomationElement.RootElement,
                TreeScope.Subtree,
                    Sub(UIElm, evt)
                        If Not GlobalHandlerEnabled Then Return
                        Dim element As AutomationElement = TryCast(UIElm, AutomationElement)
                        If element Is Nothing Then Return

                        Dim NativeHandle As IntPtr = CType(element.Current.NativeWindowHandle, IntPtr)
                        Dim ProcessId As Integer = element.Current.ProcessId
                        If ProcessId = Process.GetCurrentProcess().Id Then
                            Dim CurrentForm As Form = Nothing
                            If Not MyMainForm.IsHandleCreated Then Return
                            MyMainForm.Invoke(New MethodInvoker(
                                Sub()
                                    CurrentForm = Application.OpenForms.
                                           OfType(Of Form)().
                                           FirstOrDefault(Function(f) f.Handle = NativeHandle)
                                End Sub))
                            If CurrentForm IsNot Nothing Then
                                Dim FormName As String = FormsHandler.FirstOrDefault(Function(f) f?.Name = CurrentForm.Name)?.Name
                                If Not String.IsNullOrEmpty(FormName) Then
                                    RemoveHandler CurrentForm.Resize, ResizeHandler
                                    FormsHandler.Remove(FormsHandler.Where(Function(fn) fn.Name = FormName).First())
                                End If

                                AddHandler CurrentForm.Resize, ResizeHandler
                                FormsHandler.Add(CurrentForm)

                                CurrentForm.Invoke(New MethodInvoker(
                                Sub()
                                    CurrentForm.Text = CurrentForm.Text & $" ({CurrentForm.Width}, {CurrentForm.Height})"
                                End Sub))
                            End If
                        End If
                    End Sub)

        Application.Run(MyMainForm)

    End Sub

End Module




ui-automation