Jak*_*ner 7 c# wpf xaml window startup
我有一个WPF应用程序,它将通过专用窗口显示有关投影仪的信息.我想配置用于投影仪显示的屏幕以及用于主应用程序窗口的内容.
此代码将在指定屏幕上生成投影仪输出:
var screen = GetProjectorScreen();
_projectorWindow = new ProjectorWindow();
_projectorWindow.Left = screen.WorkingArea.Left;
_projectorWindow.Top = screen.WorkingArea.Top;
_projectorWindow.Owner = _parentWindow;
_projectorWindow.Show();
public static Screen GetProjectorScreen()
{
var screens = Screen.AllScreens;
if (screens.Length > 1 && Settings.Default.DisplayScreen < screens.Length)
{
return screens[Settings.Default.DisplayScreen];
}
return screens[0];
}
Run Code Online (Sandbox Code Playgroud)
我试图用启动表单做同样的技巧,但到目前为止没有成功.我试图在MainWindow构造函数中设置Top和Left属性,但这不起作用.
通过设置StartupUri从App.xaml.cs启动启动窗口:
StartupUri = new Uri("Windows/MainWindow.xaml", UriKind.Relative);
Run Code Online (Sandbox Code Playgroud)
有没有其他方法来启动启动表单?我试图只调用构造函数,但这会导致崩溃,因为某些资源不再被加载.
Jak*_*ner 10
我搞定了.在设置窗口位置之前,必须将WindowState设置为Normal.并且在创建窗口之前,即在构造函数调用之后,该设置将根本不起作用.因此,我在Windows_Loaded事件中调用显式设置.如果需要移动窗口,这可能会导致闪烁,但这对我来说是可以接受的.
在用户手动更改屏幕设置后,也应调用SetScreen方法.
private void SetScreen()
{
var mainScreen = ScreenHandler.GetMainScreen();
var currentScreen = ScreenHandler.GetCurrentScreen(this);
if (mainScreen.DeviceName != currentScreen.DeviceName)
{
this.WindowState = WindowState.Normal;
this.Left = mainScreen.WorkingArea.Left;
this.Top = mainScreen.WorkingArea.Top;
this.Width = mainScreen.WorkingArea.Width;
this.Height = mainScreen.WorkingArea.Height;
this.WindowState = WindowState.Maximized;
}
}
Run Code Online (Sandbox Code Playgroud)
备份ScreenHandler实用程序非常简单:
public static class ScreenHandler
{
public static Screen GetMainScreen()
{
return GetScreen(Settings.Default.MainScreenId);
}
public static Screen GetProjectorScreen()
{
return GetScreen(Settings.Default.ProjectorScreenId);
}
public static Screen GetCurrentScreen(Window window)
{
var parentArea = new Rectangle((int)window.Left, (int)window.Top, (int)window.Width, (int)window.Height);
return Screen.FromRectangle(parentArea);
}
private static Screen GetScreen(int requestedScreen)
{
var screens = Screen.AllScreens;
var mainScreen = 0;
if (screens.Length > 1 && mainScreen < screens.Length)
{
return screens[requestedScreen];
}
return screens[0];
}
}
Run Code Online (Sandbox Code Playgroud)
已接受的答案不再适用于应用清单中带有每个显示器 DPI 的 Windows 10。
以下是对我有用的内容:
public partial class MyWindow : Window
{
readonly Rectangle screenRectangle;
public MyWindow( System.Windows.Forms.Screen screen )
{
screenRectangle = screen.WorkingArea;
InitializeComponent();
}
[DllImport( "user32.dll", SetLastError = true )]
static extern bool MoveWindow( IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint );
protected override void OnSourceInitialized( EventArgs e )
{
base.OnSourceInitialized( e );
var wih = new WindowInteropHelper( this );
IntPtr hWnd = wih.Handle;
MoveWindow( hWnd, screenRectangle.Left, screenRectangle.Top, screenRectangle.Width, screenRectangle.Height, false );
}
void Window_Loaded( object sender, RoutedEventArgs e )
{
WindowState = WindowState.Maximized;
}
}
Run Code Online (Sandbox Code Playgroud)
只是设置左/上不起作用。根据我的测试,每个显示器的 DPI 感知仅在窗口已经创建并放置在某个显示器上之后才会启动。在此之前,显然窗口的 Left/Top 属性随主监视器的 DPI 缩放。
对于每显示器 DPI 和显示器布局的某些组合,这会导致一个错误,其中将 Left/Top 属性设置为 System.Windows.Forms.Screen 矩形的像素值会导致窗口位于其他位置。
上述解决方法仅适用于最大化,它并不总是设置正确的窗口大小。但至少它设置了正确的左上角,这足以使最大化正常工作。
| 归档时间: |
|
| 查看次数: |
8467 次 |
| 最近记录: |