проблема с редактированием в Treeview

Тема в разделе "Visual Basic", создана пользователем yxoglyxo, 1 ноя 2008.

  1. yxoglyxo

    yxoglyxo Гость

    Всем привет!
    Имеется TreeView на форме типа:

    -RootNodeText

    ----------Node11Text

    ---------------Node12Text

    ------------------Node13Text: 10

    -RootNodeText

    ----------Node21Text

    ---------------Node22Text

    ------------------Node23Text: 20

    etc


    при щелкании мышкой по Node13Text или Node23Text нужно их отредактировать (использую StartLabelEdit). Загвоздка тут вот в чем:
    текст должен редактироваться РЯДОМ с текстом Node13Text, т.е. щелкаю мышкой по Node13Text и в режим редактирования переходия не сам
    текст Node13Text, а пространство рядом с ним - там где на схеме цифра 10 (или 20), чтобы фактически редактировать цифры рядом с выбранным Node'ом, оставляя название нетронутым... Ух, лучше бы раз показать чем вслепую объяснять.

    Зараннее благодарна любым советам и просто мыслям вслух :(
     
  2. Tanya

    Tanya Гость

    Наверняка, существует несколько возможностей реализации такой задачи. Например:
    1) Создать (нарисовать) на форме TextBox. сделать его по умолчани невидимым, затем в нужный момент определить расположение SelectedNode и в нем требуемый текст и не запускать StartEditLabel, а расположить по известным уже координатам TextBox, внести в тего требуемый текст и сделать его видимым. По окончании ввода в SelectedItem записывать фиксированную + введенное значение

    Плюс: отдельная обработка числового значения
    Минус: а бог его знает, как это делается ))), то есть приблизительно понятно, что от API не уйти, но сложность с определением выделенного Node, а так бы этот вариант был бы лучше следующего )))

    2) Запустить StartEditLabel, определить хендл окна редактирования, перехватывать сообщения к этому окну и обрабатывать так как нужно по задаче.
    Плюсы: а) не нужно искать SelectedNode
    б) лично я знаю как это делается ))))
    Минусы: а) API! Замена процедуры окна - вещь деликатная!
    б) при обработке сообщение окну редактирования могут быть всякие неточности ... нонет предела совершенству, возможно ты сможешь устранить все эти баги.

    Итак, вариант 2! )))
    Потребуется: модуль формы и стандартный модуль
    В модуле формы Form1:
    Код (Text):
    Option Explicit

    Private Sub Form_Load()
    With Me.TreeView1
    'Просто заполняем тривью
    .Nodes.Add(, , "R1", "RootNodeText").Expanded = True
    .Nodes.Add("R1", tvwChild, "R2", "Node11Text").Expanded = True
    .Nodes.Add("R2", tvwChild, "R3", "Node12Text").Expanded = True
    .Nodes.Add("R2", tvwChild, "R4", "Node13Text: 10").Expanded = True
    .Nodes.Add(, , "R5", "RootNodeText").Expanded = True
    .Nodes.Add("R5", tvwChild, "R6", "Node21Text").Expanded = True
    .Nodes.Add("R6", tvwChild, "R7", "Node22Text").Expanded = True
    .Nodes.Add("R6", tvwChild, "R8", "Node23Text: 20").Expanded = True
    End With
    End Sub

    Private Sub TreeView1_AfterLabelEdit(Cancel As Integer, NewString As String)
    'на всякий случай после редактирования устанавливаем процедуру обработки по умолчанию
    If hProcEditOld<>0 Then
    Call SetWindowLong(hEdit, GWL_WNDPROC, hProcEditOld)
    hProcEditOld=0
    End If

    End Sub

    Private Sub TreeView1_DblClick()

    Dim i As Integer

    With Me.TreeView1
    If Not .SelectedItem Is Nothing Then

    i = InStr(1, .SelectedItem.Text, ": ")

    'В примере - признак редактирования Node символы двоеточие+пробел
    If i > 0 Then
    iStart = i + 1

    .StartLabelEdit

    'Определяем хендл окна редактирования
    hEdit = SendMessage(.hWnd, &H110F, 0, 0)

    'Заменяем стандартную процедуру обработки, на свою
    hProcEditOld = SetWindowLong(hEdit, GWL_WNDPROC, AddressOf [b]SubWndProcEdit[/b])

    'Выделяем в поле весь текст после двоеточие + пробел
    SendMessage hEdit, EM_SETSEL, iStart, Len(.SelectedItem.Text)

    End If
    End If
    End With
    В стандартном модуле Module1
    Код (Text):
    Option Explicit

    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

    Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
    (ByVal lpPrevWndFunc As Long, _
    ByVal hWnd As Long, _
    ByVal Msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long

    Public Const GWL_WNDPROC = (-4)

    Public Const WM_CHAR = &H102
    Public Const WM_KEYUP = &H101
    Public Const WM_KEYDOWN = &H100
    Public Const WM_LBUTTONUP = &H202


    Public Const EM_SETSEL = &HB1
    Public Const EM_GETSEL = &HB0

    Public Const VK_END = &H23
    Public Const VK_BACK = &H8
    Public Const VK_DELETE = &H2E
    Public Const VK_ESCAPE = &H1B
    Public Const VK_HOME = &H24
    Public Const VK_RETURN = &HD
    Public Const VK_RIGHT = &H27
    Public Const VK_LEFT = &H25
    Public Const VK_UP = &H26
    Public Const VK_DOWN = &H28

    Public hProcEditOld As Long
    Public hEdit As Long
    Public iStart As Long
    '

    'своя процедура обработки сообщение окну редактирования
    Public Function SubWndProcEdit(ByVal hWnd As Long, _
    ByVal uMsg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long

    On Error Resume Next

    Dim bln As Boolean 'флаг, который если Истина, показывает, что нужно запускать обработку сообщения стандартной процедурой
    Dim i1 As Long, i2 As Long

    bln = False

    Select Case uMsg
    Case WM_CHAR 'был введен символ, мы допускаем ввод только цифр
    If wParam < &H30 Or wParam > &H39 Then
    bln = False
    Else
    bln = True 'вот они цифры! )))
    End If

    Case WM_KEYDOWN, WM_KEYUP
    Select Case wParam
    Case VK_HOME
    'не позволим перемещаться за пределы редактируемого текста
    bln = False
    'Тут тоже не совсем верно работает, выделяется весь редактируемый текст, вместо простого перемещения курсора
    SendMessage hEdit, EM_SETSEL, iStart, iStart
    SubWndProcEdit = True

    Case VK_LEFT, VK_BACK, VK_UP
    'строго говоря BackSpace не работает, это относится к минусам )))
    'проверяем текущее положение курсора
    i1 = SendMessage(hEdit, EM_GETSEL, 0, i2) Mod (2 ^ 8)

    'здесь попытка предотвратить перемещения курсора в нередактируемый текст
    If i1 = iStart And i1 = i2 Then
    bln = False

    ElseIf (i1 <= iStart And i1 <> i2) Then
    bln = False

    Else
    bln = True
    End If

    Case VK_END, VK_RIGHT, VK_DOWN, VK_DELETE, VK_ESCAPE, VK_RETURN
    bln = True' эти клавиши обрабатываются как обычно

    Case Else

    'мы допускаем ввод только цифр
    If wParam < &H30 Or wParam > &H39 Then
    bln = False
    Else
    bln = True
    End If

    End Select

    Case WM_LBUTTONUP
    'здесь мы не знаем, где кликнули, вернее знаем, но не заморачиваемся: позволяем выполниться процедуре по умолчанию
    SubWndProcEdit = CallWindowProc(hProcEditOld, hEdit, uMsg, wParam, lParam)

    'и затем проверяем новое положение курсора, если в нередактируемом тексте - возврат к редактируемому
    i1 = SendMessage(hEdit, EM_GETSEL, 0, i2) Mod (2 ^ 8)

    If i1 <= iStart Then
    bln = False

    SendMessage hEdit, EM_SETSEL, iStart, iStart
    End If

    bln = False
    Case Else
    bln = True
    'все остальные сообщения обрабатываются стандартно

    End Select

    'обязательно нужно вернуть значение
    If bln Then
    SubWndProcEdit = CallWindowProc(hProcEditOld, hEdit, uMsg, wParam, lParam)
    Else
    SubWndProcEdit = True
    End If

    End Function
     
Загрузка...
Похожие Темы - проблема редактированием Treeview
  1. Zloikaktus
    Ответов:
    0
    Просмотров:
    8
  2. c0de3r
    Ответов:
    5
    Просмотров:
    128
  3. DobermannTT
    Ответов:
    10
    Просмотров:
    137
  4. SoulPaladin
    Ответов:
    4
    Просмотров:
    134
  5. Artael
    Ответов:
    1
    Просмотров:
    110

Поделиться этой страницей