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

Proportional resizing maintaining integral line height (PB Win 6 & 7)

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

  • PBWin Proportional resizing maintaining integral line height (PB Win 6 & 7)

    ' Proportional resizing maintaining integral line height (PB Win 6, 7 and 8).

    ' This skeleton program presents methods to ensure that after any resizing,
    ' the lowest text line in a textbox, listview, combobox, or listbox, is
    ' always displayed in full height (not clipped). Without adjustment the
    ' lowest text line may be partially displayed (clipped) after resizing.
    ' Proportional resizing is used, i.e. any control is resized in proportion
    ' to the resizing of the dialog window. The font size is never changed.
    ' So screens with higher resolutions and/or small fonts setting will just
    ' display a relatively larger number of lines. The number of displayable
    ' characters on each line will also change with resizing. This can be dealt
    ' with by including horizontal scroll bars in the controls to ensure that
    ' long lines may still be read even in reduced size controls.
    '
    ' Final Version, July 31, 2002:
    '
    ' The program has been revised extensively. The sizing routines are now in a
    ' separate include file: "SizeCtls.inc", which is in the subsequent post.
    ' The sizing routines, which sizes textbox, listview, listbox and
    ' combobox, may be used both with pixels (UNflag = 0) and dialog units
    ' (UNflag=1) as input to suit your needs. The routines can take into account
    ' the changing need for both vertical and horizontal scroll bars after
    ' resizing during run-time. You may experiment with different numbers of
    ' items in the various controls.
    '
    ' I thank the PowerBasic Forum for great inspiration and help, in particular
    ' Carlo Pagani and Lance Edmonds.
    '
    ' Best wishes
    '
    ' Erik Christensen ---- e.chr@email.dk
    '
    ' P.S. December 3, 2005. The program has been tested under PBWIN80, and it
    ' works without any problems in that version as well.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL        '  This is helpful to prevent errors in coding
    '
    '------------------------------------------------------------------------------
    ' Initial Declares - eliminate unnecessary macros in COMMCTRL.INC
    '------------------------------------------------------------------------------
    %NOANIMATE         = 1  ' Animate control
    '  %NOBUTTON          = 1  ' Button
    '  %NOCOMBO           = 1  ' Combo box
    %NOCOMBOEX         = 1  ' ComboBoxEx
    %NODATETIMEPICK    = 1  ' Date/time picker
    %NODRAGLIST        = 1  ' Drag list control
    '  %NOEDIT            = 1  ' Edit control
    %NOFLATSBAPIS      = 1  ' Flat scroll bar
    '  %NOHEADER          = 1  ' Header control
    %NOHOTKEY          = 1  ' HotKey control
    %NOIMAGELIST       = 1  ' Image APIs
    %NOIPADDRESS       = 1  ' IP Address edit control
    '  %NOLIST            = 1  ' List box control
    '  %NOLISTVIEW        = 1  ' ListView control
    %NOMENUHELP        = 1  ' Menu help
    %NOMONTHCAL        = 1  ' MonthCal
    %NOMUI             = 1  ' MUI
    %NONATIVEFONTCTL   = 1  ' Native Font control
    %NOPAGESCROLLER    = 1  ' Pager
    %NOPROGRESS        = 1  ' Progress control
    %NOREBAR           = 1  ' Rebar control
    '  %NOSTATUSBAR       = 1  ' Status bar
    %NOTABCONTROL      = 1  ' Tab control
    %NOTOOLBAR         = 1  ' Tool bar
    %NOTOOLTIPS        = 1  ' Tool tips
    %NOTRACKBAR        = 1  ' Track bar
    %NOTRACKMOUSEEVENT = 1  ' Track Mouse Event
    %NOTREEVIEW        = 1  ' TreeView
    %NOUPDOWN          = 1  ' Up Down arrow control
    ' ----------------------------------------------------------
    #INCLUDE "win32api.inc"     ' Win 32 API include file !
    #INCLUDE "commctrl.inc"
    '------------------
    GLOBAL hHead& ' This needs to be placed here.
    '
    ' Include file for sizing of controls:
    #INCLUDE "SizeCtls.inc" ' Be sure to provide the correct path.
    '
    ' *************************************************************
    '              Application Constants and Declares
    ' *************************************************************
    ' ----------------------------------------------------------
    %Form1_FILE                                     = 500
    %Form1_EXIT                                     = 530
    '
    %FORM1_TEXT1              = 105
    %FORM1_COMBOBOX1          = 110
    %FORM1_LISTBOX1           = 115
    %FORM1_BUTTON1            = 120
    %FORM1_BUTTON2            = 125
    %FORM1_LISTVIEW           = 130
    ' --------------------------------------------------
    DECLARE SUB CreateDialog_Form1(BYVAL hParent&)
    DECLARE CALLBACK FUNCTION Form1_DlgProc
    DECLARE FUNCTION SampleListView(BYVAL hDlg AS LONG, BYVAL lID AS LONG, BYVAL lColCnt AS _
        LONG, BYVAL lRowCnt AS LONG) AS LONG
    ' --------------------------------------------------
    DECLARE CALLBACK FUNCTION CBF_FORM1_BUTTON2()
    ' *************************************************************
    '            Application Global Variables and Types
    ' *************************************************************
    GLOBAL hForm1&    ' Dialog handle
    ' Global Handles for menus
    GLOBAL hForm1_Menu0&
    GLOBAL hForm1_Menu1&
    GLOBAL hCombo1&,hButton1&,hButton2&
    ' *************************************************************
    '                   Application Entrance
    ' *************************************************************
    FUNCTION PBMAIN ()AS LONG
        LOCAL Count&
        LOCAL CC1 AS INIT_COMMON_CONTROLSEX
        CC1.dwSize=SIZEOF(CC1)
        CC1.dwICC=%ICC_WIN95_CLASSES
        InitCommonControlsEX CC1
        CreateDialog_Form1 0
        ' Dialogs Handle in variable - hForm1&
        DIALOG SHOW MODELESS hForm1& , CALL Form1_DlgProc
        DO
            DIALOG DOEVENTS TO Count&
        LOOP UNTIL Count&=0
    END FUNCTION
    ' *************************************************************
    '                    Application Dialogs
    ' *************************************************************
    SUB CreateDialog_Form1(BYVAL hParent&)
        DIM Rct AS RECT
        LOCAL X&,Y&,X1&,Y1&,hDlg&,MPX&,MPY&,MUX&,MUY&
        LOCAL hDC&,Res&,Res2&
        LOCAL prc AS rect
        LOCAL I&,t$
        '
        ' Get dimension in pixels of Work Area on screen (desktop).
        SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(Rct), 0
        ' Get Max X pixels
        MPX = Rct.nRight - Rct.nLeft
        MPX = MPX - 2 * GetSystemMetrics(%SM_CXEDGE) - 4 ' Adjust for Dialog Edge (left and right)
        '                                                ' Allow for resizing
        ' Get Max Y pixels
        MPY = Rct.nBottom - Rct.nTop
        MPY = MPY - 2 * GetSystemMetrics(%SM_CYEDGE) ' Adjust for Dialog Edge (upper and lower)
        MPY = MPY - GetSystemMetrics(%SM_CYMENU)     ' Adjust for Menu height
        '
        ' Make temporary invisible dialog just to convert from pixels to dialog units.
        DIALOG NEW 0,"",,,0,0,, TO hDlg&
        DIALOG PIXELS hDlg&, MPX,MPY TO UNITS MUX,MUY
        DIALOG END hDlg& ' Close dialog
    
        LOCAL N&, CT&        '  Variables used for Reading Data in Arrays for Listbox and Combobox
        ' hParent& = 0 if no parent Dialog
        ' Make dialog to fill desktop work space.
        DIALOG NEW hParent&, "Proportional resizing maintaining integral line height", , ,MUX, MUY, %WS_POPUP OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR _
            %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS _
            OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
            %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_WINDOWEDGE OR _
            %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR, TO hForm1&
            ' The %WS_THICKFRAME style will create a dialog that has a sizing border.
            ' That is, the dialog will be resizable. NB: No status bar is necessary
            ' for this feature.
        ' ---------------------------
        MENU NEW BAR TO hForm1_Menu0&
        ' ---------------------------
        MENU NEW POPUP TO hForm1_Menu1&
        MENU ADD POPUP, hForm1_Menu0& ,"E&xit", hForm1_Menu1&, %MF_ENABLED
        MENU ADD STRING, hForm1_Menu1&, "E&xit",  %Form1_EXIT, %MF_ENABLED
        MENU ATTACH hForm1_Menu0&, hForm1&
        '
        ' The following controls are created using dummy position and size.
        ' They are resized to their initial position and size in
        ' SUB ResizeControls which is called in the %WM_INITDIALOG section of
        ' the windows callback function. Thus it is sufficient to specify the
        ' positions and sizes only once in SUB ResizeControls.
        CONTROL ADD "Button", hForm1&,  %FORM1_BUTTON1,  "Button &1", 100,100,100,100, _
            %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP, 0
        CONTROL HANDLE hForm1&,  %FORM1_BUTTON1 TO hButton1&
        CONTROL ADD TEXTBOX, hForm1&,  %FORM1_TEXT1,"", 100,100,100,100, _
            %WS_CHILD OR %WS_VISIBLE OR %ES_MULTILINE OR %ES_WANTRETURN OR %ES_LEFT OR %ES_AUTOVSCROLL OR %WS_VSCROLL OR %WS_TABSTOP, _
            %WS_EX_CLIENTEDGE
        FOR I&=1 TO 50
            t$=t$+"this is TEXTBOX test string line"+STR$(I&)
            IF i&<50 THEN T$=T$+$CRLF
        NEXT
        CONTROL SET TEXT hForm1&,%FORM1_TEXT1, t$
        ' - - - - - - - - - - - - - - - - - - - - - - - - -
        DIM COMBOBOX1_List(9) AS LOCAL STRING
        FOR N&=0 TO 9
            COMBOBOX1_List(N&)="Item"+STR$(N&+1)+" in Combobox"
        NEXT N&
        ' - - - - - - - - - - - - - - - - - - - - - - - - -
        CONTROL ADD COMBOBOX, hForm1&,  %FORM1_COMBOBOX1, COMBOBOX1_List(), 100,100,100,100, _
            %WS_CHILD OR %WS_VISIBLE OR %CBS_DROPDOWNLIST OR %WS_HSCROLL OR %WS_VSCROLL OR %CBS_NOINTEGRALHEIGHT OR %WS_TABSTOP, _
            %WS_EX_CLIENTEDGE
        ' - - - - - - - - - - - - - - - - - - - - - - - - -
        DIM LISTBOX1_List(20) AS LOCAL STRING
        FOR N&=0 TO 19
            LISTBOX1_List(N&)="Test Item"+STR$(N&+1)+" in Listbox"
        NEXT N&
        ' - - - - - - - - - - - - - - - - - - - - - - - - -
        CONTROL ADD LISTBOX, hForm1&,  %FORM1_LISTBOX1, LISTBOX1_List(), 100,100,100,100, _
            %WS_CHILD OR %WS_VISIBLE OR %LBS_NOINTEGRALHEIGHT OR %WS_HSCROLL OR %WS_VSCROLL OR %LBS_NOTIFY OR %WS_TABSTOP, _
            %WS_EX_CLIENTEDGE
            'NB: The %LBS_NOINTEGRALHEIGHT, %WS_HSCROLL and %WS_VSCROLL styles should always be included.
        '
        CONTROL ADD "SysListView32", hForm1&, %FORM1_LISTVIEW, "", _
            100,100,100,100, %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_TABSTOP _
            OR %LVS_REPORT OR %LVS_SHOWSELALWAYS, %WS_EX_LEFT OR _
            %WS_EX_RIGHTSCROLLBAR
        SampleListView hForm1&, %FORM1_LISTVIEW, 3, 8 'From PBForms
        '
        CONTROL ADD "Button", hForm1&,  %FORM1_BUTTON2,  "E&xit",100,100,100,100, _
            %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP, 0 CALL CBF_FORM1_BUTTON2
        CONTROL HANDLE hForm1&,  %FORM1_BUTTON2 TO hButton2&
    END SUB
    '
    FUNCTION SampleListView(BYVAL hDlg AS LONG, BYVAL lID AS LONG, BYVAL lColCnt AS _
        LONG, BYVAL lRowCnt AS LONG) AS LONG
        ' Specify the details of the listview content
        LOCAL lStyle  AS LONG
        LOCAL tLVC    AS LV_COLUMN
        LOCAL tLVI    AS LV_ITEM
        LOCAL szBuf   AS ASCIIZ * 32
        LOCAL lCol    AS LONG
        LOCAL lRow    AS LONG
        LOCAL hCtl    AS LONG
        CONTROL HANDLE hDlg, lID TO hCtl
        lStyle = ListView_GetExtendedListViewStyle(hCtl)
        ListView_SetExtendedListViewStyle hCtl, _
            lStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES
        'Load column headers.
        tLVC.mask    = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM
        tLVC.fmt     = %LVCFMT_LEFT
        tLVC.pszText = VARPTR(szBuf)
        FOR lCol = 0 TO lColCnt - 1
            szBuf = "Column " + FORMAT$(lCol+1)
            tLVC.iOrder = lCol
            ListView_InsertColumn hCtl, lCol, tLVC
        NEXT lCol
        'Load sample data.
        FOR lRow = 0 TO lRowCnt - 1
            tLVI.stateMask   = %LVIS_FOCUSED
            tLVI.pszText     = VARPTR(szBuf)
            tLVI.iItem       = lRow
            FOR lCol = 0 TO lColCnt - 1
                szBuf           = "Column " + FORMAT$(lCol+1) + " Row " + FORMAT$(lRow+1)
                tLVI.iSubItem   = lCol
                tLVI.lParam     = lRow
                IF lCol = 0 THEN
                    tLVI.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                    ListView_InsertItem hCtl, tLVI
                ELSE
                    tLVI.mask = %LVIF_TEXT
                    ListView_SetItem hCtl, tLVI
                END IF
            NEXT lCol
        NEXT i
        'Auto size columns.
        FOR lCol = 0 TO lColCnt - 1
            ListView_SetColumnWidth hCtl, lCol, %LVSCW_AUTOSIZE
        NEXT lCol
    END FUNCTION
    '
    SUB ResizeControls(BYVAL X AS LONG,BYVAL Y AS LONG)
        ' In this routine the positions and sizes of all the controls
        ' are specified as proportions (~percentages) of the dialog
        ' X and Y dimensions. Imagine when doing the design that the
        ' dialog area is 100 x 100 in percent. Define the position and
        ' size of the controls according to this area. When resizing is
        ' done, the proportions (~percentages) defining each control are
        ' never changed - only X and Y (defining the absolute size of the
        ' dialog) are changed.
        '
        ' Variables defining position and size of each control in turn
        LOCAL Xp& ' Horizontal position (upper-left corner)
        LOCAL Yp& ' Vertical position   (upper-left corner)
        LOCAL W&  ' Width
        LOCAL H&  ' Height
        '
        SendMessage hForm1&, %WM_SETREDRAW, %FALSE, BYVAL %NULL ' Disable redraw temporarily to reduce flicker.
        '
        ' Resize TEXTBOX while maintaining integral line height.
        Xp = .25*X : Yp = .02*Y : W = .74*X : H = .5*Y
        CALL SizeTextbox(hForm1&,%FORM1_TEXT1,Xp,Yp,W,H,0)
        '
        ' Resize LISTBOX while maintaining integral line height.
        Xp = .02*X : Yp = .14*Y : W = .22*X : H = .75*Y
        CALL SizeListbox(hForm1&,%FORM1_LISTBOX1,Xp,Yp,W,H,0)
        '
        ' Resize COMBOBOX while maintaining integral line height in dropped rectangle.
        Xp = .02*X : Yp = .02*Y : W = .22*X : H = .5*Y
        CALL SizeCombobox(hForm1&,%FORM1_COMBOBOX1,Xp,Yp,W,H,0)
        '
        ' Resize LISTVIEW while maintaining integral line height.
        Xp = .25*X : Yp = .55*Y : W = .58*X : H = .35*Y
        CALL SizeListview(hForm1&,%FORM1_LISTVIEW,Xp,Yp,W,H,0)
        '
        ' Resize BUTTONS.
        Xp = .85*X : Yp = .70*Y : W = .14*X : H = .07*Y
        MoveWindow hButton1&,Xp,Yp,W,H,%TRUE
        '
        Xp = .85*X : Yp = .80*Y : W = .14*X : H = .07*Y
        MoveWindow hButton2&,Xp,Yp,W,H,%TRUE
        '
        SendMessage hForm1&, %WM_SETREDRAW, %TRUE, BYVAL %NULL ' enable redraw
        InvalidateRect hForm1&, BYVAL %NULL , %TRUE
        UpdateWindow hForm1&
    END SUB
    
    ' *************************************************************
    '                             Dialog Window Procedure
    '                             for Form Form1
    '                             uses Global Handle - hForm1&
    ' *************************************************************
    
    CALLBACK FUNCTION Form1_DlgProc
        DIM MinMaxPtr AS MINMAXINFO PTR
        DIM hStatusBar AS STATIC DWORD
        DIM StatusText AS ASCIIZ * 250
        LOCAL HeadNotif AS HD_NOTIFY PTR
        LOCAL rc AS RECT ,X1&,Y1&,X&,Y&
        DIM StatusBarHeight AS STATIC LONG
        SELECT CASE CBMSG
            CASE %WM_INITDIALOG
                ' Ensure correct initial sizing.
                GetClientRect CBHNDL, rc
                X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                CALL ResizeControls(X,Y)
                ' The next few lines define a status bar.
                ' NB: The area of the status bar is subtracted from the available dialog area.
                hStatusBar = CreateStatusWindow(%SBARS_SIZEGRIP OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %CCS_BOTTOM, "", CBHNDL, 0)
                DIALOG PIXELS hForm1&, X&, Y& TO UNITS X1&, Y1&
                StatusText = "Dialog Size in pixels: X: "+FORMAT$(X,"####")+"   Y: "+FORMAT$(Y,"####") _
                    + ",  in dialog units: X: "+FORMAT$(X1,"###")+"   Y: "+FORMAT$(Y1,"###")
                SendMessage hStatusBar, %WM_SETTEXT, 0, VARPTR(StatusText)
                GetClientRect hStatusBar, rc
                StatusBarHeight& = rc.nBottom - rc.nTop
                SetFocus CBHNDL
            CASE %WM_SIZE
                ' Get size of dialog after tracking.
                GetClientRect CBHNDL, rc
                ' Resize status bar
                MoveWindow hStatusBar, rc.nLeft,rc.nBottom-StatusBarHeight, _
                    rc.nRight - rc.nLeft, StatusBarHeight, %TRUE
                ' Resize controls
                X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                CALL ResizeControls(X,Y)
                DIALOG PIXELS hForm1&, X&, Y& TO UNITS X1&, Y1&
                StatusText = "Dialog Size in pixels: X: "+FORMAT$(X,"####")+"   Y: "+FORMAT$(Y,"####") _
                    + ",  in dialog units: X: "+FORMAT$(X1,"###")+"   Y: "+FORMAT$(Y1,"###")
                SendMessage hStatusBar, %WM_SETTEXT, 0, VARPTR(StatusText)
            CASE %WM_GETMINMAXINFO
                MinMaxPtr=CBLPARAM
                ' Set the minimum size of dialog. You can define these values according to need.
                @MinMaxPtr.ptMinTrackSize.x = 480 ' minimum X of dialog in pixels
                @MinMaxPtr.ptMinTrackSize.y = 330 ' minimum Y of dialog in pixels
            CASE %WM_NOTIFY
                HeadNotif = CBLPARAM
                IF @HeadNotif.hdr.hwndFrom = hHead& THEN
                    IF @HeadNotif.hdr.code = %HDN_ITEMCHANGED THEN
                        ' Resize if a divider in the listview header has been dragged.
                        GetClientRect CBHNDL, rc
                        X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                        CALL SizeListview(CBHNDL,%FORM1_LISTVIEW,.25*X,.55*Y,.58*X,.35*Y,0)
                    END IF
                END IF
            CASE %WM_COMMAND
                ' Process Messages to Controls that have no Callback Function
                ' and Process Messages to Menu Items
                SELECT CASE LOWRD(CBWPARAM)    ' Parse by Ctrl ID #
                    CASE  %Form1_EXIT                                         ' Popup Menu Item Selected
                        DIALOG END hForm1&
                    CASE ELSE
                END SELECT
        END SELECT
        FUNCTION = 0
    END FUNCTION
    ' ------------------------------------------------
    CALLBACK FUNCTION CBF_FORM1_BUTTON2
        IF CBCTLMSG=%BN_CLICKED THEN
            DIALOG END hForm1&
        END IF
    END FUNCTION
    ' ------------------------------------------------



    [This message has been edited by Erik Christensen (edited December 03, 2005).]

  • #2
    INCLUDE FILE
    Code:
    '*******************************************************************************
    ' "SizeCtls.inc" for PB Win 6, 7 and 8.
    '  ============
    '
    '  Sizing controls while maintaining integral line height INCLUDE FILE.
    '  ====================================================================
    '
    '  Public domain by Erik Christensen ----- e.chr@email.dk
    '
    '  These four routines can size and resize textbox, listbox, combobox
    '  and listview controls during runtime while maintaining integral line
    '  heights, i.e. avoiding clipping of the lowest displayed line at any time.
    '  You may change the content of the controls during runtime. They will always
    '  be able to display the data by automatically adding or deleting scroll
    '  bars according to the need.
    '
    '  The input to the routines is:
    '    dialog handle
    '    control id
    '    X position (upper left corner) of control within the dialog area
    '    Y position (upper left corner) of control within the dialog area
    '    Width of control
    '    Height of control
    '    UNflag (0 for dimensions in pixels, 1 for dimensions in dialog units)
    '
    '  See further directions in each individual routine. See also examples of
    '  calling the routines in the accompanying skeleton test program.
    '
    '  Thanks to the PowerBasic Forum for help and inspiration, in particular to
    '  Carlo Pagani and Lance Edmonds. Comments for improvement are welcome.
    '
    '  Good luck!
    '
    '  Erik
    '
    '***************************************************************************************************
    '
    SUB SizeTextbox(BYVAL hDlg&,BYVAL id&,BYVAL Xp&,BYVAL Yp&,BYVAL W&,BYVAL H&,BYVAL UNflag&)
        ' Resize TEXTBOX while maintaining integral line height.
        LOCAL txt$,Res&,Res2&,TextLineHeight&,hCtr&
        IF UNflag& THEN ' convert dialog units to pixels
            DIALOG UNITS hDlg&, Xp&, Yp& TO PIXELS Xp&, Yp&
            DIALOG UNITS hDlg&, W&, H& TO PIXELS W&, H&
        END IF
        CONTROL HANDLE hDlg&, id& TO hCtr&
        CONTROL GET TEXT hDlg&, id& TO txt$ ' save temporarily present text.
        CONTROL SET TEXT hDlg&, id&,"a"+$CRLF+"a"
        CONTROL SEND hDlg&,id&,%EM_POSFROMCHAR,0,0 TO Res&  ' HIWRD = 1
        CONTROL SEND hDlg&,id&,%EM_POSFROMCHAR,3,0 TO Res2& ' HIWRD = 17
        TextLineHeight& = HIWRD(Res2&)-HIWRD(Res&)       ' height in pixel of one line in textbox
        H& = INT(H&/TextLineHeight&) * TextLineHeight& _ ' Get integral lines height
            + 2 * GetSystemMetrics(%SM_CYEDGE) + 2       ' Add edge heights (may be improved)
        CONTROL SET TEXT hDlg&, id&, txt$   ' set text back to control
        ' Set new position and size of textbox
        MoveWindow hCtr&,Xp&,Yp&,W&,H&,%TRUE
    END SUB
    '
    SUB SizeListview(BYVAL hDlg&,BYVAL id&,BYVAL Xp&,BYVAL Yp&,BYVAL W&,BYVAL H&,BYVAL UNflag&)
        ' Resize LISTVIEW while maintaining integral line height.
        LOCAL Res&,Res2&,I&,hCtr&,VS&,HS&
        LOCAL ListviewColumnsNumber&,ListviewHeaderHeight&,ListviewItemHeight&
        LOCAL ListviewRowsNumber&,TotalWidth&,TotalHeight&
        LOCAL VScrollBarWidth&,HScrollBarHeight&
        LOCAL rc AS RECT
        IF UNflag& THEN ' convert dialog units to pixels
            DIALOG UNITS hDlg&, Xp&, Yp& TO PIXELS Xp&, Yp&
            DIALOG UNITS hDlg&, W&, H& TO PIXELS W&, H&
        END IF
        CONTROL HANDLE hDlg&, id& TO hCtr&
        VScrollBarWidth&  = GetSystemMetrics(%SM_CXVSCROLL)
        HScrollBarHeight& = GetSystemMetrics(%SM_CYHSCROLL)
        hHead& = SendMessage(hCtr&,%LVM_GETHEADER,0,0) ' NB: this header handle is global because
                                                       ' action can also be elicited by changing
                                                       ' the header widths (See windows callback function).
        ListviewColumnsNumber& = SendMessage(hHead&,%HDM_GETITEMCOUNT,0,0) ' Number of columns
        Res2& = SendMessage(hHead&, %HDM_GETITEMRECT, 0, VARPTR(rc))
        ListviewHeaderHeight& = rc.nBottom - rc.nTop   ' Height in pixels of listview header
        rc.nLeft = %LVIR_LABEL
        Res2& = SendMessage(hCtr&,%LVM_GETITEMRECT, 0, VARPTR(rc))
        ListviewItemHeight& = rc.nBottom - rc.nTop     ' Height in pixels of one line in listview
        ListviewRowsNumber& = SendMessage(hCtr&,%LVM_GETITEMCOUNT,0,0) ' Number of items (rows)
        FOR I&=0 TO ListviewColumnsNumber-1
            Res& = SendMessage(hCtr&,%LVM_GETCOLUMNWIDTH,I,0)
            TotalWidth& = TotalWidth& + Res& ' Total width of content in listview
        NEXT
        TotalHeight& = ListviewRowsNumber& * ListviewItemHeight& + ListviewHeaderHeight& ' Total height of listview content
        ' Assess if scrollbars will be displayed and make proper adjustments:
        IF H& < TotalHeight& + HScrollBarHeight& THEN VS& = 1 ' Vertical scroll bar dependent on horizontal scroll bar
        IF H& < TotalHeight& THEN VS& = VScrollBarWidth&      ' Vertical scroll bar certain
        IF W& < TotalWidth& + VScrollBarWidth& THEN HS& = 1   ' Horizontal scroll bar dependent on vertical scroll bar
        IF W& < TotalWidth& THEN HS& = HScrollBarHeight&      ' Horizontal scroll bar certain
        IF HS& = HScrollBarHeight& AND VS& = 1 THEN VS& = VScrollBarWidth&
        IF VS& = VScrollBarWidth& AND HS& = 1 THEN HS& = HScrollBarHeight&
        H& = H& - ListviewHeaderHeight& - HS&
        H& = INT(H&/ListviewItemHeight&) * ListviewItemHeight& _ ' Get integral lines height
                  + ListviewHeaderHeight& _                      ' Add header height
                  + GetSystemMetrics(%SM_CYEDGE) + 1 _           ' Add edge heights (may be improved)
                  + HS&                                          ' Add horizontal scroll factor
        ' Set new position and size of listview
        MoveWindow hCtr&,Xp&,Yp&,W&,H&,%TRUE
    END SUB
    '
    SUB SizeListbox(BYVAL hDlg&,BYVAL id&,BYVAL Xp&,BYVAL Yp&,BYVAL W&,BYVAL H&,BYVAL UNflag&)
        ' Resize LISTBOX while maintaining integral line height.
        ' The built-in behavior of listbox is not satisfactory
        ' when switching to and from horizontal scroll bar. Therefore,
        ' the %LBS_NOINTEGRALHEIGHT style should be applied, so we
        ' can control the whole process. The %WS_HSCROLL and %WS_VSCROLL
        ' styles are also necessary.
        LOCAL I&,j&,TotalWidth&,Temp$,nResult&,nCount&,hDC&
        LOCAL TotalHeight&,hCtr&,VS&,HS&
        LOCAL rc AS RECT
        LOCAL Si AS APISIZE
        LOCAL hFont AS LONG
        LOCAL VScrollBarWidth&,HScrollBarHeight&,ListboxItemHeight&
        IF UNflag& THEN ' convert dialog units to pixels
            DIALOG UNITS hDlg&, Xp&, Yp& TO PIXELS Xp&, Yp&
            DIALOG UNITS hDlg&, W&, H& TO PIXELS W&, H&
        END IF
        CONTROL HANDLE hDlg&, id& TO hCtr&
        ListboxItemHeight&  = SendMessage(hCtr&,%LB_GETITEMHEIGHT,0,0)
        VScrollBarWidth&  = GetSystemMetrics(%SM_CXVSCROLL)
        HScrollBarHeight& = GetSystemMetrics(%SM_CYHSCROLL)
        '
        ' Find maximum width string to determine if a horizontal scroll bar is needed.
        ' Lance Edmonds is thanked for his example in the source code forum.
        nCount = 1
        hDC = GetDC(hCtr&)
        hFont = SendMessage(hCtr&, %WM_GETFONT, 0, 0)
        IF hFont THEN hFont = SelectObject(hDC, hFont)
        j = SendMessage(hCtr&, %LB_GETCOUNT, 0, 0)
        TotalHeight& = j * ListboxItemHeight& ' Total height of listbox content.
        ' Enumerate the strings in the LISTBOX
        FOR i = 0 TO j - 1
          nResult = SendMessage(hCtr&,%LB_GETTEXTLEN, i, 0)
          IF nResult THEN
            Temp = SPACE$(nResult)
            SendMessage hCtr&, %LB_GETTEXT, i, STRPTR(Temp)
            ' Get the width of the string. Addition of "N" provides a safety margin.
            GetTextExtentPoint32 hDC, BYCOPY Temp + "N", nResult + 1, Si
            ' Get the maximum width.
            nCount = MAX&(nCount, Si.cx)
          END IF
        NEXT i
        ' Set horizontal extent of the listbox. If this is larger than
        ' listbox's physical width, a horizontal scroll bar is sutomatically added.
        SendMessage hCtr&, %LB_SETHORIZONTALEXTENT, nCount, 0
        ' Clean up
        IF hFont THEN SelectObject hDC, hFont
        ReleaseDC hCtr&, hDC
        '
        TotalWidth& = nCount
        '
        ' Assess if scrollbars will be displayed and make proper adjustments:
        IF H& < TotalHeight& + HScrollBarHeight& THEN VS& = 1 ' Vertical scroll bar dependent on horizontal scroll bar
        IF H& < TotalHeight& THEN VS& = VScrollBarWidth&      ' Vertical scroll bar certain
        IF W& < TotalWidth& + VScrollBarWidth& THEN HS& = 1   ' Horizontal scroll bar dependent on vertical scroll bar
        IF W& < TotalWidth& THEN HS& = HScrollBarHeight&      ' Horizontal scroll bar certain
        IF HS& = HScrollBarHeight& AND VS& = 1 THEN VS& = VScrollBarWidth&
        IF VS& = VScrollBarWidth& AND HS& = 1 THEN HS& = HScrollBarHeight&
        H& = H& - HS&
        H& = INT(H&/ListboxItemHeight&) * ListboxItemHeight& _ ' Get integral lines height
                  + 2 * GetSystemMetrics(%SM_CYEDGE) + 1 _     ' Add edge height (may be improved)
                  + HS&                                        ' Add horizontal scroll factor
        ' Set new position and size of listbox
        ' The following approach always going from larger to smaller width gives
        ' the best results.
        MoveWindow hCtr&,Xp&,Yp&,W&+VScrollBarWidth&,H&,%TRUE
        MoveWindow hCtr&,Xp&,Yp&,W&,H&,%TRUE
    END SUB
    '
    SUB SizeCombobox(BYVAL hDlg&,BYVAL id&,BYVAL Xp&,BYVAL Yp&,BYVAL W&,BYVAL H&,BYVAL UNflag&)
        ' Resize COMBOBOX while maintaining integral line height.
        ' The built-in behavior of combobox is not satisfactory
        ' when switching to and from horizontal scroll bar. Therefore,
        ' the %CBS_NOINTEGRALHEIGHT style should be applied, so we
        ' can control the whole process. The %WS_HSCROLL and %WS_VSCROLL
        ' styles are also necessary.
        STATIC t$
        LOCAL I&,j&,TotalWidth&,Temp$,nResult&,nCount&,hDC&
        LOCAL TotalHeight&,hCtr&,VS&,HS&
        LOCAL rc AS RECT
        LOCAL Si AS APISIZE
        LOCAL hFont AS LONG
        LOCAL VScrollBarWidth&,HScrollBarHeight&
        LOCAL ComboHeight&, ComboItemHeight&
        IF UNflag& THEN ' convert dialog units to pixels
            DIALOG UNITS hDlg&, Xp&, Yp& TO PIXELS Xp&, Yp&
            DIALOG UNITS hDlg&, W&, H& TO PIXELS W&, H&
        END IF
        CONTROL HANDLE hDlg&, id& TO hCtr&
        ComboHeight&  = SendMessage(hCtr&,%CB_GETITEMHEIGHT,-1,0)
        ComboItemHeight&  = SendMessage(hCtr&,%CB_GETITEMHEIGHT,0,0)
        VScrollBarWidth&  = GetSystemMetrics(%SM_CXVSCROLL)
        HScrollBarHeight& = GetSystemMetrics(%SM_CYHSCROLL)
        '
        ' Find maximum width string to determine if a horizontal scroll bar is needed.
        ' Lance Edmonds is thanked for his example in the source code forum.
        nCount = 1
        hDC = GetDC(hCtr&)
        hFont = SendMessage(hCtr&, %WM_GETFONT, 0, 0)
        IF hFont THEN hFont = SelectObject(hDC, hFont)
        j = SendMessage(hCtr&,%CB_GETCOUNT, 0, 0)
        TotalHeight& = j * ComboItemHeight& ' Total height of combobox content.
        ' Enumerate the strings in the COMBOBOX
        FOR i = 0 TO j - 1
          nResult = SendMessage(hCtr&,%CB_GETLBTEXTLEN, i, 0)
          IF nResult THEN
            Temp = SPACE$(nResult)
            SendMessage hCtr&,%CB_GETLBTEXT, i, STRPTR(Temp)
            ' Get the width of the string. Addition of "N" provides a safety margin.
            GetTextExtentPoint32 hDC, BYCOPY Temp+"N", nResult+1, Si
            ' Get the maximum width.
            nCount = MAX&(nCount, Si.cx)
          END IF
        NEXT i
        ' Set horizontal extent of the combobox. If this is larger than
        ' combobox's physical width, a horizontal scroll bar is sutomatically added.
        SendMessage hCtr&, %CB_SETHORIZONTALEXTENT, nCount, 0
        ' Clean up
        IF hFont THEN SelectObject hDC, hFont
        ReleaseDC hCtr&, hDC
        '
        TotalWidth& = nCount
        '
        ' Assess if scrollbars will be displayed and make proper adjustments:
        H& = H& - ComboHeight&
        IF H& < TotalHeight& + HScrollBarHeight& THEN VS& = 1 ' Vertical scroll bar dependent on horizontal scroll bar
        IF H& < TotalHeight& THEN VS& = VScrollBarWidth&      ' Vertical scroll bar certain
        IF W& < TotalWidth& + VScrollBarWidth& THEN HS& = 1   ' Horizontal scroll bar dependent on vertical scroll bar
        IF W& < TotalWidth& THEN HS& = HScrollBarHeight&      ' Horizontal scroll bar certain
        IF HS& = HScrollBarHeight& AND VS& = 1 THEN VS& = VScrollBarWidth&
        IF VS& = VScrollBarWidth& AND HS& = 1 THEN HS& = HScrollBarHeight&
        H& = H& - HS&
        '
        ' The following line is necessary to make the combobox "behave" satisfactorily:
        IF HS& > 1 AND TotalHeight& - H& <= ComboItemHeight& THEN H& = H& - (ComboItemHeight& + 1 - (TotalHeight&-H&))
        '
        H& = INT(H&/ComboItemHeight&) * ComboItemHeight& _       ' Get integral lines height of dropped rectangle
                        + ComboHeight& _                         ' Add height of combobox
                        + 4 * GetSystemMetrics(%SM_CYEDGE) + 1 _ ' Add edge height (may be improved)
                        + HS&                                    ' Add horizontal scroll factor
        ' Set new position and size of combobox
        ' The following approach always going from larger to smaller width gives
        ' the best results.
        MoveWindow hCtr&,Xp&,Yp&,W&+VScrollBarWidth&,H&,%TRUE
        MoveWindow hCtr&,Xp&,Yp&,W&,H&,%TRUE
    END SUB
    ' end include file "SizeCtls.inc"
    ------------------




    [This message has been edited by Erik Christensen (edited December 03, 2005).]

    Comment


    • #3
      David Kenny has kindly pointed out to me that if more listview controls are being used in the same dialog, the callback function needs to know the control ID of the listview being changed. Thus I have changed the code slightly to deal with this issue. Thanks to David Kenny for making me aware of this. The code now works well also with PBwin 9.01. The include file 'SizeCtls.inc' is unchanged.


      Best regards,

      Erik

      September 28, 2009:
      The control ID of the listview could not be obtained using @HeadNotif.hdr.idFrom. This is always zero. Therefore another method suggested by David Kenny is being used. That method, which works, is explained in the code.

      September 29, 2009:
      The reason why @HeadNotif.hdr.idFrom does not work and the method suggested by David Kenny does work is that the callback message in question is aimed at the header control, which is embedded as a child in the listview control. Because of that arrangement the header control does not have its own control ID. You need to get the control ID of the listview parent. Thus the method used is logical and makes sense.

      Code:
      #COMPILE EXE
      #REGISTER NONE
      #DIM ALL        '  This is helpful to prevent errors in coding
      '
      '------------------------------------------------------------------------------
      ' Initial Declares - eliminate unnecessary macros in COMMCTRL.INC
      '------------------------------------------------------------------------------
      %NOANIMATE         = 1  ' Animate control
      '  %NOBUTTON          = 1  ' Button
      '  %NOCOMBO           = 1  ' Combo box
      %NOCOMBOEX         = 1  ' ComboBoxEx
      %NODATETIMEPICK    = 1  ' Date/time picker
      %NODRAGLIST        = 1  ' Drag list control
      '  %NOEDIT            = 1  ' Edit control
      %NOFLATSBAPIS      = 1  ' Flat scroll bar
      '  %NOHEADER          = 1  ' Header control
      %NOHOTKEY          = 1  ' HotKey control
      %NOIMAGELIST       = 1  ' Image APIs
      %NOIPADDRESS       = 1  ' IP Address edit control
      '  %NOLIST            = 1  ' List box control
      '  %NOLISTVIEW        = 1  ' ListView control
      %NOMENUHELP        = 1  ' Menu help
      %NOMONTHCAL        = 1  ' MonthCal
      %NOMUI             = 1  ' MUI
      %NONATIVEFONTCTL   = 1  ' Native Font control
      %NOPAGESCROLLER    = 1  ' Pager
      %NOPROGRESS        = 1  ' Progress control
      %NOREBAR           = 1  ' Rebar control
      '  %NOSTATUSBAR       = 1  ' Status bar
      %NOTABCONTROL      = 1  ' Tab control
      %NOTOOLBAR         = 1  ' Tool bar
      %NOTOOLTIPS        = 1  ' Tool tips
      %NOTRACKBAR        = 1  ' Track bar
      %NOTRACKMOUSEEVENT = 1  ' Track Mouse Event
      %NOTREEVIEW        = 1  ' TreeView
      %NOUPDOWN          = 1  ' Up Down arrow control
      ' ----------------------------------------------------------
      #INCLUDE "win32api.inc"     ' Win 32 API include file !
      #INCLUDE "commctrl.inc"
      '------------------
      GLOBAL hHead& ' This needs to be placed here.
      '
      ' Include file for sizing of controls:
      #INCLUDE "SizeCtls.inc" ' Be sure to provide the correct path.
      
      'TYPE NMHDR
      '  hwndFrom AS DWORD
      '  idfrom AS Dword
      '  iCODE AS LONG    ' used for messages, so needs to be LONG, not DWORD...
      'END TYPE
      '
      ' *************************************************************
      '              Application Constants and Declares
      ' *************************************************************
      ' ----------------------------------------------------------
      %Form1_FILE                                     = 500
      %Form1_EXIT                                     = 530
      '
      %FORM1_TEXT1              = 105
      %FORM1_COMBOBOX1          = 110
      %FORM1_LISTBOX1           = 115
      %FORM1_BUTTON1            = 120
      %FORM1_BUTTON2            = 125
      %FORM1_LISTVIEW           = 130
      ' --------------------------------------------------
      DECLARE SUB CreateDialog_Form1(BYVAL hParent&)
      DECLARE CALLBACK FUNCTION Form1_DlgProc
      DECLARE FUNCTION SampleListView(BYVAL hDlg AS LONG, BYVAL lID AS LONG, BYVAL lColCnt AS _
          LONG, BYVAL lRowCnt AS LONG) AS LONG
      ' --------------------------------------------------
      DECLARE CALLBACK FUNCTION CBF_FORM1_BUTTON2()
      ' *************************************************************
      '            Application Global Variables and Types
      ' *************************************************************
      GLOBAL hForm1&    ' Dialog handle
      ' Global Handles for menus
      GLOBAL hForm1_Menu0&
      GLOBAL hForm1_Menu1&
      GLOBAL hCombo1&,hButton1&,hButton2&
      ' *************************************************************
      '                   Application Entrance
      ' *************************************************************
      FUNCTION PBMAIN ()AS LONG
          LOCAL Count&
          LOCAL CC1 AS INIT_COMMON_CONTROLSEX
          CC1.dwSize=SIZEOF(CC1)
          CC1.dwICC=%ICC_WIN95_CLASSES
          InitCommonControlsEX CC1
          CreateDialog_Form1 0
          ' Dialogs Handle in variable - hForm1&
          DIALOG SHOW MODELESS hForm1& , CALL Form1_DlgProc
          DO
              DIALOG DOEVENTS TO Count&
          LOOP UNTIL Count&=0
      END FUNCTION
      ' *************************************************************
      '                    Application Dialogs
      ' *************************************************************
      SUB CreateDialog_Form1(BYVAL hParent&)
          DIM Rct AS RECT
          LOCAL X&,Y&,X1&,Y1&,hDlg&,MPX&,MPY&,MUX&,MUY&
          LOCAL hDC&,Res&,Res2&
          LOCAL prc AS rect
          LOCAL I&,t$
          '
          ' Get dimension in pixels of Work Area on screen (desktop).
          SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(Rct), 0
          ' Get Max X pixels
          MPX = Rct.nRight - Rct.nLeft
          MPX = MPX - 2 * GetSystemMetrics(%SM_CXEDGE) - 4 ' Adjust for Dialog Edge (left and right)
          '                                                ' Allow for resizing
          ' Get Max Y pixels
          MPY = Rct.nBottom - Rct.nTop
          MPY = MPY - 2 * GetSystemMetrics(%SM_CYEDGE) ' Adjust for Dialog Edge (upper and lower)
          MPY = MPY - GetSystemMetrics(%SM_CYMENU)     ' Adjust for Menu height
          '
          ' Make temporary invisible dialog just to convert from pixels to dialog units.
          DIALOG NEW 0,"",,,0,0,, TO hDlg&
          DIALOG PIXELS hDlg&, MPX,MPY TO UNITS MUX,MUY
          DIALOG END hDlg& ' Close dialog
      
          LOCAL N&, CT&        '  Variables used for Reading Data in Arrays for Listbox and Combobox
          ' hParent& = 0 if no parent Dialog
          ' Make dialog to fill desktop work space.
          DIALOG NEW hParent&, "Proportional resizing maintaining integral line height", , ,MUX, MUY, %WS_POPUP OR _
              %WS_BORDER OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR _
              %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS _
              OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
              %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_WINDOWEDGE OR _
              %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
              %WS_EX_RIGHTSCROLLBAR, TO hForm1&
              ' The %WS_THICKFRAME style will create a dialog that has a sizing border.
              ' That is, the dialog will be resizable. NB: No status bar is necessary
              ' for this feature.
          ' ---------------------------
          MENU NEW BAR TO hForm1_Menu0&
          ' ---------------------------
          MENU NEW POPUP TO hForm1_Menu1&
          MENU ADD POPUP, hForm1_Menu0& ,"E&xit", hForm1_Menu1&, %MF_ENABLED
          MENU ADD STRING, hForm1_Menu1&, "E&xit",  %Form1_EXIT, %MF_ENABLED
          MENU ATTACH hForm1_Menu0&, hForm1&
          '
          ' The following controls are created using dummy position and size.
          ' They are resized to their initial position and size in
          ' SUB ResizeControls which is called in the %WM_INITDIALOG section of
          ' the windows callback function. Thus it is sufficient to specify the
          ' positions and sizes only once in SUB ResizeControls.
          CONTROL ADD "Button", hForm1&,  %FORM1_BUTTON1,  "Button &1", 100,100,100,100, _
              %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP, 0
          CONTROL HANDLE hForm1&,  %FORM1_BUTTON1 TO hButton1&
          CONTROL ADD TEXTBOX, hForm1&,  %FORM1_TEXT1,"", 100,100,100,100, _
              %WS_CHILD OR %WS_VISIBLE OR %ES_MULTILINE OR %ES_WANTRETURN OR %ES_LEFT OR %ES_AUTOVSCROLL OR %WS_VSCROLL OR %WS_TABSTOP, _
              %WS_EX_CLIENTEDGE
          FOR I&=1 TO 50
              t$=t$+"this is TEXTBOX test string line"+STR$(I&)
              IF i&<50 THEN T$=T$+$CRLF
          NEXT
          CONTROL SET TEXT hForm1&,%FORM1_TEXT1, t$
          ' - - - - - - - - - - - - - - - - - - - - - - - - -
          DIM COMBOBOX1_List(9) AS LOCAL STRING
          FOR N&=0 TO 9
              COMBOBOX1_List(N&)="Item"+STR$(N&+1)+" in Combobox"
          NEXT N&
          ' - - - - - - - - - - - - - - - - - - - - - - - - -
          CONTROL ADD COMBOBOX, hForm1&,  %FORM1_COMBOBOX1, COMBOBOX1_List(), 100,100,100,100, _
              %WS_CHILD OR %WS_VISIBLE OR %CBS_DROPDOWNLIST OR %WS_HSCROLL OR %WS_VSCROLL OR %CBS_NOINTEGRALHEIGHT OR %WS_TABSTOP, _
              %WS_EX_CLIENTEDGE
          ' - - - - - - - - - - - - - - - - - - - - - - - - -
          DIM LISTBOX1_List(20) AS LOCAL STRING
          FOR N&=0 TO 19
              LISTBOX1_List(N&)="Test Item"+STR$(N&+1)+" in Listbox"
          NEXT N&
          ' - - - - - - - - - - - - - - - - - - - - - - - - -
          CONTROL ADD LISTBOX, hForm1&,  %FORM1_LISTBOX1, LISTBOX1_List(), 100,100,100,100, _
              %WS_CHILD OR %WS_VISIBLE OR %LBS_NOINTEGRALHEIGHT OR %WS_HSCROLL OR %WS_VSCROLL OR %LBS_NOTIFY OR %WS_TABSTOP, _
              %WS_EX_CLIENTEDGE
              'NB: The %LBS_NOINTEGRALHEIGHT, %WS_HSCROLL and %WS_VSCROLL styles should always be included.
          '
          CONTROL ADD "SysListView32", hForm1&, %FORM1_LISTVIEW, "", _
              100,100,100,100, %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_TABSTOP _
              OR %LVS_REPORT OR %LVS_SHOWSELALWAYS, %WS_EX_LEFT OR _
              %WS_EX_RIGHTSCROLLBAR
          SampleListView hForm1&, %FORM1_LISTVIEW, 3, 8 'From PBForms
          '
          CONTROL ADD "Button", hForm1&,  %FORM1_BUTTON2,  "E&xit",100,100,100,100, _
              %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP, 0 CALL CBF_FORM1_BUTTON2
          CONTROL HANDLE hForm1&,  %FORM1_BUTTON2 TO hButton2&
      END SUB
      '
      FUNCTION SampleListView(BYVAL hDlg AS LONG, BYVAL lID AS LONG, BYVAL lColCnt AS _
          LONG, BYVAL lRowCnt AS LONG) AS LONG
          ' Specify the details of the listview content
          LOCAL lStyle  AS LONG
          LOCAL tLVC    AS LV_COLUMN
          LOCAL tLVI    AS LV_ITEM
          LOCAL szBuf   AS ASCIIZ * 32
          LOCAL lCol    AS LONG
          LOCAL lRow    AS LONG
          LOCAL hCtl    AS LONG
          CONTROL HANDLE hDlg, lID TO hCtl
          lStyle = ListView_GetExtendedListViewStyle(hCtl)
          ListView_SetExtendedListViewStyle hCtl, _
              lStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES
          'Load column headers.
          tLVC.mask    = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM
          tLVC.fmt     = %LVCFMT_LEFT
          tLVC.pszText = VARPTR(szBuf)
          FOR lCol = 0 TO lColCnt - 1
              szBuf = "Column " + FORMAT$(lCol+1)
              tLVC.iOrder = lCol
              ListView_InsertColumn hCtl, lCol, tLVC
          NEXT lCol
          'Load sample data.
          FOR lRow = 0 TO lRowCnt - 1
              tLVI.stateMask   = %LVIS_FOCUSED
              tLVI.pszText     = VARPTR(szBuf)
              tLVI.iItem       = lRow
              FOR lCol = 0 TO lColCnt - 1
                  szBuf           = "Column " + FORMAT$(lCol+1) + " Row " + FORMAT$(lRow+1)
                  tLVI.iSubItem   = lCol
                  tLVI.lParam     = lRow
                  IF lCol = 0 THEN
                      tLVI.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                      ListView_InsertItem hCtl, tLVI
                  ELSE
                      tLVI.mask = %LVIF_TEXT
                      ListView_SetItem hCtl, tLVI
                  END IF
              NEXT lCol
          NEXT i
          'Auto size columns.
          FOR lCol = 0 TO lColCnt - 1
              ListView_SetColumnWidth hCtl, lCol, %LVSCW_AUTOSIZE
          NEXT lCol
      END FUNCTION
      '
      SUB ResizeControls(BYVAL X AS LONG,BYVAL Y AS LONG)
          ' In this routine the positions and sizes of all the controls
          ' are specified as proportions (~percentages) of the dialog
          ' X and Y dimensions. Imagine when doing the design that the
          ' dialog area is 100 x 100 in percent. Define the position and
          ' size of the controls according to this area. When resizing is
          ' done, the proportions (~percentages) defining each control are
          ' never changed - only X and Y (defining the absolute size of the
          ' dialog) are changed.
          '
          ' Variables defining position and size of each control in turn
          LOCAL Xp& ' Horizontal position (upper-left corner)
          LOCAL Yp& ' Vertical position   (upper-left corner)
          LOCAL W&  ' Width
          LOCAL H&  ' Height
          '
          SendMessage hForm1&, %WM_SETREDRAW, %FALSE, BYVAL %NULL ' Disable redraw temporarily to reduce flicker.
          '
          ' Resize TEXTBOX while maintaining integral line height.
          Xp = .25*X : Yp = .02*Y : W = .74*X : H = .5*Y
          CALL SizeTextbox(hForm1&,%FORM1_TEXT1,Xp,Yp,W,H,0)
          '
          ' Resize LISTBOX while maintaining integral line height.
          Xp = .02*X : Yp = .14*Y : W = .22*X : H = .75*Y
          CALL SizeListbox(hForm1&,%FORM1_LISTBOX1,Xp,Yp,W,H,0)
          '
          ' Resize COMBOBOX while maintaining integral line height in dropped rectangle.
          Xp = .02*X : Yp = .02*Y : W = .22*X : H = .5*Y
          CALL SizeCombobox(hForm1&,%FORM1_COMBOBOX1,Xp,Yp,W,H,0)
          '
          ' Resize LISTVIEW while maintaining integral line height.
          Xp = .25*X : Yp = .55*Y : W = .58*X : H = .35*Y
          CALL SizeListview(hForm1&,%FORM1_LISTVIEW,Xp,Yp,W,H,0)
          '
          ' Resize BUTTONS.
          Xp = .85*X : Yp = .70*Y : W = .14*X : H = .07*Y
          MoveWindow hButton1&,Xp,Yp,W,H,%TRUE
          '
          Xp = .85*X : Yp = .80*Y : W = .14*X : H = .07*Y
          MoveWindow hButton2&,Xp,Yp,W,H,%TRUE
          '
          SendMessage hForm1&, %WM_SETREDRAW, %TRUE, BYVAL %NULL ' enable redraw
          InvalidateRect hForm1&, BYVAL %NULL , %TRUE
          UpdateWindow hForm1&
      END SUB
      
      ' *************************************************************
      '                             Dialog Window Procedure
      '                             for Form Form1
      '                             uses Global Handle - hForm1&
      ' *************************************************************
      
       CALLBACK FUNCTION Form1_DlgProc
          DIM MinMaxPtr AS MINMAXINFO PTR
          DIM hStatusBar AS STATIC DWORD
          DIM StatusText AS ASCIIZ * 250
          LOCAL HeadNotif AS HD_NOTIFY PTR
          LOCAL pNMHDR    AS NMHDR PTR
          LOCAL rc AS Rect ,X1&,Y1&,X&,Y&
          LOCAL CtrlID    AS DWORD
          DIM StatusBarHeight AS STATIC LONG
          SELECT CASE CBMSG
              CASE %WM_INITDIALOG
                  ' Ensure correct initial sizing.
                  GetClientRect CBHNDL, rc
                  X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                  CALL ResizeControls(X,Y)
                  ' The next few lines define a status bar.
                  ' NB: The area of the status bar is subtracted from the available dialog area.
                  hStatusBar = CreateStatusWindow(%SBARS_SIZEGRIP OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %CCS_BOTTOM, "", CBHNDL, 0)
                  DIALOG PIXELS hForm1&, X&, Y& TO UNITS X1&, Y1&
                  StatusText = "Dialog Size in pixels: X: "+FORMAT$(X,"####")+"   Y: "+FORMAT$(Y,"####") _
                      + ",  in dialog units: X: "+FORMAT$(X1,"###")+"   Y: "+FORMAT$(Y1,"###")
                  SendMessage hStatusBar, %WM_SETTEXT, 0, VARPTR(StatusText)
                  GetClientRect hStatusBar, rc
                  StatusBarHeight& = rc.nBottom - rc.nTop
                  SetFocus CBHNDL
              CASE %WM_SIZE
                  ' Get size of dialog after tracking.
                  GetClientRect CBHNDL, rc
                  ' Resize status bar
                  MoveWindow hStatusBar, rc.nLeft,rc.nBottom-StatusBarHeight, _
                      rc.nRight - rc.nLeft, StatusBarHeight, %TRUE
                  ' Resize controls
                  X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                  CALL ResizeControls(X,Y)
                  DIALOG PIXELS hForm1&, X&, Y& TO UNITS X1&, Y1&
                  StatusText = "Dialog Size in pixels: X: "+FORMAT$(X,"####")+"   Y: "+FORMAT$(Y,"####") _
                      + ",  in dialog units: X: "+FORMAT$(X1,"###")+"   Y: "+FORMAT$(Y1,"###")
                  SendMessage hStatusBar, %WM_SETTEXT, 0, VARPTR(StatusText)
              CASE %WM_GETMINMAXINFO
                  MinMaxPtr=CBLPARAM
                  ' Set the minimum size of dialog. You can define these values according to need.
                  @MinMaxPtr.ptMinTrackSize.x = 480 ' minimum X of dialog in pixels
                  @MinMaxPtr.ptMinTrackSize.y = 330 ' minimum Y of dialog in pixels
              CASE %WM_NOTIFY
                  HeadNotif = CBLPARAM
                  pNMHDR = CBLPARAM
                  IF @HeadNotif.hdr.Code = %HDN_ITEMCHANGED THEN
                      ' Resize if a divider in the listview header has been dragged.
                      GetClientRect CBHNDL, rc
                      X =  rc.nRight - rc.nLeft : Y = rc.nBottom - rc.nTop
                      '
                      ' since @HeadNotif.hdr.idFrom for some unknown reason is always zero, the CtrlID of
                      ' the listview had to be obtained using the method below devised by David Kenny.
                      '
                      WINDOW GET ID GetParent(@pNMHDR.hwndFrom) TO CtrlID 'Get the ID of the parent of the control (the listview)
                      ' David Kenny explains:
                      ' "This is the way I am getting the conrol ID.
                      ' I am getting the parent handle of the handle passed in hwndFrom.
                      ' It does match the listview handle.  So I get the CtrlID using it.
                      ' This does work when I have multiple Listviews on the same window."
                      '
                      CALL SizeListview(CBHNDL,CtrlID,.25*X,.55*Y,.58*X,.35*Y,0)
                  END IF
              CASE %WM_COMMAND
                  ' Process Messages to Controls that have no Callback Function
                  ' and Process Messages to Menu Items
                  SELECT CASE LOWRD(CBWPARAM)    ' Parse by Ctrl ID #
                      CASE  %Form1_EXIT          ' Popup Menu Item Selected
                          DIALOG END hForm1&
                      CASE ELSE
                  END SELECT
          END SELECT
          FUNCTION = 0
      END FUNCTION
      'Best regards
      
      ' ------------------------------------------------
      CALLBACK FUNCTION CBF_FORM1_BUTTON2
          IF CBCTLMSG=%BN_CLICKED THEN
              DIALOG END hForm1&
          END IF
      END FUNCTION
      ' ------------------------------------------------
      Last edited by Erik Christensen; 29 Sep 2009, 10:32 AM.

      Comment

      Working...
      X