Announcement

Collapse
No announcement yet.

Tabs

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

  • Tabs

    I've been experimenting with the Peter Stephensen's DDTTab code, and
    I have a few questions:

    1) If I insert a MSGBOX in callback function for Tab 1 before the
    SELECT CASE statement, and then run the program, clicking on the
    button in Tab 1 does not generate a call to the Tab 1 callback.

    I tried integrating the DDTTab code into another program I'm working
    on and the callback functions for the tabs are never called. Even if
    I send a message to hTabDlg1 in an attempt to force a call. I am
    pulling my hair out trying to get the controls on the tabs to resize
    when the main window is resized.

    Is there something missing from the example or from my understanding?

    2) The TAB structure as I understand it:

    Code:
    hDlg     main/parent window
    hTab     tab control for hDlg
    hTabDlg1 child window to hTab
    hTabDlg2 ...
    In the main dialog callback for hDlg, is there any way to reference
    the hTabDlg1, 2, etc. without using GLOBAL handles?

    3) Should either the CONTROL SET SIZE hTab or MoveWindow hTab procedures
    generate a %WM_SIZE message for the hTabDlg1,2,etc.?

    ------------------
    Bernard Ertl
    Bernard Ertl
    InterPlan Systems

  • #2
    Bern --
    hTabDlgX should be child controls of MAIN window similar hTab.
    hTab simply informs main window that selected one of the tabs.
    Nothing more.
    In callback for main window you should resize ALL controls/forms.




    ------------------
    E-MAIL: [email protected]

    Comment


    • #3
      Semen,

      My declaration code looks something like:

      Code:
         DIALOG NEW 0, Title$, ,, 300, 200, %WS_POPUPWINDOW OR %WS_CAPTION OR _
                 %WS_MAXIMIZEBOX OR %WS_MINIMIZEBOX OR %WS_SIZEBOX OR %WS_MAXIMIZE TO hDlg&
         DIALOG GET SIZE hDlg& TO xSize&, ySize&
      
         ' Tab control
         hTab = TabCtrl(hDlg&, %IDC_TAB, 5, 20, xSize& - 20, ySize& - 50)
      
         ' Tab - dialog 1
         DIALOG NEW hTab, "Activities",,, 1000, 1000, %WS_CHILD OR %WS_VISIBLE  TO hTabDlg1
      In the callback for hDlg&, I can reference hTab via :

      Code:
      hTab = GetDlgItem( CBHNDL, %IDC_TAB)
      but the hTabDlg1,2,3,etc. do not have %IDs, so I don't see how to reference them
      (other than using GLOBALs for those handles, which I guess I am forced to do).
      Are you suggesting that the Tab 1 should be declared with hDlg& instead of hTab?:

      Code:
         ' Tab - dialog 1
         DIALOG NEW hDlg&, "Activities",,, 1000, 1000, %WS_CHILD OR %WS_VISIBLE  TO hTabDlg1
      I'm still puzzled by the callbacks for the hTabDlg1,2,3,etc DIALOGS. Why are they
      never called? How do you process messages for controls placed on the tabs?



      ------------------
      Bernard Ertl
      Bernard Ertl
      InterPlan Systems

      Comment


      • #4
        As Semen said, the parent of the child dialogs must be the main dialog, not the tab control. Therefore your "DIALOG NEW hTab" code should be changed to "DIALOG NEW hDlg".

        When a tab control is clicked, the notification is send to it's parent, not the callback for the tab page.

        The concept is simple: the tab control and the pages thus displayed in the tab control are actually separate entities - there is no direct communication between them... it is up to your code control the visibility of the tab page dialogs depending on the notification messages the parent callback receives.



        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          I dont' know how thorough this code is going to be, been a while since I did a Tabbed dialog box but this code works GREAT...


          It has it's flaws but they are very very minor, it uses a modeless dialog box on top of a modal dialog box..

          Thanks to Jim Hugeley for the help on this! (Anyone heard from Jim lately?)
          This code is v ery incomplete and the Dialog Proc will be cut short to limit the code posted (length).

          Please note that you do not process messages in the DialogProc for the individual controls, they are on modeless dialog boxes so you process them in the TabPageDialogProc

          Code:
          Function WinMain (ByVal hInstance     As Long, _
                            ByVal hPrevInstance As Long, _
                            lpCmdLine           As Asciiz Ptr, _
                            ByVal iCmdShow      As Long) As Long
          
          Local x            As Long
          Local t_Result      As Long 'Thread result
          Local lWidth        As Long
          Local lHeight       As Long
          Local lTop          As Long
          Local lLeft         As Long
          Local Margin        As Long
          Local lLoop         As Long
          Local hThread       As Long
          Local iItem         As Long
          Local sTmp          As String
          Local icc           As INIT_COMMON_CONTROLSEX
          Local tie           As TC_ITEM
          ReDim g_hDlgMisc(0 To 2) As Long
          '------------------------------------------------
          hInst = hInstance
          g_Result =  DefineDefaultSettings(hInst)
          If IsFalse g_Result Then Exit Function
          '------------------------------------------------
          
          'If IsFalse NagWare Then Exit Function
          g_hMenu = LoadMenu(hInst, "MAINMENU")
          pMenu = GetSubMenu(LoadMenu(hInst, "POPUPMENU"), 0)
          
          Dialog New 0, Mine + " " + Ver,%CW_USEDEFAULT,%CW_USEDEFAULT, 350,175, %WS_OVERLAPPEDWINDOW Or %WS_EX_CONTROLPARENT Or %WS_EX_RIGHT To hDlg
          'Dialog New 0,Mine + " " + Ver,,, 300,175, %WS_CAPTION Or %WS_SYSMENU  To hDlg
          'Order has been changed to keep the tab in sequence to the dialog box
          
          
          Dialog Get Size hDlg To lWidth, lHeight
          lWidth  = lWidth - 4
          lHeight = lHeight - 22  ' Make room for ok/cancel/apply buttons
          Margin = 1
          
          
          icc.dwICC = %ICC_TAB_CLASSES
          icc.dwSize = SizeOf(icc)
          InitCommonControlsEx icc
          
          '%HDLG_TABBUTTON = %WM_USER + 6  'g_hDlgMisc(lPage)
          '%HDLG_TAB      = %WM_USER + 7  'g_hDlgMisc(lPage)
              Control Add "SysTabControl32", hDlg, %HDLG_TAB, "", Margin,Margin, _
                          lWidth - Margin * 2, lHeight - 14 - Margin * 4, %WS_CHILD Or _
                          %WS_VISIBLE Or %WS_TABSTOP Or %TCS_TOOLTIPS Or _
                          %TCS_TABS Or %TCS_FIXEDWIDTH Or %TCS_FOCUSONBUTTONDOWN Or _
                          %WS_CLIPSIBLINGS Or %WS_CHILD, 0
          
              'Get hWnd of Tab Control
              Control Handle hDlg, %HDLG_TAB To hDlgTabCtl
          
              'Tab 0
              sTmp = "&General"
              tie.mask = %TCIF_TEXT Or %TCIF_IMAGE
              tie.iImage = -1
              tie.pszText = StrPtr( sTmp )
              iItem = 0
              g_Result = TabCtrl_InsertItem( hDlgTabCtl, iItem, tie)
              'Tab 1
              sTmp = "&Server"
              tie.mask = %TCIF_TEXT Or %TCIF_IMAGE
              tie.iImage = -1
              tie.pszText = StrPtr( sTmp )
              iItem = 1
              g_Result = TabCtrl_InsertItem( hDlgTabCtl, iItem, tie)
          
              'Tab 2
              sTmp = "Event &Log"
              tie.mask = %TCIF_TEXT Or %TCIF_IMAGE
              tie.iImage = -1
              tie.pszText = StrPtr( sTmp )
              iItem = 2
              g_Result = TabCtrl_InsertItem( hDlgTabCtl, iItem, tie)
          
          
              'Create modeless dialogs for the two tabs..
              Control Get Size hDlg, %HDLG_TAB To lWidth, lHeight
          
              'Allow for height of tab
              Margin = 2
              lTop = 12 + Margin
              lHeight = lHeight - 12 - ( Margin * 3 )
              lLeft = Margin
              lWidth = lWidth - ( Margin * 2 )
              Dialog New hDlg,"" , lLeft, lTop , lWidth, lHeight, _
                         %WS_CHILD Or %DS_CONTROL, 0 To g_hDlgMisc(0)
          
              'Create Second tab here
              Dialog New hDlg,"" , lLeft, lTop , lWidth, lHeight, _
                         %WS_CHILD Or %DS_CONTROL, 0 To g_hDlgMisc(1)
          
              'Create Thirds here
              Dialog New hDlg,"" , lLeft, lTop , lWidth, lHeight, _
                         %WS_CHILD Or %DS_CONTROL, 0 To g_hDlgMisc(2)
          
          
          lWidth  = lWidth - 4
          lHeight = lHeight - 22  ' Make room for ok/cancel/apply buttons
          
          
          Control Add "msctls_statusbar32", hDlg, %ID_STATUS,"" ,0 , 0 , 0, 16,%WS_CHILD Or %WS_BORDER Or %WS_VISIBLE Or %SBS_SIZEGRIP
          'Get handle of Status bar
          Control Handle oDlg, %ID_STATUS To g_hStatus
          
          For lLoop = 0 To 2
              Dialog Show Modeless g_hDlgMisc(lLoop) Call hDlgTabPageCallback
              Dialog Show State g_hDlgMisc(lLoop), %SW_HIDE
          Next
          
          Dialog Show State g_hDlgMisc(0), %SW_SHOW
          
          %ROW_DATA = 125
          Control Add Frame, g_hDlgMisc(1), %HDLG1_FRAME1,"Statistics",1,1,295,125
          Control Add Label, g_hDlgMisc(1), %HDLG1_LABEL1,"Current connections:",10,15,100,10
          Control Add Label, g_hDlgMisc(1), %HDLG1_LABEL2, "Total files received",10,25,100,10
          Control Add Label, g_hDlgMisc(1), %HDLG1_LABEL3, "Total bytes received",10,35,100,10
          
          
          Control Add Label, g_hDlgMisc(1), %HDLG1_STAT1,"0",%ROW_DATA,15,30,10,%ES_LEFT
          Control Add Label, g_hDlgMisc(1), %HDLG1_STAT2,"0",%ROW_DATA,25,25,10,%ES_LEFT
          Control Add Label, g_hDlgMisc(1), %HDLG1_STAT3,"0",%ROW_DATA,35,25,10,%ES_LEFT
          
          
          'Tab 2
          'Control Add TextBox, g_hDlgMisc(2),%HDLG2_TEXT1,ReadFileAsText(g_LogFile),5,5,lWidth - 5,lHeight + 10,%ES_MULTILINE Or %ES_AUTOVSCROLL,%WS_EX_STATICEDGE Or %WS_EX_LEFT
          Control Add TextBox, g_hDlgMisc(2),%HDLG2_TEXT1,"",5,5,lWidth - 5,lHeight + 10,%ES_MULTILINE Or %ES_AUTOVSCROLL,%WS_EX_STATICEDGE Or %WS_EX_LEFT
          
          Thread Create ThreadDialog(hDlg) To hThread
          ' Let the thread end when it stops
          Thread Close hThread To t_Result
          
          Dialog Send hDlg, %WM_SETICON, %ICON_BIG, hIcon
          Menu Attach g_hMenu, hDlg
          
          'Control Set Text g_hDlgMisc(2),%HDLG2_TEXT1,ReadFileAsText(g_LogFile) 'This line puts the log file from the file itself on the window
          'This has to go here because the log needs to be displayed first, then open for append
          If IsTrue g_LogEvents Then
             g_hLog = FreeFile
             Open g_LogFile For Append As #g_hLog 'For logging events
          End If
          Dialog Show Modal hDlg Call DialogProc
                  ' It is a MUST that you shut down the
                  ' modeless dialogs.. Other wise you are creating
                  ' a memory leak
          For lLoop = 0 To 2
              Dialog End g_hDlgMisc(lLoop)
          Next
          
          'Close FTP Socket if open
          If g_shSock > 0 Then ftpCloseServerPort
          Close #g_hLog 'CLose log file
          Erase g_ServerList
          Erase gSock
          Erase g_HDlgMisc
          Erase g_Statistics
          End Function  
          '
          '
          
          Callback Function DialogProc() as long 'CHOPPED TO AVOID LONG CODE ON BBS
              Case %WM_INITDIALOG
                  CenterWindow oDlg
                  'Tab 0
                  Control Set Check g_oDlgMisc(0), %IDCHECK1, UseCustomKey 
          End Function
          
          '
          '
          CallBack Function TabPageCallback() As Long
          Local wMsg   As Long
          Local wParam As Long
          Local lParam As Long
          Local lLoop  As Long
          Local sTmp   As String
          
          wMsg = CbMsg
          lParam = CbLparam
          wparam = CbWparam
          
            Select Case wMsg
              Case %WM_DESTROY
          
          
              Case %WM_COMMAND
                Select Case LoWrd(wParam)
          
                       Case %IDCHECK1
                            Control Enable oDlg, %IDAPPLY
                            Control Get Check g_oDlgMisc(0), %IDCHECK1 To UseCustomKey
                            If IsTrue UseCustomKey Then
                                Control Enable g_oDlgMisc(0), %IDTEXT4
                                Control Disable g_oDlgMisc(0), %IDSHOWKEY
                                Control Disable g_oDlgMisc(0), %IDTEXT3
                                Control Disable g_oDlgMisc(0), %IDLABEL3
                            Else
                                Control Enable g_oDlgMisc(0), %IDSHOWKEY
                                Control Set Text g_oDlgMisc(0), %IDTEXT4, ""
                                Control Disable g_oDlgMisc(0), %IDTEXT4
                                Control Enable g_oDlgMisc(0), %IDTEXT3
                                Control Enable g_oDlgMisc(0), %IDLABEL3
                            End If
          
          
                       Case %IDCHECK5
                            Control Enable oDlg, %IDAPPLY
                            Control Get Check  g_oDlgMisc(0), %IDCHECK5 To UsePassword
                            If IsFalse UsePassword Then
                               Control Disable g_oDlgMisc(0), %CHPASSWORD
                               Exit Function
                            Else
                               Control Enable g_oDlgMisc(0), %CHPASSWORD
                               If Len(Password) = 0 Then
                                  If IsTrue ChangePassword(hDlg,"Enter new password",PassWord) Then
                                    Control Enable oDlg, %IDAPPLY
                                    SetPassword
                                  End If
                               End If
                               Control Set Focus oDlg, %IDAPPLY
                            End If
                            Function = 1
                            Exit Function
          
                       Case %CHPASSWORD
                            Control Enable oDlg, %IDAPPLY
                            If IsTrue ChangePassword(hDlg,"Enter new password",PassWord) Then
                               SetPassword
                               Control Set Focus oDlg, %IDAPPLY
                               Function = 1
                               Exit Function
                            Else
                               MsgBox "Passwords don't match",%MB_ICONSTOP,CCS
                            End If
          
          
                      Case %ID2_CHANGE
                            Control Enable oDlg, %IDAPPLY
                            sTmp = BrowseForFolder(CbHndl,"Receive to this Directory",g_InFileDir)
                            If Len(sTmp) > 1 Then g_InFileDir = sTmp 'If they hit cancel don't change
                            Control Set Text CbHndl, %ID2_LABEL4,g_InFileDir
          
                      Case %IDTEXT3,%IDNOENCRYPT,%IDOPTION1,%IDOPTION2
                            Control Enable oDlg, %IDAPPLY
                      Case %ID2_TEXT1,%ID2_TEXT2
                            Control Enable oDlg, %IDAPPLY
                      Case %IDCHECK2,%IDCHECK3,%IDCHECK4,%ID2_SVRENABLE
                            Control Enable oDlg, %IDAPPLY
          
                End Select
            End Select
          End Function 
          
          '
          '
          Function ThreadDialog(ByVal hWnd As Long) As Long
          Local Rc As Long
          Do
              Dialog DoEvents
              Dialog Get Size hWnd To Rc,Rc
          Loop While Rc
          
          Function = 1
          End Function
          ------------------
          Scott
          Scott Turchin
          MCSE, MCP+I
          http://www.tngbbs.com
          ----------------------
          True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

          Comment


          • #6
            Lance,

            I experimented with changing the DIALOG NEW from hTab to hDlg and
            the only difference was that the hTabDlg1 window was relocated with
            respect the x,y of the hDlg window instead of the hTab control.
            Everything else worked the same.

            The problem I am encountering is not the displaying of the hTabDlg
            windows when clicking on the tabs. Peter's code works fine for that.
            The problem(s) are:

            1) How to reference the hTabDlg1,2,etc. DIALOGS from the hDlg callback
            without using GLOBALs in order to resize them (and the controls they contain)
            when hDlg is resized.

            2) How to communicate with controls which are placed on the
            hTabDlg1,2,etc. DIALOGS. In Peter's DDTTAB sample, there is a button
            control placed on hTabDlg1. Clicking that button does not generate
            a call (%BN_CLICKED message) to either hDlg's or hTabDlg1's callback
            functions.


            Scott,

            Thanks for the code sample. I'm off to play with it and see what happens...



            ------------------
            Bernard Ertl
            Bernard Ertl
            InterPlan Systems

            Comment


            • #7
              Well....

              The problem with the callbacks appears to be that the hTabDlg1,2,etc.
              DIALOGS are never associated with them. I tried adding:

              Code:
              '       SetWindowLong th.DlgHdr(i).hTabDlg, %DWL_DLGPROC, th.DlgHdr(i).lpfnCallback
              '       SetWindowLong th.DlgHdr(i).hTabDlg, %GWL_WNDPROC, th.DlgHdr(i).lpfnCallback
              to the InitTabControl function, but neither one worked.

              Then I tried adding:

              Code:
                 DIALOG SHOW MODELESS hTabDlg1, CALL cbTab1
                 DIALOG SHOW STATE hTabDlg1, %SW_HIDE
              after the DIALOG NEW hTabDlg1,2,3etc. statements and all of the
              sudden the callbacks are being called.

              Now I have a new set of questions:

              1) If hDlg is the parent window and hTab and hTabDlg1,2,3etc.
              are children to it, does DIALOG END hDlg automatically END the
              hTabDlg1,2,3,etc. DIALOGS, or do I need to explicitly END them in
              hDlg's WM_DESTROY event?

              2) What is the purpose of the lpfnCallback field in the DLGHDR
              type declaration of the DDTTAB code? This is what really threw
              me I guess. I was thinking that the tab initialization code was
              assigning the callbacks to the dialogs.



              ------------------
              Bernard Ertl
              Bernard Ertl
              InterPlan Systems

              Comment


              • #8
                I've not seen the code you are referring, but you should ensure the main dialog should include the extended style %WS_EX_CONTROLPARENT, and the modeless child "page" dialogs should use the %DS_CONTROL style. This is why the "page" dialogs should not be children of the tab control. If you make the tab control the parent of the tab pages, you'll find that the keyboard tab control won't seamlessly integrate the tab and the visible page on the dialog.

                You should not need to use DIALOG END on the child dialogs.

                Each dialog "page" needs a callback function if you wish to receive notification messages from it's controls.

                You can share a single dialog callback for all of the pages (and even the parent dialog if you so choose), but you'll have to add extra code in your message handlers to ensure that your code is aware of which control/dialog originated the message.



                ------------------
                Lance
                PowerBASIC Support
                mailto:[email protected][email protected]</A>
                Lance
                mailto:[email protected]

                Comment


                • #9
                  Whoops! I thought that Peter's DDTTAB was available in your FILEs
                  section. I just checked and couldn't find it. I know I d/l'd or cut
                  & pasted it from this site. It's not too large, so I'm including it
                  below since I asked so many questions about it.

                  Lance,

                  Thanks for the info. Looks like the example left out a little bit.

                  Just to clarify for me (don't want memory leaks):

                  If I add DIALOG SHOW MODELESS hTabDlg1,2,3etc. (with individual callbacks)
                  for each child DIALOG, and then have a DIALOG SHOW MODELESS for the hDlg
                  parent, I only need concern myself with the closing the hDlg parent and
                  the hDlgTab1,2,3etc. child dialogs will be closed automatically?

                  Here's Peter's code (which I got somehwere from this forum/files area),
                  my comments added with '// :


                  DDTTAB.INC

                  Code:
                  '------- TabDDT.inc ---------------
                  '----------------------------------
                  ' DDT Tab Control
                  ' Peter Stephensen 2000
                  '----------------------------------
                  #IF NOT %DEF(%TAB_DLGMAX)
                      %TAB_DLGMAX = 10                ' Maximal number of tab items
                  #ENDIF
                  
                  #IF NOT %DEF(%TAB_LINES)
                      %TAB_LINES = 2                  ' Number of lines in Tab control. Set this to 2
                  #ENDIF                              ' if multiline-style is used
                  
                  TYPE DLGHDR
                      hTabDlg AS LONG
                      lpfnCallback AS LONG '// what is this for? It's never used
                  END TYPE
                  
                  TYPE TABHDR
                      lID AS LONG                     ' Integer ID for Tab Control
                      cDialogs AS LONG                ' Number of dialogs
                      DlgHdr(%TAB_DLGMAX) AS DLGHDR   ' Dialogs
                  END TYPE
                  
                  DECLARE SUB TabDisplay(hDlg AS LONG,TabID AS LONG,newTab AS LONG)
                  
                  GLOBAL pth AS TABHDR PTR
                  
                  FUNCTION TabCtrl(BYVAL hDlg AS LONG, BYVAL ID AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL xx AS LONG, BYVAL yy AS LONG) AS LONG
                  
                      LOCAL hTab AS LONG
                  
                      IF hDlg = 0 THEN EXIT FUNCTION
                      CONTROL ADD "SysTabControl32", hDlg, ID, "", x, y, xx, yy, %WS_CHILD OR %WS_VISIBLE
                      CONTROL HANDLE hDlg, ID TO hTab
                  
                      FUNCTION = hTab
                  
                  END FUNCTION
                  
                  FUNCTION InitTabControl(hDlg AS LONG, th AS TABHDR) AS LONG
                  
                      LOCAL tie AS TC_ITEM
                      LOCAL rcTab AS RECT
                      LOCAL i AS LONG
                      LOCAL hInst AS LONG
                      LOCAL hWndTab AS LONG
                      LOCAL zBuffer AS ASCIIZ*128
                  
                      InitCommonControls
                  
                      pth = LocalAlloc(%LPTR, SIZEOF(@pth))
                  
                      hInst = GetModuleHandle(BYVAL 0)
                      hWndTab = GetDlgItem(hDlg,th.lID)
                  
                      GetClientRect hwndTab,rcTab
                  
                      ' Add a tab for each of the child dialog boxes.
                      FOR i = 0 TO th.cDialogs-1
                          tie.mask = %TCIF_TEXT OR %TCIF_IMAGE
                          tie.iImage = -1
                          GetWindowText th.DlgHdr(i).hTabDlg, zBuffer, 128
                          tie.pszText = VARPTR(zBuffer)
                          TabCtrl_InsertItem hwndTab, i, tie
                  
                          MoveWindow th.DlgHdr(i).hTabDlg, _
                                     4, _
                                     %TAB_LINES*23, _
                                     rcTab.nRight-rcTab.nLeft-11, _
                                     rcTab.nBottom-rcTab.nTop-%TAB_LINES*23-3, _
                                     %TRUE
                  '// Tried to add a callback without using DIALOG SHOW MODE[LESS] statement.
                  '// Did not work...
                  '//        SetWindowLong th.DlgHdr(i).hTabDlg, %DWL_DLGPROC, th.DlgHdr(i).lpfnCallback
                  '//        SetWindowLong th.DlgHdr(i).hTabDlg, %GWL_WNDPROC, th.DlgHdr(i).lpfnCallback
                      NEXT i
                  
                      @pth = th
                      TabDisplay hDlg, th.lID, 0
                  
                  END FUNCTION
                  
                  SUB TabDisplay(hDlg AS LONG,TabID AS LONG, TabIndex AS LONG)
                  
                      STATIC PrevTabIndex AS LONG
                      LOCAL i AS LONG
                  
                      IF PrevTabIndex THEN
                          ShowWindow PrevTabIndex, %SW_HIDE
                      END IF
                  
                      IF pth = 0 THEN EXIT SUB
                  
                      ShowWindow @pth.DlgHdr(TabIndex).hTabDlg, %SW_SHOW
                      PrevTabIndex = @pth.DlgHdr(TabIndex).hTabDlg
                  
                  END SUB
                  
                  SUB OnTabNotify (BYVAL hDlg AS LONG, BYVAL lParam AS LONG )
                  
                      LOCAL lpNmh   AS NMHDR PTR
                  
                      IF pth = 0 THEN EXIT SUB
                  
                      lpNmh = lParam
                      SELECT CASE @lpNmh.Code
                      CASE %TCN_LAST TO %TCN_FIRST
                          SELECT CASE @lpNmh.idFrom
                          CASE @pth.lID
                              SELECT CASE @lpNmh.Code
                              CASE %TCN_SELCHANGE
                                  TabDisplay hDlg, @pth.lID, TabCtrl_GetCurSel(GetDlgItem(hDlg,@pth.lID))
                              END SELECT
                          END SELECT
                      END SELECT
                  
                  END SUB
                  and DDTTAB.BAS

                  Code:
                  '-----TabEx.bas----
                  #COMPILE EXE
                  #INCLUDE "commctrl.inc"
                  #INCLUDE "DDTtab.inc"
                  
                  %IDC_TAB = 1000
                  
                  DECLARE CALLBACK FUNCTION MainDlgProc
                  
                  FUNCTION PBMAIN
                  
                      LOCAL th AS TABHDR
                      LOCAL hDlg AS LONG
                      LOCAL hTab AS LONG
                      LOCAL hTabDlg1 AS LONG
                      LOCAL hTabDlg2 AS LONG
                  
                      ' Main dialog
                      DIALOG NEW 0, "DDT - Tab Example",,,400, 300, %WS_SYSMENU OR %WS_MINIMIZEBOX OR %DS_CENTER TO hDlg
                  
                      ' Tab control
                      hTab = TabCtrl(hDlg, %IDC_TAB, 20, 20, 300, 200)
                  
                      ' Tab - dialog 1
                  '// Peter's code assign's the tabbed DIALOGS to hTab
                  '// Advice from guru's is to change to hDlg
                      DIALOG NEW hTab, "Tab nr. 1",,,400, 300, %WS_CHILD OR %WS_VISIBLE  TO hTabDlg1
                      CONTROL ADD LABEL, hTabDlg1, -1, "This is Tab 1", 5,5,50,14
                      CONTROL ADD BUTTON, hTabDlg1, 100, "davs1",30,30, 40,15
                  
                      ' Tab - dialog 2
                      DIALOG NEW hTab, "Tab nr. 2",,,400, 300, %WS_CHILD OR %WS_VISIBLE  TO hTabDlg2
                      CONTROL ADD LABEL, hTabDlg2, -1, "This is Tab 2", 5,5,50,14
                  
                      th.lID = %IDC_TAB
                      th.cDialogs = 2
                  
                      th.DlgHdr(0).hTabDlg       = hTabDlg1
                      th.DlgHdr(0).lpfnCallback = CODEPTR(cbTab1)
                  '// Again, this threw me.  The CODEPTR is never used...
                  
                      th.DlgHdr(1).hTabDlg       = hTabDlg2
                      th.DlgHdr(1).lpfnCallback  = CODEPTR(cbTab2)
                  
                      InitTabControl hDlg, th
                      DIALOG SHOW MODAL hDlg CALL MainDlgProc
                  
                  END FUNCTION
                  
                  CALLBACK FUNCTION MainDlgProc
                  
                      SELECT CASE CBMSG
                          CASE %WM_INITDIALOG
                          CASE %WM_NOTIFY
                              OnTabNotify CBHNDL, CBLPARAM
                  
                          CASE %WM_COMMAND
                              SELECT CASE LOWRD(CBWPARAM)
                              END SELECT
                    END SELECT
                  
                  END FUNCTION
                  
                  CALLBACK FUNCTION cbTab1
                  
                  '// Added MSGBOX for testing.  cbTab1 never called by Peter's orig. code
                  '// MSGBOX "tab 1"
                  
                      SELECT CASE CBMSG
                          CASE %WM_INITDIALOG
                          CASE %WM_COMMAND
                              SELECT CASE LOWRD(CBWPARAM)
                              END SELECT
                    END SELECT
                  
                  END FUNCTION
                  
                  CALLBACK FUNCTION cbTab2
                  
                    SELECT CASE CBMSG
                           CASE %WM_INITDIALOG
                           CASE %WM_COMMAND
                                SELECT CASE LOWRD(CBWPARAM)
                                END SELECT
                    END SELECT
                  
                  END FUNCTION
                  '------ END OF TabEx.bas -------
                  ------------------
                  Bernard Ertl
                  Bernard Ertl
                  InterPlan Systems

                  Comment


                  • #10
                    bern --
                    i added some statements to my code, posted in http://www.powerbasic.com/support/pb...ead.php?t=2268

                    probably, it will be more clear for you.

                    Code:
                       #compile exe
                       #register none
                       #dim all
                       #include "commctrl.inc"
                    
                       %id_tab = 1001
                    
                       callback function tabproc1
                          select case cbmsg
                             case %wm_initdialog
                                control add frame, cbhndl, -1, " tab 1 ", 0, 0, 255, 140
                                control add textbox, cbhndl, 101, "textbox #1", 10, 20, 235, 80, _
                                   %es_multiline or %es_wantreturn or %ws_tabstop, %ws_ex_clientedge
                                control add button, cbhndl, 102, "if you are very brave, push me", 20, 110, 215, 15
                             case %wm_command
                                if cbctl = 102 then msgbox "tab 1"
                          end select
                       end function
                       callback function tabproc2
                          select case cbmsg
                             case %wm_initdialog
                                control add frame, cbhndl, -1, " tab 2 ", 0, 0, 255, 140
                                control add textbox, cbhndl, 101, "textbox #2", 10, 20, 235, 80, _
                                   %es_multiline or %es_wantreturn or %ws_tabstop, %ws_ex_clientedge
                                control add button, cbhndl, 102, "if you are not very brave, push me anyway", 20, 110, 215, 15
                             case %wm_command
                                if cbctl = 102 then msgbox "tab 2"
                             end select
                       end function
                       
                       callback function tabproc3
                          select case cbmsg
                             case %wm_initdialog
                                control add frame, cbhndl, -1, " tab 1 ", 0, 0, 255, 140
                                control add textbox, cbhndl, 101, "textbox #3", 10, 20, 235, 80, _
                                   %es_multiline or %es_wantreturn or %ws_tabstop, %ws_ex_clientedge
                                control add button, cbhndl, 102, "better not to push me", 20, 110, 215, 15
                             case %wm_command
                                if cbctl = 102 then msgbox "tab 3"
                          end select
                       end function
                    
                       callback function maindlgproc
                          static lastidx as long, hwndtab() as long
                          local tie as tc_item, i as long, caption as string
                          %ntabch = 3
                          select case cbmsg
                             case %wm_initdialog
                                control add "systabcontrol32", cbhndl, %id_tab, ", 10, 10, 280, 180, %ws_child or %ws_tabstop or %ws_visible
                                control add button, cbhndl, %idok, "accept", 40, 200, 100, 15
                                control add button, cbhndl, %idcancel, "cancel", 150, 200, 100, 15
                                redim hwndtab(1 to %ntabch)
                                for i = 1 to %ntabch
                                   dialog new cbhndl, ", 20, 35, 255, 140, %ds_control or %ws_child to hwndtab(i)
                                   select case i
                                      case 1
                                         dialog show modeless hwndtab(i) call tabproc1: caption = " one "
                                      case 2
                                         dialog show modeless hwndtab(i) call tabproc2: caption = " two "
                                      case 3
                                         dialog show modeless hwndtab(i) call tabproc3: caption = " three "
                                   end select
                                   if i = 1 then showwindow hwndtab(i), %sw_show else _
                                      showwindow hwndtab(i), %sw_hide
                                   tie.mask = %tcif_text or %tcif_image
                                   tie.iimage = -1
                                   tie.psztext = strptr(caption)
                                   tabctrl_insertitem getdlgitem(cbhndl, %id_tab), i, tie
                                next
                                setfocus getdlgitem(cbhndl, %id_tab)
                             case %wm_notify
                                local lpnmh as nmhdr ptr
                                lpnmh = cblparam
                                select case @lpnmh.code
                                   case %tcn_last to %tcn_first
                                      select case @lpnmh.idfrom
                                         case %id_tab
                                           select case @lpnmh.code
                                              case %tcn_selchange
                                                 i = tabctrl_getcursel(getdlgitem(cbhndl,%id_tab))
                                                 showwindow hwndtab(lastidx + 1), %sw_hide
                                                 lastidx = i: showwindow hwndtab(lastidx + 1), %sw_show
                                           end select
                                   end select
                                end select
                          end select
                       end function
                       function pbmain
                          local hdlg as long
                          initcommoncontrols
                          dialog new 0, "ddt - tab example",,, 300, 225, _
                             %ws_minimizebox or %ws_caption or %ws_sysmenu, %ws_ex_controlparent to hdlg
                          dialog show modal hdlg call maindlgproc
                       end function
                    ------------------
                    e-mail: [email protected]

                    Comment


                    • #11
                      Thanks Semen. Your code looks like it is simpler than the sample
                      I've been working with. I'm off to play with it.



                      ------------------
                      Bernard Ertl
                      Bernard Ertl
                      InterPlan Systems

                      Comment


                      • #12
                        Semen, I've been playing with your code and I modified it
                        to experiment with resizing. However, there is quite a bit of
                        flicker when grabbing the bottom right corner and moving it
                        around.

                        Is there any easy way (or hard way?) to reduce or eliminate the
                        flicker?

                        Thanks again for your help.

                        Code:
                           #COMPILE EXE
                           #REGISTER NONE
                           #DIM ALL
                           #INCLUDE "commctrl.inc"
                        
                        
                           %ID_TAB = 1001
                        
                        
                           CALLBACK FUNCTION TabProc1
                              LOCAL x&, y&         '// BE
                              SELECT CASE CBMSG
                                 CASE %WM_INITDIALOG
                        '// BE - Commented out original FRAME.  Modified below
                        '// BE - to have ID for resizing
                        '            CONTROL ADD FRAME, CBHNDL, -1, " Tab 1 ", 0, 0, 255, 140
                                    CONTROL ADD FRAME, CBHNDL, 100, " Tab 1 ", 0, 0, 255, 140
                                    CONTROL ADD TEXTBOX, CBHNDL, 101, "Textbox #1", 10, 20, 235, 80, _
                                       %ES_MULTILINE OR %ES_WANTRETURN OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
                        '// BE - Commented out for resizing.  Add a toolbar
                        '// BE - if buttons needed....
                        '            CONTROL ADD BUTTON, CBHNDL, 102, "If you are very brave, push me", 20, 110, 215, 15
                                 CASE %WM_SIZE                                          '// BE - Tab window is being resized
                                    DIALOG GET SIZE CBHNDL TO x&, y&                    '// BE - Get new dimensions
                                    CONTROL SET SIZE CBHNDL, 100, x&, y&                '// BE - Resize FRAME control
                                    CONTROL SET SIZE CBHNDL, 101, x& - 20, y& - 60      '// BE - Resize TEXTBOX control
                        '// BE - no button to trap...
                        '         CASE %WM_COMMAND
                        '            IF CBCTL = 102 THEN MSGBOX "Tab 1"
                              END SELECT
                           END FUNCTION
                        
                        
                           CALLBACK FUNCTION TabProc2
                              LOCAL x&, y&         '// BE
                              SELECT CASE CBMSG
                                 CASE %WM_INITDIALOG
                        '// BE - Commented out original FRAME.  Modified below
                        '// BE - to have ID for resizing
                        '            CONTROL ADD FRAME, CBHNDL, -1, " Tab 2 ", 0, 0, 255, 140
                                    CONTROL ADD FRAME, CBHNDL, 100, " Tab 2 ", 0, 0, 255, 140
                                    CONTROL ADD TEXTBOX, CBHNDL, 101, "Textbox #2", 10, 20, 235, 80, _
                                       %ES_MULTILINE OR %ES_WANTRETURN OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
                        '// BE - Commented out for resizing.  Add a toolbar
                        '// BE - if buttons needed....
                        '            CONTROL ADD BUTTON, CBHNDL, 102, "If you are not very brave, push me anyway", 20, 110, 215, 15
                                 CASE %WM_SIZE                                          '// BE - Tab window is being resized
                                    DIALOG GET SIZE CBHNDL TO x&, y&                    '// BE - Get new dimensions
                                    CONTROL SET SIZE CBHNDL, 100, x&, y&                '// BE - Resize FRAME control
                                    CONTROL SET SIZE CBHNDL, 101, x& - 20, y& - 60      '// BE - Resize TEXTBOX control
                        '// BE - no button to trap...
                        '         CASE %WM_COMMAND
                        '            IF CBCTL = 102 THEN MSGBOX "Tab 2"
                                 END SELECT
                           END FUNCTION
                        
                        
                           CALLBACK FUNCTION TabProc3
                              LOCAL x&, y&         '// BE
                              SELECT CASE CBMSG
                                 CASE %WM_INITDIALOG
                        '// BE - Commented out original FRAME.  Modified below
                        '// BE - to have ID for resizing
                        '            CONTROL ADD FRAME, CBHNDL, -1, " Tab 1 ", 0, 0, 255, 140
                                    CONTROL ADD FRAME, CBHNDL, 100, " Tab 3 ", 0, 0, 255, 140
                                    CONTROL ADD TEXTBOX, CBHNDL, 101, "Textbox #3", 10, 20, 235, 80, _
                                       %ES_MULTILINE OR %ES_WANTRETURN OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
                        '// BE - Commented out for resizing.  Add a toolbar
                        '// BE - if buttons needed....
                        '            CONTROL ADD BUTTON, CBHNDL, 102, "Better not to push me", 20, 110, 215, 15
                                 CASE %WM_SIZE                                          '// BE - Tab window is being resized
                                    DIALOG GET SIZE CBHNDL TO x&, y&                    '// BE - Get new dimensions
                                    CONTROL SET SIZE CBHNDL, 100, x&, y&                '// BE - Resize FRAME control
                                    CONTROL SET SIZE CBHNDL, 101, x& - 20, y& - 60      '// BE - Resize TEXTBOX control
                        '// BE - no button to trap...
                        '         CASE %WM_COMMAND
                        '            IF CBCTL = 102 THEN MSGBOX "Tab 3"
                              END SELECT
                           END FUNCTION
                        
                        
                           CALLBACK FUNCTION MainDlgProc
                              STATIC LastIdx AS LONG, hWndTab() AS LONG
                              LOCAL tie AS TC_ITEM, i AS LONG, Caption AS STRING
                              LOCAL x&, y&   '// BE
                              %nTabCh = 3
                              SELECT CASE CBMSG
                                 CASE %WM_INITDIALOG
                                    CONTROL ADD "SysTabControl32", CBHNDL, %ID_TAB, "", 10, 10, 280, 180, %WS_CHILD OR %WS_TABSTOP OR %WS_VISIBLE
                        '// BE - commented out following buttons.  I would put them
                        '// BE - in a toolbar for a resizable DIALOG
                        '            CONTROL ADD BUTTON, CBHNDL, %IDOK, "Accept", 40, 200, 100, 15
                        '            CONTROL ADD BUTTON, CBHNDL, %IDCANCEL, "Cancel", 150, 200, 100, 15
                                    REDIM hWndTab(1 TO %nTabCh)
                                    FOR i = 1 TO %nTabCh
                                       DIALOG NEW CBHNDL, "", 20, 35, 255, 140, %DS_CONTROL OR %WS_CHILD TO hWndTab(i)
                                       SELECT CASE i
                                          CASE 1
                                             DIALOG SHOW MODELESS hWndTab(i) CALL TabProc1: Caption = " One "
                                          CASE 2
                                             DIALOG SHOW MODELESS hWndTab(i) CALL TabProc2: Caption = " Two "
                                          CASE 3
                                             DIALOG SHOW MODELESS hWndTab(i) CALL TabProc3: Caption = " Three "
                                       END SELECT
                                       IF i = 1 THEN ShowWindow hWndTab(i), %SW_SHOW ELSE _
                                          ShowWindow hWndTab(i), %SW_HIDE
                                       tie.mask = %TCIF_TEXT OR %TCIF_IMAGE
                                       tie.iImage = -1
                                       tie.pszText = STRPTR(Caption)
                                       TabCtrl_InsertItem GetDlgItem(CBHNDL, %ID_TAB), i, tie
                                    NEXT
                                    SetFocus GetDlgItem(CBHNDL, %ID_TAB)
                                 CASE %WM_SIZE                                          '// BE - Parent window is being resized
                                    DIALOG GET SIZE CBHNDL TO x&, y&                    '// BE - Get new dimensions
                                    CONTROL SET SIZE CBHNDL, %ID_TAB, x& - 20, y& - 45  '// BE - Resize tab control
                                    
                                    FOR i = 1 TO %nTabCh                                '// BE - For every tab,
                                       DIALOG SET SIZE hWndTab(i), x& - 45, y& - 85     '// BE - Resize corresponding DIALOG
                                    NEXT                                                '// BE
                                 CASE %WM_NOTIFY
                                    LOCAL lpNmh AS NMHDR PTR
                                    lpNmh = CBLPARAM
                                    SELECT CASE @lpNmh.Code
                                       CASE %TCN_LAST TO %TCN_FIRST
                                          SELECT CASE @lpNmh.idFrom
                                             CASE %ID_TAB
                                               SELECT CASE @lpNmh.Code
                                                  CASE %TCN_SELCHANGE
                                                     i = TabCtrl_GetCurSel(GetDlgItem(CBHNDL,%ID_TAB))
                                                     ShowWindow hWndTab(LastIdx + 1), %SW_HIDE
                                                     LastIdx = i: ShowWindow hWndTab(LastIdx + 1), %SW_SHOW
                                               END SELECT
                                       END SELECT
                                    END SELECT
                              END SELECT
                           END FUNCTION
                        
                        
                           FUNCTION PBMAIN
                              LOCAL hDlg AS LONG
                              InitCommonControls
                        '// BE - commented out original DIALOG CALL.  Modifed it below to
                        '// BE - be resizable (with %WS_SIZEBOX and %WS_MAXIMIZEBOX).
                        '// BE - I also added %WS_CLIPCHILDREN to try to reduce flicker on resizing,
                        '// BE - but it does not appear to change anything.
                        '      DIALOG NEW 0, "DDT - Tab Example",,, 300, 225, _
                        '         %WS_MINIMIZEBOX OR %WS_CAPTION OR %WS_SYSMENU, %WS_EX_CONTROLPARENT TO hDlg
                              DIALOG NEW 0, "DDT - Tab Example",,, 300, 225, _
                                 %WS_SIZEBOX OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CAPTION OR _
                                 %WS_SYSMENU OR %WS_CLIPCHILDREN, %WS_EX_CONTROLPARENT TO hDlg
                              DIALOG SHOW MODAL hDlg CALL MainDlgProc
                           END FUNCTION

                        ------------------
                        Bernard Ertl
                        Bernard Ertl
                        InterPlan Systems

                        Comment


                        • #13
                          Easiest solution - to change Case %WM_SIZE in main DlgProc to
                          Case %WM_EXITSIZEMOVE

                          ------------------
                          E-MAIL: [email protected]

                          Comment


                          • #14
                            OK. Semen, thanks.

                            %WM_EXITSIZEMOVE caused the resizing to wait until the mouse button
                            was released. Stopped the flickering alright. But I was hoping
                            to have the controls resize along with the main window.

                            Is it possible that the flickering is due to the painting of the
                            background for the tab control itself? Any way to make the tab
                            control just show the tabs and border without painting a fill inside
                            the borders (or does it already work that way?)?



                            ------------------
                            Bernard Ertl
                            Bernard Ertl
                            InterPlan Systems

                            Comment


                            • #15
                              I like that %WM_EXITSIZEMOVE, I may just use that from now on....


                              Thanks,

                              Scott


                              ------------------
                              Scott
                              Scott Turchin
                              MCSE, MCP+I
                              http://www.tngbbs.com
                              ----------------------
                              True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                              Comment


                              • #16
                                Bern --
                                I don't know general decision.
                                If you design own custom control, you can prevent flickering by using memory hDC.

                                Like rule, flickering is linked with WM_ERASEBKGND (gray <-> white).
                                In custom controls I ignore this event and redraw all in WM_PAINT.

                                In case of textbox similar technic doesn't give correct results.
                                Particually you can reduce flickering by following way.
                                (instead of WM_SIZE) in MainDlgProc
                                Code:
                                  Case %WM_ENTERSIZEMOVE
                                     Dim fh As Static Long
                                     fh = 1
                                  Case %WM_SIZE                                          '// BE - Parent window is being resized
                                     Dialog Get Size CbHndl To x&, y&                    '// BE - Get new dimensions
                                     Control Set Size CbHndl, %ID_TAB, x& - 20, y& - 45  '// BE - Resize tab control
                                     For i = 1 To %nTabCh                                '// BE - For every tab,
                                        Dialog Set Size hWndTab(i), x& - 45, y& - 85     '// BE - Resize corresponding DIALOG
                                        Dim rc As RECT, hw As Long
                                        If fh And (i = LastIdx + 1) Then
                                           hW = GetDlgItem(hWndTab(i), 101) ' Textbox
                                           GetClientRect hW, rc
                                           ValidateRect hW, rc
                                        End If
                                     Next                                                             '// BE
                                        
                                  Case %WM_EXITSIZEMOVE
                                     If fh Then
                                        InvalidateRect hWndTab(LastIdx + 1), ByVal 0, 1
                                        UpdateWindow hWndTab(LastIdx + 1)
                                     End If
                                     fh = 0
                                ------------------
                                E-MAIL: [email protected]

                                Comment


                                • #17
                                  Thanks Semen. You've been a tremendous help.

                                  I am not in a position to write my own custom control or use the
                                  technique you just posted (which was very interesting). I'm using
                                  a third party grid control on my tabs.

                                  I guess I'm going to live with the flicker.



                                  ------------------
                                  Bernard Ertl
                                  Bernard Ertl
                                  InterPlan Systems

                                  Comment

                                  Working...
                                  X