Painting on an imagegadget with the mouse using Plot()

Just starting out? Need help? Post your questions and find answers here.
Hydrate
Enthusiast
Enthusiast
Posts: 436
Joined: Mon May 16, 2005 9:37 pm
Contact:

Painting on an imagegadget with the mouse using Plot()

Post by Hydrate »

Im trying to paint on an imagegadget (by painting to the image) using the plot command with the mouse. My problem is that even if I put this command in the Callback, or the eventloop of my program when I move the mouse too quickly it misses bits. This suggests to me that the program is not picking up the mouse moving as fast as it is, how can I do this?

The basic function is if LeftMouseDown them a variable is set to true, if that is true it draws.. Then if LeftMouseUp its set to false again.

Any ideas?
.::Image::.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Use a line instead of a point.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Try capturing the mouse input as soon as the button is clicked. Use SetCapture_(). Don't forget to release the capture on mouse up though!
I may look like a mule, but I'm not a complete ass.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Won't help, he needs to use lines between the last point and the current one.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

You may try this:

Code: Select all

Global lpPrevFunc

Procedure StaticProc(hWnd,uMsg,wParam,lParam)
	Static MTX,MTY
	
    Select uMsg
		Case #WM_LBUTTONDOWN
		MX = lParam & $FFFF : MY = lParam  >> 16		
		MTX = MX : MTY = MY

		StartDrawing(ImageOutput(0))
		Plot(MX,MY,#White)
		StopDrawing()
		
		Case #WM_MOUSEMOVE			
		If wParam & #MK_LBUTTON
			GetCursorPos_(cpt.POINT)			
			ScreenToClient_(hWnd,cpt)
		
			MX = cpt\x : MY = cpt\y
						
			StartDrawing(ImageOutput(0))
			LineXY(MTX,MTY,MX,MY,#White)
			StopDrawing()
			
			MTX = MX : MTY = MY
			
			SetGadgetState(0,ImageID(0))
			
			SetCapture_(hWnd)
		EndIf
		
		Case #WM_LBUTTONUP
		ReleaseCapture_()
    EndSelect
     
    ProcedureReturn CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
EndProcedure

CreateImage(0,300,220)
StartDrawing(ImageOutput(0))
Box(0,0,310,230,#Gray)
StopDrawing()

OpenWindow(0,0,0,320,240,"PurePaint",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ImageGadget(0,10,10,0,0,ImageID(0),0)

lpPrevFunc = SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@StaticProc())

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
[edit]
Some important information:

- You need to call SetCapture_() in order to still recieve the #WM_MOUSEMOVE message when moving the mouse out of the client area respectivley if it gets negative.

- You may wounder why SetCapture_() is called constantly instead just once for #WM_LBUTTONDOWN. I tested this, it doesn't work. It needs to be called constantly while moving the mouse.

- Only the Y-Coordinate recieved from #WM_MOUSEMOVE can get negative, not X-Coordinate. If it gets smaller then NULL it becomes a value of $FFFF. So I use GetCursorPos_() / ScreenToClient_() to avoid this.
Last edited by Fluid Byte on Fri Apr 11, 2008 6:54 pm, edited 1 time in total.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

@Fluid: I don't know why, but your example almost locks one core of my processor :?
Windows 7 & PureBasic 4.4
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Oops! :oops:

Sorry mate, just replace WindowEvent() with WaitWindowEvent(). :)
Last edited by Fluid Byte on Tue Apr 21, 2009 12:07 am, edited 1 time in total.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

Fluid Byte wrote:Oops! Image

Sorry mate, just replace WindowEvent() with WaitWindowEvent(). Image
Ahh, didn't see that :lol:
Windows 7 & PureBasic 4.4
Hydrate
Enthusiast
Enthusiast
Posts: 436
Joined: Mon May 16, 2005 9:37 pm
Contact:

Post by Hydrate »

Using lines instead works fantastically, thank you very much.
.::Image::.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Fluid Byte wrote:- You may wounder why SetCapture_() is called constantly instead just once for #WM_LBUTTONDOWN. I tested this, it doesn't work. It needs to be called constantly while moving the mouse.
It is because of your blanket call to 'CallWindowProc_()' etc. You should really capture the mouse once only in this kind of situation :

Code: Select all

 
Global lpPrevFunc 

Procedure StaticProc(hWnd,uMsg,wParam,lParam) 
   Static MTX,MTY 
    
    Select uMsg 
      Case #WM_LBUTTONDOWN 
      MX = lParam & $FFFF : MY = lParam  >> 16       
      MTX = MX : MTY = MY 

      StartDrawing(ImageOutput(0)) 
      Plot(MX,MY,#White) 
      StopDrawing() 
      result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam) 
      SetCapture_(hWnd) 
       
      Case #WM_MOUSEMOVE          
      If wParam & #MK_LBUTTON 
         GetCursorPos_(cpt.POINT)          
         ScreenToClient_(hWnd,cpt) 
       
         MX = cpt\x : MY = cpt\y 
                   
         StartDrawing(ImageOutput(0)) 
         LineXY(MTX,MTY,MX,MY,#White) 
         StopDrawing() 
          
         MTX = MX : MTY = MY 
          
         SetGadgetState(0,ImageID(0)) 
      Else
        result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam) 
      EndIf 
       
      Case #WM_LBUTTONUP 
      ReleaseCapture_() 
      result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam) 

      Default 
        result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam) 

    EndSelect 
      
    ProcedureReturn result
EndProcedure 

CreateImage(0,300,220) 
StartDrawing(ImageOutput(0)) 
Box(0,0,310,230,#Gray) 
StopDrawing() 

OpenWindow(0,0,0,320,240,"PurePaint",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
CreateGadgetList(WindowID(0)) 
ImageGadget(0,10,10,0,0,ImageID(0),0) 

lpPrevFunc = SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@StaticProc()) 

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend 
I may look like a mule, but I'm not a complete ass.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Yeah, I always forget to return from procedure. Had a similar issue a while ago where an OD ListView gadget still was showing the focus rect because I didn't returned from the #WM_DRAWITEM message. Keept me busy for at least for two hours.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Post Reply