Announcement

Collapse
No announcement yet.

Editing TreeView item calls %OKID. Why?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Editing TreeView item calls %OKID. Why?

    In a larger program I ran into this problem - editing a TreeView item results in at %WM_Command/%IDOK notification.

    In this example, I enter edit mode in the TreeView (triple click on something) and then press a key, such as "a".

    The msgbox pops up showing that I got a %WM_Command/%IDOK notification.

    Why would that be?

    Code:
     #Compile Exe
     #Dim All
    #Include "Win32api.inc"
    #Include "commctrl.inc"
     %ID_TreeView = 100
     Function PBMain() As Long
        Local hDlg As Dword, hItem As Dword
        Local hTemp As Dword, hTemp2 As Dword, hTemp3 As Dword
        Dialog New Pixels, 0, "TreeView",200,200,155,250, %WS_SysMenu, 0 To hDlg
        Control Add Treeview, hDlg, 100, "", 10,10,130,200, _
            %WS_Child Or %WS_Visible Or %WS_TabStop Or %TVS_HasButtons Or _
            %TVS_HasLines Or %TVS_LinesAtRoot Or %TVS_EditLabels Or _
            %TVS_ShowSelAlways Or %TVS_TrackSelect Or %TVS_InfoTip, _
            %WS_Ex_ClientEdge Or %WS_Ex_StaticEdge Or %WS_Ex_DlgModalFrame Or _
            %WS_Ex_AcceptFiles Or %WS_Ex_Left Or %WS_Ex_LtrReading Or _
            %WS_Ex_RightScrollbar
    
        Treeview Insert Item hDlg, 100, 0, %TVI_Last, 2,2,"Top" To hItem
    
        Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 2,4,"Mother" To hTemp
           Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Dan" To hTemp2
           Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Bob" To hTemp3
              Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Foot" To hTemp2
              Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Arm" To hTemp2
    
        Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 1,4,"Father" To hTemp
           Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Helen" To hTemp2
           Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Amy" To hTemp3
              Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Leg" To hTemp2
              Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Finger" To hTemp2
        Control Add Button, hDlg, 200, "Walk", 10,220,40,20
        Control Add Label, hDlg, 300, "<node>", 70,220,50,20, %WS_Border
    
        Dialog Show Modal hDlg Call DlgProc
     End Function
    
    
     CallBack Function DlgProc() As Long
     Dim hTree As Dword, hUpNode As Dword, hTVEdit As Dword, temp$, temp2$
     Static hNode As Dword
        If Cb.Msg = %WM_Command And Cb.Ctl = 200 Then
           If hNode = 0 Then  Treeview Get Select Cb.Hndl, %ID_TreeView To hNode
    
        End If
    
    
        If Cb.Msg = %WM_Command And Cb.Ctl = %IdOk Then
           MsgBox "ok button"
        End If
    
        If Cb.Msg = %WM_Notify And Cb.Ctl = 200 Then
             Select Case Cb.NmCode
                        Case %TVN_BeginLabelEdit
                          Control Handle Cb.Hndl, 200 To hTree
                          hTVEdit = Treeview_GetEditControl(hTree)  'handle of TreeView edit control
                          Control Get Text Cb.Hndl, GetDlgCtrlID(hTVEdit) To temp$  'get original text
                          Control Send Cb.Hndl, GetDlgCtrlID(hTVEdit), %EM_LIMITTEXT, 25, 0   '25 char max
    
                        Case %TVN_EndLabelEdit
                          hTVEdit = Treeview_GetEditControl(hTree)   'handle of TreeView edit control
                          Control Get Text Cb.Hndl, GetDlgCtrlID(hTVEdit) To temp2$  'get new text
                          Function = 1     '1=new text  0=original text
             End Select
        End If
     End Function

  • #2
    I found a discussion of the problem in MSDN. Basically don't use controls with an ID of %IDOK.

    But I wanted to use %IDOK to respond to a user pressing enter in a combobox (I don't have a %IDOK button).

    Unless anyone has a work around for the problem MSDN discusses, I guess I'll have to find another way to respond to the user pressing "Enter" in my combobox.


    WM_COMMAND|IDOK errors are received when you edit labels in a TreeView control.
    Back to the top
    CAUSE
    The edit control created by the TreeView control can, and usually does, have an...
    The edit control created by the TreeView control can, and usually does, have an identifier of 1. This identifier is the same as IDOK. This can cause the parent window or dialog box to receive WM_COMMAND messages with an identifier of 1. Then the TreeView control passes on the EN_UPDATE and EN_CHANGE notifications from the edit control to the TreeView's parent.

    This was a design decision made to meet system requirements and cannot be changed. If the parent window is going to perform some action in response to a command with an identifier of 1, this problem can occur. This problem is especially significant in dialog boxes that use the standard IDOK for a command button control.
    Back to the top
    RESOLUTION
    Avoid using command and control identifiers with an identifier of 1 (IDOK). To...
    Avoid using command and control identifiers with an identifier of 1 (IDOK). To be safe, the application should not use any identifiers less than 100 when used in conjunction with a TreeView control.

    Another way to avoid this problem is to check the notification codes in the WM_COMMAND messages. Then respond only to the proper notification codes such as BN_CLICKED.

    Comment


    • #3
      .. Another way to avoid this problem is to check the notification codes in the WM_COMMAND messages.
      Then respond only to the proper notification codes such as BN_CLICKED.
      Code:
          If Cb.Msg = %WM_Command And Cb.Ctl = %IdOk Then
             If Cb.CtlMsg = %BN_CLICKED Then
                MsgBox "ok button"
             End If
          End If
      Rgds, Dave

      Comment


      • #4
        Hi Dave, and thanks for the response.

        Using %BN_Clicked has the problem that when I press enter after editing a label in a TreeView, that also calls the %IDOK.

        I'm not sure how to tell the difference between ENTER in a combobox (the edit box), and and ENTER in the TreeView edit box. It would appear that both of their edit boxes show up with a control ID of 1 under the %WM_Command message.

        Comment


        • #5
          So, it looks like if I use a callback for the Combobox, the IDOK notification for pressing Enter in the combobox edit box will go to the combobox callback function.

          But if I use a callback for a TreeView, pressing Enter gets handled by the dialog callback, not the TreeView callback.

          Hmmm... I might have expected pressing Enter on both control edit boxes would go to their respective callback functions.

          I guess I'll have to look more - if it doesn't seem right, there must be something else to know about it.

          The code below is modified to show that the dialog callback responds to Enter, not the TreeView callback.

          Code:
           #Compile Exe
           #Dim All
          #Include "Win32api.inc"
          #Include "commctrl.inc"
           %ID_TreeView = 100
           Function PBMain() As Long
              Local hDlg As Dword, hItem As Dword
              Local hTemp As Dword, hTemp2 As Dword, hTemp3 As Dword
              Dialog New Pixels, 0, "TreeView",200,200,155,250, %WS_SysMenu, 0 To hDlg
              Control Add Treeview, hDlg, 100, "", 10,10,130,200, _
                  %WS_Child Or %WS_Visible Or %WS_TabStop Or %TVS_HasButtons Or _
                  %TVS_HasLines Or %TVS_LinesAtRoot Or %TVS_EditLabels Or _
                  %TVS_ShowSelAlways Or %TVS_TrackSelect Or %TVS_InfoTip, _
                  %WS_Ex_ClientEdge Or %WS_Ex_StaticEdge Or %WS_Ex_DlgModalFrame Or _
                  %WS_Ex_AcceptFiles Or %WS_Ex_Left Or %WS_Ex_LtrReading Or _
                  %WS_Ex_RightScrollbar   Call TVProc
          
              Treeview Insert Item hDlg, 100, 0, %TVI_Last, 2,2,"Top" To hItem
          
              Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 2,4,"Mother" To hTemp
                 Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Dan" To hTemp2
                 Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Bob" To hTemp3
                    Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Foot" To hTemp2
                    Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Arm" To hTemp2
          
              Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 1,4,"Father" To hTemp
                 Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Helen" To hTemp2
                 Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Amy" To hTemp3
                    Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Leg" To hTemp2
                    Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Finger" To hTemp2
              Control Add Button, hDlg, 200, "Walk", 10,220,40,20
              Control Add Label, hDlg, 300, "<node>", 70,220,50,20, %WS_Border
          
              Dialog Show Modal hDlg Call DlgProc
           End Function
          
          
           CallBack Function DlgProc() As Long
           Dim hTree As Dword, hUpNode As Dword, hTVEdit As Dword, temp$, temp2$
           Static hNode As Dword
              If Cb.Msg = %WM_Command And Cb.Ctl = 200 Then
                 If hNode = 0 Then  Treeview Get Select Cb.Hndl, %ID_TreeView To hNode
              End If
          
              If Cb.Msg = %WM_Command And Cb.Ctl = %IdOk Then
                 If Cb.CtlMsg = %BN_Clicked Then
                    MsgBox "Dialog proc ok button"
                 End If
              End If
          
              If Cb.Msg = %WM_Notify And Cb.Ctl = 200 Then
                   Select Case Cb.NmCode
                              Case %TVN_BeginLabelEdit
                                Control Handle Cb.Hndl, 200 To hTree
                                hTVEdit = Treeview_GetEditControl(hTree)  'handle of TreeView edit control
                                Control Get Text Cb.Hndl, GetDlgCtrlID(hTVEdit) To temp$  'get original text
                                Control Send Cb.Hndl, GetDlgCtrlID(hTVEdit), %EM_LIMITTEXT, 25, 0   '25 char max
          
                              Case %TVN_EndLabelEdit
                                hTVEdit = Treeview_GetEditControl(hTree)   'handle of TreeView edit control
                                Control Get Text Cb.Hndl, GetDlgCtrlID(hTVEdit) To temp2$  'get new text
                                Function = 1     '1=new text  0=original text
                   End Select
              End If
           End Function
          
           CallBack Function TVProc() As Long
              If Cb.Msg = %WM_Command And Cb.Ctl = %IdOk Then
                 If Cb.CtlMsg = %BN_Clicked Then
                    MsgBox "TV proc ok button"
                    Function = 1
                 End If
              End If
           End Function

          Comment


          • #6
            To understand how Windows work, you have to use SDK. For example, DDT does not
            follow the standard behaviour for buttons as shown in the table below.

            The following is adapted from Newcomer and Rector and shows the standard
            keyboard interface for dialogs in Windows.
            Code:
            WM_COMMAND messages generated by dialog handler
            -----------------------------------------------
            key          control  default  source      HIWRD(wparam)  LOWRD(wParam) lParam
            pressed      with     push     of          (Notification) (ID)          (hCtrl)
                         focus    button?  WM_COMMAND
            ===============================================================================
            Enter        Button   -        current     BN_CLICKED     current        button
                                           button                     button ID      handle
            -------------------------------------------------------------------------------
            Enter        Not a    No       Windows     0              IDOK           NULL
                         button
            -------------------------------------------------------------------------------
            Enter        Not a    Yes      Windows     BN_CLICKED     Default        NULL
                         button                                       button ID
            -------------------------------------------------------------------------------
            Escape        -       -        Windows     0              IDCANCEL       NULL
            
            -------------------------------------------------------------------------------
            System Menu  N/A      N/A      Windows     0              IDCANCEL       NULL
            (Close)
            -------------------------------------------------------------------------------
            Ctrl-Break   N/A      N/A      Windows     0              IDCANCEL       NULL
            
            -------------------------------------------------------------------------------
            Space bar    Button   Yes/No   current     BN_CLICKED     current        button
                                           button                     button ID      handle
            -------------------------------------------------------------------------------
            Notice that the ID of the default button does not have to be IDOK, something that for
            all intents and purpose is not supported by DDT.

            Given the table above, and the fact that the IsDialogMessage function sends the WM_GETDLGCODE message
            to a control to query its type and to determine the keys the control is interested in processing, it is
            possible to prevent WM_COMMAND(IDOK) from reaching the dialog.

            1. Subclass the label edit control
            The embedded child label edit control is subclassed when the form receives the TVN_BEGINLABELEDIT
            notification from the treeview control.

            2. Discard the Enter key
            We do this by telling the IsDialogMessage function that we want to process the Enter key by returning
            DLGC_WANTMESSAGE when it asks the control what it wants to do with the Enter key.

            The following SDK code demonstrates this.

            Code:
            '###############################################################################
            '                             Phoenix Visual Designer
            '                              Generated source code
            '###############################################################################
            
            '                                Acknowledgements
            ' José Roca:
            ' For his ground breaking work which interfaces low-level COM and
            ' PowerBASIC-COM automation.
            '
            ' Jeffrey Richter:
            ' For his original implementation of a layout algorithm which positions
            ' controls in a window based on a set of rules.
            
            #DIM ALL
            #REGISTER NONE
            #COMPILE EXE
            #OPTION VERSION4
            
            #INCLUDE "WIN32API.INC"
            #INCLUDE "COMMCTRL.INC"
            
            '=========================== [ Control Identifiers ] ===========================
            
            ' Form1
            %IDD_FORM1                                  = 100
            %IDC_FORM1_TREEVIEW1                        = 101
            
            '====================== [ Global Variable Declarations ] =======================
            
            GLOBAL  ghInstance    AS DWORD    ' handle of the application instance
            
            '-------------------------------------------------------------------------------
            '
            ' PROCEDURE: WinMain
            ' PURPOSE:   Program entry point, calls initialization function, processes
            '            message loop.
            '
            '-------------------------------------------------------------------------------
            
            FUNCTION WINMAIN _
              ( _
              BYVAL hInstance     AS DWORD, _       ' handle of current instance
              BYVAL hPrevInstance AS DWORD, _       ' handle of previous instance(not used in Win32)
              BYVAL pszCmdLine    AS ASCIIZ PTR, _  ' address of command line
              BYVAL nCmdShow      AS LONG _         ' show state of window
              ) AS LONG
            
              LOCAL szClassName     AS ASCIIZ * %MAX_PATH       ' class name
              LOCAL twcx            AS WNDCLASSEX               ' class information
              LOCAL tmsg            AS tagMsg                   ' message information
              LOCAL ticc            AS INIT_COMMON_CONTROLSEX   ' specifies common control classes to register
              LOCAL hWnd            AS DWORD                    ' handle of main window
              LOCAL hWndModeless    AS DWORD                    ' handle of the current active window
            
              ' Save the handle of the application instance
              ghInstance = hInstance
            
              ' Register the Form1 window
              szClassName        = "Form1_Class"
              twcx.cbSize        = SIZEOF(twcx)                               ' size of WNDCLASSEX structure
              twcx.style         = %CS_DBLCLKS                                ' class styles
              twcx.lpfnWndProc   = CODEPTR(Form1_WndProc)                     ' address of window procedure used by class
              twcx.cbClsExtra    = 0                                          ' extra class bytes
              twcx.cbWndExtra    = 0                                          ' extra window bytes
              twcx.hInstance     = ghInstance                                 ' instance of the process that is registering the window
              twcx.hIcon         = LoadIcon(%NULL, BYVAL %IDI_APPLICATION)    ' handle of class icon
              twcx.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)        ' handle of class cursor
              twcx.hbrBackground = %COLOR_BTNFACE + 1                         ' brush used to fill background of window's client area
              twcx.lpszMenuName  = %NULL                                      ' resource identifier of the class menu
              twcx.lpszClassName = VARPTR(szClassName)                        ' class name
              twcx.hIconSm       = %NULL                                      ' handle of small icon shown in caption/system Taskbar
              IF ISFALSE RegisterClassEx(twcx) THEN
                FUNCTION = %TRUE
                EXIT FUNCTION
              END IF
            
              ' Load the common controls library and
              ' specify the classes to register.
              ticc.dwSize = SIZEOF(ticc)
              ticc.dwICC  = %ICC_TREEVIEW_CLASSES
              InitCommonControlsEx ticc
            
              ' Create the Form1 window
              hWnd = CreateWindowEx(%WS_EX_WINDOWEDGE, _                                          ' extended styles
                                    "Form1_Class", _                                              ' class name
                                    "Treeview and IDOK", _                                        ' caption
                                    %WS_OVERLAPPEDWINDOW OR %WS_VISIBLE, _                        ' window styles
                                    70, 130, _                                                    ' left, top
                                    360, 374, _                                                   ' width, height
                                    %NULL, %NULL, _                                               ' handle of owner, menu handle
                                    ghInstance, BYVAL %NULL)                                      ' handle of instance, creation parameters
              ' If window could not be created, return "failure"
              IF ISFALSE hWnd THEN
                FUNCTION = %FALSE
                EXIT FUNCTION
              END IF
            
              ' Make the window visible; update its client area
              ShowWindow hWnd, nCmdShow
              UpdateWindow hWnd
            
              ' Main message loop of program.
              ' Acquire and dispatch messages until a WM_QUIT message is received.
              WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0)
                IF ISFALSE IsDialogMessage(hWnd, tmsg) THEN
                  TranslateMessage tmsg
                  DispatchMessage tmsg
                END IF
              WEND
            
              FUNCTION = tmsg.wParam
            
            END FUNCTION
            
            '-------------------------------------------------------------------------------
            '
            ' PROCEDURE: Form1_WndProc
            ' PURPOSE:   Processes messages for the Form1 window.
            '
            '-------------------------------------------------------------------------------
            
            FUNCTION Form1_WndProc _
              ( _
              BYVAL hWnd    AS DWORD, _ ' window handle
              BYVAL uMsg    AS DWORD, _ ' type of message
              BYVAL wParam  AS DWORD, _ ' first message parameter
              BYVAL lParam  AS LONG _   ' second message parameter
              ) EXPORT AS LONG
            
              LOCAL szItem      AS ASCIIZ * %MAX_PATH   ' working variable
              LOCAL ttvins      AS TV_INSERTSTRUCT      ' specifies the attributes of a new treeview item
              LOCAL ptnmhdr     AS NMHDR PTR            ' information about a notification message
              LOCAL phItem      AS DWORD PTR            ' pointer to array used to track parent treeview items
              LOCAL ptttdi      AS NMTTDISPINFO PTR     ' tooltip notification message information
              LOCAL hWndChild   AS DWORD                ' handle of child window
              LOCAL hFont       AS DWORD                ' handle of font used by form
            
              SELECT CASE uMsg
                CASE %WM_COMMAND
            
                  SELECT CASE LOWRD(wParam)
                    CASE %IDOK
                      IF HIWRD(wParam) = %BN_CLICKED THEN
                        MSGBOX "Enter key pressed"
                      END IF
                  END SELECT
            
                CASE %WM_NOTIFY
                  ptnmhdr = lParam
            
                  SELECT CASE @ptnmhdr.idFrom
                    CASE %IDC_FORM1_TREEVIEW1
            
                      SELECT CASE @ptnmhdr.code
                        CASE %TVN_BEGINLABELEDIT
                          ' Get the handle of the label edit control
                          hWndChild = SendMessage(@ptnmhdr.hwndFrom, %TVM_GETEDITCONTROL, 0, 0)
                          ' Subclass the control
                          SetProp hWndChild, "OLDWNDPROC", SetWindowLong(hWndChild, %GWL_WNDPROC, CODEPTR(EditLabel_SubclassProc))
            
                        CASE %TVN_SELCHANGED
            
                        CASE %TVN_ENDLABELEDIT
                          ' Return true to accept the changes
                          FUNCTION = %TRUE
                          EXIT FUNCTION
                      END SELECT
            
                  END SELECT
            
                CASE %WM_SYSCOLORCHANGE
                  ' Forward this message to common controls so that they will
                  ' be properly updated when the user changes the color settings.
                  SendMessage GetDlgItem(hWnd, %IDC_FORM1_TREEVIEW1), %WM_SYSCOLORCHANGE, wParam, lParam
            
                CASE %WM_SETFOCUS
                  ' Set the keyboard focus to the first control that is
                  ' visible, not disabled, and has the WS_TABSTOP style
                  SetFocus GetNextDlgTabItem(hWnd, %NULL, %FALSE)
            
                CASE %WM_DESTROY
                  PostQuitMessage 0
                  FUNCTION = %FALSE
                  EXIT FUNCTION
            
                CASE %WM_CREATE
                  ' Create font used by container
                  hFont = GetStockObject(%DEFAULT_GUI_FONT)
            
                  ' Create the TreeView1 treeview control
                  hWndChild = CreateWindowEx(%WS_EX_CLIENTEDGE, _                                 ' extended styles
                                             "SysTreeView32", _                                   ' class name
                                             "", _                                                ' caption
                                             %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR _          ' window styles
                                             %WS_TABSTOP OR _
                                             %TVS_HASBUTTONS OR %TVS_HASLINES OR _                ' class styles
                                             %TVS_LINESATROOT OR %TVS_EDITLABELS OR _
                                             %TVS_SHOWSELALWAYS, _
                                             65, 45, _                                            ' left, top
                                             221, 211, _                                          ' width, height
                                             hWnd, %IDC_FORM1_TREEVIEW1, _                        ' handle of parent, control ID
                                             ghInstance, BYVAL %NULL)                             ' handle of instance, creation parameters
                  SendMessage hWndChild, %WM_SETFONT, hFont, %TRUE
            
                  ' Allocate memory for the array used to track parent items
                  phItem = HeapAlloc(GetProcessHeap(), %HEAP_ZERO_MEMORY, 256 * 4)
                  IF ISTRUE phItem THEN
                    ' Add the items
                    szItem = "Country"
                    ttvins.item.itemex.mask           = %TVIF_TEXT OR %TVIF_CHILDREN
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.item.itemex.cChildren      = 1
                    ttvins.hParent                    = %TVI_ROOT
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[0] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "Grenada"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "Trinidad"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "Dominica"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "St. Vincent"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "St. Lucia"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "Cuba"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    szItem = "Canada"
                    ttvins.item.itemex.mask           = %TVIF_TEXT
                    ttvins.item.itemex.pszText        = VARPTR(szItem)
                    ttvins.hParent                    = @phItem[0]
                    ttvins.hInsertAfter               = %TVI_LAST
                    @phItem[1] = SendMessage(hWndChild, %TVM_INSERTITEM, 0, BYVAL VARPTR(ttvins))
            
                    HeapFree GetProcessHeap(), 0, phItem
                  END IF
            
                  ' Create the OK text button
                  hWndChild = CreateWindowEx(%NULL, _                                             ' extended styles
                                             "Button", _                                          ' class name
                                             "OK", _                                              ' caption
                                             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _         ' window styles
                                             %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, _       ' class styles
                                             134, 295, _                                          ' left, top
                                             86, 26, _                                            ' width, height
                                             hWnd, %IDOK, _                                       ' handle of parent, control ID
                                             ghInstance, BYVAL %NULL)                             ' handle of instance, creation parameters
                  SendMessage hWndChild, %WM_SETFONT, hFont, %TRUE
            
                  FUNCTION = %FALSE
                  EXIT FUNCTION
              END SELECT
            
              FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam)
            
            END FUNCTION
            
            '-------------------------------------------------------------------------------
            '
            ' PROCEDURE: Form1_TreeView1_SubclassProc
            ' PURPOSE:   Processes messages for the subclassed label edit control.
            '
            '-------------------------------------------------------------------------------
            
            FUNCTION EditLabel_SubclassProc _
              ( _
              BYVAL hWnd    AS DWORD, _ ' control handle
              BYVAL uMsg    AS DWORD, _ ' type of message
              BYVAL wParam  AS DWORD, _ ' first message parameter
              BYVAL lParam  AS LONG _   ' second message parameter
              ) EXPORT AS LONG
            
              LOCAL ptmsg           AS tagMsg PTR
              LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
              LOCAL lMsgResult      AS LONG     ' value returned to message after message is processed
            
              lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")
            
              SELECT CASE uMsg
                CASE %WM_DESTROY
                  ' Remove control subclassing
                  SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")
            
                CASE %WM_GETDLGCODE 
                  ' Windows is querying for the control type or keys the control is
                  ' interested  in processing.
                  lMsgResult = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
                  IF lParam THEN
                    ptmsg = lParam
                    IF @ptmsg.message = %WM_KEYDOWN THEN
                      IF wParam = %VK_RETURN THEN
                        ' Tell windows we will process this key.
                        ' (The net effect is that the key is discarded)
                        FUNCTION = %DLGC_WANTMESSAGE
                        EXIT FUNCTION
                      END IF
                    END IF
                  END IF
                  ' Return the default dialog codes for the control
                  FUNCTION = lMsgResult
                  EXIT FUNCTION
              END SELECT
            
              FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
            
            END FUNCTION

            Just compile, run, click a label, enter some text, and press the Enter key.
            Last edited by Dominic Mitchell; 11 Apr 2009, 11:50 PM.
            Dominic Mitchell
            Phoenix Visual Designer
            http://www.phnxthunder.com

            Comment


            • #7
              Dominic,

              Thanks for the information. I'll make use of it!

              One of the interesting? things about learning PowerBASIC has been figuring out how to program with DDT vs doing the same tasks in SDK style - not to mention learning where DDT leaves off and SDK is required.

              I'm beginning to see why many of the more experienced PowerBASIC programmers have drifted to the SDk style of programming.

              Comment


              • #8
                Before you drift too far from 'MiddleEarth' into that (SDK) realm of sorcerers and wizards...

                Think about using GetFocus() to discriminate between Enter key responses - gets a little more difficult
                when the key press occurs while the focus is in the edit section of a combobox (id = 1001 btw) or the label of a
                treeview - but in that case you can use GetParent(GetFocus()) as below..
                Code:
                 
                #Compile Exe
                #Dim All
                #Include "Win32api.inc"
                #Include "commctrl.inc"
                 %ID_TreeView = 100
                 
                Function PBMain() As Long
                    Local hDlg As Dword, hItem As Dword
                    Local hTemp As Dword, hTemp2 As Dword, hTemp3 As Dword
                    Dialog New Pixels, 0, "TreeView",200,200,155,250, %WS_SysMenu, 0 To hDlg
                    Control Add Treeview, hDlg, 100, "", 10,10,130,200, _
                        %WS_Child Or %WS_Visible Or %WS_TabStop Or %TVS_HasButtons Or _
                        %TVS_HasLines Or %TVS_LinesAtRoot Or %TVS_EditLabels Or _
                        %TVS_ShowSelAlways Or %TVS_TrackSelect Or %TVS_InfoTip, _
                        %WS_Ex_ClientEdge Or %WS_Ex_StaticEdge Or %WS_Ex_DlgModalFrame Or _
                        %WS_Ex_AcceptFiles Or %WS_Ex_Left Or %WS_Ex_LtrReading Or _
                        %WS_Ex_RightScrollbar'   Call TVProc
                 
                    Treeview Insert Item hDlg, 100, 0, %TVI_Last, 2,2,"Top" To hItem
                 
                    Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 2,4,"Mother" To hTemp
                       Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Dan" To hTemp2
                       Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Bob" To hTemp3
                          Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Foot" To hTemp2
                          Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Arm" To hTemp2
                 
                    Treeview Insert Item hDlg, 100, hItem, %TVI_Last, 1,4,"Father" To hTemp
                       Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 2,4,"Helen" To hTemp2
                       Treeview Insert Item hDlg, 100, hTemp, %TVI_Last, 1,4,"Amy" To hTemp3
                          Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 2,4,"Leg" To hTemp2
                          Treeview Insert Item hDlg, 100, hTemp3, %TVI_Last, 1,4,"Finger" To hTemp2
                    Control Add Button,   hDlg, 200, "Walk", 10, 219, 40, 21
                    Control Add Label,    hDlg, 300, "<node>", 60, 219, 34, 21, %WS_BORDER
                    Control Add Combobox, hDlg, 400, , 105, 219, 45, 120
                 
                    Dialog Show Modal hDlg Call DlgProc
                End Function
                 
                CallBack Function DlgProc() As Long
                 Dim hTree As Dword, hUpNode As Dword, hTVEdit As Dword, temp$, temp2$
                 Static hNode As Dword
                    If Cb.Msg = %WM_Command And Cb.Ctl = 200 Then
                       If hNode = 0 Then  Treeview Get Select Cb.Hndl, %ID_TreeView To hNode
                    End If
                 
                    If Cb.Msg = %WM_Command And Cb.Ctl = %IdOk Then
                       If Cb.CtlMsg = %BN_Clicked Then
                          Control Handle Cb.Hndl, 100 To hTree
                          Dim hCombo As Dword
                          Control Handle Cb.Hndl, 400 To hCombo
                             If GetFocus = hTree Then
                                MsgBox "Treeview node? ok"
                             ElseIf GetParent(GetFocus) = hTree Then
                                MsgBox "Treeview edit ok"
                             ElseIf GetParent(GetFocus) = hCombo Then
                                MsgBox "ComboBox edit ok"
                             End If
                       End If
                    End If
                 
                    If Cb.Msg = %WM_Notify And Cb.Ctl = 100 Then                ' 100 = %ID_TreeView
                         Select Case Cb.NmCode
                                    Case %TVN_BeginLabelEdit
                                      Control Handle Cb.Hndl, 100 To hTree
                                      hTVEdit = Treeview_GetEditControl(hTree)  'handle of TreeView edit control
                                      Control Get Text hTree, GetDlgCtrlID(hTVEdit) To temp$  'get original text
                                      Control Send hTree, GetDlgCtrlID(hTVEdit), %EM_LIMITTEXT, 25, 0   '25 char max
                 
                                    Case %TVN_EndLabelEdit
                                      hTVEdit = Treeview_GetEditControl(hTree)   'handle of TreeView edit control
                                      Control Get Text hTree, GetDlgCtrlID(hTVEdit) To temp2$  'get new text
                                      Function = 1     '1=new text  0=original text
                         End Select
                    End If
                End Function
                Rgds, Dave

                Comment


                • #9
                  Why can't i make the label edit to work?
                  F2 should invoke edit right?
                  hellobasic

                  Comment


                  • #10
                    Think about using GetFocus() to discriminate between Enter key responses - gets a little more difficult
                    To make things interesting, let's say IDOK is suppose to close the dialog except
                    when editing a treeview label or text in the combo box. I know you can use a flag,
                    but I wanted to point out that your code in its current form is problematic.
                    Dominic Mitchell
                    Phoenix Visual Designer
                    http://www.phnxthunder.com

                    Comment


                    • #11
                      Don't know about F2 but if you click once, then slooowwww click a second time that should go into edit mode.
                      (PS Gary's original code had some wrong IDs in that section of the DlgProc function)
                      Rgds, Dave

                      Comment


                      • #12
                        Wouldn't you normally use IDCANCEL to close a dialog?
                        Can you explain where you see the problem please (not doubting just not seeing )
                        Rgds, Dave

                        Comment


                        • #13
                          Why can't i make the label edit to work?
                          F2 should invoke edit right?
                          That behaviour is not native to the standard treeview. To get it to behave like the one
                          in Windows Explorer, you will have to send TVM_EDITLABEL in response to WM_KEDOWN(VK_F2).
                          Dominic Mitchell
                          Phoenix Visual Designer
                          http://www.phnxthunder.com

                          Comment


                          • #14
                            Wouldn't you normally use IDCANCEL to close a dialog?
                            Dialogs were envisioned to be simple windows, therefore, both IDOK and IDCANCEL are used to close a dialog.

                            IDOK -> close the dialog and accept the input.
                            IDCANCEL -> close the dialog and discard the input.

                            Can you explain where you see the problem please (not doubting just not seeing )
                            Let's say IDOK is suppose to close the dialog, but we don't want to close when the user simply presses
                            the Enter key to indicate end of label editing and that changes to the label should be accepted. IDCANCEL
                            (Esc key) while editing, indicates end of editing label, but discard changes.
                            Under this scenario, your code will always close the dialog even when the user has just finished editing a label.
                            Dominic Mitchell
                            Phoenix Visual Designer
                            http://www.phnxthunder.com

                            Comment


                            • #15
                              Ok I think I start to see what you are saying but seems to me that in this (not so simple) dialog you will have to add code to have either the IDOK or IDCANCEL message actually send a Dialog End (EndDialog in SDK) message. Wouldn't that normally be the case?

                              Certainly as the sample code stands, hitting the enter key while in LV Edit mode completes the editting and TVN_EndLabelEdit is fired - no sign of the dialog trying to exit.
                              Rgds, Dave

                              Comment


                              • #16
                                When I first started working with the combobox/treeview in-place
                                editing I kept thinking of the edit box as part of the parent - not
                                a separate control with its own ID and messages/notifications. Somehow
                                what I read never seemed to bring it to my attention the way
                                these posts have done.

                                Dave,
                                Thanks for the code, which makes use of the idea that the edit
                                box has focus, not the parent of the edit box.

                                Dominic,
                                Other than needing to adjust the code as Dave mentioned, is there
                                still an issue with his general approach that you're concerned with?
                                I couldn't tell if you were concerned about the code specifics, or
                                a general limitation of some kind.

                                I appreciate the comments from you both.

                                As I noted earlier I was also able to make my code work by sending
                                IDOK to a combobox callback, saving the dialog callback for the
                                IDOK of the Treeview. With Dave's code I could eliminate the
                                combobox callback.

                                But I haven't yet figure out why the IDOK will go to a combobox callback
                                but not to a Treeview callback. Do either of you understand
                                that behavior? (Dominic, I read your earlier post, but I'm not sure
                                if it answered the question or if you meant to direct me to a different solution).
                                Last edited by Gary Beene; 12 Apr 2009, 09:20 AM.

                                Comment


                                • #17
                                  Ok I think I start to see what you are saying but seems to me that in this (not so simple)
                                  dialog you will have to add code to have either the IDOK or IDCANCEL message actually send
                                  a Dialog End (EndDialog in SDK) message. Wouldn't that normally be the case?
                                  Yes, because when IDOK or IDCANCEL is received, it means the dialog should close.
                                  And depending on the message that caused WM_COMMAND(IDCANCEL) to be generated, you
                                  don't even have to call EndDialog.
                                  Dominic Mitchell
                                  Phoenix Visual Designer
                                  http://www.phnxthunder.com

                                  Comment


                                  • #18
                                    Code:
                                    But I haven't yet figure out why the IDOK will go to a combobox callback
                                    but not to a Treeview callback.
                                    Treeview controls do not send WM_COMMAND messages.

                                    (Dominic, I read your earlier post, but I'm not sure
                                    if it answered the question or if you meant to direct me to a different solution).
                                    I thought you did not want to receive WM_COMMAND(IDOK) when the Enter key was pressed
                                    while editing a treeview label.
                                    Dominic Mitchell
                                    Phoenix Visual Designer
                                    http://www.phnxthunder.com

                                    Comment


                                    • #19
                                      And depending on the message that caused WM_COMMAND(IDCANCEL) to be generated, you
                                      don't even have to call EndDialog.
                                      Another teaser
                                      Intrigued, can you give an example please?
                                      Rgds, Dave

                                      Comment


                                      • #20
                                        That callback procedure is incorrect in some other places, not related to the WM_COMMAND/IDOK (explained by the MSDN entry) ...

                                        When processing WM_NOTIFY, CB.CTL and CB.CTLMSG should be CB.NMID and CB.NMCODE. CB.CTL and CB.CTLMSG are only valid when CB.MSG is WM_COMMAND (documented).

                                        When working with the edit control ( getting the text), DDT statements (CONTROL GET TEXT) should not be used, since that edit control was not created using a CONTROL ADD statement. (GetWindowText() would be a good option)

                                        MCM
                                        Michael Mattias
                                        Tal Systems (retired)
                                        Port Washington WI USA
                                        [email protected]
                                        http://www.talsystems.com

                                        Comment

                                        Working...
                                        X