发掘ListBox的潜力(三):显示即时提示(Tips)

ListBox显示即时提示(Tips)

  Listbox内容太长时超出Listbox宽度的部分将无法显示,一种解决方法是让Listbox产生横向滚动条,滚动显示内容(见前面的《发掘ListBox的潜力(一):自动调整横向滚动条宽度 》),另一种方法是让Listbox以Tips的方法显示完整内容。本文要实现的是后一种方式。

  Tips其实是一个特殊的窗体,类名为:tooltips_class32(在Commctrl(D6)有定义),可使用CreateWindow函数创建;Windows定义了一组以TTM_开头的消息用来与之通信,比如设置显示内容使用TTM_SETTITLE、删除显示内容使用TTM_DELTOOL。下面是例子:

hWndTip := CreateWindow(TOOLTIPS_CLASS, 'kktListBoxToolTips',
    WS_POPUP or TTS_NOPREFIX or TTS_ALWAYSTIP, 0, 0, 0, 0, hWndTip, 0, HInstance, nil);
SendMessage(hWndTip, TTM_ADDTOOL, 0, Integer(@ti));
SendMessage(hWndTip, TTM_DELTOOL, 0, Integer(@ti));
Tips有两种显示时机:鼠标指向某ListItem时和鼠标点击某ListItem时,这里提供了一个选项供用户,默认为鼠标点击ListItem时显示,因此在type作如下声明:
TToolTipShowEvent = (tsMouseOver, tsClick);
并在控件published处声明ShowToolTipWhen属性:
property ShowToolTipWhen: TToolTipShowEvent read FShowToolTipWhen write SetShowToolTipWhen default tsClick;
接下来处理WM_LBUTTONDOWN消息判断是否应该显示内容,及处理要显示的内容:
procedure TkktListBox.WMMouseLBDown(var Message: TMessage);
var
 
X, Y, i: integer;
begin
  inherited;
  if (FShowToolTipWhen = tsMouseOver) then Exit;
  X := LOWORD(Message.lParam);
  Y := HIWORD(Message.lParam);
  i := ItemAtPos(Point(X, Y), true); //ItemIndex
  if (i = -1) and (TipsIndex <> -1) then HideToolTip;
  if i<>-1 then ShowToolTip(X, Y, i);
end;
对WM_MOUSEMOVE的处理方式类似:
procedure TkktListBox.WMMouseMove(var Message: TMessage);
var
  X, Y, i: integer;
begin
  if (FShowToolTipWhen = tsClick) then Exit;
  X := LOWORD(Message.lParam);
  Y := HIWORD(Message.lParam);
  i := ItemAtPos(Point(X, Y), true);
  if (i = -1) and (TipsIndex <> -1) then HideToolTip;
  if i<>-1 then ShowToolTip(X, Y, i);
  inherited;
end;
Tips的消隐则在CM_MOUSELEAVE消息里处理:
procedure TkktListBox.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  HideToolTip;
end;
下面给出TkktListBox的完整代码:
unit kktListBox;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls, Commctrl;

const TTM_SETTITLE = (WM_USER + 32);

type
TGetHintTextEvent = procedure(Index: integer; var HintText: string; Sender: TObject) of object;
TToolTipShowEvent = (tsMouseOver, tsClick);



