Author |
Topic: Tabs (Read 877 times) |
|
KenDown
Full Member
member is offline


Posts: 181
|
 |
Tabs
« Thread started on: Nov 14th, 2016, 8:44pm » |
|
Hmmmm.
I'm writing a program using tabs (as per the Wiki article http://bb4w.wikispaces.com/Creating+a+tab+control) and it's all working nicely. I click on the different tabs and the right things display on screen.
Now, however, I want to change tabs under control of the program, so that when I click on something in one tab, that tab hides and another tab displays. I can do it easily with
SYS"ShowWindow",!dlg%(3),0 SYS"ShowWindow",!dlg%(0),5
but the second tab is not selected or highlighted or whatever you want to call it. If I click on a third tab, it appears overwritten by dlg%(0), which is not at all nice!
Anyone with any ideas how I can force the second tab to be selected and the first one deselected? I've tried mucking around with the variables currsel% and prevsel% to no avail.
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Tabs
« Reply #1 on: Nov 15th, 2016, 11:56am » |
|
The short answer is no, I don't know...
There is a PROCSetFocus in winlib5A, which you presumably already have loaded. Does that help?
D
|
|
Logged
|
|
|
|
Zaphod
Guest
|
 |
Re: Tabs
« Reply #2 on: Nov 15th, 2016, 2:48pm » |
|
So each tab has a dialog on it. When changing tabs you close that dialog and open the other, something like this: Code: REM Change to selected tab
IF CurTab% > -1 PROC_closedialog(Dlg%(CurTab%)) :REM Close old Tab dialog
PROC_showdialog(Dlg%(TabID%)) :REM Open new Tab dialog
CurTab% = TabID% :REM update current pointer
Then the newly opened dialog default control will have focus. I think that is what you are asking.
I also found a problem when minimizing the program and restoring it in that the current tab controls are not repainted, no idea why. I solved this by putting some code in the main loop to detect this situation and reinitialize the current dialog.
Code: REM This block is to fix a peculiarity where the current tab dialog does not repaint after being minimized.
SYS"IsIconic", @hwnd% TO L% :REM L% non-zero when minimized
IF L% THEN
Min%=TRUE :REM Window has been minimized
ELSE :REM Window is not minimized now.
IF Min% PROC_closedialog(Dlg%(CurTab%)): PROC_showdialog(Dlg%(CurTab%)) :REM Just back from being minimized
Min%=FALSE :REM Update flag, effectively a memory of last scanned state.
ENDIF
It may also be necessary to update the data on the current tab as if you had just got to it.
|
« Last Edit: Nov 15th, 2016, 3:57pm by Zaphod » |
Logged
|
|
|
|
KenDown
Full Member
member is offline


Posts: 181
|
 |
Re: Tabs
« Reply #3 on: Nov 15th, 2016, 5:44pm » |
|
Actually, no. You don't close any of the dialog boxes! That's the big convenience about tabs: with dialog boxes accessed via buttons or menu options you have to save the contents and close one box, look up another, then return to the first and actually redraw it with the saved contents.
With tabs the dialog boxes stay open and you can skip from one tab to another - one dialog box to another - without saving or redrawing anything. Your data is still there. Wonderfuil!
I'm using the code from the Wiki article and you have this inside the main loop:
IFhTC%>0THEN SYS"SendMessage",hTC%,&130B,0,0TOcurrsel% IFcurrsel%<>prevsel%THEN IFprevsel%>=0SYS"ShowWindow",!dlg%(prevsel%),0 SYS"ShowWindow",!dlg%(currsel%),5 prevsel%=currsel% PROCtabhelp(currsel%) ENDIF ENDIF
It seems to cope with minimising without any problems, but it will not accept automatic changes, as described in my original post.
|
|
Logged
|
|
|
|
Zaphod
Guest
|
 |
