कैसे एक खिड़की बनाने के लिए हमेशा शीर्ष पर नेट में रहते हैं?


93

मेरे पास एक C # winforms ऐप है जो दूसरे प्रोग्राम में मैक्रो चलाता है। दूसरा कार्यक्रम लगातार विंडोज़ को पॉप अप करेगा और आम तौर पर चीजों को एक बेहतर शब्द, पागल की कमी के लिए देखो। मैं एक रद्द बटन लागू करना चाहता हूं, जो प्रक्रिया को चलने से रोक देगा, लेकिन मुझे शीर्ष पर रहने के लिए विंडो नहीं मिल सकती है। मैं इसे C # में कैसे करूँ?

संपादित करें: मैंने TopMost = सत्य की कोशिश की है; , लेकिन दूसरा कार्यक्रम शीर्ष पर अपनी स्वयं की खिड़कियों को पॉप अप करता रहता है। क्या हर n मिलीसेकंड में मेरी विंडो को शीर्ष पर भेजने का कोई तरीका है?

संपादित करें: जिस तरह से मैंने इसे हल किया था वह एक सिस्टम ट्रे आइकन जोड़कर था जो उस पर डबल-क्लिक करके प्रक्रिया को रद्द कर देगा। सिस्टम ट्रे आइकन को कवर नहीं किया गया है। जवाब देने वाले सभी को धन्यवाद। मैंने इस लेख को पढ़ा कि 'सुपर-ऑन-टॉप' विंडो क्यों नहीं है ... यह तार्किक रूप से काम नहीं करता है।


61
हां, हर कुछ मिलीसेकंड के लिए एक टाइमर सेट करें जो आपके Form.TopMost को सही पर सेट करेगा। फिर, बस इसे दिलचस्प बनाने के लिए, जब "पागल" कार्यक्रम लोड होता है, मॉर्टल कॉम्बैट से ऑडियो क्लिप खेलें "फाइट!" :
बीफ्री

2
आपको लगता है कि आपकी टिप्पणी प्रफुल्लित करने वाली थी, आप सोच सकते हैं कि आप बुरी प्रथा का उपहास कर सकते हैं। मेरी समस्या एक संदर्भ मेनू बना रही थी जो एक फ्लो-आउट पैनल के साथ एक फॉर्म पर तैरता है। यदि आप इसे एक्टीवेट () विधि कहते हैं, तो एक फ़्लैलेआउटआउट केवल स्क्रॉल किया जा सकता है, कुछ परिस्थितियों में फ़ोकस () पर्याप्त नहीं है। आप इसे स्क्रॉल नहीं कर पाएंगे। यह चोरी करने वालों के संदर्भों से ध्यान केंद्रित करता है, भले ही इसके पास सबसे ऊपर = सच हो! जैसा कि कोई भी समझदार व्यक्ति जानता है कि यह आपके विनियोग अनुप्रयोगों को MTAThread मोड में चलने देने के लिए ईश्वरीय व्यवहारिक है और वह हर रूप देता है, जो समाधान को सरल बनाता है:
Traubenfuchs

1
निहारना, एक शैतान: pastebin.com/sMJX0Yav यह चंचलता के बिना निर्दोष रूप से काम करता है और नींद (1) इसे गंभीर प्रदर्शन से दूर रखने के लिए पर्याप्त है। जब वह संदर्भ मेनू पर ध्यान केंद्रित करता है, तो वह अपने कार्यक्षेत्र में किसी को भी देखता रहता है? एक बार जब संदर्भ मेनू बंद हो जाता है, तो यह उम्मीद है कि खाली अपवाद हैंडलर में चलता है और मर जाता है। आप एक अलग विराम में निर्माण कर सकते हैं, हालांकि।
Traubenfuchs

मैंने बस इस समस्या का समाधान यहां पोस्ट किया: stackoverflow.com/questions/2546566/…
kfn

क्रॉस-थ्रेड ऑपरेशन अपवाद के कारण @Traubenfuchs विफल हो जाएगा। यह काम करना चाहिए।
फेसपालम ४२

जवाबों:


171

Form.TopMost तब तक काम करेंगे जब तक कि अन्य प्रोग्राम सबसे ऊपरी विंडो नहीं बना रहा है।

एक खिड़की बनाने का कोई तरीका नहीं है जो किसी अन्य प्रक्रिया की नई सबसे ऊपरी खिड़कियों से ढंका नहीं है। रेमंड चेन ने बताया क्यों।


10
यदि 2016 में और इसके बाद भी कोई अन्य पूर्ण न्यूबॉइक्स इसे देखें, तो कोशिश करेंForm.ActiveForm.TopMost
डेविल्स एडवोकेट

1
@ScottBeeson: यह अच्छा है। इस तकनीकी गतिशील दुनिया में अद्यतन जानकारी बहुत आवश्यक है। धन्यवाद:)।
संदीप कुशवाह

47

मैं अपना WinForms एप्लिकेशन "ऑलवेज ऑन टॉप" बनाने के लिए खोज कर रहा था, लेकिन "टॉपमोस्ट" सेट करना मेरे लिए कुछ नहीं कर पाया। मुझे पता था कि यह संभव था क्योंकि WinAmp ऐसा करता है (अन्य अनुप्रयोगों के एक मेजबान के साथ)।

मैंने जो किया वह "user32.dll" के लिए एक कॉल था। मेरे पास ऐसा करने के लिए कोई योग्यता नहीं थी और यह बहुत अच्छा काम करता है। यह एक विकल्प है, वैसे भी।

सबसे पहले, निम्नलिखित नामस्थान आयात करें:

using System.Runtime.InteropServices;

अपनी कक्षा की घोषणा में कुछ चर जोड़ें:

private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private const UInt32 SWP_NOSIZE = 0x0001;
private const UInt32 SWP_NOMOVE = 0x0002;
private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;

User32.dll फ़ंक्शन के लिए प्रोटोटाइप जोड़ें:

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

फिर आपके कोड में (मैंने Form_Load ()) में कॉल जोड़ा, कॉल जोड़ें:

SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);

उम्मीद है की वो मदद करदे। संदर्भ


2
यह न केवल WinForms अनुप्रयोगों के लिए, बल्कि कंसोल विंडो के लिए भी काम करता है । अच्छा लगा!
रोज

अच्छा लगा, इस काम की पुष्टि कर सकता है। लेकिन मैं इसे सबसे ऊपर नहीं होने के लिए वापस कैसे बदल पाऊंगा? क्या कोई HWND_BOTTOMMOST ध्वज है जिसे आप साझा कर सकते हैं?
मार्क

अच्छा सवाल है, अगर आप इस शीर्ष-सबसे अधिक क्षमता और डिफ़ॉल्ट व्यवहार के बीच स्वैप करना चाहते थे (उदाहरण के लिए, आपके पास विंडो व्यवहार के लिए "हमेशा शीर्ष पर" चेकबॉक्स है)। मुझे लगता है कि शायद उचित झंडे के साथ यह संभव होगा। यदि आपके पास सही झंडे हैं, जो डिफ़ॉल्ट विंडो व्यवहार (SWP_DEFAULT = 0x0003 कहते हैं) का वर्णन करता है, तो आप इन झंडे के साथ फिर से "SetWindowPos ()" कह सकते हैं। मुझे यकीन नहीं है; मैंने इसमें गौर नहीं किया है। सौभाग्य अगर आप करते हैं, और अगर कोई करता है तो कृपया इसे यहां जोड़ें!
clamum

यह हमेशा की तरह फुल स्क्रीन गेम मोड पर काम नहीं कर रहा है
सजीथा रथनायके

2
@ मर्क हाँ, एक ध्वज HWND_NOTOPMOST (= -2) है। Docs.microsoft.com/en-us/windows/win32/api/winuser/…
केविन वुइल्यूमियर

23

यदि "पागल हो रहा है" से आपका मतलब है कि प्रत्येक विंडो दूसरे से ध्यान चुराती है, तो टॉपमोस्ट समस्या का समाधान नहीं करेगा।

इसके बजाय, कोशिश करें:

CalledForm.Owner = CallerForm;
CalledForm.Show();

यह फोकस चुराए बिना 'चाइल्ड' फॉर्म दिखाएगा। यदि माता-पिता सक्रिय या केंद्रित है तो भी बच्चे का रूप उसके माता-पिता के ऊपर रहेगा। यह कोड केवल तभी आसानी से काम करता है जब आपने मालिक के रूप में बच्चे के फॉर्म का एक उदाहरण बनाया हो। अन्यथा, आपको API का उपयोग करके स्वामी को सेट करना पड़ सकता है।


1
बहुत बहुत धन्यवाद मैंने बिल्कुल इसका इस्तेमाल किया है और इसने पूरी तरह से काम किया है!
ऐविटिस जीएन

1
धन्यवाद .. वास्तव में मैं क्या देख रहा था
समीरा कुमारसिंह

CalledForm.Ownerअपने आप से सेटिंग ( CalledForm) के कारण होगा System.ArgumentException: 'एक परिपत्र नियंत्रण संदर्भ बनाया गया है। एक नियंत्रण के स्वामित्व या खुद के लिए नहीं किया जा सकता है। '
फेसपल्म 42

