Home All Groups Group Topic Archive Search About

Subclass Help WM_NOTIFY

Author
18 Oct 2005 1:29 PM
Alastair MacFarlane
Dear All,

Can somone suggest why I don't receive a WM_NOTIFY message from a control on
a subclassed form. I am trying to follow up from alpine's suggestion that I
use NM_CUSTOMDRAW. The code is an altered WindowProc is attached (long). Can
somone please suggest on what is going wrong here:

Public Function WindowProc(ByVal hWnd As Long, _
    ByVal uMsg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
   Dim i As Integer
   Dim hCurrFont As Long
   Dim lf As LOGFONT
   Dim lColour As Long
   Dim hOldFont As Long
   Dim tMessage As NMHDR
   Dim tTVMessage As NMTVCUSTOMDRAW
   Dim lCode As Long
   Dim tItem As TV_ITEM
   Dim lRet As Long
   Form1.Label1.Caption = "HERE"
   Select Case msg
       Case WM_NOTIFY
           CopyMemory tMessage, ByVal lParam, Len(tMessage)
           lCode = tMessage.code
           Select Case lCode
               Case NM_CUSTOMDRAW
                   If tMessage.hwndFrom <> TreeView1.hWnd Then
                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
uMsg, wParam, lParam)
                       Exit Function
                   End If
                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
                       Result = CDRF_NOTIFYITEMDRAW
                       Exit Function
                   End If
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
                       CopyMemory tItem, ByVal tTVMessage.nmcmd.lItemLParam,
Len(tItem)
                           hCurrFont =
GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
                           If lRet > 0 Then
                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5), 700,
FW_NORMAL)
                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
False
                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2) 'False
                               lRet = DeleteObject(mlHeaderFont)
                               mlHeaderFont = CreateFontIndirect(lf)
                               hOldFont = SelectObject(tTVMessage.nmcmd.hdc,
mlHeaderFont)
                            End If
                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) * 255)
                       tTVMessage.clrText = lColour
                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
                       Result = CDRF_NEWFONT
                       Exit Function
                   End If
               Case Else
                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
wParam, lParam)
                   Exit Function
           End Select
       Case Else
       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam, lParam)
   End Select
End Function

I have not added all the constants and Types but I can if somone thinks that
it will help. The sub routine is being called but it never receives a
WM_NOTIFY message.

Thanks...

Alastair MacFarlane

Author
18 Oct 2005 1:59 PM
Robert
You omitted the code where the WindowProc is attached to a hWnd. Maybe
you've got the wrong hWnd?

Robert

Show quoteHide quote
"Alastair MacFarlane" <AlastairMacFarl***@discussions.microsoft.com> wrote
in message news:E096BEEB-69A7-49E4-A20F-E21F6DA4DFC0@microsoft.com...
> Dear All,
>
> Can somone suggest why I don't receive a WM_NOTIFY message from a control
on
> a subclassed form. I am trying to follow up from alpine's suggestion that
I
> use NM_CUSTOMDRAW. The code is an altered WindowProc is attached (long).
Can
> somone please suggest on what is going wrong here:
>
> Public Function WindowProc(ByVal hWnd As Long, _
>     ByVal uMsg As Long, _
>     ByVal wParam As Long, _
>     ByVal lParam As Long) As Long
>    Dim i As Integer
>    Dim hCurrFont As Long
>    Dim lf As LOGFONT
>    Dim lColour As Long
>    Dim hOldFont As Long
>    Dim tMessage As NMHDR
>    Dim tTVMessage As NMTVCUSTOMDRAW
>    Dim lCode As Long
>    Dim tItem As TV_ITEM
>    Dim lRet As Long
>    Form1.Label1.Caption = "HERE"
>    Select Case msg
>        Case WM_NOTIFY
>            CopyMemory tMessage, ByVal lParam, Len(tMessage)
>            lCode = tMessage.code
>            Select Case lCode
>                Case NM_CUSTOMDRAW
>                    If tMessage.hwndFrom <> TreeView1.hWnd Then
>                        WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
> uMsg, wParam, lParam)
>                        Exit Function
>                    End If
>                    CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>                    If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>                        Result = CDRF_NOTIFYITEMDRAW
>                        Exit Function
>                    End If
>                    If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT
Then
>                        CopyMemory tItem, ByVal
tTVMessage.nmcmd.lItemLParam,
Show quoteHide quote
> Len(tItem)
>                            hCurrFont =
> GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>                            lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>                            If lRet > 0 Then
>                                lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5),
700,
> FW_NORMAL)
>                                lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>                                lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
> False
>                                lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
'False
>                                lRet = DeleteObject(mlHeaderFont)
>                                mlHeaderFont = CreateFontIndirect(lf)
>                                hOldFont =
SelectObject(tTVMessage.nmcmd.hdc,
Show quoteHide quote
> mlHeaderFont)
>                             End If
>                        lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
255)
>                        tTVMessage.clrText = lColour
>                        CopyMemory ByVal lParam, tTVMessage,
Len(tTVMessage)
>                        Result = CDRF_NEWFONT
>                        Exit Function
>                    End If
>                Case Else
>                    WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
> wParam, lParam)
>                    Exit Function
>            End Select
>        Case Else
>        WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
lParam)
>    End Select
> End Function
>
> I have not added all the constants and Types but I can if somone thinks
that
> it will help. The sub routine is being called but it never receives a
> WM_NOTIFY message.
>
> Thanks...
>
> Alastair MacFarlane
Author
18 Oct 2005 2:12 PM
MikeD
"Alastair MacFarlane" <AlastairMacFarl***@discussions.microsoft.com> wrote
in message news:E096BEEB-69A7-49E4-A20F-E21F6DA4DFC0@microsoft.com...
> Dear All,
>
> Can somone suggest why I don't receive a WM_NOTIFY message from a control
> on
> a subclassed form. I am trying to follow up from alpine's suggestion that
> I
> use NM_CUSTOMDRAW. The code is an altered WindowProc is attached (long).
> Can
> somone please suggest on what is going wrong here:

What are you subclassing? Is it the control or the control's parent?
WM_NOTIFY messages are sent *by* the control *to* its parent.  Therefore,
you need to subclass the control's parent (i.e. the form the control is on).

--
Mike
Microsoft MVP Visual Basic
Author
18 Oct 2005 2:22 PM
alpine
Are you subclassing the treeview's parent window?

HTH,
Bryan
_______________________________
Bryan Stafford
New Vision Software
newvision_don'tspam@mvps.org


On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
<AlastairMacFarl***@discussions.microsoft.com> wrote:

