Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: ListBox и Hint  (Прочитано 6892 раз)
0 Пользователей и 1 Гость смотрят эту тему.
artsb
Гость
« : 04-12-2007 17:55 » 


С помощью такого кода можно выводить подсказки для соответствующих строк:

void __fastcall TForm1::ListBox1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
static int OldIndex = -1;
int Index = ListBox1->ItemAtPos(Point(X, Y), true);
if((Index > -1) && (Index != OldIndex))
{
ListBox1->Hint = ListBox1->Items->Strings[Index];
Application->ActivateHint(Mouse->CursorPos);
}
else{ ListBox1->Hint ="";
}
OldIndex = Index;
}

Но, минус в том, что подсказка вылетает даже в том случае если название строки состоит из одного символа, что естественно неудобно и некрасиво. Темболее, она вылетает где попало.

Хотелось бы узнать как определить длину строки с индексом i в пикселах, чтобы потом сравнить с шириной ListBox'а?
И как можно вывести подсказку в определённой позиции, т.е. чтобы левый край подсказки был равен левому краю ListBox'а, а верхний край - Верхнему краю строки, на которую наведён курсор.
Спасибо.
Записан
RXL
Технический
Администратор

ru
Online Online
Пол: Мужской

WWW
« Ответ #1 : 05-12-2007 07:45 » 

artsb, управление хинтами в BC ограничено только тем, что их можно разрешать/запрещать и менять текст. В "продвинутых" компонентах TMS я нашел еще управление цветом фона, но больше ничего нет. Хинт выскакивает в позиции мыши и подвинуть его штатными средствами нельзя. Попробуй средствами Win32 API получить HWND окна под курсором в момент появления хинта (как его еще определить то?...) и передвинуть прямым посылом в него сообщений. В общем... не знаю, чем помочь. Разве что запретить штатный хинт и реализовать свой.

Размер отрендеренной строки можно понять несколькими способами. Самое простое - эту строку отрендерить и измерить Ага Напр., создай TLabel с параметрами шрифта, аналогичными компоненту с измеряемой строкой, включи autosize, скопируй в него текст и померь длину компонента.
« Последнее редактирование: 05-12-2007 07:49 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Команда клуба

by
Offline Offline
Пол: Мужской

« Ответ #2 : 05-12-2007 09:07 » 

Код на Delphi, переведешь сам.
Порядок действий:
1 Создаешь свой класс наследник класса THintWindow:
Код:
THintWindow1 = class(THintWindow)
  public
   procedure ActivateHint(Rect: TRect; const AHint: string); override;
  end;

procedure THintWindow1.ActivateHint(Rect: TRect; const AHint: string);
begin
  //какой то код определяющий положение подсказки и записывающий его в Rect
  inherited ActivateHint(Rect, AHint);
end;
2. Создаешь свой класс наследник TCustomListBox, в котором перехватываешь события CM_MOUSEENTER (заход мыши в листбокс) и CM_MOUSELEAVE (выход мыши из листбокс). В которых снимаешь-устанавливаешь флаг, нужный для обработки события WM_MOUSEMOVE.
3. В обработчике события WM_MOUSEMOVE определяешь Items по позиции курсора (если флаг установлен). Затем определяешь ширину текста:
Код:
ListBox1.Canvas.Font:=ListBox1.Font;
 If ListBox1.Canvas.TextWidth(ListBox1.Items.Strings[i])>ListBox1.ClientWidth then
 begin
  //Код прописывающий в глобальную переменную Rect подсказки,
  //которая передается в процедуру THintWindow1.ActivateHint
  Application.ShowHint:=False;
  OldHintWindow:=HintWindowClass;//запоминаем родной хинт-класс, здесь HintWindowClass - глобальная переменная Delphi, думаю в балдере она тоже есть
  HintWindowClass:=THintWindow1;//устанавливаем свой класс хинта
  Application.ShowHint:=True;
  Application.CancelHint;
  ListBox1.Hint:=ListBox1.Items.Strings[i];
 end;
4. При выходе из листбокса (событие CM_MOUSELEAVE) востанавливаем родной хинт-класс:
Код:
  Application.ShowHint:=False;
  HintWindowClass:=OldHintWindow;//восстанавливаем родной хинт-класс
  Application.ShowHint:=True;


« Последнее редактирование: 05-12-2007 09:14 от zubr » Записан
artsb
Гость
« Ответ #3 : 05-12-2007 19:41 » 

А я уже сделал, спасибо. Вот пользуйтесь. Всё работает.
В этом примере на Form1 только ListBox1.

Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
void __fastcall TForm1::NewHintProc(System::AnsiString &HintStr,
                                   bool &CanShow,
                                   THintInfo &HintInfo)
{
TPoint Pos;
if (HintInfo.HintControl==ListBox1)
 {
  Pos.x = 0;
  Pos.y = ListBox1->Tag;
  HintInfo.HintPos = ListBox1->ClientToScreen(Pos);
  HintInfo.HintStr = ListBox1->Hint;
 }
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  FHintRow = -1;
  Application->OnShowHint = NewHintProc;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
TRect ItemPos;
int   ItemNum;
AnsiString   FHint;
TPoint MousePos;   
MousePos.x = X;
MousePos.y= Y;
ItemNum = ListBox1->ItemAtPos(MousePos, True);
if (ItemNum != FHintRow)   
{
  FHintRow = ItemNum;
  if (ItemNum !=-1 && ListBox1->Canvas->TextWidth(ListBox1->Items->Strings[ItemNum]) >= ListBox1->ClientWidth) 
   {
      ItemPos = ListBox1->ItemRect(ItemNum);
      ListBox1->Tag = ItemPos.top;
      FHint = ListBox1->Items->Strings[ItemNum];
      ListBox1->Hint = FHint;
      Application->CancelHint();
    }
  else
    {
      ListBox1->Hint = "";
      ListBox1->Tag = -1;
      Application->CancelHint();
    }
}
}
//---------------------------------------------------------------------------
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 06-12-2007 04:40 » 

artsb, молодец Улыбаюсь









возьми с полки пирожок Улыбаюсь
Записан

artsb
Гость
« Ответ #5 : 06-12-2007 08:14 » 

Пожалуйста.

Кстати, в классе TForm1 незабываем прописать новый метод:
Код:
class TForm1 : public TForm
{
  __published:
  ...
  private:
  public: 
    int FHintRow;
    __fastcall TForm1(TComponent* Owner);
    void __fastcall NewHintProc(System::AnsiString &HintStr, bool &CanShow, THintInfo &HintInfo);
};
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines