PlanetSquires Forums

Support Forums => Other Software and Code => Topic started by: Petrus Vorster on May 10, 2015, 06:20:21 PM

Title: Grid type Control
Post by: Petrus Vorster on May 10, 2015, 06:20:21 PM
I have never used a grid control in any of my programs.
(A listview for display of info yes, but not for user inputs)
I have taken a look at mylittlegrid, but can seem to find any related help in the documentation.
Is there some free control out there that one can use where i can change the headers and allow controlled user input in columns and rows?
Title: Re: Grid type Control
Post by: David Kenny on May 11, 2015, 01:38:09 PM
Peter,

This is not a direct answer to your inquiry, but I thought it worth mentioning. You can use the list view as you do now.  When a user performs an action that your program takes as a signal to start edit mode (ie, single click or double-click on an item) you create an edit box over the top of the item and process the input yourself.  Not trivial, but doable.  There are examples on PB's forums.  None use SDK style programming so you would have to convert from DDT. Search for "editable listview".

David
Title: Re: Grid type Control
Post by: Petrus Vorster on May 11, 2015, 02:11:14 PM
Ok, i can give that a shot, thanks. Sounds workable!
Unless of course i buy the little grid  :)
How does users find the registered version?
Title: Re: Grid type Control
Post by: Petrus Vorster on May 11, 2015, 02:16:17 PM
Something Gary Beene posted on the Pb forums:
'Compilable Example:
#Compiler PBWin 10
#Compile Exe
#Dim All
%Unicode=1
#Include "win32api.inc"  'Jose Roca includes

Enum Equates Singular
   IDC_ListView     = 500
   IDM_Demo
End Enum

Global hDlg, hListView As Dword, SortDirection As Long
Global MaxRow, MaxCol, CurrentRow, CurrentCol, OrigLVProc As Long

Function PBMain() As Long
   Dialog New Pixels, 0, "ListView Grid Demo",300,300,400,220, %WS_OverlappedWindow To hDlg
   CreateListView
   Dialog Show Modal hDlg Call DlgProc
End Function

CallBack Function DlgProc() As Long
   Local i,j As Long, pLVDI As LV_DISPINFO Ptr, lplvcd As NMLVCUSTOMDRAW Ptr
   Select Case Cb.Msg
      Case %WM_InitDialog
         'initialize data/location
         CreateLVData
         CurrentRow = 1 : CurrentCol = 1
         UpdateStatusBar
         BuildAcceleratorTable
         OrigLVProc = SetWindowLong(hListView, %GWL_WndProc, CodePtr(NewLVProc))  'subclass LV
      Case %WM_Destroy
         SetWindowLong hListView, %GWL_WNDPROC, OrigLVProc
      Case %WM_Command
         Select Case Cb.Ctl
            Case %IDM_Demo    'Ctrl-D to run the Demo
               For i = 1 To 3
                  CurrentCol = i
                  For j = 1 To 10
                     CurrentRow = j  : Sleep 250
                     UpdateStatusBar : Control ReDraw hDlg, %IDC_ListView
                  Next j
               Next i
         End Select
      Case %WM_Notify
         Select Case Cb.NmId
            Case %IDC_ListView
               Select Case Cb.NmCode
                  Case %NM_CustomDraw
                       lpLvCd = CbLParam
                       Select Case @lplvcd.nmcd.dwDrawStage
                          Case %CDDS_PREPAINT, %CDDS_ITEMPREPAINT
                             Function = %CDRF_NOTIFYSUBITEMDRAW
                          Case %CDDS_ITEMPREPAINT Or %CDDS_SUBITEM
                             If  @lplvcd.nmcd.dwItemSpec = CurrentRow-1 Then
                                If @lpLvCd.iSubItem <> CurrentCol-1 Then
                                   @lpLvCd.clrTextBk = %White
                                Else
                                   @lpLvCd.clrTextBk = %Green
                                End If
                             End If
                           Function = %CDRF_NEWFONT
                       End Select
               End Select
         End Select
   End Select
End Function

Sub CreateListView
   Control Add ListView, hDlg, %IDC_ListView,"", 10,10,380,200
   Control Handle hDlg, %IDC_ListView To hListView
   ListView Set StyleXX hDlg, %IDC_ListView, %LVS_Ex_CheckBoxes Or %LVS_Ex_GridLines Or %LVS_Ex_FullRowSelect
