2009-06-16 8 views
8

मेरे पास एक WinForm ऐप है जिसमें अन्य बच्चे के रूप हैं (एमडीआई नहीं)। यदि उपयोगकर्ता "Esc" दबाता है तो शीर्षतम रूप को बंद किया जाना चाहिए, भले ही इसमें फोकस न हो।WinForm ऐप में शीर्षतम रूप का हैंडल कैसे प्राप्त करें?

मैं एस्केप को पकड़ने के लिए कीबोर्ड कीबोर्ड हुक का उपयोग कर सकता हूं लेकिन मुझे बंद होने के लिए फॉर्म के हैंडल की भी आवश्यकता है।

मुझे लगता है कि Win32 API का उपयोग करके ऐसा करने का कोई तरीका है, लेकिन प्रबंधित कोड का उपयोग कर कोई समाधान है?

उत्तर

7

यहाँ एक तरह से सर्वोच्च रूप Win32 का उपयोग करता है पाने के लिए है (बहुत ही सुंदर नहीं है, लेकिन यह काम करता है):

public const int GW_HWNDNEXT = 2; // The next window is below the specified window 
public const int GW_HWNDPREV = 3; // The previous window is above 

[DllImport("user32.dll")] 
static extern IntPtr GetTopWindow(IntPtr hWnd); 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool IsWindowVisible(IntPtr hWnd); 

[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindow", SetLastError = true)] 
public static extern IntPtr GetNextWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int wFlag); 

/// <summary> 
/// Searches for the topmost visible form of your app in all the forms opened in the current Windows session. 
/// </summary> 
/// <param name="hWnd_mainFrm">Handle of the main form</param> 
/// <returns>The Form that is currently TopMost, or null</returns> 
public static Form GetTopMostWindow(IntPtr hWnd_mainFrm) 
{ 
    Form frm = null; 

    IntPtr hwnd = GetTopWindow((IntPtr)null); 
    if (hwnd != IntPtr.Zero) 
    { 
     while ((!IsWindowVisible(hwnd) || frm == null) && hwnd != hWnd_mainFrm) 
     { 
      // Get next window under the current handler 
      hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); 

      try 
      { 
       frm = (Form)Form.FromHandle(hwnd); 
      } 
      catch 
      { 
       // Weird behaviour: In some cases, trying to cast to a Form a handle of an object 
       // that isn't a form will just return null. In other cases, will throw an exception. 
      } 
     } 
    } 

    return frm; 
} 
1

FormCollection OpenForms संपत्ति के माध्यम से एक आवेदन पत्र में वर्तमान में खुले रूपों को सूचीबद्ध करने के

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx

तो फिर तुम सर्वोच्च() प्रत्येक प्रपत्र की संपत्ति की जांच कर सकता देखें आवेदन वस्तु द्वारा प्रयोग किया जाता है। और जब आपको सबसे ऊपर का फॉर्म मिलता है, तो आप इसे बंद कर देते हैं।

+2

दुर्भाग्य से फॉर्म। टोपमोस्ट संपत्ति एक मान प्राप्त करती है या सेट करती है यह दर्शाती है कि फ़ॉर्म को शीर्षतम रूप के रूप में प्रदर्शित किया जाना चाहिए या नहीं। यह मुझे नहीं बताता है कि फॉर्म सबसे ज्यादा है या नहीं। – tzup

1

आप अपने शीर्षतम रूप में एक सिंगलटन जैसी पैटर्न को कार्यान्वित कर सकते हैं, और एक स्थैतिक संपत्ति प्रदान कर सकते हैं जो स्वयं का एक उदाहरण देता है और इसे बंद कर देता है।

public class MainForm : Form 
    { 
     private static MainForm mainForm; 

     public static MainForm { get { return mainForm; } } 

     public MainForm() 
     { 
     mainForm = this; 
     } 
    } 


    // When the ESC key is pressed... 
    MainForm.MainForm.Close(); 
+0

मुझे लगता है कि आपने इस सवाल को गलत समझा। एक मुख्य रूप से अधिकतम मुख्य रूप से कैस्केडिंग के साथ एक मुख्य रूप अधिकतम और कई अन्य छोटे रूपों के साथ WinForm ऐप की कल्पना करें। हर बार जब आप एएससी को मारते हैं तो सबसे ऊपर का फॉर्म बंद होना चाहिए (ध्यान रखें कि इसमें फोकस नहीं हो सकता है)। उम्मीद है कि यह चीजों को स्पष्ट बनाता है। – tzup

+0

मुझे लगता है कि आपने उसकी प्रतिक्रिया को गलत समझा होगा। एक समय में केवल एक मेनफॉर्म खुला है, है ना? सिंगलटन पैटर्न आपके कीबोर्ड हुक समेत ऐप में कहीं से भी एक स्थिर हैंडल प्रस्तुत करता है। –

+0

@ ज़ाचरी येट्स, आवश्यकता मुख्य रूप से नहीं, बल्कि बाल रूपों को बंद करने में सक्षम होना है। – tzup

3

कैसे इस बारे में का उपयोग कर Application.Openforms

Form GetTopMostForm() 
{ 
    return Application.OpenForms 
     .Cast<Form>() 
     .First(x => x.Focused); 
} 
+0

आवश्यकता है कि सबसे ऊपर के रूप को बंद करना है, जो फोकस नहीं हो सकता है। – tzup

2

मुझे पता है यह एक 4 साल पुराना धागा है, लेकिन मुझे एक ही समस्या थी और सिर्फ एक वैकल्पिक समाधान के साथ आया अगर किसी और ने इस सवाल पर ठोकर खाई और Win32 कॉल के साथ गड़बड़ नहीं करना चाहता।

मुझे लगता है कि शीर्ष-सबसे अधिक फॉर्म अंतिम सक्रिय होगा। तो आप एप्लिकेशन के समान फॉर्मों का एक अलग संग्रह रख सकते हैं। ओपनफॉर्म, इस संग्रह को छोड़कर ऑर्डर किया जाएगा जब प्रत्येक अंतिम सक्रिय किया गया था। जब भी कोई फॉर्म सक्रिय होता है, तो उसे संग्रह के पहले आइटम पर ले जाएं। जब भी आप ईएससी कुंजी देखते हैं, तो आप संग्रह बंद कर देंगे [0] और इसे हटा दें।

+2

या एक ढेर का उपयोग करें, यह इसके लिए एक संग्रह से अधिक प्राकृतिक है –

संबंधित मुद्दे