2009-06-12 42 views
19

Folks,Làm thế nào để hiển thị dạng trước trong C#

Hãy không ai biết làm thế nào để hiển thị một mẫu từ một ứng dụng khác vô hình, có nó được sự tập trung (ví dụ: xuất hiện trên các cửa sổ khác)? Tôi đang làm việc trong C# .NET 3.5.

tôi nghi ngờ tôi đã lấy "hoàn toàn cách tiếp cận sai" ... Tôi làm khôngApplication.Run (TheForm mới()) thay vào đó tôi (TheForm mới()). ShowModal(). .. Biểu mẫu về cơ bản là một cuộc đối thoại phương thức, với một vài hộp kiểm; một hộp văn bản, và OK và Hủy bỏ các nút. Người dùng đánh dấu vào một hộp kiểm và các loại trong một mô tả (hoặc bất cứ điều gì) sau đó nhấn OK, biểu mẫu biến mất và quá trình đọc đầu vào của người dùng từ Biểu mẫu, Loại bỏ nó và tiếp tục xử lý.

Tác phẩm này, ngoại trừ khi biểu mẫu hiển thị nó không lấy tiêu điểm, thay vào đó nó xuất hiện phía sau ứng dụng "máy chủ", cho đến khi bạn nhấp vào nó trong thanh tác vụ (hoặc bất kỳ thứ gì). Đây là một hành vi gây phiền nhiễu nhất, mà tôi dự đoán sẽ gây ra nhiều "cuộc gọi hỗ trợ" và phiên bản VB6 hiện tại không có vấn đề này, vì vậy tôi sẽ sử dụng lại ... và người dùng sẽ không chấp nhận điều đó (và cũng không nên họ).

Vì vậy ... Tôi bắt đầu nghĩ rằng tôi cần phải suy nghĩ lại toàn bộ shebang ... Tôi nên hiển thị biểu mẫu phía trước, dưới dạng "ứng dụng bình thường" và đính kèm phần còn lại của quá trình xử lý vào nút OK sự kiện nhấp chuột. Nó sẽ hoạt động, Nhưng điều đó sẽ mất thời gian mà tôi không có (tôi đã qua thời gian/ngân sách) ... vì vậy trước tiên tôi thực sự cần phải cố gắng làm cho phương pháp tiếp cận hiện tại làm việc ... ngay cả bằng cách nhanh chóng và phương pháp bẩn.

Vì vậy, hãy làm bất cứ ai biết cách "buộc" Biểu mẫu .NET 3.5 (bằng phương tiện công bằng hoặc gia cầm) để lấy tiêu điểm? Tôi đang nghĩ đến các lệnh gọi API cửa sổ "ma thuật" (Tôi biết

Chạng vạng: Điều này dường như chỉ là vấn đề khi làm việc, chúng tôi đang sử dụng Visual Studio 2008 trên Windows XP SP3 ... I đã chỉ thất bại trong việc tái tạo các vấn đề với một SSCCE (xem dưới đây) ở nhà trên Visual C# 2008 trên Vista Ulimate ... Điều này hoạt động tốt.Hhh? WTF?

Ngoài ra, tôi thề rằng tại nơi làm việc hôm qua cho thấy các hình thức khi tôi chạy EXE, nhưng không phải khi F5'ed (hoặc Ctrl-F5'ed) trực tiếp từ IDE (mà tôi chỉ đưa lên với) ... Ở nhà hình thức cho thấy tốt một trong hai cách.Tuy nhiên confusterpating!

Có thể có hoặc không liên quan, nhưng Visual Studi o bị rơi và cháy sáng nay khi dự án đang chạy trong chế độ gỡ lỗi và chỉnh sửa mã "đang di chuyển" ... nó đã bị mắc kẹt những gì tôi cho là một vòng lặp vô tận của các thông báo lỗi. Các thông báo lỗi là một cái gì đó về "không thể gỡ lỗi dự án này bởi vì nó không phải là dự án hiện tại, hoặc một cái gì đó ... Vì vậy, tôi chỉ giết nó với quá trình thám hiểm. Nó bắt đầu trở lại tốt, và thậm chí cung cấp để phục hồi" bị mất "tập tin, một lời đề nghị mà tôi chấp nhận

using System; 
using System.Windows.Forms; 

namespace ShowFormOnTop { 
    static class Program { 
     [STAThread] 
     static void Main() { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      //Application.Run(new Form1()); 
      Form1 frm = new Form1(); 
      frm.ShowDialog(); 
     } 
    } 
} 

Bối cảnh:. tôi porting một thực hiện VB6 hiện có để NET ... đó là một 'cắm' cho một 'khách hàng' ứng dụng GIS gọi MapInfo Các. khách hàng hiện tại "làm việc vô hình" và hướng dẫn của tôi là "giữ phiên bản mới càng gần với phiên bản cũ", hoạt động đủ tốt (sau nhiều năm vá), nó chỉ được viết bằng ngôn ngữ không được hỗ trợ, vì vậy chúng tôi cần chuyển

