当前位置:  开发笔记 > 编程语言 > 正文

C#:如何使表单记住其Bounds和WindowState(考虑双显示器设置)

如何解决《C#:如何使表单记住其Bounds和WindowState(考虑双显示器设置)》经验,为你挑选了0个好方法。

我创建了一个表可以继承的类,它处理表单位置,大小和状态.而且效果很好.除了一件事:

当您在与主要屏幕不同的屏幕上最大化应用程序时,位置和大小(在最大化之前)被正确存储,但是当它最大化时(根据其先前的状态),它在我的主监视器上最大化.当我将其恢复到正常状态时,它会转到之前的其他屏幕.当我再次最大化它时,它当然会在正确的屏幕上最大化.

所以我的问题是......我怎样才能制作一个表格,当它最大化时,记住它最大化的屏幕是什么?当表单再次打开时,如何恢复?


一种完整的问题解决方案

我接受了一个非常好的提示,如果在屏幕上如何.但这只是我问题的一部分,所以这是我的解决方案:

负载

    首先得到存储BoundsWindowState任何存储.

    然后设置Bounds.

    确保Bounds通过Screen.AllScreens.Any(ø => ø.Bounds.IntersectsWith(Bounds))或可见MdiParent.Controls.OfType().First().ClientRectangle.IntersectsWith(Bounds).

    如果没有,就这样做Location = new Point();.

    然后设置窗口状态.

关闭时

    商店WindowState.

    如果WindowStateFormWindowState.Normal,则存储Bounds,否则存储RestoreBounds.

就是这样!=)

一些示例代码

因此,正如Oliver所建议的,这里有一些代码.它需要充实,但这可以作为任何想要的人的开始:

PersistentFormHandler

负责在某处存储和获取数据.

public sealed class PersistentFormHandler
{
    /// The form identifier in storage.
    public string Name { get; private set; }


    /// Gets and sets the window state. (int instead of enum so that it can be in a BI layer, and not require a reference to WinForms)
    public int WindowState { get; set; }


    /// Gets and sets the window bounds. (X, Y, Width and Height)
    public Rectangle WindowBounds { get; set; }


    /// Dictionary for other values.
    private readonly Dictionary otherValues;


    /// 
    /// Instantiates new persistent form handler.
    /// 
    /// The  will be used as .
    /// Default state of the window.
    /// Default bounds of the window.
    public PersistentFormHandler(Type windowType, int defaultWindowState, Rectangle defaultWindowBounds)
        : this(windowType, null, defaultWindowState, defaultWindowBounds) { }

    /// 
    /// Instantiates new persistent form handler.
    /// 
    /// The  will be used as base .
    /// Use this if you need to separate windows of same type. Will be appended to .
    /// Default state of the window.
    /// Default bounds of the window.
    public PersistentFormHandler(Type windowType, string id, int defaultWindowState, Rectangle defaultWindowBounds)
    {
        Name = string.IsNullOrEmpty(id) 
            ? windowType.FullName 
            : windowType.FullName + ":" + id;

        WindowState = defaultWindowState;
        WindowBounds = defaultWindowBounds;

        otherValues = new Dictionary();
    }


    /// 
    /// Looks for previously stored values in database.
    /// 
    /// False if no previously stored values were found.
    public bool Load()
    {
        // See Note 1
    }

    /// 
    /// Stores all values in database
    /// 
    public void Save()
    {
        // See Note 2
    }

    /// 
    /// Adds the given  to the collection of values that will be
    /// stored in database on .
    /// 
    /// Type of object.
    /// The key you want to use for this value.
    /// The value to store.
    public void Set(string key, T value)
    {
        // Create memory stream
        using (var s = new MemoryStream())
        {
            // Serialize value into binary form
            var b = new BinaryFormatter();
            b.Serialize(s, value);

            // Store in dictionary
            otherValues[key] = new Binary(s.ToArray());
        }
    }

    /// 
    /// Same as , but uses default() as fallback value.
    /// 
    /// Type of object
    /// The key used on .
    /// The stored object, or the default() object if something went wrong.
    public T Get(string key)
    {
        return Get(key, default(T));
    }

