2008-09-05 8 views
22

तो, मैंने इस प्रश्न पूछने से पहले Google और SO खोजा था। असल में मेरे पास एक डीएलएल है जिसमें इसका एक रूप संकलित है। इस फॉर्म का उपयोग स्क्रीन पर जानकारी प्रदर्शित करने के लिए किया जाएगा। आखिरकार यह असीमित होगा और डीएलएल में बहुत सारे अनुकूलन का पर्दाफाश करेगा। अभी के लिए मैं बस इसे ठीक से प्रदर्शित करना चाहता हूँ। मेरी समस्या यह है कि मैं इसे पावरहेल सत्र में लोड करके डीएलएल का उपयोग करता हूं। तो जब मैं फॉर्म को प्रदर्शित करने की कोशिश करता हूं और इसे शीर्ष पर आने के लिए मिलता हूं और ध्यान केंद्रित करता हूं, तो अन्य सभी ऐप्स को प्रदर्शित करने में कोई समस्या नहीं है, लेकिन मैं अपने जीवन के लिए पावरहेल विंडो पर प्रदर्शित नहीं कर सकता । यहां वह कोड है जिसे मैं वर्तमान में उपयोग करने के लिए उपयोग करने और इसे प्रदर्शित करने के लिए उपयोग कर रहा हूं। मुझे यकीन है कि इसे समझने के बाद इसमें से अधिकतर की आवश्यकता नहीं होगी, यह केवल उन सभी चीजों का प्रतिनिधित्व करता है जिन्हें मैंने Google के माध्यम से पाया था।सी # फोर्स फॉर्म फोकस

CLass Blah 
{ 
     [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")] 
     public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni); 

     [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")] 
     public static extern bool SetForegroundWindow(IntPtr hWnd); 

     [DllImport("User32.dll", EntryPoint = "ShowWindowAsync")] 
     private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); 
     private const int WS_SHOWNORMAL = 1; 

    public void ShowMessage(string msg) 
    { 
      MessageForm msgFrm = new MessageForm(); 
      msgFrm.lblMessage.Text = "FOO"; 
      msgFrm.ShowDialog(); 
      msgFrm.BringToFront(); 
      msgFrm.TopMost = true; 
      msgFrm.Activate(); 

      SystemParametersInfo((uint)0x2001, 0, 0, 0x0002 | 0x0001); 
      ShowWindowAsync(msgFrm.Handle, WS_SHOWNORMAL); 
      SetForegroundWindow(msgFrm.Handle); 
      SystemParametersInfo((uint)0x2001, 200000, 200000, 0x0002 | 0x0001); 
    } 
} 

मैं कहता हूँ के रूप में मुझे यकीन है कि इस बात का सबसे या तो जरूरत नहीं या यहां तक ​​कि बाहर फ्लैट गलत हूँ, मैं सिर्फ चीजें हैं जो मैं कोशिश की थी दिखाना चाहते थे। साथ ही, जैसा कि मैंने उल्लेख किया है, मैं इसे किसी बिंदु पर असीमित रूप से प्रदर्शित करने की योजना बना रहा हूं, जिसे मुझे संदेह है कि एक अलग थ्रेड की आवश्यकता होगी। फॉर्म को अपने स्वयं के धागे में विभाजित करना इसे पावरहेल सत्र पर ध्यान केंद्रित करना आसान बनाता है?


@Joel, जानकारी के लिए धन्यवाद। यहाँ है कि मैं क्या आपके सुझाव के आधार की कोशिश की है:

msgFrm.ShowDialog(); 
msgFrm.BringToFront(); 
msgFrm.Focus(); 
Application.DoEvents(); 

प्रपत्र अभी भी PowerShell सत्र के तहत आता है। मैं थ्रेडिंग के बाहर काम करने के साथ आगे बढ़ जाऊंगा। मैंने पहले धागे पैदा किए हैं लेकिन कभी भी जहां माता-पिता को धागे को बच्चे के थ्रेड से बात करने की ज़रूरत नहीं है, इसलिए हम देखेंगे कि यह कैसा चल रहा है।

अब तक सभी विचारों के लिए Thnks।


