C# 从OnPaint调用OnDrawItem时,OnDrawItem不考虑水平滚动位置
正如标题所说 历史记录:为了使用C# 从OnPaint调用OnDrawItem时,OnDrawItem不考虑水平滚动位置,c#,listbox,horizontal-scrolling,onpaint,C#,Listbox,Horizontal Scrolling,Onpaint,正如标题所说 历史记录:为了使用DrawMode.OwnerDrawFixed和自定义OnDrawItem()减少我的列表框中的闪烁,我使用了本页的子类化示例: 哪个使用 SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.allpaintingwmpaint | ControlStyles.UserPaint,true) 它工作得很好,除了一件事:当我侧向滚动以查看长字符串时,OnDrawItem()似乎不理解它应该用偏移量
DrawMode.OwnerDrawFixed
和自定义OnDrawItem()减少我的列表框中的闪烁,我使用了本页的子类化示例:
哪个使用
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.allpaintingwmpaint | ControlStyles.UserPaint,true)代码>
它工作得很好,除了一件事:当我侧向滚动以查看长字符串时,OnDrawItem()似乎不理解它应该用偏移量绘制。看起来水平滚动偏移量在途中丢失了,调用OnPaint()填充的区域被我的OnDrawItem()填充,就好像列表框根本没有横向滚动一样
请注意:如果我禁用了ControlStyles.UserPaint
,并让系统直接调用OnDrawItem(),它工作正常,我可以正常地侧滚。但它会闪烁,速度太慢,无法使用。我需要自定义OnPaint()和ControlStyles.OptimizedDoubleBuffer
使其平滑
有人能告诉我在哪里/如何获得水平滚动位置,或者需要做些什么来自动实现这一点,比如当系统调用OnDrawItem时?我在这里找到了一个解决方案:
这是一种黑客行为,因为ListBox根本不公开滚动条周围的任何属性,但它可以工作。我使用了一个简化版本,直接从msg.WParam提取数据,而不调用任何外部dll函数。无论如何,OnPaint将在之后立即调用,因此没有理由担心发送额外的滚动事件
private int mHScroll;
protected override void WndProc(ref System.Windows.Forms.Message msg) {
if (msg.Msg == WM_HSCROLL) {
switch ((int)msg.WParam & 0xffff) {
case SB_PAGELEFT:
mHScroll = Math.Max(0, mHScroll - ClientSize.Width * 2 / 3); //A page is 2/3 the width.
break;
case SB_PAGERIGHT:
mHScroll = Math.Min(HorizontalExtent, mHScroll + ClientSize.Width * 2 / 3);
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
mHScroll = ((int)msg.WParam >> 16) & 0xffff;
break;
}
}
base.WndProc(ref msg);
}
这是一个内部工具,它适合我。已解决。为这些内置的本机Windows控件修补UserPaint是一项永不停止的黑客行为。现在还不清楚滚动条是如何工作的。这没有任何意义,取而代之的是从ListView派生,在构造函数中将View=List和DoubleBuffered设置为true。t滚动条没有问题。垂直方向根据项目数添加自身。当我将HorizontalExtent设置为比控件更宽时,水平添加了它自己。起初我查看的是ListView,但出于这个目的,它似乎完全是矫枉过正。我只需要一个固定大小的元素列表,带有滚动条和自定义绘图例程,所以我选择了ListBox。来吧-1关于这个问题:-(给我一些有用的信息,不要傲慢。@Hans:如果你不知道如何设置列表框的滚动条,你可能根本帮不上忙。ListView.View=List;在列中排列项目是完全没有用的!我有20k+行,长度从0到几kB不等。这个工具用于显示从大到大的日志文件自定义高光颜色。