Yanıtlar:
Hmmm, Form'u geçersiz kılmıyor, ShowWithoutActivation yeterli mi?
protected override bool ShowWithoutActivation
{
get { return true; }
}
Kullanıcının bu bildirim penceresini de tıklamasını istemiyorsanız, CreateParams'ı geçersiz kılabilirsiniz:
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
iç kontrollerin odak çalmasını önlemek için ayarlamam gerekiyor
WS_EX_NOACTIVATE
ve WS_EX_TOOLWINDOW
vardır 0x08000000
ve 0x00000080
sırasıyla.
Çalıntı PInvoke.net sitesindeki ShowWindow yöntemi:
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 bunu yanıtladı, sadece kodu doğrudan yapıştırarak genişletiyorum. Düzenleme haklarına sahip biri bunu kopyalayabilir ve umursadığım herkes için silebilir;))
Win32 P / Invoke kullanmaya hazırsanız , ShowWindow yöntemini kullanabilirsiniz (ilk kod örneği tam olarak istediğinizi yapar).
Bu benim için işe yaradı. TopMost sağlar ancak odak çalmaz.
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;
}
}
TopMost ayarını Visual Studio tasarımcısında veya başka bir yerde atlamayı unutmayın.
Bu buradan çalınmış, err, ödünç alınmıştır (Geçici Çözümlere tıklayın):
Bunu yapmak bir kesmek gibi görünüyor, ancak işe yarıyor gibi görünüyor:
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
Düzenleme: Not, bu sadece odak çalmadan önceden oluşturulmuş bir formu yükseltir.
Alex Lyman / TheSoftwareJedi'nin cevaplarındaki pinvoke.net'ten alınan örnek kod, pencereyi "en üstteki" bir pencere haline getirecektir, bu da açıldıktan sonra normal pencerelerin arkasına koyamayacağınız anlamına gelir. Matias'ın bunu ne için kullanmak istediğine dair açıklaması göz önüne alındığında, istediği bu olabilir. Ancak, kullanıcının pencerenizi açtıktan sonra diğer pencerelerin arkasına koymasını istiyorsanız, örnekte HWND_TOPMOST (-1) yerine HWND_TOP (0) kullanın.
WPF'de şu şekilde çözebilirsiniz:
Pencereye şu nitelikleri koyun:
<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>
Son öznitelik ihtiyacınız olan ShowActivated = "False".
Bildirim Formunu ayrı bir iş parçacığında oluşturun ve başlatın ve Form açıldıktan sonra odağı ana formunuza sıfırlayın. Bildirim Formundan, Form.Shown
olaydan tetiklenen bir OnFormOpened olayı sağlayın . Bunun gibi bir şey:
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
}
Ayrıca, NotifcationForm nesnenizin tutamacını ana Form ( frm.Close()
) tarafından program aracılığıyla kapatılabilmesi için tutabilirsiniz .
Bazı ayrıntılar eksik, ancak umarım bu doğru yönde ilerlemenizi sağlar.
Ne tür bir bildirim görüntülemek istediğinizi düşünmek isteyebilirsiniz.
Kullanıcıya Messagebox'ı kullanarak bir olay hakkında bilgi vermek kesinlikle kritikse, ana pencere üzerindeki diğer olayları kullanıcı onaylayana kadar engellemesinin doğası gereği önerilen yol gösterilecektir. Ancak pop-up körlüğünün farkında olun.
Kritik durumdan daha azsa, bildirimleri görüntülemek için pencerenin altındaki araç çubuğu gibi alternatif bir yol kullanmak isteyebilirsiniz. Bildirimleri ekranın sağ alt köşesinde görüntülediğinizi yazdınız - bunu yapmanın standart yolu , bir sistem tepsisi simgesinin kombinasyonuyla bir balon ucu kullanmak olacaktır .
Bu iyi çalışıyor.
Bakınız: OpenIcon - MSDN ve 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);
}
Sen can ben aslında odak çalmak olmadan BringToFront yöntemi ile sona nerede Yukarıdaki öneriler en zarif biri olduğunu itiraf etmeliyim rağmen, tek başına çok mantıkla idare.
Her neyse, ben bu koştu ve son zamanlarda aramalar yapılmışsa daha fazla BringToFront çağrıları izin vermemek için bir DateTime özelliği kullanarak çözdü.
Örneğin, üç formu ('Form1, 2 ve 3') işleyen bir çekirdek sınıf olan 'Core' varsayalım. Her form, pencereleri öne getirmek için Core'u çağıran bir DateTime özelliğine ve bir Activate olayına ihtiyaç duyar:
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;
}
Ve sonra Çekirdek Sınıfta çalışma oluşturun:
internal static void BringAllToFront(Form inForm)
{
Form1.BringToFront();
Form2.BringToFront();
Form3.BringToFront();
inForm.Focus();
}
Yan notta, simge durumuna küçültülmüş bir pencereyi orijinal durumuna (simge durumuna getirilmemiş) geri yüklemek istiyorsanız, şunu kullanın:
inForm.WindowState = FormWindowState.Normal;
Yine, bunun bir BringToFrontWithoutFocus eksikliğinde sadece bir yama çözümü olduğunu biliyorum. DLL dosyasından kaçınmak istiyorsanız bir öneri olarak kastedilmektedir.
Bu necro gönderme olarak kabul edilir bilmiyorum, ama bu ı user32's "ShowWindow" ve "SetWindowPos" yöntemleri ile çalışma alamadım beri ne yaptı. Ve hayır, yeni pencerenin her zaman üstte olması gerektiğinden "ShowWithoutActivation" geçersiz kılınmaz. Neyse, parametre olarak bir form alan bir yardımcı yöntem oluşturdum; çağrıldığında, formu gösterir, öne getirir ve geçerli pencerenin odağını çalmadan TopMost yapar (görünüşe göre öyle, ancak kullanıcı fark etmez).
[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);
}
}
Kulağa aptalca gelebileceğini biliyorum, ama bu işe yaradı:
this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
Bunu pencerem TopMost ile yapmam gerekiyordu. Yukarıdaki PInvoke yöntemini uyguladım ancak Load etkinimin yukarıdaki Talha gibi çağrılmadığını buldum. Sonunda başardım. Belki bu birisine yardım eder. İşte benim çözümüm:
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
Kullanarak yeni bir form oluşturduğunuzda
Form f = new Form();
f.ShowDialog();
bu form kapatılıncaya kadar kodunuz ana formda yürütülmeye devam edemediği için odağı çalar.
Bunun istisnası, yeni bir form oluşturmak için iş parçacığı kullanarak Form.Show () yöntemidir. Bununla birlikte, iş parçacığının genel olarak görünür olduğundan emin olun, çünkü bir işlev içinde bildirirseniz, işlevinizden çıkar çıkmaz iş parçanız sona erer ve form kaybolur.
Bunu anladım: window.WindowState = WindowState.Minimized;
.