ठीक है, इसे सूत्रण समस्या का ख्याल रखा। @Quarrelsome, मैंने उन दोनों को आजमाया। न तो (न ही दोनों एक साथ) काम किया। थ्रेडिंग का उपयोग करने के बारे में बुराई के बारे में मैं उत्सुक हूं? मैं आवेदन का उपयोग नहीं कर रहा हूँ। रुन और मुझे अभी तक कोई समस्या नहीं है। मैं मध्यस्थ वर्ग का उपयोग कर रहा हूं कि माता-पिता के धागे और बच्चे के थ्रेड दोनों तक पहुंच है। उस ऑब्जेक्ट में मैं एक प्रॉपर्टी लॉक करने के लिए रीडरवाइटर लॉक का उपयोग कर रहा हूं जो उस संदेश का प्रतिनिधित्व करता है जिसे मैं उस फॉर्म पर प्रदर्शित करना चाहता हूं जिसे बच्चा थ्रेड बनाता है। माता-पिता संपत्ति को ताला लगाते हैं तो लिखते हैं कि क्या प्रदर्शित किया जाना चाहिए। बाल धागा संपत्ति को ताला लगा देता है और यह बताता है कि इसे फ़ॉर्म पर लेबल को क्या बदलना चाहिए। बच्चे को इसे मतदान अंतराल पर करना पड़ता है (मैं इसे 500ms तक डिफ़ॉल्ट करता हूं) जिसे मैं वास्तव में खुश नहीं करता हूं, लेकिन मुझे बच्चे के धागे को यह जानने के लिए एक घटना संचालित तरीका नहीं मिला कि प्रकोति बदल गई है, इसलिए मैं ' मैं मतदान के साथ अटक गया।

+0

तुम सिर्फ रूप में नियंत्रणों में से एक पर ध्यान दें() फोन कर सकते हैं? –

+0

प्रतिक्रियाओं के लिए धन्यवाद। @Chad, एक ही परिणाम है कि मैं पहले से ही हो रही थी के साथ घाव अभी फोकस() फार्म पर एक नियंत्रण की कोशिश कर रहा। @Dean, मैं अपने विधि का उपयोग करने मैं अपने आप थ्रेड में फ़ॉर्म को विभाजित करने के लिए की आवश्यकता होगी लगता है। मैंने उस बिंदु को उस बिंदु पर करने की योजना बनाई ताकि मुझे लगता है कि मैं उस पर शुरू करूंगा। – EBGreen

उत्तर

16

मुझे भी सक्रिय करने और अग्रभूमि में खिड़की लाने में परेशानी थी। यहां वह कोड है जो अंततः मेरे लिए काम करता है। मुझे यकीन नहीं है कि यह आपकी समस्या का समाधान करेगा या नहीं।

असल में, ShowWindow() फिर SetForegroundWindow() पर कॉल करें।

using System.Diagnostics; 
using System.Runtime.InteropServices; 

// Sets the window to be foreground 
[DllImport("User32")] 
private static extern int SetForegroundWindow(IntPtr hwnd); 

// Activate or minimize a window 
[DllImportAttribute("User32.DLL")] 
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
private const int SW_SHOW = 5; 
private const int SW_MINIMIZE = 6; 
private const int SW_RESTORE = 9; 

private void ActivateApplication(string briefAppName) 
{ 
    Process[] procList = Process.GetProcessesByName(briefAppName); 

    if (procList.Length > 0) 
    { 
     ShowWindow(procList[0].MainWindowHandle, SW_RESTORE); 
     SetForegroundWindow(procList[0].MainWindowHandle); 
    } 
} 
+0

मुझे ShowWindow() को किस पैरामीटर को पास करना चाहिए; तरीका???? – Hassanation

+0

इन सभी SW_ स्थिरांक के लिए आपको मूल परिभाषा कहां मिलती है? – gonzobrains

+1

@gonzobrains http://pinvoke.net –

0

आपको इसके लिए कोई Win32 फ़ंक्शन आयात करने की आवश्यकता नहीं है। यदि फोकस() पर्याप्त नहीं है तो फ़ॉर्म में भी एक होना चाहिए .ब्रिंगटॉफ्रंट() विधि जिसका आप उपयोग कर सकते हैं। अगर यह विफल हो जाता है, तो आप इसे सेट कर सकते हैं। टोपीमोस्ट प्रॉपर्टी को सच में। आप छोड़ना नहीं चाहते हैं, तो यह हमेशा के लिए सच है, इसलिए एप्लिकेशन को कॉल करें। डिवाइवेंट्स ताकि फॉर्म उस संदेश को संसाधित कर सके और इसे वापस गलत पर सेट कर सके।

