drwaing a box while dragging mouse

Just starting out? Need help? Post your questions and find answers here.
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

drwaing a box while dragging mouse

Post by localmotion34 »

how do you get a box drawn after you press and hold the left mouse button down, and then drag the mouse. what i mean is like in visual designer when you click and drag a gadget, a box is drawn that follows the mouse, and then the gadget is repositioned to the new coordinates of the box. how do you do that?

Code: Select all

!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Post by Danilo »

Thats the base:

Code: Select all

; 
; by Danilo, 24.11.2003 - german forum 
; 
Procedure OnMouseSelection(x,y,width,height) 
  Debug "-----" 
  Debug "Selected:" 
  Debug "X     : "+Str(x) 
  Debug "Y     : "+Str(y) 
  Debug "Width : "+Str(width) 
  Debug "Height: "+Str(height) 
EndProcedure 


Procedure DrawMouseSelector(hWnd) 
  Shared WindowProc_MouseSelectStartX, WindowProc_MouseSelectLastX 
  Shared WindowProc_MouseSelectStartY, WindowProc_MouseSelectLastY 
  Shared WindowProc_MouseSelectRect.RECT 

  If WindowProc_MouseSelectStartX > WindowProc_MouseSelectLastX 
    WindowProc_MouseSelectRect\left   = WindowProc_MouseSelectLastX 
    WindowProc_MouseSelectRect\right  = WindowProc_MouseSelectStartX 
  Else 
    WindowProc_MouseSelectRect\left   = WindowProc_MouseSelectStartX 
    WindowProc_MouseSelectRect\right  = WindowProc_MouseSelectLastX 
  EndIf 
  If WindowProc_MouseSelectStartY > WindowProc_MouseSelectLastY 
    WindowProc_MouseSelectRect\top    = WindowProc_MouseSelectLastY 
    WindowProc_MouseSelectRect\bottom = WindowProc_MouseSelectStartY 
  Else 
    WindowProc_MouseSelectRect\top    = WindowProc_MouseSelectStartY 
    WindowProc_MouseSelectRect\bottom = WindowProc_MouseSelectLastY 
  EndIf

  hDC = GetDC_(hWnd)
    DrawFocusRect_(hDC,@WindowProc_MouseSelectRect)
  ReleaseDC_(hWnd,hDC)
  ;UpdateWindow_(hWnd) ; Win9x fix?
EndProcedure


Procedure WindowProc(hWnd,Msg,wParam,lParam) 
  Shared WindowProc_MouseSelect 
  Shared WindowProc_MouseSelectStartX, WindowProc_MouseSelectLastX 
  Shared WindowProc_MouseSelectStartY, WindowProc_MouseSelectLastY 
  Shared WindowProc_MouseSelectRect.RECT 

  Select Msg 
    Case #WM_LBUTTONDOWN 
      WindowProc_MouseSelect  = 1 
      WindowProc_MouseSelectStartX = lParam&$FFFF 
      WindowProc_MouseSelectStartY = (lParam>>16)&$FFFF 
      GetClientRect_(hWnd,winrect.RECT) 
      MapWindowPoints_(hWnd,0,winrect,2) 
      ClipCursor_(winrect)
    Case #WM_LBUTTONUP 
      If WindowProc_MouseSelect > 1 
        DrawMouseSelector(hWnd)
        If WindowProc_MouseSelectRect\left <> WindowProc_MouseSelectRect\right And WindowProc_MouseSelectRect\top <> WindowProc_MouseSelectRect\bottom 
          OnMouseSelection(WindowProc_MouseSelectRect\left,WindowProc_MouseSelectRect\top,WindowProc_MouseSelectRect\right-WindowProc_MouseSelectRect\left,WindowProc_MouseSelectRect\bottom-WindowProc_MouseSelectRect\top)
          SetCapture_(0)
        EndIf 
      EndIf 
      ClipCursor_(0) 
      WindowProc_MouseSelect = 0 
    Case #WM_MOUSEMOVE 
      If WindowProc_MouseSelect > 0 And wParam & #MK_LBUTTON 
        If WindowProc_MouseSelect > 1
          DrawMouseSelector(hWnd)
        Else
          WindowProc_MouseSelect + 1
        EndIf
        WindowProc_MouseSelectLastX = lParam&$FFFF 
        WindowProc_MouseSelectLastY = (lParam>>16)&$FFFF 
        DrawMouseSelector(hWnd)
        SetCapture_(hWnd)
      EndIf 
  EndSelect 
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 



