Hỏi về TreeView Object - Kết hợp sự kiện MouseDown() và Hàm HitTest()

Liên hệ QC

tungson_mrcc

Thành viên hoạt động
Tham gia
25/4/07
Bài viết
108
Được thích
72
Nhờ các bạn hướng dẫn:
Ý đồ của tôi là khi người dùng kích chuột trên TreeView Object, tôi sẽ dùng sự kiện MouseDown kết hợp với Hàm HistText(X,Y) để dẫn mạch cho chương trình chạy tiếp.

Tuy nhiên khi chạy thử thì thấy chương trình chạy không đúng. Khi kích chuột ngay tại Node thi SourceNode = Nothing, còn kích chuột vẩn vơ trên TreeView thì SourceNode lại có kết quả.

Mong được các bác chỉ dẫn .

Trân trọng

Mã:
Private Sub MyTreeView_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
Dim SourceNode As Node
 
Set SourceNode = Me.MyTreeView.HitTest(X, Y)
If SourceNode Is Nothing Then
msgbox "Hay chon Node thich hop"
Else
'Cho chay cac sub routine khác
End If
 
Nhờ các bạn hướng dẫn:
Ý đồ của tôi là khi người dùng kích chuột trên TreeView Object, tôi sẽ dùng sự kiện MouseDown kết hợp với Hàm HistText(X,Y) để dẫn mạch cho chương trình chạy tiếp.

Tuy nhiên khi chạy thử thì thấy chương trình chạy không đúng. Khi kích chuột ngay tại Node thi SourceNode = Nothing, còn kích chuột vẩn vơ trên TreeView thì SourceNode lại có kết quả.

Mong được các bác chỉ dẫn .

Trân trọng

Mã:
Private Sub MyTreeView_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
Dim SourceNode As Node
 
Set SourceNode = Me.MyTreeView.HitTest(X, Y)
If SourceNode Is Nothing Then
msgbox "Hay chon Node thich hop"
Else
'Cho chay cac sub routine khác
End If

Có thể bạn phải sử dụng hàm API ClientToScreen để quy đổi toạ độ chuột về màn hình.
 
Upvote 0
Theo mình thì anh Tuân nói đúng, cái tọa độ mà Hàm trả về nó bị lệch. Mình điều chỉnh bằng 1 tỷ lệ X*15 và Y*15 nghe chừng ổn, vậy hướng giải quyết của anh Tuân là chuẩn.
Các bạn tham khảo ví dụ nha, mình dùng MouseMove nên các bạn cứ rê chuột qua các Node

Mã:
Private Sub TreeView1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
    Dim PointedNode As Node
    Set PointedNode = TreeView1.HitTest(x * 15, y * 15)
    LabelX.Caption = "X: " & Str(x)
    LabelY.Caption = "Y: " & Str(y)
    If PointedNode Is Nothing Then
        Labelnode.Caption = ""
    Else
        Labelnode.Caption = "Node: " & PointedNode.Text
    End If
End Sub
'=======================
Private Sub UserForm_Initialize()
Dim i
    With TreeView1.Nodes
    For i = 1 To 14
        .Add , , , Sheet1.Cells(i, 1)
        Next
    End With
    
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Có thể bạn phải sử dụng hàm API ClientToScreen để quy đổi toạ độ chuột về màn hình.
Cám ơn Bác Nghị Hách đã trả lời.
Xin cho hỏi tiếp: tôi có thể tải cái API ClientToScreen ở đâu? Sử dụng nó như thế nào?

Mình là dân a ma tơ, biết về VBE la do chịu khó vào GPE, nên còn nhiều cái chưa biết lắm. MOng các bạn chỉ dẫn thêm.

Trân trọng.
 
Upvote 0
Gửi bạn Sealand,
Mình tải file ví dụ của bạn về, khi chạy thử vẫn bị lỗi "Could not load an Object..." như hôm qua đã thông báo với bạn.
Vào VBA, mở được form của bạn thì không thấy cái TreeView1 đâu cả. Không biết có phải là do cái TreeView Object của bạn không giống với cái mình đang có nên mới có chuyện như vậy.
Cám ơn bạn đã chỉ dẫn cho mình.
 
