Recent

Author Topic: GetAsyncKeyState error when Taskbar is clicked  (Read 14609 times)

anna

  • Sr. Member
  • ****
  • Posts: 426
GetAsyncKeyState error when Taskbar is clicked
« on: October 25, 2010, 08:09:18 am »
Lazarus : Lazarus-0.9.29-27722-fpc-2.4.0-20101017-win32.exe
OS : WinXp SP3.

Run attached project. And do next as it showed on screenshot:
1.Click on Start monitoring left mouse button clicks button
2. Click on some place on taskbar.
3. Click on some free place in the application form.
4. Click on some free place in the application form again (only now you will see message in edit field).

Why is not clicking left mouse button determined on item 3?
If I don't click on taskbar (i.e. if I skip item 2 and item 3), LBUTTON click is determined immediately. Why? How to do determination clicks always working.
« Last Edit: October 25, 2010, 08:10:50 am by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #1 on: October 25, 2010, 08:57:51 am »
look, whatever you're trying to do, GetAsyncKeyState+Timer is NOT the way. the only time when GetAsyncKeyState might be of use to you is to check whether shift/ctrl is held during drag/drop. otherwise, don't use it. especially not for mouse.

use control's keyboard/mouse events for events within your application.

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #2 on: October 26, 2010, 12:45:26 pm »
look, whatever you're trying to do, GetAsyncKeyState+Timer is NOT the way. the only time when GetAsyncKeyState might be of use to you is to check whether shift/ctrl is held during drag/drop. otherwise, don't use it. especially not for mouse.

use control's keyboard/mouse events for events within your application.
Well, I remade project:
Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls,

  Windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
procedure StartMouse; external 'hook';
procedure RemoveHookMouse; external 'hook';


procedure TForm1.Button1Click(Sender: TObject);
begin
  StartMouse;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  RemoveHookMouse;
  Edit1.clear;
end;

end.



It uses hook.dll (must exist in same dir as project1.exe):
Code: [Select]
library hook;

{$R *.res}

uses windows, messages;

var
 SaveExitProc: Pointer;
 // Handle the traps

HMouse: hHook = 0;

// Function traps
function Key_HookMouse (code: integer; wParam: integer;
                       lParam: integer): integer stdcall;
begin
 if (code>= 0) and ((wParam = WM_NCLBUTTONUP) or (wParam = WM_LBUTTONUP))
  then begin
         SendMessage (findwindowex(findwindow('Window','Form1'),0,'Edit',''), WM_SETTEXT,
                   0, integer(pchar('Click was detected!')));
       end;
  Result:= CallNextHookEx (HMouse, code, wParam, lParam);
end;

procedure StartMouse;
// Set the trap keyboard

begin
if HMouse = 0 then
  HMouse:= SetWindowsHookEx (WH_MOUSE, @ Key_HookMouse,
                             hInstance, 0);
 if HMouse = 0 then
   MessageBox (0, 'The trap is not established', 'Error', mb_Ok);
end;

procedure RemoveHookMouse;
// Update mouse traps
begin
 if HMouse <> 0 then
 begin
   UnhookWindowsHookEx (HMouse);
   HMouse:= 0
 end;
end;

procedure RemoveExit;
// Remove the trap at the end of work
begin
 if HMouse <> 0

  then UnhookWindowsHookEx (HMouse);
 ExitProc:= SaveExitProc;
end;

exports
 StartMouse,
 RemoveHookMouse;

begin
// Specifying the exit procedure, which lifts the trap
  SaveExitProc:= ExitProc;
  ExitProc:= @ RemoveExit;
end.

But when I run project through lazarus and close application by ALT+F4, I see error : http://img258.imageshack.us/img258/7562/14883928.png
What's wrong?
« Last Edit: October 26, 2010, 02:08:31 pm by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #3 on: October 27, 2010, 04:41:29 pm »
Maybe somebody knows better way to intercept mouse messages, say without dll?

Application must be able to catch message even if cursor goes out of  application's form.
« Last Edit: October 27, 2010, 04:45:13 pm by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #4 on: October 28, 2010, 07:04:07 am »
what is it with people here wanting to hook stuff...

the thing is that some stuff needs to be in shared memory, accessible to entire system. in c++ that is done with a compiler directive. in pascal, we need to put in a bit more effort. read this. that's where i learned to do it.

Maybe somebody knows better way to intercept mouse messages...
no. hooks work just fine (once you get them to work).

...say without dll?
nope. it has to be a dll. you could trick the system into thinking your exe is a dll but there's no point.

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #5 on: October 28, 2010, 03:38:53 pm »
Please help anybody with bug, which I had. So, first remade dll (see above) to this :
Code: [Select]
library project1;

{$R *.res}

uses windows, messages;

var
 SaveExitProc: Pointer;
 // Handle the traps

HMouse: hHook = 0;

// Function traps
function Key_HookMouse (code: integer; wParam: integer;
                       lParam: integer): integer stdcall;
begin
 if (code>= 0) and ((wParam = WM_NCLBUTTONUP) or (wParam = WM_LBUTTONUP))
  then begin
         SendMessage(findwindow('Window','project1'), WM_SYSCOMMAND,SC_MINIMIZE, 0);
         SendMessage(findwindow('Window','project1'), WM_SYSCOMMAND,SC_RESTORE, 0);
       end;
  Result:= CallNextHookEx (HMouse, code, wParam, lParam);
end;

procedure StartMouse;
// Set the trap keyboard

