如何检测滚动MDIClient窗口的时间

时间:2013-12-02 11:45:51

标签: c# winforms events

当用户通过拖动MDIClient的滚动条滑块滚动它时,我需要更新System.Windows.Forms.MDIClient容器中子窗口的位置。

但是,当发生这种情况时,我找不到触发的事件。

我只是错过了它,或者我是否需要一种解决方法,可能直接与滚动条对话?

我已经尝试过处理MDIClient.Layout事件,但它们并没有被滚动触发。

编辑:我实际上只需要知道滚动何时停止,以便改变我的子窗口的位置。

EDIT2:作为一种临时解决方法,我每秒都会在计时器上重置子窗口位置,显然不理想,但总比没有好。看起来很糟糕!

1 个答案:

答案 0 :(得分:2)

尽管有点尴尬,但这是可能的。 Winforms并不容易找到MdiClient窗口,并且类本身不会公开Scroll事件。这可以解决,就像在Winforms中一样,您必须对父窗口的本机MDI客户端窗口进行子类化,以便捕获WM_VSCROLL消息。此代码运行良好,将其粘贴到父表单类中:

void MdiClient_Scroll(object sender, ScrollEventArgs e) {
    if (e.Type == ScrollEventType.EndScroll) {
        // Do your stuff
        //...
    }
}

private MdiClientWrapper wrapper;

protected override void OnHandleCreated(EventArgs e) {
    // Find the MdiClient and sub-class it so we can get the Scroll event
    base.OnHandleCreated(e);
    if (wrapper != null) wrapper.Scroll -= MdiClient_Scroll;
    var client = this.Controls.OfType<MdiClient>().First();
    wrapper = new MdiClientWrapper();
    wrapper.AssignHandle(client.Handle);
    wrapper.Scroll += MdiClient_Scroll;
}

private class MdiClientWrapper : NativeWindow {
    public event ScrollEventHandler Scroll;
    private int oldPos;
    protected override void WndProc(ref Message m) {
        if (m.Msg == 0x115) {   // Trap WM_VSCROLL
            var type = (ScrollEventType)(m.WParam.ToInt32() & 0xffff);
            var pos = m.WParam.ToInt32() >> 16;
            Scroll(this, new ScrollEventArgs(type, oldPos, pos));
            oldPos = pos;
        }
        base.WndProc(ref m);
    }
}