Page 1 of 1

Disable PanelGadget tabs?

Posted: Sat Jun 18, 2005 3:07 pm
by PB
Anyone know how to disable a PanelGadget tab? (I did a search here for
"disable tab" and nothing relevant was found).

Posted: Sat Jun 18, 2005 4:54 pm
by Sparkie
I wasn't able to find any API to disable a tab, but I did come up with a quick way to prevent a tab from being selected. If you want more control of the appearance, you'll have to ownerdraw your PanelGadget. ;)

Code: Select all

#WinMain = 0
#MyPanel = 0

Global oldCallback

; --> SubClass procedure for PanelGadget
Procedure PanelCallback(hwnd, msg, wparam, lparam)
  Shared previousTab
  result = CallWindowProc_(oldCallback, hwnd, msg, wparam, lparam)
  Select msg
    Case #WM_NOTIFY
      *pNMHDR.NMHDR = lparam
      Select *pNMHDR\code
        Case #TCN_SELCHANGING
          ; --> Get the index of the Tab that is about to lose focus
          previousTab = GetGadgetState(#MyPanel)
        Case #TCN_SELCHANGE 
          ; --> Get the index of the selected Tab
          currentTab = GetGadgetState(#MyPanel)
          ; --> If it's Tab index 2, our disabled tab, 
          ; --> SetGadgetState to the previousTab index
          If currentTab = 2
            SetGadgetState(0, previousTab)
          EndIf
      EndSelect
  EndSelect
  ProcedureReturn result
EndProcedure
      
If OpenWindow(#WinMain, 0, 0, 300, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "PanelGadget") And CreateGadgetList(WindowID(#WinMain))
  PanelGadget(#MyPanel, 10, 10, 280, 180)
  AddGadgetItem (#MyPanel, -1, "Panel 1")
  AddGadgetItem (#MyPanel, -1, "Panel 2")
  AddGadgetItem (#MyPanel, -1, "Disabled")
  CloseGadgetList()
  ; --> We need the parent of PanelGadget so we can subclass and recieve messages
  hPanelParent = GetParent_(GadgetID(#MyPanel))
  oldCallback = SetWindowLong_(hPanelParent, #GWL_WNDPROC, @PanelCallback()) 
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf

Posted: Sun Jun 19, 2005 2:05 am
by PB
Thanks Sparkie, but my app already has a callback and using your code
seems to interfere with it (ie. gadgets are no longer drawn correctly, etc).
Any way to integrate the above into my current callback? I did try but I
could still select other panels... :(

(Basically, I want to just have one panel available until a certain gadget
is checked, so if the user tries to select other panels, nothing happens).

Posted: Sun Jun 19, 2005 2:18 am
by Sparkie
Sorry about that PB. :( I just threw that code together so there wasn't much testing on my part. If you can you post some of your code, maybe I can figure it out. :)

Posted: Sun Jun 19, 2005 2:29 am
by PB
No worries Sparkie. :) I'm using a normal Callback as per the docs, and here's
the only part of your code I injected into the routine. This doesn't stop me
selecting another tab. I'll probably work it out, just need to play for a bit.

Update: If I put a Debug command after #WM_NOTIFY, it never gets seen,
so it seems this message isn't received in my callback. Hmm.

Code: Select all

; prevtab is global.
Case #WM_NOTIFY
  *pNMHDR.NMHDR=lParam
  If *pNMHDR\code=#TCN_SELCHANGING
    prevtab=GetGadgetState(#panel)
  ElseIf *pNMHDR\code=#TCN_SELCHANGE
    If GetGadgetState(#panel)<>2 : SetGadgetState(#panel,prevtab) : EndIf
  EndIf

Posted: Sun Jun 19, 2005 2:35 am
by Sparkie
The PanelGadet's parent is a static control and not the main window. That's why you're not recieving the #WM_NOTIFY messages when changing tabs. This is why I had to subclass the static control. I'm not sure why that subclass procedure is interfering with your gadget draws though. :?

Posted: Sun Jun 19, 2005 2:46 am
by PB
WORKING! :D Here's what I did this time:

Code: Select all

Procedure PanelCallback(hWnd,msg,wparam,lParam)
  Result=CallWindowProc_(MainCallback,hWnd,msg,wparam,lParam)
  If msg=#WM_NOTIFY
    *pNMHDR.NMHDR=lParam
    Select *pNMHDR\code
      Case #TCN_SELCHANGING : prevtab=GetGadgetState(#panel)
      Case #TCN_SELCHANGE : If GetGadgetState(#panel)<>2 : SetGadgetState(#panel,prevtab) : EndIf
    EndSelect
  EndIf
  ProcedureReturn Result
EndProcedure
And in my main code:

Code: Select all

SetWindowCallback(@Callback())
MainCallback=SetWindowLong_(GetParent_(GadgetID(#panel)),#GWL_WNDPROC,@PanelCallback())
Both "MainCallback" and "prevtab" are global variables. Maybe I just had
a typo or missed something before. All works and all gadgets drawn. :)

@Fred: New command request -- DisablePanelGadgetTab(#gadget,index)

;)

Posted: Sun Jun 19, 2005 2:51 am
by Sparkie
Or maybe my explaining the process to you was a little unclear. Glad you worked it out. :)

Posted: Sun Jun 19, 2005 2:57 am
by PB
I never really understood subclassing, to be honest. I thought it was the same
thing as a callback -- obviously not. :) I thought I could just take your code and
throw it into my existing callback, but subclassing seems to be something more.

Posted: Sun Jun 19, 2005 6:06 am
by localmotion34
PB wrote: @Fred: New command request -- DisablePanelGadgetTab(#gadget,index)

;)
i dont think that will be an option since there is no associated MESSAGE in win32.hlp about disabling a paneltab.

you can add a tab by sending the #tcm_insertitem message, but there is no associated "#tcm_disableitem" message

what youd have to do to get the greyed "disabled" look for that tab item is to create an ownerdrawn tabcontrol, and each time the tab is drawn, check to see if the item is disabled, and then draw the text in a color that mimicks the "disabled" state

Posted: Sun Jun 19, 2005 9:16 am
by Manol
Hi PB,
See the next code

Code: Select all

Procedure showPanel()
    AddGadgetItem(1, 2, "New Hidden Panel")
EndProcedure

Procedure hidePanel()
    RemoveGadgetItem(1, 2)
EndProcedure


OpenWindow(1, 0,0,300, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "")

    If CreateMenu(0, WindowID())
        MenuTitle("Panel")
            MenuItem( 1, "Create New Panel")
            MenuItem( 2, "Remove New Panel")
    EndIf

    CreateGadgetList(WindowID())
    
        PanelGadget(1, 10, 10, 250, 250)
             AddGadgetItem(1, 0, "Test Panel 1")
             AddGadgetItem(1, 1, "Test Panel 2")
       ; ClosePanelGadget()

Repeat

        EventID.l = WaitWindowEvent()
        Select EventID

            Case #PB_EventMenu
                Select EventMenuID()
                    Case 1
                        showPanel()
                    Case 2
                        hidePanel()
                EndSelect

            Case #PB_EventGadget
                Select EventGadgetID()

                EndSelect
                
        EndSelect

Until quit
Or this other
OpenWindow( 0,0,0,300,300,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Test" )
CreateGadgetList( WindowID( 0 ) )

OptionGadget ( 0, 10, 10, 150, 20, "Show Secret Gadget" )
OptionGadget ( 1, 10, 30, 150, 20, "Hide Secret Gadget" )
SetGadgetState( 1, 1 )


PanelGadget( 2, 10, 60, 270, 230 )
AddGadgetItem( 2,-1,"Secret" )
StringGadget( 3,10,10,100,20,"" )

;ClosePanelGadget()

HideGadget ( 2,1 )
HideWindow ( 0, 0 )

Repeat
EW = WaitWindowEvent()

If EW = #PB_Event_Gadget
Select EventGadgetID()
Case 0 : HideGadget( 2, 0 )
Case 1 : HideGadget( 2, 1 )
EndSelect
EndIf

Until EW = #PB_EventCloseWindow
End
Manolo

Posted: Sun Jun 19, 2005 10:25 am
by Edwin Knoppert
You can determine where mouse is and cancel the hittest or mouseactivate.
Of course the keys is a problem.

The following topic (PowerBASIC) shows how to determine that.

http://www.hellobasic.com/cgi-bin/forum ... 1105091425

However, the latest approach differs completely, due poor results i simply used WM_SETREDRAW and restore to previous tab.

Selchanging:

' Store currently selected tab in a property.
SetProp NMH.hWndFrom, "VD__CURSEL", VD_Tab_GetCursel( NMH.hWndFrom, 0 )

' Freeze this main form, we release it in another event.
SendMessage nCbHndl, %WM_SETREDRAW, 0, 0

Selchange:


Local R As RECT

' Here we decide To Restore To desired form, example uses some dumb timer+Mod, use your own criteria..

VD_Debug_Print Str$( Round( Timer, 0 ) Mod 2 )

If IsFalse( Round( Timer, 0 ) Mod 2 ) Then

' Set To previously selected form.
VD_Tab_ShowForm( NMH.hWndFrom, 0, GetProp( NMH.hWndFrom, "VD__CURSEL" ) )

End If

' It's important we repaint the whole form.

' Release..
SendMessage nCbHndl, %WM_SETREDRAW, 1, 0

' Obtain client area For redraw.
GetClientRect nCbHndl, R

' Redraw all.
RedrawWindow( nCbHndl, R, 0, %RDW_ERASE Or %RDW_INVALIDATE Or %RDW_UPDATENOW Or %RDW_ALLCHILDREN )


The timer is just nonsense code, remove, it's just a flag you should maintain if the restore is required or not.

Posted: Sun Jun 19, 2005 11:26 am
by PB
Thanks Manol and Edwin, but Sparkie's method is what I require in this case.
I don't want to hide/show the panel tab, as it's in the middle and not an end.
And with Sparkie's code, it also works if the keyboard tries to change tabs.