国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

發掘ListBox的潛力(一):自動調整橫向滾動條寬度

2019-11-18 18:06:09
字體:
來源:轉載
供稿:網友
自繪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

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.


上一篇:如何使程序在運行時自動注冊ActiveX控件

下一篇:CRC算法的實現

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 博罗县| 潞西市| 昆明市| 分宜县| 成武县| 尼勒克县| 东阿县| 阿瓦提县| 苍梧县| 永定县| 延川县| 交口县| 柘城县| 大荔县| 德安县| 伊春市| 和田县| 永吉县| 郁南县| 渝中区| 布尔津县| 威宁| 通山县| 蒲城县| 且末县| 聂拉木县| 梁平县| 武宁县| 罗定市| 班戈县| 常熟市| 迭部县| 陕西省| 太仓市| 耿马| 临武县| 章丘市| 铁力市| 崇仁县| 微博| 彰武县|