发掘ListBox的潜力(一):自动调整横向滚动条宽度

2016-02-19 18:25 2 1 收藏

想要天天向上,就要懂得享受学习。图老师为大家推荐发掘ListBox的潜力(一):自动调整横向滚动条宽度,精彩的内容需要你们用心的阅读。还在等什么快点来看看吧!

【 tulaoshi.com - 编程语言 】

《自绘ListBox的两种效果》一文帖出之后,从反馈信息来看,大家对这种小技巧还是很认同。接下来我将继续围绕ListBox写一系列的文章,进一步发掘ListBox的潜力,其中包括:自动调整横向滚动条宽度、即时提示(Tips)、拖放插入点提示等,并在最后制作一个在滚动区内的ListBox组。
  

自动调整横向滚动条宽度

  网上可以找到很多让Listbox产生横向滚动条的文章,其中的方法基本一样,就是定义一个函数,遍历Items取得最大的TextWidth值,然后发Listbox发消息LB_SETHORIZONTALEXTENT产生横向滚动条。典型例子如下:
  procedure SetWidth(Sender: TObject);
  var
      i, w: Integer;
  begin
      w := 0;
      with ListBox1 do begin
          for i:=0 to Items.Count -1 do begin
              if Canvas.TextWidth(Items[i])  w then
                  w := Canvas.TextWidth(Items[i]);
          end;
          SendMessage(Handle, LB_SETHORIZONTALEXTENT, w+4, 0);
      end;
  end;
  以上代码的确可用而且被广泛使用,但它有一个很大的缺点:效率大低。因为每次在Listbox中追加、插入或删除一个条目时,都要调用此函数重新计算横向滚动条宽度,而遍历所有项目和调用TextWidth都是很是很耗时的操作。如果用户将条目从当前Listbox拖往另一个Listbox,那么用户一个操作将有两个Listbox必须重新计算横向滚动条宽度,当Listbox内容有上百条的时候,你将明显感觉反应迟缓。
  OK,现在换个思路。
  当追加或插入新条目时,只要判断新内容的TextWidth是否大于滚动条宽度,如果是调整滚动条宽度即可。那么删除呢?是的,遍历是不可避免的,但并不是每次删除都需要。可以定义一个变量记录Listbox中TextWidth值最大的条目Index,只有删除这个条目时才需要遍历,其它时候完全可以不管它。
  还有一种情况必须考虑,用户可能会改变屏幕字体,这时也必须重新计算横向滚动条宽度。跟删除操作一样计算原最大条目的新TextWidth值即可。
    如果窗体上有多个Listbox,记录每个Listbox的最大条目也是一件很麻烦的事,所以我把它封装起来,下面给出完整代码:
  

  unit kktListBox;

  {========================================================================
    DESIGN BY :  彭国辉
    DATE:        2004-12-24
    SITE:       
http://kacarton.yeah.net/
    BLOG:        http://blog.csdn.net/nhconch
    EMAIL:       kacarton#sohu.com

    文章为作者原创,转载前请先与本人联系,转载请注明文章出处、保留作者信息,谢谢支持!
  =========================================================================}
  

  interface

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  uses
    Windows, Messages, SysUtils, Classes, Controls, StdCtrls, Commctrl;

  type
    TkktListBox = class(TListBox)
    private
      MaxLenItemIndex: Integer;
      FScrollWidth: Integer;
      procedure LBAddString(var Message: TMessage); message LB_ADDSTRING;
      procedure LBInsertString(var Message: TMessage); message LB_INSERTSTRING;
      procedure LBDeleteString(var Message: TMessage); message LB_DELETESTRING;
      procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
      procedure AdjuctScrollWidth(Message: TMessage);
      procedure ResetScrollWidth;

    protected

    public
      constructor Create(AOwner: TComponent); override;

    end;

  procedure Register;

  implementation

  { TkktListBox }

  constructor TkktListBox.Create(AOwner: TComponent);
  begin
    inherited Create(AOwner);
    MaxLenItemIndex := -1;
    FScrollWidth := 0;
  end;

  procedure TkktListBox.LBAddString(var Message: TMessage);
  begin
    inherited;
    if Message.Result = LB_ERR then Exit;
    AdjuctScrollWidth(Message);
  end;

  procedure TkktListBox.LBInsertString(var Message: TMessage);
  begin
    inherited;
    if Message.Result = LB_ERR then Exit;
    AdjuctScrollWidth(Message);
  end;

  procedure TkktListBox.LBDeleteString(var Message: TMessage);
  begin
    inherited;
    if Message.Result = LB_ERR then Exit;
    if Message.WParam = MaxLenItemIndex then ResetScrollWidth;
  end;

  procedure TkktListBox.CMFontChanged(var Message: TMessage);
  var
    sz: SIZE;
  begin
    inherited;
    if MaxLenItemIndex = -1 then Exit;
    //这里没有使用TextWidth,而是用GetTextExtentPoint32函数,如果你有兴趣的话
    //可以跟踪一个TextWidth函数,它最终是调用GetTextExtentPoint32实现的

    GetTextExtentPoint32(Canvas.Handle, PChar(Items[MaxLenItemIndex]), Length(Items[MaxLenItemIndex]), sz);
    FScrollWidth := sz.cx + 4;
    Perform(LB_SETHORIZONTALEXTENT, FScrollWidth, 0);
  end;

  procedure TkktListBox.AdjuctScrollWidth(Message: TMessage);
  var
    sz: SIZE;
  begin
    GetTextExtentPoint32(Canvas.Handle, PChar(Message.LParam), StrLen(PChar(Message.LParam)), sz);
    if sz.cx + 4  FScrollWidth then begin
      FScrollWidth := sz.cx + 4;
      Perform(LB_SETHORIZONTALEXTENT, FScrollWidth, 0);
      MaxLenItemIndex := Message.Result;
    end;
  end;

  procedure TkktListBox.ResetScrollWidth;
  var
    i, MaxWidth: Integer;
    sz: SIZE;
  begin
    MaxWidth := 0;
    i := Items.Count - 1;
    MaxLenItemIndex := -1;
    while i=0 do begin
  
    sz.cx := 0;
      GetTextExtentPoint32(Canvas.Handle, PChar(Items[i]), Length(Items[i]), sz);
      if sz.cx + 4  MaxWidth then begin
  
      MaxWidth := sz.cx + 4;
        MaxLenItemIndex := i;
      end;
      Dec(i);
    end;
    FScrollWidth := MaxWidth;
    Perform(LB_SETHORIZONTALEXTENT, FScrollWidth, 0);
  end;

  procedure Register;
  begin
    RegisterComponents('Kacarton', [TkktListBox]);
  end;

  end.

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

