Хакер писал(а):Смотря какой.
Хакер писал(а):В контроле предусмотрено.
kuhtiov писал(а):Это реализуется через хитрый класс. Я его как раз сейчас ковыряю.
Option Explicit
' demo project showing how to custom draw single items in a listview
' by Bryan Stafford of New Vision Software® - newvision@imt.net
' this demo is released into the public domain "as is" without
' warranty or guaranty of any kind. In other words, use at
' your own risk.
' See the comments at the end of this module for a brief explaination of
' what subclassing is.
' Generic WM_NOTIFY notification codes for common controls
Public Enum WinNotifications
NM_FIRST = (-0&) ' (0U- 0U) ' // generic to all controls
NM_LAST = (-99&) ' (0U- 99U)
NM_OUTOFMEMORY = (NM_FIRST - 1&)
NM_CLICK = (NM_FIRST - 2&)
NM_DBLCLK = (NM_FIRST - 3&)
NM_RETURN = (NM_FIRST - 4&)
NM_RCLICK = (NM_FIRST - 5&)
NM_RDBLCLK = (NM_FIRST - 6&)
NM_SETFOCUS = (NM_FIRST - 7&)
NM_KILLFOCUS = (NM_FIRST - 8&)
NM_CUSTOMDRAW = (NM_FIRST - 12&)
NM_HOVER = (NM_FIRST - 13&)
End Enum
Public Const WM_NOTIFY As Long = &H4E&
' constants used for customdraw routine
Public Const CDDS_PREPAINT As Long = &H1&
Public Const CDRF_NOTIFYITEMDRAW As Long = &H20&
Public Const CDDS_ITEM As Long = &H10000
Public Const CDDS_ITEMPREPAINT As Long = CDDS_ITEM Or CDDS_PREPAINT
Public Const CDRF_NEWFONT As Long = &H2&
' The NMHDR structure contains information about a notification message. The pointer
' to this structure is specified as the lParam member of a WM_NOTIFY message.
Public Type NMHDR
hWndFrom As Long ' Window handle of control sending message
idFrom As Long ' Identifier of control sending message
code As Long ' Specifies the notification code
End Type
' sub struct of the NMCUSTOMDRAW struct
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
' generic customdraw struct
Public Type NMCUSTOMDRAW
hdr As NMHDR
dwDrawStage As Long
hDC As Long
rc As RECT
dwItemSpec As Long
uItemState As Long
lItemlParam As Long
End Type
' listview specific customdraw struct
Public Type NMLVCUSTOMDRAW
nmcd As NMCUSTOMDRAW
clrText As Long
clrTextBk As Long
' if IE >= 4.0 this member of the struct can be used
iSubItem As Integer
End Type
' function used to manipulate memory data
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes&)
' gdi function used to select bold font into the hDC passed in the prepaint message
Public Declare Function SelectObject Lib "gdi32" (ByVal hDC&, ByVal hObject&) As Long
' handle to the bold font set for the form. this is used to set the bold font for the listview items
Public g_hBoldFont As Long
' this var will hold a pointer to the original message handler so we MUST
' save it so that it can be restored before we exit the app. if we don't
' restore it.... CRASH!!!!
Public g_addProcOld As Long
' function used to call the next window proc in the "chain" for the subclassed window
Public Declare Function CallWindowProc& Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc&, _
ByVal hWnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
'WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
'
' Do NOT try to step through this function in debug mode!!!!
' You WILL crash!!! Also, do NOT set any break points in this function!!!
' You WILL crash!!! Subclassing is non-trivial and should be handled with
' EXTREAME care!!!
'
' There are ways to use a "Debug" dll to allow you to set breakpoints in
' subclassed code in the IDE but this was not implimented for this demo.
'
'WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
' this is *our* implimentation of the message handling routine
' determine which message was recieved
Select Case iMsg
Case WM_NOTIFY
' if it's a WM_NOTIFY message copy the data from the address pointed to
' by lParam into a NMHDR struct
Dim udtNMHDR As NMHDR
CopyMemory udtNMHDR, ByVal lParam, 12&
With udtNMHDR
If .code = NM_CUSTOMDRAW Then
' if the code member of the struct is NM_CUSTOMDRAW, copy the data
' pointed to by lParam into a NMLVCUSTOMDRAW struct
Dim udtNMLVCUSTOMDRAW As NMLVCUSTOMDRAW
' this is now OUR copy of the struct
CopyMemory udtNMLVCUSTOMDRAW, ByVal lParam, Len(udtNMLVCUSTOMDRAW)
With udtNMLVCUSTOMDRAW.nmcd
' determine whether or not this is one of the messages we are interested in
Select Case .dwDrawStage
' if it's a prepaint message, tell windows WE want first dibs
' on painting for each item and then exit without letting VB get this message
Case CDDS_PREPAINT
WindowProc = CDRF_NOTIFYITEMDRAW
Exit Function
' if it's time to paint an item, check to see if it's divisible by 3.
' if it is, select the bold font that we borrowed from the form into the
' hDC of the listview and set the text color to something *different*.
' then tell windows that we changed the font for this item.
Case CDDS_ITEMPREPAINT
If .dwItemSpec = 3 Then
Call SelectObject(.hDC, g_hBoldFont)
' we can also set the color for items in the listview.
' we will set the color for every third item....
'If (.dwItemSpec Mod 9) = 0 Then
udtNMLVCUSTOMDRAW.clrText = RGB(128, 128, 128)
udtNMLVCUSTOMDRAW.clrTextBk = RGB(128, 128, 128)
' copy OUR copy of the struct back to the memory address pointed to by lParam
CopyMemory ByVal lParam, udtNMLVCUSTOMDRAW, Len(udtNMLVCUSTOMDRAW)
'End If
' tell windows that we changed the font and do not allow VB to get this message
WindowProc = CDRF_NEWFONT
Exit Function
End If
End Select
End With
End If
End With
End Select
' pass all messages on to VB and then return the value to windows
WindowProc = CallWindowProc(g_addProcOld, hWnd, iMsg, wParam, lParam)
End Function
' What is subclassing anyway?
'
' Windows runs on "messages". A message is a unique value that, when
' recieved by a window or the operating system, tells either that
' something has happened and that an action of some sort needs to be
' taken. Sort of like your nervous system passing feeling messages
' to your brain and the brain passing movement messages to your body.
'
' So, each window has what's called a message handler. This is a
' function where all of the messages FROM Windows are recieved. Every
' window has one. I mean EVERY window. That means every button, textbox,
' picturebox, form, etc... Windows keeps track of where the message
' handler (called a WindowProc [short for PROCedure]) in a "Class"
' structure associated with each window handle (otherwise known as hWnd).
'
' What happens when a window is subclassed is that you insert a new
' window procedure in line with the original window procedure. In other
' words, Windows sends the messages for the given window to YOUR WindowProc
' FIRST where you are responsible for handling any messages you want to
' handle. Then you MUST pass the remaining messages on to the default
' WindoProc. So it looks like this:
'
' Windows Message Sender --> Your WindowProc --> Default WindowProc
'
' A window can be subclassed MANY times so it could look like this:
'
' Windows Message Sender --> Your WindowProc --> Another WindowProc _
' --> Yet Another WindowProc --> Default WindowProc
'
' You can also change the order of when you respond to a message by
' where in your routine you pass the message on to the default WindowProc.
' Let's say that you want to draw something on the window AFTER the
' default WindowProc handles the WM_PAINT message. This is easily done
' by calling the default proc before you do your drawing. Like so:
'
' Public Function WindowProc(Byval hWnd, Byval etc....)
'
' Select Case iMsg
' Case SOME_MESSAGE
' DoSomeStuff
'
' Case WM_PAINT
' ' pass the message to the defproc FIRST
' WindowProc = CallWindowProc(g_addProcOld, hWnd, iMsg, wParam, lParam)
'
' DoDrawingStuff ' <- do your drawing
'
' Exit Function ' <- exit since we already passed the
' ' measage to the defproc
'
' End Select
'
' ' pass all messages on to VB and then return the value to windows
' WindowProc = CallWindowProc(g_addProcOld, hWnd, iMsg, wParam, lParam)
'
' End Function
'
'
' This is just a basic overview of subclassing but I hope it helps if
' you were fuzzy about the subject before reading this.
'
Option Explicit
' demo project showing how to custom draw single items in a listview
' by Bryan Stafford of New Vision Software® - newvision@imt.net
' this demo is released into the public domain "as is" without
' warranty or guaranty of any kind. In other words, use at
' your own risk.
' constant used to get the address of the window proc for the subclassed window
Private Const GWL_WNDPROC As Long = (-4&)
' API call to alter the class data for this window
Private Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hWnd&, _
ByVal nIndex&, ByVal dwNewLong&)
Private Sub Form_Load()
' we will *borrow* the font from the form since we are not using it.
' set the font attributes we want the custom draw items in the listview to have
' With lvCustomDraw.Font
' .Bold = True
' '.Italic = True
' '.Underline = True
' End With
' grab a handle to the form's font and store it in the global variable
Dim IFont As IFont
Set IFont = lvCustomDraw.Font
g_hBoldFont = IFont.hFont
' fill the listview with some stuff....
With lvCustomDraw
.ColumnHeaders.Add , , "Item Column"
.ColumnHeaders.Add , , "Subitem 1"
.ColumnHeaders.Add , , "Subitem 2"
Dim i&
For i = 1 To 100
With .ListItems.Add(, , "Item " & CStr(i))
.SubItems(1) = "Subitem 1"
.SubItems(2) = "Subitem 2"
End With
Next
End With
' take control of message processing by installing our message handling
' routine into the chain of message routines for this window.
' we subclass the form because wm_notify messages are sent to the parent
' of the control, in this case, the VB form.
g_addProcOld = SetWindowLong(Me.hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Private Sub Form_Unload(Cancel As Integer)
' give message processing control back to VB
' if you don't do this you WILL crash!!!
Call SetWindowLong(hWnd, GWL_WNDPROC, g_addProcOld)
End Sub
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 106