Show quoteHide quote
>Dear All,
>
>Can somone suggest why I don't receive a WM_NOTIFY message from a control on
>a subclassed form. I am trying to follow up from alpine's suggestion that I
>use NM_CUSTOMDRAW. The code is an altered WindowProc is attached (long). Can
>somone please suggest on what is going wrong here:
>
>Public Function WindowProc(ByVal hWnd As Long, _
>    ByVal uMsg As Long, _
>    ByVal wParam As Long, _
>    ByVal lParam As Long) As Long
>   Dim i As Integer
>   Dim hCurrFont As Long
>   Dim lf As LOGFONT
>   Dim lColour As Long
>   Dim hOldFont As Long
>   Dim tMessage As NMHDR
>   Dim tTVMessage As NMTVCUSTOMDRAW
>   Dim lCode As Long
>   Dim tItem As TV_ITEM
>   Dim lRet As Long
>   Form1.Label1.Caption = "HERE"
>   Select Case msg
>       Case WM_NOTIFY
>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>           lCode = tMessage.code
>           Select Case lCode
>               Case NM_CUSTOMDRAW
>                   If tMessage.hwndFrom <> TreeView1.hWnd Then
>                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
>uMsg, wParam, lParam)
>                       Exit Function
>                   End If
>                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>                       Result = CDRF_NOTIFYITEMDRAW
>                       Exit Function
>                   End If
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
>                       CopyMemory tItem, ByVal tTVMessage.nmcmd.lItemLParam,
>Len(tItem)
>                           hCurrFont =
>GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>                           If lRet > 0 Then
>                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5), 700,
>FW_NORMAL)
>                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
>False
>                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2) 'False
>                               lRet = DeleteObject(mlHeaderFont)
>                               mlHeaderFont = CreateFontIndirect(lf)
>                               hOldFont = SelectObject(tTVMessage.nmcmd.hdc,
>mlHeaderFont)
>                            End If
>                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) * 255)
>                       tTVMessage.clrText = lColour
>                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
>                       Result = CDRF_NEWFONT
>                       Exit Function
>                   End If
>               Case Else
>                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
>wParam, lParam)
>                   Exit Function
>           End Select
>       Case Else
>       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam, lParam)
>   End Select
>End Function
>
>I have not added all the constants and Types but I can if somone thinks that
>it will help. The sub routine is being called but it never receives a
>WM_NOTIFY message.
>
>Thanks...
>
>Alastair MacFarlane
Author
18 Oct 2005 2:39 PM
Alastair MacFarlane
Thanks all for your reply. I am running the subclass from the form as follows:

  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
WindowProc)

therefore I presume I am subclassing the treeview control itself.

The full code on the form is as follows:

Option Explicit

Private Const GWL_WNDPROC As Long = (-4&)
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
(ByVal hWnd&, _
     ByVal nIndex&, ByVal dwNewLong&) As Long

Private Sub Form_Load()
   Dim lCount As Long
   With TreeView1.Nodes
       .Add , , "ROOT", "ROOT"
       For lCount = 1 To 25
           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item Number
" & lCount
       Next
   End With
  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
End Sub

Thanks again for your support?

Alastair

Show quoteHide quote
"alpine" wrote:

> Are you subclassing the treeview's parent window?
>
> HTH,
> Bryan
> _______________________________
> Bryan Stafford
> New Vision Software
> newvision_don'tspam@mvps.org
>
>
> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>
> >Dear All,
> >
> >Can somone suggest why I don't receive a WM_NOTIFY message from a control on
Author
18 Oct 2005 3:27 PM
alpine
You'll need to subclass the treeview's parent window.  Have a look at
the WM_NOTIFY topic in the MSDN for further info on this message.

HTH,
Bryan
_______________________________
Bryan Stafford
New Vision Software
newvision_don'tspam@mvps.org


On Tue, 18 Oct 2005 07:39:05 -0700, "Alastair MacFarlane"
<AlastairMacFarl***@discussions.microsoft.com> wrote:

Show quoteHide quote
>Thanks all for your reply. I am running the subclass from the form as follows:
>
>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>WindowProc)
>
>therefore I presume I am subclassing the treeview control itself.
>
>The full code on the form is as follows:
>
>Option Explicit
>
>Private Const GWL_WNDPROC As Long = (-4&)
>Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
>(ByVal hWnd&, _
>     ByVal nIndex&, ByVal dwNewLong&) As Long
>
>Private Sub Form_Load()
>   Dim lCount As Long
>   With TreeView1.Nodes
>       .Add , , "ROOT", "ROOT"
>       For lCount = 1 To 25
>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item Number
>" & lCount
>       Next
>   End With
>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>WindowProc)
>End Sub
>
>Private Sub Form_Unload(Cancel As Integer)
>  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
>End Sub
>
>Thanks again for your support?
>
>Alastair
>
>"alpine" wrote:
>
>> Are you subclassing the treeview's parent window?
>>
>> HTH,
>> Bryan
>> _______________________________
>> Bryan Stafford
>> New Vision Software
>> newvision_don'tspam@mvps.org
>>
>>
>> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>
>> >Dear All,
>> >
>> >Can somone suggest why I don't receive a WM_NOTIFY message from a control on
Author
18 Oct 2005 6:14 PM
Alastair MacFarlane
Alpine,

Once again thanks for the reply. I have now changed the code to subclass the
control parent instead as per your and msdn's advice, BUT the WM_NOTIFY
message does not get raised. I have declared the messgage handler as on the
Form_Load:

lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)

and WM_NOTIFY is declared as in the module:

Public Const WM_NOTIFY = &H4E

Is there any property of the form (Form1) that could interfere with the
message queue. When I add a breakpoint at the line below the "Case
WM_NOTIFY" (which I know you shouldn't), the line "CopyMemory tMessage,
ByVal lParam, Len(tMessage)" is never called.

   Select Case msg
       Case WM_NOTIFY
           CopyMemory tMessage, ByVal lParam, Len(tMessage)
           lCode = tMessage.code
           Select Case lCode

My aim (as discussed in a previous post) is to change the size of specific
node fonts.

Thanks again for your continued support and I apologise if I seem somewhat
dense.

Alastair MacFarlane


