Page 1 of 1

Possible without Callback??

Posted: Sat Nov 26, 2005 7:07 pm
by josku_x
Hello!

I know that some functions doesn't need callbacks and I am now working on a project where I want to avoid using them..

so, here is the code I want to have without callback:

Code: Select all

#TVGN_DROPHILITE = 8 

Procedure WinCallback(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_NOTIFY 
      *pnmhdr.NMHDR = lparam 
      ; --> If TreeGadget receives a right click, select the item 
      If *pnmhdr\hwndFrom = GadgetID(0) And *pnmhdr\code = #NM_RCLICK 
        ; --> hItem = The handle to item that has been right clicked 
        hItem = SendMessage_(*pnmhdr\hwndFrom, #TVM_GETNEXTITEM, #TVGN_DROPHILITE, 0) 
        ; --> Select that item 
        SendMessage_(*pnmhdr\hwndFrom, #TVM_SELECTITEM, #TVGN_CARET, hItem) 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 0, 0, 350, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Sparkies TreeGadget - Right Click Selects") And CreateGadgetList(WindowID(0)) 
  TreeGadget(0, 10, 10, 180, 180) 
  For i = 0 To 5 
    AddGadgetItem (0, -1, "Item "+ Str(i)) 
    AddGadgetItem (0, -1, "Parent " + Str(i)) 
    OpenTreeGadgetNode(0) 
    AddGadgetItem(0, -1, "Sub Item 1") 
    AddGadgetItem(0, -1, "Sub Item 2") 
    AddGadgetItem(0, -1, "Sub Item 3") 
    AddGadgetItem(0, -1, "Sub Item 4") 
    CloseTreeGadgetNode(0) 
  Next 
  SetWindowCallback(@WinCallback()) 
  Repeat 
    event = WaitWindowEvent() 
  Until event = #PB_Event_CloseWindow 
EndIf 
End
Is this possible? I tried to do that many times but just failed.
I just want to avoid using a callback, please don't ask why.

Thanks!

Posted: Sat Nov 26, 2005 7:29 pm
by srod

Code: Select all

If OpenWindow(0, 0, 0, 350, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Sparkies TreeGadget - Right Click Selects") And CreateGadgetList(WindowID(0)) 
  TreeGadget(0, 10, 10, 180, 180) 
  For i = 0 To 5 
    AddGadgetItem (0, -1, "Item "+ Str(i)) 
    AddGadgetItem (0, -1, "Parent " + Str(i)) 
    OpenTreeGadgetNode(0) 
    AddGadgetItem(0, -1, "Sub Item 1") 
    AddGadgetItem(0, -1, "Sub Item 2") 
    AddGadgetItem(0, -1, "Sub Item 3") 
    AddGadgetItem(0, -1, "Sub Item 4") 
    CloseTreeGadgetNode(0) 
  Next 
  Repeat 
    event = WaitWindowEvent() 
    if eventtype() = #PB_EventType_RightClick and eventgadgetid() = 0
      pt.point\x=windowmousex() : pt\y=windowmousey() ;Get mouse coordinates.
      mapwindowpoints_(windowid(),gadgetid(0),@pt,1) ;Make coords relative to client area of tree gadget.
;Next 3 lines obtain the handle to the item under the cursor.
      tv.TV_HITTESTINFO
        tv\pt\x = pt\x : tv\pt\y = pt\y
        sendmessage_(gadgetid(0), #TVM_HITTEST, 0, tv)
;Now select the said item.
      SendMessage_(gadgetid(0), #TVM_SELECTITEM, #TVGN_CARET, tv\hItem) 
    endif


  Until event = #PB_Event_CloseWindow 
EndIf 
End
Regards.

Posted: Sat Nov 26, 2005 7:48 pm
by josku_x
Thanks! you made my day!

Posted: Sat Nov 26, 2005 7:51 pm
by josku_x
By the way is this possible using SetGadgetState()?

Posted: Sat Nov 26, 2005 8:07 pm
by srod
josku_x wrote:By the way is this possible using SetGadgetState()?
Yes, but we simply switch a line of code, for a line of code, so nothing is really gained! Indeed, the new line still relies upon the handle of the item obtained by a Win API call, so it's is still not going to be cross platform.

Code: Select all

If OpenWindow(0, 0, 0, 350, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Sparkies TreeGadget - Right Click Selects") And CreateGadgetList(WindowID(0)) 
  TreeGadget(0, 10, 10, 180, 180) 
  For i = 0 To 5 
    AddGadgetItem (0, -1, "Item "+ Str(i)) 
    AddGadgetItem (0, -1, "Parent " + Str(i)) 
    OpenTreeGadgetNode(0) 
    AddGadgetItem(0, -1, "Sub Item 1") 
    AddGadgetItem(0, -1, "Sub Item 2") 
    AddGadgetItem(0, -1, "Sub Item 3") 
    AddGadgetItem(0, -1, "Sub Item 4") 
    CloseTreeGadgetNode(0) 
  Next 
  Repeat 
    event = WaitWindowEvent() 
    if eventtype() = #PB_EventType_RightClick and eventgadgetid() = 0
      pt.point\x=windowmousex() : pt\y=windowmousey() ;Get mouse coordinates.
      mapwindowpoints_(windowid(),gadgetid(0),@pt,1) ;Make coords relative to client area of tree gadget.
;Next 3 lines obtain the handle to the item under the cursor.
      tv.TV_HITTESTINFO
        tv\pt\x = pt\x : tv\pt\y = pt\y
        sendmessage_(gadgetid(0), #TVM_HITTEST, 0, tv)
;Now select the said item.
;      SendMessage_(gadgetid(0), #TVM_SELECTITEM, #TVGN_CARET, tv\hItem) 
    setgadgetstate(0,TreeGadgetItemNumber(0, tv\hItem))
    endif


  Until event = #PB_Event_CloseWindow 
EndIf 
End

Posted: Sat Nov 26, 2005 10:33 pm
by josku_x
I don't want it be cross-platform, I only do applications for Windows. I just want to make things easy, so thanks anyway.

Posted: Sat Nov 26, 2005 10:36 pm
by srod
The code above uses SetGadgetState()

Posted: Sat Nov 26, 2005 10:38 pm
by josku_x
Is there not any other way to do this? I mean your code is excellent srod, but it seems to be little complex.

Posted: Sat Nov 26, 2005 11:01 pm
by srod
The following, whilst easier, isn't perfect as you'll discover on using it! All it does is simulate a left click every time the right button is clicked.

Code: Select all

If OpenWindow(0, 0, 0, 350, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Sparkies TreeGadget - Right Click Selects") And CreateGadgetList(WindowID(0)) 
  TreeGadget(0, 10, 10, 180, 180) 
  For i = 0 To 5 
    AddGadgetItem (0, -1, "Item "+ Str(i)) 
    AddGadgetItem (0, -1, "Parent " + Str(i)) 
    OpenTreeGadgetNode(0) 
    AddGadgetItem(0, -1, "Sub Item 1") 
    AddGadgetItem(0, -1, "Sub Item 2") 
    AddGadgetItem(0, -1, "Sub Item 3") 
    AddGadgetItem(0, -1, "Sub Item 4") 
    CloseTreeGadgetNode(0) 
  Next 
  Repeat 
    event = WaitWindowEvent() 
    if eventtype() = #PB_EventType_RightClick and eventgadgetid() = 0 
      pt.point\x=windowmousex() : pt\y=windowmousey() ;Get mouse coordinates. 
      mapwindowpoints_(windowid(),gadgetid(0),@pt,1) ;Make coords relative to client area of tree gadget. 
    sendmessage_(gadgetid(0), #WM_LBUTTONDOWN, 0, pt\y<<16+pt\x)
    endif 
  Until event = #PB_Event_CloseWindow 
EndIf 
End
The problem is that if we drift away from the callback, then there is no ready built in PB command for determining which item was right-clicked within the tree gadget. This is, after all, a somewhat unusual requirement and even if the Purebasic team were to extend the functionality of the tree gadget in this way, then they would likely be using one of the methods above.

Even Sparkie's method, as clever as it is (and a method that would never have occurred to me!) still requires the use of the Win API.

Your best bet, if you want to stear away from using the API directly, would be to wrap up functions like this into a little .pbi include file which you could easily call from your own programs.

Posted: Sun Nov 27, 2005 12:33 am
by Sparkie
This is very similar to srod's code. I just replaced the mapwindowpoints_() function with native PB stuff. Other than that, I don't how to make it any easier than this. :)

I had completly forgotten about using the TreeGadgetItemNumber() for getting the item index# from it's API handle. Thanks for the reminder srod :cool:

Code: Select all

If OpenWindow(0, 0, 0, 450, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Sparkie/srod TreeGadget - Right Click Selects") And CreateGadgetList(WindowID(0)) 
  TreeGadget(1, 80, 100, 180, 180) 
  For i = 0 To 5 
    AddGadgetItem (1, -1, "Item "+ Str(i)) 
    AddGadgetItem (1, -1, "Parent " + Str(i)) 
    OpenTreeGadgetNode(1) 
    AddGadgetItem(1, -1, "Sub Item 1") 
    AddGadgetItem(1, -1, "Sub Item 2") 
    AddGadgetItem(1, -1, "Sub Item 3") 
    AddGadgetItem(1, -1, "Sub Item 4") 
    CloseTreeGadgetNode(1) 
  Next 
  Repeat 
    event = WaitWindowEvent() 
    If EventType() = #PB_EventType_RightClick And EventGadgetID() = 1 
      ;--> Fill in the mouse x/y coordinates
      tvht.TV_HITTESTINFO\pt\x = WindowMouseX() - GadgetX(1)
      tvht.TV_HITTESTINFO\pt\y = WindowMouseY() - GadgetY(1)
      ;--> Get the handle to the TreeGadget Item under mouse x/y coordinates
      hItem = SendMessage_(GadgetID(1), #TVM_HITTEST, 0, @tvht) 
      ;--> Get the Treegadget item index from the handle (hItem)
      tvItem = TreeGadgetItemNumber(1, hItem)
      ;--> Select that item
      SetGadgetState(1, tvItem) 
    EndIf 
  Until event = #PB_Event_CloseWindow 
EndIf 
End

Posted: Mon Nov 28, 2005 5:42 pm
by josku_x
Thanks! You both are great! Now my problem is solved, but I have again a problem with TreeGadget..... :oops:

Now it is, I want to have an item in the treegadget that can be modified (I mean the place where the item text is, would be editable, so users can write into them as if they were StringGadgets)

But this time it can have callback, but if it is possible without callback, please.

Thanks in advance!

(I know I am asking much questions about treeGadgets, but it is very important as my project uses them all-the-time)

And thanks again, you are great! (both of you :wink: )

Posted: Mon Nov 28, 2005 7:58 pm
by srod
Yes it is possible, but not without a callback!

viewtopic.php?t=2693&highlight=treegadget

Posted: Mon Nov 28, 2005 8:38 pm
by josku_x
Thanks.