OpenWindow(0,0,0,400,400,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Mega Mouse Selector") 
  SetWindowCallback(@WindowProc()) 
HideWindow(0,0) 

Repeat 
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow 
      End 
  EndSelect 
ForEver
And here a modified version, a Photoshop clone. :lol:

Code: Select all

; 
; by Danilo, 24.11.2003 - german forum 
; 
;   - modified to a full blown paint program, 
;     by Danilo - 09.06.2004, english forum ;) 
; 
Procedure OnMouseSelection(x,y,width,height) 
  Shared Current_ActiveColor 

  ;Debug "-----" 
  ;Debug "Selected:" 
  ;Debug "X     : "+Str(x) 
  ;Debug "Y     : "+Str(y) 
  ;Debug "Width : "+Str(width) 
  ;Debug "Height: "+Str(height) 
  
  UseImage(1) 
  If StartDrawing(ImageOutput()) 
    Box(x,y,width,height,Current_ActiveColor) 
    StopDrawing() 
  EndIf 
  SetGadgetState(1,ImageID()) ; update ImageGadget 
EndProcedure 


Procedure DrawMouseSelector(hWnd) 
  Shared WindowProc_MouseSelectStartX, WindowProc_MouseSelectLastX 
  Shared WindowProc_MouseSelectStartY, WindowProc_MouseSelectLastY 
  Shared WindowProc_MouseSelectRect.RECT 

  If WindowProc_MouseSelectStartX > WindowProc_MouseSelectLastX 
    WindowProc_MouseSelectRect\left   = WindowProc_MouseSelectLastX 
    WindowProc_MouseSelectRect\right  = WindowProc_MouseSelectStartX 
  Else 
    WindowProc_MouseSelectRect\left   = WindowProc_MouseSelectStartX 
    WindowProc_MouseSelectRect\right  = WindowProc_MouseSelectLastX 
  EndIf 
  If WindowProc_MouseSelectStartY > WindowProc_MouseSelectLastY 
    WindowProc_MouseSelectRect\top    = WindowProc_MouseSelectLastY 
    WindowProc_MouseSelectRect\bottom = WindowProc_MouseSelectStartY 
  Else 
    WindowProc_MouseSelectRect\top    = WindowProc_MouseSelectStartY 
    WindowProc_MouseSelectRect\bottom = WindowProc_MouseSelectLastY 
  EndIf 

  hDC = GetDC_(hWnd) 
    DrawFocusRect_(hDC,@WindowProc_MouseSelectRect) 
  ReleaseDC_(hWnd,hDC) 
  ;UpdateWindow_(hWnd) ; Win9x fix? 
EndProcedure 


Procedure WindowProc(hWnd,Msg,wParam,lParam) 
  Shared WindowProc_MouseSelect 
  Shared WindowProc_MouseSelectStartX, WindowProc_MouseSelectLastX 
  Shared WindowProc_MouseSelectStartY, WindowProc_MouseSelectLastY 
  Shared WindowProc_MouseSelectRect.RECT 

  Select Msg 
    Case #WM_LBUTTONDOWN 
      MouseX = lParam&$FFFF 
      MouseY = (lParam>>16)&$FFFF 
      If MouseX =< 600 And MouseY <= 480 
        WindowProc_MouseSelect  = 1 
        WindowProc_MouseSelectStartX = MouseX 
        WindowProc_MouseSelectStartY = MouseY 
        GetClientRect_(GadgetID(1),winrect.RECT) 
        MapWindowPoints_(hWnd,0,winrect,2) 
        ClipCursor_(winrect) 
      EndIf 
    Case #WM_LBUTTONUP 
      If WindowProc_MouseSelect > 1 
        DrawMouseSelector(hWnd) 
        If WindowProc_MouseSelectRect\left <> WindowProc_MouseSelectRect\right And WindowProc_MouseSelectRect\top <> WindowProc_MouseSelectRect\bottom 
          OnMouseSelection(WindowProc_MouseSelectRect\left,WindowProc_MouseSelectRect\top,WindowProc_MouseSelectRect\right-WindowProc_MouseSelectRect\left,WindowProc_MouseSelectRect\bottom-WindowProc_MouseSelectRect\top) 
          SetCapture_(0) 
        EndIf 
      EndIf 
      ClipCursor_(0) 
      WindowProc_MouseSelect = 0 
    Case #WM_MOUSEMOVE 
      If WindowProc_MouseSelect > 0 And wParam & #MK_LBUTTON 
        If WindowProc_MouseSelect > 1 
          DrawMouseSelector(hWnd) 
        Else 
          WindowProc_MouseSelect + 1 
        EndIf 
        WindowProc_MouseSelectLastX = lParam&$FFFF 
        WindowProc_MouseSelectLastY = (lParam>>16)&$FFFF 
        DrawMouseSelector(hWnd) 
        SetCapture_(hWnd) 
      EndIf 
  EndSelect 
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 



