Author Topic: [Solved] CWindow and subclassing ListBox  (Read 395 times)

0 Members and 1 Guest are viewing this topic.

Offline Darren Fox

  • Newbie
  • *
  • Posts: 2
  • Gender: Male
[Solved] CWindow and subclassing ListBox
« on: March 07, 2018, 01:34:16 AM »
Greetings all,

My first post here.   ;D

I've been playing around with the CWindow class that comes with the Win API headers Josť developed.  I've come across a problem I can't figure out.  It's probably something simple I'm overlooking but I would appreciate some guidance.  When I try to subclass a ListBox, the subclassing works but the items I try to add to the ListBox don't show up.

Here is my code:
Code: [Select]
#COMPILE EXE
#DIM ALL

#Include Once "CWindow.inc"
#Include "ListBoxCtrl.inc"

%LBC_MAIN   = 1001

Function WinMain (ByVal hInstance As Dword, ByVal hPrevInstance As Dword, ByVal lpszCmdLine As WStringZ Ptr, ByVal nCmdShow As Long) As Long

    Local pWindow As IWindow
    pWindow = Class "CWindow"
    If IsNothing(pWindow) Then Exit Function

    Local hMain, hListBox As Dword, Index As Long

    hMain = pWindow.CreateWindow(%NULL, "CWindow Skeleton", 0, 0, 0, 0, 0, 0, CodePtr(WinMainProc))
    pWindow.ClassStyle = %CS_DBLCLKS
    pWindow.SetClientSize 450, 300
    pWindow.CenterWindow

    hListBox = pWindow.AddListBox(hMain, %LBC_MAIN, "", 20, 20, 200, 200, 0, 0, CodePtr(ListBoxProc))

    For Index = 1 To 10
        ListBox_AddString hListBox, "Item " + Format$(Index, "00")
    Next Index

    pWindow.DoEvents(nCmdShow)

End Function

Function WinMainProc (ByVal hWnd As Dword, ByVal uMsg As Dword, ByVal wParam As Dword, ByVal lParam As Long) As Long

    Static hInstance As Dword        ' // Instance handle
    Static lpc As CREATESTRUCT Ptr   ' // Pointer to the creation parameters
    Static pWindow As IWindow        ' // Reference to the IWindow interface

    Select Case uMsg

        Case %WM_CREATE
            lpc = lParam
            hInstance = @lpc.hInstance
            pWindow = CWindow_GetObjectFromCreateStruct(lParam)
            Exit Function

        Case %WM_COMMAND
            Select Case LO(WORD, wParam)
                Case %IDCANCEL
                    If HI(WORD, wParam) = %BN_CLICKED Then
                    SendMessage hWnd, %WM_CLOSE, 0, 0
                    Exit Function
                    End If

            End Select

        Case %WM_DESTROY
            PostQuitMessage 0
            Exit Function

    End Select

    Function = DefWindowProc(hWnd, uMsg, wParam, lParam)

End Function

Function ListBoxProc(ByVal hWnd As Dword, ByVal uMsg As Dword, ByVal wParam As Dword, ByVal lParam As Long) As Long

    Select Case uMsg

        Case %WM_LBUTTONUP
            MsgBox "Button up"
            Exit Function

    End Select

    Function = DefWindowProc(hWnd, uMsg, wParam, lParam)

End Function

If I click the left mouse button on the ListBox, I get the "Button up" message.  If I take the subclassing away:

Code: [Select]
hListBox = pWindow.AddListBox(hMain, %LBC_MAIN, "", 20, 20, 200, 200)
the items will show up in the ListBox just fine.

I also tried creating the subclass using the SetWindowLong technique, swapping the proc after the items had already been added to the ListBox, but the result was the same.  I've tried stepping through it with the debugger to see if I could find the problem but I'm not seeing it.  The variables appear to be updating as they should but the ListBox never gets populated with the items.

Can someone tell me what I'm doing wrong?
« Last Edit: March 07, 2018, 07:48:39 AM by Darren Fox »
PB/Win 10.03 on Win7 Pro.

Offline Josť Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 3185
  • Gender: Male
    • Josť Roca Software
Re: CWindow and subclassing ListBox
« Reply #1 on: March 07, 2018, 04:10:14 AM »
Change your code in ListBoxProc to:

Code: [Select]
Function ListBoxProc(ByVal hWnd As Dword, ByVal uMsg As Dword, ByVal wParam As Dword, ByVal lParam As Long) As Long

   SELECT CASE uMsg
      CASE %WM_DESTROY
         ' // REQUIRED: Remove control subclassing
         SetWindowLong hwnd, %GWL_WNDPROC, RemoveProp(hwnd, "OLDWNDPROC")

        Case %WM_LBUTTONUP
            MsgBox "Button up"
            Exit Function

   END SELECT

   FUNCTION = CallWindowProc(GetProp(hwnd, "OLDWNDPROC"), hwnd, uMsg, wParam, lParam)

End Function

A subclassed control must call CallWindowProc, no DefWindowProc.

Offline Darren Fox

  • Newbie
  • *
  • Posts: 2
  • Gender: Male
Re: CWindow and subclassing ListBox
« Reply #2 on: March 07, 2018, 07:48:09 AM »
Yep.  I figured it was something simple I wasn't doing right.  Thanks, Josť!  I'm sure I will be bugging you more as I progress with my first CWindow app.   ;D
PB/Win 10.03 on Win7 Pro.