Drag to Move/Resize Gadgets

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Drag to Move/Resize Gadgets

Post by IdeasVacuum »

The following code allows gadgets to be dragged around the client area of the parent Window. I need to restrict that movement so that the gadgets only move along X. That works fine.

However, I also need to restrict the resize of the gadgets such that they can only be stretched along X. The code adds the #WS_SIZEBOX flag, and this gives the ability to resize the sample gadget (does not work with all gadget types, but StringGadget is a good one for my project). It has two issues though:

1) It adds an ugly border - I need to keep the gadget as-is, no border.
2) It allows the gadget to be resized in Y, I need to restrict resize to X only.

So, I think this is basically the wrong way to go about it, although it gets really close to what is needed.......

Code: Select all

Enumeration
#Win
#Gdt
EndEnumeration

Structure SubClassGadget
        hWnd.i
  oldWndProc.i
   mouseDown.i
   mouseOffX.i
   mouseOffY.i
EndStructure

Global NewList gadgets.SubClassGadget()

Procedure GadgetCallback(hWnd,Msg,wParam,lParam)
;----------------------------------------------

  Select Msg

             Case #WM_LBUTTONDOWN

                      ForEach gadgets()

                            If gadgets()\hWnd = hWnd

                                     gadgets()\mouseOffX = lParam & $FFFF
                                     gadgets()\mouseOffY = (lParam>>16) & $FFFF
                                     gadgets()\mouseDown = 1
                                     SetFocus_(hWnd)

                                     SetCursor_(LoadCursor_(0,#IDC_SIZEALL))

                                     ProcedureReturn 0
                            EndIf
                      Next

             Case #WM_SIZING

                      If wParam & #MK_LBUTTON

                              ForEach gadgets()

                                    If gadgets()\hWnd = hWnd And gadgets()\mouseDown

                                                SetCursor_(LoadCursor_(0,#IDC_SIZEWE))

                                              ResizeGadget(GetWindowLongPtr_(hWnd,#GWL_ID), #PB_Ignore, #PB_Ignore, #PB_Ignore, 30)

                                               SetCursor_(LoadCursor_(0,#IDC_SIZEALL))
                                              SetCapture_(hWnd)

                                              ProcedureReturn 0
                                    EndIf
                              Next

                      ElseIf wParam = 0

                              SetCursor_(LoadCursor_(0,#IDC_SIZEALL))
                      EndIf

             Case #WM_MOUSEMOVE

                      If wParam & #MK_LBUTTON

                              ForEach gadgets()

                                    If gadgets()\hWnd = hWnd And gadgets()\mouseDown

                                              GetCursorPos_(p.POINT)
                                              MapWindowPoints_(0,WindowID(#Win),@p,1)
                                              x = p\x - gadgets()\mouseOffX
                                              y = p\y - gadgets()\mouseOffY
                                              If x < 0 : x = 0 : EndIf
                                              If y < 0 : y = 0 : EndIf
                                              GetClientRect_(hWnd,rect.RECT)
                                              GetClientRect_(WindowID(#Win),rect2.RECT)
                                              If x > rect2\right  - rect\right  : x = rect2\right  - rect\right  : EndIf
                                              If y > rect2\bottom - rect\bottom : y = rect2\bottom - rect\bottom : EndIf
                                              ResizeGadget(GetWindowLongPtr_(hWnd,#GWL_ID), x, #PB_Ignore, #PB_Ignore, #PB_Ignore)

                                               SetCursor_(LoadCursor_(0,#IDC_SIZEALL))
                                              SetCapture_(hWnd)

                                              ProcedureReturn 0
                                    EndIf
                              Next

                      ElseIf wParam = 0

                              SetCursor_(LoadCursor_(0,#IDC_SIZEALL))
                      EndIf

             Case #WM_LBUTTONUP

                      ForEach gadgets()

                             If gadgets()\hWnd = hWnd

                                      gadgets()\mouseDown = 0
                             EndIf
                      Next

                       SetCursor_(LoadCursor_(0,#IDC_SIZEALL))
                      SetCapture_(0)

                      ProcedureReturn 0

             Case #WM_LBUTTONDBLCLK

                      ForEach gadgets()

                             If gadgets()\hWnd = hWnd

                                      FreeGadget(GetWindowLongPtr_(hWnd,#GWL_ID))
                             EndIf
                      Next

                      ProcedureReturn 0

  EndSelect

  ForEach gadgets()

           If gadgets()\hWnd = hWnd

                     ProcedureReturn CallWindowProc_(gadgets()\oldWndProc,hWnd,Msg,wParam,lParam)
           EndIf
  Next

EndProcedure

Procedure AddGadget(hGadget)
;---------------------------

          If IsGadget(hGadget)

                    hWnd = GadgetID(hGadget) ; for #PB_Any
          Else
                    hWnd = hGadget
          EndIf

          If hWnd

                    LastElement(gadgets())
                     AddElement(gadgets())

                       gadgets()\hWnd = hWnd
                 gadgets()\oldWndProc = SetWindowLongPtr_(hWnd,#GWL_WNDPROC,@GadgetCallback())
          EndIf

          ProcedureReturn hGadget

EndProcedure

If OpenWindow(#Win, 0, 0, 500, 300, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

    SetWindowColor(#Win, RGB(100,60,60))


     AddGadget(StringGadget(#Gdt, 20, 20, 100, 30, "Test", #PB_String_BorderLess|#PB_String_ReadOnly|#PB_Text_Center|#WS_SIZEBOX))
    ;AddGadget(ContainerGadget(#Gdt, 20, 20, 100, 30, #WS_SIZEBOX))
    ;AddGadget(CanvasGadget(#Gdt, 20, 20, 100, 30, #WS_SIZEBOX))
             SetGadgetColor(#Gdt,#PB_Gadget_BackColor,RGB(175,255,175))


             Repeat

                   iEvent = WaitWindowEvent(1)

             Until iEvent = #PB_Event_CloseWindow
EndIf

End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Drag to Move/Resize Gadgets

Post by chi »

No ugly border and horizontal resize only (change #HTBOTTOMRIGHT to #HTRIGHT) ;)

Code: Select all

Procedure Resize()
  ResizeImage(0, GadgetWidth(3), GadgetHeight(3))
  StartDrawing(ImageOutput(0))
    Box(0,0,OutputWidth(), OutputHeight(), RGB(64,64,64))
    Circle(150,150,100, RGB(255,0,0))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(10,10, "ImageGadget inside Container")
  StopDrawing()
  SetGadgetState(4, ImageID(0))
EndProcedure

OpenWindow(0, 0, 0, 420, 300, "designer", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
SetWindowColor(0, RGB(37,37,38))

ButtonGadget(0, 140, 90, 140, 30, "move = LMB down")
SetWindowLongPtr_(GadgetID(0), #GWL_STYLE, GetWindowLongPtr_(GadgetID(0), #GWL_STYLE) | #WS_CLIPSIBLINGS)

StringGadget(1, 40, 70, 140, 30, "resize = Shift + LMB down")
SetWindowLongPtr_(GadgetID(1), #GWL_STYLE, GetWindowLongPtr_(GadgetID(1), #GWL_STYLE) | #WS_CLIPSIBLINGS)

ContainerGadget(3, 40, 115, 210, 100, #PB_Container_BorderLess)
  SetWindowLongPtr_(GadgetID(3), #GWL_STYLE, GetWindowLongPtr_(GadgetID(3), #GWL_STYLE) | #WS_CLIPSIBLINGS)
  CreateImage(0, GadgetWidth(3), GadgetHeight(3), 24, RGB(64,64,64))
  ImageGadget(4, 0, 0, GadgetWidth(3), GadgetHeight(3), 0)
  DisableGadget(4, #True)
  Resize()
  BindGadgetEvent(3, @Resize())  
CloseGadgetList()

Repeat
  event = WaitWindowEvent()
  Select event
      
    Case #WM_LBUTTONDOWN
      ReleaseCapture_()
      GetCursorPos_(cursorpos.POINT)
      gadget = WindowFromPoint_(PeekQ(cursorpos))
      If GetAsyncKeyState_(#VK_SHIFT) & 32768
        SendMessage_(gadget, #WM_NCLBUTTONDOWN, #HTBOTTOMRIGHT, 0) ; #HTRIGHT = stretch width only
      Else
        SendMessage_(gadget, #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
      EndIf
      
  EndSelect
Until event = #PB_Event_CloseWindow
Last edited by chi on Fri Feb 21, 2014 2:46 pm, edited 1 time in total.
Et cetera is my worst enemy
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Drag to Move/Resize Gadgets

Post by IdeasVacuum »

Hi Chi ~ erm, code crashes on launch? :?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Drag to Move/Resize Gadgets

Post by Thunder93 »

Resize() command is in the wrong place. At least needs to be moved one down.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Drag to Move/Resize Gadgets

Post by chi »

Strange! No problems with PB 5.21 LTS (x64 + x86). Code was written pretty fast, so there might be some other oddities ;)

Edit: code updated
Et cetera is my worst enemy
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Drag to Move/Resize Gadgets

Post by Thunder93 »

chi wrote:Strange! No problems with PB 5.21 LTS (x64 + x86). Code was written pretty fast, so there might be some other oddities ;)
Might be a cache thing... Because the code that you originally posted wouldn't of worked in any version of PB. Resize() has dependencies. ImageGadget(4, is one of them. So doing the Resize() before that gadget creation, Resize() can't go very far in the process.
Last edited by Thunder93 on Fri Feb 21, 2014 2:58 pm, edited 1 time in total.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Drag to Move/Resize Gadgets

Post by IdeasVacuum »

Ah, that's better :)

Resize is not restricted to X only though, and I have to find a better input than Shift + LMB (it should just work, resize if mouse cursor is near the edge of the gadget, as per my example). I'm trying to workout how Falsam's code works for MindMap.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Drag to Move/Resize Gadgets

Post by Thunder93 »

You had the following top-most in the Resize() function

Code: Select all

ResizeGadget(4, #PB_Ignore, #PB_Ignore, GadgetWidth(3), GadgetHeight(3))
So having the Resize() command before

Code: Select all

ImageGadget(4, 0, 0, GadgetWidth(3), GadgetHeight(3), ImageID(0))
would cause issues.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Drag to Move/Resize Gadgets

Post by chi »

Resize is not restricted to X only though
Just change SendMessage_(gadget, #WM_NCLBUTTONDOWN, #HTBOTTOMRIGHT, 0) to #HTRIGHT, #HTLEFT or whatever #HT? you like ^^
Might be a cache thing...
Never heard of that ;). But i have a problem with autocompletion (with-endwith) too, since last setup... who knows

Edit: After a restart my old code throws an error on ResizeGadget(4... WTF? :oops:
Et cetera is my worst enemy
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Drag to Move/Resize Gadgets

Post by Thunder93 »

lol
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Drag to Move/Resize Gadgets

Post by IdeasVacuum »

Actually, having removed half the code (it handles image gadget/button gadget, which I do not need) and using the #HTRIGHT flag as noted in the code, things look very encouraging! I think I should be able to use the gadget rect to determine whether the User is moving the gadget or stretching it. Thanks for the help :wink:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Drag to Move/Resize Gadgets

Post by chi »

np :D
Et cetera is my worst enemy
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Drag to Move/Resize Gadgets

Post by electrochrisso »

Great stuff Chi. :)
PureBasic! Purely the best 8)
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5502
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Drag to Move/Resize Gadgets

Post by Kwai chang caine »

Cool !!!
Thanks CHI 8)
ImageThe happiness is a road...
Not a destination
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Drag to Move/Resize Gadgets

Post by chi »

You're welcome :)
Et cetera is my worst enemy
Post Reply