OpenWindow(0,0,0,640,500,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Mega Mouse Selector (modified)") 
  SetWindowCallback(@WindowProc()) 
  CreateGadgetList(WindowID()) 
  ImageGadget(1,0,0,600,480,CreateImage(1,600,480)) 
  
  RandomSeed(666) 
  
  For a = 0 To 20 
    CreateImage(a+2,40,24) 
    StartDrawing(ImageOutput()) 
      col = Random($FFFFFF) 
      Box(0,0,40,24,col) 
      If a = 0 : Current_ActiveColor = col : EndIf 
    StopDrawing() 
    ButtonImageGadget(a+2,600,a*24,40,24,ImageID()) 
  Next a 
  
  CreateImage(25,40,18) 
  If StartDrawing(ImageOutput()) 
    Box(1,1,38,16,Current_ActiveColor) 
    StopDrawing() 
  EndIf 
  TextGadget(24,10,485,100,15,"Active color:") 
  ImageGadget(25,120,482,40,18,ImageID()) 

HideWindow(0,0) 

Repeat 
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow 
      End 
    Case #PB_Event_Gadget 
      gadget = EventGadgetID() 
      If gadget >= 2 And gadget <= 22 

        UseImage(gadget) ; get new color 
        If StartDrawing(ImageOutput()) 
          Current_ActiveColor = Point(5,5) 
          StopDrawing() 
        EndIf 

        UseImage(25) ; update current color gadget 
        If StartDrawing(ImageOutput()) 
          Box(1,1,38,16,Current_ActiveColor) 
          StopDrawing() 
        EndIf 
        SetGadgetState(25,ImageID()) 

      EndIf 
  EndSelect 
ForEver
cya,
...Danilo
...:-=< http://codedan.net/work >=-:...
-= FaceBook.com/DaniloKrahn =-
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

Post by localmotion34 »

what i was asking for is this: open visual designer and draw a button gadget on the window. now move the mouse over the buttongadget. press the left button down and a rectange is drawn around the buttongadget. keep holding the left button down and drag the mouse. the rectangle follows the mouse around the window. release the button and the button gadget moves to where the rectange was when the mouse button was released. thats what i need to know how to do.

Code: Select all

!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

That's nice Danilo.

I spent hours coding a similar routine using XORed boxes etc. Didn't realise you could do it that way.
I think the word I'm looking for rhymes with rollocks! Ah well, you live and learn.
Thanks for sharing.
I may look like a mule, but I'm not a complete ass.
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

Post by localmotion34 »

any idea at all? i mean how did they do it for visual designer? click on a gadget, a box is drawn, drag the mouse and the drawn box follows. release the mouse, and the gadget moves to where the box is when the mouse was released. someone has to know.

Code: Select all

!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6172
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

although often not seen as the 'right' way, you can draw directly on a window, so...

1. click on the gadget -> grab the click, retrieve the coordinates of that gadget
2. draw in xor mode a box
3. when the mouse moves, draw the box again (erasing it) and draw it again at the new mouse pos (showing it again)
4. when mouse button released draw the box one more time (erasing it again) then move the gadget to the new spot

i think that's all... :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB - upgrade incoming...)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Post by Danilo »

localmotion34 wrote:someone has to know.
Are you requesting that we should write your code, or did you
try yourself ??
If you tried yourself, its an good idea to show your current code.

Look how my above selector-examples work, look what messages
i catch, look in PSDK/MSDN what WM_MOUSEMOVE, WM_LBUTTONDOWN,
WM_LBUTTONUP etc. do, read a book about WinAPI, ...

...and look at this small'n dirty example:

Code: Select all

; 
; simple gadget mover example 
; 
; by Danilo, 10.06.2004 - english forum 
; (coded for lazy localmotion34) 
; 
Structure MouseBtnMover 
  WndProc.l 
  hGadget.l 
  Gadget.l  
EndStructure 

NewList oldCallbacks.MouseBtnMover() 

Global MouseBtnDown   , hMouseBtnDown 
Global MouseBtnDownX  , MouseBtnDownY 
Global MouseMoveCursor, rect.RECT 
Global MoveMode 


Procedure DrawSelectorBox() 
  If StartDrawing(WindowOutput()) 
    DrawingMode(2|4) 
      Box(rect\left-1,rect\Top-1,rect\right+2,rect\bottom+2) 
      Box(rect\left-2,rect\Top-2,rect\right+4,rect\bottom+4) 
    StopDrawing() 
  EndIf 
EndProcedure 


Procedure SetCurrentRect(hWnd) 
  GetWindowRect_(hWnd,@rect) 
  MapWindowPoints_(0,WindowID(0),@rect,2) 
  rect\right  - rect\left 
  rect\bottom - rect\top 
EndProcedure 


Procedure _MoveCallback(hWnd,Msg,wParam,lParam) 
  If MoveMode 
    SetCursor_(MouseMoveCursor) 
    If Msg = #WM_LBUTTONDOWN Or Msg = #WM_LBUTTONDBLCLK 
      MouseBtnDownX = lParam&$FFFF 
      MouseBtnDownY = (lParam>>16)&$FFFF 
      MouseBtnDown  = #TRUE 
      hMouseBtnDown = hWnd 
      SetCurrentRect(hWnd) 
      DrawSelectorBox() 
      GetClientRect_(WindowID(0),ClipRect.RECT) 
      MapWindowPoints_(WindowID(0),0,@ClipRect,2) 
      ClipCursor_(@ClipRect) 
      SetCapture_(hWnd) 
      ProcedureReturn 0 
    ElseIf Msg = #WM_LBUTTONUP  
      MouseBtnDown  = #FALSE 
      DrawSelectorBox() 
      
      ForEach oldCallbacks() 
        If oldCallbacks()\hGadget = hWnd 
          ResizeGadget(oldCallbacks()\Gadget,rect\left,rect\top,-1,-1) 
        EndIf 
      Next 
      ;MoveWindow_(hWnd,rect\left,rect\top,rect\right,rect\bottom,1) 
      
      SetCapture_(0) 
      ClipCursor_(0) 
      ;InvalidateRect_(WindowID(0),0,1) 
      ;UpdateWindow_(WindowID(0)) 
      ProcedureReturn 0 
    ElseIf Msg = #WM_MOUSEMOVE 
      If MouseBtnDown 
        MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
        MouseOffsetY.w = (lParam>>16)&$FFFF - MouseBtnDownY 
        DrawSelectorBox() 
        rect\left + MouseOffsetX 
        rect\top  + MouseOffsetY 
        MouseBtnDownX + MouseOffsetX 
        MouseBtnDownY + MouseOffsetY 
        DrawSelectorBox() 
      EndIf 
      ProcedureReturn 0 
    EndIf 
  EndIf 

  ForEach oldCallbacks() 
    If oldCallbacks()\hGadget = hWnd 
      ProcedureReturn CallWindowProc_(oldCallbacks()\WndProc,Hwnd,Msg,wParam,lParam) 
    EndIf 
  Next 
EndProcedure 


Procedure SetMoveCallback(gadget) 
  AddElement(oldCallbacks()) 
  oldCallbacks()\WndProc = SetWindowLong_(GadgetID(gadget),#GWL_WNDPROC,@_MoveCallback()) 
  oldCallbacks()\hGadget = GadgetID(gadget) 
  oldCallbacks()\Gadget  = gadget 
EndProcedure 




MouseMoveCursor = LoadCursor_(0,#IDC_SIZEALL) 

OpenWindow(0,150,150,500,500,#PB_Window_SystemMenu|#PB_Window_Invisible|#PB_Window_SizeGadget,"move button") 
  CreateGadgetList(WindowID()) 

  CheckBoxGadget(0,10,5,100,15,"Move Mode") 

  ButtonGadget(1, 10,25,100,30,"Button 1") 
  ButtonGadget(2,120,25,100,30,"Button 2") 
  ListViewGadget(3,10,65,100,150) 
    For a = 1 To 10 : AddGadgetItem(3,-1,"ListView Item "+Str(a)) : Next a 
  ComboBoxGadget(4,120,65,100,200) 
    For a = 1 To 10 : AddGadgetItem(4,-1,"ComboBox Item "+Str(a)) : Next a 
  StringGadget(5,120,95,100,20,"StringGadget") 
  ExplorerTreeGadget(6,10,225,210,200,"c:") 
  ProgressBarGadget(7,120,130,100,20,0,100) 
    SetGadgetState(7,30) 
  TrackBarGadget(8,120,165,100,20,0,100)
  SpinGadget(9,120,195,100,20,0,100)
    SetGadgetText(9,"SpinGadget")
  
  For a = 1 To 9 ; Add MoveCallback to all gadgets (except gadget 0) 
    SetMoveCallback(a) 
  Next a 

HideWindow(0,0) 

Repeat 
  Select WaitWindowEvent() 
    Case #PB_EVENT_CLOSEWINDOW 
      Break 
    Case #PB_EventGadget 
      Select EventGadgetID() 
        Case 0 ; Move Mode 
          MoveMode = GetGadgetState(0) 
      EndSelect 
  EndSelect 
ForEver 

You dont learn anything if you use this code for your own project.

You have to *understand* the main thing here:
how to handle mouse events (WM_MOUSEMOVE,WM_LBUTTONDOWN/UP,...)
with WinAPI in a callback.
If you understood how it works, why it works and what this messages
do... you can code such things and much more yourself.


And finally an old example of moving an image gadget with the mousecursor:

Code: Select all

;
; by Danilo, 23.10.2003 - german forum
;
#IMAGE = 1

Procedure WindowProc(hWnd,Msg,wParam,lParam)
  Shared WindowProc_ImageInMove

  Select Msg
    Case #WM_LBUTTONDOWN
      WindowProc_ImageInMove = 1
    Case #WM_LBUTTONUP
      WindowProc_ImageInMove = 0
    Case #WM_MOUSEMOVE
      If ChildWindowFromPoint_(hWnd,lParam & $FFFF,(lParam>>16) & $FFFF) = GadgetID(#IMAGE) And wParam&#MK_LBUTTON And WindowProc_ImageInMove
        ResizeGadget(#IMAGE,(lParam & $FFFF)-GadgetWidth(#IMAGE)/2,((lParam>>16)&$FFFF)-GadgetHeight(#IMAGE)/2,-1,-1)
        UpdateWindow_(hWnd) ; Win9x fix
      Else
        WindowProc_ImageInMove = 0
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

OpenWindow(0,0,0,400,400,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"image") 
  SetWindowCallback(@WindowProc())
  CreateGadgetList(WindowID())
  
  If CreateImage(#IMAGE,100,100)=0
    MessageRequester("ERROR","Cant create image",#MB_ICONERROR)
    End
  EndIf

  StartDrawing(ImageOutput())
    f.f = $FF / ImageHeight()
    For a = 0 To ImageHeight()
      Line(0,a,ImageWidth(),0,RGB($FF,f*a,$00))
    Next a
  StopDrawing()

  ImageGadget(#IMAGE,0,0,0,0,UseImage(#IMAGE))

HideWindow(0,0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver
cya,
...Danilo
...:-=< http://codedan.net/work >=-:...
-= FaceBook.com/DaniloKrahn =-
zikitrake
Addict
Addict
Posts: 878
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Post by zikitrake »

Hi,

In the code of above (From Danilo)

Code: Select all

; 
; simple gadget mover example 
; 
; by Danilo, 10.06.2004 - english forum 
; (coded for lazy localmotion34) 
; 
Structure MouseBtnMover 
  WndProc.l 
  hGadget.l 
  Gadget.l  
EndStructure 

NewList oldCallbacks.MouseBtnMover()
.
.
.
if I change the line ComboBoxGadget(4,120,65,100,200) to ComboBoxGadget(4,120,65,100,200,#PB_ComboBox_Editable), I can't drag (move) this gadget.

Can someone help me? Thank you
PB 6.21 beta, PureVision User
Post Reply