Listview và Listbox - Hỏi về ưu khuyết. (1 người xem)

  • Thread starter Thread starter cantl
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

cantl

!!! Giải thoát !!!
Thành viên bị đình chỉ hoạt động
Tham gia
6/8/08
Bài viết
1,815
Được thích
1,163
Giới tính
Nam
Chào các bác,
Các bác cho em hỏi giữa Listview và Listbox thì nên chọn cái nào lên form cho hoành tráng ạ?
Em không muốn dùng theo kiểu tùy trường hợp, mà chỉ có thể chọn 1 mà thôi.
Ưu, khuyết là gì ạ?
 
Các bác cho em hỏi giữa Listview và Listbox thì nên chọn cái nào lên form cho hoành tráng ạ?
Vấn đề không phải là hoành tráng mà cái nào hỗ trợ tùy biến nhiều hơn cho người lập trình, viết giao diện.
Tôi thì chọn Listview. (Nếu bên Access thì khỏi lăn tăn vụ này vì Form Access có công cụ mạnh là SubForm/SubReport)
Điểm bất tiện của Listview chỉ có một, là phải đăng ký MSCOMCTL.OCX để sử dụng.
 
Upvote 0
Upvote 0
Listview như anh @ongke0711 nói là phải đăng ký, mặc dù Listview có đường lưới(grid) đẹp, nhưng mang qua máy khác không đăng ký là không hiện. Dùng Listbox thì không sao. Em chỉ biết có vậy.
 
Upvote 0
Việc chọn ListView (control trong MSCOMCTL.OCX) hay ListBox trong MSForms thì cần xem nhu cầu thực sự chức năng mà mình thiết kế. Mỗi cái có ưu điểm nổi bật riêng:
ListView của MS
- Chỉ chạy trong môi trường 32-bit. Nếu ứng dụng bạn viết không khắt khe về môi trường, người dùng chấp nhận chỉ cài Office 32-bit thì điều này chấp nhận được.
- Không hỗ trợ unicode. Về khoản này thì điểm trừ nhiều nhất với ứng dụng dùng font unicode.
- Tùy biến hiển thị (định dạng font, màu sắc, hình ảnh giữa các dòng) gần giống với cách hiển thị của Windows Explorer (cũ). Trình độ lập trình càng cao thì càng có khả năng tùy biến hiển thị nó phong phú.

ListBox trong MSForms
- Là control thuộc MSForms được cài đặt kèm theo bộ Office nên đương nhiên hỗ trợ cả 32 và 64-bit.
- Hỗ trợ unicode
- Với số lượng dữ liệu khá lớn tốc độ load nhanh.
- Hạn chế duy nhất là hiển thị rất giản đơn, không tùy biến định dạng màu sắc, font các dòng, không đính kèm hình ảnh được.
 
Upvote 0
Bác Tuân nói đúng đó. Tôi cũng quên vụ Unicode. Nếu đã cài OCX thì cài cái OCX của bác Tuân luôn là ngon lành cành đào. Tôi cũng có dùng BSAC OCX.
 
Upvote 0
Đã "nhiều quá không nhớ hết" thì hỏi làm gì?
Cứ thử đi thử lại nhiều lần. Kinh nghiệm sẽ dạy cho biết ưu/khuyết điểm.

Bạn có khuynh hướng giống nhiều người xin code ở đây. Đã không tự viết code được mà còn đòi "tối ưu". Đòi vậy tưởng là hoành tráng, nhưng gặp thằng cắc cớ nó hỏi: "chỗ này làm gì vậy?" thì muối mặt.
 
Upvote 0
Trao đổi với bác @cantl là vui nhất.
Listbox, listview bỏ qua bên đi, nó nằm ngoài tầm với của mình rồi.
Hiện mình chỉ quan tâm, là làm cách nào để xử lý được dữ liệu luôn trên nền web. Có thể giao diện là nhập liệu, truyền dữ liệu vè máy chủ xử lý và trả lại kết quả trên giao diện web.
Đang đau đầu đây
 
Upvote 0
Upvote 0
Anh có tệp nào ví dụ không, đưa em thử chuyển thành Unicode.
Trước đây tôi có dùng Listview trong mấy bài này.
https://www.giaiphapexcel.com/diendan/threads/tải-dữ-liệu-từ-excel-sang-dbf.161020/#post-1077114
https://www.giaiphapexcel.com/diendan/threads/lấy-dữ-liệu-từ-sql-đưa-vào-listview.161131/#post-1076436

Nếu tôi dùng font .vni và listview cũng dùng font này thì hiển thị được tiếng Việt.

File đính kèm bên dưới.

Còn về vụ 32bit, 64bit thì tôi vẫn sử dụng bình thường.
- 32bit thì copy và đăng ký OCX vào "C:\Windows\System32\".
- 64 bit thì copy và đăng ký OCX vào "C:\Windows\SysWOW64\".

Screenshot at Jan 16 20-35-29.png

Hình này là tôi dùng BSAC.OCX
1705412665751.png
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Anh có tệp nào ví dụ không, đưa em thử chuyển thành Unicode.


ListView và TreeView chạy ổn trong môi trường Window và Office 64bit, không biết anh có nhầm gì không?


Mình đang nói ListView trong bộ ActiveX MSCOMCTL.OCX đấy nhé. API tạo control thì không tính vì ní không dễ áp dụng cho số đông người lập trình VBA.
 
Upvote 0
Nên dẫn các bạn thích lập trình đi vào chuyên nghiệp sớm anh @Nguyễn Duy Tuân, nếu như đang tuổi 23 hiểu sớm còn hơn chờ 30 mới biết "chuyện". API tính ra chỉ như trò chơi mới, chơi nhiều sẽ quen tay.

Lập trình mà không đi đến chuyên nghiệp, tức là đi nữa đường gặp ánh hào quang, mừng rỡ nên dừng bước.

Các ứng dụng API thường là đã có người viết sẵn cả, còn lại là do cách mình thừa kế chúng như thế nào. Khi chúng đã đi vào một góc của não bộ rồi, thì chúng như một tài sản.
 
Upvote 0
Dưới đây là một đoạn mã mà một lập trình viên API khao khát làm được, cho dù là ngôn ngữ lập trình nào, HĐH Window hay Linux.
Đoạn mã này là đoạn mã mà VBA tạo lệnh chạy ở cấp thấp nhất trong máy tính.
Để viết đoạn mã này cần có nhiều năm học tập và nhiều năm kinh nghiệm.
Các phần cần học như: Ngôn ngữ Assembly, học dịch ngược, API Win32.
Các bạn biết đó, API có các hàm rất "nguy hiểm", viết mã "sai một li là đi một dặm". Nên nhiều năm kinh nghiệm là rất quý giá.

(Đoạn mã này chỉ thực hiện một mục đích duy nhất là chóng ứng dụng Office sụp khi sử dụng hàm API SetTimer. )
Đoạn mã này cũng có thể áp dụng cho phát triển ListView API, ngon lành là đằng khác.

JavaScript:
' //
' // 64/32 bit timer class for VBA
' // by The trick 2019
' //

Option Explicit

#If VBA7 = 0 Then
  Private Enum LongLong:[_]:End Enum
  Private Enum LongPtr:[_]:End Enum
#End If
Private Const FADF_AUTO                     As Long = 1
Private Const HEAP_CREATE_ENABLE_EXECUTE    As Long = &H40000
Private Const HEAP_NO_SERIALIZE             As Long = &H1
Private Const HEAP_ZERO_MEMORY              As Long = &H8
Private Const PROCESS_HEAP_ENTRY_BUSY       As Long = &H4
Private Const WNDPROCINDEX                  As Long = 8
Private Const HEAP_ENV_VARIABLE             As String = "TrickVBATimer"
Private Const TIMERPROC_INDEX               As Long = 5

Private Type SAFEARRAYBOUND
    cElements           As Long
    lLbound             As Long
End Type

Private Type PROCESS_HEAP_ENTRY
    lpData              As LongPtr
    cbData              As Long
    cbOverhead          As Byte
    iRegionIndex        As Byte
    wFlags              As Integer
    dwCommittedSize     As Long
    dwUnCommittedSize   As Long
    lpFirstBlock        As LongPtr
    lpLastBlock         As LongPtr
