.NET WPF 세션 간 창 크기 기억
기본적으로 사용자가 내 응용프로그램의 창 크기를 조정할 때 응용프로그램을 다시 열 때 응용프로그램의 크기가 동일합니다.
처음에는 Size Changed 이벤트를 처리하고 Height와 Width를 저장하려고 했지만, 더 쉬운 해결책이 있을 것 같습니다.
꽤 간단한 문제지만, 저는 그것에 대한 쉬운 해결책을 찾을 수 없습니다.
user.config 파일에 값을 저장합니다.
설정 파일에 값을 만들어야 합니다. 값은 속성 폴더에 있어야 합니다.다섯 개의 값을 만듭니다.
Top
double
Left
double
Height
double
Width
double
Maximized
bool
창이 최대화되는지 여부를 유지합니다.더 많은 정보를 저장하려면 다른 유형 또는 구조가 필요합니다.
처음 두 개는 0으로 초기화하고 두 번째 두 개는 응용프로그램의 기본 크기로 초기화하고 마지막 두 개는 거짓으로 초기화합니다.
Window_OnSourceInitialized 이벤트 핸들러를 만들고 다음을 추가합니다.
this.Top = Properties.Settings.Default.Top;
this.Left = Properties.Settings.Default.Left;
this.Height = Properties.Settings.Default.Height;
this.Width = Properties.Settings.Default.Width;
// Very quick and dirty - but it does the job
if (Properties.Settings.Default.Maximized)
{
WindowState = WindowState.Maximized;
}
참고: 설정된 창 배치는 생성자가 아닌 창의 on source 초기화 이벤트에 들어가야 합니다. 그렇지 않으면 두 번째 모니터에서 창을 최대화하면 기본 모니터에서 창이 항상 다시 시작되고 액세스할 수 없습니다.
Window_Closing 이벤트 핸들러를 만들고 다음을 추가합니다.
if (WindowState == WindowState.Maximized)
{
// Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
Properties.Settings.Default.Top = RestoreBounds.Top;
Properties.Settings.Default.Left = RestoreBounds.Left;
Properties.Settings.Default.Height = RestoreBounds.Height;
Properties.Settings.Default.Width = RestoreBounds.Width;
Properties.Settings.Default.Maximized = true;
}
else
{
Properties.Settings.Default.Top = this.Top;
Properties.Settings.Default.Left = this.Left;
Properties.Settings.Default.Height = this.Height;
Properties.Settings.Default.Width = this.Width;
Properties.Settings.Default.Maximized = false;
}
Properties.Settings.Default.Save();
응용 프로그램이 닫힌 상태에서 화면 연결을 끊거나 화면 해상도를 변경하여 표시 영역을 작게 만들면 이 작업이 실패하므로 값을 적용하기 전에 원하는 위치와 크기가 여전히 유효한지 확인해야 합니다.
실제로 설정 저장을 제외하고 코드백을 사용할 필요가 없습니다.사용자 지정 마크업 확장을 사용하여 창 크기와 위치를 다음과 같은 설정으로 바인딩할 수 있습니다.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1"
Title="Window1"
Height="{my:SettingBinding Height}"
Width="{my:SettingBinding Width}"
Left="{my:SettingBinding Left}"
Top="{my:SettingBinding Top}">
이 마크업 확장에 대한 코드는 http://www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/ 에서 찾을 수 있습니다.
사용자 자신의 설정을 "롤링"하고 수동으로 어딘가에 저장할 수 있으며 일반적으로 작동하지만 모든 경우를 올바르게 처리하지 못하는 것은 매우 쉽습니다.종료 시 GetWindowPlacement()를 호출하고 시작 시 SetWindowPlacement()를 호출하여 OS가 작업을 수행하도록 하는 것이 훨씬 좋습니다.발생할 수 있는 모든 비정상적인 에지 사례(여러 모니터, 최대화된 상태에서 닫힌 경우 일반 창의 크기 저장 등)를 처리하여 사용자가 그럴 필요가 없습니다.
이 MSDN 샘플은 WPF 앱과 함께 사용하는 방법을 보여줍니다.샘플이 완벽하지 않습니다. 창이 처음 실행할 때 왼쪽 상단 모서리에서 가능한 작게 시작되고 설정 디자이너가 유형 값을 저장할 때 일부 이상한 동작이 발생합니다.WINDOWPLACEMENT
), 하지만 적어도 시작은 해야 합니다.
Thomas가 위에 게시한 "긴 형식" 바인딩은 코딩이 거의 필요하지 않으므로 네임스페이스 바인딩이 있는지 확인하십시오.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:WpfApplication1.Properties"
Title="Window1"
Height="{Binding Source={x:Static p:Settings.Default}, Path=Height, Mode=TwoWay}"
Width="{Binding Source={x:Static p:Settings.Default}, Path=Width, Mode=TwoWay}"
Left="{Binding Source={x:Static p:Settings.Default}, Path=Left, Mode=TwoWay}"
Top="{Binding Source={x:Static p:Settings.Default}, Path=Top, Mode=TwoWay}">
그런 다음 코드백을 절약하려면 다음과 같이 하십시오.
private void frmMain_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.Save();
}
또는 다음과 같은 방법을 사용할 수도 있습니다(소스 참조).프로젝트에 WindowSettings 클래스를 추가하고 다음을 삽입합니다.WindowSettings.Save="True"
기본 창의 머리글에서:
<Window x:Class="YOURPROJECT.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Services="clr-namespace:YOURNAMESPACE.Services"
Services:WindowSettings.Save="True">
여기서 창 설정은 다음과 같이 정의됩니다.
using System;
using System.ComponentModel;
using System.Configuration;
using System.Windows;
namespace YOURNAMESPACE.Services
{
/// <summary>
/// Persists a Window's Size, Location and WindowState to UserScopeSettings
/// </summary>
public class WindowSettings
{
#region Fields
/// <summary>
/// Register the "Save" attached property and the "OnSaveInvalidated" callback
/// </summary>
public static readonly DependencyProperty SaveProperty = DependencyProperty.RegisterAttached("Save", typeof (bool), typeof (WindowSettings), new FrameworkPropertyMetadata(OnSaveInvalidated));
private readonly Window mWindow;
private WindowApplicationSettings mWindowApplicationSettings;
#endregion Fields
#region Constructors
public WindowSettings(Window pWindow) { mWindow = pWindow; }
#endregion Constructors
#region Properties
[Browsable(false)] public WindowApplicationSettings Settings {
get {
if (mWindowApplicationSettings == null) mWindowApplicationSettings = CreateWindowApplicationSettingsInstance();
return mWindowApplicationSettings;
}
}
#endregion Properties
#region Methods
public static void SetSave(DependencyObject pDependencyObject, bool pEnabled) { pDependencyObject.SetValue(SaveProperty, pEnabled); }
protected virtual WindowApplicationSettings CreateWindowApplicationSettingsInstance() { return new WindowApplicationSettings(this); }
/// <summary>
/// Load the Window Size Location and State from the settings object
/// </summary>
protected virtual void LoadWindowState() {
Settings.Reload();
if (Settings.Location != Rect.Empty) {
mWindow.Left = Settings.Location.Left;
mWindow.Top = Settings.Location.Top;
mWindow.Width = Settings.Location.Width;
mWindow.Height = Settings.Location.Height;
}
if (Settings.WindowState != WindowState.Maximized) mWindow.WindowState = Settings.WindowState;
}
/// <summary>
/// Save the Window Size, Location and State to the settings object
/// </summary>
protected virtual void SaveWindowState() {
Settings.WindowState = mWindow.WindowState;
Settings.Location = mWindow.RestoreBounds;
Settings.Save();
}
/// <summary>
/// Called when Save is changed on an object.
/// </summary>
private static void OnSaveInvalidated(DependencyObject pDependencyObject, DependencyPropertyChangedEventArgs pDependencyPropertyChangedEventArgs) {
var window = pDependencyObject as Window;
if (window != null)
if ((bool) pDependencyPropertyChangedEventArgs.NewValue) {
var settings = new WindowSettings(window);
settings.Attach();
}
}
private void Attach() {
if (mWindow != null) {
mWindow.Closing += WindowClosing;
mWindow.Initialized += WindowInitialized;
mWindow.Loaded += WindowLoaded;
}
}
private void WindowClosing(object pSender, CancelEventArgs pCancelEventArgs) { SaveWindowState(); }
private void WindowInitialized(object pSender, EventArgs pEventArgs) { LoadWindowState(); }
private void WindowLoaded(object pSender, RoutedEventArgs pRoutedEventArgs) { if (Settings.WindowState == WindowState.Maximized) mWindow.WindowState = Settings.WindowState; }
#endregion Methods
#region Nested Types
public class WindowApplicationSettings : ApplicationSettingsBase
{
#region Constructors
public WindowApplicationSettings(WindowSettings pWindowSettings) { }
#endregion Constructors
#region Properties
[UserScopedSetting] public Rect Location {
get {
if (this["Location"] != null) return ((Rect) this["Location"]);
return Rect.Empty;
}
set { this["Location"] = value; }
}
[UserScopedSetting] public WindowState WindowState {
get {
if (this["WindowState"] != null) return (WindowState) this["WindowState"];
return WindowState.Normal;
}
set { this["WindowState"] = value; }
}
#endregion Properties
}
#endregion Nested Types
}
}
NuGet Project Restore Windows Place는 이 모든 것을 지원하며 XML 파일에 정보를 저장합니다.
창에서 작동하려면 다음을 호출하는 것처럼 간단합니다.
((App)Application.Current).WindowPlace.Register(this);
앱에서 창을 관리하는 클래스를 만듭니다.자세한 내용은 위의 github 링크를 참조하십시오.
저는 RandomEngys의 훌륭한 답변을 바탕으로 더 일반적인 솔루션을 만들었습니다.그러면 파일 위치가 실행 중인 폴더에 저장되므로 새 창마다 새 속성을 만들 필요가 없습니다.이 솔루션은 코드 뒤에 있는 최소한의 코드로 저에게 매우 유용합니다.
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Xml;
using System.Xml.Serialization;
namespace WindowPlacementNameSpace
{
// RECT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
// POINT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
// WINDOWPLACEMENT stores the position, size, and state of a window
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public POINT minPosition;
public POINT maxPosition;
public RECT normalPosition;
}
public static class WindowPlacement
{
private static readonly Encoding Encoding = new UTF8Encoding();
private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(WINDOWPLACEMENT));
[DllImport("user32.dll")]
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll")]
private static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private static void SetPlacement(IntPtr windowHandle, string placementXml)
{
if (string.IsNullOrEmpty(placementXml))
{
return;
}
byte[] xmlBytes = Encoding.GetBytes(placementXml);
try
{
WINDOWPLACEMENT placement;
using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
{
placement = (WINDOWPLACEMENT)Serializer.Deserialize(memoryStream);
}
placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
placement.flags = 0;
placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
SetWindowPlacement(windowHandle, ref placement);
}
catch (InvalidOperationException)
{
// Parsing placement XML failed. Fail silently.
}
}
private static string GetPlacement(IntPtr windowHandle)
{
WINDOWPLACEMENT placement;
GetWindowPlacement(windowHandle, out placement);
using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8))
{
Serializer.Serialize(xmlTextWriter, placement);
byte[] xmlBytes = memoryStream.ToArray();
return Encoding.GetString(xmlBytes);
}
}
}
public static void ApplyPlacement(this Window window)
{
var className = window.GetType().Name;
try
{
var pos = File.ReadAllText(Directory + "\\" + className + ".pos");
SetPlacement(new WindowInteropHelper(window).Handle, pos);
}
catch (Exception exception)
{
Log.Error("Couldn't read position for " + className, exception);
}
}
public static void SavePlacement(this Window window)
{
var className = window.GetType().Name;
var pos = GetPlacement(new WindowInteropHelper(window).Handle);
try
{
File.WriteAllText(Directory + "\\" + className + ".pos", pos);
}
catch (Exception exception)
{
Log.Error("Couldn't write position for " + className, exception);
}
}
private static string Directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
}
뒤에 있는 코드에서 이 두 가지 방법을 추가합니다.
///This method is save the actual position of the window to file "WindowName.pos"
private void ClosingTrigger(object sender, EventArgs e)
{
this.SavePlacement();
}
///This method is load the actual position of the window from the file
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
this.ApplyPlacement();
}
xaml 창에서 이것을 추가합니다.
Closing="ClosingTrigger"
기본 해결 방법은 설정 파일을 사용하는 것입니다.설정 파일의 문제는 모든 설정을 정의하고 데이터를 앞뒤로 복사하는 코드를 직접 작성해야 한다는 것입니다.추적해야 할 속성이 많은 경우 상당히 지루합니다.
저는 이를 위해 매우 유연하고 사용하기 쉬운 라이브러리를 만들었습니다. 어떤 개체의 속성을 추적할지 알려주면 나머지를 수행할 수 있습니다.원하는 경우 구성할 수도 있습니다.
도서관 이름은 Jot (github)이고, 여기 제가 쓴 오래된 CodeProject 기사가 있습니다.
창 크기와 위치를 추적하기 위해 사용하는 방법은 다음과 같습니다.
public MainWindow()
{
InitializeComponent();
_stateTracker.Configure(this)
.IdentifyAs("MyMainWindow")
.AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
.RegisterPersistTrigger(nameof(Closed))
.Apply();
}
Jot vs. 설정 파일:Jot의 경우 코드가 상당히 적으며 각 속성을 한 번만 언급하면 되므로 오류가 발생할 가능성이 훨씬 적습니다.설정 파일의 경우 속성을 명시적으로 만들 때 한 번, 값을 앞뒤로 복사하는 코드에서 추가로 네 번 각 속성을 5번 언급해야 합니다.
스토리지, 직렬화 등을 완벽하게 구성할 수 있습니다.또한 IOC를 사용할 때 확인되는 모든 개체에 추적을 자동으로 적용하도록 연결할 수도 있으므로 속성을 영구적으로 유지하려면 [Trackable] 특성을 적용하기만 하면 됩니다.
제가 이 모든 것을 쓰는 이유는 도서관이 최고라고 생각하고 그것에 대해 입 밖에 내고 싶지 않기 때문입니다.
저는 이것을 하는 빠른 수업을 썼습니다.이름은 다음과 같습니다.
public MainWindow()
{
FormSizeSaver.RegisterForm(this, () => Settings.Default.MainWindowSettings,
s =>
{
Settings.Default.MainWindowSettings = s;
Settings.Default.Save();
});
InitializeComponent();
...
코드는 다음과 같습니다.
public class FormSizeSaver
{
private readonly Window window;
private readonly Func<FormSizeSaverSettings> getSetting;
private readonly Action<FormSizeSaverSettings> saveSetting;
private FormSizeSaver(Window window, Func<string> getSetting, Action<string> saveSetting)
{
this.window = window;
this.getSetting = () => FormSizeSaverSettings.FromString(getSetting());
this.saveSetting = s => saveSetting(s.ToString());
window.Initialized += InitializedHandler;
window.StateChanged += StateChangedHandler;
window.SizeChanged += SizeChangedHandler;
window.LocationChanged += LocationChangedHandler;
}
public static FormSizeSaver RegisterForm(Window window, Func<string> getSetting, Action<string> saveSetting)
{
return new FormSizeSaver(window, getSetting, saveSetting);
}
private void SizeChangedHandler(object sender, SizeChangedEventArgs e)
{
var s = getSetting();
s.Height = e.NewSize.Height;
s.Width = e.NewSize.Width;
saveSetting(s);
}
private void StateChangedHandler(object sender, EventArgs e)
{
var s = getSetting();
if (window.WindowState == WindowState.Maximized)
{
if (!s.Maximized)
{
s.Maximized = true;
saveSetting(s);
}
}
else if (window.WindowState == WindowState.Normal)
{
if (s.Maximized)
{
s.Maximized = false;
saveSetting(s);
}
}
}
private void InitializedHandler(object sender, EventArgs e)
{
var s = getSetting();
window.WindowState = s.Maximized ? WindowState.Maximized : WindowState.Normal;
if (s.Height != 0 && s.Width != 0)
{
window.Height = s.Height;
window.Width = s.Width;
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Left = s.XLoc;
window.Top = s.YLoc;
}
}
private void LocationChangedHandler(object sender, EventArgs e)
{
var s = getSetting();
s.XLoc = window.Left;
s.YLoc = window.Top;
saveSetting(s);
}
}
[Serializable]
internal class FormSizeSaverSettings
{
public double Height, Width, YLoc, XLoc;
public bool Maximized;
public override string ToString()
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, this);
ms.Position = 0;
byte[] buffer = new byte[(int)ms.Length];
ms.Read(buffer, 0, buffer.Length);
return Convert.ToBase64String(buffer);
}
}
internal static FormSizeSaverSettings FromString(string value)
{
try
{
using (var ms = new MemoryStream(Convert.FromBase64String(value)))
{
var bf = new BinaryFormatter();
return (FormSizeSaverSettings) bf.Deserialize(ms);
}
}
catch (Exception)
{
return new FormSizeSaverSettings();
}
}
}
기본 설정에서 WindowXml이라는 문자열을 만듭니다.
Window Loaded(윈도우 로드됨) 및 Closing(닫기) 이벤트에서 이 확장 방법을 사용하여 Window(윈도우) 크기와 위치를 복원하고 저장합니다.
using YourProject.Properties;
using System;
using System.Linq;
using System.Windows;
using System.Xml.Linq;
namespace YourProject.Extensions
{
public static class WindowExtensions
{
public static void SaveSizeAndLocation(this Window w)
{
try
{
var s = "<W>";
s += GetNode("Top", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Top : w.Top);
s += GetNode("Left", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Left : w.Left);
s += GetNode("Height", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Height : w.Height);
s += GetNode("Width", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Width : w.Width);
s += GetNode("WindowState", w.WindowState);
s += "</W>";
Settings.Default.WindowXml = s;
Settings.Default.Save();
}
catch (Exception)
{
}
}
public static void RestoreSizeAndLocation(this Window w)
{
try
{
var xd = XDocument.Parse(Settings.Default.WindowXml);
w.WindowState = (WindowState)Enum.Parse(typeof(WindowState), xd.Descendants("WindowState").FirstOrDefault().Value);
w.Top = Convert.ToDouble(xd.Descendants("Top").FirstOrDefault().Value);
w.Left = Convert.ToDouble(xd.Descendants("Left").FirstOrDefault().Value);
w.Height = Convert.ToDouble(xd.Descendants("Height").FirstOrDefault().Value);
w.Width = Convert.ToDouble(xd.Descendants("Width").FirstOrDefault().Value);
}
catch (Exception)
{
}
}
private static string GetNode(string name, object value)
{
return string.Format("<{0}>{1}</{0}>", name, value);
}
}
}
다음과 같이 하십시오.
public class WindowStateHelper
{
public static string ToXml(System.Windows.Window win)
{
XElement bounds = new XElement("Bounds");
if (win.WindowState == System.Windows.WindowState.Maximized)
{
bounds.Add(new XElement("Top", win.RestoreBounds.Top));
bounds.Add(new XElement("Left", win.RestoreBounds.Left));
bounds.Add(new XElement("Height", win.RestoreBounds.Height));
bounds.Add(new XElement("Width", win.RestoreBounds.Width));
}
else
{
bounds.Add(new XElement("Top", win.Top));
bounds.Add(new XElement("Left", win.Left));
bounds.Add(new XElement("Height", win.Height));
bounds.Add(new XElement("Width", win.Width));
}
XElement root = new XElement("WindowState",
new XElement("State", win.WindowState.ToString()),
new XElement("Visibility", win.Visibility.ToString()),
bounds);
return root.ToString();
}
public static void FromXml(string xml, System.Windows.Window win)
{
try
{
XElement root = XElement.Parse(xml);
string state = root.Descendants("State").FirstOrDefault().Value;
win.WindowState = (System.Windows.WindowState)Enum.Parse(typeof(System.Windows.WindowState), state);
state = root.Descendants("Visibility").FirstOrDefault().Value;
win.Visibility = (System.Windows.Visibility)Enum.Parse(typeof(System.Windows.Visibility), state);
XElement bounds = root.Descendants("Bounds").FirstOrDefault();
win.Top = Convert.ToDouble(bounds.Element("Top").Value);
win.Left = Convert.ToDouble(bounds.Element("Left").Value);
win.Height = Convert.ToDouble(bounds.Element("Height").Value);
win.Width = Convert.ToDouble(bounds.Element("Width").Value);
}
catch (Exception x)
{
System.Console.WriteLine(x.ToString());
}
}
}
앱이 닫힐 때:
Properties.Settings.Default.Win1Placement = WindowStateHelper.ToXml(win1);
Properties.Settings.Default.Win2Placement = WindowStateHelper.ToXml(win2);
...
앱이 시작될 때:
WindowStateHelper.FromXml(Properties.Settings.Default.Win1Placement, win1);
WindowStateHelper.FromXml(Properties.Settings.Default.Win2Placement, win2);
...
저는 랜스 클리블랜드의 답변을 사용하여 설정을 바인딩하고 있습니다.그러나 내 창이 화면 밖으로 나오지 않도록 코드를 더 사용하고 있습니다.
private void SetWindowSettingsIntoScreenArea()
{
// first detect Screen, where we will display the Window
// second correct bottom and right position
// then the top and left position.
// If Size is bigger than current Screen, it's still possible to move and size the Window
// get the screen to display the window
var screen = System.Windows.Forms.Screen.FromPoint(new System.Drawing.Point((int)Default.Left, (int)Default.Top));
// is bottom position out of screen for more than 1/3 Height of Window?
if (Default.Top + (Default.Height / 3) > screen.WorkingArea.Height)
Default.Top = screen.WorkingArea.Height - Default.Height;
// is right position out of screen for more than 1/2 Width of Window?
if (Default.Left + (Default.Width / 2) > screen.WorkingArea.Width)
Default.Left = screen.WorkingArea.Width - Default.Width;
// is top position out of screen?
if (Default.Top < screen.WorkingArea.Top)
Default.Top = screen.WorkingArea.Top;
// is left position out of screen?
if (Default.Left < screen.WorkingArea.Left)
Default.Left = screen.WorkingArea.Left;
}
언급URL : https://stackoverflow.com/questions/847752/net-wpf-remember-window-size-between-sessions
'source' 카테고리의 다른 글
후드 아래에서 잠금 문은 무엇을 합니까? (0) | 2023.05.05 |
---|---|
psql: 서버에 연결할 수 없습니다.해당 파일 또는 디렉터리 없음(Mac OS X) (0) | 2023.05.05 |
모든 디렉토리 및 파일을 재귀적으로 복사하려면 어떻게 해야 합니까? (0) | 2023.04.25 |
Linux python3 - lib 'SQL Server'를 열 수 없습니다. (0) | 2023.04.25 |
WPF 창의 핸들을 찾는 중입니다. (0) | 2023.04.25 |