End Sub

Sub CreateLVData
   Local i,j As Long
   MaxRow = 50    : MaxCol = 10
   For i = 1 To MaxCol
      ListView Insert Column hDlg, %IDC_ListView, i, "Col" + Trim$(Str$(i)), 100, 0
   Next i
   For i = 1 To MaxRow
      ListView Insert Item hDlg, %IDC_ListView, i,0, "Row " + Trim$(Str$(i))
      For j = 1 To MaxCol
         ListView Set Text hDlg, %IDC_ListView, i, j, "Row" + Trim$(Str$(i)) + " Col" + Trim$(Str$(j))
      Next j
   Next i
End Sub

Sub BuildAcceleratorTable
   Local c As Long, ac() As ACCELAPI, hAccelerator As Dword  ' for keyboard accelator table values
   Dim ac(0)
   ac(c).fvirt = %FVIRTKEY Or %FCONTROL : ac(c).key   = %VK_D : ac(c).cmd   = %IDM_Demo  : Incr c
   Accel Attach hDlg, AC() To hAccelerator
End Sub

Sub UpdateStatusBar
   Dialog Set Text hDlg, "ListView Grid Demo:  " + Str$(CurrentRow) + Str$(CurrentCol)
End Sub

Function NewLVProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   Local hdnptr As HD_NOTIFY Ptr, hdiptr As HD_ITEM Ptr, w,iResult As Long
   Local LpLvNm As NM_LISTVIEW Ptr, LVHT As LVHitTestInfo
   Select Case Msg
      Case %WM_KeyDown
         Select Case wParam
            Case %VK_Up
               CurrentRow = Max(1,CurrentRow-1)
               UpdateStatusBar
               Control ReDraw hDlg, %IDC_ListView
            Case %VK_Down
               CurrentRow = Min(MaxRow,CurrentRow+1)
               UpdateStatusBar
               Control ReDraw hDlg, %IDC_ListView
            Case %VK_Left
               CurrentCol = Max(1,CurrentCol-1)
               UpdateStatusBar
               Control ReDraw hDlg, %IDC_ListView
            Case %VK_Right
               CurrentCol = Min(MaxCol,CurrentCol+1)
               UpdateStatusBar
               Control ReDraw hDlg, %IDC_ListView
            Case %VK_Pgup
               Dialog Set Text hDlg, "PageUp"   'not sure what row/col this corresponds to
            Case %VK_PgDn
               Dialog Set Text hDlg, "PageDown" 'not sure what row/col this corresponds to
            Case %VK_Home
               CurrentCol = 1
               If GetKeyState(%VK_Control) Then CurrentRow = 1
               Control ReDraw hDlg, %IDC_ListView
               UpdateStatusBar
            Case %VK_End
               CurrentCol = MaxCol
               If GetKeyState(%VK_Control) Then CurrentRow = MaxRow
               Control ReDraw hDlg, %IDC_ListView
               UpdateStatusBar
        End Select
   End Select
   Function = CallWindowProc(OrigLVProc, hWnd, Msg, wParam, lParam)
End Function

Will play around with this, it seems most of the tricks is in here.
Title: Re: Grid type Control
Post by: Petrus Vorster on May 11, 2015, 02:20:44 PM
Nope, just colored backgrounds. Will dig more....
Title: Re: Grid type Control
Post by: Petrus Vorster on May 11, 2015, 03:05:38 PM
Found a working example on the PB site. Simple, but effective.
#INCLUDE ONCE "WIN32API.INC"
#INCLUDE ONCE "COMMCTRL.INC"
#INCLUDE ONCE "PBForms.INC"

%IDD_DIALOG1   =  101
%IDC_LISTVIEW1 = 1001
%IDC_TEXTBOX1  = 1002

FUNCTION PBMAIN()
    PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR _
        %ICC_INTERNET_CLASSES)
    ShowDIALOG1 %HWND_DESKTOP
END FUNCTION

