You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
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
PowerBASIC and related source code. Please do not post questions or discussions, just source code.
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, 11:07 AM.
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, 10:00 AM.
Reason: Minor documentation spelling/grammar corrections
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Leave a comment: