- ' Helper routines for resizing and moving / stretching controls 
- ' in a window and setting the minimum size of a window 
-     
- 'factors for placement, used as string:  
- '  "TL" or "0.0, 0.0"  = Top left 
- '  "TM" or "0.5, 0.0"  = Top middle 
- '  "TR" or "1.0, 0.0"  = Top right 
- '  "ML" or "0.0, 0.5"  = Middle left  
- '  "MM" or "0.5, 0.5"  = Middle middle (Centre) 
- '  "MR" or "1.0, 0.5"  = Middle right  
- '  "BL" or "0.0, 1.0"  = Bottom left 
- '  "BM" or "0.5, 1.0"  = Bottom middle 
- '  "BR" or "1.0, 1.0"  = Bottom right 
-   
- ' 
- 'Examples: 
- ' 
- 'Pin control on the bottom-right-hand side of the window 
- 'pinCtl(hCtl, hWin, "BR") 
- 'pinCtl(hCtl, hWin, "1.0, 1.0") 
-   
- 'Move / Stretch control if window is resized, from offset 1 to offset 2 
- 'pinCtl(hCtl, hWin, "TL", "BR" ) 
- 'pinCtl(hCtl, hWin, "0.0, 0.0", "1.0, 1.0") 
-   
- 'Stop resizing and moving control if the window falls below a certain size (pixels) 
- 'unpinCtl(hCtl, hWin, 450, 350) 
-   
- 'Move / Resize the controls when WM_SIZE message of parent window is handled: 
- 'resizeControls(hWin) 
-   
- 'Limit the minimum permitted size of a window to width and height (pixels), 
- 'can be used with the WM_GETMINMAXINFO message: 
- 'setMinSize(450, 350) 
-   
- ===================================================================================  
-   
- uses corewin 
-   
- % HWND_DESKTOP=0 
- % WM_SIZING=532 
- % WM_GETMINMAXINFO=36 
- % SWP_NOZORDER=4 
- % SWP_DEFERERASE=0x2000 
-   
- type Sizel 
-    int cx    'width 
-    int cy    'height 
- end type 
-   
- type PFactor 
-    double fx 
-    double fy 
- end type 
-        
- type sizing_data 
-    int index 
-    sys hParent 
-    sys hCtl 
-    PFactor pf1                    'placement factors 
-    PFactor pf2                    'placement factors 
-    RECT ofs                       'offset Left, Top, Right, Bottom 
-    int unpinned                   '0=pinned, 1=unpinned 
-    int w, h                       'width and height of parent 
- end type 
-   
- 'bounds for record data 
- type MaxPinnedCtls 
-    int count 
- end type 
-   
- MaxPinnedCtls MaxPinned = {10}    
- redim sizing_data PinCtl_Rec[MaxPinned.count] 
-   
-   
- 'Attach position of the Control relative to the Parent window 
- sub pinCtl(sys hCtl, sys hParent, string placement1, optional string placement2="NONE_") 
-     PFactor pf1, pf2  
-   
-     string place1=lcase(ltrim rtrim(placement1)) 
-     string place2=lcase(ltrim rtrim(placement2)) 
-   
-     'Method 1: Static attachment 
-     while 1  
-        if place1="tl" then pf1.fx=0.0 : pf1.fy=0.0 : exit while 
-        if place1="tm" then pf1.fx=0.5 : pf1.fy=0.0 : exit while 
-        if place1="tr" then pf1.fx=1.0 : pf1.fy=0.0 : exit while 
-        if place1="ml" then pf1.fx=0.0 : pf1.fy=0.5 : exit while 
-        if place1="mm" then pf1.fx=0.5 : pf1.fy=0.5 : exit while 
-        if place1="mr" then pf1.fx=1.0 : pf1.fy=0.5 : exit while 
-        if place1="bl" then pf1.fx=0.0 : pf1.fy=1.0 : exit while 
-        if place1="bm" then pf1.fx=0.5 : pf1.fy=1.0 : exit while 
-        if place1="br" then pf1.fx=1.0 : pf1.fy=1.0 : exit while               
-        'factors as values? 
-        int pos=instr(place1,",") 
-        if pos then pf1.fx=val(left(place1,pos-1)) : pf1.fy=val(mid(place1,pos+1)) : exit while 
-        mbox "Error: wrong placement 1 in pinCtl function" : exit while 
-     wend 
-     if place2="none_" then pf2.fx=pf1.fx : pf2.fy=pf1.fy 
-         
-     'Method 2: Stretchy attachment? 
-     while 1 
-        if place2="none_" then exit while  
-        if place2="tl" then pf2.fx=0.0 : pf2.fy=0.0 : exit while 
-        if place2="tm" then pf2.fx=0.5 : pf2.fy=0.0 : exit while 
-        if place2="tr" then pf2.fx=1.0 : pf2.fy=0.0 : exit while 
-        if place2="ml" then pf2.fx=0.0 : pf2.fy=0.5 : exit while 
-        if place2="mm" then pf2.fx=0.5 : pf2.fy=0.5 : exit while 
-        if place2="mr" then pf2.fx=1.0 : pf2.fy=0.5 : exit while 
-        if place2="bl" then pf2.fx=0.0 : pf2.fy=1.0 : exit while 
-        if place2="bm" then pf2.fx=0.5 : pf2.fy=1.0 : exit while 
-        if place2="br" then pf2.fx=1.0 : pf2.fy=1.0 : exit while               
-        'factors as values? 
-        pos=instr(place2,",") 
-        if pos then pf2.fx=val(left(place2,pos-1)) : pf2.fy=val(mid(place2,pos+1)) : exit while 
-        mbox "Error: wrong placement 2 in pinCtl function" : exit while 
-     wend    
-   
-     Sizel ctlSize 
-     RECT pRect, cRect 
-     RECT ofs 
-       
-     'Get the size of the hParent window to be able to calculate offsets 
-     GetClientRect(hParent, &pRect) 
-     ctlSize.cx = pRect.right : ctlSize.cy = pRect.bottom 
-     GetWindowRect(hCtl, &cRect) 
-         
-     'Calculate the offsets of the left, top, bottom, and right of the control. 
-     MapWindowPoints(HWND_DESKTOP, GetParent(hCtl),  &cRect, 2) 
-     ofs.left=  cRect.left   - ctlSize.cx*pf1.fx 
-     ofs.top=   cRect.top    - ctlSize.cy*pf1.fy 
-     ofs.right= cRect.right  - ctlSize.cx*pf2.fx 
-     ofs.bottom=cRect.bottom - ctlSize.cy*pf2.fy 
-   
-     'Add entry to the data records 
-     static int idx  
-     'does hCtl already exist? 
-     int i 
-     for i=1 to idx 
-       if PinCtl_Rec[i].hCtl=hCtl then 
-         idx=i-1 
-         exit for 
-       end if 
-     next i                
-     idx+=1 
-     if idx>MaxPinned.count then 
-       MaxPinned.count+=10 
-       redim sizing_data PinCtl_Rec[MaxPinned.count] 
-     end if   
-     PinCtl_Rec[idx].index=idx 
-     PinCtl_Rec[idx].hParent=hParent 
-     PinCtl_Rec[idx].hCtl=hCtl 
-     PinCtl_Rec[idx].pf1.fx=pf1.fx 
-     PinCtl_Rec[idx].pf1.fy=pf1.fy 
-     PinCtl_Rec[idx].pf2.fx=pf2.fx 
-     PinCtl_Rec[idx].pf2.fy=pf2.fy 
-     PinCtl_Rec[idx].ofs.left=ofs.left 
-     PinCtl_Rec[idx].ofs.top=ofs.top 
-     PinCtl_Rec[idx].ofs.right=ofs.right 
-     PinCtl_Rec[idx].ofs.bottom=ofs.bottom     
- end sub 
-   
- 'Mark control to stop resizing / moving at certain size of window (pixels) 
- sub unpinCtl(sys hCtl, sys hParent, int width, height) 
-     int ix 
-     bool found=false 
-     for ix=1 to MaxPinned.count 
-        if PinCtl_Rec[ix].hCtl=hCtl then 
-          PinCtl_Rec[ix].unpinned=1 
-          PinCtl_Rec[ix].w=width 
-          PinCtl_Rec[ix].h=height 
-          found=true : exit for 
-        end if   
-     next ix 
-     if found=false then mbox "Error: Cannot find hCtl: " hCtl "in PinCtl_Rec" 
- end sub 
-   
- 'Procedure for resizing attached controls when WM_SIZE message is handled 
- sub resizeControls(sys hWin) 
-     PFactor pf1, pf2 
-     RECT ofs    
-     Sizel ctlSize    
-     RECT pRect, cRect   'parent, control 
-   
-     'Get the new size of the window 
-     GetClientRect(hWin, &pRect) 
-     ctlSize.cx = pRect.right : ctlSize.cy = pRect.bottom    
-   
-     int ix 
-     'Go through each element in the data entries to see if it needs to be moved. 
-     for ix = 1 to MaxPinned.count 
-         if PinCtl_Rec[ix].index=0 then exit for 
-         'If the element was inside the window that was resized, it needs to move. 
-         if hWin = PinCtl_Rec[ix].hParent then 
-             'Get the data out of the data entries for that record 
-             pf1.fx=PinCtl_Rec[ix].pf1.fx : pf1.fy=PinCtl_Rec[ix].pf1.fy : pf2.fx=PinCtl_Rec[ix].pf2.fx : pf2.fy=PinCtl_Rec[ix].pf2.fy             
-             ofs.left=PinCtl_Rec[ix].ofs.left : ofs.top=PinCtl_Rec[ix].ofs.top : ofs.right=PinCtl_Rec[ix].ofs.right : ofs.bottom=PinCtl_Rec[ix].ofs.bottom             
-   
-             'Stop resizing / moving if hParent falls below a certain size (pixels)? 
-             if PinCtl_Rec[ix].unpinned=1 then 
-               if ctlSize.cx < PinCtl_Rec[ix].w then ctlSize.cx=PinCtl_Rec[ix].w 
-               if ctlSize.cy < PinCtl_Rec[ix].h then ctlSize.cy=PinCtl_Rec[ix].h                             
-             end if 
-   
-             'Calculate the new position and size of the control 
-             ofs.left+=ctlSize.cx*pf1.fx : ofs.top+=ctlSize.cy*pf1.fy : ofs.right+=ctlSize.cx*pf2.fx : ofs.bottom+=ctlSize.cy*pf2.fy 
-             SetWindowPos(PinCtl_Rec[ix].hCtl, 0, ofs.left, ofs.top, (ofs.right-ofs.left), (ofs.bottom-ofs.top), SWP_NOZORDER|SWP_DEFERERASE)                                                      
-         end if 
-     next ix 
- end sub 
-   
- 'Can be combined with WM_GETMINMAXINFO message 
- macro setMinSize(xMin, yMin) 
-    MINMAXINFO *mm 
-    @mm = lParam 
-   
-    mm.ptMinTrackSize.x = xMin 
-    mm.ptMinTrackSize.y = yMin 
- end macro 
-   
- ============================================================================= 
- 'Adapt offsets of an existing control, using the given factors 
- 'Optional add delta to position  
- sub modpinCtl(sys hCtl, optional int dx=0,dy=0,dcx=0,dcy=0) 
-     Sizel ctlSize    
-     RECT pRect, cRect   'parent, control 
-     RECT ofs 
-      
-     int i 
-     for i=1 to MaxPinned.count 
-       if PinCtl_Rec[i].hCtl=hCtl then 
-         exit for 
-       end if 
-     next i 
-     if PinCtl_Rec[i].hCtl != hCtl then exit sub                
-   
-     'Get the size of the hParent window to be able to calculate offsets 
-     GetClientRect(PinCtl_Rec[i].hParent, &pRect) 
-     ctlSize.cx = pRect.right : ctlSize.cy = pRect.bottom 
-     GetWindowRect(hCtl, &cRect) 
-   
-     'Calculate the offsets of the left, top, bottom, and right of the control. 
-     MapWindowPoints(HWND_DESKTOP, GetParent(hCtl),  &cRect, 2) 
-     ofs.left=  cRect.left   + dx  - ctlSize.cx*PinCtl_Rec[i].pf1.fx 
-     ofs.top=   cRect.top    + dy  - ctlSize.cy*PinCtl_Rec[i].pf1.fy 
-     ofs.right= cRect.right  + dcx - ctlSize.cx*PinCtl_Rec[i].pf2.fx 
-     ofs.bottom=cRect.bottom + dcy - ctlSize.cy*PinCtl_Rec[i].pf2.fy 
-   
-     PinCtl_Rec[i].ofs.left=ofs.left 
-     PinCtl_Rec[i].ofs.top=ofs.top 
-     PinCtl_Rec[i].ofs.right=ofs.right 
-     PinCtl_Rec[i].ofs.bottom=ofs.bottom     
- end sub 
-