답변:
흠, 단순히 Form.ShowWithoutActivation을 재정의하는 것만으로는 충분하지 않습니까?
protected override bool ShowWithoutActivation
{
get { return true; }
}
사용자가이 알림 창을 클릭하지 못하게하려면 CreateParams를 재정의 할 수 있습니다.
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
내부 컨트롤이 초점을 훔치지 않도록 설정해야했습니다.
WS_EX_NOACTIVATE
과 WS_EX_TOOLWINDOW
있다 0x08000000
및 0x00000080
각각.
PInvoke.net 의 ShowWindow 메소드 에서 도난당했습니다 .
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이 대답했습니다. 코드를 직접 붙여 넣어 코드를 확장하고 있습니다. 편집 권한을 가진 사람이 코드를 복사하여 삭제할 수 있습니다.)
Win32 P / Invoke 를 사용하려는 경우 ShowWindow 메서드를 사용할 수 있습니다 (첫 번째 코드 샘플은 원하는 것을 정확하게 수행함 ).
이것이 나를 위해 일한 것입니다. 포커스가 거의없는 TopMost를 제공합니다.
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;
}
}
Visual Studio 디자이너 또는 다른 곳에서 TopMost 설정을 생략해야합니다.
이것은 여기에서 도난 당하고, 실수로 차용되었습니다 (해결 방법을 클릭하십시오).
이 작업은 해킹처럼 보이지만 작동하는 것 같습니다.
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
편집 : 참고로, 초점을 훔치지 않고 이미 만든 양식을 올릴 수 있습니다.
WPF에서는 다음과 같이 해결할 수 있습니다.
창에서 다음 속성을 입력하십시오.
<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>
마지막 속성은 ShowActivated = "False"가 필요한 속성입니다.
별도의 스레드에서 알림 양식을 작성하고 시작하고 양식을 연 후 포커스를 기본 양식으로 다시 설정하십시오. 알림 양식에 이벤트에서 시작된 OnFormOpened 이벤트를 제공하십시오 Form.Shown
. 이 같은:
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
}
또한 주 양식 ( frm.Close()
) 으로 프로그래밍 방식으로 닫을 수 있도록 NotifcationForm 객체에 대한 핸들을 유지할 수 있습니다 .
일부 세부 사항이 누락되었지만 희망적으로 올바른 방향으로 나아갈 수 있기를 바랍니다.
어떤 종류의 알림을 표시 할 것인지 고려할 수 있습니다.
사용자에게 일부 이벤트에 대해 알리는 것이 절대적으로 중요한 경우 사용자가 확인할 때까지 Messagebox.Show를 사용하면 다른 이벤트를 기본 창에 차단할 수 있으므로 권장되는 방법입니다. 그러나 팝업 실명에 유의하십시오.
중요하지 않은 경우 다른 방법을 사용하여 창의 맨 아래에있는 도구 모음과 같은 알림을 표시 할 수 있습니다. 화면 오른쪽 하단에 알림을 표시한다고 썼습니다. 표준 트레이 는 시스템 트레이 아이콘 과 함께 풍선 도움말을 사용하는 것입니다 .
이것은 잘 작동합니다.
참조 : OpenIcon-MSDN 및 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);
}
실제로 포커스를 훔치지 않고 BringToFront 메서드로 끝나는 위의 제안이 가장 우아하다는 것을 인정해야하지만 논리로만 처리 할 수 있습니다 .
어쨌든, 나는 이미 최근에 전화를 한 경우 더 이상의 BringToFront 호출을 허용하지 않기 위해 DateTime 속성을 사용 하여이 문제를 해결했습니다.
예를 들어 'Form1, 2 및 3'의 세 가지 양식을 처리하는 핵심 클래스 'Core'를 가정하십시오. 각 양식에는 DateTime 속성과 Core를 호출하여 창을 앞으로 가져 오는 Activate 이벤트가 필요합니다.
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;
}
그런 다음 핵심 클래스에서 작업을 작성하십시오.
internal static void BringAllToFront(Form inForm)
{
Form1.BringToFront();
Form2.BringToFront();
Form3.BringToFront();
inForm.Focus();
}
참고로, 최소화 된 창을 원래 상태 (최대화되지 않음)로 복원하려면 다음을 사용하십시오.
inForm.WindowState = FormWindowState.Normal;
다시 말하지만, 이것이 BringToFrontWithoutFocus가없는 패치 솔루션이라는 것을 알고 있습니다. DLL 파일을 피하려면 제안으로 사용됩니다.
이것이 네크로 포스팅으로 간주되는지는 모르겠지만 user32의 "ShowWindow"및 "SetWindowPos"메소드로 작동하지 않기 때문에 내가 한 일입니다. 새 창은 항상 맨 위에 있어야하므로이 경우 "ShowWithoutActivation"을 재정의해도 작동하지 않습니다. 어쨌든 폼을 매개 변수로 사용하는 도우미 메서드를 만들었습니다. 호출되면 양식을 표시하고 앞쪽으로 가져 와서 현재 창의 초점을 훔치지 않고 TopMost로 만듭니다.
[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);
}
}
나는 그것이 어리석은 것처럼 들리지만, 이것은 효과가 있었다 :
this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
내 창 TopMost 로이 작업을 수행해야했습니다. 위의 PInvoke 메서드를 구현했지만 Load 이벤트가 위의 Talha처럼 호출되지 않는 것으로 나타났습니다. 나는 마침내 성공했다. 어쩌면 이것은 누군가를 도울 것입니다. 내 해결책은 다음과 같습니다.
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
그것을 알아 냈습니다 : window.WindowState = WindowState.Minimized;
.