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

Relocate and resize controls automatically when dialog size changes

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

  • Relocate and resize controls automatically when dialog size changes

    Test code, Example.bas
    Code:
    ' This example program was written using PBWin9 DDT commands.
     
    '----------------------------------------------------------------------------(')
     
    #COMPILE EXE "Example.exe"
    #DIM ALL
     
    '----------------------------------------------------------------------------(')
     
    %USEMACROS = 1
     
    '----------------------------------------------------------------------------(')
     
    #IF NOT %DEF( %WINAPI )
     #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF( %COMMCTRL_INC )
     #INCLUDE "COMMCTRL.INC"
    #ENDIF
    #INCLUDE "lsxLibrary.inc"  ' Include the lsx library somewhere after win32api.inc"
     
    '----------------------------------------------------------------------------(')
     
    %btnButton1 = 1001
    %btnButton2 = 1002
    %btnButton3 = 1003
    %cbxCombobox = 1004
    %dlgExample = 1005
    %edtEditBox1 = 1006
    %edtEditBox2 = 1007
    %lblComboBox = 1008
    %lblEditBox1 = 1009
    %stbStatusbar = 1010
    %tvwTreeview = 1011
     
    '----------------------------------------------------------------------------(')
     
    FUNCTION PBMAIN( )
     INITCOMMONCONTROLS
     CreateExampleDialog %HWND_DESKTOP
    END FUNCTION
     
    '----------------------------------------------------------------------------(')
     
    CALLBACK FUNCTION ExampleDialogCallback( )
     SELECT CASE AS LONG CBMSG
      CASE %WM_INITDIALOG
       ' Fill in some sample data
       SampleComboBox CB.HNDL, %cbxCombobox, 30
       SampleTreeView CB.HNDL, %tvwTreeview, 5
       ' Register the controls you want to manage
       lsxEngine CB.HNDL, %lblComboBox, %lsxRegister
       lsxEngine CB.HNDL, %cbxCombobox, %lsxRegister
       lsxEngine CB.HNDL, %tvwTreeview, %lsxRegister
       lsxEngine CB.HNDL, %edtEditBox2, %lsxRegister
       lsxEngine CB.HNDL, %btnButton1, %lsxRegister
       lsxEngine CB.HNDL, %btnButton2, %lsxRegister
       lsxEngine CB.HNDL, %btnButton3, %lsxRegister
      CASE %WM_SIZE
       CONTROL SEND CBHNDL, %stbStatusbar, CBMSG, CBWPARAM, CBLPARAM
       ' Tell the engine how you want the controls to react
       lsxEngine CB.HNDL, %lblComboBox, %lsxCalcX
       lsxEngine CB.HNDL, %cbxCombobox, %lsxCalcX
       lsxEngine CB.HNDL, %tvwTreeview, %lsxCalcW OR %lsxCalcH
       lsxEngine CB.HNDL, %edtEditBox2, %lsxCalcY OR %lsxCalcW
       lsxEngine CB.HNDL, %btnButton1, %lsxCalcX OR %lsxCalcY
       lsxEngine CB.HNDL, %btnButton2, %lsxCalcX OR %lsxCalcY
       lsxEngine CB.HNDL, %btnButton3, %lsxCalcX OR %lsxCalcY
      CASE %WM_GETMINMAXINFO
       ' This is here just so the dialog deosn't shrink TOO small
       LOCAL udtMinMaxInfo AS MINMAXINFO PTR
       LOCAL lngResult AS LONG
       lngResult = DEFWINDOWPROC( CB.HNDL, CB.MSG, CB.WPARAM, CB.LPARAM )
       udtMinMaxInfo = CB.LPARAM
       @udtMinMaxInfo.ptMinTrackSize.x = 500
       @udtMinMaxInfo.ptMinTrackSize.y = 350
       FUNCTION = 0
      CASE %WM_NCACTIVATE
       STATIC hWndSaveFocus AS DWORD
       IF ISFALSE CBWPARAM THEN
        hWndSaveFocus = GETFOCUS( )
       ELSEIF hWndSaveFocus THEN
        SETFOCUS( hWndSaveFocus )
        hWndSaveFocus = 0
       END IF
     END SELECT
    END FUNCTION
     
    '----------------------------------------------------------------------------(')
     
    FUNCTION SampleComboBox( BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount _
       AS LONG ) AS LONG
     LOCAL i AS LONG
     CONTROL SEND hDlg, lID, %CB_SETEXTENDEDUI, %TRUE, 0
     FOR i = 1 TO lCount
      COMBOBOX ADD hDlg, lID, USING$( "Test Item #", i )
     NEXT i
    END FUNCTION
     
    '----------------------------------------------------------------------------(')
     
    FUNCTION SampleTreeView( BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount _
       AS LONG ) AS LONG
     LOCAL i AS LONG
     LOCAL j AS LONG
     LOCAL k AS LONG
     LOCAL hRoot AS DWORD
     LOCAL hParent AS DWORD
     LOCAL hChild AS DWORD
     FOR i = 1 TO lCount
      TREEVIEW INSERT ITEM hDlg, lID, %TVI_ROOT, %TVI_LAST, 0, 0, USING$( "Root#", i ) TO hRoot
      FOR j = 1 TO lCount
       TREEVIEW INSERT ITEM hDlg, lID, hRoot, %TVI_LAST, 0, 0, USING$( "Item#", j ) TO hParent
       FOR k = 1 TO lCount
        TREEVIEW INSERT ITEM hDlg, lID, hParent, %TVI_LAST, 0, 0, USING$( "SubItem#", k ) TO hChild
       NEXT k
      NEXT j
     NEXT i
    END FUNCTION
     
    '----------------------------------------------------------------------------(')
     
    FUNCTION CreateExampleDialog( BYVAL hParent AS DWORD ) AS LONG
     LOCAL lngResult AS LONG
     LOCAL hDlg AS DWORD
     DIALOG NEW hParent, "Example DDT Dialog", 157, 83, 376, 300, %WS_POPUP OR _
       %WS_BORDER OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_SYSMENU OR _
       %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
       %WS_VISIBLE OR %DS_MODALFRAME OR %DS_CENTER OR %DS_3DLOOK OR _
       %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CLIENTEDGE OR _
       %WS_EX_WINDOWEDGE OR %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
       %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
     CONTROL ADD LABEL, hDlg, %lblEditBox1, "Edit Box 1", 7, 7, 42, 13, _
       %WS_CHILD OR %WS_VISIBLE OR %SS_LEFT OR %SS_CENTERIMAGE, %WS_EX_LEFT _
       OR %WS_EX_LTRREADING
     CONTROL ADD TEXTBOX, hDlg, %edtEditBox1, "I don't move", 49, 7, 114, 13
     CONTROL ADD LABEL, hDlg, %lblComboBox, "Combobox", 224, 7, 42, 13, _
       %WS_CHILD OR %WS_VISIBLE OR %SS_LEFT OR %SS_CENTERIMAGE, %WS_EX_LEFT _
       OR %WS_EX_LTRREADING
     CONTROL ADD COMBOBOX, hDlg, %cbxCombobox,, 266, 7, 105, 77, %WS_CHILD OR _
       %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWNLIST OR %CBS_SORT, _
       %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
     CONTROL ADD TREEVIEW, hDlg, %tvwTreeview, "", 7, 28, 364, 182, _
       %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %TVS_HASBUTTONS OR _
       %TVS_HASLINES OR %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS OR _
       %TVS_CHECKBOXES, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
       %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
     CONTROL ADD TEXTBOX, hDlg, %edtEditBox2, "Edit box 2 ( in read only " + _
       "mode)", 7, 217, 280, 63, %WS_CHILD OR %WS_VISIBLE OR %ES_LEFT OR _
       %ES_MULTILINE OR %ES_READONLY, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
       %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
     CONTROL ADD BUTTON, hDlg, %btnButton1, "Button1", 294, 217, 35, 28
     CONTROL ADD BUTTON, hDlg, %btnButton2, "Button2", 336, 217, 35, 28
     CONTROL ADD BUTTON, hDlg, %btnButton3, "Button 3", 294, 252, 77, 28
     CONTROL ADD STATUSBAR, hDlg, %stbStatusbar, "", 0, 287, 375, _
       13, %WS_CHILD OR %WS_VISIBLE, %WS_EX_TRANSPARENT OR %WS_EX_LEFT OR _
       %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
     DIALOG SHOW MODAL hDlg, CALL ExampleDialogCallback TO lngResult
     FUNCTION = lngResult
    END FUNCTION
    lsxLibrary.inc
    Code:
    '======================================================================'
    ' "LSX Engine" (Location Size eXchanger)                               '
    '                                                                      '
    ' An include library written in PB9 to easily relocate or resize       '
    ' DDT controls when a dialog is resized.                               '
    '                                                                      '
    ' Written by: George W. Bleck                                          '
    ' Revision:   1.0                                                      '
    ' Date:       2009/04/26                                               '
    '======================================================================'
    ' To use the engine, you must first pre-register each control you wish '
    ' to update later.  Registration is easy and would typically be done   '
    ' in your dialog's WM_INITIALIZE.                                      '
    '                                                                      '
    ' Here is an example of a registration:                                '
    '                                                                      '
    '    lsxEngine {Dialog Handle}, {Control ID}, %lsxRegister             '
    '                                                                      '
    ' If you manually relocate or resize a control and want to manage the  '
    ' new parameters it has, just register the control again. It will      '
    ' update the database with the new information. Be aware this command  '
    ' cannot be combined with other commands.                              '
    '======================================================================'
    ' To have that control Relocate/Resize properly in your dialog you     '
    ' just need to call the engine again under you dialog's WM_SIZE event. '
    '                                                                      '
    ' For example, if you wanted the control to move horizontally as the   '
    ' dialog widened just put the following under WM_SIZE:                 '
    '                                                                      '
    '    lsxEngine {Dialog Handle}, {Control ID}, %lsxCalcX                '
    '                                                                      '
    ' Note the example did not specify anything about the control's width  '
    ' or about it's Y position or height.  The engine only changes the     '
    ' constraints you tell it to.  All other constraints are left as is.   '
    '                                                                      '
    ' This leads us to combined commands.  You can combine commands using  '
    ' the OR operator to have cumulative effects.  Another example is in   '
    ' order.  If you wanted a control to widen as your dialog is widened   '
    ' but it should slide down as the dialog height is stretched, just do  '
    ' the following in your WM_SIZE for that control:                      '
    '                                                                      '
    '    lsxEngine {Dialog Handle}, {Control ID}, %lsxCalcY OR %lsxCalcW   '
    '                                                                      '
    ' It's that simple!  Just create a WM_SIZE entry for each control      '
    ' detailing how you want it to act when the dialog size is changed.    '
    '======================================================================'
    ' There is also a command to ERASE the entire control database in the  '
    ' event you want to rebuild the database.  An example of this would be '
    ' If you destroy and recreate all your dialogs.  Also be aware that    '
    ' This command cannot be combined with other commands.                 '
    '======================================================================'
    ' Lastly, given the simplicity of the mechanisms you can create some   '
    ' interesting effects by combining seemingly opposite commands.        '
    ' Combining the %lsxCalcX command with the %lsxCalcW command would     '
    ' cause a control to get wider and move to the right as a dialog is    '
    ' stretched wider.                                                     '
    ' Not quite sure of a viable use but HEY you never know!               '
    '======================================================================'
     
    '----------------------------------------------------------------------------(')
    
    ' Custom constants
    %lsxRegister = &B000001 ' Registers a control in the control database
    %lsxCalcX    = &B000010 ' Causes a control to move horizontally as a dialog's width is changed
    %lsxCalcY    = &B000100 ' Causes a control to move vertically as a dialog's height is changed
    %lsxCalcW    = &B001000 ' Causes a control to get wider/narrower as a dialog's width is changed
    %lsxCalcH    = &B010000 ' Causes a control to get taller/shorter as a dialog's height is changed
    %lsxReset    = &B100000 ' ERASES the entire control database
     
    '----------------------------------------------------------------------------(')
    
    ' Custom data type declaration
    TYPE lsxDataType
     hDlg AS DWORD
     lngControlID AS LONG
     lngX AS LONG
     lngY AS LONG
     lngW AS LONG
     lngH AS LONG
     lngCalcX AS LONG
     lngCalcW AS LONG
     lngCalcY AS LONG
     lngCalcH AS LONG
    END TYPE
     
    '----------------------------------------------------------------------------(')
    
    ' Internally used function, determines if a control is already in the database and returns it's array index
    FUNCTION lsxGetDBIndex( BYVAL hDlg AS DWORD, BYVAL lngControlID AS LONG, udtControlInfo( ) AS lsxDataType, BYVAL lngControlCount AS LONG ) AS DWORD
     LOCAL lngControlIndex AS LONG
     FOR lngControlIndex = 1 TO lngControlCount
      IF udtControlInfo( lngControlIndex ).hDlg = hDlg AND udtControlInfo( lngControlIndex ).lngControlID = lngControlID THEN
       FUNCTION = lngControlIndex
       EXIT FUNCTION
      END IF
     NEXT lngControlIndex
    END FUNCTION
     
    '----------------------------------------------------------------------------(')
    
    SUB lsxEngine( BYVAL hDlg AS DWORD, BYVAL lngControlID AS LONG, BYVAL dwdCommand AS DWORD )
     DIM udtControlInfo( 0 ) AS STATIC lsxDataType
     STATIC lngControlCount AS LONG
     LOCAL udtNewControlInfo AS lsxDataType
     LOCAL lngDlgW AS LONG
     LOCAL lngDlgH AS LONG
     LOCAL lngSearchIndex AS LONG
     DIALOG GET CLIENT hDlg TO lngDlgW, lngDlgH
     ' Record the control's existing information
     IF (dwdCommand AND %lsxRegister) = %lsxRegister THEN
      lngSearchIndex = lsxGetDBIndex( hDlg, lngControlID, udtControlInfo( ), lngControlCount )
      IF lngSearchIndex = 0 THEN
       INCR lngControlCount
       REDIM PRESERVE udtControlInfo( lngControlCount )
       lngSearchIndex = lngControlCount
      END IF
      ' Record the dialog handle and control id
      udtControlInfo( lngSearchIndex ).hDlg = hDlg
      udtControlInfo( lngSearchIndex ).lngControlID = lngControlID
      ' Get the controls initial loc and size information
      CONTROL GET LOC hDlg, lngControlID TO udtControlInfo( lngSearchIndex ).lngX, udtControlInfo( lngSearchIndex ).lngY
      CONTROL GET SIZE hDlg, lngControlID TO udtControlInfo( lngSearchIndex ).lngW, udtControlInfo( lngSearchIndex ).lngH
      ' Precalculate the offsets that are used later to make life easier/faster
      udtControlInfo( lngSearchIndex ).lngCalcX = lngDlgW - udtControlInfo( lngSearchIndex ).lngX
      udtControlInfo( lngSearchIndex ).lngCalcW = lngDlgW - udtControlInfo( lngSearchIndex ).lngW
      udtControlInfo( lngSearchIndex ).lngCalcY = lngDlgH - udtControlInfo( lngSearchIndex ).lngY
      udtControlInfo( lngSearchIndex ).lngCalcH = lngDlgH - udtControlInfo( lngSearchIndex ).lngH
      EXIT SUB
     END IF
     ' Reset the database and control count, deletes all existing control info
     IF (dwdCommand AND %lsxReset) = %lsxReset THEN
      ERASE udtControlInfo( )
      lngControlCount = 0
      EXIT SUB
     END IF
     ' If we got this far client wants us to actually do calculate a controls Loc and or Size'
     '                                                                                       '
     ' Be aware this is GIGO, so a combo like "%lsxCalcX OR %lsxCalcW" can be passed.        '
     '                                                                                       '
     ' In the above example, if you widened a dialog it would cause the control  to not      '
     ' only move to the right, but widen as well!  Probably not an expected result.          '
     ' But hey, you never know what someone might want right???                              '
     lngSearchIndex = lsxGetDBIndex( hDlg, lngControlID, udtControlInfo( ), lngControlCount )
     IF lngSearchIndex THEN
      udtNewControlInfo = udtControlInfo( lngSearchIndex )
      IF ( dwdCommand AND %lsxCalcX ) = %lsxCalcX THEN
       udtNewControlInfo.lngX = lngDlgW - udtNewControlInfo.lngCalcX
      END IF
      IF ( dwdCommand AND %lsxCalcY ) = %lsxCalcY THEN
       udtNewControlInfo.lngY = lngDlgH - udtNewControlInfo.lngCalcY
      END IF
      IF ( dwdCommand AND %lsxCalcW ) = %lsxCalcW THEN
       udtNewControlInfo.lngW = lngDlgW - udtNewControlInfo.lngCalcW
      END IF
      IF ( dwdCommand AND %lsxCalcH ) = %lsxCalcH THEN
       udtNewControlInfo.lngH = lngDlgH - udtNewControlInfo.lngCalcH
      END IF
      CONTROL SET LOC hDlg, lngControlID, udtNewControlInfo.lngX, udtNewControlInfo.lngY
      CONTROL SET SIZE hDlg, lngControlID, udtNewControlInfo.lngW, udtNewControlInfo.lngH
      CONTROL REDRAW hDlg, lngControlID
      EXIT SUB
     END IF
    END SUB
    Last edited by George Bleck; 26 Apr 2009, 11:00 AM. Reason: Minor documentation spelling/grammar corrections
    <b>George W. Bleck</b>
    <img src='http://www.blecktech.com/myemail.gif'>

  • #2
    Where can TreeView_SetItem be found ??
    Dubravko

    Comment


    • #3
      Not sure why it didn't work out of the box for you but it gave me the opportunity to more fully convert the Example.bas to full PBWin9 compliance.

      I used PBFORMS to spit it out quickly then modded it to use PBWin9 commands. I forgot to mod the sample treeview section though :whistle:.

      Recopy the Example.bas as it should now be fully (I hope!) converted to PBWin9 commands.
      Last edited by George Bleck; 26 Apr 2009, 10:44 AM.
      <b>George W. Bleck</b>
      <img src='http://www.blecktech.com/myemail.gif'>

      Comment


      • #4
        Just as a side note to anyone interested, it would be unfair to not point out there is a another excellent control resize post here:

        http://www.powerbasic.com/support/pb...ghlight=resize

        It allows you to preset the control's movement methods and then call a single command to resize them all. Very nice!

        In an application I was writing I needed to change some of the resize constraints on the fly and as well as add/delete controls so I built my code from the ground up to handle things one-by-one. Without trying the other post I'm not sure how you handle creating/destroying controls. I also like to see what the controls are doing in WM_SIZE so it makes some descriptive sense to me at the time something is resizing.

        It boils down to taste in the long run and I don't want others to miss out on another fine peice of code in the other post if it suits your needs better.
        Last edited by George Bleck; 26 Apr 2009, 12:07 PM.
        <b>George W. Bleck</b>
        <img src='http://www.blecktech.com/myemail.gif'>

        Comment

        Working...
        X