begin
if HMouse = 0 then
  HMouse:= SetWindowsHookEx (WH_MOUSE, @ Key_HookMouse,
                             hInstance, 0);
 if HMouse = 0 then
   MessageBox (0, 'The trap is not established', 'Error', mb_Ok);
end;

procedure RemoveHookMouse;
// Update mouse traps
begin
 if HMouse <> 0 then
 begin
   UnhookWindowsHookEx (HMouse);
   HMouse:= 0
 end;
end;

procedure RemoveExit;
// Remove the trap at the end of work
begin
 if HMouse <> 0

  then UnhookWindowsHookEx (HMouse);
 ExitProc:= SaveExitProc;
end;

exports
 StartMouse,
 RemoveHookMouse;

begin
// Specifying the exit procedure, which lifts the trap
  SaveExitProc:= ExitProc;
  ExitProc:= @ RemoveExit;
end.

Then place dll to the same folder as project1.exe and start exe.
Open Microsoft Paint. Press Start monitoring left mouse button clicks button. Start draw something in Paint window. You must release left mouse button at least 20 times to see bug. The bug is that application does multiple minimizeing-restoring instead of 1 minimize for 1 left mouse button.

Why does it do that?
« Last Edit: October 28, 2010, 03:41:31 pm by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #6 on: October 28, 2010, 04:17:22 pm »
Why does it do that?
i'm gonna have to do some guessing because i'm not on my windows machine now... (honestly, i'm surprised it works at all)

one, it's been a while but i seem to recall i used to put -1 as a lparam for minimizing/restoring... see if it helps...

two, how does it work if you replace two sendmessage calls with closewindow/openicon?

three (hint) - you are supposed to keep hook procedures down to a bare minimum - call findwindow (or whatever) in startmouse proc and keep the window handle in a variable.

four (hint) - you should not call findwindow at all (let alone two times per mouse message). pass the handle as an argument to startmouse. second benefit to that is that you're avoiding the case that there could be more windows with the same classname/title (for example the form designer). the fact that all lazarus-made windows have the same window class makes that even more reasonable.

five, do not use ExitProc in a dll (or in an exe, for that matter but especially in dll). use DLLProc or unit finalization section.

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #7 on: October 28, 2010, 05:00:48 pm »
Why does it do that?
i'm gonna have to do some guessing because i'm not on my windows machine now... (honestly, i'm surprised it works at all)

one, it's been a while but i seem to recall i used to put -1 as a lparam for minimizing/restoring... see if it helps...

Same! Problem stay.

two, how does it work if you replace two sendmessage calls with closewindow/openicon?
Same! 1 LMB = 1..3 minimizings-restores instead of 1

I think that Result:= CallNextHookEx (HMouse, code, wParam, lParam);make these problems. When I write Result:=1, then problem disappears but some applications begin to work slow and with errors.
« Last Edit: October 28, 2010, 05:07:13 pm by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #8 on: October 28, 2010, 05:10:02 pm »
Windows messages are bad idea. I killed lots of time and it doesn't work. Better tell me how to make timers working (see 1st post).
« Last Edit: October 28, 2010, 05:18:15 pm by anna »
WinXP SP3 Pro Russian 32-bit (5.1.2600)

zariq

  • Full Member
  • ***
  • Posts: 109
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #9 on: October 28, 2010, 09:36:37 pm »
Hi everybody.

I would just like to say to Ivan that Even though, it seems, you are not fond of people wanting to use hooks, it's good you are sharing your knowledge.

I would like to make a few points if I may.

1. some things might not be possible without the use of hooks, and
   therefore people have no choice but to use them.

2. Most People are naturally curious and and will want to know how 
   to do something even if they dont have a need to use a particular
   technique.

3. People should know that these sort of things are possible not
   only in c but other languages. People using and discussing these
   techniques can only be good for lazarus. I agree with your
   thoughts that hooks  should not be used in programs meant to be
   used by other people, especially if your are not very good at
   using them.

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #10 on: October 29, 2010, 10:36:09 pm »
Windows messages are bad idea. I killed lots of time and it doesn't work. Better tell me how to make timers working (see 1st post).
i find your lack of patience disturbing.

I think that Result:= CallNextHookEx (HMouse, code, wParam, lParam);make these problems. When I write Result:=1, then problem disappears but some applications begin to work slow and with errors.
so if you cut the message chain (prevent anyone from getting the message) some problems go away? Scrap what you've got so far. Take Stutz's example (link in my older post), study it and slowly build on top of it, step by step. Do not cut corners. You can bend a few rules in a vanilla-application but in a hook-app, don't.

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #11 on: October 30, 2010, 04:17:04 am »
Quote from: ivan17
so if you cut the message chain (prevent anyone from getting the message) some problems go away? Scrap what you've got so far.
Microsoft writes that :

" If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the target window procedure."
WinXP SP3 Pro Russian 32-bit (5.1.2600)

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #12 on: October 30, 2010, 07:12:09 am »
Finally, I made acceptable project (attached).
But as you can see, problem is remained. For example, open Notepad and pess Tab key on keyboard. You will see triple minimizing insead of 1. Moreover it will be spontaneous minimizing every 10 second if I even didn't touch keyboard or mouse.
WinXP SP3 Pro Russian 32-bit (5.1.2600)

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: GetAsyncKeyState error when Taskbar is clicked
« Reply #13 on: October 30, 2010, 09:05:09 am »
ivan17
So Mr.Stutz made project very worst then me. In my ''windows Messages project'' there are not spontaneous triggering of dll code.
WinXP SP3 Pro Russian 32-bit (5.1.2600)

 

TinyPortal © 2005-2018