Giới thiệu về tôi: Tôi khá là một noob đối với C# và .NET nói chung, mặc dù tôi đã có chứng chỉ xóa đáy, nhưng tôi đã là lập trình viên chuyên nghiệp trong 10 năm; Vì vậy, tôi sắp xếp "biết một số thứ".

Mọi thông tin chi tiết sẽ được chào đón nhiều nhất ... và Cảm ơn tất cả các bạn đã dành thời gian đọc nội dung này. Sự thỏa hiệp không phải là (rõ ràng) sở trường của tôi.

Chúc mừng. Keith.

Trả lời

44

Đơn giản chỉ cần

yourForm.TopMost = true; 
+0

Tôi sẽ đi cho nó một burl. Cảm ơn bạn đã gợi ý. Tôi đánh giá cao nó. – corlettk

+0

Đơn giản chỉ cần đặt this.TopMost = true trong Form_Load hoạt động như một sự quyến rũ. Cảm ơn bạn, cảm ơn và cảm ơn bạn! – corlettk

+0

Tôi đã có một vấn đề tương tự, và đã cố gắng sử dụng này.Focus() và this.Activate() trong Load sự kiện không thành công, nhưng thiết lập này.TopMost = true trong sự kiện Load làm việc hoàn hảo cho tôi! Bài đăng tuyệt vời và cảm ơn một triệu câu trả lời. +1 – Jim

4

Có một tình trạng quá tải của Form.ShowDialog() mà phải mất một đối tượng IWin32Window. IWin32Window đó được coi là cửa sổ cha cho biểu mẫu.

Nếu bạn có cửa sổ chính dưới dạng System.Windows.Forms.Form, hãy tiếp tục và chỉ chuyển nó. Nếu không, hãy lấy HWND (có thể bằng P/Invoking to FindWindow()), và tạo một triển khai IWin32Window giả mà chỉ trả về HWND (More details).

+0

Không có cửa sổ nào khác trong ứng dụng ... chỉ là "cuộc đối thoại nhỏ" này (để cho phép người dùng nhập một số siêu dữ liệu để cập nhật). – corlettk

3
  1. Bạn nói rằng nó hoạt động tốt khi bạn sử dụng Application.Run. Tại sao bạn không muốn sử dụng Application.Run, sau đó?
  2. Bạn đã thử gọi BringToFront() từ OnLoad hoặc OnShown?
+0

Tôi đã nói rằng tôi không sử dụng Application.Run, tôi không nói nó làm cho biểu mẫu hiển thị. Tôi đã không "chạy" ứng dụng vì điều này về cơ bản không phải là "sự kiện điều khiển"; đó là một dòng chính dài mà chỉ cần hiển thị một cuộc đối thoại phương thức với một vài điều khiển ... Nếu tôi cần phải cơ cấu lại ứng dụng để "hướng sự kiện" thì tôi sẽ làm như vậy ... Tôi đã không làm như vậy ban đầu vì nó không phù hợp với vấn đề. FIRST Tôi hy vọng sẽ tìm thấy một giải pháp khác cho mẫu được hiển thị "phía sau" ứng dụng GIS của máy chủ. Tôi sẽ thử BringToFront() trong phương pháp OnShow (cả hai đều mới trên tôi ;-) Tôi đánh giá cao sự giúp đỡ của bạn. Chúc mừng. Keith. – corlettk

+1

Xin lỗi, tôi tưởng tượng bạn nói rằng Application.Run tránh được vấn đề. Tuy nhiên, sự phản đối của bạn là hơi kỳ quặc. Các biểu mẫu nhận các sự kiện giống như cách bạn làm Application.Run hoặc Form.ShowDialog. Trong thực tế, cách thức mà hai công việc này gần như là (nhưng không hoàn toàn) giống hệt nhau. Cả hai đều gọi ThreadContext.FromCurrent() RunMessageLoop (ThreadContext là một lớp bên trong trong System.Windows.Forms.dll). –

+0

Aha ... Phản đối của tôi đối với Application.Run được dựa trên sự thiếu hiểu biết thuần túy không được chê bai. Tôi vừa mới nhận ra rằng Application.Run BLOCKS THE CALLING THREAD. (Tha thứ cho tiếng hét của tôi, không có nhiều lựa chọn để nhấn mạnh trong các bình luận SO). Tôi thực sự đánh giá cao lời khuyên của bạn, và tôi sẽ đi làm sáng nay để thử nó. Xin lỗi nếu tôi hơi khó chịu, đã trễ và tôi đã rất mệt mỏi, và ngày càng thất vọng. – corlettk

0

Có vẻ như đó là hành vi dành riêng cho XP ... Do đó tôi không thể tái tạo nó trên Vista.

http://www.gamedev.net/community/forums/topic.asp?topic_id=218484

EDIT: PS: Đó là quá khứ trước khi đi ngủ tôi (02:00 ;-).

Thanx tất cả cho câu trả lời của bạn ... có một vài điều "tôi có thể thử ... Tôi thậm chí có thể đi vào văn phòng vào ngày mai để thử họ ... Yeah, yeah ... Tôi đã có một cuộc sống một lần, nhưng tôi giao dịch nó cho một mái tóc và một công việc ;-)