Upvote 0
Gửi bạn Sealand,
Mình tải file ví dụ của bạn về, khi chạy thử vẫn bị lỗi "Could not load an Object..." như hôm qua đã thông báo với bạn.
Vào VBA, mở được form của bạn thì không thấy cái TreeView1 đâu cả. Không biết có phải là do cái TreeView Object của bạn không giống với cái mình đang có nên mới có chuyện như vậy.
Cám ơn bạn đã chỉ dẫn cho mình.

Vậy thì bạn tạo 1 file ví dụ rồi tạo Form và add cái treeview của bạn vào rồi gửi lên đây xem sao
 
Upvote 0
Gửi bạn Sealand,
Mình tải file ví dụ của bạn về, khi chạy thử vẫn bị lỗi "Could not load an Object..." như hôm qua đã thông báo với bạn.
Vào VBA, mở được form của bạn thì không thấy cái TreeView1 đâu cả. Không biết có phải là do cái TreeView Object của bạn không giống với cái mình đang có nên mới có chuyện như vậy.
Cám ơn bạn đã chỉ dẫn cho mình.
Tôi tải file của anh sealand cũng bị tình trạng như bạn! Tôi làm lại cái khác, bạn thử xem sao nhé
 

File đính kèm

Upvote 0
Theo mình thì anh Tuân nói đúng, cái tọa độ mà Hàm trả về nó bị lệch. Mình điều chỉnh bằng 1 tỷ lệ X*15 và Y*15 nghe chừng ổn, vậy hướng giải quyết của anh Tuân là chuẩn.
Các bạn tham khảo ví dụ nha, mình dùng MouseMove nên các bạn cứ rê chuột qua các Node

Mã:
Private Sub TreeView1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
    Dim PointedNode As Node
    Set PointedNode = TreeView1.HitTest(x * 15, y * 15)
    LabelX.Caption = "X: " & Str(x)
    LabelY.Caption = "Y: " & Str(y)
    If PointedNode Is Nothing Then
        Labelnode.Caption = ""
    Else
        Labelnode.Caption = "Node: " & PointedNode.Text
    End If
End Sub
'=======================
Private Sub UserForm_Initialize()
Dim i
    With TreeView1.Nodes
    For i = 1 To 14
        .Add , , , Sheet1.Cells(i, 1)
        Next
    End With
    
End Sub

Cách làm của anh Sealand là chạy được rồi, tuy nhiên giá trị 15 không phải lúc nào cũng đúng cho mọi thiết bị màn hình máy tính.

Bản chất VBA dùng đơn vị tính Twip nhưng các hàm API hay các control (ActiveX) lại trả về đơn vị Pixcel nên VBA không hiểu. Vì vậy chúng ta cần viết hàm quy đổi đơn vị từ Pixcel sang Twip

Các bạn hãy tạo một Module rồi copy đoạn code về hàm PixelsToTwips dưới đây:
Mã:
Option Explicit

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long

Private Const LOGPIXELSX = 88
Private Const LOGPIXELSY = 90

Public Enum enDirection
    enVERTICAL = 1
    enHORIZONTAL = 0
End Enum

Function PixelsToTwips(lngPixels As Long, Direction As enDirection) As Long
    On Error GoTo lbError
    Dim lDeviceHandle As Long
    Dim lPixelsPerInch As Long
    lDeviceHandle = GetDC(0)
    If Direction = enHORIZONTAL Then
        lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSX)
    Else
        lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSY)
    End If
    lDeviceHandle = ReleaseDC(0, lDeviceHandle)
    PixelsToTwips = lngPixels * 1440 / lPixelsPerInch
fExit:
    On Error Resume Next
    Exit Function
lbError:
    MsgBox Err.Description, vbOKOnly + vbCritical, "Error: " & Err.Number
End Function

Như vậy, thay vì dùng đoạn code trong TreeView1_MouseMove
Set PointedNode = TreeView1.HitTest(x * 15, y * 15)

Ta dùng
Set PointedNode = TreeView1.HitTest(PixelsToTwips(x, enHORIZONTAL), PixelsToTwips(y, enVERTICAL))