3

से सिर्फ शो() अलग खिड़की व्यवहार नहीं ShowDialog() करता है?

क्या होगा अगर आप की कोशिश की:

msgFrm.Show(); 
msgFrm.BringToFront(); 
msgFrm.Focus(); 
3

सर्वोच्च = true .एक्टिवेट()?

इनमें से कोई भी अच्छा है?

इसे अपने धागे में विभाजित करना थोड़ा बुरा है क्योंकि यह ठीक से काम नहीं करेगा अगर आप इसे एप्लिकेशन के साथ नहीं कहते हैं। रुन और वह थ्रेड को निगल देगा। सबसे खराब स्थिति परिदृश्य में मुझे लगता है कि आप इसे एक अलग प्रक्रिया में अलग कर सकते हैं और डिस्क या डब्ल्यूसीएफ के माध्यम से संवाद कर सकते हैं।

16

यहां कुछ कोड है जिसे मैंने कुछ वर्षों के लिए एक या दूसरे रूप में उपयोग किया है। एक और ऐप पॉप-अप में विंडो बनाने के लिए कुछ गॉथैस हैं। एक बार जब आप खिड़की संभाल ऐसा करते हैं:

 if (IsIconic(hWnd)) 
     ShowWindowAsync(hWnd, SW_RESTORE); 

     ShowWindowAsync(hWnd, SW_SHOW); 

     SetForegroundWindow(hWnd); 

     // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm 
     // Converted to Delphi by Ray Lischner 
     // Published in The Delphi Magazine 55, page 16 
     // Converted to C# by Kevin Gale 
     IntPtr foregroundWindow = GetForegroundWindow(); 
     IntPtr Dummy = IntPtr.Zero; 

     uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindow, Dummy); 
     uint thisThreadId  = GetWindowThreadProcessId(hWnd, Dummy); 

     if (AttachThreadInput(thisThreadId, foregroundThreadId, true)) 
     { 
     BringWindowToTop(hWnd); // IE 5.5 related hack 
     SetForegroundWindow(hWnd); 
     AttachThreadInput(thisThreadId, foregroundThreadId, false); 
     } 

     if (GetForegroundWindow() != hWnd) 
     { 
     // Code by Daniel P. Stasinski 
     // Converted to C# by Kevin Gale 
     IntPtr Timeout = IntPtr.Zero; 
     SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, Timeout, 0); 
     SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Dummy, SPIF_SENDCHANGE); 
     BringWindowToTop(hWnd); // IE 5.5 related hack 
     SetForegroundWindow(hWnd); 
     SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Timeout, SPIF_SENDCHANGE); 
     } 

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

//Win32 API calls necesary to raise an unowned processs main window 

[DllImport("user32.dll")] 

private static extern bool SetForegroundWindow(IntPtr hWnd); 
[DllImport("user32.dll")] 
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); 
[DllImport("user32.dll")] 
private static extern bool IsIconic(IntPtr hWnd); 
[DllImport("user32.dll", SetLastError = true)] 
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni); 
[DllImport("user32.dll", SetLastError = true)] 
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId); 
[DllImport("user32.dll")] 
private static extern IntPtr GetForegroundWindow(); 
[DllImport("user32.dll")] 
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); 
[DllImport("user32.dll")] 
static extern bool BringWindowToTop(IntPtr hWnd); 

[DllImport("user32.dll")] 
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount); 
[DllImport("user32.dll")] 
private static extern int GetWindowThreadProcessId(IntPtr hWnd, ref Int32 lpdwProcessId); 
[DllImport("User32.dll")] 
public static extern IntPtr GetParent(IntPtr hWnd); 