    /// 
    /// Gets the value identified by the given .
    /// 
    /// Type of object
    /// The key used on .
    /// Value to return if the given  could not be found.
    /// In other words, if you haven't used  yet.
    /// The stored object, or the  object if something went wrong.
    public T Get(string key, T fallback)
    {
        // If we have a value with this key
        if (otherValues.ContainsKey(key))
        {
            // Create memory stream and fill with binary version of value
            using (var s = new MemoryStream(otherValues[key].ToArray()))
            {
                try
                {
                    // Deserialize, cast and return.
                    var b = new BinaryFormatter();
                    return (T)b.Deserialize(s);
                }
                catch (InvalidCastException)
                {
                    // T is not what it should have been
                    // (Code changed perhaps?)
                }
                catch (SerializationException)
                {
                    // Something went wrong during Deserialization
                }
            }
        }

        // Else return fallback
        return fallback;
    }
}

注1:在加载方法,你必须寻找先前存储的WindowState,WindowBounds和其他值.我们使用SQL Server,并有一个Window表格,表格中的列Id,Name,MachineName(为Environment.MachineName), ,UserId,WindowState,X,Y,.Height Width因此,对于每一个窗口,你将有一个排WindowState,X,Y,HeightWidth为每个用户和机器.另外,我们有一个WindowValues只有一个外键的表WindowId,一个Key类型StringValue列和一个类型的列Binary.如果有找不到的东西,我只是保留默认值并返回false.

注意2:在save方法中,您当然要执行与Load方法相反的操作.为当前用户和计算机创建行Window以及WindowValues它们是否已存在.

PersistentFormBase

此类使用上一个类,并为其他表单形成一个方便的基类.

// Should have been abstract, but that makes the the designer crash at the moment...
public class PersistentFormBase : Form
{
    private PersistentFormHandler PersistenceHandler { get; set; }

    private bool handlerReady;

    protected PersistentFormBase()
    {
        // Prevents designer from crashing
        if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
        {
            Load += persistentFormLoad;
            FormClosing += persistentFormFormClosing;
        }
    }

    protected event EventHandler ValuesLoaded;
    protected event EventHandler StoringValues;

    protected void StoreValue(string key, T value)
    {
        if (!handlerReady)
            throw new InvalidOperationException();
        PersistenceHandler.Set(key, value);
    }

    protected T GetValue(string key)
    {
        if (!handlerReady)
            throw new InvalidOperationException();
        return PersistenceHandler.Get(key);
    }

    protected T GetValue(string key, T fallback)
    {
        if (!handlerReady)
            throw new InvalidOperationException();
        return PersistenceHandler.Get(key, fallback);
    }

    private void persistentFormLoad(object sender, EventArgs e)
    {
        // Create PersistenceHandler and load values from it
        PersistenceHandler = new PersistentFormHandler(GetType(), (int) FormWindowState.Normal, Bounds);
        PersistenceHandler.Load();
        handlerReady = true;

        // Set size and location
        Bounds = PersistenceHandler.WindowBounds;

        // Check if we have an MdiParent
        if(MdiParent == null)
        {
            // If we don't, make sure we are on screen
            if (!Screen.AllScreens.Any(ø => ø.Bounds.IntersectsWith(Bounds)))
                Location = new Point();
        }
        else
        {
            // If we do, make sure we are visible within the MdiClient area
            var c = MdiParent.Controls.OfType().FirstOrDefault();
            if(c != null && !c.ClientRectangle.IntersectsWith(Bounds))
                Location = new Point();
        }

        // Set state
        WindowState = Enum.IsDefined(typeof (FormWindowState), PersistenceHandler.WindowState) ? (FormWindowState) PersistenceHandler.WindowState : FormWindowState.Normal;

        // Notify that values are loaded and ready for getting.
        var handler = ValuesLoaded;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    private void persistentFormFormClosing(object sender, FormClosingEventArgs e)
    {
        // Set common things
        PersistenceHandler.WindowState = (int) WindowState;
        PersistenceHandler.WindowBounds = WindowState == FormWindowState.Normal ? Bounds : RestoreBounds;

        // Notify that values will be stored now, so time to store values.
        var handler = StoringValues;
        if (handler != null)
            handler(this, EventArgs.Empty);

        // Save values
        PersistenceHandler.Save();
    }
}

这就是它.要使用它,表单只会从PersistentFormBase继承.这将自动处理边界和状态.如果还应存储任何其他内容,例如分割器距离,您将监听ValuesLoadedStoringValues事件,并使用GetValueStoreValue方法.

希望这可以帮助别人!如果有,请告诉我.而且,如果您认为可以做得更好或其他什么,请提供一些反馈.我想学习=)

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有