2012-10-18 24 views
18

मुझे पता है कि यह एक बुरा विचार क्यों है। यदि कोई एप्लिकेशन इनपुट फोकस चुराता है, तो मैं इसे नापसंद करता हूं, लेकिन यह पूरी तरह से व्यक्तिगत उपयोग के लिए है और मैं इसे करना चाहता हूं; यह कुछ भी परेशान नहीं करेगा।मेरे आवेदन को सामने कैसे लाया जाए?

(उत्सुकता के लिए: मैं नेटबीन में यूनिट परीक्षण चला रहा हूं, जो लॉग फ़ाइल उत्पन्न करता है। जब मेरा पृष्ठभूमि एप्लिकेशन लॉग फ़ाइल का टाइमस्टैम्प परिवर्तन देखता है, तो मैं इसे लॉग फ़ाइल को पार्स करना चाहता हूं और परिणामों को दिखाने के लिए सामने आ जाता हूं)।

This question मदद नहीं की, और न ही गुगल किया। ऐसा लगता है कि BringToFront() ने लंबे समय तक काम नहीं किया है और मुझे कोई विकल्प नहीं मिल रहा है।

कोई विचार?

+1

आप यह नहीं कर सकते हैं। विंडोज एक्सपी के पास एक कामकाज था जो इसे अनुमति देगा; तब से संस्करण इसे प्रतिबंधित करते हैं। –

+0

+1 @ken यदि आप 100% सुनिश्चित हैं, तो एक उत्तर पोस्ट करें और मैं पुरस्कार दूंगा। मैं कुछ अस्पष्ट चाल की उम्मीद कर रहा था जैसे सिस्टम ट्रे को सिकुड़ना और फिर बहाल करना, या फिर छुपा देना ... – Mawg

+1

हो गया - क्या यह काम करेगा? :-) –

उत्तर

16

आप इस भरोसेमंद नहीं कर सकते हैं। विंडोज एक्सपी में एक वर्कअराउंड था जो इसे अनुमति देगा, लेकिन इसके बाद के संस्करण इसे अधिकांश भाग के लिए प्रतिबंधित करते हैं (नीचे नोट देखें)। यह स्पष्ट रूप से SetForegroundWindow पर MSDN दस्तावेज की टिप्पणी अनुभाग में कहा गया है:

प्रणाली को प्रतिबंधित करता है जो प्रक्रियाओं अग्रभूमि खिड़की सेट कर सकते हैं। एक प्रक्रिया केवल अग्रभूमि विंडो को सेट कर सकती है यदि निम्न स्थितियों में से कोई एक सत्य है:

  • प्रक्रिया अग्रभूमि प्रक्रिया है।
  • प्रक्रिया अग्रभूमि प्रक्रिया द्वारा शुरू की गई थी।
  • प्रक्रिया को अंतिम इनपुट ईवेंट प्राप्त हुआ।
  • कोई अग्रभूमि प्रक्रिया नहीं है।
  • अग्रभूमि प्रक्रिया को डीबग किया जा रहा है।
  • अग्रभूमि लॉक नहीं है (LockSetForegroundWindow देखें)।
  • अग्रभूमि लॉक टाइम-आउट समाप्त हो गया है (SystemParametersInfo में SPI_GETFOREGROUNDLOCKTIMEOUT देखें)।
  • कोई मेनू सक्रिय नहीं है।

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

उद्धृत दस्तावेज, विशेष रूप से पहली वाक्य के अंतिम अनुच्छेद पर ध्यान दें।

यह विशुद्ध रूप से निजी इस्तेमाल के लिए है और मैं ऐसा करना चाहते हैं के साथ समस्या; यह कुछ भी परेशान नहीं करेगा।

यह है कि कोई भी एप्लिकेशन एक ही काम करने का प्रयास कर सकता है। "पूरी तरह से व्यक्तिगत उपयोग" कैसे करता है यह आपको व्यक्तिगत रूप से बताता है न कि केवल कोई आवेदन? :-)

नोट: मैंने सहायता टूलबटन पर क्लिक करते समय आईडीई के दस्तावेज़ को अग्रभूमि में दिखाने के लिए सोचने के बारे में सोचने की कोशिश की है, लेकिन मुझे लगता है कि चमकदार टास्कबार बटन (और मैं उपयोगकर्ता ऐसा करना चाहते हैं)।

+0

