Screen-Mouse doesn't work when Screen in Container?

Advanced game related topics
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I believe the problem lies in the messaging used as the windowed screen is assumed to be opened on a toplevel window, whereas the container is a static control. (but that's a guess) Here's a small include that preserves all original function names, so using it requires no extra effort:

Code: Select all

Structure MOUSESTATE
  mouseloc.POINT
  mbutton.i[4]
EndStructure

Procedure MouseInit()
  ProcedureReturn 1
EndProcedure

Procedure MouseExamine()
  Shared _mstate.MOUSESTATE
  Static screenw=0, screenh=0
  If Not screenw
    GetClientRect_(ScreenID(),@cr.RECT)
    screenw = cr\right-cr\left
    screenh = cr\bottom-cr\top
  EndIf
  RtlZeroMemory_(@_mstate, SizeOf(MOUSESTATE))
  GetCursorPos_(@_mstate\mouseloc)
  If WindowFromPoint_(_mstate\mouseloc\x | (_mstate\mouseloc\y<<32))=ScreenID() 
    SetCursor_(0)
  EndIf
  MapWindowPoints_(0,ScreenID(),@_mstate\mouseloc,1)
  If _mstate\mouseloc\x < 0 : _mstate\mouseloc\x = 0 : EndIf
  If _mstate\mouseloc\y < 0 : _mstate\mouseloc\y = 0 : EndIf
  If _mstate\mouseloc\x >= screenw : _mstate\mouseloc\x = screenw-1 : EndIf
  If _mstate\mouseloc\y >= screenh : _mstate\mouseloc\y = screenh-1 : EndIf
  With _mstate
    \mbutton[1]= GetAsyncKeyState_(#VK_LBUTTON) & 32768
    \mbutton[3]= GetAsyncKeyState_(#VK_MBUTTON) & 32768
    \mbutton[2]= GetAsyncKeyState_(#VK_RBUTTON) & 32768
  EndWith
EndProcedure

Procedure GetMouseX()
  Shared _mstate.MOUSESTATE
  ProcedureReturn _mstate\mouseloc\x
EndProcedure

Procedure GetMouseY()
  Shared _mstate.MOUSESTATE
  ProcedureReturn _mstate\mouseloc\y
EndProcedure

Procedure GetMouseKey(button)
  Shared _mstate.MOUSESTATE
  ProcedureReturn _mstate\mbutton[button]
EndProcedure

Macro InitMouse() : MouseInit() : EndMacro
Macro ExamineMouse() : MouseExamine() : EndMacro
Macro MouseX() : GetMouseX() : EndMacro
Macro MouseY() : GetMouseY() : EndMacro
Macro MouseButton(button) : GetMouseKey(button) : EndMacro
Small test: (note that the code is the same as if you weren't using the include)

Code: Select all

OpenWindow(0,0,0,640,240,"",#PB_Window_ScreenCentered)
InitSprite():InitMouse():InitKeyboard()
ContainerGadget(0,0,0,320,240)
OpenWindowedScreen(GadgetID(0),0,0,320,240,0,0,0)

Repeat
  While WindowEvent():Wend
  ClearScreen(0)
  ExamineMouse()
  StartDrawing(ScreenOutput())
    DrawText(100,100,Str(MouseX())+", "+Str(MouseY()), #White, #Black)
    If MouseButton(#PB_MouseButton_Left)
      DrawText(100,120,"Left")
    EndIf
    If MouseButton(#PB_MouseButton_Middle)
      DrawText(130,120,"Middle")
    EndIf
    If MouseButton(#PB_MouseButton_Right)
      DrawText(180,120,"Right")
    EndIf
  StopDrawing()
  FlipBuffers()
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_All)
I didn't do MouseDelta, mainly because I've never used it myself, but it would be simple enough to add.
BERESHEIT
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

thanx, netmaestro!

gives me a better insight in the API functions for the cursor than I had before.

- you have a SetCursor_(0) in there, but not the opposite?
(darn have no win32.hlp at hand...)

- I assume, (_mstate\mouseloc\x | (_mstate\mouseloc\y<<32)) is the synthesis of a POINT struct?
... couldn_t we pass _mstate\mouseloc directly?


btw.. it does not exactly work like the DX mouse,
if the cursor is outside the screen, the coordinates are still updated.
but I think this is even better.

... I see that the coords are limited manually by 4 ifs...
this enables us to limit them a bit further outside, so we could disply a crosswire that vanishes slowly beyond the border....

all in all, really nice snippet and very inspiring.
thnx again :D
oh... and have a nice day.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Re: Screen-Mouse doesn't work when Screen in Container?

Post by Kaeru Gaman »

hu... it's over a year ago... time runs fast.

@netmaestro

I got a confirmation question left...

what about the SetCursor_(0) in there...?
I wonder why it is to be called every iteration to hide the cursor, but never to show it.
normally I would assume I hide the cursor when it enters the screen and show it again when it leaves the screen.

would you mind explaning this more detailed?
thanx a lot so far!
oh... and have a nice day.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Screen-Mouse doesn't work when Screen in Container?

Post by Olliv »

@Kaeru

Each area of the screen (desktop screen) is assigned with a cursor pattern through the window class.

So, you can remove it...

Code: Select all

  If WindowFromPoint_(_mstate\mouseloc\x | (_mstate\mouseloc\y<<32))=ScreenID() 
    SetCursor_(0)
  EndIf
...add it just before the main loop...

Code: Select all

Define.I Zob
Global hCursor.I = CreateCursor_(Zob, 0, 0, 1, 1, @Zob, @Zob)
SetClassLong_(ScreenID(), #GCL_HCURSOR, hCursor)
...and add it after the main loop

Code: Select all

DestroyCursor_(hCursor)
Also you preserve the cursor in the window and out of the graphic screen, and you don't check what the OS already checks (if mouse cursor is in or out of the graphic screen)...
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Re: Screen-Mouse doesn't work when Screen in Container?

Post by Kaeru Gaman »

Each area of the screen (desktop screen) is assigned with a cursor pattern through the window class.
hm.. ok that makes it a bit clearer.
that could explain why I can deactivate it for the screencontainer and leave the outside untouched.

but why do I have to deactivate it each iteration?

sorry, cursor manipulation via API is just brandnew for me.
my goal is to fully understand what netmeastro showed there.

I'm away from wanting to use the dx mouselib, I will solve it via WindowMouseX/Y and API.

in the end, it would be sufficent to just hide the cursor when it is over any element of my window, container or not.
I don't need the rest of the window area for controls, it's just to provide a blind frame to cover the rest of the desktop when it has a different aspect ratio.
oh... and have a nice day.
Post Reply