来源:https://www.tulaoshi.com/n/20160219/1617635.html

延伸阅读
标签: windows10
如何在win10系统中对窗口标题栏和滚动条宽度进行调整?   在操作Windows系统的时候,咱们都需要打开其中的文件夹窗口,例如咱们查找一个文件夹或者是打开一个程序的时候,都需要涉及到这个操作,想必很多用户都觉得,咱们Windows系统窗口标题栏和滚动条的宽度都是固定的,也从来没有想到对这个进行调整。但是实际上并不是,咱们是可以...
标签: Web开发
到现在为止,初始化这些MooTools插件对象就会开始变得越来越熟悉。滚动条(Slider)没有任何不同,你要创建一个新的滚动条,定义滚动条和滑块相关的元素,然后设置你的选项,再创建一些回调事件的控制函数。尽管滚动条(Slider)遵循这个熟悉的模式,但是任然还有一点特殊的地方。 基本用法创建一个新的滚动条(Slider)对象 我们首先从HTML...
标签: Web开发
代码如下: //调用函数 var pagestyle = function() { var rframe = $("#mainFrame"); //ie7默认情况下会有上下滚动条,去掉上下15像素 var h = $(window).height() - rframe.offset().top - 15; rframe.height(h); } //注册加载事件 $("#mainFrame").load(pagestyle); //注册窗体改变大小事件 $(window).resize(pagestyle);
很多开发者在做Android UI时不知道如何设置ScrollView滚动条控件的滑块颜色,其实通过ScrollView的xml布局属性android:scrollbarThumbVertical可以关联一个drawable对象,比如说在ScrollView中我们有 android:scrollbars="vertical" //滚动条是垂直的 android:scrollbarThumbVertical="@drawable/red" //垂直滚动条颜色为red,red可以是一个png...
标签: Web开发
记录滚动条位置 dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd...

经验教程

153

收藏

8
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部