+1 (और उपरोक्त आपकी टिप्पणी के लिए ;-) जाहिर है, मैं आशा में रहूंगा और इसे देने से कुछ घंटे पहले इसे खोल दूंगा। जैसा कि मैंने कहा था, मैं कुछ अस्पष्ट चाल की उम्मीद कर रहा था जैसे सिस्टम ट्रे को सिकुड़ना और फिर बहाल करना, या फिर फिर से दिखाना, लेकिन कुछ भी नहीं जो मैंने कोशिश की है :-(यह बहुत काम है, बस Alt-Tab से बचने के लिए (हम्म, शायद अगर मैं एक "लॉन्चर" अनुप्रयोग है, जो तब एक "प्रक्रिया" एप्लिकेशन का शुभारंभ किया था। नए एप्लिकेशन तो अग्रभूमि में लांच होगा?) – Mawg

+0

आप AlwaysOnTop शैली का उपयोग नहीं कर सकते हैं कि यह अन्य एप्लिकेशन के लिए अनुकूल है, फिर भी यह usaer ड्रा करेंगी ध्यान दें। यद्यपि ग्रोल/स्नारल जैसी कुछ विशेष चेतावनी सेवाएं इसके लिए बेहतर हैं। –

+0

@ केन, धन्यवाद, यह अभी ठीक है। मैंने अपनी टिप्पणी और +1 हटा दी। –

3

आप उस सीमा को हल करने के लिए एक निष्पादन योग्य लिख सकते हैं।उदाहरण के लिए अपनी इच्छित विंडो को सामने लाने के लिए एकमात्र उद्देश्य के साथ उदाहरण के लिए एक सरल (गैर-दृश्य) एप्लिकेशन (मूल रूप से एक कंसोल ऐप लेकिन {$ APPTYPE CONSOLE} के बिना) लें।

आपकी निगरानी पृष्ठभूमि एप्लिकेशन जब भी आपके लेट्टोफ्रंट कार्रवाई की आवश्यकता होती है तो कमांड लाइन कॉल (जैसे ShellExecute) के माध्यम से सहायक ऐप को कॉल करता है। चूंकि यह ऐप अग्रभूमि प्रक्रिया बन रहा है, इसलिए यह अन्य विंडोज़ को सामने ला सकता है (SetForeGroundWindow)। आप अपने लक्षित विंडो पर हैंडल प्राप्त करने के लिए FindWindow का उपयोग कर सकते हैं या अपने सहायक ऐप को शुरू करते समय उपयुक्त पैरामीटर पास कर सकते हैं।

+0

+1 @रिक हाँ, मैं ऐसा करने पर विचार कर रहा था। थोड़ा और अधिक प्रयास/एक छोटे से messt है, लेकिन अगर यह एक ही रास्ता है ... – Mawg

12

मैं अपने अनुप्रयोगों में से एक में कुछ इसी तरह कर रहा हूँ और इस समारोह XP में मुझे लिए काम करता है/Vista/W7:

function ForceForegroundWindow(hwnd: THandle): Boolean; 
const 
    SPI_GETFOREGROUNDLOCKTIMEOUT = $2000; 
    SPI_SETFOREGROUNDLOCKTIMEOUT = $2001; 
var 
    ForegroundThreadID: DWORD; 
    ThisThreadID: DWORD; 
    timeout: DWORD; 
begin 
    if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE); 

    if GetForegroundWindow = hwnd then Result := True 
    else 
    begin 
    // Windows 98/2000 doesn't want to foreground a window when some other 
    // window has keyboard focus 

    if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or 
     ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and 
     ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and 
     (Win32MinorVersion > 0)))) then 
    begin 
     Result := False; 
     ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil); 
     ThisThreadID := GetWindowThreadPRocessId(hwnd, nil); 
     if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then 
     begin 
     BringWindowToTop(hwnd); // IE 5.5 related hack 
     SetForegroundWindow(hwnd); 
     AttachThreadInput(ThisThreadID, ForegroundThreadID, False); 
     Result := (GetForegroundWindow = hwnd); 
     end; 
     if not Result then 
     begin 
     // Code by Daniel P. Stasinski 
     SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0); 
     SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0), 
      SPIF_SENDCHANGE); 
     BringWindowToTop(hwnd); // IE 5.5 related hack 
     SetForegroundWindow(hWnd); 
     SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE); 
     end; 
    end 
    else 
    begin 
     BringWindowToTop(hwnd); // IE 5.5 related hack 
     SetForegroundWindow(hwnd); 
    end; 

    Result := (GetForegroundWindow = hwnd); 
    end; 
end; 

एक अन्य समाधान फोकस चोरी करने के लिए नहीं है और सिर्फ में खिड़की सर्वोच्च डाल जेड बफर:

procedure ForceForegroundNoActivate(hWnd : THandle); 

begin 
if IsIconic(Application.Handle) then 
    ShowWindow(Application.Handle, SW_SHOWNOACTIVATE); 
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE); 
SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE); 
end; 
+0

क्या इसका * हमेशा * काम करता है? –

+1