Hàm PixelsToTwips sẽ đúng cho mọi thiết bị màn hình.
 
Upvote 0
Cái này ứng dụng để làm gì nhỉ ??
 
Upvote 0
Cám ơn các bạn đã quan tâm giúp đỡ.
Bác Trư định "Kidding Me" chăng. Thấy thâm niên của Bác từ 12.2006 cơ mà.

Mình đang mò cái TreeView, định làm mấy cái Sub xử lý các thao tác giống như khi ta làm việc với Explorer. (Như người ta làm ở đây nè.)

Mong được các bạn chỉ dẫn thêm.

Trân trọng
 
Upvote 0
ko cái mình hỏi là lấy tọa độ mouse để làm gì và ứng dụng vào việc gì ấy mà
 
Upvote 0
ko cái mình hỏi là lấy tọa độ mouse để làm gì và ứng dụng vào việc gì ấy mà

Không biết chủ topic mục đích cụ thể là gì, nhưng mình có ý tưởng là khi đưa chuột vào các node thì status của form hiện thông tin mô tả về mục/node đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Không biết chủ topic mục đích cụ thể là gì, nhưng mình có ý tưởng là khi đưa chuột vào các node thì status của form hiện thông tin mô tả về mục/node đó.

Xin trả lời các Bác như sau:
Khi tìm hiểu về TreeView tôi thấy:
Ưu điểm: cách trình bày thông tin rất hay, mà bảng dữ liệu lại rất gọn, nó lại tự động hiện dòng thông tin (kiểu như TipText) khi Node.Text có chiều dài lớn hơn bề rộng của TreeView
 
Lần chỉnh sửa cuối:
Upvote 0
Không biết chủ topic mục đích cụ thể là gì, nhưng mình có ý tưởng là khi đưa chuột vào các node thì status của form hiện thông tin mô tả về mục/node đó.
Khổ chủ xin trả lời các Bác như sau:
Khi tìm hiểu về TreeView, mình thấy nó rất tiện cho người dùng (end user) , vì thấy cách trình bày của nó cũng giống như cây thư mục trong cửa sổ Explorer (theo mình hiểu thì chính là nó đấy thôi).

Mặc dù vậy,nếu so sánh TreeView với Explorer thì quá khập khiễng, vì mức độ tiện nghi của Explorer là quá cao.

Xin gửi các Bác file đang làm, nhờ các Bác xem và cho thêm ý kiến góp ý.

Tôi muốn là khi người nhắp chuột trên một Node, thì đầu tiên phải biết đó là Node nào - cái này phải nhờ đến HitTest(x,y). Nhưng tham số x, y mà HitTest sử dụng lại không giống với x,y mà sự kiện mousedown trả về. Phần này đã được giải quyết rất hay nhờ Bác Sealand và Bác Nghị Hách (một lần nữa rất cảm ơn)

Bước tiếp theo tôi xét xem người dùng bấm nút chuôt nào:
- Nếu là bấm chuột trái thì hiện thông tin tương ứng với Node mà người dùng nhắp chuột.
- Nếu là bấm chuột phải thì cho hiện Context Menu. Đến đây thì tôi lại đang bí: khi tôi kích vào một lệnh trên ContextMenu thì thuộc tính .OnAction của control không chịu chạy.

Chân thành cám ơn sự quan tâm giúp đỡ của các Bác.
Trân trọng.
 

File đính kèm

Upvote 0
Bước tiếp theo tôi xét xem người dùng bấm nút chuôt nào:
- Nếu là bấm chuột trái thì hiện thông tin tương ứng với Node mà người dùng nhắp chuột.
- Nếu là bấm chuột phải thì cho hiện Context Menu. Đến đây thì tôi lại đang bí: khi tôi kích vào một lệnh trên ContextMenu thì thuộc tính .OnAction của control không chịu chạy.

Chân thành cám ơn sự quan tâm giúp đỡ của các Bác.
Trân trọng.
Cho MySub vào 1 Module nào đó xem
Chuyện bình thường... bạn đã làm hoành tráng đến mức thế kia, chỉ còn có tí xíu, chẳng lẽ không nhận ra tính logic của vấn đề
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom