Page 1 of 1

DISABLE A PANELGADGET ITEM

Posted: Fri Jun 24, 2005 9:05 pm
by localmotion34
ok folks, here it is. code for a disabled panelgadget item. some notes first:

1) if you inspect a PB panelgadget closely with WinID, youll find that the parent of the panel is NOT the main window, but a STATIC control EXACTLY the same size and position. this most likely is used to trap all the drawitem and other messages.

2) this static control now allows you to SUBCLASS and process messages ANY way you want WITHOUT setting windowcallback.

3) this took me a while to do, so if you use it, give me my props. :wink:

Code: Select all

Global OriginProc.l,textcolor 

Dim oldsel.l(1)

Procedure tabproc(hwnd,msg,wParam,lParam)
  Select msg 
    Case #WM_DRAWITEM
      textbuffer.s=Space(255)
      *lpdis.DRAWITEMSTRUCT=lParam 
      tab.TC_ITEM
      Select *lpdis\CtlType 
        Case #ODT_TAB
          Select *lpdis\itemState 
            Case #ODS_SELECTED 
              tab\Mask=#TCIF_TEXT
              tab\pszText=@textbuffer
              tab\cchTextMax=255
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab)
              textcolor.l= #Black
            Case #ODS_SELECTED | #ODS_FOCUS 
              drawfoc.l=#True 
              
            Case 0
              tab\Mask=#TCIF_PARAM
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab)
              If tab\lParam=1
                tab\Mask=#TCIF_TEXT
                tab\pszText=@textbuffer
                tab\cchTextMax=255
                SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab)
                textcolor.l= #White
                *lpdis\rcItem\left+5
                *lpdis\rcItem\top+3
                SetTextColor_(*lpdis\hdc, textcolor) 
                DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
                textcolor.l= RGB(84,82,84)
                *lpdis\rcItem\top-3
                *lpdis\rcItem\left-5
                ; this code here draws text just like windows disabled, grey with white shadow
                ; by messing with the RECT coordinates
              Else 
              tab\Mask=#TCIF_TEXT
              tab\pszText=@textbuffer
              tab\cchTextMax=255
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab)
              textcolor.l= #Black
            EndIf
          EndSelect 
          If drawfoc=#True
            DrawFocusRect_(*lpdis\hdc, *lpdis\rcItem)
          EndIf 
          SetBkMode_(*lpdis\hdc, #TRANSPARENT) 
          *lpdis\rcItem\left+4
          *lpdis\rcItem\top+2
          SetTextColor_(*lpdis\hdc, textcolor) 
          DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
          ProcedureReturn 0
      EndSelect 
    Case #WM_NOTIFY
      *pNMHDR.NMHDR = lParam
      tab1.TC_ITEM 
      Select *pNMHDR\code
        Case #TCN_SELCHANGING
          ; --> Get the index of the Tab that is about to lose focus
          oldsel(0)=SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0)
        Case #TCN_SELCHANGE
          ; --> Get the index of the selected Tab
          newTab = SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0)
          tab1\Mask=#TCIF_PARAM
          SendMessage_(*pNMHDR\hwndFrom,#TCM_GETITEM,newTab,@tab1)
          If tab1\lParam=1
            SendMessage_(*pNMHDR\hwndFrom,#TCM_SETCURSEL,oldsel(0),0)
          EndIf
          ProcedureReturn 0 
      EndSelect 
      
  EndSelect 
  ProcedureReturn CallWindowProc_(OriginProc,hwnd,msg,wParam,lParam) 
EndProcedure
 
Procedure disablepanelitem(panel,item,State)
  If State=1
  itm.TC_ITEM
  itm\Mask=#TCIF_PARAM
  SendMessage_(GadgetID(panel),#TCM_GETITEM,item,@itm)
  itm\lParam=1
  itm\Mask=#TCIF_PARAM
  SendMessage_(GadgetID(panel),#TCM_SETITEM,item,@itm)
ElseIf State=0
  itm.TC_ITEM
  itm\Mask=#TCIF_PARAM
  SendMessage_(GadgetID(panel),#TCM_GETITEM,item,@itm)
  itm\lParam=0
  itm\Mask=#TCIF_PARAM
  SendMessage_(GadgetID(panel),#TCM_SETITEM,item,@itm)
EndIf 
EndProcedure

#WindowWidth  = 390
#WindowHeight = 350
If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, #PB_Window_MinimizeGadget, "")
  If CreateGadgetList(WindowID())
    PanelGadget(30,30,30,360,300)
    SetWindowLong_(GadgetID(30),#GWL_STYLE,GetWindowLong_(GadgetID(30),#GWL_STYLE)	|#TCS_OWNERDRAWFIXED)
    RedrawWindow_(GadgetID(30),0,0,7)
    ShowWindow_(GadgetID(30),#SW_SHOW)
    OriginProc=SetWindowLong_(GetParent_(GadgetID(30)),#GWL_WNDPROC,@tabproc())
    For a=0 To 3
      AddGadgetItem(30,a,"test" + Str(a))
    Next 
    CloseGadgetList()
  EndIf
  
  disablepanelitem(30,2,1)
  
  ;- event loop
  Repeat
    
    EventID = WaitWindowEvent()
    
    If EventID = #PB_EventGadget
      
      Select EventGadgetID()
        
        
        
      EndSelect
      
    EndIf
    
  Until EventID = #PB_EventCloseWindow
  
EndIf
  
End 

     
and there you have it. DISABLED TAB ITEMS

and the crowd goes wild:::::

Posted: Fri Jun 24, 2005 9:42 pm
by Blade
Great work!
I'm always amazed when someone has such results without using callbacks... Don't know why, but callbacks look like cheating... ;) IMHO

Posted: Fri Jun 24, 2005 10:32 pm
by localmotion34
oh, but this IS a callback. EVERY single function a window or gadget processes is defined in the DefWinProc created by the windows system.

i can create a buttongadget, set a window "long" value to redirect the windowprocedure to my own handwritten, and every time the button is clicked, instead of it pressing down, i can make it show a popup menu, or whatever i want.

this is called SUBCLASSING. that is, i take a certain gadget, a member of a CLASS, and i sub-direct its functions. and any function i dont want to deal with, i pass back to the default winproc.

its like screening at the airport. people whom they dont want to examine are allowed to pass, but people who they want a closer look at are redirected and given additional instructions.

i am actually going to make a PB userlibrary out of this, because the PB panel gadget has a parent of a static window, which i can subclass by setting the windowprocedure to my own.

procedure paneldisablefunction(#panel)
parent=getparent_(gadgetid(panel))
OriginProc=SetWindowLong_(GetParent_(GadgetID(30)),#GWL_WNDPROC,@tabproc())
endprocedure

tabproc() could be part of a PB user library that is statically linked to your app, removing the need to spell out all the code.

Posted: Sat Oct 07, 2006 12:16 pm
by clipper
Searching for a Solution to disable a Panel, I´ve found this thread.

Yes, the code works fine, the Panel could disabled, but my Gadgets are lost!!

Is meanwhile a better solution available?
I´ve searched all over the forum´s and didn´t find anything.
Or is there a snippet to ghost the caption of a single Gadget?

Code: Select all

Global OriginProc.l,textcolor 
Global Dim oldsel.l(1) 

Procedure tabproc(hwnd,msg,wParam,lParam) 
  Select msg 
    Case #WM_DRAWITEM 
      textbuffer.s=Space(255) 
      *lpdis.DRAWITEMSTRUCT=lParam 
      tab.TC_ITEM 
      Select *lpdis\CtlType 
        Case #ODT_TAB 
          Select *lpdis\itemState 
            Case #ODS_SELECTED 
              tab\Mask=#TCIF_TEXT 
              tab\pszText=@textbuffer 
              tab\cchTextMax=255 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
              textcolor.l= #Black 
            Case #ODS_SELECTED | #ODS_FOCUS 
              drawfoc.l=#True 
              
            Case 0 
              tab\Mask=#TCIF_PARAM 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
              If tab\lParam=1 
                tab\Mask=#TCIF_TEXT 
                tab\pszText=@textbuffer 
                tab\cchTextMax=255 
                SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
                textcolor.l= #White 
                *lpdis\rcItem\left+5 
                *lpdis\rcItem\top+3 
                SetTextColor_(*lpdis\hdc, textcolor) 
                DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
                textcolor.l= RGB(84,82,84) 
                *lpdis\rcItem\top-3 
                *lpdis\rcItem\left-5 
                ; this code here draws text just like windows disabled, grey with white shadow 
                ; by messing with the RECT coordinates 
              Else 
              tab\Mask=#TCIF_TEXT 
              tab\pszText=@textbuffer 
              tab\cchTextMax=255 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
              textcolor.l= #Black 
            EndIf 
          EndSelect 
          If drawfoc=#True 
            DrawFocusRect_(*lpdis\hdc, *lpdis\rcItem) 
          EndIf 
          SetBkMode_(*lpdis\hdc, #TRANSPARENT) 
          *lpdis\rcItem\left+4 
          *lpdis\rcItem\top+2 
          SetTextColor_(*lpdis\hdc, textcolor) 
          DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
          ProcedureReturn 0 
      EndSelect 
    Case #WM_NOTIFY 
      *pNMHDR.NMHDR = lParam 
      tab1.TC_ITEM 
      Select *pNMHDR\code 
        Case #TCN_SELCHANGING 
          ; --> Get the index of the Tab that is about to lose focus 
          oldsel(0)=SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0) 
        Case #TCN_SELCHANGE 
          ; --> Get the index of the selected Tab 
          newTab = SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0) 
          tab1\Mask=#TCIF_PARAM 
          SendMessage_(*pNMHDR\hwndFrom,#TCM_GETITEM,newTab,@tab1) 
          If tab1\lParam=1 
            SendMessage_(*pNMHDR\hwndFrom,#TCM_SETCURSEL,oldsel(0),0) 
          EndIf 
          ProcedureReturn 0 
      EndSelect 
      
  EndSelect 
  ProcedureReturn CallWindowProc_(OriginProc,hwnd,msg,wParam,lParam) 
EndProcedure 
  
Procedure disablepanelitem(panel,item,State) 
  If State=1 
  itm.TC_ITEM 
  itm\Mask=#TCIF_PARAM 
  SendMessage_(GadgetID(panel),#TCM_GETITEM,item,@itm) 
  itm\lParam=1 
  itm\Mask=#TCIF_PARAM 
  SendMessage_(GadgetID(panel),#TCM_SETITEM,item,@itm) 
ElseIf State=0 
  itm.TC_ITEM 
  itm\Mask=#TCIF_PARAM 
  SendMessage_(GadgetID(panel),#TCM_GETITEM,item,@itm) 
  itm\lParam=0 
  itm\Mask=#TCIF_PARAM 
  SendMessage_(GadgetID(panel),#TCM_SETITEM,item,@itm) 
EndIf 
EndProcedure 


If OpenWindow(0, 100, 200, 390, 350, "", #PB_Window_MinimizeGadget) 
  If CreateGadgetList(WindowID(0)) 
     ButtonGadget(6,5,5,120,35,"Disable Panel 2")
     PanelGadget(30,5,45,380,300) 
     SetWindowLong_(GadgetID(30),#GWL_STYLE,GetWindowLong_(GadgetID(30),#GWL_STYLE)   |#TCS_OWNERDRAWFIXED) 
     RedrawWindow_(GadgetID(30),0,0,7) 
     ShowWindow_(GadgetID(30),#SW_SHOW) 
     OriginProc=SetWindowLong_(GetParent_(GadgetID(30)),#GWL_WNDPROC,@tabproc()) 
     For a=1 To 5
         AddGadgetItem(30,a,"Panel " + Str(a)) 
         StringGadget(a,a*15,a*10,100,20,Str(a)) 
     Next 
     CloseGadgetList() 
  EndIf 
  Repeat 
    EventID = WaitWindowEvent() 
    If EventID = #PB_Event_Gadget 
       Select EventGadget()
          Case 6
             disablepanelitem(30,1,1)
       EndSelect  
    EndIf 
  Until EventID = #PB_Event_CloseWindow 
EndIf 
End 

Posted: Sat Oct 07, 2006 12:46 pm
by Trond
I think you need a code to disable your caps lock key as well.

Posted: Sat Oct 07, 2006 1:06 pm
by clipper
Trond wrote:I think you need a code to disable your caps lock key as well.
???

Posted: Sat Oct 07, 2006 2:42 pm
by Trond
clipper wrote:
Trond wrote:I think you need a code to disable your caps lock key as well.
???
Not you, look at the topic title.

Posted: Sun Oct 08, 2006 5:22 am
by clipper
Because the code of localmotion34 destroyes the gadgets on the panel, i´ve looked around for a solution and have found this site:

http://hyper.sunjapan.com.cn/~hz/win32/commctl6.htm

Under "Tab Control" there is a property sheet with a property like "TCIS_DISABLED" ...
:twisted: I´m not so familar with c and have tricked a afternoon with no result!

Isn´t it possible to disable a PanelgadgetItem?

Posted: Sun Oct 08, 2006 8:14 am
by netmaestro
Yes the TCIS_DISABLED state appears to promise an easy solution to disabling items in a tab control but it's only an illusion. MS themselves say there's no easy way to disable tab control items. You have to ownerdraw and keep track of the items that are "disabled" and handle their messages accordingly. It's a long way around and a major pain but that's the reality for this control.

Posted: Sun Oct 08, 2006 9:16 am
by PB
> MS themselves say there's no easy way to disable tab control items

Wouldn't it be easier just to disable all gadgets on a certain tab, instead of
disabling the tab itself? Would be more intuitive too, from feedback I had.

Posted: Sun Oct 08, 2006 12:04 pm
by srod
I'm not sure if I've covered everything, but...

Code: Select all

Global dis2

Procedure winproc(hwnd,msg,wParam,lParam) 
  Protected result, tch.TC_HITTESTINFO, *pNMHDR.NMHDR, newtab
  result=#PB_ProcessPureBasicEvents

  Select msg 
    Case #WM_NOTIFY 
      *pNMHDR= lParam 
      Select *pNMHDR\code 
        Case #TCN_SELCHANGING 
          If GetAsyncKeyState_(#VK_LBUTTON)&32768 ;Selection by mouse button.
;Identify which tab was selected.
            GetCursorPos_(tch\pt)
            MapWindowPoints_(#Null,GadgetID(30),tch\pt,1)
            newtab= SendMessage_(GadgetID(30), #TCM_HITTEST,0, tch)
            If newtab = 1 And dis2
              result=1
            EndIf
          ElseIf GetAsyncKeyState_(#VK_LEFT)&32768 ;Selection by left cursor.
            If dis2 And GetGadgetState(30)=2
              result=1
            EndIf
          ElseIf GetAsyncKeyState_(#VK_RIGHT)&32768 ;Selection by right cursor.
            If dis2 And GetGadgetState(30)=0
              result=1
            EndIf
          EndIf
      EndSelect 
  EndSelect 
  ProcedureReturn result
EndProcedure 
  

If OpenWindow(0, 100, 200, 390, 350, "", #PB_Window_MinimizeGadget) 
  If CreateGadgetList(WindowID(0)) 
     ButtonGadget(6,5,5,140,35,"Disable/enable Panel 2") 
     PanelGadget(30,5,45,380,300) 
     For a=1 To 5 
         AddGadgetItem(30,a,"Panel " + Str(a)) 
         StringGadget(a,a*15,a*10,100,20,Str(a)) 
     Next 
     CloseGadgetList() 
  EndIf 
  SetWindowCallback(@winproc()) 
  Repeat 
    EventID = WaitWindowEvent() 
    If EventID = #PB_Event_Gadget 
       Select EventGadget() 
          Case 6 
            dis2=1-dis2
            If dis2 And GetGadgetState(30)=1
              SetGadgetState(30,0)
            EndIf
       EndSelect  
    EndIf 
  Until EventID = #PB_Event_CloseWindow 
EndIf 
End 

I think it is done...

Posted: Tue Oct 10, 2006 1:28 pm
by clipper
Thanks a lot for your code srod.
What I missed, is that the panelcaptions is ghosted if the panel is disabled.



The lost gadgets in localmotion34´s code is a result from the function
disablepanelitem()
I think itm\lParam=0 or itm\lParam=1 overwrites the Panels handle so that the gadgets couldn´t be drawn on the panel.
- I store the PanelState in a global array.

DoDo: Insert some code to step to the next enabled panel if we the user changed the panels by the keyboard

I´ve joined the code from srod and localmotion34:

Code: Select all

Global Dim Panels.l(0)

Procedure winproc(hwnd,msg,wParam,lParam) 
  Protected result, tch.TC_HITTESTINFO, *pNMHDR.NMHDR, newtab 
  result=#PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_DRAWITEM 
      textbuffer.s=Space(255) 
      *lpdis.DRAWITEMSTRUCT=lParam 
      tab.TC_ITEM 
      Select *lpdis\CtlType 
        Case #ODT_TAB 
          Select *lpdis\itemState 
            Case #ODS_SELECTED 
              tab\Mask=#TCIF_TEXT 
              tab\pszText=@textbuffer 
              tab\cchTextMax=255 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM   ,*lpdis\itemID,@tab) 
              textcolor.l= #Black 
            Case #ODS_SELECTED | #ODS_FOCUS 
              drawfoc.l=#True       
            Case 0 
              tab\Mask=#TCIF_PARAM 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM   ,*lpdis\itemID,@tab) 
              If Panels(*lpdis\itemID)
                 tab\Mask=#TCIF_TEXT 
                 tab\pszText=@textbuffer 
                 tab\cchTextMax=255 
                 SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
                 *lpdis\rcItem\left+5 
                 *lpdis\rcItem\top+3 
                 textcolor.l= #White
                 SetTextColor_(*lpdis\hdc, textcolor)                  
                 DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
                 textcolor.l= 5526100  ;RGB(84,82,84) 
                 *lpdis\rcItem\top -3 
                 *lpdis\rcItem\left-5 
              Else 
              tab\Mask=#TCIF_TEXT 
              tab\pszText=@textbuffer 
              tab\cchTextMax=255 
              SendMessage_(*lpdis\hwndItem,#TCM_GETITEM,*lpdis\itemID,@tab) 
              textcolor.l= #Black 
            EndIf 
          EndSelect 
          If drawfoc=#True 
            DrawFocusRect_(*lpdis\hdc, *lpdis\rcItem) 
          EndIf 
          SetBkMode_(*lpdis\hdc, #TRANSPARENT) 
          *lpdis\rcItem\left+4 
          *lpdis\rcItem\top+2 
          SetTextColor_(*lpdis\hdc, textcolor) 
          DrawText_(*lpdis\hdc, textbuffer, Len(textbuffer), *lpdis\rcItem, dtFlags) 
          ProcedureReturn 0 
      EndSelect 
       
    Case #WM_NOTIFY 
      *pNMHDR= lParam
      Select *pNMHDR\code
        Case #TCN_SELCHANGING
            itm.TC_ITEM 
            itm\Mask=#TCIF_PARAM  
            If GetAsyncKeyState_(#VK_LBUTTON) & 32768
               GetCursorPos_(tch\pt) 
               MapWindowPoints_(#Null,*pNMHDR\hwndFrom,tch\pt,1)            
               If Panels(SendMessage_(*pNMHDR\hwndFrom, #TCM_HITTEST,0, tch) )
                  result=1                  
               EndIf
            ElseIf GetAsyncKeyState_(#VK_LEFT)& 32768 ;
               panel = SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0) - 1       
               If panel > 0 And Panels(panel)
                  result=1             
               EndIf  
            ElseIf GetAsyncKeyState_(#VK_RIGHT)& 32768 ;Selection by right cursor.
               panel = SendMessage_(*pNMHDR\hwndFrom,#TCM_GETCURSEL,0,0) + 1
               ct = PeekL(@Panels()-8) -1
               If panel < ct And Panels(panel)
                  result=1            
               EndIf           
            EndIf 
      EndSelect 
  EndSelect 
  ProcedureReturn result 
EndProcedure 
  


If OpenWindow(0, 100, 200, 390, 350, "", #PB_Window_MinimizeGadget) 
  If CreateGadgetList(WindowID(0)) 
     For i=1 To 4
        ButtonGadget(5+i,5+i*48,5,48,25,"D/E"+Str(i+1))
     Next i
     PanelGadget(30,5,45,380,300)
     SetWindowLong_(GadgetID(30),#GWL_STYLE,GetWindowLong_(GadgetID(30),#GWL_STYLE)   |#TCS_OWNERDRAWFIXED)    
     For a=1 To 5 
         ReDim Panels.l(a)
         Panels.l(a)=#False          ; Enable the new Panel
         AddGadgetItem(30,a,"Panel " + Str(a)) 
         StringGadget(a,a*15,a*10,100,20,"Panel " + Str(a)) 
     Next  
     CloseGadgetList() 
  EndIf 
  SetWindowCallback(@winproc()) 
  Repeat 
    EventID = WaitWindowEvent() 
    If EventID = #PB_Event_Gadget 
       eg=EventGadget() 
       Select eg
          Case 6,7,8,9 
            Panels(eg-5)=1-Panels(eg-5)
            RedrawWindow_(GadgetID(30),0,0,7) 
            ShowWindow_(GadgetID(30),#SW_SHOW)        
       EndSelect  
    EndIf 
  Until EventID = #PB_Event_CloseWindow 
EndIf 
End