Show quoteHide quote
"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
news:905al1587bgtet142qpocpign5e0bh9i2h@4ax.com...
> You'll need to subclass the treeview's parent window.  Have a look at
> the WM_NOTIFY topic in the MSDN for further info on this message.
>
> HTH,
> Bryan
> _______________________________
> Bryan Stafford
> New Vision Software
> newvision_don'tspam@mvps.org
>
>
> On Tue, 18 Oct 2005 07:39:05 -0700, "Alastair MacFarlane"
> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>
>>Thanks all for your reply. I am running the subclass from the form as
>>follows:
>>
>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>WindowProc)
>>
>>therefore I presume I am subclassing the treeview control itself.
>>
>>The full code on the form is as follows:
>>
>>Option Explicit
>>
>>Private Const GWL_WNDPROC As Long = (-4&)
>>Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
>>(ByVal hWnd&, _
>>     ByVal nIndex&, ByVal dwNewLong&) As Long
>>
>>Private Sub Form_Load()
>>   Dim lCount As Long
>>   With TreeView1.Nodes
>>       .Add , , "ROOT", "ROOT"
>>       For lCount = 1 To 25
>>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item
>> Number
>>" & lCount
>>       Next
>>   End With
>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>WindowProc)
>>End Sub
>>
>>Private Sub Form_Unload(Cancel As Integer)
>>  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
>>End Sub
>>
>>Thanks again for your support?
>>
>>Alastair
>>
>>"alpine" wrote:
>>
>>> Are you subclassing the treeview's parent window?
>>>
>>> HTH,
>>> Bryan
>>> _______________________________
>>> Bryan Stafford
>>> New Vision Software
>>> newvision_don'tspam@mvps.org
>>>
>>>
>>> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>
>>> >Dear All,
>>> >
>>> >Can somone suggest why I don't receive a WM_NOTIFY message from a
>>> >control on
>
Author
18 Oct 2005 7:22 PM
alpine
I just ran a test here in both VB5 & 6 and the WM_NOTIFY messages come
through just fine for the treeview.  Are you getting *any* messages
coming through your windowproc?

HTH,
Bryan
_______________________________
Bryan Stafford
New Vision Software
newvision_don'tspam@mvps.org


On Tue, 18 Oct 2005 19:14:32 +0100, "Alastair MacFarlane"
<anonym***@microsoft.com> wrote:

Show quoteHide quote
>Alpine,
>
>Once again thanks for the reply. I have now changed the code to subclass the
>control parent instead as per your and msdn's advice, BUT the WM_NOTIFY
>message does not get raised. I have declared the messgage handler as on the
>Form_Load:
>
>lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
>
>and WM_NOTIFY is declared as in the module:
>
>Public Const WM_NOTIFY = &H4E
>
>Is there any property of the form (Form1) that could interfere with the
>message queue. When I add a breakpoint at the line below the "Case
>WM_NOTIFY" (which I know you shouldn't), the line "CopyMemory tMessage,
>ByVal lParam, Len(tMessage)" is never called.
>
>   Select Case msg
>       Case WM_NOTIFY
>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>           lCode = tMessage.code
>           Select Case lCode
>
>My aim (as discussed in a previous post) is to change the size of specific
>node fonts.
>
>Thanks again for your continued support and I apologise if I seem somewhat
>dense.
>
>Alastair MacFarlane
>
>
>"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
>news:905al1587bgtet142qpocpign5e0bh9i2h@4ax.com...
>> You'll need to subclass the treeview's parent window.  Have a look at
>> the WM_NOTIFY topic in the MSDN for further info on this message.
>>
>> HTH,
>> Bryan
>> _______________________________
>> Bryan Stafford
>> New Vision Software
>> newvision_don'tspam@mvps.org
>>
>>
>> On Tue, 18 Oct 2005 07:39:05 -0700, "Alastair MacFarlane"
>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>
>>>Thanks all for your reply. I am running the subclass from the form as
>>>follows:
>>>
>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>WindowProc)
>>>
>>>therefore I presume I am subclassing the treeview control itself.
>>>
>>>The full code on the form is as follows:
>>>
>>>Option Explicit
>>>
>>>Private Const GWL_WNDPROC As Long = (-4&)
>>>Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
>>>(ByVal hWnd&, _
>>>     ByVal nIndex&, ByVal dwNewLong&) As Long
>>>
>>>Private Sub Form_Load()
>>>   Dim lCount As Long
>>>   With TreeView1.Nodes
>>>       .Add , , "ROOT", "ROOT"
>>>       For lCount = 1 To 25
>>>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item
>>> Number
>>>" & lCount
>>>       Next
>>>   End With
>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>WindowProc)
>>>End Sub
>>>
>>>Private Sub Form_Unload(Cancel As Integer)
>>>  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
>>>End Sub
>>>
>>>Thanks again for your support?
>>>
>>>Alastair
>>>
>>>"alpine" wrote:
>>>
>>>> Are you subclassing the treeview's parent window?
>>>>
>>>> HTH,
>>>> Bryan
>>>> _______________________________
>>>> Bryan Stafford
>>>> New Vision Software
>>>> newvision_don'tspam@mvps.org
>>>>
>>>>
>>>> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
>>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>>
>>>> >Dear All,
>>>> >
>>>> >Can somone suggest why I don't receive a WM_NOTIFY message from a
>>>> >control on
>>
>
Author
18 Oct 2005 7:52 PM
Alastair MacFarlane
Alpine

Thanks again. The handler is getting some messages but no WM_NOTIFY
messages. I have attached the full form and module code and I would
appreciate your comments.

Alastair MacFarlane

'****Start Form Header Info ****
'Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX"
'****End Form Header Info ****


'****Start Form Code****
Option Explicit
Private Const GWL_WNDPROC As Long = (-4&)
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
(ByVal hWnd&, _
     ByVal nIndex&, ByVal dwNewLong&) As Long

Private Sub Form_Load()
   Dim lCount As Long
   With TreeView1.Nodes
       .Add , , "ROOT", "ROOT"
       For lCount = 1 To 25
           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item Number
" & lCount
       Next
   End With
  lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
  Call SetWindowLong(hWnd, GWL_WNDPROC, lpPrevWndProc)
End Sub
'****End Form Code****

'****Start Module Code****

Public Type RECT
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type

' WinAPI Notification Structure
Public Type NMHDR
   hwndFrom As Long
   idFrom As Long
   code As Long
End Type

' Custom Draw Structure
Public Type NMCUSTOMDRAWINFO
   hdr As NMHDR
   dwDrawStage As Long
   hdc As Long
   rc As RECT
   dwItemSpec As Long
   iItemState As Long
   lItemLParam As Long
End Type

' Custom Draw Structure Associated with the TreeView
Public Type NMTVCUSTOMDRAW
   nmcmd As NMCUSTOMDRAWINFO
   clrText As Long
   clrTextBk As Long
   iLevel As Integer
End Type

' Font Constants
Public Const LF_FACESIZE = 32
Public Const FW_NORMAL = 400
Public Const OBJ_FONT = 6

