Câu trả lời:
Hmmm, không chỉ đơn giản là ghi đè Form.ShowWithoutActivation đủ?
protected override bool ShowWithoutActivation
{
get { return true; }
}
Và nếu bạn không muốn người dùng nhấp vào cửa sổ thông báo này, bạn có thể ghi đè CreatParams:
protected override CreateParams CreateParams
{
get
{
CreateParams baseParams = base.CreateParams;
const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOOLWINDOW = 0x00000080;
baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );
return baseParams;
}
}
form1.Enabled = false
để ngăn chặn các kiểm soát bên trong lấy cắp tiêu điểm
WS_EX_NOACTIVATE
và WS_EX_TOOLWINDOW
là 0x08000000
và 0x00000080
tương ứng.
Bị đánh cắp từ phương thức ShowWindow của PInvoke.net :
private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
int hWnd, // Window handle
int hWndInsertAfter, // Placement-order handle
int X, // Horizontal position
int Y, // Vertical position
int cx, // Width
int cy, // Height
uint uFlags); // Window positioning flags
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowInactiveTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
frm.Left, frm.Top, frm.Width, frm.Height,
SWP_NOACTIVATE);
}
(Alex Lyman đã trả lời điều này, tôi chỉ mở rộng nó bằng cách dán trực tiếp mã. Ai đó có quyền chỉnh sửa có thể sao chép nó ở đó và xóa nó cho tất cả những gì tôi quan tâm;))
Nếu bạn sẵn sàng sử dụng Win32 P / Gọi , thì bạn có thể sử dụng phương thức ShowWindow (mẫu mã đầu tiên thực hiện chính xác những gì bạn muốn).
Đây là những gì làm việc cho tôi. Nó cung cấp TopMost nhưng không lấy nét tập trung.
protected override bool ShowWithoutActivation
{
get { return true; }
}
private const int WS_EX_TOPMOST = 0x00000008;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_TOPMOST;
return createParams;
}
}
Nhớ bỏ qua cài đặt TopMost trong trình thiết kế Visual Studio hoặc ở nơi khác.
Điều này bị đánh cắp, lỗi, mượn, từ đây (bấm vào Workaround):
Làm điều này có vẻ như một hack, nhưng nó dường như hoạt động:
this.TopMost = true; // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top
Chỉnh sửa: Lưu ý, điều này chỉ làm tăng một hình thức đã được tạo mà không lấy cắp trọng tâm.
Mã mẫu từ pinvoke.net trong câu trả lời của Alex Lyman / TheSoftwareJedi's sẽ biến cửa sổ thành cửa sổ "trên cùng", nghĩa là bạn không thể đặt nó phía sau các cửa sổ bình thường sau khi nó bật lên. Đưa ra mô tả của Matias về những gì anh ta muốn sử dụng này cho, đó có thể là những gì anh ta muốn. Nhưng nếu bạn muốn người dùng có thể đặt cửa sổ của bạn phía sau các cửa sổ khác sau khi bạn bật nó lên, chỉ cần sử dụng HWND_TOP (0) thay vì HWND_TOPMOST (-1) trong mẫu.
Trong WPF bạn có thể giải quyết nó như thế này:
Trong cửa sổ đặt các thuộc tính này:
<Window
x:Class="myApplication.winNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Notification Popup" Width="300" SizeToContent="Height"
WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>
Thuộc tính cuối cùng là thuộc tính bạn cần ShowActivated = "Sai".
Tạo và bắt đầu Biểu mẫu thông báo trong một chuỗi riêng biệt và đặt lại tiêu điểm trở lại biểu mẫu chính của bạn sau khi Biểu mẫu mở ra. Có Mẫu thông báo cung cấp một sự kiện OnFormOpened được kích hoạt từ Form.Shown
sự kiện này. Một cái gì đó như thế này:
private void StartNotfication()
{
Thread th = new Thread(new ThreadStart(delegate
{
NotificationForm frm = new NotificationForm();
frm.OnFormOpen += NotificationOpened;
frm.ShowDialog();
}));
th.Name = "NotificationForm";
th.Start();
}
private void NotificationOpened()
{
this.Focus(); // Put focus back on the original calling Form
}
Bạn cũng có thể giữ tay cầm đối tượng NotifcationForm của mình để nó có thể được đóng theo chương trình bởi Biểu mẫu chính (frm.Close()
).
Một số chi tiết bị thiếu, nhưng hy vọng điều này sẽ giúp bạn đi đúng hướng.
Bạn có thể muốn xem xét loại thông báo nào bạn muốn hiển thị.
Nếu nó cực kỳ quan trọng để cho người dùng biết về một số sự kiện, sử dụng Messagebox.Show sẽ là cách được đề xuất, do bản chất của nó là chặn bất kỳ sự kiện nào khác vào cửa sổ chính, cho đến khi người dùng xác nhận nó. Hãy nhận biết về mù pop-up, mặc dù.
Nếu nó ít quan trọng hơn, bạn có thể muốn sử dụng một cách khác để hiển thị thông báo, chẳng hạn như thanh công cụ ở dưới cùng của cửa sổ. Bạn đã viết, rằng bạn hiển thị các thông báo ở phía dưới bên phải của màn hình - cách tiêu chuẩn để thực hiện việc này sẽ là sử dụng đầu bóng bay với sự kết hợp của biểu tượng khay hệ thống .
Điều này hoạt động tốt.
Xem: OpenIcon - MSDN và SetForegroundWindow - MSDN
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern bool OpenIcon(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ActivateInstance()
{
IntPtr hWnd = IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;
// Restore the program.
bool result = OpenIcon(hWnd);
// Activate the application.
result = SetForegroundWindow(hWnd);
// End the current instance of the application.
//System.Environment.Exit(0);
}
Bạn cũng có thể xử lý nó bằng logic một mình, mặc dù tôi phải thừa nhận rằng các đề xuất ở trên nơi bạn kết thúc bằng phương thức BringToFront mà không thực sự đánh cắp trọng tâm là cách thanh lịch nhất.
Dù sao đi nữa, tôi đã gặp phải vấn đề này và giải quyết nó bằng cách sử dụng thuộc tính DateTime để không cho phép các cuộc gọi BringToFront tiếp theo nếu các cuộc gọi đã được thực hiện gần đây.
Giả sử một lớp lõi, 'Lõi', xử lý ví dụ ba biểu mẫu, 'Biểu mẫu 1, 2 và 3'. Mỗi biểu mẫu cần một thuộc tính DateTime và một sự kiện Kích hoạt gọi Core để đưa các cửa sổ lên phía trước:
internal static DateTime LastBringToFrontTime { get; set; }
private void Form1_Activated(object sender, EventArgs e)
{
var eventTime = DateTime.Now;
if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
Core.BringAllToFront(this);
LastBringToFrontTime = eventTime;
}
Và sau đó tạo công việc trong Lớp lõi:
internal static void BringAllToFront(Form inForm)
{
Form1.BringToFront();
Form2.BringToFront();
Form3.BringToFront();
inForm.Focus();
}
Mặt khác, nếu bạn muốn khôi phục cửa sổ thu nhỏ về trạng thái ban đầu (không được tối đa hóa), hãy sử dụng:
inForm.WindowState = FormWindowState.Normal;
Một lần nữa, tôi biết đây chỉ là một giải pháp vá lỗi trong việc thiếu một ComeToFrontWithoutF Focus. Nó có nghĩa là một gợi ý nếu bạn muốn tránh tập tin DLL.
Tôi không biết liệu đây có được coi là đăng bài không, nhưng đây là những gì tôi đã làm vì tôi không làm cho nó hoạt động với các phương thức "ShowWindow" và "SetWindowPos" của user32. Và không, ghi đè "ShowWithoutActivation" không hoạt động trong trường hợp này vì cửa sổ mới phải luôn ở trên đầu. Dù sao, tôi đã tạo ra một phương thức của trình trợ giúp có dạng là tham số; khi được gọi, nó hiển thị biểu mẫu, đưa nó ra phía trước và làm cho nó trở thành TopMost mà không lấy cắp trọng tâm của cửa sổ hiện tại (rõ ràng là như vậy, nhưng người dùng sẽ không nhận thấy).
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern IntPtr SetForegroundWindow(IntPtr hWnd);
public static void ShowTopmostNoFocus(Form f)
{
IntPtr activeWin = GetForegroundWindow();
f.Show();
f.BringToFront();
f.TopMost = true;
if (activeWin.ToInt32() > 0)
{
SetForegroundWindow(activeWin);
}
}
Tôi biết nó nghe có vẻ ngu ngốc, nhưng điều này đã làm việc:
this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
Tôi cần phải làm điều này với cửa sổ TopMost của tôi. Tôi đã triển khai phương thức PInvoke ở trên nhưng thấy rằng sự kiện Tải của tôi không được gọi như Talha ở trên. Cuối cùng tôi đã thành công. Có lẽ điều này sẽ giúp được ai đó. Đây là giải pháp của tôi:
form.Visible = false;
form.TopMost = false;
ShowWindow(form.Handle, ShowNoActivate);
SetWindowPos(form.Handle, HWND_TOPMOST,
form.Left, form.Top, form.Width, form.Height,
NoActivate);
form.Visible = true; //So that Load event happens
Khi bạn tạo một biểu mẫu mới bằng cách sử dụng
Form f = new Form();
f.ShowDialog();
nó đánh cắp trọng tâm vì mã của bạn không thể tiếp tục thực thi trên biểu mẫu chính cho đến khi biểu mẫu này được đóng lại.
Ngoại lệ là bằng cách sử dụng luồng để tạo một biểu mẫu mới sau đó Form.Show (). Hãy chắc chắn rằng luồng được hiển thị trên toàn cầu, bởi vì nếu bạn khai báo nó trong một hàm, ngay khi hàm của bạn thoát, luồng của bạn sẽ kết thúc và biểu mẫu sẽ biến mất.