Chúc mừng tất cả. Keith.

+0

Tôi sẽ bỏ phiếu này (câu trả lời của riêng tôi) nếu tôi có thể ... Tôi vừa hoàn thành "hoàn toàn xác minh" rằng: form.TopMost = true; khắc phục sự cố trên XP (tất cả các phiên bản hiện tại của chúng tôi + Phiên bản SOE tiếp theo) và Vista. Cho vay thêm sự tin tưởng vào cuộc tranh luận rằng "Tôi là @ Putz!" ... Một số ngày bạn không thể thực hiện một thủ thuật ;-) – corlettk

+1

Bạn có thể xóa câu trả lời này nếu bạn muốn :) –

1

Tôi đã hack ứng dụng này từ một ứng dụng mà tôi đang thực hiện. Chúng tôi có một ứng dụng lớn tải một loạt các mô-đun được viết bởi các nhóm khác nhau. Chúng tôi đã viết một trong các mô-đun này và cần có hộp thoại đăng nhập mở trong quá trình khởi tạo này. Nó được đặt thành '.TopMost = true', nhưng điều đó không hiệu quả.

Nó sử dụng WindowsFormsSynchronizationContext để mở hộp thoại và sau đó nhận lại kết quả của hộp thoại.

Tôi hiếm khi thực hiện mã hóa GUI và nghi ngờ điều này có thể quá mức cần thiết, nhưng có thể giúp ai đó nếu họ gặp khó khăn. Tôi đã có vấn đề với sự hiểu biết làm thế nào nhà nước được thông qua để các SendOrPostCallback, như tất cả các ví dụ tôi có thể tìm thấy đã không sử dụng nó.

Ngoài ra, điều này được lấy từ một ứng dụng đang hoạt động, nhưng tôi đã xóa một vài bit mã và đã thay đổi một số chi tiết. Xin lỗi nếu nó không biên dịch.

public bool Dummy() 
{ 

// create the login dialog 
DummyDialogForm myDialog = new DummyDialogForm(); 

// How we show it depends on where we are. We might be in the main thread, or in a background thread 
// (There may be better ways of doing this??) 
if (SynchronizationContext.Current == null) 
{ 
    // We are in the main thread. Just display the dialog 
    DialogResult result = myDialog.ShowDialog(); 
    return result == DialogResult.OK; 
} 
else 
{ 
    // Get the window handle of the main window of the calling process 
    IntPtr windowHandle = Process.GetCurrentProcess().MainWindowHandle; 

    if (windowHandle == IntPtr.Zero) 
    { 
     // No window displayed yet 
     DialogResult result = myDialog.ShowDialog(); 
     return result == DialogResult.OK; 
    } 
    else 
    { 
     // Parent window exists on separate thread 
     // We want the dialog box to appear in front of the main window in the calling program 
     // We would like to be able to do 'myDialog.ShowDialog(windowHandleWrapper)', but that means doing something on the UI thread 
     object resultState = null; 
     WindowsFormsSynchronizationContext.Current.Send(
      new SendOrPostCallback(delegate(object state) { resultState = myDialog.ShowDialog(); }), resultState); 

     if (resultState is DialogResult) 
     { 
      DialogResult result = (DialogResult) resultState; 
      return result == DialogResult.OK; 
     } 
     else 
      return false; 

    } 
} 

}

3

Form.Activate() làm việc trong trường hợp của tôi.

1

Activate() cũng làm việc cho tôi.

BringToFront() không làm gì trong trường hợp này, tôi không biết tại sao.

-1

Đây là những gì tôi sử dụng để mang lại một biểu mẫu mở là một phần của ứng dụng của tôi ở mặt trước. Bạn thậm chí có thể sử dụng nó bằng một nút. Nhưng biểu mẫu cần phải mở hoặc ứng dụng sẽ bị hỏng.

"YourOpenForm" phải là tên của biểu mẫu của bạn từ cửa sổ thuộc tính.

private void button1_Click(object sender, EventArgs e) 
    { 
     Application.OpenForms["YourOpenForm"].BringToFront(); 
    } 

Chúc may mắn!

2

Đây là giải pháp cuối cùng tôi đã viết sau 20 nỗ lực khác nhau:

/* A workaround for showing a form on the foreground and with focus, 
* even if it is run by a process other than the main one 
*/ 
public static void ShowInForeground(this Form form, bool showDialog = false) 
{ 
    if (showDialog) 
    { 
     //it's an hack, thanks to http://stackoverflow.com/a/1463479/505893 
     form.WindowState = FormWindowState.Minimized; 
     form.Shown += delegate(Object sender, EventArgs e) { 
      ((Form)sender).WindowState = FormWindowState.Normal; 
     }; 
     form.ShowDialog(); 
    } 
    else 
    { 
     //it's an hack, thanks to http://stackoverflow.com/a/11941579/505893 
     form.WindowState = FormWindowState.Minimized; 
     form.Show(); 
     form.WindowState = FormWindowState.Normal; 

     //set focus on the first control 
     form.SelectNextControl(form.ActiveControl, true, true, true, true); 
    } 
} 
Các vấn đề liên quan