Я хотел сделать то же самое, и после поиска я нашел здесь ваш код, который помог, но, конечно, не решил проблему. Но поиграв с этим, я нашел решение.
Ключ пришел, когда я понял, что, поскольку кнопки прокрутки работают, вы можете использовать это, чтобы заставить работать ползунок. Другими словами, когда наступает событие SB_THUMBTRACK, я выдаю повторные события SB_LINELEFT и SB_LINERIGHT, пока мой дочерний ListView не приблизится к тому месту, где находится мастер. Да, это не идеально, но работает достаточно близко.
В моем случае мой основной ListView называется «reportView», а мой дочерний ListView называется «summaryView». Вот мой подходящий код:
public class MyListView : ListView
{
public event ScrollEventHandler HScrollEvent;
protected override void WndProc(ref System.Windows.Forms.Message msg)
{
if (msg.Msg==WM_HSCROLL && HScrollEvent != null)
HScrollEvent(this,new ScrollEventArgs(ScrollEventType.ThumbTrack, (int)msg.WParam));
base.WndProc(ref msg);
}
}
А потом сам обработчик события:
reportView.HScrollEvent += new ScrollEventHandler((sender,e) => {
if ((ushort) e.NewValue != SB_THUMBTRACK)
SendMessage(summaryView.Handle, WM_HSCROLL, (IntPtr) e.NewValue, IntPtr.Zero);
else {
int newPos = e.NewValue >> 16;
int oldPos = GetScrollPos(reportView .Handle, SB_HORZ);
int pos = GetScrollPos(summaryView.Handle, SB_HORZ);
int lst;
if (pos != newPos)
if (pos<newPos && oldPos<newPos) do { lst=pos; SendMessage(summaryView.Handle,WM_HSCROLL,(IntPtr)SB_LINERIGHT,IntPtr.Zero); } while ((pos=GetScrollPos(summaryView.Handle,SB_HORZ)) < newPos && pos!=lst);
else if (pos>newPos && oldPos>newPos) do { lst=pos; SendMessage(summaryView.Handle,WM_HSCROLL,(IntPtr)SB_LINELEFT, IntPtr.Zero); } while ((pos=GetScrollPos(summaryView.Handle,SB_HORZ)) > newPos && pos!=lst);
}
});
Извините за странное форматирование циклов while, но именно так я предпочитаю кодировать подобные вещи.
Следующей проблемой было избавление от полос прокрутки в дочернем ListView. Я заметил, что у вас есть метод с именем HideScrollBar. Это действительно не работает для меня. Я нашел лучшее решение в моем случае - оставить там полосу прокрутки, но вместо этого «прикрыть» ее. Я делаю это с заголовком столбца. Я просто вставляю свой дочерний элемент управления под главный элемент управления, чтобы закрыть заголовок столбца. А потом я растягиваю ребенка, чтобы выпасть из панели, в которой он находится. И затем, чтобы обеспечить немного границы вдоль края моей содержащей панели, я добавляю элемент управления, чтобы закрыть видимый нижний край моего дочернего ListView. В конечном итоге выглядит довольно красиво.
Я также добавил обработчик событий для синхронизации изменения ширины столбцов, например:
reportView.ColumnWidthChanging += new ColumnWidthChangingEventHandler((sender,e) => {
summaryView.Columns[e.ColumnIndex].Width = e.NewWidth;
});
Хотя все это кажется чем-то вроде клуджа, у меня это работает.