यह एक गैर-व्यवस्थापक के रूप में चल रहा है Win7 पर काम नहीं करता, न ही यह एक मशीन चल रहा है पर ठीक से काम करता है Win2008 डोमेन पर, ऐसा नहीं करता है 'टी * हमेशा * काम, यही कारण है कि मैंने जवाब दिया जो मैंने किया था। :-) बेशक, मैं (और ऑपरेटिंग सिस्टम के निर्माता) को क्या जानता हूं? –

+0

यह, और इसी तरह के दृष्टिकोण, मेरे ऐप सक्रिय नहीं होने पर कभी मेरे लिए काम नहीं किया। –

29

यहाँ कुछ सरल काम करने के लिए लगता है कि, कई एक्सपी, Server2003, विस्टा, Server2008, W7 से मिलकर बक्से के साथ परीक्षण किया गया है। टेस्ट एप्लिकेशन एक मानक (या व्यवस्थापक) खाते के साथ भाग गया, अग्रभूमि में लिखते समय नोटपैड से इनपुट फोकस चुरा लिया।

var 
    Input: TInput; 
begin 
    ZeroMemory(@Input, SizeOf(Input)); 
    SendInput(1, Input, SizeOf(Input)); // don't send anyting actually to another app.. 
    SetForegroundWindow(Handle); 

आप इसे और अधिक t.i. कर सकते हैं। एक न्यूनतम ऐप के लिए या यदि आवश्यक हो तो।

+0

वह फोकस क्यों करेगा? –

+1

@ डेविड हेफरन, क्योंकि "प्रक्रिया को अंतिम इनपुट ईवेंट प्राप्त हुआ"। मैंने इसका परीक्षण किया है, और यह बहुत अच्छी तरह से काम करता है। – kobik

+1

धन्यवाद! विंडोज 8.1 में भी काम करता है। –

-1

Form.bringtofront; ?

काम करना चाहिए। यदि आप इसे टाइमर में डालते हैं तो यह आगे रहेगा।

3

यह विंडोज 7 + 8 ओएस में भी काम करना चाहिए। केवल आवश्यकता है एक आवेदन स्वयं कार्यों को कॉल कर सकते हैं। एक और प्रक्रिया के खिड़की के सामने सेट करने के लिए बाहरी ऐप का उपयोग करना ट्रिकर है।

Application.Restore; // unminimize window, makes no harm always call it 
SetWindowPos(self.Handle, HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE or SWP_NOSIZE); 
SetWindowPos(self.Handle, HWND_TOPMOST,0,0,0,0, SWP_NOMOVE or SWP_NOSIZE); 
SetWindowPos(self.Handle, HWND_NOTOPMOST,0,0,0,0, SWP_SHOWWINDOW or SWP_NOMOVE or SWP_NOSIZE); 

संपादित ठीक है, मैं इस के साथ एक समस्या में पता चला। आवेदन सामने लाया गया है लेकिन ध्यान मूल आवेदन में रखा जाता है। समस्या को ठीक करने के लिए इस उत्तर का प्रयोग करें, इसकी काफी जटिल विधि है लेकिन कॉपीपेस्ट चाल करता है। ForceForegroundWindow (wnd) को कॉल करने से पहले आपको एप्लिकेशन को कॉल करना पड़ सकता है। रीस्टोर विंडो को अनइंमिमाइज़ करना। https://stackoverflow.com/a/5885318/185565

3
function WinActivate(const AWinTitle: string): boolean; 
var 
    _WindowHandle: HWND; 
begin 
    Result := false; 
    _WindowHandle := FindWindow(nil, PWideChar(AWinTitle)); 
    if _WindowHandle <> 0 then 
    begin 
    if IsIconic(_WindowHandle) then 
     Result := ShowWindow(_WindowHandle, SW_RESTORE) 
    else 
     Result := SetForegroundWindow(_WindowHandle); 
    end; 
end; 

if WinActivate(self.Caption) then 
    ShowMessage('This works for me in Windows 10'); 
2

मान लिया जाये कि आप अस्थायी रूप से सेट कर सकते हैं अपने रूपों fsStayOnTop होने की FormStyle और उसके बाद क्या करना है और आवेदन को पुनर्स्थापित और BringToFront और फिर formstyle वापस जो कुछ भी यह था करने के लिए बदल चल रहा कोई अन्य StayOnTop अनुप्रयोगों देखते हैं कि।

tmpFormStyle := Application.MainForm.FormStyle; 
Application.MainForm.FormStyle := fsStayOnTop; 
Application.Restore; // optional 
Application.BringToFront; 
Application.MainForm.FormStyle := tmpFormStyle; 

फिर से, यह केवल तभी काम करता है जब कोई अन्य लाइवटॉप एप्लिकेशन न हो।

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