Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Tooltip в Listview (Items+Subitems+FullRowSelect) / 8 сообщений из 8, страница 1 из 1
15.10.2013, 23:11
    #38428900
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Listview -Report (details)
Задача: если какой-то subitem не виден полностью, надо отобразить его в Tooltip при наведении мыши.

В VB6 использовал следующий код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
Private Sub ListView1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
  On Error Resume Next 'попытка предотвратить crash когда белое поле
   
  Dim lItemIndex As Long
  Dim lSubItemIndex As Long
  Dim lvhti As LVHITTESTINFO
   
  lvhti.pt.x = x / Screen.TwipsPerPixelX
  lvhti.pt.y = y / Screen.TwipsPerPixelY
  Call SendMessage(ListView1.hwnd, LVM_SUBITEMHITTEST, 0, lvhti)
  lItemIndex = lvhti.iItem + 1
  lSubItemIndex = lvhti.iSubItem
   
  If (m_lCurItemIndex <> lItemIndex) Or (m_lCurSubItemIndex <> lSubItemIndex) Then
    m_lCurItemIndex = lItemIndex
    m_lCurSubItemIndex = lSubItemIndex
    If (m_lCurItemIndex = 0) Or (m_lCurSubItemIndex = 0) Then   ' no item(subitem) under the mouse pointer
      TT.Destroy
    Else
      If (ListView1.ColumnHeaders(m_lCurSubItemIndex + 1).Width - 170) < _
       TextWidth(ListView1.ListItems(m_lCurItemIndex).SubItems(m_lCurSubItemIndex)) Then
        TT.TipText = ListView1.ListItems(m_lCurItemIndex).SubItems(m_lCurSubItemIndex) 'm_lCurItemIndex & "/" & m_lCurSubItemIndex
        TT.Create ListView1.hwnd
      Else
        TT.Destroy
      End If
    End If
  End If
End Sub

В качестве ToolTip использовал класс CToolTip API-based
Код: vbnet
1.
2.
3.
4.
5.
   m_lTTHwnd = CreateWindowEx(0&, _
      TOOLTIPS_CLASSA, _
      vbNullString, _
      lWinStyle, _
      CW_USEDEFAULT, _

и т.д.
Все это в общем достойно работает, скажем так с некоторой погрешностью оценки TextWidth(ListView1.ListItems...)

Сейчас пытаюсь понять что я могу сделать в .NET
Кинул на форму Tooltip1 (.Net)
Оценкой ширины текста пока не занимался, но рабочий код пока такой (повторяет ту же идею):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
  Private Sub ListView1_MouseMove(ByVal sender As Object,
   ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseMove
    'Debug.Print(e.X.ToString & "," & e.Y.ToString)

    Dim lvhti As New LVHITTESTINFO
    lvhti.pt.x = e.X
    lvhti.pt.y = e.Y
    Call SendMessage_LVHITTESTINFO(ListView1.Handle, LVM_SUBITEMHITTEST, 0, lvhti)
    Dim lItemIndex As Integer = lvhti.iItem
    Dim lSubItemIndex As Integer = lvhti.iSubItem
    'Dim info As ListViewHitTestInfo = ListView1.HitTest(ListView1.PointToClient(Cursor.Position))
    'If (IsNothing(info.Item) = False And IsNothing(info.SubItem) = False) Then
    '  Debug.Print("NET: " & info.Item.Index.ToString & "," & info.SubItem.Text)
    'End If
    If (m_lCurItemIndex <> lItemIndex) Or (m_lCurSubItemIndex <> lSubItemIndex) Then
      m_lCurItemIndex = lItemIndex
      m_lCurSubItemIndex = lSubItemIndex
      Debug.Print(lItemIndex.ToString & "," & lSubItemIndex.ToString)
      If (m_lCurItemIndex = -1) Or (m_lCurSubItemIndex = -1) Then 'no item(subitem) under the mouse pointer
        'ToolTip1.SetToolTip(ListView1, "")
      Else
        'ToolTip1.SetToolTip(ListView1, ListView1.Items(m_lCurItemIndex).SubItems(m_lCurSubItemIndex).Text)
        Debug.Print("ListView1.Items(m_lCurItemIndex).SubItems(m_lCurSubItemIndex).Text")
        ToolTip1.Show(ListView1.Items(m_lCurItemIndex).SubItems(m_lCurSubItemIndex).Text, ListView1)
      End If
    End If

  End Sub

  Private Sub ListView1_MouseLeave(ByVal sender As Object,
                                   ByVal e As System.EventArgs) Handles ListView1.MouseLeave
    m_lCurItemIndex = -1
    m_lCurSubItemIndex = -1
    Debug.Print("-1,-1")
  End Sub



Оно то в целом работает но вижу букет глюков.
1. ToolTip1.Show (или ToolTip1.SetToolTip) приводят к мгновенному появлению тултипа
(несистемное поведение)
Причем таймер InitialDelay (в конструкторе) при непосредственном вызове этих ф-ций похоже бесполезен -проверил.
А в указанных ф-ция варианты с параметром InitialDelay отсутствуют
Как лечить?

2. Место появления Tooltip нестандартно (стандартно -это когда нижний левый край курсора) и зависит от того с какой скоростью и в каком направлении елозить.
Это скорее всего можно выправить, так как координаты есть, размер курсора оценивается и соотв. параметры в вариантах вызова ф-ций присутствуют.

3. Когда Tooltip отображается, невозможно с ходу воткнуться мышью в строчку (чтоб ее выделить) - как бы стеклянная стена - это не порядок.
Как лечить ?

4. Пожалуй самый неприятный и заставляет задуматься.
1) Tooltip отображается
2) Ждем пока он не самоудалится по таймеру (duration)
3) Закрываем главную форму
4) Получаем "краш" в ф-ции сабклассинга основной формы Form1 с ListView1
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
...
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)

  End Sub