CALLBACK FUNCTION ShowDIALOG1Proc()
    LOCAL my_LpLvNm AS NM_LISTVIEW PTR
    STATIC LVRow AS LONG, LVCol AS LONG
    STATIC hListView AS LONG, i AS LONG, x AS LONG, y AS LONG, txtv AS STRING, datav AS LONG
    STATIC SIrect AS RECT

    SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
            ' Initialization handler
            CONTROL HANDLE CBHNDL, %IDC_LISTVIEW1 TO hListView

        CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CB.WPARAM THEN
                ' Save control focus
                hWndSaveFocus = GetFocus()
            ELSEIF hWndSaveFocus THEN
                ' Restore control focus
                SetFocus(hWndSaveFocus)
                hWndSaveFocus = 0
            END IF

        CASE %WM_NOTIFY
            IF LOWRD(CBWPARAM)= %IDC_LISTVIEW1 THEN
                    my_LpLvNm = CBLPARAM
                    SELECT CASE @my_LpLvNm.hdr.code
                        CASE %NM_CLICK
                            'cursor position
                            LVRow = @my_LpLvNm.iItem
                            LVCol = @my_LpLvNm.iSubItem
                            LISTVIEW UNSELECT CBHNDL, %IDC_LISTVIEW1, LVRow + 1
                            i = ListView_GetSubItemRect(hListView, LVRow, LVCol, %LVIR_BOUNDS, VARPTR(SIrect))
                            CONTROL GET LOC CBHNDL, %IDC_LISTVIEW1 TO x, y
                            IF LVCol = 0 THEN
                                LISTVIEW GET COLUMN CBHNDL, %IDC_LISTVIEW1, 1 TO datav
                                CONTROL SET LOC CBHNDL, %IDC_TEXTBOX1, x + SIrect.nLeft + 6 , y + SIrect.nTop + 1
                                CONTROL SET SIZE CBHNDL, %IDC_TEXTBOX1, datav - 7 , SIrect.nBottom - SIrect.nTop
                            ELSE
                                CONTROL SET LOC CBHNDL, %IDC_TEXTBOX1, x + SIrect.nLeft + 7 , y + SIrect.nTop + 1
                                CONTROL SET SIZE CBHNDL, %IDC_TEXTBOX1, SIrect.nRight - SIrect.nLeft - 8 , SIrect.nBottom - SIrect.nTop
                            END IF
                            CONTROL NORMALIZE CBHNDL, %IDC_TEXTBOX1
                            CONTROL SET FOCUS CBHNDL, %IDC_TEXTBOX1
                            LISTVIEW GET TEXT CBHNDL, %IDC_LISTVIEW1, LVRow + 1,  LVCol + 1 TO txtv
                            CONTROL SET TEXT CBHNDL, %IDC_TEXTBOX1, txtv
                            FUNCTION = 1
                            EXIT FUNCTION
                    END SELECT
            END IF

        CASE %WM_COMMAND
            ' Process control notifications
            SELECT CASE AS LONG CB.CTL
                CASE %IDC_TEXTBOX1
                    IF CB.CTLMSG = %EN_CHANGE THEN
                        CONTROL GET TEXT CBHNDL, %IDC_TEXTBOX1 TO txtv
                        IF ISTRUE INSTR(txtv, $CRLF) THEN
                            CONTROL HIDE CBHNDL, %IDC_TEXTBOX1
                            txtv = REMOVE$(txtv, $CRLF)
                            LISTVIEW SET TEXT CBHNDL, %IDC_LISTVIEW1, LVRow + 1,  LVCol + 1, txtv
                        END IF
                    END IF
            END SELECT
    END SELECT

END FUNCTION

FUNCTION SampleListView(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lColCnt _
    AS LONG, BYVAL lRowCnt AS LONG) AS LONG
    LOCAL lCol   AS LONG
    LOCAL lRow   AS LONG
    LOCAL lStyle AS LONG

    LISTVIEW GET STYLEXX hDlg, lID TO lStyle
    LISTVIEW SET STYLEXX hDlg, lID, lStyle OR %LVS_EX_FULLROWSELECT OR _
        %LVS_EX_GRIDLINES

    ' Load column headers.
    FOR lCol = 1 TO lColCnt
        LISTVIEW INSERT COLUMN hDlg, lID, lCol, USING$("Column #", lCol), 0, 0
    NEXT lCol

    ' Load sample data.
    FOR lRow = 1 TO lRowCnt
        LISTVIEW INSERT ITEM hDlg, lID, lRow, 0, USING$("Column # Row #", _
            lCol, lRow)
        FOR lCol = 1 TO lColCnt
            LISTVIEW SET TEXT hDlg, lID, lRow, lCol, USING$("Column # Row #", _
                lCol, lRow)
        NEXT lCol
    NEXT lRow

    ' Auto size columns.
    FOR lCol = 1 TO lColCnt
        LISTVIEW FIT HEADER hDlg, lID, lCol
    NEXT lCol