private const int SW_HIDE = 0; 
private const int SW_SHOWNORMAL = 1; 
private const int SW_NORMAL = 1; 
private const int SW_SHOWMINIMIZED = 2; 
private const int SW_SHOWMAXIMIZED = 3; 
private const int SW_MAXIMIZE = 3; 
private const int SW_SHOWNOACTIVATE = 4; 
private const int SW_SHOW = 5; 
private const int SW_MINIMIZE = 6; 
private const int SW_SHOWMINNOACTIVE = 7; 
private const int SW_SHOWNA = 8; 
private const int SW_RESTORE = 9; 
private const int SW_SHOWDEFAULT = 10; 
private const int SW_MAX = 10; 

private const uint SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000; 
private const uint SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001; 
private const int SPIF_SENDCHANGE = 0x2; 
+1

यह केवल जवाब है कि यहाँ मेरे लिए काम किया, धन्यवाद Gevin साझा करने के लिए है! –

+2

बीटीडब्ल्यू, यह रेमंड चेन के अनुसार एक खतरनाक अभ्यास की तरह लगता है यह यूआई फ्रीज को उत्तेजित कर सकता है: मैंने आपको चेतावनी दी: इनपुट कतारों को जोड़ने के खतरे http://blogs.msdn.com/b/oldnewthing/archive/2008/ 08/01/8795860.aspx आप कभी भी इस समस्या केविन को पूरा किया? –

+0

इस कोड का उपयोग ऐसे आवेदकों में कई ग्राहक साइटों पर वर्षों से किया जा रहा है जो 24x7 को बिना किसी समस्या के समस्याएं चलाते हैं। इसका मतलब यह नहीं है कि चेन सही नहीं है लेकिन यदि यह एक समस्या है तो यह अक्सर नहीं होता है। –

0

क्या आप सिर्फ कॉलिंग कॉलिंग का बच्चा नहीं चाहते हैं?

ऐसा करने के लिए आपको कॉलिंग विंडो में पास की आवश्यकता होगी और ShowDialog (IWin32Window स्वामी) विधि का उपयोग करें।

2

निम्नलिखित समाधान अपनी आवश्यकताओं को पूरा करना चाहिए:

  1. विधानसभा PowerShell में लोड किया जा सकता है और मुख्य वर्ग
  2. जब इस उदाहरण पर ShowMessage विधि कहा जाता है, एक नई विंडो दिखाया गया है instantiated और सक्रिय
  3. यदि आप कई बार ShowMessage को कॉल करते हैं, तो वही विंडो इसके शीर्षक टेक्स्ट को अपडेट करती है और
  4. विंडो का उपयोग बंद करने के लिए, विधि का निपटान करें

चरण 1: चलो एक अस्थायी कार्यशील निर्देशिका बनाएँ (आप स्वाभाविक रूप से अपनी खुद की निर्देशिका का उपयोग कर सकते)

(powershell.exe) 
mkdir C:\TEMP\PshWindow 
cd C:\TEMP\PshWindow 

चरण 2: अब की क्लास है कि हम PowerShell में के साथ बातचीत की जाएगी निर्दिष्ट कर सकते हैं:

// file 'InfoProvider.cs' in C:\TEMP\PshWindow 
using System; 
using System.Threading; 
using System.Windows.Forms; 

namespace PshWindow 
{ 
    public sealed class InfoProvider : IDisposable 
    { 
     public void Dispose() 
     { 
      GC.SuppressFinalize(this); 
      lock (this._sync) 
      { 
       if (!this._disposed) 
       { 
        this._disposed = true; 
        if (null != this._worker) 
        { 
         if (null != this._form) 
         { 
          this._form.Invoke(new Action(() => this._form.Close())); 
         } 
         this._worker.Join(); 
         this._form = null; 
         this._worker = null; 
        } 
       } 
      } 
     } 

     public void ShowMessage(string msg) 
     { 
      lock (this._sync) 
      { 
       // make sure worker is up and running 
       if (this._disposed) { throw new ObjectDisposedException("InfoProvider"); } 
       if (null == this._worker) 
       { 
        this._worker = new Thread(() => (this._form = new MyForm(this._sync)).ShowDialog()) { IsBackground = true }; 
        this._worker.Start(); 
        while (this._form == null || !this._form.Created) 
        { 
         Monitor.Wait(this._sync); 
        } 
       } 

       // update the text 
       this._form.Invoke(new Action(delegate 
       { 
        this._form.Text = msg; 
        this._form.Activate(); 
       })); 
      } 
     } 