InvalidOperationException
Попытка доступа к элементу управления 'ListView1' не из того потока в кот. он был создан
Сообщение m = WM_CLOSE
.
Судя по вчерашнему опыту эта штука как-то умудрилась наклепать копий ListView1.

Что не так делаю? Не, я понимаю что я вчера окном htmlHelp возился - это сложно, там хитрый сабклассинг.
Но здесь вроде как ничего жуткого нет.
Form1, Listview1, Tooltip1 -все "родное", API можно не использовать.

Хотя... пока писал, проверил, кажется понял в каком месте он создал клона:
Код: vbnet
1.
ToolTip1.Show(ListView1.Items(m_lCurItemIndex).SubItems(m_lCurSubItemIndex).Text, ListView1) 


window
Type: System.Windows.Forms.IWin32Window
The Control to display the ToolTip for.
и
System.Windows.Forms.Control -не совсем одно и то же

Если заменить на
Код: vbnet
1.
ToolTip1.SetToolTip(ListView1, ListView1.Items(m


то
глюк 3. "глюк стеклянной стены" -исчезает
глюк 4. краш сабклассинга - исчезает
===
Вообще нужен (и должен быть) какой-то более системный подход к решению вопроса.
MouseMove -как не крути - в каком-то смысле "самопалка".

Я очень подозреваю что LVS_EX_INFOTIP + LVN_GETINFOTIP notification code :
LVS_EX_INFOTIPVersion 4.71. When a list-view control uses the LVS_EX_INFOTIP style, the LVN_GETINFOTIP notification code is sent to the parent window before displaying an item's tooltip.
Хотя несколько смущают подчеркнутые слова:
LVN_GETINFOTIPSent by a large icon view list-view control that has the LVS_EX_INFOTIP extended style. This notification code is sent when the list-view control is requesting additional text information to be displayed in a tooltip. It is sent in the form of a WM_NOTIFY message.
Remarks
This notification code is only sent by list-view controls that have the LVS_EX_INFOTIP extended style. The LVN_GETINFOTIP notification code is sent only for subitem 0 .
Но где-то промелькнуло пока искал решение, что для FullRowSelect якобы и для subitems тоже работает.
Не то? Или близко?
И если да, есть ли в .Net что либо встроенное на эту тему?

Еще обратил внимание на св-во (.NET) ShowItemsTooltips
но там похоже имеется ввиду добавление независимого текста-описания,
мне же надо отображать "родной текст" и только если не вписывается в ширину столбца.

Есть идеи, опыт, соображения?
...
Рейтинг: 0 / 0
16.10.2013, 04:56
    #38429065
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Дмитрий77Вообще нужен (и должен быть) какой-то более системный подход к решению вопроса.
MouseMove -как не крути - в каком-то смысле "самопалка".

Я очень подозреваю что LVS_EX_INFOTIP + LVN_GETINFOTIP notification code :
LVS_EX_INFOTIPVersion 4.71. When a list-view control uses the LVS_EX_INFOTIP style, the LVN_GETINFOTIP notification code is sent to the parent window before displaying an item's tooltip.Еще обратил внимание на св-во (.NET) ShowItemsTooltips
Это оно и есть.
Работает на Вистах, 7-ках и 8-ках. LVN_GETINFOTIP не генерируется. Если строка не вписывается, то автоматом генерируетя системный Tooltip (работает и для итемов, и для сабитемов). "Самопалка" не нужна. Решение в одну строчку кода:
Код: vbnet
1.
2.
3.
    If sys_WinVista Then ListView1.ShowItemToolTips = True '==Or LVS_EX_INFOTIP
    '!!!но если через ShowItemToolTips,
    ' то это надо делать ДО установки остальных стилей через API либо в конструкторе.



А вот на XP такая автоматика отсутствует. Вместо этого генерируется LVN_GETINFOTIP, причем DWORD dwFlags
в структуре NMLVGETINFOTIP structure даже указывает на то, не обрезается ли текст итема. Но беда в другом
iSubItemType: int
One-based index of the subitem to which this structure refers. If this member is zero, the structure is referring to the item and not a subitem.
This member is not currently used and will always be zero . И даже не в этом (subitem можно добыть через HitTest). А в том что этот Msg генерируется только при смене итема, а не сабитема (при движении вдоль строки итема при смене subitem-а не генерируется).
Посему для XP нужна "самопалка".

Дмитрий771. ToolTip1.Show (или ToolTip1.SetToolTip) приводят к мгновенному появлению тултипа
(несистемное поведение)
Причем таймер InitialDelay (в конструкторе) при непосредственном вызове этих ф-ций похоже бесполезен -проверил.
А в указанных ф-ция варианты с параметром InitialDelay отсутствуют
Как лечить?

2. Место появления Tooltip нестандартно (стандартно -это когда нижний левый край курсора) и зависит от того с какой скоростью и в каком направлении елозить.
Это скорее всего можно выправить, так как координаты есть, размер курсора оценивается и соотв. параметры в вариантах вызова ф-ций присутствуют.
Чтоб срабатывала задержка (согласно конструктора тултипа)
надо его сначала очистить, а потом обновить с текстом.
Код: vbnet
1.
2.
        ToolTip1.SetToolTip(CType(sender, Control), "")
        ToolTip1.SetToolTip(CType(sender, Control), lSubItem.Text)


И все путем. Причем вопрос с "координатами" также при этом решается ибо за стандартные 500мс задержки тултип успевает "сообразить" где вылазить.

Код для XP вроде такой оптимален (без API):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
  Dim m_lCurItem As ListViewItem 'тек.строка в ListView1
  Dim m_lCurSubItem As ListViewItem.ListViewSubItem 'тек.столбец в ListView1

  Private Sub ListView1_MouseMove(ByVal sender As Object,
   ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseMove

    If sys_WinVista Then Exit Sub 'эти махинации нужны только для XP

    Dim info As ListViewHitTestInfo = _
     CType(sender, ListView).HitTest(CType(sender, ListView).PointToClient(Cursor.Position))
    Dim lItem As ListViewItem = info.Item
    Dim lSubItem As ListViewItem.ListViewSubItem = info.SubItem

    If ReferenceEquals(m_lCurItem, lItem) = False Or _
     ReferenceEquals(m_lCurSubItem, lSubItem) = False Then
      m_lCurItem = lItem
      m_lCurSubItem = lSubItem
      If IsNothing(lItem) Or IsNothing(lSubItem) Then 'no item(subitem) under the mouse pointer
        'Debug.Print("Nothing")
      Else
        'Debug.Print(lItem.Index.ToString & "," & lSubItem.Text)
        ToolTip1.SetToolTip(CType(sender, Control), "")
        Dim g As Graphics = CreateGraphics()
        If g.MeasureString(lSubItem.Text, lSubItem.Font).Width > lSubItem.Bounds.Width Then _
          ToolTip1.SetToolTip(CType(sender, Control), lSubItem.Text)
      End If
    End If
End Sub

  Private Sub ListView1_MouseLeave(ByVal sender As Object,
                                   ByVal e As System.EventArgs) Handles ListView1.MouseLeave

    If sys_WinVista Then Exit Sub 'эти махинации нужны только для XP
    m_lCurItem = Nothing
    m_lCurSubItem = Nothing
End Sub



Но вот эта проблема в дебагере не решается и периодически может вылазить, хотя в exe пофиг:
Дмитрий4. Пожалуй самый неприятный и заставляет задуматься.
1) Tooltip отображается
2) Ждем пока он не самоудалится по таймеру (duration)
3) Закрываем главную форму
4) Получаем "краш" в ф-ции сабклассинга основной формы Form1 с ListView1
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
...
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)

  End Sub