' WinAPI LogFont Structure
Public Type LOGFONT
   lfHeight As Long
   lfWidth As Long
   lfEscapement As Long
   lfOrientation As Long
   lfWeight As Long
   lfItalic As Byte
   lfUnderline As Byte
   lfStrikeOut As Byte
   lfCharSet As Byte
   lfOutPrecision As Byte
   lfClipPrecision As Byte
   lfQuality As Byte
   lfPitchAndFamily As Byte
   lfFaceName(LF_FACESIZE) As Byte
End Type

' WinAPI TreeView Item Structure
Public Type TV_ITEM
   mask As Long
   hitem As Long
   state As Long
   stateMask As Long
   pszText As Long ' pointer
   cchTextMax As Long
   iImage As Long
   iSelectedImage As Long
   cChildren As Long
   lParam As Long
End Type

' Windows messages
Public Const NM_CUSTOMDRAW = (0 - 12)
Public Const WM_NOTIFY = &H4E

' Custom Draw Messages
Public Const CDDS_PREPAINT& = &H1
Public Const CDDS_POSTPAINT& = &H2
Public Const CDDS_PREERASE& = &H3
Public Const CDDS_POSTERASE& = &H4
Public Const CDDS_ITEM& = &H10000
Public Const CDDS_ITEMPREPAINT& = CDDS_ITEM Or CDDS_PREPAINT
Public Const CDDS_ITEMPOSTPAINT& = CDDS_ITEM Or CDDS_POSTPAINT
Public Const CDDS_ITEMPREERASE& = CDDS_ITEM Or CDDS_PREERASE
Public Const CDDS_ITEMPOSTERASE& = CDDS_ITEM Or CDDS_POSTERASE
Public Const CDDS_SUBITEM& = &H20000

Public Const CDRF_DODEFAULT& = &H0
Public Const CDRF_NEWFONT& = &H2
Public Const CDRF_SKIPDEFAULT& = &H4
Public Const CDRF_NOTIFYPOSTPAINT& = &H10
Public Const CDRF_NOTIFYITEMDRAW& = &H20
Public Const CDRF_NOTIFYSUBITEMDRAW = &H20 'flags are the same, we can
distinguish by context
Public Const CDRF_NOTIFYPOSTERASE& = &H40
Public Const CDRF_NOTIFYITEMERASE& = &H80

Public mlHeaderFont As Long

Public Declare Function GetCurrentObject Lib "gdi32" _
    (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias _
    "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Public Declare Function DeleteObject Lib "gdi32" _
    (ByVal hObject As Long) As Long
Public Declare Function CreateFontIndirect Lib "gdi32" _
    Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
Public Declare Function SelectObject Lib "gdi32" _
    (ByVal hdc As Long, ByVal hObject As Long) As Long

Public Declare Function GetObjectAPI Lib "gdi32" Alias _
    "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As
Any) 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 lpPrevWndProc As Long

Public Function WindowProc(ByVal hWnd As Long, _
    ByVal uMsg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
   Dim i As Integer
   Dim hCurrFont As Long
   Dim lf As LOGFONT
   Dim lColour As Long
   Dim hOldFont As Long
   Dim tMessage As NMHDR
   Dim tTVMessage As NMTVCUSTOMDRAW
   Dim lCode As Long
   Dim tItem As TV_ITEM
   Dim lRet As Long
   Form1.Label1.Caption = "HERE"
   Select Case msg
       Case WM_NOTIFY
           CopyMemory tMessage, ByVal lParam, Len(tMessage)
           lCode = tMessage.code
           Select Case lCode
               Case NM_CUSTOMDRAW
                   If tMessage.hwndFrom <> TreeView1.hWnd Then
                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
uMsg, wParam, lParam)
                       Exit Function
                   End If
                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
                       Result = CDRF_NOTIFYITEMDRAW
                       Exit Function
                   End If
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
                       CopyMemory tItem, ByVal tTVMessage.nmcmd.lItemLParam,
Len(tItem)
                           hCurrFont =
GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
                           If lRet > 0 Then
                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5), 700,
FW_NORMAL)
                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
False
                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
'False
                               lRet = DeleteObject(mlHeaderFont)
                               mlHeaderFont = CreateFontIndirect(lf)
                               hOldFont = SelectObject(tTVMessage.nmcmd.hdc,
mlHeaderFont)
                            End If
                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
255)
                       tTVMessage.clrText = lColour
                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
                       Result = CDRF_NEWFONT
                       Exit Function
                   End If
               Case Else
                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
wParam, lParam)
                   Exit Function
           End Select
       Case Else
       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
lParam)
   End Select
End Function
'****End Module Code****








