Vista 알림 아이콘 대화 상자를 WPF로 모방합니다
-
21-08-2019 - |
문제
Vista (예 : 네트워크 또는 사운드 아이콘과 같은)에서 알림 아이콘을 단일 클릭하면 테두리면이면서도 캡션이없는 대화 상자가 표시됩니다 (http://i.msdn.microsoft.com/aa511448. notificationArea22(en-us, msdn.10).png):
http://i.msdn.microsoft.com/aa511448. notificationArea22(en-us, msdn.10).png
WPF에서 어떻게 이것을 모방 할 수 있습니까? 새 창을 만들고 창 스타일을 "없음"으로 설정하고 "canresize"로 resizemode는 프레임이 약간 너무 얇고 대화 상자가 방출 될 수 있다는 점을 제외하고는 근접한 결과를 얻습니다. resizemode를 "Noresize"로 설정하면 에어로 테두리가없는 창이됩니다 (얇은 2px 실선 테두리.)
해결책 2
나는 마침내 그것을 알아 냈습니다. Windows 스타일을 "없음"으로 설정하고 "Canresize"로 설정하면 캡션없이 올바른 두꺼운 테두리를 얻을 수 있습니다.
다행히도이 문제는 WM_NCHITTEST를 처리하여 쉽게 수정됩니다. Window
사례:
private IntPtr _hwnd;
protected override void OnSourceInitialized(EventArgs e) {
_hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
System.Windows.Interop.HwndSource.FromHwnd(_hwnd).AddHook(_WndProc);
base.OnSourceInitialized(e);
}
private const int WM_NCHITTEST = 132;
private const int HTCLIENT = 1;
private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
// We should only receive messages for our own window handle.
System.Diagnostics.Debug.Assert(hwnd == _hwnd);
if (msg == WM_NCHITTEST) {
handled = true;
return (IntPtr)HTCLIENT;
}
return IntPtr.Zero;
}
커서가 경계에 있음을 창문에 알리지 않으면 크기 조정 커서가 절대로 제시되지 않습니다.
다른 팁
속임수는 자신의 국경을 더하는 것입니다. 기본 컨텐츠 요소를 DockPanel로 만들고 테두리를 추가하여 그렇게했습니다. 경계를 사용하여 Vista 스타일 창과 일치하는 모양을 사용자 정의 할 수 있습니다. 나는 색상이 좋지 않으므로 특정 이름을 지정할 수는 없지만 회색을 예로 사용했습니다.
다음을 시도하십시오
<Window x:Class="WpfApplication10.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300"
WindowStyle="None"
ResizeMode="NoResize">
<DockPanel>
<Border
BorderBrush="Gray"
BorderThickness="5">
<TextBlock>Here we go</TextBlock>
</Border>
</DockPanel>
</Window>
필요한 것은 창 스타일의 올바른 조합을 지정하는 것입니다. WPF는 Windows에서 사용 가능한 모든 옵션을 노출시키지 않지만 Pinvoke를 사용하여 직접 설정할 수 있습니다.
나는 지금 Vista 기계에 있지 않으므로 스타일 조합을 테스트하여 올바른 모양을 제공하는 것을 볼 수는 없지만 스타일 목록 (C#)은 여기에 있습니다. http://pinvoke.net/default.aspx/user32/getwindowlong.html
당신은 창 클래스에서 :
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
private const int GWL_STYLE = -16;
private const int GWL_EXSTYLE = -20;
private const UInt32 SWP_NOSIZE = 0x0001;
private const UInt32 SWP_NOMOVE = 0x0002;
private const UInt32 SWP_NOZORDER = 0x0004;
private const UInt32 SWP_NOREDRAW = 0x0008;
private const UInt32 SWP_NOACTIVATE = 0x0010;
private const UInt32 SWP_FRAMECHANGED = 0x0020;
public override void OnSourceInitialized(EventArgs e)
{
IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
// set styles to a combination of WS_ flags and exstyles to a combination of WS_EX_ flags
SetWindowLong(hwnd, GWL_STYLE, styles);
SetWindowLong(hwnd, GWL_EXSTYLE, exstyles);
// and to activate changes:
SetWindowPos(hwnd,IntPtr.Zero,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
}
나는 지금까지 내가 생각한 것을 게시 할 것이라고 생각했다. 이것은 꽤 가까워집니다.
<Window.Style>
<Style TargetType="{x:Type Window}">
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderThickness="1" CornerRadius="4" Background="{x:Null}">
<Border.BorderBrush>
<SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
</Border.BorderBrush>
<Border BorderThickness="5" Background="{x:Null}">
<Border.BorderBrush>
<SolidColorBrush Color="{x:Static SystemColors.ActiveBorderColor}" Opacity="0.5" />
</Border.BorderBrush>
<Border BorderThickness="1" Background="White">
<Border.BorderBrush>
<SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
</Border.BorderBrush>
<ContentPresenter />
</Border>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
분명히 그들은 ActiveWindowborderColor에서 투명성 이상을 사용하여 국경의 중간을 끌어 들이고 있습니다. 상단 1/4에는 흰색 오버레이가 있고 하단 3/4에는 검은 색 오버레이가있는 것 같습니다. 또한 바깥 쪽 테두리는 오른쪽과 아래쪽 가장자리에 악센트 색상이 있습니다. 내가 Real을 위해이 작업을 수행한다면, 나는 테두리에서 파생 된 USERCONTROL을 만들어서 그와 같은 모든 작은 세부 사항을 처리하고 (원하는 경우 크기를 조정하고) 창의 스타일을 리소스 사전에 버릴 수 있습니다.