TkktListBox = class(TListBox) private
hWndTip: THandle;
ti: TOOLINFO; TipsIndex: integer; FOnGetHintText: TGetHintTextEvent; FHintTitle: String; FShowToolTipWhen: TToolTipShowEvent;
文章来自编程手札http://blog.csdn.net/nhocnch,您现在所见为非法转载!
procedure SetHintText(Index: integer); procedure SetHintTitle(const Value: String); procedure SetShowToolTipWhen(const Value: TToolTipShowEvent); protected property ScrollWidth stored False;
public
constructor Create(AOwner: TComponent); override; procedure CreateWnd; override; destructor Destroy; override; published property HintTitle: String read FHintTitle write SetHintTitle; property ShowToolTipWhen: TToolTipShowEvent read FShowToolTipWhen write SetShowToolTipWhen default tsClick; property OnGetHintText: TGetHintTextEvent Read FOnGetHintText write FOnGetHintText; end;
procedure Register;
implementation { TkktListBox }
procedure TkktListBox.CMMouseLeave(var Message: TMessage); begin inherited; HideToolTip; end; constructor TkktListBox.Create(AOwner: TComponent); begin inherited Create(AOwner); TipsIndex := -1; FShowToolTipWhen := tsClick; end; 文章来自编程手札http://blog.csdn.net/nhconch,您现在所见为非法转载!!
//uId := Handle;
hinst := hInstance; lpszText := nil;
//LPSTR_TEXTCALLBACK;
//CALLBACK将导致回调次数太多
Rect.Left := 0; Rect.Top := 0; Rect.Bottom := 0; Rect.Right := 0; end; sendMessage(hWndTip, WM_SETFONT, Self.Font.Handle, Integer(LongBool(False))); SendMessage(hWndTip, TTM_ADDTOOL, 0, Integer(@ti)); SendMessage(hWndTip, TTM_SETTITLE, 0, Integer(Pchar(FHintTitle))); end; destructor TkktListBox.Destroy; begin if hWndTip<>0 then SendMessage(hWndTip, WM_CLOSE, 0, 0); inherited; end; procedure TkktListBox.HideToolTip; begin TipsIndex := -1; SendMessage(hWndTip, TTM_TRACKACTIVATE, 0, 0); end; procedure TkktListBox.ShowToolTip(X, Y, Index: integer); var APoint: TPoint; ARect: TRect; begin if (FShowToolTipWhen = tsClick) and (Index = TipsIndex) then Exit; if FShowToolTipWhen = tsMouseOver then begin APoint := Point(X+20, Y+20); end else begin //FShowToolTipWhen = tsClick ARect := ItemRect(Index); APoint := ARect.TopLeft; end; APoint := Self.ClientToScreen(APoint); SendMessage(hWndTip, TTM_TRACKPOSITION, 0, MAKELPARAM(APoint.X, APoint.Y)); if Index = TipsIndex then Exit; SetHintText(Index); SendMessage(hWndTip, TTM_TRACKACTIVATE, 1, integer(@ti)); TipsIndex := Index; end; procedure TkktListBox.WMMouseLBDown(var Message: TMessage); var X, Y, i: integer; begin inherited; if (csDesigning in ComponentState) or (FShowToolTipWhen = tsMouseOver) then Exit; X := LOWORD(Message.lParam); Y := HIWORD(Message.lParam); i := ItemAtPos(Point(X, Y), true); //ItemIndex if (i = -1) and (TipsIndex <> -1) then HideToolTip; if i<>-1 then ShowToolTip(X, Y, i); end; procedure TkktListBox.WMMouseMove(var Message: TMessage); var X, Y, i: integer; begin if (csDesigning in ComponentState) or (FShowToolTipWhen = tsClick) then Exit; X := LOWORD(Message.lParam); Y := HIWORD(Message.lParam); i := ItemAtPos(Point(X, Y), true); if (i = -1) and (TipsIndex <> -1) then HideToolTip; if i<>-1 then ShowToolTip(X, Y, i); inherited; end; procedure TkktListBox.SetHintTitle(const Value: String); begin if FHintTitle = Value then Exit; FHintTitle := Value; SendMessage(hWndTip, TTM_SETTITLE, 0, Integer(Pchar(FHintTitle))); end; procedure TkktListBox.SetHintText(Index: integer); var HintText: string; begin if Index<0 then Exit; SendMessage(hWndTip, TTM_DELTOOL, 0, Integer(@ti)); HideToolTip; HintText := Items[Index]; if Assigned(FOnGetHintText) then FOnGetHintText(Index, HintText, Self); ti.lpszText := @HintText[1]; SendMessage(hWndTip, TTM_ADDTOOL, 0, Integer(@ti)); end; procedure TkktListBox.SetShowToolTipWhen(const Value: TToolTipShowEvent); begin if FShowToolTipWhen <> Value then begin FShowToolTipWhen := Value; HideToolTip; end; end; procedure Register; begin RegisterComponents('Kacarton', [TkktListBox]); end; end.

 

 

<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值