Show quoteHide quote
"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
news:qnial15i1rlnph00veel2p8h6jne1uijel@4ax.com...
>I just ran a test here in both VB5 & 6 and the WM_NOTIFY messages come
> through just fine for the treeview.  Are you getting *any* messages
> coming through your windowproc?
>
> HTH,
> Bryan
> _______________________________
> Bryan Stafford
> New Vision Software
> newvision_don'tspam@mvps.org
>
>
> On Tue, 18 Oct 2005 19:14:32 +0100, "Alastair MacFarlane"
> <anonym***@microsoft.com> wrote:
>
>>Alpine,
>>
>>Once again thanks for the reply. I have now changed the code to subclass
>>the
>>control parent instead as per your and msdn's advice, BUT the WM_NOTIFY
>>message does not get raised. I have declared the messgage handler as on
>>the
>>Form_Load:
>>
>>lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
>>
>>and WM_NOTIFY is declared as in the module:
>>
>>Public Const WM_NOTIFY = &H4E
>>
>>Is there any property of the form (Form1) that could interfere with the
>>message queue. When I add a breakpoint at the line below the "Case
>>WM_NOTIFY" (which I know you shouldn't), the line "CopyMemory tMessage,
>>ByVal lParam, Len(tMessage)" is never called.
>>
>>   Select Case msg
>>       Case WM_NOTIFY
>>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>>           lCode = tMessage.code
>>           Select Case lCode
>>
>>My aim (as discussed in a previous post) is to change the size of specific
>>node fonts.
>>
>>Thanks again for your continued support and I apologise if I seem somewhat
>>dense.
>>
>>Alastair MacFarlane
>>
>>
>>"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
>>news:905al1587bgtet142qpocpign5e0bh9i2h@4ax.com...
>>> You'll need to subclass the treeview's parent window.  Have a look at
>>> the WM_NOTIFY topic in the MSDN for further info on this message.
>>>
>>> HTH,
>>> Bryan
>>> _______________________________
>>> Bryan Stafford
>>> New Vision Software
>>> newvision_don'tspam@mvps.org
>>>
>>>
>>> On Tue, 18 Oct 2005 07:39:05 -0700, "Alastair MacFarlane"
>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>
>>>>Thanks all for your reply. I am running the subclass from the form as
>>>>follows:
>>>>
>>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>>WindowProc)
>>>>
>>>>therefore I presume I am subclassing the treeview control itself.
>>>>
>>>>The full code on the form is as follows:
>>>>
>>>>Option Explicit
>>>>
>>>>Private Const GWL_WNDPROC As Long = (-4&)
>>>>Private Declare Function SetWindowLong Lib "user32" Alias
>>>>"SetWindowLongA"
>>>>(ByVal hWnd&, _
>>>>     ByVal nIndex&, ByVal dwNewLong&) As Long
>>>>
>>>>Private Sub Form_Load()
>>>>   Dim lCount As Long
>>>>   With TreeView1.Nodes
>>>>       .Add , , "ROOT", "ROOT"
>>>>       For lCount = 1 To 25
>>>>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item
>>>> Number
>>>>" & lCount
>>>>       Next
>>>>   End With
>>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>>WindowProc)
>>>>End Sub
>>>>
>>>>Private Sub Form_Unload(Cancel As Integer)
>>>>  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
>>>>End Sub
>>>>
>>>>Thanks again for your support?
>>>>
>>>>Alastair
>>>>
>>>>"alpine" wrote:
>>>>
>>>>> Are you subclassing the treeview's parent window?
>>>>>
>>>>> HTH,
>>>>> Bryan
>>>>> _______________________________
>>>>> Bryan Stafford
>>>>> New Vision Software
>>>>> newvision_don'tspam@mvps.org
>>>>>
>>>>>
>>>>> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
>>>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>>>
>>>>> >Dear All,
>>>>> >
>>>>> >Can somone suggest why I don't receive a WM_NOTIFY message from a
>>>>> >control on
>>>
>>
>
Author
18 Oct 2005 8:42 PM
MikeD
Show quote Hide quote
"Alastair MacFarlane" <anonym***@microsoft.com> wrote in message
news:uKW5G2B1FHA.2312@TK2MSFTNGP14.phx.gbl...
> Alpine
>
> Thanks again. The handler is getting some messages but no WM_NOTIFY
> messages. I have attached the full form and module code and I would
> appreciate your comments.
> Public Function WindowProc(ByVal hWnd As Long, _
>    ByVal uMsg As Long, _
>    ByVal wParam As Long, _
>    ByVal lParam As Long) As Long
>   Dim i As Integer
>   Dim hCurrFont As Long
>   Dim lf As LOGFONT
>   Dim lColour As Long
>   Dim hOldFont As Long
>   Dim tMessage As NMHDR
>   Dim tTVMessage As NMTVCUSTOMDRAW
>   Dim lCode As Long
>   Dim tItem As TV_ITEM
>   Dim lRet As Long
>   Form1.Label1.Caption = "HERE"
>   Select Case msg
>       Case WM_NOTIFY
>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>           lCode = tMessage.code
>           Select Case lCode
>               Case NM_CUSTOMDRAW
>                   If tMessage.hwndFrom <> TreeView1.hWnd Then
>                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
> uMsg, wParam, lParam)
>                       Exit Function
>                   End If
>                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>                       Result = CDRF_NOTIFYITEMDRAW
>                       Exit Function
>                   End If
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
>                       CopyMemory tItem, ByVal
> tTVMessage.nmcmd.lItemLParam, Len(tItem)
>                           hCurrFont =
> GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>                           If lRet > 0 Then
>                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5),
> 700, FW_NORMAL)
>                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
> False
>                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
> 'False
>                               lRet = DeleteObject(mlHeaderFont)
>                               mlHeaderFont = CreateFontIndirect(lf)
>                               hOldFont =
> SelectObject(tTVMessage.nmcmd.hdc, mlHeaderFont)
>                            End If
>                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
> 255)
>                       tTVMessage.clrText = lColour
>                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
>                       Result = CDRF_NEWFONT
>                       Exit Function
>                   End If
>               Case Else
>                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
> wParam, lParam)
>                   Exit Function
>           End Select
>       Case Else
>       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
> lParam)
>   End Select
> End Function


You *sure* about that code?  There are problems with it as posted.  For one,
in your Select Case, you've got the variable as 'msg' but it should be
'uMsg' (per your procedure header).  Also, you need to preface the reference
to TreeView1 with the form's name (or other reference to the form).
Furthermore, there's no declaration for your 'Result' variable.  Maybe
that's declared elsewhere, but I also noticed there was no Option Explicit
for this module.

However, once I corrected these problems, your code at least ran and handled
the WM_NOTIFY message.  I don't know that it did what it was supposed to do,
but it at least ran.

Here's what I changed your WindowProc to:

-----BEGIN CODE
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal
wParam As Long, ByVal lParam As Long) As Long

   Dim i As Integer
   Dim hCurrFont As Long
   Dim lf As LOGFONT
   Dim lColour As Long
   Dim hOldFont As Long
   Dim tMessage As NMHDR
   Dim tTVMessage As NMTVCUSTOMDRAW
   Dim lCode As Long
   Dim tItem As TV_ITEM
   Dim lRet As Long

   Dim Result As Long

   Form1.Label1.Caption = "HERE"
   Select Case uMsg
       Case WM_NOTIFY
           Debug.Print "WM_NOTIFY"
           CopyMemory tMessage, ByVal lParam, Len(tMessage)
           lCode = tMessage.code
           Select Case lCode
               Case NM_CUSTOMDRAW
                   If tMessage.hwndFrom <> Form1.TreeView1.hWnd Then
                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
uMsg, wParam, lParam)
                       Exit Function
                   End If
                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
                       Result = CDRF_NOTIFYITEMDRAW
                       Exit Function
                   End If
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
                       CopyMemory tItem, ByVal tTVMessage.nmcmd.lItemLParam,
Len(tItem)
                           hCurrFont =
GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
                           If lRet > 0 Then
                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5), 700,
FW_NORMAL)
                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5)
'False
                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
'False
                               lRet = DeleteObject(mlHeaderFont)
                               mlHeaderFont = CreateFontIndirect(lf)
                               hOldFont = SelectObject(tTVMessage.nmcmd.hdc,
mlHeaderFont)
                            End If
                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
255)
                       tTVMessage.clrText = lColour
                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
                       Result = CDRF_NEWFONT
                       Exit Function
                   End If
               Case Else
                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
wParam, lParam)
                   Exit Function
           End Select
       Case Else
       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
lParam)
   End Select
End Function
-----END CODE

Also, make sure the module contains Option Explicit.


--
Mike
Microsoft MVP Visual Basic
Author
18 Oct 2005 9:23 PM
Alastair MacFarlane
Mike & Alpine,