End Type

Private Type SAFEARRAY
    cDims               As Integer
    fFeatures           As Integer
    cbElements          As Long
    cLocks              As Long
    pvData              As LongPtr
    Bounds              As SAFEARRAYBOUND
End Type

Private m_pAsmThunk     As LongPtr
Private m_hCodeHeap     As LongPtr
Private m_pEbMode       As LongPtr
Private m_lIdEvent      As LongPtr
#If VBA7 Then
Private Declare PtrSafe Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableW" (ByVal lpName As LongPtr, ByVal lpValue As LongPtr) As Long
Private Declare PtrSafe Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableW" (ByVal lpName As LongPtr, ByVal lpBuffer As LongPtr, ByVal nSize As Long) As Long
Private Declare PtrSafe Function HeapCreate Lib "kernel32" (ByVal flOptions As Long, ByVal dwInitialSize As LongPtr, ByVal dwMaximumSize As LongPtr) As LongPtr
Private Declare PtrSafe Function HeapDestroy Lib "kernel32" (ByVal hHeap As LongPtr) As Long
Private Declare PtrSafe Function HeapAlloc Lib "kernel32" (ByVal hHeap As LongPtr, ByVal dwFlags As Long, ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function HeapFree Lib "kernel32" (ByVal hHeap As LongPtr, ByVal dwFlags As Long, ByVal lpMem As LongPtr) As Long
Private Declare PtrSafe Function HeapWalk Lib "kernel32" (ByVal hHeap As LongPtr, ByRef lpEntry As PROCESS_HEAP_ENTRY) As Long
Private Declare PtrSafe Function HeapLock Lib "kernel32" (ByVal hHeap As LongPtr) As Long
Private Declare PtrSafe Function HeapUnlock Lib "kernel32" (ByVal hHeap As LongPtr) As Long
Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleW" (ByVal lpModuleName As LongPtr) As LongPtr
Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpProcName As String) As LongPtr
Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryW" (ByVal lpLibFileName As LongPtr) As LongPtr
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef pDestination As Any, ByRef Source As Any, ByVal Length As LongPtr)
  #If Win64 Then
  Private Declare PtrSafe Sub DupArray Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination() As Any, ByRef pSA As Any, Optional ByVal Length As LongPtr = 8)
  #Else
  Private Declare PtrSafe Sub DupArray Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination() As Any, ByRef pSA As Any, Optional ByVal Length As LongPtr = 4)
  #End If