END FUNCTION

FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG
    LOCAL hDlg  AS DWORD
    DIALOG NEW PIXELS, hParent, "Very Simple Editable Listview", , , _
        768, 372, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _
        %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME _
        OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
        %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
        %WS_EX_RIGHTSCROLLBAR, TO hDlg
    CONTROL ADD LISTVIEW, hDlg, %IDC_LISTVIEW1, "", 20, 20, 730, _
        330, %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %LVS_REPORT OR _
        %LVS_SHOWSELALWAYS, %WS_EX_LEFT
    CONTROL SET COLOR hDlg, %IDC_LISTVIEW1, %BLACK, RGB(225, 225, 255)
    CONTROL ADD TEXTBOX,  hDlg, %IDC_TEXTBOX1, "", 590, 0, 160, 20, %WS_CHILD _
        OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_LEFT OR %ES_AUTOHSCROLL OR %ES_MULTILINE OR %ES_WANTRETURN OR %ES_AUTOVSCROLL, _
        %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    CONTROL HIDE hDlg, %IDC_TEXTBOX1

    SampleListView hDlg, %IDC_LISTVIEW1, 7, 30

    DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    FUNCTION = lRslt
END FUNCTION
                                                                                               
Title: Re: Grid type Control
Post by: Klaas Holland on May 11, 2015, 06:16:28 PM
This is the SDK version build with FF-PB, but I did not get it converted to FF-FB jet.
Title: Re: Grid type Control
Post by: David Kenny on May 12, 2015, 06:12:39 AM
Very nice Klaas!

Did you start with a DDT example and convert it to SDK yourself or build from scratch? 


Peter,

Klaas saved you a bunch of work man.  This looks to me like it could easily be adapted to your needs.
Title: Re: Grid type Control
Post by: James Fuller on May 12, 2015, 09:37:33 AM
The issue I have with most of these ListView/Grid attempts is the lack of multiline headers.
Jose did have an example but I believe it failed with more than one listview in a window.
I hope Paul will have multi-line header text  in the FreeBasic grid he said he is working on.
This is a Report mode based on Patrice's(?) code for manipulating the header font.

James
Title: Re: Grid type Control
Post by: Petrus Vorster on May 12, 2015, 02:07:54 PM
Klaas, this is a neat piece of work!!!
I am very impressed!!!
Thanks a million.
Now show me another forum on the internet with help and support like this!!!

Problem solved! Will give due credits!!!!!!
Title: Re: Grid type Control
Post by: Paul Squires on May 12, 2015, 02:52:13 PM
Quote from: Klaas Holland on May 11, 2015, 06:16:28 PM
This is the SDK version build with FF-PB, but I did not get it converted to FF-FB jet.
Hi Klaas,

If you post your FreeBasic version then I will help fix it for you.
Title: Re: Grid type Control
Post by: Petrus Vorster on May 12, 2015, 02:56:46 PM
Man, this tool works like a charm!
So easy!
I am very impressed.
For now PB is fine, haven't really thought about doing a project in FB.

Nice thing about this is the listview headers in the Project is in Dutch which of course is mostly the same as my language.
Kind of making it feel like a very personalized help!

Full marks!
Title: Re: Grid type Control
Post by: Eddy Van Esch on May 12, 2015, 04:25:52 PM
Klaas,
thanks a lot for your fine example! This is really what I needed. ListViews are new to me and I didn't know where to start!

Something I noticed, when clicking on an item in column 2, a textbox appears on the cell, but I can not type any text in it. When I type a character I hear a 'ping' sound (some kind of windows sound message).
In column 4 I can type text in the ListView textbox and when I hit ENTER key, the text is stored in the LV. So that works as advertised.  :)
Thanks again!