2
तुम क्यों CalledForm के बजाय CallerForm का उपयोग कौन सा है :)
जेस्पर

16

सेट Form.TopMost


मैंने कोशिश की, यह ... क्या मुझे लगातार ऐसा करने की आवश्यकता है? 'क्रेज़ी प्रोग्राम' तुरंत खत्म हो जाता है ...
jle

2
नहीं - यदि आप अपना फॉर्म सेट करते हैं। टॉपमोस्ट = ट्रू, यह काम करना चाहिए। "क्रेज़ी" प्रोग्राम में यह होना चाहिए कि यह टॉपमोस्ट पर सेट किए गए डायलॉग भी हों, जिस स्थिति में आप इसे ओवरराइड नहीं कर सकते।
रीड कोपसे

निष्पक्ष लड़ाई नहीं। धन्यवाद।
जले

11

मेरे पास एक क्षणिक 5 मिनट का अंतराल था और मैं इस तरह से फ़ॉर्म को निर्दिष्ट करना भूल गया:

  myformName.ActiveForm.TopMost = true;

लेकिन मैं वास्तव में क्या चाहता था!

  this.TopMost = true;

मेरे लिए परफेक्ट काम किया। if (checkBox1.Checked == true) {this.TopMost = true; } और {this.TopMost = false; }
योश

मेरे लिए एकदम सही काम किया। धन्यवाद।
लेवानी टिट्बेरिया जूल

6

फॉर्म की .TopMostसंपत्ति को सही पर सेट करें ।

आप शायद इसे हर समय इस तरह से नहीं छोड़ना चाहते हैं: इसे तब सेट करें जब आपकी बाहरी प्रक्रिया शुरू हो और जब यह खत्म हो जाए तो इसे वापस रख दें।


5

जिस तरह से मैंने इसे हल किया वह एक सिस्टम ट्रे आइकन बनाकर था जिसमें एक रद्द विकल्प था।


5

निम्न कोड बनाता है खिड़की हमेशा शीर्ष पर रहती है और साथ ही इसे फ्रेमलेस बनाती है।

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace StayOnTop
{
    public partial class Form1 : Form
    {
        private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        private const UInt32 SWP_NOSIZE = 0x0001;
        private const UInt32 SWP_NOMOVE = 0x0002;
        private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        public Form1()
        {
            InitializeComponent();
            FormBorderStyle = FormBorderStyle.None;
            TopMost = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SetWindowPos(this.Handle, HWND_TOPMOST, 100, 100, 300, 300, TOPMOST_FLAGS);
        }

        protected override void WndProc(ref Message m)
        {
            const int RESIZE_HANDLE_SIZE = 10;

            switch (m.Msg)
            {
                case 0x0084/*NCHITTEST*/ :
                    base.WndProc(ref m);

                    if ((int)m.Result == 0x01/*HTCLIENT*/)
                    {
                        Point screenPoint = new Point(m.LParam.ToInt32());
                        Point clientPoint = this.PointToClient(screenPoint);
                        if (clientPoint.Y <= RESIZE_HANDLE_SIZE)
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)13/*HTTOPLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)12/*HTTOP*/ ;
                            else
                                m.Result = (IntPtr)14/*HTTOPRIGHT*/ ;
                        }
                        else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE))
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)10/*HTLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)2/*HTCAPTION*/ ;
                            else
                                m.Result = (IntPtr)11/*HTRIGHT*/ ;
                        }
                        else
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)15/*HTBOTTOM*/ ;
                            else
                                m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ;
                        }
                    }
                    return;
            }
            base.WndProc(ref m);
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.Style |= 0x20000; // <--- use 0x20000
                return cp;
            }
        }
    }
}

एलेक्सन से सहमत - क्या आपके कार्यक्रम को सबसे ऊपर बनाता है? ऐसा लगता है कि यह वास्तव में सिर्फ "सबसे ऊपरी = सच" बयान है, जो बहुत सारे मामलों में काम नहीं कर रहा है। बाकी सभी कोड वास्तव में समस्या का जवाब नहीं देते हैं।
फहाब

4

आप की दृश्यता को दबाने के लिए आप क्या अन्य आवेदन कर रहे हैं? क्या आपने अपने वांछित प्रभाव को प्राप्त करने के अन्य तरीकों की जांच की है? कृपया अपने उपयोगकर्ताओं को इस तरह के दुष्ट व्यवहार के अधीन करने से पहले ऐसा करें जैसा कि आप वर्णन कर रहे हैं: आप क्या करने की कोशिश कर रहे हैं जैसे कि कुछ शरारती साइटें ब्राउज़र विंडो के साथ क्या करती हैं ...