#Else
Private Declare Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableW" ( ByVal lpName As Long, ByVal lpValue As Long) As Long
Private Declare Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableW" ( ByVal lpName As Long, ByVal lpBuffer As Long, ByVal nSize As Long) As Long
Private Declare Function HeapCreate Lib "kernel32" ( ByVal flOptions As Long, ByVal dwInitialSize As Long, ByVal dwMaximumSize As Long) As Long
Private Declare Function HeapDestroy Lib "kernel32" ( ByVal hHeap As Long) As Long
Private Declare Function HeapAlloc Lib "kernel32" ( ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" ( ByVal hHeap As Long, ByVal dwFlags As Long, ByVal lpMem As Long) As Long
Private Declare Function HeapWalk Lib "kernel32" ( ByVal hHeap As Long, ByRef lpEntry As PROCESS_HEAP_ENTRY) As Long
Private Declare Function HeapLock Lib "kernel32" ( ByVal hHeap As Long) As Long
Private Declare Function HeapUnlock Lib "kernel32" ( ByVal hHeap As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleW" ( ByVal lpModuleName As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryW" ( ByVal lpLibFileName As Long) As Long
Private Declare Function SetTimer Lib "user32" ( ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" ( ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( ByRef pDestination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Sub DupArray Lib "kernel32" Alias "RtlMoveMemory" ( ByRef Destination() As Any, ByRef pSA As Any, Optional ByVal Length As Long = 4)
#End If

Public Event Tick(ByVal hwnd As LongPtr, ByVal idEvent As LongPtr)

Private m_vTag          As Variant
Private m_lInterval     As Long

Public Property Let Interval(ByVal lValue As Long)
  If lValue = m_lInterval Then Exit Property
  If m_pAsmThunk Then
    KillTimer 0, m_lIdEvent
    m_lIdEvent = SetTimer(0, 0, lValue, m_pAsmThunk)
    If m_lIdEvent = 0 Then Err.Raise 5
    #If Win64 Then
    CopyMemory ByVal m_pAsmThunk + &H3A, m_lIdEvent, Len(m_lIdEvent)
    #Else
    CopyMemory ByVal m_pAsmThunk + &H16, m_lIdEvent, Len(m_lIdEvent)
    #End If
  Else
    If Not CreateAsm(lValue) Then Err.Raise 5
  End If
  m_lInterval = lValue
End Property

Public Property Get Interval() As Long
    Interval = m_lInterval
End Property

Public Property Let Tag(ByVal vValue As Variant)
    m_vTag = vValue
End Property

Public Property Set Tag(ByVal vValue As Variant)
    Set m_vTag = vValue
End Property

Public Property Get Tag() As Variant
  If IsObject(m_vTag) Then Set Tag = m_vTag Else Tag = m_vTag
End Property

' // Callback function
'/ / Nêìu baòn sýÒa ðôÒi viò trí cuÒa hàm này baòn nên câòp nhâòt hãÌng sôì TIMERPROC_INDEX
Private Function TimerProc(ByVal hwnd As LongPtr, ByVal uMsg As Long, ByVal idEvent As LongPtr, ByVal dwTime As Long) As Long
  On Error Resume Next
  RaiseEvent Tick(hwnd, idEvent)
  Err.Clear
End Function
  
'// Taòo hôòi thun nêìu không tôÌn taòi
Private Function CreateAsm(ByVal lInterval As Long) As Boolean
  Dim bIsInIDE    As Boolean
  Dim lIdEvent    As LongPtr
  #If Not (-VBA6 Or -VBA7) Then
  Debug.Assert MakeTrue(bIsInIDE)
  #End If
  If m_pAsmThunk Then CreateAsm = True: Exit Function
  If GetCodeHeap() = 0 Then Exit Function
  #If Not (-VBA6 Or -VBA7) Then
  If bIsInIDE Then
  #End If
    If m_pEbMode = 0 Then m_pEbMode = SearchEbMode(): If m_pEbMode = 0 Then Exit Function
  #If Not (-VBA6 Or -VBA7) Then
  End If
  #End If
  #If -VBA7 And -Win64 Then
    m_pAsmThunk = Create64BitThunk()
    If m_pAsmThunk = 0 Then Exit Function
    lIdEvent = SetTimer(0, 0, lInterval, m_pAsmThunk)
    If lIdEvent = 0 Then
      HeapFree m_hCodeHeap, HEAP_NO_SERIALIZE, m_pAsmThunk - 4
      m_pAsmThunk = 0
      Exit Function
    End If
    CopyMemory ByVal m_pAsmThunk + &H3A, lIdEvent, Len(lIdEvent)
  #Else
    m_pAsmThunk = Create32BitThunk()
    If m_pAsmThunk = 0 Then Exit Function
    lIdEvent = SetTimer(0, 0, lInterval, m_pAsmThunk)
    If lIdEvent = 0 Then HeapFree m_hCodeHeap, HEAP_NO_SERIALIZE, m_pAsmThunk - 4: m_pAsmThunk = 0: Exit Function
    #If -VBA6 Or -VBA7 Then
    CopyMemory ByVal m_pAsmThunk + &H16, lIdEvent, Len(lIdEvent)
    #Else
    If bIsInIDE Then CopyMemory ByVal m_pAsmThunk + &H16, lIdEvent, Len(lIdEvent)
    #End If
  '// Debug.Print Hex(m_pAsmThunk)
  #End If
  m_lIdEvent = lIdEvent
  CreateAsm = True
End Function

#If -VBA7 And -Win64 Then
' // Search for EbMode function
Private Function SearchEbMode() As LongPtr
  ' / / 0. Côì gãìng lâìy EbMode týÌ các thunk trýõìc
  SearchEbMode = GetEbModeFromThunks()
  If SearchEbMode Then Exit Function
  Dim hVbe            As LongPtr
  Dim e_lfanew        As Long
  Dim iNumOfSec       As Integer
  Dim iOptSize        As Integer
  Dim pSection        As LongPtr
  Dim lIndex          As Long
  Dim cName           As Currency
  Dim pStartScan      As LongPtr
  Dim pEndScan        As LongPtr
  Dim bTemplate(&H5F) As Byte
  Dim bMask(&H5F)     As Byte
  Dim bData()         As Byte
  Dim tSAMap          As SAFEARRAY
  '// 1. Search for VBE7.dll ".text" section
  hVbe = GetModuleHandle(StrPtr("VBE7"))
  If hVbe = 0 Then Exit Function
  CopyMemory e_lfanew, ByVal hVbe + &H3C, 4
  CopyMemory iNumOfSec, ByVal hVbe + e_lfanew + 6, 2
  CopyMemory iOptSize, ByVal hVbe + e_lfanew + &H14, 2
  pSection = hVbe + e_lfanew + &H18 + iOptSize
  For lIndex = 0 To iNumOfSec - 1
    CopyMemory cName, ByVal pSection, 8
    '// Search for ".text" section
    If cName = 50023612.1134@ Then
      CopyMemory pStartScan, ByVal pSection + &HC, 4
      CopyMemory pEndScan, ByVal pSection + &H8, 4
      pStartScan = pStartScan + hVbe
      pEndScan = pEndScan + pStartScan - 1
      Exit For
    End If
    pSection = pSection + &H28
  Next
  If pStartScan = 0 Or pEndScan = 0 Then Exit Function
  '// 2. Search for Proc/MethCallEngine thunk template
  '// 48 89 4C 24 08 48 89 54 24 10 4C 89 44 24 18 4C
  '// 89 4C 24 20 48 B8 11 11 11 11 11 11 11 11 48 0B
  '// C0 74 32 48 B8 XX XX XX XX XX XX XX XX FF D0 48
  '// 83 F8 02 74 20 48 B8 11 11 11 11 11 11 11 11 48
  '// 8B 4C 24 08 48 8B 54 24 10 4C 8B 44 24 18 4C 8B
  '// 4C 24 20 FF E0 48 33 C0 C2 11 11
  '// XX XX XX XX XX XX XX XX - EbMode
  '// Setup template
  CopyMemory bTemplate(&H0), 609147917080124.0392@, 8
  CopyMemory bTemplate(&H8), 548317242310341.8404@, 8
  CopyMemory bTemplate(&H10), 122996679316526.1961@, 8
  CopyMemory bTemplate(&H18), 81291849773882.1905@, 8
  CopyMemory bTemplate(&H20), 79148524.8704@, 8
  CopyMemory bTemplate(&H28), 524697394135171.072@, 8
  CopyMemory bTemplate(&H30), 127684979858204.0707@, 8
  CopyMemory bTemplate(&H38), 519295061033333.9921@, 8
  CopyMemory bTemplate(&H40), 261787042489960.3595@, 8
  CopyMemory bTemplate(&H48), -840931986015968.9712@, 8
  CopyMemory bTemplate(&H50), -459725066342497.3748@, 8
  CopyMemory bTemplate(&H58), 111.8658@, 8
  '// Setup mask
  For lIndex = 0 To UBound(bMask)
    If lIndex < &H25 Or (lIndex > &H2C And lIndex < &H5B) Then
      bMask(lIndex) = 1
    End If
  Next
  '// Map array to data
  With tSAMap
    .cbElements = 1
    .cDims = 1
    .fFeatures = FADF_AUTO
    .Bounds.cElements = CLng(pEndScan - pStartScan) + 1
    .pvData = pStartScan
  End With
  DupArray bData, VarPtr(tSAMap)
  lIndex = FindSignature(bData(), bTemplate(), bMask())
  DupArray bData, 0@
  If lIndex = -1 Then Exit Function
  CopyMemory SearchEbMode, ByVal pStartScan + lIndex + &H25, Len(SearchEbMode)
  Debug.Print "SearchEbMode: "; SearchEbMode
End Function

' // Create 64 bit thunk
Private Function Create64BitThunk() As LongPtr
  Dim pCode           As LongPtr
  Dim llThunk(19)     As Currency
  Dim pfnKillTimer    As LongPtr
  Dim pfnTimerProc    As LongPtr
  Dim pVtbl           As LongPtr
  Dim hUser32         As LongPtr
  If m_hCodeHeap = 0 Then Exit Function
  hUser32 = GetModuleHandle(StrPtr("user32"))
  If hUser32 = 0 Then
    hUser32 = LoadLibrary(StrPtr("user32"))
    If hUser32 = 0 Then Exit Function
  End If
  pfnKillTimer = GetProcAddress(hUser32, "KillTimer")
  If pfnKillTimer = 0 Then Exit Function
  pCode = HeapAlloc(m_hCodeHeap, HEAP_NO_SERIALIZE Or HEAP_ZERO_MEMORY, &H9E)
  If pCode = 0 Then Exit Function
  pCode = pCode + 4   ' // Disable
  '// 48 83 EC 38 48 89 4C 24 40 48 89 54 24 48 4C 89
  '// 44 24 50 4C 89 4C 24 58 48 B8 00 00 00 00 00 00
  '// 00 00 FF D0 48 85 C0 74 06 3C 01 74 23 EB 66 FF
  '// 0D C7 FF FF FF 48 31 C9 48 BA 00 00 00 00 00 00
  '// 00 00 48 B8 00 00 00 00 00 00 00 00 FF D0 EB 45
  '// 48 B9 00 00 00 00 00 00 00 00 48 8B 54 24 40 4C
  '// 8B 44 24 48 4C 8B 4C 24 50 48 8B 44 24 58 48 89
  '// 44 24 20 48 8D 44 24 30 48 C7 00 00 00 00 00 48
  '// 89 44 24 28 48 B8 00 00 00 00 00 00 00 00 FF D0
  '// 48 8B 44 24 30 48 83 C4 38 C3
  llThunk(0) = 261561642688109.0376@
  llThunk(1) = -855338227140910.8928@
  llThunk(2) = 635128552707379.3092@
  llThunk(3) = 4.7176@
  llThunk(4) = 841287065171859.8656@
  llThunk(5) = -4308860891082.0346@
  llThunk(6) = -394929513387840.1267@
  llThunk(7) = 4.7688@
  llThunk(8) = 309172.6336@
  llThunk(9) = 503835040177926.9632@
  llThunk(10) = 4.7432@
  llThunk(11) = 549443149092460.9536@
  llThunk(12) = 261561864333952.7307@
  llThunk(13) = -855449057939821.1504@
  llThunk(14) = 346897298657326.8036@
  llThunk(15) = 518814677073086.2408@
  llThunk(16) = 20262005062.1577@
  llThunk(17) = -338698839475932.3648@
  llThunk(18) = -428650304872247.8264@
  llThunk(19) = 4.9976@
  '// Get TimerProc address
  CopyMemory pVtbl, ByVal ObjPtr(Me), Len(pVtbl)
  CopyMemory pfnTimerProc, ByVal pVtbl + (TIMERPROC_INDEX + 7) * Len(pfnTimerProc), Len(pfnTimerProc)
  CopyMemory ByVal pCode, llThunk(0), &H9A
  CopyMemory ByVal pCode + &H1A, m_pEbMode, Len(m_pEbMode)
  CopyMemory ByVal pCode + &H44, pfnKillTimer, Len(pfnKillTimer)
  CopyMemory ByVal pCode + &H52, ObjPtr(Me), 8
  CopyMemory ByVal pCode + &H86, pfnTimerProc, Len(pfnTimerProc)
  Create64BitThunk = pCode
End Function

#Else

' // Search for EbMode function
Private Function SearchEbMode() As LongPtr
  '// 0. Try to get EbMode from previous thunks
  SearchEbMode = GetEbModeFromThunks(): If SearchEbMode Then Exit Function
  Dim hVbe            As LongPtr
  Dim pSection        As LongPtr
  Dim pStartScan      As LongPtr
  Dim pEndScan        As LongPtr
  Dim e_lfanew        As Long
  Dim iNumOfSec       As Integer
  Dim iOptSize        As Integer
  Dim lIndex          As Long
  Dim cName           As Currency
  Dim bTemplate(&H27) As Byte
  Dim bMask(&H27)     As Byte
  Dim bData()         As Byte
  Dim tSAMap          As SAFEARRAY
  Dim vb$
  '// 1. Search for VBE7/6.dll ".text" section
  #If VBA7 Then
  vb = "VBE7"
  #ElseIf VBA6 Then
  vb = "VBE6"
  #Else
  vb = "VBA6"
  #End If
  hVbe = GetModuleHandle(StrPtr(vb))
  If hVbe = 0 Then Exit Function
  #If -VBA6 Or -VBA7 Then
  CopyMemory e_lfanew, ByVal hVbe + &H3C, 4
  CopyMemory iNumOfSec, ByVal hVbe + e_lfanew + 6, 2
  CopyMemory iOptSize, ByVal hVbe + e_lfanew + &H14, 2
  pSection = hVbe + e_lfanew + &H18 + iOptSize
  For lIndex = 0 To iNumOfSec - 1
    CopyMemory cName, ByVal pSection, 8
    '// Search for ".text" section
    If cName = 50023612.1134@ Then
      CopyMemory pStartScan, ByVal pSection + &HC, 4
      CopyMemory pEndScan, ByVal pSection + &H8, 4
      pStartScan = pStartScan + hVbe
      pEndScan = pEndScan + pStartScan - 1
      Exit For
    End If
    pSection = pSection + &H28
  Next
  If pStartScan = 0 Or pEndScan = 0 Then Exit Function
  '// 2. Search for Proc/MethCallEngine thunk template
  '// A1 YY YY YY YY 0B C0 74 13 B8 XX XX XX XX FF D0
  '// 83 F8 02 74 07 B8 11 11 11 11 FF E0 33 C0 C2 11
  '// 11
  '// XX XX XX XX - EbMode
  '// Setup template
  CopyMemory bTemplate(&H0), 841273619855599.2225@, 8
  CopyMemory bTemplate(&H8), -338698839475927.6525@, 8
  CopyMemory bTemplate(&H10), 122996651539948.9667@, 8
  CopyMemory bTemplate(&H18), 127979657317731.9697@, 8
  CopyMemory bTemplate(&H20), 0.0017@, 8
  '// Setup mask
  For lIndex = 0 To UBound(bMask)
    Select Case lIndex
    Case 1 To 4, 10 To 13, 33 To 40: bMask(lIndex) = 0
    Case Else: bMask(lIndex) = 1
    End Select
  Next
  '// Map array to data
  With tSAMap
    .cbElements = 1
    .cDims = 1
    .fFeatures = FADF_AUTO
    .Bounds.cElements = CLng(pEndScan - pStartScan) + 1
    .pvData = pStartScan
  End With
  DupArray bData, VarPtr(tSAMap)
  lIndex = FindSignature(bData(), bTemplate(), bMask())
  DupArray bData, 0@
  If lIndex = -1 Then Exit Function
  CopyMemory SearchEbMode, ByVal pStartScan + lIndex + &HA, Len(SearchEbMode)
  #Else
  SearchEbMode = GetProcAddress(hVbe, "EbMode")
  #End If
End Function

' // Create 32 bit thunk

Private Function Create32BitThunk() As LongPtr
  Dim pCode           As LongPtr
  Dim pfnKillTimer    As LongPtr
  Dim pfnTimerProc    As LongPtr
  Dim pVtbl           As LongPtr
  Dim hUser32         As LongPtr
  Dim bIsInIDE        As Boolean
  Dim llThunk(8)      As Currency
  #If Not (-VBA6 Or -VBA7) Then
  Debug.Assert MakeTrue(bIsInIDE)
  #Else
  bIsInIDE = True
  #End If
  If m_hCodeHeap = 0 Then Exit Function
  '// Get TimerProc address
  CopyMemory pVtbl, ByVal ObjPtr(Me), Len(pVtbl)
  CopyMemory pfnTimerProc, ByVal pVtbl + (TIMERPROC_INDEX + 7) * Len(pfnTimerProc), Len(pfnTimerProc)
  If bIsInIDE Then
    hUser32 = GetModuleHandle(StrPtr("user32"))
    If hUser32 = 0 Then
      hUser32 = LoadLibrary(StrPtr("user32"))
      If hUser32 = 0 Then Exit Function
    End If
    pfnKillTimer = GetProcAddress(hUser32, "KillTimer")
    If pfnKillTimer = 0 Then Exit Function
    pCode = HeapAlloc(m_hCodeHeap, HEAP_NO_SERIALIZE Or HEAP_ZERO_MEMORY, &H48)
    If pCode = 0 Then Exit Function
    pCode = pCode + 4   ' // Disable
    '// E8 00 00 00 00 85 C0 74 06 3C 01 74 16 EB 32 FF
    '// 0D 00 00 00 00 68 00 00 00 00 6A 00 E8 3A 10 00
    '// 00 EB 1E 6A 00 54 FF 74 24 18 FF 74 24 18 FF 74
    '// 24 18 FF 74 24 18 68 00 00 00 00 E8 00 00 00 00
    '// 58 C2 10 00
    llThunk(0) = 841287033897458.0968@
    llThunk(1) = -5772536353434.9306@
    llThunk(2) = 11434920928.8717@
    llThunk(3) = 456836774114.0992@
    llThunk(4) = 843054938821800.2176@
    llThunk(5) = 843048357232162.2052@
    llThunk(6) = 2929994243867.242@
    llThunk(7) = 389231.4112@
    llThunk(8) = 109.8328@
    CopyMemory ByVal pCode, llThunk(0), &H44
    CopyMemory ByVal pCode + 1, m_pEbMode - (pCode + 5), Len(m_pEbMode)
    CopyMemory ByVal pCode + &H11, pCode - 4, Len(pCode)
    CopyMemory ByVal pCode + &H1D, pfnKillTimer - (pCode + &H1C + 5), Len(pfnKillTimer)
    CopyMemory ByVal pCode + &H37, ObjPtr(Me), Len(pCode)
    CopyMemory ByVal pCode + &H3C, pfnTimerProc - (pCode + &H3B + 5), Len(pfnTimerProc)
  Else
    pCode = HeapAlloc(m_hCodeHeap, HEAP_NO_SERIALIZE Or HEAP_ZERO_MEMORY, &H29)
    If pCode = 0 Then Exit Function
    pCode = pCode + 4   ' // Disable
    llThunk(0) = -6526210967837.071@
    llThunk(1) = -6526210968229.3644@
    llThunk(2) = 174641.266@
    llThunk(3) = 120762440711195.876@
    CopyMemory ByVal pCode, llThunk(0), &H25
    CopyMemory ByVal pCode + &H14, ObjPtr(Me), Len(pCode)
    CopyMemory ByVal pCode + &H19, pfnTimerProc - (pCode + &H18 + 5), Len(pfnTimerProc)
  End If
  Create32BitThunk = pCode
End Function

#End If

'//TiÌm kiêìm chýÞ kyì bãÌng Mask
Private Function FindSignature(ByRef bData() As Byte, ByRef bSignature() As Byte, ByRef bMask() As Byte) As Long
  Dim lDataIndex  As Long
  Dim lSignIndex  As Long
  lDataIndex = 0: lSignIndex = 0
  Do While lDataIndex <= UBound(bData)
    If bData(lDataIndex) = bSignature(lSignIndex) Or bMask(lSignIndex) = 0 Then
      lSignIndex = lSignIndex + 1
      If lSignIndex > UBound(bSignature) Then
        FindSignature = lDataIndex - UBound(bSignature)
        Exit Function
      End If
    Else
      If lSignIndex Then
        lDataIndex = lDataIndex - lSignIndex + 1
        lSignIndex = 0
      End If
    End If
    lDataIndex = lDataIndex + 1
  Loop
  FindSignature = -1
End Function

' // Nhâòn heap cho asm thunks
'/ / Lõìp lýu nó vào biêìn env toàn cuòc
Private Function GetCodeHeap() As LongPtr
  Dim sHeapHandleString   As String
  Dim lIndex              As Long
  If m_hCodeHeap Then GetCodeHeap = m_hCodeHeap:       Exit Function
  sHeapHandleString = Space$(Len(GetCodeHeap) * 2)
  If GetEnvironmentVariable(StrPtr(HEAP_ENV_VARIABLE), StrPtr(sHeapHandleString), LenB(sHeapHandleString)) Then
    #If VBA7 Then
    m_hCodeHeap = CLngPtr("&H" & sHeapHandleString)
    #Else
    m_hCodeHeap = CLng("&H" & sHeapHandleString)
    #End If
    GetCodeHeap = m_hCodeHeap
    Exit Function
  End If
  m_hCodeHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE Or HEAP_NO_SERIALIZE, 0, 0)
  If m_hCodeHeap = 0 Then Exit Function
  sHeapHandleString = Hex$(m_hCodeHeap)
  For lIndex = Len(sHeapHandleString) + 1 To Len(GetCodeHeap) * 2
    sHeapHandleString = "0" & sHeapHandleString
  Next
  SetEnvironmentVariable StrPtr(HEAP_ENV_VARIABLE), StrPtr(sHeapHandleString)
  GetCodeHeap = m_hCodeHeap
End Function


'/ / Trích xuâìt hàm EbMode týÌ thunks trýõìc ðó
Private Function GetEbModeFromThunks() As LongPtr
  Dim tEntry  As PROCESS_HEAP_ENTRY
  If m_hCodeHeap = 0 Then Exit Function
  HeapLock m_hCodeHeap
  Do While HeapWalk(m_hCodeHeap, tEntry)
    #If -VBA7 And -Win64 Then
    If tEntry.wFlags And PROCESS_HEAP_ENTRY_BUSY And tEntry.cbData >= &H1E Then
      CopyMemory GetEbModeFromThunks, ByVal tEntry.lpData + &H1E, Len(GetEbModeFromThunks)
    #Else
    If tEntry.wFlags And PROCESS_HEAP_ENTRY_BUSY And tEntry.cbData >= &H1E Then
      CopyMemory GetEbModeFromThunks, ByVal tEntry.lpData + &H5, Len(GetEbModeFromThunks)
      GetEbModeFromThunks = GetEbModeFromThunks + (tEntry.lpData + &H4) + 5
    #End If
      Exit Do
    End If
  Loop
  HeapUnlock m_hCodeHeap
End Function

' // KiêÒm tra xem có thunks nào không hoaòt ðôòng không và giaÒi phóng chúng
' // TraÒ vêÌ sôì thunk ðang hoaòt ðôòng
Private Function CleanupThunks() As Long
  Dim tEntry      As PROCESS_HEAP_ENTRY
  Dim lDisable    As Long
  Dim lCount      As Long
  Dim pThunk      As LongPtr
  If m_hCodeHeap = 0 Then Exit Function
  HeapLock m_hCodeHeap
  Do While HeapWalk(m_hCodeHeap, tEntry)
    If pThunk Then HeapFree m_hCodeHeap, HEAP_NO_SERIALIZE, pThunk: pThunk = 0
    If tEntry.wFlags And PROCESS_HEAP_ENTRY_BUSY And tEntry.cbData >= Len(lDisable) Then
      '// Check if disabled
      CopyMemory lDisable, ByVal tEntry.lpData, Len(lDisable)
      If lDisable Then pThunk = tEntry.lpData Else lCount = lCount + 1
    End If
  Loop
  If pThunk Then HeapFree m_hCodeHeap, HEAP_NO_SERIALIZE, pThunk
  HeapUnlock m_hCodeHeap
  CleanupThunks = lCount
End Function

Private Sub Class_Terminate()
  If m_lIdEvent Then
    KillTimer 0, m_lIdEvent
    m_lIdEvent = 0
  End If
  If m_pAsmThunk Then
    HeapFree m_hCodeHeap, HEAP_NO_SERIALIZE, m_pAsmThunk - 4
    m_pAsmThunk = 0
  End If
  If CleanupThunks() = 0 Then
    HeapDestroy m_hCodeHeap
    m_hCodeHeap = 0
    SetEnvironmentVariable StrPtr(HEAP_ENV_VARIABLE), 0
  End If
End Sub

#If Not (-VBA6 Or -VBA7) Then
Private Function MakeTrue(ByRef bValue As Boolean) As Boolean: bValue = True: MakeTrue = True: End Function
#End If
 
Upvote 0

Chi tiết API khai báo cao siêu hay cấp thấp ở link sau

giới thiệu cho VBA và VB6 link sau

Copy ở đâu thì cũng nên tôn trọng tác giả một chút
 
Lần chỉnh sửa cuối:
Upvote 0
Cứ thử đi thử lại nhiều lần. Kinh nghiệm sẽ dạy cho biết
Cách đây vài ngày tôi cũng nói vậy, lúc xin form hoành tráng của ongke
Bạn có khuynh hướng giống nhiều người xin code ở đây. Đã không tự viết code được mà còn đòi "tối ưu". Đòi vậy tưởng là hoành tráng, nhưng gặp thằng cắc cớ nó hỏi: "chỗ này làm gì vậy?" thì muối mặt.
Bên chủ đề Alt + x không chạy cũng tình trạng này. Toàn code sao chép chắp vá mà xài đồ cao siêu để ẩn title, không biết khi nào sử dụng sự kiện nào, lỗi thì chỉ khóc chứ không biết sửa.
 
Upvote 0
Tôn trọng tác giả ở đây này mấy 3, The trick chính là nickname của lập trình viên VB6 có tiếng trên vbforum.

Tôi đâu có để là "The Sanbi"

JavaScript:
' //
' // 64/32 bit timer class for VBA
' // by The trick 2019
' //
 
Upvote 0
Mò đâu ra được cái link cũng phô ra cho được cái "Bông hoa lá cành".

Sao không bỏ thời gian đi tìm cái link tinh hoa lập trình VB hội tụ tại một bài viết này này:
 
Upvote 0
Toàn API RÁC bày đặt...................VBA lỗi thời và ọp ẹp cứ làm ra vẻ cao siêu
 
Upvote 0
Thay vì thời gian bỏ ra "Màu mè" như vậy ta đi tìm những thứ trợ giúp bài viết kiểu như thế này. Hơi sức đâu đi làm "Anh hùng cứu thế giới" ghê gớm vậy.


Ví dụ một ListView lập trình API của ông Raul388 này này:

HeaderMenu.JPG

ActiveColumn.JPG

ImplementControlColumn.PNG
 

File đính kèm

Upvote 0
Nên dẫn các bạn thích lập trình đi vào chuyên nghiệp sớm anh @Nguyễn Duy Tuân, nếu như đang tuổi 23 hiểu sớm còn hơn chờ 30 mới biết "chuyện". ...

Mình đồng tình việc lập trình nên hướng dần đến tính chuyên nghiệp. Chuyên nghiệp nó thể hiện từ rất nhiều khía cạnh trong lập trình từ việc trình giao diện làm sao, format code như thế nào, tổ chức code, đặt tên,.... ti tỉ thứ mà người lập trình cần có nhiều thời gian học dần. Lập trình API để tạo ra control người lập trình cần có trình độ cao vượt bậc chứ không phải bình thường. Những bạn đam mê lập trình và muốn chinh phục lập trình API để tạo control thì cứ thong thả nghiền ngẫm lâu dài chứ không dễ ăn đâu.

Tiếp nối nội dung mình trình bày ở bài trước thì mình thêm ý kiến về việc lựa chọn control nào cho phần mềm của bạn.
Nếu bạn lựa chọn ListBox trong MSForms thì ta không bàn tiếp nữa. Còn nếu vì cần phải dùng controls ngoài để đáp ứng giao diện ứng dụng bạn phải lựa chọn control ngoài thì cần xem xét:
+ Nếu bạn chưa đạt đến trình độ cao siêu về API thì nên lựa chọn đồ có sẵn, đó là các activex controls. Bạn chỉ cần học cách đẩy dữ liệu vào, đưa code tương tác vào các sự kiện của control là xong. Dành thời gian vào code nghiệp vụ, các kỹ thuật thuộc về control đã có nhà phát triển làm. Việc đăng ký OCX khi chạy ở máy khác là việc rất bình thường. Khi tạo phần mềm mà bạn muốn phân phối tới người khác sử dụng dễ dàng bạn nên học tạo bộ Setup để tự động hóa việc đăng ký.

+ Nếu bạn muốn file của mình có mã nguồn tạo control 100%, - không dùng activex controls thì bạn phải rất cẩn thận. Lập trình API tạo controls chạy trong VBA là rất khó, bạn không thể bê nguyên code trong VB6 sang, bạn cũng không thể dùng code từ đời Office 2007 trở về trước vì nó hoàn toàn viết cho 32-bit. Từ Office 2010 trở lại đây có hai phiên bản 32 và 64-bit nên các code cũ chưa được nâng cấp phần lớn lỗi với 64-bit. Các bạn không thuộc chuyên gia về API thì không tự sửa được đâu. Vậy nếu bạn xác định dùng mã nguồn loại này thì bạn cần phải có chỗ dựa đó là một ai đó đủ khả năng hỗ trợ bạn sửa code để control chạy ngon lành nếu không là đứt gánh giữa đường.
 
Upvote 0
Cái nào người viết code VÀ người nhập code vào file cho người dùng có đủ tự tin để giải thích chỉ dẫn cho người dùng và biết nhận thức những biến cố ngoài dự tính và debug được thì là cái nên dùng.

Ở trình độ thớt (lời thật mất lòng) những cái bàn về phần mềm cao siêu lắm. Thớt có học hôm nay thì cũng vài tuần là quên hết. Bắt buộc phải trải kinh nghiệm thôi.

Mấy thằng "Lập Trình Viên nổi tiếng" khó chịu lắm. Bảo chúng fill cái metrics để mình xem có thể áp dụng được cho đồ án, chúng nhăn như khỉ đột. Hầu hết các trường hợp mình phải nhắc lại "tôi không chú tâm lắm về nghề code của anh/chị. Đó là công việc của người tuyển dụng. Cái tôi chú trọng là sản phẩm của anh/chị có bảo đảm là thích hợp cho đồ án của tôi không? cái metrics tôi đưa ra là mục đích ấy"
 
Lần chỉnh sửa cuối:
Upvote 0
@Nguyễn Duy Tuân anh nói VBA khó viết API, làm các bạn mới học VBA sợ run tay chân hết.
Dễ như ăn một miếng bánh nhưng "bánh API hơi to hơi cứng hơi khô" một xíu thôi.
Học API chịu đọc, chịu tìm hiểu, chịu khó, chịu thiệt, chịu suy tư, suy nghĩ, suy ngẫm, chịu vận động não bộ, chịu ngồi vào máy tính là có thể thành công.


Có thành công nào mà thiếu đi nỗ lực. Nếu các bạn không tin thì VBA mình xuất phát từ con số 0.

Học ở người chửi, đánh mình càng nhớ lâu, thấm sâu.
Học ở người ghanh ghét, ghanh đua càng chạy nhanh.
Học ở người nhân cách lớn càng mạnh mẽ, hùng dũng.
Học ở người trí tuệ lớn càng thông minh, hoàn thiện.
 
Upvote 0
Tưởng khoe cái gì hoá ra VB6 ... vãi kinh hồn xem xong mút được gì từ mã đó

Tôi chơi VB6 gần 10 na9m nay trên máy có tầm 20 GB mã chọn lọc các kiểu ... đầy ra còn của ai cái đó thì cái biết tác giả cái không

Trong cái ucListView nó có khoãng 4600 dòng code à

1705495820471.png

Mã nguồn VB6, ASM ... của "The trick" trên máy của tôi có trên 5 GB khoãng trên 200 dự án code mẫu gì đó

Nó tham gia nhiều Web Quốc tế ... đọc xem


Thong thả dò đi thấy vài web nữa ... bày đặt khoe VB6 :p ... khoãng vài năm trước thì không khoe . tầm này họ đang từ bỏ dần hết rồi lại lôi ra khoe

xem đi sẽ thấy đầy mã VB6 đỉnh cao của chóp thôi rồi tự thấy mình là ai à --=0--=0--=0 xong lên mấy Web đó nổ siêu sọt rác xem sao ?

vào link sau mà xem cái AddIns cho VB6 nó khoãng 16 ngàn dòng code và mã ASM thôi
 
Lần chỉnh sửa cuối:
Upvote 0
ai đó tò mò có thể tham khảo thêm cách họ sử dụng HTMLGrid tạo lưới xem dữ liệu

mã nguồn sau của tay code quốc tịch Đức viết ... có trên máy tôi vài năm trước .... Tôi Copy úp lại trên đây

1705548963591.png

Nếu có khả năng hack thì vào link sau bà tám với tay hacker Nga ngố và The Trick ...

Thong thả vươn xa ra các Web quốc tế bà tám xem rồi tự biết khả năng code két của chính mình là gì thôi ?!!!

 

File đính kèm

Upvote 0
Theo tôi mọi người không nên share mã tạo controls trong VB6 vào đây vì VBA không thể dùng nó.
 
Upvote 0
Tôi cũng không muốn share mã tạo controls trong VB6 làm gì vì nó cổ rồi và không còn phù hợp với Office 64 bít nữa ...

họ khoe thì Tôi úp cho tham khảo đơn giản mà không ôm mớ API RÁC ...thôi chứ không mang lại giá trị gì cả khi tái sử dụng nó cho VBA

Với lại nhiều API sử dụng tốt trên VB6 nhưng đó là API cũ và có nhiều hàm không còn sử dụng tốt trên Office x64 và Windows 11

nên cũng không cần thiết tái sử dụng nó làm gì cho mất thời gian vô tích sự
 
Lần chỉnh sửa cuối:
Upvote 0
Tính ra đọc mấy bài viết gần đây thấy nhiều cái hài ghê :D .
Không biết tự khi nào, thế giới đã tồn tại kiểu người như thế này và có thể bạn đã gặp:

Người đó mới đi du lịch một vài quốc gia mà tự lên mặt rằng đã hiểu hết toàn bộ thế giới.

Người đó chỉ đọc có vài quyển sách đã bắt đầu đi dạy đời người khác như thể mình biết hết chữ nghĩa trên đời này vậy.
Bởi vậy..
Shakespeare từng nói: "Kẻ ngu cho rằng mình khôn, nhưng người khôn tự biết mình khôn." Nhiều khi sự khoe khoang của bạn chẳng là gì trong mắt người khác, mà ngược lại, họ cảm thấy bạn như đang làm trò hề vậy.

- Mình mới lên vài trang web quốc tế (và bị banned nick :D:D) thì lại nghĩ nhưng người khác yếu kém hơn mình, không vươn tầm thế giới. Với đầu óc hạn hẹp của hắn ta, đâu biết rằng diễn đàn này có rất nhiều người là thành viên, thường xuyên đọc các trang như: stackoverflow, github, codeproject, reddit, medium, W3Schools, sqlservercentral... (chắc là đọc không cần phải qua google dịch rồi).
- Có cả kho code, thượng vàng hạ cám đều có hết (đôi khi hắn không biết đâu là vàng đâu là cám mới chết), nhưng cái bi kịch là cả chục năm không tự viết ra được cái gì có ích mặc dù cái đơn giản nhất, có thể gọi là "xài" được.
- À còn một cái bi kịch nữa tôi chắc bà con trên đây đều biết đó là: "Tâm lý của kẻ thua cuộc". Người này thường sẽ có thói quen hạ thấp, chê bai những công việc, sản phẩm của người khác để nâng mình lên, để mọi người chú ý tới mình hơn nhưng không ngờ càng làm mọi người càng buồn cười và càng "chán không thèm nói" :D:D .
Thôi không nói nhiều nữa sợ nói nhiều người ta đọc cũng không hiểu...-0-0-0-
 
Upvote 0
Bu lại xong trầu dìa và trỏ mõm là giỏi thôi ... Tôi bị hack mất đầy nick vào thời điểm bị virus mã hoá máy tính

Không phải cứ mất nick là xấu ... ngu mới hiểu như vậy

1705582745416.png
 
Upvote 0
Việc chọn ListView (control trong MSCOMCTL.OCX) hay ListBox trong MSForms thì cần xem nhu cầu thực sự chức năng mà mình thiết kế. Mỗi cái có ưu điểm nổi bật riêng:
ListView của MS
- Chỉ chạy trong môi trường 32-bit. Nếu ứng dụng bạn viết không khắt khe về môi trường, người dùng chấp nhận chỉ cài Office 32-bit thì điều này chấp nhận được.
- Không hỗ trợ unicode. Về khoản này thì điểm trừ nhiều nhất với ứng dụng dùng font unicode.
- Tùy biến hiển thị (định dạng font, màu sắc, hình ảnh giữa các dòng) gần giống với cách hiển thị của Windows Explorer (cũ). Trình độ lập trình càng cao thì càng có khả năng tùy biến hiển thị nó phong phú.

ListBox trong MSForms
- Là control thuộc MSForms được cài đặt kèm theo bộ Office nên đương nhiên hỗ trợ cả 32 và 64-bit.
- Hỗ trợ unicode
- Với số lượng dữ liệu khá lớn tốc độ load nhanh.
- Hạn chế duy nhất là hiển thị rất giản đơn, không tùy biến định dạng màu sắc, font các dòng, không đính kèm hình ảnh được.
Ngoài những vấn đề anh Tuân nói thì ListBox có ưu điểm load dữ liệu theo nhiều cách để nhanh hơn rất nhiều so với ListView, thay vì cả 2 đều có thể dùng phương thức AdItem, nhưng ListBox còn có thuộc tính RowSource, thuộc tính List và thuộc tính Column để load dữ liệu. Trong khi nếu AdItem thì dữ liệu càng nhiều thì dùng vòng lặp càng chết thời gian.
 
Upvote 0
Ngoài những vấn đề anh Tuân nói thì ListBox có ưu điểm load dữ liệu theo nhiều cách để nhanh hơn rất nhiều so với ListView, thay vì cả 2 đều có thể dùng phương thức AdItem, nhưng ListBox còn có thuộc tính RowSource, thuộc tính List và thuộc tính Column để load dữ liệu. Trong khi nếu AdItem thì dữ liệu càng nhiều thì dùng vòng lặp càng chết thời gian.
chính xác như vậy ListBox chạy rất nhanh ... hãy thử dữ liệu nhiều nhất có thể là thấy ngay thôi
 
Upvote 0
Upvote 0
Tính ra đọc mấy bài viết gần đây thấy nhiều cái hài ghê :D .
<quote 1/>
Bởi vậy..
<quote 2/>
Mấy cái này bạn quote ở đâu vậy:
Quote 1: người viết cố tình chửi đạo giáo. Cả Giê-su lẫn Si-Đạt-đa đâu có ai đọc nhiều sách hay đi cũng thế giới đâu?
Quote 2: Shakespeare có nghề bẻ chữ. Người viết cũng là người tự mình diễn giải lời "danh nhân" thôi.
 
Upvote 0
Mấy cái này bạn quote ở đâu vậy:
Quote 1: người viết cố tình chửi đạo giáo. Cả Giê-su lẫn Si-Đạt-đa đâu có ai đọc nhiều sách hay đi cũng thế giới đâu?
Quote 2: Shakespeare có nghề bẻ chữ. Người viết cũng là người tự mình diễn giải lời "danh nhân" thôi.
:D Bác suy diễn ra xa quá rồi. Những nhân vật như bác nói cả thế giới có được mấy người mà người viết dám nói tới họ bác. À mà có khi diễn đàn này lại có một...
 
Upvote 0
Bác @SA_DQ là ông già khựa hay sao mà ai cũng hay nhắc

Do bác này hay reaction bài viết em, nên em bực mình đã dùng công nghệ để ẩn reactionsList của diễn đàn. Nhìn bác đưa bàn tay ok là thấy móng tay bác luôn, chán. Thấy bắt ghê, móng toàn "vi khuẩn thời tiền sử".

Bài của anh Tuân có mấy thành viên reaction, giờ đã không thấy nữa:
1705595662814.png


Lỡ tay làm sao không biết, ẩn mất luôn cái nút "Show ignore content", nên các bài viết "mấy nhân vật vip" cũng ẩn mất tiêu. Giờ chẳng làm cách nào đọc được.
 
Lần chỉnh sửa cuối:
Upvote 0
Bác @SA_DQ là ông già khựa hay sao mà ai cũng hay nhắc
Mình chưa có bài nào tham gia trong chủ đề này kia mà, Hay bài mình đăng ở đây đã bị xóa rồ?

(/ề chủ đề này mình chắc là không thể & không có khả năng tham gia rồi!

Mong mọi người chừa mình ra đi nha!
 
Upvote 0
À quên, ListView còn có một vài cái hay như có thể Sort dữ liệu, có thể Find dữ liệu, thêm icon.
đúng vậy ListView trên VB, VB6 hay Delphi cơ bản nó như nhau. Nhưng khác nhau khi viết trên các ngôn ngữ lập trình hiện đại hiện đang phát triển thì nó hổ trợ tốt hơn như viết tiếng Việt có dấu trực tiếp trong Code mà không cần viết hàm tuỳ chỉnh xử lý Unicode nữa

Tôi khuyên thật

1/ nên cố giắng tập viết và sử dụng trên VBA ( nếu chưa biết ngôn ngữ khác ) Vì quá trình viết vừa tìm tòi khám phá và khai thác ra nhiều cái hay trong đó mà mình có thể làm chủ được nó

2/ nếu biết ngôn ngữ khác VD: Delphi thì mọi cái có sẳn chỉ kéo vào sử dụng thiết kế cái Form xong tuỳ chỉnh theo ý thích nếu có khả năng

3/ Hết cách cả dùng đồ của bên thứ 3 vì ta lệ thuộc nó và sẽ lỗi theo thời gian . khi bị lỗi ngộ nhỡ họ đi pháp rồi thì sao ta lại làm lại từ đầu

4/ trừ ai đó chưa có khả năng tuỳ chỉnh ở mức thuần VBA thì mới nên sử dụng đồ của bên thứ 3...

xem hình sau tôi mới thử dò trên Delphi

1705623628667.png


mấy năm trước tôi Mê API của Ms trên Delphi vì mọi cái do các kỹ sư Delphi viết cho sẳn còn ta chỉ call và tuỳ chỉnh Builder 32 hay 64 bit
Nhưng khi sử dụng trên Windows10 thì tốt ... vừa rồi tôi cài Windows11 thì có hàm báo lỗi nhiều khi cũng không biết tại sao

chỉ đoán thôi vì sử dụng API cũ khi trên Windows 11 thì Ms có cập nhật các API mới nên nó lỗi. vì vậy khi code can thiệp API sâu vào hệ thống Windows thì nó sẻ lỗi theo thời gian vì ta chưa cập nhật hay điều chỉnh kịp .... vì vậy nên tôi mới nói ngộ nhỡ dùng hàng của bên thứ 3 lệ thuộc nó xong họ đi pháp thì sao !? ( Không chắc chắn nha = hên/xui --=0--=0--=0 )

Tốt nhất nên độc lập tự chủ mà viết cho dù = 1/10 của ai đó thì mình cũng từng bước làm chủ nó xong mới bước kế tiếp cao hơn

Trừ khi không có khả năng trên thì nên dùng đồ của bên Thứ 3 !!! thay vì tự khai báo API tái sử dụng trên hệ thống VBA lỗi thời, tù túng và ọp ẹp
 
Lần chỉnh sửa cuối:
Upvote 0
Theo tôi mọi người không nên share mã tạo controls trong VB6 vào đây vì VBA không thể dùng nó.
Không biết anh dựa vào cơ sở nào hay nội quy diễn đàn để nói điều này.

Chứ em thấy bài viết đăng ở mục Lập trình với Excel, VB6 có tạo các OCX hoặc dll cho Excel, không chỉ riêng VBA, mọi người có thể đăng mã Python, C# hay C++ mà mã đó có thể ứng dụng cho Excel.

VB6 hiện nay có thể sớm có công cụ chuyển mã thành 64bit, để chạy tốt trên nhiều nền tảng.

Microsoft hứa là vẫn sẽ còn hỗ trợ VB kể cả Window 11, cũng có thể là Window 12, nên không có gì là không nên chia sẻ ở mục bài viết này.
 
Upvote 0
Theo tôi mọi người không nên share mã tạo controls trong VB6 vào đây vì VBA không thể dùng nó.
Không biết anh dựa vào cơ sở nào hay nội quy diễn đàn để nói điều này.

Chứ em thấy bài viết đăng ở mục Lập trình với Excel, VB6 có tạo các OCX hoặc dll cho Excel, không chỉ riêng VBA, mọi người có thể đăng mã Python, C# hay C++ mà mã đó có thể ứng dụng cho Excel.

VB6 hiện nay có thể sớm có công cụ chuyển mã thành 64bit, để chạy tốt trên nhiều nền tảng.

Microsoft hứa là vẫn sẽ còn hỗ trợ VB kể cả Window 11, cũng có thể là Window 12, nên không có gì là không nên chia sẻ ở mục bài viết này.

Thực tế mình rất thích VB6 vì lập trình rất dễ, nó và VBA có quan hệ anh em, nhiều code có thể bê nguyên từ VB6 sang VBA dùng nên dân lập trình VBA hoàn toàn có thể dựa vào code VB6 để thừa kế nhưng không phải tạo control từ thành phần "UserControl". Bản thân mình vẫn có các dự án viết bằng VB6 còn phải bảo trì. Chỉ mong Microsoft support, nâng cấp lên hay công ty nào đó mua lại VB6 mà phát triển nó lên thôi. Nói vậy để bạn hay ai đó biết mình không phải dị ứng VB6 vì nó cũ kỹ. Lý do ở đây là không phù hợp với chủ đề bài viết này hoặc nó còn rất nan giải , qua nhiều bước mà người chia sẻ code (của tây) mới đang chỉ để lửng lơ chưa áp dụng được trong VBA.

Bài viết trước tôi viết "Theo tôi mọi người không nên share mã tạo controls trong VB6 vào đây vì VBA không thể dùng nó.". Không phải mình dựa vào nội quy nào của diễn đàn, vì:

+ Cả hai bài share của hai người về control unListView, HTMLGrid đều nguyên bản code VB6, họ sử dụng thành phần "UserControl" để tạo control. Trong VBA không có thành phần này vì vậy không thể bê nguyên code đó sang được.

ucListViewDemo.jpg

htmlgriddemo.jpg

+ Có rất nhiều diễn đàn chuyên về VB6 cả Việt Nam lẫn tây chia sẻ rất nhiều mã nguồn VB6, nếu ai cũng bê đồ VB6 từ đông tây share lại (không chế biến về VBA) thì thực sự sẽ làm nhiều người không biết làm thế nào để chạy trong VBA. Chúng ta biết đây là "Diễn đàn Excel" vì thể những thứ chia sẻ dùng ngôn ngữ lập trình gì, công cụ gì, trong một chủ đề cụ thể về VBA thì ta nên share cái mà người ta có khả năng ứng dụng trực tiếp hoặc chia sẻ cách để chuyển đổi để ứng dụng được nó. Nếu các bạn có khả năng và thời gian làm thì các bạn hãy chuyển đổi từ code VB6 sang VBA dù đơn giản để người khác có thể ứng dụng hay học theo, hoặc chuyển sang ocx thì tôi nghĩ rất tốt.
 
Lần chỉnh sửa cuối:
Upvote 0
1/ có lẽ cộng đồng VB6 và tín đồ VB6 đang mòn mõi, hóng hớt và hy vọng ở twinbasic.com tương thích ngược với VB6

2/ Tôi sử dụng Office2021_x64 hết nên không thử HTMLGrid khi viết lại trên VB6 thành HTMLGrid.ocx được

không lẻ xoá Office2021_x64 đi cài lại 32 bít thì thật phí mất thời gian không đáng phải phí hay sao

xong chỉ dò mỗi HTMLGrid để tái sử dụng cho 32 bit :p
 
Upvote 0
@Nguyễn Duy Tuân

Trong VBA có thể lập trình API cửa sổ (Window), các API như Timer, SubClassing, WindowHook, hoặc thư viện như UxTheme Window, GDI, GDIPlus, ..., dựa vào đó sẽ tạo được chức năng tương tự UserControl VB6, và có thể tạo ra controls "ngầu" hơn nhiều theo tư duy và sáng tạo của người phát triển, tất cả VBA đều làm được nhưng cách tiếp cận là tạo mới mã nguồn. VBA không thể tạo ra các Properties vào khung lập trình, nhưng ta có thể tạo chúng với cách riêng.
 
Upvote 0
@Nguyễn Duy Tuân

Trong VBA có thể lập trình API cửa sổ (Window), các API như Timer, SubClassing, WindowHook, hoặc thư viện như UxTheme Window, GDI, GDIPlus, ..., dựa vào đó sẽ tạo được chức năng tương tự UserControl VB6, và có thể tạo ra controls "ngầu" hơn nhiều theo tư duy và sáng tạo của người phát triển, tất cả VBA đều làm được nhưng cách tiếp cận là tạo mới mã nguồn. VBA không thể tạo ra các Properties vào khung lập trình, nhưng ta có thể tạo chúng với cách riêng.

Mình hoàn toàn hiểu và biết tính khả thi đó. Với API ta hoàn toàn tạo được control bằng code. Mình từng có thời gian thử làm những thứ mà không phụ thuộc vào VBA cung cấp rồi, từng tạo cửa sổ Window cùng các controls (Label, Edit, Button) không cần Userform; Tạo Unicode Menu In Userform.

1/ có lẽ cộng đồng VB6 và tín đồ VB6 đang mòn mõi, hóng hớt và hy vọng ở twinbasic.com tương thích ngược với VB6

2/ Tôi sử dụng Office2021_x64 hết nên không thử HTMLGrid khi viết lại trên VB6 thành HTMLGrid.ocx được

không lẻ xoá Office2021_x64 đi cài lại 32 bít thì thật phí mất thời gian không đáng phải phí hay sao

xong chỉ dò mỗi HTMLGrid để tái sử dụng cho 32 bit :p

twinBASIC.jpg

Xem roadmap thì thật tuyệt vời. Có cả lập trình COM, ActiveX thì có thể tạo controls nhúng trong Userform của VBA đó. Năm 2024 có thứ hay để chờ đợi rồi.
 
Upvote 0
Rảnh chơi cho vui tôi mất 10 phút Tách code bài số 28 ra File OCX sử dụng tốt cho Exe

Ai sử dụng Office 32 bit tải về thử xem... cách sử dụng code gần như Form trên VB6

Lần đầu sử dụng phải đăng ký OCX với Windows xong các thao tác khác trên VBA Add OCX vào vào sử dụng xem tình hình sao

Lưu ý OCX viết lại trên VB6 chỉ sử dụng cho 32 bít còn 64 bít là lỗi

Hình Ảnh sử dụng trên Máy tôi OK
1705651047017.png

đăng ký: Kéo File OCX thả vào File Register_ActiveX_OCX_DLL.vbs xong chọn yes là xong
 

File đính kèm

Upvote 0
Tôi mới Mở cái Latop cùi chạy Office 2021_x32 thử thấy chạy tốt đó

Ai thích thử dò xem ... xem hình --=0--=0--=0

Capture.PNG
Bài đã được tự động gộp:

Tôi mới Mở cái Latop cùi chạy Office 2021_x32 thử thấy chạy tốt đó

Ai thích thử dò xem ... xem hình --=0--=0--=0

Capture.PNG

Xem roadmap thì thật tuyệt vời. Có cả lập trình COM, ActiveX thì có thể tạo controls nhúng trong Userform của VBA đó. Năm 2024 có thứ hay để chờ đợi rồi.
Xem link này fafalone là tay code cứng API viết OCX rồi ... nhưng Tôi tải về Lỗi sử dụng trên Office2021_x64

Nói chung còn dài hơi lắm ... Delphi Ổn định mấy chục năm nay rồi và có tên tuổi trên quốc tế có lẻ dùng nó là Tốt nhất

rảnh tham khảo thêm cho vui và biết thôi
 
Upvote 0

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

Back
Top Bottom