Page 1 of 1
Painting on an imagegadget with the mouse using Plot()
Posted: Fri Apr 11, 2008 2:22 pm
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?
Posted: Fri Apr 11, 2008 2:29 pm
by Trond
Use a line instead of a point.
Posted: Fri Apr 11, 2008 2:37 pm
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!
Posted: Fri Apr 11, 2008 3:56 pm
by Trond
Won't help, he needs to use lines between the last point and the current one.
Posted: Fri Apr 11, 2008 4:39 pm
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.
Posted: Fri Apr 11, 2008 5:05 pm
by milan1612
@Fluid: I don't know why, but your example almost locks one core of my processor

Posted: Fri Apr 11, 2008 5:06 pm
by Fluid Byte
Oops!
Sorry mate, just replace WindowEvent() with
WaitWindowEvent().

Posted: Fri Apr 11, 2008 5:14 pm
by milan1612
Fluid Byte wrote:Oops!
Sorry mate, just replace WindowEvent() with
WaitWindowEvent().

Ahh, didn't see that

Posted: Fri Apr 11, 2008 6:22 pm
by Hydrate
Using lines instead works fantastically, thank you very much.
Posted: Fri Apr 11, 2008 8:21 pm
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
Posted: Fri Apr 11, 2008 10:23 pm
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.