कम से कम लीस्ट सरप्राइज के नियम का पालन करने की कोशिश करें । उपयोगकर्ता स्वयं अधिकांश अनुप्रयोगों के z- क्रम को निर्धारित करने में सक्षम होने की उम्मीद करते हैं। आपको नहीं पता कि उनके लिए सबसे महत्वपूर्ण क्या है, इसलिए यदि आप कुछ भी बदलते हैं, तो आपको अपना खुद का प्रचार करने के बजाय हर चीज के पीछे दूसरे अनुप्रयोग को आगे बढ़ाने पर ध्यान देना चाहिए।

यह बेशक मुश्किल है, क्योंकि विंडोज में विशेष रूप से परिष्कृत विंडो मैनेजर नहीं है। दो दृष्टिकोण खुद सुझाव देते हैं:

  1. शीर्ष स्तर की खिड़कियों की गणना करना और जांचना कि वे किस प्रक्रिया से संबंधित हैं , यदि ऐसा है तो उनके z- क्रम को छोड़ देना चाहिए । (मुझे यकीन नहीं है कि इन WinAPI फ़ंक्शंस के लिए फ्रेमवर्क विधियाँ हैं।)
  2. बाल प्रक्रिया अनुमतियों के साथ इसे डेस्कटॉप तक पहुँचने से रोकने के लिए अनुमति देना ... लेकिन मैं यह कोशिश नहीं करूंगा जब तक कि othe दृष्टिकोण विफल नहीं हो जाता है, क्योंकि बाल प्रक्रिया उपयोगकर्ता बातचीत की आवश्यकता के दौरान एक ज़ोंबी स्थिति में समाप्त हो सकती है।

4

अपने फ़ॉर्म को संवाद बॉक्स क्यों नहीं बना रहे:

myForm.ShowDialog();

1
हाँ! मुझे यही चाहिए था। TopMost = trueक्रोम सहित सब कुछ के ऊपर मेरे फॉर्म को मजबूर करना , जब यह वास्तविकता है कि यह सिर्फ एक सेटिंग बॉक्स है और मुझे मुख्य फॉर्म के शीर्ष पर इसकी आवश्यकता है। Kudos आप इंटरनेट व्यक्ति के लिए।
MDMoore313

3

यहाँ SetForegroundWindow समतुल्य है:

form.Activate();

मैंने लोगों को अजीब चीजें करते देखा है जैसे:

this.TopMost = true;
this.Focus();
this.BringToFront();
this.TopMost = false;

http://blog.jorgearimany.com/2010/10/win32-setforegroundwindow-equivalent-in.html


क्या होगा यदि मैं नहीं चाहता कि मेरी खिड़की सक्रिय हो, मैं इसे सबसे ऊपर (सूचनात्मक, इंटरैक्टिव नहीं) चाहता हूं? मैं केवल इसलिए पूछता हूं क्योंकि वास्तव में "टॉपेस्ट = ट्रू" जारी करना मेरे मामले में काम नहीं कर रहा है (यह सिस्टम पर काम करता है, दूसरों पर नहीं)।
फहाब

यह हमारे लिए काम करने के लिए मिला: this.Show(); this.Activate(); this.BringToFront(); लेकिन यह जवाब हमें उस समाधान के लिए मिला। धन्यवाद!
जिब्स

1

मुझे पता है कि यह पुराना है, लेकिन मैंने इस प्रतिक्रिया को नहीं देखा।

विंडो में (xaml) जोड़ें:

Deactivated="Window_Deactivated"

Window_Deactivated के लिए कोड में:

private void Window_Deactivated(object sender, EventArgs e)
    {
        Window window = (Window)sender;
        window.Activate();
    }

यह आपकी विंडो को शीर्ष पर रखेगा।


1
आपने इस प्रतिक्रिया को नहीं देखा क्योंकि प्रश्न winform के बारे में है।
काइनेटिक

1

के आधार पर clamum के जवाब है, और केविन Vuilleumier के अन्य ध्वज व्यवहार के लिए जिम्मेदार के बारे में टिप्पणी है, मैं इस टॉगल कि बीच स्विच कर दिया पर शीर्ष और नहीं पर शीर्ष एक बटन प्रेस के साथ।

private void button1_Click(object sender, EventArgs e)
    {
        if (on)
        {
            button1.Text = "yes on top";
            IntPtr HwndTopmost = new IntPtr(-1);
            SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags);
            on = false;
        }
        else
        {
            button1.Text = "not on top";
            IntPtr HwndTopmost = new IntPtr(-2);
            SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags);
            on = true;
        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.