BCX Demonstration Program TabReOrderAnchor.bas by Ian Casey

The Code

Demo showing 3 examples of tab control.

  1. Move/Anchor controls - ~lines ~103-104, 202-210 and ~280-506
  2. Move Tab to new position - ~lines 121-146 and lines 220-278
  3. Ownerdrawn/Colorize the selected tabs- lines ~ 65 and lines ~148-190

This demo was developed as follows


 GUI "BCX_Tab_Demo",PIXELS
 
 #include <winuser.h>
  
 CONST LHandle(A) = (HWND)GetWindowLongPtr(A,GWLP_USERDATA)
 CONST GetImageListFile(A,B) = ImageList_LoadImage(NULL,A,B,0,CLR_NONE,IMAGE_BITMAP,LR_LOADFROMFILE)
  
 CONST tabPadding = 2                        'adjust as needed 
 CONST tabbackcolor = 0x00FFFF                 'adjust as needed 
 'CONST tabtextcolor = 0xFF0000                 'adjust as needed 
 GLOBAL tabtextcolor ' = 0xFF0000 
 ' A = Filename 
 ' B = width of one image in list 
  
 GLOBAL Form1  AS HWND
 GLOBAL Tabb1  AS HWND
  
 GLOBAL Button1    AS HWND
 GLOBAL Button2    AS HWND
 GLOBAL Button3    AS HWND
 GLOBAL Button4    AS HWND
 GLOBAL Button5    AS HWND
 GLOBAL Button6    AS HWND
 GLOBAL Button7    AS HWND
 GLOBAL Button8    AS HWND
 GLOBAL Button9    AS HWND
 GLOBAL Listview   AS HWND
 GLOBAL Rich       AS HWND
 GLOBAL Slide1     AS HWND
 GLOBAL Slide2     AS HWND
 GLOBAL Slide3     AS HWND
 GLOBAL Slide4     AS HWND
 GLOBAL Stc1       AS HWND
 GLOBAL Stc2       AS HWND
 GLOBAL StatusBar1 AS HWND
  
 GLOBAL Stc1_FC
 GLOBAL Stc1_BC
  
 GLOBAL ID_StatusBar1
  
 GLOBAL Tab1Page[7] AS HWND
  
 SET Days$[7]
 "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
 END SET
  
 '------------------------------------------------------------------------------ 
  
 TYPE anchor
   IsSubForm
   XMin
   YMin
   PrevRC AS RECT
 END TYPE
  
 CONST StatusBar1_Styles = WS_CHILD|WS_VISIBLE|WS_TABSTOP|SBARS_SIZEGRIP
 CONST StatusBar1_XStyles = WS_EX_LEFT
  
 SUB FORMLOAD
   'Notice these controls are assigned to the Tab Control 
   Form1    = BCX_FORM("BCX Colorized Tab Demo with sizing & drag/drop",0,0,428,355)
   Tabb1    = BCX_TAB(Form1,500, 7,Tab1Page,Days$, 10, 12,400,270)',NULL, _ 
   '  WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS | TCS_OWNERDRAWFIXED | TCS_MULTILINE | TCS_TABS | TCS_FOCUSNEVER,0) 
   MODSTYLE(Tabb1,TCS_OWNERDRAWFIXED | TCS_MULTILINE |TCS_SCROLLOPPOSITE)                    'for colorize code by Mr Unreliable 
   TabCtrl_SetPadding(Tabb1, tabPadding, 0)                'just padding around the tabs text 
  
   Rich     = BCX_RICHEDIT("A NEW TAB CONTROL",Tab1Page[0],502,50,10,300,200)
   Listview = BCX_LISTVIEW("" ,Tab1Page[1],505,10,10,370,230)
   Button2  = BCX_BUTTON ("Button 2 "  ,Tab1Page[2],504, 330,220, 60,24)
   Button3  = BCX_BUTTON ("Button 3 "  ,Tab1Page[2],504, 2,220, 60,24)
   Button4  = BCX_BUTTON ("Button 4 "  ,Tab1Page[2],504, 73,220, 60,24)
   Button5  = BCX_BUTTON ("Button 5 "  ,Tab1Page[2],504, 145,220, 60,24)
   Button6  = BCX_BUTTON ("Button 6 "  ,Tab1Page[2],504, 216,220, 60,24)
   Button7  = BCX_BUTTON ("Button 7 "  ,Tab1Page[2],504, 330,2, 60,24)
   Button8  = BCX_BUTTON ("Button 8 "  ,Tab1Page[2],504, 330,105, 60,24)
   Stc1     = BCX_LABEL (CRLF$ & "Proportional Scaling to page size" & CRLF$ & "for Wednesday" ,Tab1Page[2],404, 2,2, 320,210)
   Stc1_FC = 16711680 : Stc1_BC = 8454143
   BCX_SET_FONT Stc1,"Comic Sans MS",14,0,1
   MODSTYLE(Stc1,SS_CENTER)
  
   Slide1   = BCX_SLIDER("Text on bottom",Tab1Page[3],503, 40,20, 80,180,0,TBS_VERT)
   Slide2   = BCX_SLIDER("Thursday Text on top",   Tab1Page[3],503,150,50,180, 60,1)
   Slide3   = BCX_SLIDER("Text on right", Tab1Page[4],503, 50,60, 30, 70,3,TBS_VERT)
   Slide4   = BCX_SLIDER("Text on left Friday",  Tab1Page[4],503, 90,10,150, 40,2)
   Button9  = BCX_BUTTON("Okay, not the greatest demo...Saturday",Tab1Page[5],504,20,20)
  
   Stc2     = BCX_LABEL (CRLF$ & "TAKE A BREAK, " & CRLF$ &" IT'S SUNDAY AFTER ALL"  ,Tab1Page[6],404, 1,1, 388,235)
   BCX_SET_FONT Stc2,"Comic Sans MS",16,0,1
   MODSTYLE(Stc2,SS_CENTER)
  
   'The main form 
   Button1  = BCX_BUTTON("EXIT DEMO",Form1,506,10,285)
   StatusBar1 = BCX_CONTROL(STATUSCLASSNAME, Form1, "A StatusBar", ID_StatusBar1, 0, 433, 632, 20, StatusBar1_Styles, StatusBar1_XStyles)
  
   BCX_SET_FONT LHandle(Slide1),"Comic Sans MS",10,0,1
   BCX_SET_FONT LHandle(Slide2),"Comic Sans MS",10,0,1
   'I created a macro in the demo: Lhandle(slider handle) will give you the label handle. 
   'Of course if you wanted to make the font larger than the system default you would have 
   'to reposition the label or the slider. 
  
   'Set up sizing parameters 
   InitAnchor(Form1)
   InitAnchor(Tabb1, 2)
   CALL LoadBuffer
   CENTER(Form1)
   SHOW(Form1)
  
 END SUB
  
  
 BEGIN EVENTS
   SELECT CASE CBMSG
   CASE WM_CTLCOLORSTATIC, WM_CTLCOLORBTN, WM_CTLCOLOREDIT,WM_CTLCOLORLISTBOX, WM_CTLCOLORSCROLLBAR
     SELECT CASE (HWND)CBLPARAM 'Get the control handle 
     CASE  Stc1, Stc2
       FUNCTION = BCX_SETCOLOR(Stc1_FC, Stc1_BC)
     END SELECT
  
     ''**************** This section used in drag/drop of tab arrangements **************** 
   CASE WM_SETCURSOR                                               'add drag/drop reorder tabs 
     CONST OCR_NORMAL = 32512
     DIM hRet AS HWND, pt AS POINT
     STATIC oldX AS LONG, oldY AS LONG, iParam
     STATIC TabMoveInWork
     GetCursorPos(&pt)
     ScreenToClient(Form1, &pt)                                    'pt now has dialog client coordinates 
     hRet = ChildWindowFromPoint(Form1, pt)
     iParam = CINT(CBLPARAM/0xFF00)-2                              'PB - Hi(Word, Cb.LParam)?? 
     SELECT CASE iParam
     CASE WM_LBUTTONDOWN                                         '513 Start Drag 
       IF hRet = Tabb1 AND TabCtrl_GetRowCount(Tabb1) = 1 THEN
         TabMoveInWork = 1 : oldX = pt.x : oldY = pt.y
       END IF
     CASE WM_MOUSEMOVE                                           '512 Moving 
       IF TabMoveInWork AND((oldX <> pt.x) OR(oldY <> pt.y)) THEN
         SetSystemCursor(LoadCursor(NULL,IDC_HAND ),OCR_NORMAL)
       END IF
     CASE WM_LBUTTONUP                                           '514 Drop it 
       IF TabMoveInWork THEN
         CALL MoveTabToNewLocation()
         SetSystemCursor(LoadCursor(NULL,IDC_ARROW),OCR_NORMAL)
       END IF
       TabMoveInWork = 0
     END SELECT
     '**** see MoveTabToNewLocation for the rest of drag drop ************ 
  
     '************ this section for the ownerdrawn tab control -  adapted from Mr Unreliable code ********** 
   CASE WM_DRAWITEM  ' probably tab control asking for tab draw... 
     ' -------------------------------------------- 
     DIM lpDIS AS DRAWITEMSTRUCT PTR
     DIM tDIS AS DRAWITEMSTRUCT
     DIM iTab, xTxt, yTxt, imageidx
     DIM sTxt$
     DIM crFillRct AS COLORREF
     DIM hFillBrush AS HBRUSH
     DIM   tci AS TC_ITEM
  
     lpDIS = (DRAWITEMSTRUCT *)lParam                              'The lParam contains the address of a DRAWITEMSTRUCT 
     CopyMemory(&tDIS, lpDIS, SIZEOF(tDIS))                        'retrieve the struct 
  
     IF (tDIS.CtlType = ODT_TAB) THEN iTab = tDIS.itemID ELSE FUNCTION = TRUE 'just get out of here if not tab 
  
     tci.mask = TCIF_TEXT | TCIF_IMAGE
     tci.cchTextMax = 2048
     tci.pszText = sTxt$
     TabCtrl_GetItem(Tabb1, iTab, &tci)
     sTxt$ = tci.pszText                                            'get text 
     imageidx = tci.iImage                                          'image index 
  
     IF (tDIS.itemState = ODS_SELECTED) THEN
       crFillRct = tabbackcolor - 0x50                             'included for other tab options, change as needed 
       xTxt = tDIS.rcItem.left + tabPadding                         'add padding to center 
       yTxt = tDIS.rcItem.top + tabPadding                          ' 
       SetTextColor(tDIS.hDC,0x000000FF)                           'option for text fore color, change as needed 
       SetBkColor(tDIS.hDC,tabbackcolor - 0x50)                                'text background (same as tab bkgrnd) 
     ELSE                                                           'not if selected 
       crFillRct = tabbackcolor                                     'set normal tab color, change as needed 
       xTxt = tDIS.rcItem.left + tabPadding                         'add padding to center 
       yTxt = tDIS.rcItem.top + tabPadding                          ' 
       SetTextColor(tDIS.hDC,tabtextcolor)                         'option for text fore color - if needed 
       SetBkColor(tDIS.hDC,tabbackcolor)                           'text background (same as tab bkgrnd) 
     END IF                                                         ' 
  
     '--- fill the rectangle with the normal/or selected color 
     hFillBrush = CreateSolidBrush(crFillRct)
     FillRect(tDIS.hDC, &tDIS.rcItem, hFillBrush)
  
     TextOut(tDIS.hDC, xTxt,yTxt, sTxt$,LEN(sTxt$))                '--- add the tab text here -- 
  
   CASE WM_COMMAND
     SELECT CASE LOWORD(wParam)
     CASE 504                                                   'buttons 
       MSGBOX "Yup, a button alright!"
  
     CASE 506                                                   'Exit demo 
       IF HIWORD(wParam) = BN_CLICKED THEN
         SendMessage(hWnd,WM_CLOSE,0,0)
       END IF
     END SELECT
  
   CASE WM_SIZE
     IF hWnd = Form1 THEN
       'Skip if minimized, OS will handle it 
       IF wParam NOT = SIZE_MINIMIZED THEN
         CALL ReSizeForm1()
         UpdateAnchor(Tabb1)
         UpdateAnchor(Form1)
       END IF
     END IF
     '****** see ReSizeForm1() for the rest of sizing code *********** 
  
  
   CASE WM_CLOSE
     SetSystemCursor(LoadCursor(NULL,IDC_ARROW),OCR_NORMAL)
   END SELECT
 END EVENTS
  
 '**************** This section for drag/drop tab arrangements **************** 
 SUB MoveTabToNewLocation()
   'get the from - to tab page indices 
   LOCAL  iTab, iDrop AS LONG
   DIM HT AS TC_HITTESTINFO
   iTab = TabCtrl_GetCurSel(Tabb1)                                    'drag this tab 
   GetCursorPos(&HT.pt)
   ScreenToClient(Tabb1, &HT.pt)                                      'tab coordinates of mouse 
   iDrop = SendMessage(Tabb1, TCM_HITTEST, 0, &HT)                    'tab page under mouse at drop 
   IF iTab = iDrop OR iDrop < 0 THEN EXIT SUB                            'exit if not a valid drop 
   'reorder titles 
   MoveTabIdx(Tabb1, iTab, iDrop)
  
   REFRESH(Tabb1)
   TabCtrl_SetCurSel(Tabb1,iDrop)
   PRINT "Moved Tab " & STR$(iTab) & " to " & STR$(iDrop)
 END SUB
  
  
 SUB MoveTabIdx (thwnd AS HWND, idx AS INT, newidx AS INT)
   DIM  ptab AS HWND PTR
   DIM curtab AS HWND, curname$
   DIM cur, cnt AS INTEGER
   DIM tci AS TC_ITEM
   DIM tabnames[64,256] AS CHAR                 '256 bytes should be more than enough for a tab name 
   DIM imageidx[64]
  
   cnt = TabCtrl_GetItemCount(thwnd)-1
   IF (cnt < 0) OR(idx > cnt) THEN EXIT SUB
  
   ptab = (HWND*)(LONG_PTR)GetWindowLongPtr(thwnd,GWLP_USERDATA)
   FOR cur = 0 TO cnt                                       'get all the tab names/imageidx 
     tci.mask = TCIF_TEXT | TCIF_IMAGE
     tci.cchTextMax = 2048
     tci.pszText = tabnames$[cur]
     TabCtrl_GetItem(thwnd, cur, &tci)
     tabnames[cur] = tci.pszText
     imageidx[cur] = tci.iImage
   NEXT
  
   curtab = ptab[idx]                          'remove the idx tab NAME ONLY 
   curname$ = tabnames$[idx]
   FOR cur = idx TO cnt
     ptab[cur]=ptab[cur+1]
     tabnames$[cur] = tabnames$[cur+1]
   NEXT
   FOR cur = cnt TO newidx   STEP -1          'make room in array to insert NAME at newidx 
     ptab[cur]=ptab[cur-1]
     tabnames$[cur] = tabnames$[cur-1]
   NEXT
   ptab[newidx] = curtab                        'insert the tab at new position 
   tabnames$[newidx] = curname$
  
   FOR cur = 0 TO cnt                           'rewrite all the tabnames/imageidx to the tabs 
     tci.pszText = tabnames$[cur]
     tci.iImage  = imageidx[cur]
     TabCtrl_SetItem(thwnd, cur, &tci)
   NEXT
 END SUB
  
 '**************** This section for resizing of anchored controls **************** 
 SUB ReSizeForm1()
   'Resize the controls 
   'Anchor Options: 
   'AnchorLeft | AnchorRight | AnchorTop | AnchorBottom | AnchorHCenter | A1nchorVCenter 
  
   MoveAnchorControl(Tabb1,     AnchorLeft   | AnchorRight   | AnchorTop     | AnchorBottom)
   MoveAnchorControl(Button1,   AnchorLeft   | AnchorBottom)
   MoveAnchorControl(StatusBar1,AnchorLeft   | AnchorRight   | AnchorBottom)
  
   'Tabbed controls 
   MoveAnchorControl(Rich,      AnchorHCenter| AnchorVCenter)
   MoveAnchorControl(Listview,  AnchorLeft   | AnchorRight   | AnchorTop     | AnchorBottom)
   MoveAnchorControl(Stc1,      AnchorLeft   | AnchorHCenter | AnchorTop     | AnchorVCenter)
   MoveAnchorControl(Button2,   AnchorRight  | AnchorHCenter | AnchorBottom  | AnchorVCenter)
   MoveAnchorControl(Button3,   AnchorLeft   | AnchorHCenter | AnchorBottom  | AnchorVCenter)
   MoveAnchorControl(Button4,   AnchorLeft   | AnchorRight   | AnchorHCenter | AnchorBottom | AnchorVCenter)
   MoveAnchorControl(Button5,   AnchorLeft   | AnchorRight   | AnchorHCenter | AnchorBottom | AnchorVCenter)
   MoveAnchorControl(Button6,   AnchorLeft   | AnchorRight   | AnchorHCenter | AnchorBottom | AnchorVCenter)
   MoveAnchorControl(Button7,   AnchorRight  | AnchorHCenter | AnchorTop     | AnchorVCenter)
   MoveAnchorControl(Button8,   AnchorRight  | AnchorHCenter | AnchorTop     | AnchorBottom | AnchorVCenter)
   MoveAnchorControl(Button9,   AnchorLeft   | AnchorRight   | AnchorHCenter | AnchorTop    | AnchorBottom | AnchorVCenter)
   MoveAnchorControl(Stc2,      AnchorLeft   | AnchorHCenter |AnchorTop      | AnchorVCenter)
  
   'to stop flicker each control does not paint itself, so we must update the form here. 
   REFRESH(Form1)
 END SUB
  
  
 'ORIGINAL BY: IDC  May 2007 
 'FEB 2009: Mike Henning helped me rewrite this. 
 'Mike added InitAnchor & UpdateAnchor 
 'Thanks Mike 
  
 'Notes: the MoveAnchorControl function is only expected to be called through 
 ' the WM_SIZE event. 
 'To use MoveAnchorControl function you will need to call 
 'InitAnchor(myForm) for the form and for any sub form like 
 'a tab control in your FormLoad code. 
 'also see the Events loop: 
 'UpdateAnchor(Form1) needs to be called after each size event 
  
 'MoveAnchorControl Parameters 
 'hwnd          - Control handle 
 'anchor        - a combination of the Constants below 
 'Horizontal : AnchorLeft | AnchorRight | AnchorHCenter 
 'Vertical   : AnchorTop | AnchorBottom | AnchorVCenter 
  
 'AnchorLeft  will just left justify the ctrl 
 'AnchorRight will just right justify the ctrl 
 'AnchorLeft | AnchorRight will left justify the Left side of the ctrl and 
 'right justify the right side of the ctrl 
  
 'AnchorHCenter will justify toward the center proportionally to page size 
 'AnchorHCenter | AnchorLeft will left justify to the left and grow the width 
 'AnchorHCenter | AnchorRight will right justify to the right and grow the width 
 'AnchorHCenter | AnchorLeft | AnchorRight will scale the ctrls position and width 
 ' 
 ' Similar results for vertical sizes are obtained by using: 
 'AnchorTop AnchorBottom & AnchorVCenter parameters 
  
 'NOTES: AnchorLeft &  AnchorTop will NOT do anything by themselves 
 '      Make the original form the smallest size you want the user to use, 
 '      InitAnchor will stop controls sizing smaller than the original 
 '      IsSubForm - optional, use 2 if control parent is a Tab page. default = false 
  
 CONST AnchorLeft = 1
 CONST AnchorRight = 2
 CONST AnchorTop = 4
 CONST AnchorBottom = 8
 CONST AnchorHCenter = 16    'this is left/right 
 CONST AnchorVCenter = 32    'this is up/down 
  
 FUNCTION MoveAnchorControl OPTIONAL (HndlWnd AS HWND, anchor AS INTEGER, Use_Client= 0 AS INTEGER) AS RECT
   DIM RAW newRC AS RECT
   DIM RAW ctrlrc AS RECT
   DIM RAW prc AS RECT
   DIM RAW scalefactor AS DOUBLE
   DIM RAW hParent AS HWND
   DIM RAW pa AS LPANCHOR
   DIM nDPI
   hParent = GetParent(HndlWnd)
   prc = GetScaledRect(hParent)
  
   nDPI = GetDpiForSystem ()
   pa = (LPANCHOR)GetProp(hParent,(LPCSTR)"Anchor")
   IF NOT pa THEN FUNCTION = prc
   ctrlrc = GetScaledRect(HndlWnd)
  
   IF prc.right < pa->XMin THEN prc.right = pa->XMin
   IF prc.bottom < pa->YMin THEN prc.bottom = pa->YMin
  
   IF pa->IsSubForm THEN
     ctrlrc.left = MAX(0, ctrlrc.left - prc.left)
     ctrlrc.top = MAX(0, ctrlrc.top - prc.top)
   ELSE
     ctrlrc.left = MAX(0, ctrlrc.left - prc.left - (GetSystemMetricsForDpi(SM_CXSIZEFRAME, nDPI)+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, nDPI)))
     ctrlrc.top = MAX(0, ctrlrc.top - prc.top - GetSystemMetricsForDpi(SM_CYCAPTION, nDPI) - (GetSystemMetricsForDpi(SM_CYSIZEFRAME, nDPI)+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, nDPI)))
   END IF
   'This checks for a menu, and subtracts the Menu size if required 
   IF GetMenu(hParent) THEN
     ctrlrc.top = ctrlrc.top - (GetSystemMetricsForDpi(SM_CYMENUSIZE, nDPI)+1)
   END IF
  
   '**************************************** 
  
   newRC = ctrlrc
   scalefactor = CDBL(prc.right )/ CDBL(pa->PrevRC.right)
  
   SELECT CASE (anchor BAND(AnchorLeft + AnchorRight + AnchorHCenter))
     '-------------------- 
   CASE AnchorRight
     '-------------------- 
     newRC.left = prc.right - (pa->PrevRC.right - ctrlrc.left)
     '-------------------- 
   CASE AnchorLeft + AnchorRight
     '-------------------- 
     newRC.right = prc.right - (pa->PrevRC.right - ctrlrc.right)
     '-------------------- 
   CASE AnchorHCenter
     '-------------------- 
     newRC.left = ctrlrc.left - ((pa->PrevRC.right - prc.right)/2)
     '-------------------- 
   CASE AnchorRight + AnchorHCenter
     '-------------------- 
     newRC.right = CINT(CDBL(ctrlrc.right) * scalefactor)
     newRC.left = prc.right - (pa->PrevRC.right - ctrlrc.left)
     newRC.left = newRC.left + ctrlrc.right - newRC.right
     '-------------------- 
   CASE AnchorLeft + AnchorHCenter
     '-------------------- 
     newRC.right = CINT(CDBL(ctrlrc.right) * scalefactor)
     '-------------------- 
   CASE AnchorLeft + AnchorRight + AnchorHCenter
     '-------------------- 
     newRC.right = CINT(CDBL(ctrlrc.right) * scalefactor)
     newRC.left = CINT(CDBL(ctrlrc.left) * scalefactor)
   END SELECT
  
   scalefactor = CDBL(prc.bottom )/ CDBL(pa->PrevRC.bottom)
   SELECT CASE (anchor BAND(AnchorTop + AnchorBottom + AnchorVCenter))
     '-------------------- 
   CASE AnchorBottom
     '-------------------- 
     newRC.top = prc.bottom - (pa->PrevRC.bottom - ctrlrc.top)
     '-------------------- 
   CASE AnchorTop + AnchorBottom
     '-------------------- 
     newRC.bottom = prc.bottom - (pa->PrevRC.bottom - ctrlrc.bottom)
     '-------------------- 
   CASE AnchorVCenter
     '-------------------- 
     newRC.top = ctrlrc.top - ((pa->PrevRC.bottom - prc.bottom)/2)
     '-------------------- 
   CASE AnchorBottom + AnchorVCenter
     '-------------------- 
     newRC.bottom = CINT(CDBL(ctrlrc.bottom) * scalefactor)
     newRC.top = prc.bottom - (pa->PrevRC.bottom - ctrlrc.top)
     newRC.top = newRC.top + ctrlrc.bottom - newRC.bottom
     '-------------------- 
   CASE AnchorTop + AnchorVCenter
     '-------------------- 
     newRC.bottom = CINT(CDBL(ctrlrc.bottom ) * scalefactor)
     '-------------------- 
   CASE (AnchorTop + AnchorBottom + AnchorVCenter)
     '-------------------- 
     newRC.bottom = CINT(CDBL(ctrlrc.bottom) * scalefactor)
     newRC.top = CINT(CDBL(ctrlrc.top) * scalefactor)
  
   END SELECT
   'Move/resize the window using API 
   CALL MoveWindow(HndlWnd, newRC.left, newRC.top, newRC.right, newRC.bottom, 0)
   FUNCTION = newRC
 END FUNCTION
  
  
 'IsSubForm 0 for normal form, 2 for tabbed control 
 SUB InitAnchor OPTIONAL(HndlWnd AS HWND, IsSubForm=0, iXmin=0, iYmin=0)
   DIM RAW pa AS LPANCHOR
   DIM RAW tmphwnd AS HWND PTR
   DIM RAW i, cnt
  
   pa = (LPANCHOR)malloc(SIZEOF(*pa))
  
   IF IsSubForm THEN '= 2 THEN 
     tmphwnd =(HWND*)GetWindowLongPtr(HndlWnd, GWLP_USERDATA)
  
     pa->PrevRC = GetScaledRect(tmphwnd[0])
   ELSE
     pa->PrevRC = GetScaledRect(HndlWnd)
   END IF
  
   pa->XMin = pa->PrevRC.right
   pa->YMin = pa->PrevRC.bottom
   IF iXmin THEN pa->XMin = iXmin
   IF iYmin THEN pa->YMin = iYmin
   pa->IsSubForm = IsSubForm
  
   IF IsSubForm = 1 THEN
     SetProp(tmphwnd[i],"Anchor",(HANDLE)pa)
   ELSE IF IsSubForm = 2 THEN
     cnt = TabCtrl_GetItemCount(HndlWnd) -1
     FOR i = 0 TO cnt
       SetProp(tmphwnd[i],"Anchor",(HANDLE)pa)
     NEXT i
   END IF
   SetProp(HndlWnd,"Anchor",(HANDLE)pa)
 END SUB
  
  
 SUB UpdateAnchor (HndlWnd AS HWND)
   DIM RAW pa AS LPANCHOR
   DIM RAW tmphwnd AS HWND PTR
  
   pa = (LPANCHOR)GetProp(HndlWnd,(LPCSTR)"Anchor")
   IF pa THEN
     IF pa->IsSubForm = 2 THEN
       tmphwnd =(HWND*)GetWindowLongPtr(HndlWnd, GWLP_USERDATA)
       pa->PrevRC = GetScaledRect(tmphwnd[0])
     ELSE
       pa->PrevRC = GetScaledRect(HndlWnd)
     END IF
  
     IF pa->PrevRC.right < pa->XMin THEN pa->PrevRC.right = pa->XMin
     IF pa->PrevRC.bottom < pa->YMin THEN pa->PrevRC.bottom = pa->YMin
   END IF
 END SUB
  
  
 FUNCTION GetScaledRect(HndlWnd AS HWND) AS RECT
   DIM tmp3RC AS RECT
   GetWindowRect (HndlWnd, &tmp3RC)
   tmp3RC.right = (tmp3RC.right - tmp3RC.left)
   tmp3RC.bottom = (tmp3RC.bottom - tmp3RC.top)
   FUNCTION = tmp3RC
 END FUNCTION
  
 '******************** Load some rich text ********************************** 
 SUB LoadBuffer()
   SendMessage(Rich, EM_SETBKGNDCOLOR, 0, 0)
   DIM RAW Buffer$
   Buffer$=""
   Buffer$ = Buffer$ & "{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl"
   Buffer$ = Buffer$ & "{\f0\froman\fprq2\fcharset0 Times New Roman;}"
   Buffer$ = Buffer$ & "{\f1\froman\fprq2\fcharset0 Tahoma;}"
   Buffer$ = Buffer$ & "{\f2\fswiss\fprq2\fcharset0 Verdana;}}"
   Buffer$ = Buffer$ & "{\colortbl ;\red255\green255\blue0;"
   Buffer$ = Buffer$ & "\red0\green0\blue0;\red0\green255\blue255;"
   Buffer$ = Buffer$ & "\red128\green128\blue128;\red255\green0\blue0;"
   Buffer$ = Buffer$ & "\red0\green255\blue0;\red0\green0\blue255;"
   Buffer$ = Buffer$ & "\red255\green255\blue255;}"
   Buffer$ = Buffer$ & "\viewkind4\uc1\pard\qc\cf1\b\i\f0\"
   Buffer$ = Buffer$ & "fs72 BCX TAB\cf2\f1\par"
   Buffer$ = Buffer$ & "\cf3 Control\cf4\i0\f2\par"
   Buffer$ = Buffer$ & "\cf5\ul\b0 D\cf6 E\cf7 M\cf1 O\cf4\ulnone\par}"
  
   SETWINDOWRTFTEXT(Rich,Buffer$)
 END SUB