我有两个问题。
1)我找到了一个代码小宝石,可以实现控件平滑滚动。
很棒。但它覆盖了WndProc方法,所以为了使用它,我必须在设计时拆下放在窗体上的FlowLayoutPanel,子类化FlowLayoutPanel,然后最终实例化我的新类并手动创建所有属性并更改对控件的所有引用为this.Controls ["ControlName"]。(或者我可以创建一个类级变量,它本质上是控件原来的样子,但当它没有在任何地方声明时,它们如何让您在智能感知上使用它?)
现在我只想知道是否实际上有一种运行时方法来实现它。
我能做些简单的事情吗,其中MainPanel是控件的名称:
MainPanel = (SmoothScrollingFlowLayoutPanel)MainPanel
这可能不是那么容易,对吧?即使如此,仍然很烦人,因为我仍然需要有子类(这可能是一个很好的设计决策,但我想要一次性自由地使用它)。所以,是否有可能将代码放入FlowLayoutPanel的父类中,就像这样:
private Delegate void WndProcHandler(ref Message m);
private WndProcHandler w;
public void SomeCode() {
w = MainPanel.WndProc; // get reference to existing wndproc method
MainPanel.WndProc = WndProcSmoothScroll; //replace with new method
}
private void WndProcSmoothScroll(ref Message m) { // make smooth scrolling work
if (
(m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
&& (((int)m.WParam & 0xFFFF) == 5)
) {
m.WParam = (IntPtr)(((int)m.WParam & ~0xFFFF) | 4);
}
if (w != null) { w(); }
base.WndProc(ref m);
}
我知道这可能有点幼稚。我将WndProc方法视为事件,但它实际上不是事件。
2) 那么我的第二个问题是,如果WndProc是事件而不是方法,我该如何做同样的事情 - 存储事件处理程序的原始列表副本,安装自己的事件处理程序以首先运行,然后调用所有原始事件处理程序?
美味的细节
如果有人感兴趣,我注意到在平滑滚动代码中可以进行优化:
//m.WParam = (IntPtr)(((int)m.WParam & ~0xFFFF) | 4);
m.WParam = (IntPtr)((int)m.WParam ^ 1);
既然我们想将最后16位从5变为4,我们只需翻转最后一位(XOR),而不是先AND再OR。
FlowLayoutPanel
来重写它的WndProc
。 - Zach Johnson