У меня есть два вопроса.
1) Я нашел небольшую жемчужину кода для как сделать плавная прокрутка элемента управления.
Отлично. Но он переопределяет метод WndProc, поэтому, чтобы использовать его, мне пришлось вырвать FlowLayoutPanel, который я поместил на форму во время разработки, создать подкласс FlowLayoutPanel, а затем, наконец, создать экземпляр моего нового класса, создать все свойства вручную и изменить все ссылки. чтобы элемент управления был this.Controls["ControlName"]. (Или, я думаю, я мог бы создать переменную уровня класса, которая, по сути, является тем, чем изначально был элемент управления, хотя как они позволяют вам использовать intellisense для него, если он нигде не объявлен?)
Так что теперь мне просто интересно, был ли на самом деле способ сделать это во время выполнения.
Могу ли я сделать что-то простое, как это, где 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, мы можем просто поменять местами последний бит (исключающее ИЛИ), а не И, а затем ИЛИ.