窗口最大化后调用的事件

5
我正在寻找一个与表单相关的事件,在窗口被最大化或最小化调用。
据我所知,有SizeChanged或WndProc事件可以处理最大化的窗口,但它会在用户尝试最大化窗口后立即调用,而不是在窗口完全最大化后调用。
我正在寻找类似于ResizeEnd的事件,但也许这个事件被称为MaximizedEnd或MinimizedEnd。
有没有什么方法可以做到这一点?

1
您可以订阅SizeChanged事件,在监听器内部创建一个线程,等待WindowState被设置为Maximized(您可以通过PInvoke获取WindowState),然后调用ResizeEnd方法。 - SimpleVar
6个回答

6
我认为这很简单:
protected override void OnSizeChanged(EventArgs e) {
  if (this.WindowState == FormWindowState.Maximized) {
    MessageBox.Show("Max!");
  }
  base.OnSizeChanged(e);
}

不确定您所说的“改变窗口大小后”的意思。这也可能起作用:

protected override void OnSizeChanged(EventArgs e) {
  if (this.WindowState == FormWindowState.Maximized) {
    this.BeginInvoke(new MethodInvoker(delegate { MessageBox.Show("Maxed"); }));
  }
  base.OnSizeChanged(e);
}

请用您的代码替换MessageBox.Show(...)

1
嗨,LarsTech,你的第一个解决方案对我有用。谢谢。 - grmbl

2
使用resize、resizeBegin和resizeEnd事件是在Winform调整大小后执行某些操作的好方法。
private bool resize_flag = true;
    private void Form1_Resize(object sender, EventArgs e)
    {
        if (!resize_flag) return;
        //your code here
        resize_flag = true;
    }

    private void Form1_ResizeBegin(object sender, EventArgs e)
    {
        resize_flag = false;
    }

    private void Form1_ResizeEnd(object sender, EventArgs e)
    {
        //your code here
        resize_flag = true;
    }

这段代码很简单但是有效!resizeEnd用于通过鼠标拖动来调整大小,而resize用于更改窗口状态,例如最大化或还原。我认为重写WndProc()是好的,但它在winform调整大小之前被触发,所以...


1
这是 Gabriel 的解决方案的详细内容。我认为也没有 WindowStateChanged 的事件。
我刚刚测试了这个解决方案,当你点击最大化按钮时它是有效的。不过它似乎被触发了三次。我建议你进行一些调试,找出你想要拦截的确切 m.Msg,以检查状态是否已更改。我在这里找到了一些 WM_ 消息的快速参考 http://www.autohotkey.com/docs/misc/SendMessageList.htm
    protected override void WndProc(ref Message m)
    {
        FormWindowState previousWindowState = this.WindowState;

        base.WndProc(ref m);

        FormWindowState currentWindowState = this.WindowState;

        if (previousWindowState != currentWindowState && currentWindowState == FormWindowState.Maximized)
        {
            // TODO: Do something the window has been maximized

        }
    }

如上所述,我已经测试了以上代码至少会被触发3次。下面的代码只会被触发一次。它可能有点冗长,但也更直观,更全面地回答了您如何触发事件的问题。感谢 Yore 在您的问题评论中提出这个想法。
public Form1()
{
    InitializeComponent();

    this.SizeChanged +=new EventHandler(Form1_SizeChanged);
    FormMaximized += new EventHandler(Form1_FormMaximized);

    _CurrentWindowState = this.WindowState;
    if (_CurrentWindowState == FormWindowState.Maximized)
    {
        FireFormMaximized();
    }
}

public event EventHandler FormMaximized;
private void FireFormMaximized()
{
    if (FormMaximized != null)
    {
        FormMaximized(this, EventArgs.Empty);
    }
}

private FormWindowState _CurrentWindowState;
private void Form1_SizeChanged(object sender, EventArgs e)
{
    if (this.WindowState == FormWindowState.Maximized && _CurrentWindowState != FormWindowState.Maximized)
    {
        FireFormMaximized();
    }
    _CurrentWindowState = this.WindowState;
}

void Form1_FormMaximized(object sender, EventArgs e)
{
    //TODO Put you're code here
}

哦,如果你真的想的话,你可以在“待办事项”部分触发你的事件。 - Dan P

0

这可能不是你想要的答案,但在窗口最大化后没有定义的 Windows Form 事件被调用。如果有任何事件需要找到,你必须自己进入消息循环。通常,如果我想知道用户是否最大化了窗口,但不关心大小是否改变,我会保存 windowstate,如果它在 SizedChanged 上改变,我可以说窗口已经最大化。


0

我知道这是一个旧的帖子,但也许有人在寻找答案时会发现这个。

您可以创建自己的自定义事件来完全实现您想要的功能。

声明事件:

Public Event Maximized(sender As Object, e As EventArgs)

触发自定义事件:

Private Sub frmMain_ResizeEnd(sender As Object, e As EventArgs) Handles Me.ResizeEnd
    If Me.WindowState = FormWindowState.Maximized Then RaiseEvent Maximized(sender, Nothing)
End Sub

处理您的自定义事件:

Private Sub frmMain_Maximized(sender As Object, e As EventArgs) Handles Me.Maximized

End Sub

或者

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    AddHandler Me.Maximized, AddressOf MaximizedEventMethod
End Sub

Private Sub MaximizedEventMethod(sender As Object, e As EventArgs)
    'add your code here
End Sub

在窗体最大化之后,ResizeEnd不会被调用,只有在最大化之前才会被调用。 - johnnyontheweb

0

我认为我们应该重写wndProc并获取WM_SYSCOMMAND事件的触发。

protected override void WndProc(ref Message m)
    {
        if ((UInt32)m.Msg == Constant.WM_SYSCOMMAND)
        {
            switch ((UInt32)m.WParam)
            {
                case Constant.SC_MAXIMIZE:

                case Constant.SC_RESTORE:

                default:
                    break;
            }
        }
        base.WndProc(ref m);
    }

SysCommands触发窗口最大化,因此如果您将处理程序放入开关中,则会过早地执行。如果在调用base.WndProc之后检查WM_SYSCOMMAND,则可能会更好,但是此时您无法确定最大化是否已完成;第一个处理程序可能会将一些后续消息发布到消息队列中。 - Rolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接