Kind regards
Title: Re: Grid type Control
Post by: Eddy Van Esch on May 12, 2015, 04:29:42 PM
AAARRGGGHHH  ;D  Silly me! I typed text characters in the edit box while only numbers are allowed !!!!!   ::)  :o   ;D

Kind regards
Title: Re: Grid type Control
Post by: David Kenny on May 13, 2015, 03:05:15 AM
Klaas,

I have a bug report for your sample listview.  When running the program, change a column width so that you get a horizontal scrollbar to appear.  If you put either column 2 or 4 into edit mode and then scroll the horizontal scrollbar, you will get drawing artifacts as the edit box is not moving also.  Similar results when using the combobox.  You can quick-fix that by adding %WM_HSCROLL to the case under the FORMT1_LISTVIEW1_CUSTOM function.

Another bug would be that none of the controls are aware that the column they are drawn over might change in size. Or might get "off it's column" when another column is being resized.

Personally, I think I would try updating the controls location and size for all scroll and columnsize events and see if I couldn't keep the edit going instead of just ending it.  Although I do think it should be ended if it is pushed out of view by a scrolling or a columnsize event. But I'll put off working on those features for the next time I need an editable ListView. ;)
Title: Re: Grid type Control
Post by: Klaas Holland on May 13, 2015, 07:19:06 AM
David,

With help from this forum by Rudolf Furstauer.

I think the EditBox and Combobox should disappear when you try to do something else.

Paul,

Here is the FF-FB version.
I build the forms from scratch, so the Forms-functions must be Ok.
The parts that don't work are commented out.

Thanks it advance.

Btw.:   The Example Addressbook does not work either because of:

    If (Index <= UBound(gAddressBook(1))) And (Index >= LBound(gAddressBook(1))) Then
       Temp = gAddressBook(Index)
    End If
Title: Re: Grid type Control
Post by: David Kenny on May 13, 2015, 02:11:52 PM
Quote from: Klaas Holland on May 13, 2015, 07:19:06 AM
I think the EditBox and Combobox should disappear when you try to do something else.
Fair enough.

You just commented on the my ramblings about what I would do.  I just wanted to make sure that you did get that there are two bugs in the version you posted.  They are minor drawing artifacts and possible incorrect size/location of the edit or combo box that happen when either a column is resized when in edit mode, or when the user scrolls the listview in the horizontal (also while in edit mode).  Canceling the edit should work for either case.
Title: Re: Grid type Control
Post by: Paul Squires on May 13, 2015, 06:58:52 PM
Quote from: Klaas Holland on May 13, 2015, 07:19:06 AM
Paul,

Here is the FF-FB version.
I build the forms from scratch, so the Forms-functions must be Ok.
The parts that don't work are commented out.

Hi Klaas,

I have attached a working FreeBASIC example for you. I added additional code to the FB version that you had in your PB version (but was missing from your download attachment). The FB example should now run similar to your PB example.

You will also need to copy the attached FF_ListView_GetCountPerPage.inc file into your CodeStore/FreeBasic/ListView folder.
Title: Re: Grid type Control
Post by: Klaas Holland on May 14, 2015, 07:14:46 PM
Paul,

Thank you for your help, now I can study the differences between PB and FB.

David,

Thank you for your bug-report.
I think this will fix it:

'--------------------------------------------------------------------------------
Function FORMT1_LISTVIEW1_CUSTOM ( _
                                ControlIndex  As Long,  _  ' index in Control Array
                                hWndForm      As Dword, _  ' handle of Form
                                hWndControl   As Dword, _  ' handle of Control
                                wMsg          As Long,  _  ' type of message
                                wParam        As Dword, _  ' first message parameter
                                lParam        As Long   _  ' second message parameter
                                ) As Long

    Select Case wMsg
        Case %WM_PARENTNOTIFY, %WM_HSCROLL, %WM_VSCROLL, %WM_MOUSEWHEEL   
            FF_Control_ShowState HWND_FORMT1_TEXT1, %SW_HIDE
            FF_Control_ShowState HWND_FORMT1_COMBO2, %SW_HIDE

    End Select

End Function


I also updated the FF-PB version of May 11, 2015.

Klaas