It does seem to work (with your revised sub) and the problem is in the
NM_CUSTOMDRAW message handling code which I will need to look at tomorrow
(UK bed-time).

I appreciate both your help but at a quick glance the code looks beyond my
ability to fix at the moment because I don't truly understand the use of
CopyMemory and the different Type structures mentioned. This one will
probably just leave me beat.

I will look at it tomorrow and thanks again for your help. Any thoughts on
the revision of the code would be appreciated but not expected.

Alastair MacFarlane
p.s. Good night from the UK.

It always seems to exit the sub about here, therefore
tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT (but what does this mean?):

                   If tMessage.hwndFrom <> Form1.TreeView1.hWnd Then
                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
uMsg, wParam, lParam)
                       Exit Function
                   End If
                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
                       Result = CDRF_NOTIFYITEMDRAW
                    **********************HERE******************
                       Exit Function
                   End If


Show quoteHide quote
"MikeD" <nob***@nowhere.edu> wrote in message
news:%23oO25RC1FHA.904@tk2msftngp13.phx.gbl...
>
> "Alastair MacFarlane" <anonym***@microsoft.com> wrote in message
> news:uKW5G2B1FHA.2312@TK2MSFTNGP14.phx.gbl...
>> Alpine
>>
>> Thanks again. The handler is getting some messages but no WM_NOTIFY
>> messages. I have attached the full form and module code and I would
>> appreciate your comments.
>> Public Function WindowProc(ByVal hWnd As Long, _
>>    ByVal uMsg As Long, _
>>    ByVal wParam As Long, _
>>    ByVal lParam As Long) As Long
>>   Dim i As Integer
>>   Dim hCurrFont As Long
>>   Dim lf As LOGFONT
>>   Dim lColour As Long
>>   Dim hOldFont As Long
>>   Dim tMessage As NMHDR
>>   Dim tTVMessage As NMTVCUSTOMDRAW
>>   Dim lCode As Long
>>   Dim tItem As TV_ITEM
>>   Dim lRet As Long
>>   Form1.Label1.Caption = "HERE"
>>   Select Case msg
>>       Case WM_NOTIFY
>>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>>           lCode = tMessage.code
>>           Select Case lCode
>>               Case NM_CUSTOMDRAW
>>                   If tMessage.hwndFrom <> TreeView1.hWnd Then
>>                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
>> uMsg, wParam, lParam)
>>                       Exit Function
>>                   End If
>>                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>>                       Result = CDRF_NOTIFYITEMDRAW
>>                       Exit Function
>>                   End If
>>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT
>> Then
>>                       CopyMemory tItem, ByVal
>> tTVMessage.nmcmd.lItemLParam, Len(tItem)
>>                           hCurrFont =
>> GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>>                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>>                           If lRet > 0 Then
>>                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5),
>> 700, FW_NORMAL)
>>                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>>                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
>> False
>>                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
>> 'False
>>                               lRet = DeleteObject(mlHeaderFont)
>>                               mlHeaderFont = CreateFontIndirect(lf)
>>                               hOldFont =
>> SelectObject(tTVMessage.nmcmd.hdc, mlHeaderFont)
>>                            End If
>>                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
>> 255)
>>                       tTVMessage.clrText = lColour
>>                       CopyMemory ByVal lParam, tTVMessage,
>> Len(tTVMessage)
>>                       Result = CDRF_NEWFONT
>>                       Exit Function
>>                   End If
>>               Case Else
>>                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
>> wParam, lParam)
>>                   Exit Function
>>           End Select
>>       Case Else
>>       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
>> lParam)
>>   End Select
>> End Function
>
>
> You *sure* about that code?  There are problems with it as posted.  For
> one, in your Select Case, you've got the variable as 'msg' but it should
> be 'uMsg' (per your procedure header).  Also, you need to preface the
> reference to TreeView1 with the form's name (or other reference to the
> form). Furthermore, there's no declaration for your 'Result' variable.
> Maybe that's declared elsewhere, but I also noticed there was no Option
> Explicit for this module.
>
> However, once I corrected these problems, your code at least ran and
> handled the WM_NOTIFY message.  I don't know that it did what it was
> supposed to do, but it at least ran.
>
> Here's what I changed your WindowProc to:
>
> -----BEGIN CODE
> Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal
> wParam As Long, ByVal lParam As Long) As Long
>
>   Dim i As Integer
>   Dim hCurrFont As Long
>   Dim lf As LOGFONT
>   Dim lColour As Long
>   Dim hOldFont As Long
>   Dim tMessage As NMHDR
>   Dim tTVMessage As NMTVCUSTOMDRAW
>   Dim lCode As Long
>   Dim tItem As TV_ITEM
>   Dim lRet As Long
>
>   Dim Result As Long
>
>   Form1.Label1.Caption = "HERE"
>   Select Case uMsg
>       Case WM_NOTIFY
>           Debug.Print "WM_NOTIFY"
>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>           lCode = tMessage.code
>           Select Case lCode
>               Case NM_CUSTOMDRAW
>                   If tMessage.hwndFrom <> Form1.TreeView1.hWnd Then
>                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
> uMsg, wParam, lParam)
>                       Exit Function
>                   End If
>                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>                       Result = CDRF_NOTIFYITEMDRAW
>                       Exit Function
>                   End If
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
>                       CopyMemory tItem, ByVal
> tTVMessage.nmcmd.lItemLParam, Len(tItem)
>                           hCurrFont =
> GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>                           If lRet > 0 Then
>                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5),
> 700, FW_NORMAL)
>                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5)
> 'False
>                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
> 'False
>                               lRet = DeleteObject(mlHeaderFont)
>                               mlHeaderFont = CreateFontIndirect(lf)
>                               hOldFont =
> SelectObject(tTVMessage.nmcmd.hdc, mlHeaderFont)
>                            End If
>                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
> 255)
>                       tTVMessage.clrText = lColour
>                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
>                       Result = CDRF_NEWFONT
>                       Exit Function
>                   End If
>               Case Else
>                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
> wParam, lParam)
>                   Exit Function
>           End Select
>       Case Else
>       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
> lParam)
>   End Select
> End Function
> -----END CODE
>
> Also, make sure the module contains Option Explicit.
>
>
> --
> Mike
> Microsoft MVP Visual Basic
>
>
>
Author
18 Oct 2005 8:44 PM
alpine
Try placing an Option Explicit at the top of your BAS module.  ;-)

HTH,
Bryan
_______________________________
Bryan Stafford
New Vision Software
newvision_don'tspam@mvps.org


On Tue, 18 Oct 2005 20:52:29 +0100, "Alastair MacFarlane"
<anonym***@microsoft.com> wrote:

Show quoteHide quote
>Alpine
>
>Thanks again. The handler is getting some messages but no WM_NOTIFY
>messages. I have attached the full form and module code and I would
>appreciate your comments.
>
>Alastair MacFarlane
>
>'****Start Form Header Info ****
>'Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX"
>'****End Form Header Info ****
>
>
>'****Start Form Code****
>Option Explicit
>Private Const GWL_WNDPROC As Long = (-4&)
>Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"
>(ByVal hWnd&, _
>     ByVal nIndex&, ByVal dwNewLong&) As Long
>
>Private Sub Form_Load()
>   Dim lCount As Long
>   With TreeView1.Nodes
>       .Add , , "ROOT", "ROOT"
>       For lCount = 1 To 25
>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item Number
>" & lCount
>       Next
>   End With
>  lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
>End Sub
>
>Private Sub Form_Unload(Cancel As Integer)
>  Call SetWindowLong(hWnd, GWL_WNDPROC, lpPrevWndProc)
>End Sub
>'****End Form Code****
>
>'****Start Module Code****
>
>Public Type RECT
>   Left As Long
>   Top As Long
>   Right As Long
>   Bottom As Long
>End Type
>
>' WinAPI Notification Structure
>Public Type NMHDR
>   hwndFrom As Long
>   idFrom As Long
>   code As Long
>End Type
>
>' Custom Draw Structure
>Public Type NMCUSTOMDRAWINFO
>   hdr As NMHDR
>   dwDrawStage As Long
>   hdc As Long
>   rc As RECT
>   dwItemSpec As Long
>   iItemState As Long
>   lItemLParam As Long
>End Type
>
>' Custom Draw Structure Associated with the TreeView
>Public Type NMTVCUSTOMDRAW
>   nmcmd As NMCUSTOMDRAWINFO
>   clrText As Long
>   clrTextBk As Long
>   iLevel As Integer
>End Type
>
>' Font Constants
>Public Const LF_FACESIZE = 32
>Public Const FW_NORMAL = 400
>Public Const OBJ_FONT = 6
>
>' WinAPI LogFont Structure
>Public Type LOGFONT
>   lfHeight As Long
>   lfWidth As Long
>   lfEscapement As Long
>   lfOrientation As Long
>   lfWeight As Long
>   lfItalic As Byte
>   lfUnderline As Byte
>   lfStrikeOut As Byte
>   lfCharSet As Byte
>   lfOutPrecision As Byte
>   lfClipPrecision As Byte
>   lfQuality As Byte
>   lfPitchAndFamily As Byte
>   lfFaceName(LF_FACESIZE) As Byte
>End Type
>
>' WinAPI TreeView Item Structure
>Public Type TV_ITEM
>   mask As Long
>   hitem As Long
>   state As Long
>   stateMask As Long
>   pszText As Long ' pointer
>   cchTextMax As Long
>   iImage As Long
>   iSelectedImage As Long
>   cChildren As Long
>   lParam As Long
>End Type
>
>' Windows messages
>Public Const NM_CUSTOMDRAW = (0 - 12)
>Public Const WM_NOTIFY = &H4E
>
>' Custom Draw Messages
>Public Const CDDS_PREPAINT& = &H1
>Public Const CDDS_POSTPAINT& = &H2
>Public Const CDDS_PREERASE& = &H3
>Public Const CDDS_POSTERASE& = &H4
>Public Const CDDS_ITEM& = &H10000
>Public Const CDDS_ITEMPREPAINT& = CDDS_ITEM Or CDDS_PREPAINT
>Public Const CDDS_ITEMPOSTPAINT& = CDDS_ITEM Or CDDS_POSTPAINT
>Public Const CDDS_ITEMPREERASE& = CDDS_ITEM Or CDDS_PREERASE
>Public Const CDDS_ITEMPOSTERASE& = CDDS_ITEM Or CDDS_POSTERASE
>Public Const CDDS_SUBITEM& = &H20000
>
>Public Const CDRF_DODEFAULT& = &H0
>Public Const CDRF_NEWFONT& = &H2
>Public Const CDRF_SKIPDEFAULT& = &H4
>Public Const CDRF_NOTIFYPOSTPAINT& = &H10
>Public Const CDRF_NOTIFYITEMDRAW& = &H20
>Public Const CDRF_NOTIFYSUBITEMDRAW = &H20 'flags are the same, we can
>distinguish by context
>Public Const CDRF_NOTIFYPOSTERASE& = &H40
>Public Const CDRF_NOTIFYITEMERASE& = &H80
>
>Public mlHeaderFont As Long
>
>Public Declare Function GetCurrentObject Lib "gdi32" _
>    (ByVal hdc As Long, ByVal uObjectType As Long) As Long
>Public Declare Sub CopyMemory Lib "kernel32" Alias _
>    "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
>Public Declare Function DeleteObject Lib "gdi32" _
>    (ByVal hObject As Long) As Long
>Public Declare Function CreateFontIndirect Lib "gdi32" _
>    Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
>Public Declare Function SelectObject Lib "gdi32" _
>    (ByVal hdc As Long, ByVal hObject As Long) As Long
>
>Public Declare Function GetObjectAPI Lib "gdi32" Alias _
>    "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As
>Any) 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 lpPrevWndProc As Long
>
>Public Function WindowProc(ByVal hWnd As Long, _
>    ByVal uMsg As Long, _
>    ByVal wParam As Long, _
>    ByVal lParam As Long) As Long
>   Dim i As Integer
>   Dim hCurrFont As Long
>   Dim lf As LOGFONT
>   Dim lColour As Long
>   Dim hOldFont As Long
>   Dim tMessage As NMHDR
>   Dim tTVMessage As NMTVCUSTOMDRAW
>   Dim lCode As Long
>   Dim tItem As TV_ITEM
>   Dim lRet As Long
>   Form1.Label1.Caption = "HERE"
>   Select Case msg
>       Case WM_NOTIFY
>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>           lCode = tMessage.code
>           Select Case lCode
>               Case NM_CUSTOMDRAW
>                   If tMessage.hwndFrom <> TreeView1.hWnd Then
>                       WindowProc = CallWindowProc(lpPrevWndProc, hWnd,
>uMsg, wParam, lParam)
>                       Exit Function
>                   End If
>                   CopyMemory tTVMessage, ByVal lParam, Len(tTVMessage)
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_PREPAINT Then
>                       Result = CDRF_NOTIFYITEMDRAW
>                       Exit Function
>                   End If
>                   If tTVMessage.nmcmd.dwDrawStage = CDDS_ITEMPREPAINT Then
>                       CopyMemory tItem, ByVal tTVMessage.nmcmd.lItemLParam,
>Len(tItem)
>                           hCurrFont =
>GetCurrentObject(tTVMessage.nmcmd.hdc, OBJ_FONT)
>                           lRet = GetObjectAPI(hCurrFont, Len(lf), lf)
>                           If lRet > 0 Then
>                               lf.lfWeight = IIf(CInt(Rnd(1) * 10 < 5), 700,
>FW_NORMAL)
>                               lf.lfItalic = (CInt(Rnd(1) * 10) < 5)
>                               lf.lfUnderline = (CInt(Rnd(1) * 10) < 5) '
>False
>                               lf.lfStrikeOut = (CInt(Rnd(1) * 10) < 2)
>'False
>                               lRet = DeleteObject(mlHeaderFont)
>                               mlHeaderFont = CreateFontIndirect(lf)
>                               hOldFont = SelectObject(tTVMessage.nmcmd.hdc,
>mlHeaderFont)
>                            End If
>                       lColour = RGB(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) *
>255)
>                       tTVMessage.clrText = lColour
>                       CopyMemory ByVal lParam, tTVMessage, Len(tTVMessage)
>                       Result = CDRF_NEWFONT
>                       Exit Function
>                   End If
>               Case Else
>                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg,
>wParam, lParam)
>                   Exit Function
>           End Select
>       Case Else
>       WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam,
>lParam)
>   End Select
>End Function
>'****End Module Code****
>
>
>
>
>
>
>
>
>"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
>news:qnial15i1rlnph00veel2p8h6jne1uijel@4ax.com...
>>I just ran a test here in both VB5 & 6 and the WM_NOTIFY messages come
>> through just fine for the treeview.  Are you getting *any* messages
>> coming through your windowproc?
>>
>> HTH,
>> Bryan
>> _______________________________
>> Bryan Stafford
>> New Vision Software
>> newvision_don'tspam@mvps.org
>>
>>
>> On Tue, 18 Oct 2005 19:14:32 +0100, "Alastair MacFarlane"
>> <anonym***@microsoft.com> wrote:
>>
>>>Alpine,
>>>
>>>Once again thanks for the reply. I have now changed the code to subclass
>>>the
>>>control parent instead as per your and msdn's advice, BUT the WM_NOTIFY
>>>message does not get raised. I have declared the messgage handler as on
>>>the
>>>Form_Load:
>>>
>>>lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
>>>
>>>and WM_NOTIFY is declared as in the module:
>>>
>>>Public Const WM_NOTIFY = &H4E
>>>
>>>Is there any property of the form (Form1) that could interfere with the
>>>message queue. When I add a breakpoint at the line below the "Case
>>>WM_NOTIFY" (which I know you shouldn't), the line "CopyMemory tMessage,
>>>ByVal lParam, Len(tMessage)" is never called.
>>>
>>>   Select Case msg
>>>       Case WM_NOTIFY
>>>           CopyMemory tMessage, ByVal lParam, Len(tMessage)
>>>           lCode = tMessage.code
>>>           Select Case lCode
>>>
>>>My aim (as discussed in a previous post) is to change the size of specific
>>>node fonts.
>>>
>>>Thanks again for your continued support and I apologise if I seem somewhat
>>>dense.
>>>
>>>Alastair MacFarlane
>>>
>>>
>>>"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
>>>news:905al1587bgtet142qpocpign5e0bh9i2h@4ax.com...
>>>> You'll need to subclass the treeview's parent window.  Have a look at
>>>> the WM_NOTIFY topic in the MSDN for further info on this message.
>>>>
>>>> HTH,
>>>> Bryan
>>>> _______________________________
>>>> Bryan Stafford
>>>> New Vision Software
>>>> newvision_don'tspam@mvps.org
>>>>
>>>>
>>>> On Tue, 18 Oct 2005 07:39:05 -0700, "Alastair MacFarlane"
>>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>>
>>>>>Thanks all for your reply. I am running the subclass from the form as
>>>>>follows:
>>>>>
>>>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>>>WindowProc)
>>>>>
>>>>>therefore I presume I am subclassing the treeview control itself.
>>>>>
>>>>>The full code on the form is as follows:
>>>>>
>>>>>Option Explicit
>>>>>
>>>>>Private Const GWL_WNDPROC As Long = (-4&)
>>>>>Private Declare Function SetWindowLong Lib "user32" Alias
>>>>>"SetWindowLongA"
>>>>>(ByVal hWnd&, _
>>>>>     ByVal nIndex&, ByVal dwNewLong&) As Long
>>>>>
>>>>>Private Sub Form_Load()
>>>>>   Dim lCount As Long
>>>>>   With TreeView1.Nodes
>>>>>       .Add , , "ROOT", "ROOT"
>>>>>       For lCount = 1 To 25
>>>>>           .Add "ROOT", tvwChild, "C\" & lCount, "Child treeview item
>>>>> Number
>>>>>" & lCount
>>>>>       Next
>>>>>   End With
>>>>>  lpPrevWndProc = SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, AddressOf
>>>>>WindowProc)
>>>>>End Sub
>>>>>
>>>>>Private Sub Form_Unload(Cancel As Integer)
>>>>>  Call SetWindowLong(TreeView1.hWnd, GWL_WNDPROC, lpPrevWndProc)
>>>>>End Sub
>>>>>
>>>>>Thanks again for your support?
>>>>>
>>>>>Alastair
>>>>>
>>>>>"alpine" wrote:
>>>>>
>>>>>> Are you subclassing the treeview's parent window?
>>>>>>
>>>>>> HTH,
>>>>>> Bryan
>>>>>> _______________________________
>>>>>> Bryan Stafford
>>>>>> New Vision Software
>>>>>> newvision_don'tspam@mvps.org
>>>>>>
>>>>>>
>>>>>> On Tue, 18 Oct 2005 06:29:04 -0700, "Alastair MacFarlane"
>>>>>> <AlastairMacFarl***@discussions.microsoft.com> wrote:
>>>>>>
>>>>>> >Dear All,
>>>>>> >
>>>>>> >Can somone suggest why I don't receive a WM_NOTIFY message from a
>>>>>> >control on
>>>>
>>>
>>
>
Author
18 Oct 2005 9:36 PM
Jeff Johnson [MVP: VB]
"alpine" <alpine_don'tsendspam@mvps.org> wrote in message
news:ijnal1pijkp2vllf4ofj08n4l1gpnr6vt9@4ax.com...

> Try placing an Option Explicit at the top of your BAS module.  ;-)

....and every other VB file you create from here on!

Tools | Options | Editor tab | Require Variable Declaration --> Check it!