Detecting joystick activity

I need to know when a PC has been idle for a while. I have a system wide hook for keyboard and mouse activity.

I now have a requirement to do the same thing for the joystick. I need to detect this activity even if my Delphi application does not have the focus.
moonriseAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

edeyCommented:
perhaps you could use a Direct Input wrapper? or, if you're not too picky on how long you wait, check for a WM_SYSCOMMAND message with the SC_SCREENSAVE parameter (I believe this gets broadcast to every app when the screen saver starts, though I could be wrong)


GL
Mike
0
intheCommented:
hi,
this examples that follows is a bit over the top but basically you need add mmsystem to uses then in the message handler you have for keyboard and mouse look also for MM_JOY1BUTTONUP MM_JOY1BUTTONDOWN etc..
Regards Barry


unit JoySetCapture_Form1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ExtCtrls, mmsystem, ComCtrls, Tabnotbk;

type
  TForm1 = class(TForm)
    TabbedNotebook1: TTabbedNotebook;
    GroupBox1: TGroupBox;
    Panel1: TPanel;
    GroupBox2: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Shape1: TShape;
    Shape2: TShape;
    Image1: TImage;
    BitBtn1: TBitBtn;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click2(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  protected
     procedure joyInit;
     procedure joyToClient(var pptJoyPos: TPoint);
     procedure WndProc(var Msg: TMessage); override;
  end;

var
  Form1: TForm1;
  Threshold: Integer;         // holds the joystick threshold value

implementation

{$R *.DFM}
procedure TForm1.WndProc(var Msg: TMessage);
var
   Cpoint: TPoint;       // holds the joystick position coordinates
begin
  {if the joystick has moved...}
  if Msg.Msg = MM_JOY1MOVE then
  begin
    {retrieve the coordinates relative to the panel}
    Cpoint.X := Msg.LParamLo;
    Cpoint.Y := Msg.LParamHI;
    JoyToClient(Cpoint);

    {modify the Smiley picture based on the position of the joystick}
    if ((Cpoint.x >= 50) and (Cpoint.x <= 55)) and
       ((Cpoint.y >= 40) and (Cpoint.y <= 45)) then
      Image2.Picture.Bitmap.Canvas.CopyRect(Rect(0,0,105,85),
        Image4.Picture.Bitmap.Canvas, Rect(0,0,105,85))
    else
      Image2.Picture.Bitmap.Canvas.CopyRect(Rect(0,0,105,85),
        Image3.Picture.Bitmap.Canvas, Rect(0,0,105,85));

    {draw the crosshair}
    Image2.Picture.Bitmap.Canvas.Pen.Color := clRed;
    Image2.Picture.Bitmap.Canvas.Pen.Width := 2;
    Image2.Picture.Bitmap.Canvas.MoveTo(Cpoint.X - 8 ,Cpoint.Y);
    Image2.Picture.Bitmap.Canvas.LineTo(Cpoint.X + 8 ,Cpoint.Y);
    Image2.Picture.Bitmap.Canvas.MoveTo(Cpoint.X ,Cpoint.Y - 8);
    Image2.Picture.Bitmap.Canvas.LineTo(Cpoint.X ,Cpoint.Y + 8);
    Image2.Picture.Bitmap.Canvas.Ellipse(Cpoint.X - 4 ,Cpoint.Y -4,
      Cpoint.X + 4 ,Cpoint.Y +4);
  end;

  {if a joystick button was pressed...}
  if Msg.Msg = MM_JOY1BUTTONDOWN then
  begin
    {color in a shape depending on which button was pressed}
    if Boolean(Msg.WParam and JOY_BUTTON1) then
      Shape1.Brush.Color := clRed;
    if Boolean(Msg.WParam and JOY_BUTTON2) then
      Shape2.Brush.Color := clRed;
  end;

  {if a joystick button was released...}
  if Msg.Msg = MM_JOY1BUTTONUP then
  begin
    {refill the shape with its original color}
    if not Boolean(Msg.WParam and JOY_BUTTON1) then
      Shape1.Brush.Color := clMaroon;
    if not Boolean(Msg.WParam and JOY_BUTTON2) then
      Shape2.Brush.Color := clMaroon;
  end;

  {send the messages on to the default message handler}
  inherited WndProc(Msg);
end;

procedure TForm1.joyInit;
var
  lpjoyInfoEx: TJOYINFOEX;    // holds extended joystick information
  lpjoyInfo: TJOYINFO;        // holds joystick information
  NumOfDevs: Integer;         // holds the number of joystick devices
  Dev1: Integer;              // holds joystick position return values
begin
  {get joystick threshold}
  JoyGetThreshold(JOYSTICKID1, @Threshold);

  {get number of joystick}
  NumofDevs := joyGetNumDevs;

  {if there are no joystick devices present, indicate an error}
  if  NumOfDevs = 0  then
  begin
    MessageBox(Form1.Handle, 'Joystick driver not present', 'Error',
               MB_OK or MB_ICONWARNING);
    Exit;
  end;

  {determine if there is a joystick present}
  Dev1 := joyGetPosEx(JOYSTICKID1, @lpjoyInfoEx);
  if Dev1 = MMSYSERR_BADDEVICEID then
    MessageBox(Form1.Handle,'Joystick 1 is not present', 'Error ', MB_OK);

  {determine if the joystick is unplugged}
  Dev1 := joyGetPos(JOYSTICKID1, @lpjoyInfo);
  if Dev1 = JOYERR_UNPLUGGED then
    MessageBox(Form1.Handle,'Joystick is unplugged', 'Error ', MB_OK);

  {set the joystick threshold}
  joySetThreshold(JOYSTICKID1, 125);
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  {capture joystick messages}
  if (joySetCapture(Form1.Handle, JOYSTICKID1, 0, TRUE) <> JOYERR_NOERROR ) then
  begin
    {indicate that there was a problem capturing the joystick}
    MessageBox(Form1.Handle,'Joystick is not captured', 'Error',
               MB_OK or MB_ICONWARNING);
    Close;
  end;
end;

{convert joytick coordinates to client coordinates}
procedure TForm1.joyToClient(var pptJoyPos: TPoint);
var
  JCaps: TJoyCaps;    // holds joystick device capabilities
  CRect: TRect;       // holds window coordinates
begin
  {get joystick capabilities}
  if (JoyGetDevCaps(JOYSTICKID1, @JCaps, SizeOf(TJOYCAPS))<>JOYERR_NOERROR) then
    Exit;

  {set the joystick position relative to the panel}
  Windows.GetClientRect(Panel1.Handle, CRect);
  pptJoyPos.X := TRUNC((Panel1.Width - 1) * (pptJoyPos.X - JCaps.wXmin) /
    (JCaps.wXmax - JCaps.wXmin));
  pptJoyPos.Y := TRUNC((Panel1.Height - 1) * (pptJoyPos.Y - JCaps.wYmin) /
    (JCaps.wYmax - JCaps.wYmin));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  {initialize joystick}
  Application.ProcessMessages;
  JoyInit;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  {release joystick capture}
  JoyReleaseCapture(JOYSTICKID1);
end;

procedure TForm1.BitBtn1Click2(Sender: TObject);
begin
  Close;
end;

end.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
intheCommented:
nboitce these lines in example:

begin
  {if the joystick has moved...}
  if Msg.Msg = MM_JOY1MOVE then ..
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

intheCommented:
hello ?
0
moonriseAuthor Commented:
Sorry about the delay, I was away on a trip.  

Question: I wrote WndProc. Are all messages sent to this or only the ones generated by this form/application?

procedure TFormMainMenu.WndProc(var Msg: TMessage);
begin
  if (Msg.Msg = MM_JOY1MOVE) or
     (Msg.Msg = MM_JOY2MOVE) or
     (Msg.Msg = MM_JOY1ZMOVE) or
     (Msg.Msg = MM_JOY2ZMOVE) or
     (Msg.Msg = MM_JOY1BUTTONDOWN) or
     (Msg.Msg = MM_JOY2BUTTONDOWN) or
     (Msg.Msg = MM_JOY1BUTTONUP) or
     (Msg.Msg = MM_JOY2BUTTONUP) then
    ProcessActivityDetected;

  // Send the messages on to the default message handler.
  inherited WndProc(Msg);
end;

0
intheCommented:
Hi
yep your application will detect all these messages if they are sent globally .. if they are sent specifically to another apps handle only then you may need to write a windows hook to catch them all but i think your winproc will be just fine.
Regards Barry
0
moonriseAuthor Commented:
Thank you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.