InvalidOperationException
Попытка доступа к элементу управления 'ListView1' не из того потока в кот. он был создан
Сообщение m = WM_CLOSE
.

Windows Forms приложения аварийно завершает работу при вызова ToolTip.SetToolTip метода для элемента управления TreeView
Для временного решения проблемы....
2. Кроме того можно удалить вызов метода SetToolTip всплывающей подсказки элемента управления и использовать встроенные подсказки элемента управления TreeView. Для этого вам необходимо убедитесь, что свойство ShowNodeToolTips элемента управления TreeView присвоено значение True, и необходимо установить свойство ToolTipText каждого TreeNode нужное значение.
Сдается мне, с подобными "временными проблемами" проще для Tooltip API-класс из VB6 перекатать.
...
Рейтинг: 0 / 0
16.10.2013, 14:52
    #38429751
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Дмитрий77Но вот эта проблема в дебагере не решается и периодически может вылазить, хотя в exe пофиг:
Дмитрий4. Пожалуй самый неприятный и заставляет задуматься.
1) Tooltip отображается
2) Ждем пока он не самоудалится по таймеру (duration)
3) Закрываем главную форму
4) Получаем "краш" в ф-ции сабклассинга основной формы Form1 с ListView1
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
...
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)

  End Sub

InvalidOperationException
Попытка доступа к элементу управления 'ListView1' не из того потока в кот. он был создан
Сообщение m = WM_CLOSE
.
C API-шным Tooltip тоже самое.
как то связано с назначением Listview1 в качестве родителя для Tooltip
Но при этом возникает не всегда, а например при закрытии по Alt+F4 при отображаемом тултипе.
Если сначала сдвинуть мышку (тултип убирается не по таймеру), а потом закрыть приложение, то не возникает.
Куда копать?
...
Рейтинг: 0 / 0
16.10.2013, 20:07
    #38430322
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Сабклассинг ни причем. Если его вообще убрать, то все равно вылетит. Он лишь помог увидеть WM_CLOSE в дебагере.
Однако воспроизвести на совсем чистом проекте почему-то не смог.
Вылет происходит при наличии текста + привязки к ListView в Tooltip на момент закрытия Form1.
В случае когда тултип закрывается сам, либо когда делаем Alt+F4, команда
Код: vbnet
1.
ToolTip1.SetToolTip(CType(sender, Control), "")