Re: Tabs
« Reply #4 on: Dec 8th, 2016, 10:23pm » |
|
I suppose the original questioner solved his problem, but for others here is an example program. It does not do exactly what the original questioner asked for in that it controls the tabs programmatically from buttons in the main window. Changing tabs from within another tab would be a very unusual Windows action. Secondly, the MSDN text and examples of dialogs in tabs, does exactly as I suggested earlier, and closes the dialogs as the tab changes, which is different from the Wiki article. Both methods are included here, with the Wiki method left as default. Code:
INSTALL @lib$+"WINLIB5A"
INSTALL @lib$+"WINLIB2A"
REM!WC
SW_HIDE = 0
SW_SHOW = 5
TCM_SETCURSEL = 4876
_LOGPIXELSX = 88
TCIF_TEXT = 1
TCM_GETCURSEL = 4875
TCM_INSERTITEMA = 4871
WS_CLIPCHILDREN = &2000000
WS_CLIPSIBLINGS = &4000000
_ICC_TAB_CLASSES = 8
Width%=300 : REM Dialogue box sizes
Height%=200
font%=8
size%=10000
SYS "GetDeviceCaps", @memhdc%, _LOGPIXELSX TO Dpi% :REM Find the screen resolution in use
Scale = Dpi%/96 :REM Scale relative to standard 96 dpi
REM Items in the main window have to be scaled to match the dialog boxes which change with dpi.
H1%= FN_button(@hwnd%,"Back",20*Scale,380*Scale,60*Scale,40*Scale,201,0)
H2%= FN_button(@hwnd%,"Fwd",80*Scale,380*Scale,60*Scale,40*Scale,202,0)
DIM dlg%(2)
dlg%(0)=FNdefine_diag1
dlg%(1)=FNdefine_diag2
dlg%(2)=FNdefine_diag3
REM Now to find the size of the dialog so we can match the tab control to it. (If needed)
REM to do this we have to open a dilaog and measure it as the font chnages the size as well!
PROC_showdialog(dlg%(0))
DIM rc{l%,t%,r%,b%}
rc.l% = 0
rc.r% = Width%
rc.t% = 0
rc.b% = Height%
SYS "MapDialogRect", !dlg%(0), rc{}
pixx% = rc.r%-rc.l%
pixy% = rc.b%-rc.t%
PROC_closedialog(dlg%(0)) :REM Destroy the dialog once we have done with it.
DIM icex{dwSize%, dwICC%}
icex.dwSize% = DIM(icex{})
icex.dwICC% = _ICC_TAB_CLASSES
SYS "InitCommonControlsEx", icex{}
ON ERROR SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : END
Click% = 0
ON SYS Click% = @wparam% : RETURN
REM --------------- Create the ControlTab window: ------------------
hTC% = FN_createwindow(@hwnd%, "SysTabControl32", "", 0, 0, pixx%, pixy%, 0, WS_CLIPSIBLINGS OR WS_CLIPCHILDREN, 0)
IF hTC% = 0 ERROR 100, "Couldn't create tab control window"
PROCAdd_Tab(hTC%,"First",0) : REM send add tab message to controltab window
PROCAdd_Tab(hTC%,"Second",1) : REM send add tab message to controltab window
PROCAdd_Tab(hTC%,"Third",2) : REM send add tab message to controltab window
REM Make the tab control the parent of the dialog box!
!(dlg%(0)!4+8) = hTC%
!(dlg%(1)!4+8) = hTC%
!(dlg%(2)!4+8) = hTC%
REM Dock window
DIM rc{l%,t%,r%,b%}
SYS "GetWindowRect", hTC%, rc{}
SYS "GetWindowLong", @hwnd%, -16 TO style%
SYS "SetWindowLong", @hwnd%, -16, style% AND NOT &50000
SYS "AdjustWindowRect", rc{}, style% AND NOT &50000, 0
SYS "SetWindowPos", @hwnd%, 0, 0, 0, rc.r%-rc.l%, rc.b%-rc.t%+100,102 :REM allow space (100) for controls in main window.
REM Needed only if dialogs not closed as tab changes, Wiki method.
PROC_showdialog(dlg%(2)): SYS"ShowWindow", !dlg%(2), SW_HIDE
PROC_showdialog(dlg%(1)): SYS"ShowWindow", !dlg%(1), SW_HIDE
PROC_showdialog(dlg%(0))
cursel% = -1
REPEAT
click% = 0
SWAP click%,Click%
CASE click% OF
WHEN 201: IF cursel% >0 THEN SYS "SendMessage", hTC%, TCM_SETCURSEL, cursel%-1, 0
WHEN 202: IF cursel% <2 THEN SYS "SendMessage", hTC%, TCM_SETCURSEL, cursel%+1, 0
ENDCASE
SYS "SendMessage", hTC%, TCM_GETCURSEL, 0, 0 TO id%
IF id% <> cursel% THEN
REM MSDN preferred method closes dialogs. (not Wiki method).
REM https://msdn.microsoft.com/en-us/library/windows/desktop/hh298366(v=vs.85).aspx
REM IF cursel% >= 0 PROC_closedialog(dlg%(cursel%))
REM PROC_showdialog(dlg%(id%))
REM cursel% = id%
REM With this Wiki method the focus is not transfered to default dialog control automatically.
IF cursel% >= 0 SYS"ShowWindow", !dlg%(cursel%), SW_HIDE
SYS"ShowWindow", !dlg%(id%), SW_SHOW
cursel% = id%
SYS "GetDlgItem",!dlg%(id%),101 TO H%
PROC_setfocus(H%)
ENDIF
UNTIL INKEY(1) = 0
END
REM
-----------------------------------------------------------------
DEFPROCAdd_Tab(htc%,text$,id%)
LOCAL cti{}, fn%, res%
DIM cti{mask%,dwState%,dwStateMask%,pszText%,cchTextMax,iImage,lparam%}
text$ += CHR$0
cti.mask%=TCIF_TEXT
cti.iImage=-1
cti.pszText%=!^text$
SYS "SendMessage", htc%, TCM_INSERTITEMA, id%, cti{} TO res%
IF res% = -1 ERROR 100, "Couldn't send Tab Control info"
ENDPROC
REM
-----------------------------------------------------------------
DEF FNdefine_diag1
LOCAL dlg%
dlg%=FN_newdialog("",0,14,Width%,Height%,font%,size%)
dlg%!16=&508800C4 : REM remove title bar and make child window
PROC_static(dlg%,"Test1",100,84,6,20,20,0)
PROC_editbox(dlg%,"",101,84,30,50,14,0)
= dlg%
DEF FNdefine_diag2
LOCAL dlg%
dlg%=FN_newdialog("",0,14,Width%,Height%,font%,size%)
dlg%!16=&508800C4 : REM remove title bar and make child window
PROC_static(dlg%,"Test2",100,84,6,20,20,0)
PROC_editbox(dlg%,"",101,84,30,50,14,0)
= dlg%
DEF FNdefine_diag3
LOCAL dlg%
dlg%=FN_newdialog("",0,14,Width%,Height%,font%,size%)
dlg%!16=&508800C4 : REM remove title bar and make child window
PROC_static(dlg%,"Test3",100,84,6,20,20,0)
PROC_editbox(dlg%,"",101,84,30,50,14,0)
= dlg%
I hope that might be useful for someone. The automatic scaling with dpi has NOT been tested, but i believe it should work.
|
|
Logged
|
|
|
|
KenDown
Full Member
member is offline


Posts: 181
|
 |
Re: Tabs
« Reply #5 on: Dec 9th, 2016, 06:38am » |
|
Oh brilliant! That does exactly what I want. It was the
SYS"SendMessage", hTC%, 4876, cursel%, 0
which did it, and no, one doesn't need to close any dialog boxes. Just determine the tab number that you need to open and set cursel% to that, send the message and the required tab opens (which automatically obscures the others).
|
|
Logged
|
|
|
|
Zaphod
Guest
|
 |
Re: Tabs
« Reply #6 on: Dec 9th, 2016, 3:16pm » |
|
Good, I am glad that was useful.
That was:
SYS"SendMessage", hTC%, TCM_SETCURSEL, cursel%, 0
for those that don't memorize the Windows Constants by number.
|
|
Logged
|
|
|
|
|