     private bool _disposed; 
     private Form _form; 
     private Thread _worker; 
     private readonly object _sync = new object(); 
    } 
} 

साथ ही फार्म कि दिखाया जाएगा:

// file 'MyForm.cs' in C:\TEMP\PshWindow 
using System; 
using System.Drawing; 
using System.Threading; 
using System.Windows.Forms; 

namespace PshWindow 
{ 
    internal sealed class MyForm : Form 
    { 
     public MyForm(object sync) 
     { 
      this._sync = sync; 
      this.BackColor = Color.LightGreen; 
      this.Width = 200; 
      this.Height = 80; 
      this.FormBorderStyle = FormBorderStyle.SizableToolWindow; 
     } 

     protected override void OnShown(EventArgs e) 
     { 
      base.OnShown(e); 
      this.TopMost = true; 

      lock (this._sync) 
      { 
       Monitor.PulseAll(this._sync); 
      } 
     } 

     private readonly object _sync; 
    } 
} 

चरण 3: विधानसभा संकलन करते हैं ...

(powershell.exe) 
csc /out:PshWindow.dll /target:library InfoProvider.cs MyForm.cs 

चरण 4: ... और PowerShell में विधानसभा लोड इसके साथ मस्ती करने के लिए:

(powershell.exe) 
[System.Reflection.Assembly]::LoadFile('C:\TEMP\PshWindow\PshWindow.dll') 
$a = New-Object PshWindow.InfoProvider 
$a.ShowMessage('Hello, world') 

एक हरे रंग शीर्षक 'हैलो, दुनिया' शीर्षक के साथ खिड़की अब पॉप-अप होना चाहिए और सक्रिय होना चाहिए।आप PowerShell विंडो को पुन: सक्रिय और डालें:

$a.ShowMessage('Stack overflow') 

विंडो के शीर्षक 'ढेर अतिप्रवाह' में बदल जानी चाहिए और खिड़की फिर से सक्रिय होना चाहिए।

हमारे खिड़की के साथ काम करना बंद कर, वस्तु निपटान करने के लिए:

$a.Dispose() 

यह समाधान काम करता है दोनों Windows XP SP3, x86 और Windows Vista SP1, 64 में अपेक्षा के अनुरूप। यदि इस समाधान के बारे में कोई सवाल है तो मैं विस्तृत चर्चा के साथ इस प्रविष्टि को अपडेट कर सकता हूं। अभी के लिए यदि मैं स्वयं व्याख्यात्मक कोड कोड की उम्मीद कर रहा हूं।

1

विशाल धन्यवाद लोग। मुझे लगता है कि मैं इसे थोड़ा कम कर दिया है, यहाँ क्या मैं एक अलग धागे पर डाल दिया है और ठीक काम कर रहा है।

private static void StatusChecking() 
     { 
      IntPtr iActiveForm = IntPtr.Zero, iCurrentACtiveApp = IntPtr.Zero; 
      Int32 iMyProcID = Process.GetCurrentProcess().Id, iCurrentProcID = 0; 
      IntPtr iTmp = (IntPtr)1; 
      while (bIsRunning) 
      { 
       try 
       { 
        Thread.Sleep(45); 
        if (Form.ActiveForm != null) 
        { 
         iActiveForm = Form.ActiveForm.Handle; 
        } 
        iTmp = GetForegroundWindow(); 
        if (iTmp == IntPtr.Zero) continue; 
        GetWindowThreadProcessId(iTmp, ref iCurrentProcID); 
        if (iCurrentProcID == 0) 
        { 
         iCurrentProcID = 1; 
         continue; 
        } 
        if (iCurrentProcID != iMyProcID) 
        { 
         SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, IntPtr.Zero, 0); 
         SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, IntPtr.Zero, SPIF_SENDCHANGE); 
         BringWindowToTop(iActiveForm); 
         SetForegroundWindow(iActiveForm); 
        } 
        else iActiveForm = iTmp; 
       } 
       catch (Exception ex) 
       { 
        Definitions.UnhandledExceptionHandler(ex, 103106); 
       } 
      } 
     } 

मैं परिभाषाओं repasting परेशान डॉन `t ...