не выполняется и не вижу способа отследить все эти ситуации
Т.е.
Код: vbnet
1.
ToolTip1.GetToolTip(ListView1)

вернет ненулевой текст.
(причем на этапе закрытия формы устанавливать текст в vbNullString уже бесполезно).

Предположительно при закрытии формы и при уничтожении Tooltip он пытается обратиться к ListView1.

Остается один вариант: тупо грохнуть ToolTip не дожидаясь "закрытия формы/приложения".

Код: vbnet
1.
2.
3.
4.
  Private Sub Form1_FormClosing(ByVal sender As Object,
   ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    ToolTip1.Dispose()
  End Sub


Для API-шного тултипа аналогично:
Код: vbnet
1.
2.
3.
4.
  Private Sub Form1_FormClosing(ByVal sender As Object,
   ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
     DestroyWindow m_lTTHwnd
  End Sub


Вроде (надеюсь) это полностью излечивает проблему.

P.S. Жулик ваш этот уборщик мусора, раз такую фигню не умеет разруливать. Скорее всего уборщик грохает объекты в неправильной последовательности или что-то в этом духе.
...
Рейтинг: 0 / 0
16.10.2013, 23:32
    #38430474
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Дмитрий77P.S. Жулик ваш этот уборщик мусора, раз такую фигню не умеет разруливать. Скорее всего уборщик грохает объекты в неправильной последовательности или что-то в этом духе.
готовить не умеешь, книги читать не хочешь.
...
Рейтинг: 0 / 0
17.10.2013, 00:42
    #38430525
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Изопропилготовить не умеешь
Тогда скажи что я неправильно приготовил .
Я достаточно подробно расписал что я делаю.

Если не делать
Код: vbnet
1.
2.
3.
4.
  Private Sub Form1_FormClosing(ByVal sender As Object,
   ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    ToolTip1.Dispose()
  End Sub


то может быть
InvalidOperationException
Попытка доступа к элементу управления 'ListView1' не из того потока в кот. он был создан

Например:
при нажатии Alt+F4 когда Tooltip отображает subitem на Listview1
Код: vbnet
1.
ToolTip1.SetToolTip(CType(sender, Control), lSubItem.Text)
...
Рейтинг: 0 / 0
17.10.2013, 03:11
    #38430561
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
Ладно, с учетом того кода что я привел, ты мне не скажешь как сготовить, там в другом проблема.
А Workaround я уже и так сделал убив тултип.

Изопропилготовить не умеешь, .
Не, не умею
Изопропилкниги читать не хочешь.
Предлагаешь читать БОЛЬШУЮ КУЛИНАРНУЮ ЭНЦИКЛОПЕДИЮ?
Ты не поверишь, НО КУШАТЬ ХОЧЕТСЯ ВСЕГДА, есть то надо , ну хотя б сосиски? не?
И в принципе я их приготовил и съел.
Но у меня остались два вопроса:
1. НАДО ЛИ выключать огонь под кастрюлей?
2. А КАК мне выключить огонь?

Да не, я не против читать
Ток за чтением книги водичка выкипет и кастрюля сгорит.

А вот не знаю я где выключатель, плита новой конструкции. Водой заливать пытался, да вот не знаю как газ выключить.
А м.б там "Уборщик плиты" встроенный? Смотрит раз в 3 минуты, сосиски зъели, вода кипит, про кастрюлю забыли, объект так сказать не используется, дай думаю выключу.

Ты мне просто ответь как сабклассинг правильно снять (если хочешь помочь здесь и сейчас)? Ты же читал инструкции.
...
Рейтинг: 0 / 0
17.10.2013, 08:40
    #38430652
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Tooltip в Listview (Items+Subitems+FullRowSelect)
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Tooltip в Listview (Items+Subitems+FullRowSelect) / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]