Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Listview with editable text and date picker

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

  • Listview with editable text and date picker

    A simple listview with editable text, date picker, and combobox field

    Click image for larger version  Name:	ListviewWithControl.png Views:	1 Size:	28.9 KB ID:	779339

    Code:
    #COMPILE EXE '#Win#
    #DIM ALL
    #INCLUDE "Win32Api.inc"
    #INCLUDE "CommCtrl.inc"
    #IF %PB_REVISION < &H1000
     #RESOURCE "MyResource.pbr"
     MACRO ComboBox_SetItemHeight(hwndCtl, index, cyItem)=SendMessage(hwndCtl, %CB_SETITEMHEIGHT, index, cyItem)
     MACRO ComboBox_SetText(hwndCtl, lpsz)=SetWindowText(hwndCtl, lpsz)
     MACRO ComboBox_GetText(hwndCtl, lpch, cchMax)=GetWindowText(hwndCtl, lpch, cchMax)
    #ELSE
     #RESOURCE MANIFEST, 1, "xpTheme.xml"
    #ENDIF
    
    GLOBAL hDlg       AS DWORD
    GLOBAL hListView  AS DWORD
    GLOBAL hEdit      AS DWORD
    GLOBAL hDatePick  AS DWORD
    GLOBAL hCombo     AS DWORD
    GLOBAL hComboEdit AS DWORD
    GLOBAL pComboEdit AS DWORD
    
    %Listview = 101
    %Edit     = 201
    %DatePick = 301
    %Combo    = 401
    '______________________________________________________________________________
    
    FUNCTION ListViewPopulate()AS LONG
     LOCAL ListviewColumnInfo AS LVCOLUMN
     LOCAL ListViewItem       AS LVITEM
     LOCAL zBuffer            AS ASCIIZ * 255
     LOCAL ROW                AS LONG
     LOCAL COL                AS LONG
     LOCAL ItemIndex          AS LONG
    
     ListviewColumnInfo.mask    = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM OR %LVCF_WIDTH
     ListviewColumnInfo.fmt     = %LVCFMT_CENTER
     ListviewColumnInfo.cx      = 150
     ListviewColumnInfo.pszText = VARPTR(zBuffer)
    
     zBuffer = "Editable Text"   : LISTVIEW_INSERTCOLUMN(hListview, 1, ListviewColumnInfo)
     zBuffer = "Editable Date"   : LISTVIEW_INSERTCOLUMN(hListview, 2, ListviewColumnInfo)
     zBuffer = "Combobox choice" : LISTVIEW_INSERTCOLUMN(hListview, 3, ListviewColumnInfo)
    
     FOR ROW = 0 TO 4
       zBuffer = "Row " & FORMAT$(ROW, "00") & " Col " & FORMAT$(0, "00")
       ListViewItem.stateMask = %LVIS_FOCUSED
       ListViewItem.pszText   = VARPTR(zBuffer)
       ListViewItem.iSubItem  = 0 'Name column
       ListViewItem.mask      = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
       ListViewItem.iItem     = ROW
       ListViewItem.lParam    = ROW
       SendMessage(hListview, %LVM_INSERTITEM, 0, VARPTR(ListViewItem)) 'Returns the index of the new item if successful, or -1 otherwise.
    
       ListViewItem.mask      = %LVIF_TEXT
       ListViewItem.iSubItem  = 1
       zBuffer = "2020-" & FORMAT$(ROW + 1, "00") & "-" & FORMAT$(5 * ROW + 1, "00")
       SendMessage(hListview, %LVM_SETITEM, 0, VARPTR(ListViewItem))
    
       ListViewItem.iSubItem  = 2
       zBuffer = "Row " & FORMAT$(ROW, "00") & " Col " & FORMAT$(ItemIndex, "00")
       SendMessage(hListview, %LVM_SETITEM, 0, VARPTR(ListViewItem))
     NEXT
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION ComboEditProc(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
     LOCAL pNcRec AS NCCALCSIZE_PARAMS POINTER
    
     SELECT CASE Msg
    
       CASE %WM_NCCALCSIZE
         pNcRec = lParam
         @pNcRec.rgrc(0).nTop = @pNcRec.rgrc(0).nTop - 1 'Move the client area aka edit part 1 pixels up in the edit control
         FUNCTION = DefWindowProc(hWnd, %WM_NCCALCSIZE, wParam, lParam)
         EXIT FUNCTION
    
        CASE %WM_DESTROY
          SetWindowLong(hWnd, %GWL_WNDPROC, pComboEdit)
    
     END SELECT
    
     FUNCTION = CallWindowProc(pComboEdit, hWnd, Msg, wParam, lParam) 'Send unprocessed messages to the original procedure
    
    END FUNCTION
    '_____________________________________________________________________________
    
    CALLBACK FUNCTION DlgProc
     LOCAL  pNotify         AS NMHDR POINTER
     LOCAL  pListviewNotify AS NMLISTVIEW POINTER
     LOCAL  pDateTimeNotify AS NMDATETIMECHANGE POINTER
     LOCAL  CellRect        AS RECT
     LOCAL  SysTime         AS SYSTEMTIME
     LOCAL  zText           AS ASCIIZ * 255
     STATIC hListviewHeader AS DWORD
     STATIC ListviewRow     AS LONG
     STATIC ListviewCol     AS LONG
    
     SELECT CASE CBMSG
    
       CASE %WM_INITDIALOG
         hListviewHeader = SendMessage(hListView, %LVM_GETHEADER, 0, 0)
         ListViewPopulate
    
       CASE %WM_COMMAND
         SELECT CASE CBCTL
    
           CASE %Edit
             IF CBCTLMSG = %EN_KILLFOCUS THEN
               SendMessage(hDlg, %WM_APP, %Edit, 0)
             END IF
    
           CASE %Combo
             IF CBCTLMSG = %CBN_KILLFOCUS THEN
               SendMessage(hDlg, %WM_APP, %Combo, 0)
             END IF
    
           CASE %IDOK
             IF GetFocus() = hEdit THEN
               SendMessage(hDlg, %WM_APP, %Edit, 0)
             END IF
             IF GetFocus() = hDatePick THEN
               SendMessage(hDlg, %WM_APP, %DatePick, 0)
             END IF
             IF GetFocus() = hCombo THEN
               SendMessage(hDlg, %WM_APP, %Combo, 0)
             END IF
    
           CASE %IDCANCEL
             IF GetFocus() = hEdit THEN
               ListviewRow = -1
               ShowWindow(hEdit, %SW_HIDE)
             END IF
             IF GetFocus() = hDatePick THEN
               ListviewRow = -1
               ShowWindow(hDatePick, %SW_HIDE)
             END IF
             IF GetFocus() = hCombo THEN
               ListviewRow = -1
               ShowWindow(hCombo, %SW_HIDE)
             END IF
    
         END SELECT
    
       CASE %WM_APP
         SELECT CASE CBWPARAM
    
           CASE %Edit 'Hide edit and update listview
             ShowWindow(hEdit, %SW_HIDE)
             GetDlgItemText(hListView, %Edit, zText, SIZEOF(zText))
             ListView_SetItemText(hListView, ListviewRow, ListviewCol, zText)
    
           CASE %DatePick  'Hide date picker and update listview
             ShowWindow(hDatePick, %SW_HIDE)
             SendMessage(hDatePick, %DTM_GETSYSTEMTIME, %NULL, BYVAL VARPTR(SysTime))
             zText = FORMAT$(SysTime.wYear, "0000") & "-" & FORMAT$(SysTime.wMonth, "00") & "-" & FORMAT$(SysTime.wDay, "00")
             ListView_SetItemText(hListView, ListviewRow, ListviewCol, zText)
    
           CASE %Combo  'Hide Combo and update listview
             ShowWindow(hCombo, %SW_HIDE)
             ComboBox_GetText(hCombo, zText, SIZEOF(zText))
             ListView_SetItemText(hListView, ListviewRow, ListviewCol, zText)
    
         END SELECT
    
       CASE %WM_NOTIFY
         pNotify = CBLPARAM
    
         'Listview header notification -------------------------------------------
         IF @pNotify.hwndFrom = hListviewHeader THEN
           'User is dragging a listview header or a divider
           IF @pNotify.code = %HDN_BEGINTRACK OR @pNotify.code = %HDN_BEGINTRACKW OR @pNotify.code = %HDN_BEGINDRAG THEN
             PostMessage(hDlg, %WM_COMMAND, MAK(DWORD, %IDCANCEL, %BN_CLICKED), 0) 'Cancel text or date edition
           END IF
         END IF
    
         'Listview notification --------------------------------------------------
         IF @pNotify.hwndFrom = hListView THEN
           pListviewNotify = pNotify
           SELECT CASE @pListviewNotify.hdr.code
             CASE %NM_CLICK
               ListviewRow = @pListviewNotify.iItem
               IF ListviewRow <> -1 THEN 'Click was made on an item
                 ListviewCol    = @pListviewNotify.iSubItem
    
                 'Get item rect
                 CellRect.nTop  = ListviewCol
                 CellRect.nLeft = %LVIR_LABEL
                 SendMessage(hListView, %LVM_GETSUBITEMRECT, ListviewRow, BYVAL VARPTR(CellRect)) 'Get subItem rect
    
                 'Get item text
                 ListView_GetItemText(hListView, ListviewRow, ListviewCol, zText, SIZEOF(zText))
    
                 'SetWindowText(hDlg, "[" & zText & "]" & STR$(ListviewRow) & STR$(ListviewCol) & _
                 '                    STR$(CellRect.nLeft) & STR$(CellRect.nRight) & _
                 '                    STR$(CellRect.nTop) & STR$(CellRect.nBottom))
    
                 IF ListviewCol = 0 THEN 'Clicked on an editable text cell
                   SetDlgItemText(hListView, %Edit, zText) 'Set edit control text
                   MoveWindow(hEdit, CellRect.nLeft, CellRect.nTop, _ 'Move and size control at listview cell coordinates
                              CellRect.nRight - CellRect.nLeft, CellRect.nBottom - CellRect.nTop, %TRUE)
                   ShowWindow(hEdit, %SW_SHOW) 'Make edit control visible
                   SendMessage(hDlg, %WM_NEXTDLGCTL, hEdit, %TRUE) 'Set focus
                 END IF
    
                 IF ListviewCol = 1 THEN 'Clicked on a date cell
                   SysTime.wYear  = VAL(PARSE$(zText, "-", 1)) 'Get cell date year
                   SysTime.wMonth = VAL(PARSE$(zText, "-", 2)) 'Get cell date month
                   SysTime.wDay   = VAL(PARSE$(zText, "-", 3)) 'Get cell date day
                   SendMessage(hDatePick, %DTM_SETSYSTEMTIME, %GDT_VALID, BYVAL VARPTR(SysTime)) 'Set initial DatePicker date
                   MoveWindow(hDatePick, CellRect.nLeft, CellRect.nTop, _ 'Move and size control at listview cell coordinates
                              CellRect.nRight - CellRect.nLeft, CellRect.nBottom - CellRect.nTop, %TRUE)
                   ShowWindow(hDatePick, %SW_SHOW) 'Make control visible
                   SendMessage(hDlg, %WM_NEXTDLGCTL, hDatePick, %TRUE) 'Set focus
                 END IF
    
                 IF ListviewCol = 2 THEN 'Clicked on a combobox
                   ComboBox_SetText(hCombo, zText) 'Set combobox-edit text
                   MoveWindow(hCombo, CellRect.nLeft, CellRect.nTop -1, _ 'Move and size control at listview cell coordinates
                              CellRect.nRight - CellRect.nLeft, CellRect.nBottom - CellRect.nTop, %TRUE)
                   ComboBox_SetItemHeight(hCombo, -1, CellRect.nBottom - CellRect.nTop - 4) 'Set combobox height, see combo subclass
                   ShowWindow(hCombo, %SW_SHOW) 'Make control visible
                   SendMessage(hDlg, %WM_NEXTDLGCTL, hCombo, %True)  'Set focus
                 END IF
    
               END IF
           END SELECT
         END IF
    
         'Date picker notification -----------------------------------------------
         IF @pNotify.hwndFrom = hDatePick THEN
           pDateTimeNotify = pNotify
           SELECT CASE LONG CBNMCODE
             CASE %NM_KILLFOCUS
               'Hide datepicker and update listview cell
               SendMessage(hDlg, %WM_APP, %DatePick, 0)
           END SELECT
         END IF
    
       CASE %WM_SIZE
         IF CBWPARAM <> %SIZE_MINIMIZED THEN
           MoveWindow(hListview, 5, 5, LOWRD(CBLPARAM) - 10, HIWRD(CBLPARAM) - 10, %TRUE)
         END IF
    
      END SELECT
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION PBMAIN()
     LOCAL hIcon AS DWORD
    
     DIALOG FONT "Segoe UI", 9
     DIALOG NEW %HWND_DESKTOP, "ListView with editable text, date, and combobox field", , , 280, 80, _
     %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_SYSMENU OR %WS_THICKFRAME, 0 TO hDlg
    
     hIcon = ExtractIcon(GetModuleHandle(""), "Shell32.dll", 294)
     SetClassLong(hDlg, %GCL_HICON, hIcon) 'Set dialog icon
     SendMessage(hDlg, %WM_SETICON, %ICON_SMALL, hIcon)
    
     CONTROL ADD "SysListView32", hDlg, %Listview, "SysListView321", 5, 5, 340, 230, _
     %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_TABSTOP OR %LVS_REPORT OR _
     %LVS_SHOWSELALWAYS, %WS_EX_LEFT OR %WS_EX_RIGHTSCROLLBAR '%LVS_SORTASCENDING OR
     hListview = GetDlgItem(hDlg, %Listview)
     LISTVIEW_SETEXTENDEDLISTVIEWSTYLE(hListview, ListView_GetExtendedListViewStyle(hListview) OR _
     %LVS_EX_FULLROWSELECT OR %LVS_EX_DOUBLEBUFFER OR %LVS_EX_HEADERDRAGDROP OR %LVS_EX_GRIDLINES)
    
     CONTROL ADD TEXTBOX, hDlg, %Edit, "Edit", 0, 0, 0, 0
     hEdit = GetDlgItem(hDlg, %Edit)
     SetParent(hEdit, hListview)
     ShowWindow(hEdit, %SW_HIDE)
    
     CONTROL ADD "SysDateTimePick32", hDlg, %DatePick, "", 0, 0, 0, 0, _
     %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING
     hDatePick = GetDlgItem(hDlg, %DatePick)
     SetParent(hDatePick, hListview)
     ShowWindow(hDatePick, %SW_HIDE)
    
     DIM MyArray(2) AS STRING
     ARRAY ASSIGN MyArray() = "Öö Ÿÿ j q y", "Hi", "Frank"
     CONTROL ADD COMBOBOX, hDlg, %Combo, MyArray(), 0, 0, 0, 0, _
     %CBS_DROPDOWN OR %WS_TABSTOP, %WS_EX_LEFT
     hCombo = GetDlgItem(hDlg, %Combo)
     SetParent(hCombo, hListview)
     ShowWindow(hCombo, %SW_HIDE)
    
     'Get combo edit control handle and subclass it
     LOCAL ComboboxInf AS COMBOBOXINFO
     ComboboxInf.cbSize = SIZEOF(COMBOBOXINFO)
     GetComboBoxInfo(hCombo, BYVAL VARPTR(ComboboxInf))
     hComboEdit = ComboboxInf.hwndItem
     pComboEdit = SetWindowLong(hComboEdit, %GWL_WndProc, CODEPTR(ComboEditProc))
    
     DIALOG SHOW MODAL hDlg CALL DlgProc
    
     DestroyIcon(hIcon)
    
    END FUNCTION
    '______________________________________________________________________________
    '
    Last edited by Pierre Bellisle; 25 Mar 2019, 07:27 PM.
Working...
X