2012-01-16 21 views
6

Tôi mở một notepad từ chương trình của mình bằng cách sử dụng Process.Start() nhưng notepad mở mới bao gồm màn hình. Nhưng tôi muốn ứng dụng của mình duy trì trọng tâm của nó.Làm cách nào để đặt tiêu điểm trở lại biểu mẫu sau khi mở một quy trình (Notepad)?

tôi tương tự (sử dụng Process.Start cùng) mở ra MS Excel và Word nhưng để có được tập trung trở lại hình thức của tôi tất cả những gì cần phải viết là:

this.Focus(); 

Nhưng Quirk với Notepad: Tôi mở notepad (và tất cả các quá trình khác như thế này)

Process process = new Process(); 
process.StartInfo.UseShellExecute = true; 
process.EnableRaisingEvents = true; 
process.StartInfo.FileName = @"abc.log"; 
process.Start(); 

Bây giờ notepad lấy nét.

tôi đã cố gắng này:

  1. this.Activate(), this.Focus(), không cần thiết phải đề cập đến

  2. [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] 
    public static extern IntPtr SetFocus(HandleRef hWnd); 
    
    { 
        IntPtr hWnd = myProcess.Handle; 
        SetFocus(new HandleRef(null, hWnd)); 
    } 
    
  3. [DllImport("User32")] 
    private static extern int SetForegroundWindow(IntPtr hwnd); 
    
    [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; 
    
    { 
        ShowWindow(Process.GetCurrentProcess().MainWindowHandle, SW_RESTORE); 
        SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle); 
    } 
    
  4. Một giải pháp dài hơn nhận được từ here.

Tất cả vẫn tập trung vào notepad. Tại sao nó khó khăn như vậy để chỉ tập trung vào một cửa sổ, cửa sổ của chính ứng dụng quá đó?

EDIT: Tốt nhất là tôi có thể mở sổ ghi chú được thu nhỏ, nhưng nó vẫn không đưa tiêu điểm vào biểu mẫu sau khi thử tất cả các mã ở trên. Notepad mở ra tối thiểu, nhưng tập trung sẽ vẫn còn trên notepad (một cái gì đó mà đôi khi chúng ta thấy trong windows xp) và hình thức sẽ được ra khỏi tập trung.

+0

Is it ok để bắt đầu cửa sổ ở trạng thái thu nhỏ? – NoviceProgrammer

+0

Có, nó là ok, nhưng nó sẽ không hoạt động. Tôi sẽ cập nhật điều đó trong câu hỏi của tôi – nawfal

+0

Bạn đã thử điều này chưa? http://stackoverflow.com/questions/2121911/starting-a-process-without-stealing-focus-c – NoviceProgrammer

Trả lời

9

Tôi đã thử hầu hết mọi thứ trên internet (vì vậy hãy chắc chắn về điều đó :)). Tốt nhất là tôi có thể lấy mẫu của tôi trên tất cả các hình thức khác, nhưng không tập trung (theo phương pháp của @Hans Passant). Đi theo các khối mã lớn trên tất cả, tôi bằng cách nào đó cảm thấy aint này sẽ dễ dàng. Vì vậy, tôi luôn sử dụng SetForegroundWindow() với các đoạn mã khác. Không bao giờ nghĩ chỉ đơn thuần là SetForegroundWindow() sẽ làm điều này.

Điều này đã hiệu quả.

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

private void button1_Click(object sender, EventArgs e) 
{ 
    Process process = new Process(); 
    process.StartInfo.FileName = @...\abc.log"; 
    process.Start(); 

    process.WaitForInputIdle(); //this is the key!! 

    SetForegroundWindow(this.Handle); 
} 

Đôi khi phương thức này tập trung vào biểu mẫu gốc (trong trường hợp biểu mẫu mong muốn của tôi là biểu mẫu con dưới dạng cha mẹ); trong trường hợp này, chỉ cần thêm this.Focus() đến dòng cuối cùng ..

Ngay cả điều này làm việc:

Microsoft.VisualBasic.Interaction.Shell(@"notepad.exe D:\abc.log", 
             Microsoft.VisualBasic.AppWinStyle.NormalNoFocus); 

Giải pháp được cung cấp bởi here

2

tôi đã cùng một vấn đề, tôi cuối cùng vết thương với lập trình gọi alt-tab:

[DllImport("user32.dll")] 
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); 

private void alttab() 
{ 
    uint WM_SYSCOMMAND = 0x0112; 
    int SC_PREVWINDOW = 0xF050;    

    PostMessage(Process.GetCurrentProcess().MainWindowHandle, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 
} 

// EDIT: Bạn nên sử dụng process.MainWindowHandle thay ofcourse

+0

Cảm ơn. Sẽ cho bạn biết ngày mai .. Đó là suy nghĩ hoàn toàn khác nhau, nhưng tôi lo lắng việc này đôi khi sẽ tạo ra vấn đề. Bạn đã bao giờ gặp vấn đề với cách tiếp cận này chưa? – nawfal

+0

tính năng này không hoạt động tốt .. – nawfal

1

của Windows ngăn chặn các ứng dụng từ xô đẩy họ cửa sổ vào khuôn mặt của người dùng, bạn đang thấy điều này tại nơi làm việc. Các quy tắc chính xác khi một ứng dụng có thể ăn cắp tập trung được ghi lại trong tài liệu MSDN cho AllowSetForegroundWindow().

Cửa sau xung quanh hạn chế này là hàm AttachThreadInput(). Mã này hoạt động tốt, tôi đã thực hiện một lối tắt để tìm ID luồng cho chuỗi sở hữu cửa sổ nền trước. Đủ tốt cho Notepad, có thể không dành cho các ứng dụng khác. Hãy cẩn thận rằng Raymond Chen không không phê duyệt loại hack này.

private void button1_Click(object sender, EventArgs e) { 
     var prc = Process.Start("notepad.exe"); 
     prc.WaitForInputIdle(); 
     int tid = GetCurrentThreadId(); 
     int tidTo = prc.Threads[0].Id; 
     if (!AttachThreadInput(tid, tidTo, true)) throw new Win32Exception(); 
     this.BringToFront(); 
     AttachThreadInput(tid, tidTo, false); 
    } 

    [DllImport("user32.dll", SetLastError = true)] 
    private static extern bool AttachThreadInput(int tid, int tidTo, bool attach); 
    [DllImport("kernel32.dll")] 
    private static extern int GetCurrentThreadId(); 
+0

Cảm ơn. Nhưng tôi nghi ngờ rằng nếu BringToFront thực sự hoạt động ở đây. Không phải nó chỉ là một biện pháp để kiểm soát được hiển thị trên một điều khiển khác? Nó không phải là. Kích hoạt là một sự lựa chọn tốt hơn ở đây? – nawfal

+0

Còn ai là Raymond Chen? Để phê chuẩn điều này? : o – nawfal

+0

Form.BringToFront() gọi SetForegroundWindow(), dễ dàng nhìn thấy bằng cách chỉ cần cố gắng để mã. Raymond Chen là một lập trình viên của Microsoft với một blog phổ biến. Bài viết trả lời ở đây quá, tôi không muốn chọc anh ta ra. http://blogs.msdn.com/b/oldnewthing/ –

-1

Hãy thử điều này:

public partial class MainForm : Form 
{ 
    private ShowForm showForm; 

    public MainForm() 
    { 
     InitializeComponent(); 
    } 

    private void showButton_Click(object sender, EventArgs e) 
    { 
     this.showForm = new ShowForm(); 
     this.showForm.FormClosed += showForm_FormClosed; 
     this.showForm.Show(this); 
    } 

    private void showForm_FormClosed(object sender, FormClosedEventArgs e) 
    { 
     this.Focus(); 
    } 
} 
+0

Làm cách nào để trả lời câu hỏi này? – nawfal

Các vấn đề liên quan