ListView에서 Row별로  힌트를 다르게 주려고 한다면

MouseMove 이벤트에 처리해야 하는것은 맞습니다.


1. 먼저 OnMouseMove이벤트에서 현재 마우스 위치에 Row 즉 ListItem을 알아야 겠죠?

    그것은 ListView에 GetItemAt 이라는 함수가 있습니다.
 
   procedure TForm3.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
   var
      item: TListItem;
    begin
       item:=ListView1.GetItemAt(X,Y);
       ....
   end;

   문론 GetItemAt으로 item을 구했는데 nil 인경우도 있습니다. 
   이럴경우도 처리해야죠

2. Mouse위치의 Item을 알았으니 ListView의 Hint를 바꿔줘야 겠죠
    다음과 같이 마우스 위치의 ListItem을 구해서 ListView의 Hint를 바꿔줄수 있습니다.
 

procedure TForm3.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  item: TListItem;
begin
  item:=ListView1.GetItemAt(X,Y);

  if Assigned(item)then
  begin
      ListView1.Tag:= item.Index ;
      ListView1.Hint:='ListView Items= '+item.Caption;
  end
......
end;
 

     그런데 Hint를 바꾼다고 해서 바로 변경된 Hint가 보여지는것이 아니죠

3.  Hint를 보여주고/ 말고 하는것은 Application객체가 담당합니다.
     
     대게 Hint가 보여지는것은 마우스위치에 있는 Control이 바뀌었을때 해당Control의 힌트를 보여주죠

      그런데 listview에서 mouse만을 움직였을때는 item만 바뀌지 control을 여전히 같은 listview이기때문에
      hint가 보여지지 않는것입니다.


4. 즉각적으로 Hint를 다시 보여주려면 Application의 Hint관련 함수를 이용하면 됩니다.
 
    // 현재 떠있는 힌트를 닫습니다.
    Application.CancelHint;    
   
    // 넘겨준 TPoint위치에 hint를 보여줍니다.
   Application.ActivateHint( point );

5. 결론적으로 listveiw의 hint를 바꾼뒤에
     위 Application 의 CancelHint  , ActivateHint 를 한번씩 호출해주면 됩니다.
 

procedure TForm3.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  item: TListItem;
begin
  item:=ListView1.GetItemAt(X,Y);

  if Assigned(item)then
  begin
      ListView1.Hint:='ListView Items= '+item.Caption;
      Application.CancelHint;
      Application.ActivateHint(Mouse.CursorPos);
  end;
end;
 

6. 그러데 MouseMove 이벤트가 같은 item위치에서 여러번 발생할수있죠
    마우스위치의 item이 바뀌지 않았는데 반복해서 CancelHint , ActivateHint 를 띄우면
    좀 이상하겠쬬

    그러니 현재 hint로 띄운 item을 기억하고 있을 필요가 있을것입니다.
    
   즉 item이 변경되면 hint를 새로 띄우는것이 아니라
    hint가 변경되면 hint를 새로띄우는것이죠

procedure TForm3.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  item: TListItem;
begin
  item:=ListView1.GetItemAt(X,Y);

  if Assigned(item)then
  begin
    if(item.Index <>ListView1.Tag ) then
    begin
      //item의 index를 ListView.Tag에 기억해두고 tag가 같지 않는경우에만 ...
      ListView1.Tag:= item.Index ; 
      ListView1.Hint:='ListView Items= '+item.Caption;
      Application.CancelHint;
      Application.ActivateHint(Mouse.CursorPos);
    end;
  end;

end;   

     뭐 대충 이런식으로 하면 됩니다.

     이 방식으로 listview뿐만 아니라 VCL의 모든 Control에 적용할수 있습니다.
     마우스 위치의 control이 변경되지 않았는데
     hint를 바꾸고 싶을경우에는 

     1)  먼저 hint를 바꾼후에 
     2)  Application.CancelHint;
     3)  Application.ActivateHint(Mouse.CursorPos);
       해주면 됩니다.
     
6. 마지막으로  Application 객체에는 hint관련해서 프로퍼티와 함수가 몇가지 더 있습니다.

      Application.Hint;
      Application.HintColor:=clRed;  //힌트 보여지는 Color
      Application.HintPause; //Control위에 마우스가 들어간뒤에 Hint가 보여지기까지 delay
      Application.HintHidePause; //hint가 나타난후에 사라지기까지 시간
      Application.HintShortCuts;
      Application.HintShortPause;

7.  hint를 좀더 발전된 형태로 보여주고 싶다면

     THintWindow 를 상속받아서 hint 클래스를 새로만드시구요   
     TMyHintWindow = class(THintwindow) 
   
     다음과 같이 HintWindowClass 에 설정해주시면 
     HintWindowClass := TMyHintWindow 
     Application객체가 HintWindowClass 에 등록된 class를 생성해서 보여줍니다.

+ Recent posts