[VC++]Muis input gebruiken i.c.m. een event*

Pagina: 1
Acties:

  • Cassius
  • Registratie: Januari 2002
  • Niet online
Beste medetweakers :) ,

Ik loop tegen een aantal problemen op bij het gebruik van C++ in Microsoft Visual C++ 2005 Express Edition (versie 8 met SP1). Hierbij heb ik de Microsoft Platform SDK geïnstalleerd. Dit topic kan geschaard worden onder het niveau 'beginner'!

De software werkt, maar mijn idee krijg ik niet concreet vertaald naar een code. Ik dacht dat wat ik in gedachten had niet zo moeilijk was, maar na het lezen van sites als deze -->

http://msdn.microsoft.com/msdnmag/issues/06/02/CAtWork/
http://www.codeproject.com/cpp/article_events1.asp

Lijkt dat event systeem mij helemaal niet eenvoudig. En om hier een input bij te gebruiken (http://www.codeproject.com/cpp/cinputevent.asp bijvoorbeeld) is voor mij ook zwaar. Ik wilde vragen of iemand met ervaring na het lezen van de volgende beschrijving advies kan geven over de structuur van mijn programma.

Ik wil rustig beginnen, wat wil zeggen; de positie van de muis uitlezen en deze gebruiken als input voor een event handler / listener. Deze mag vervolgens gewoon met cout of printf zeggen: "Your mouse has been in <x> by <y> range for <z> time, this is an event".

Dit had ik zelf in gedachte (in pseudo-achtige-code) -->

functie 'lees USB informatie'
functie 'sla USB formatie op met deze probe snelheid in array' (even ter voorbeeld, enkelvoudige array met 10 punten)
als (if) muis bij meer dan 5 metingen op linkerhelft van scherm is (op mijn scherm (1400x1050) dus tussen 0-700 en 0-1050) --> dit triggert een event dat naar deze array aan het kijken is en die spuugt het bericht het scherm op

Nu weet ik dat ik er nog -lang- niet ben en ik ben morgen in de bibliotheek voor boeken, maar ik hoop hiermee wat advies over de structuur en stappen te mogen krijgen. Alvast bedankt voor de moeite van het lezen :) !

De meeste mensen deugen!


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Cassius schreef op donderdag 07 juni 2007 @ 16:53:
functie 'lees USB informatie'
functie 'sla USB formatie op met deze probe snelheid in array' (even ter voorbeeld, enkelvoudige array met 10 punten)
als (if) muis bij meer dan 5 metingen op linkerhelft van scherm is (op mijn scherm (1400x1050) dus tussen 0-700 en 0-1050) --> dit triggert een event dat naar deze array aan het kijken is en die spuugt het bericht het scherm op
Fout dus ;)

Daar heb je een OS voor; dat OS meldt jou de positie van "de muis" wel. Voor het zelfde geld is het ding niet aangesloten op USB maar op PS/2 of whatever. Je moet dus (in princiepe) nooit de hardware direct willen benaderen.

Ik zou (simpel) met een timer om de zoveel tijd de positie van de muis pollen en daarmee werken (circulair in de array gooien of de (max.) 64 laatste posities van windows opvragen, en dan in diezelfde timer event de array nalopen en event raisen wanneer nodig).

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

RobIII schreef op donderdag 07 juni 2007 @ 17:32:
Ik zou (simpel) met een timer om de zoveel tijd de positie van de muis pollen en daarmee werken (circulair in de array gooien of de (max.) 64 laatste posities van windows opvragen, en dan in diezelfde timer event de array nalopen en event raisen wanneer nodig).
Een busy wait is een mooie system stopper, en bij teveel leniency mis je waarschijnlijk weer belangrijke updates. Handiger is om gewoon events te ontvangen van het OS, en dat kan heel mooi dmv een low-level mouse hook die je met SetWindowsHookEx() kunt zetten.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
.oisyn schreef op donderdag 07 juni 2007 @ 17:44:
[...]

Een busy wait is een mooie system stopper, en bij teveel leniency mis je waarschijnlijk weer belangrijke updates. Handiger is om gewoon events te ontvangen van het OS, en dat kan heel mooi dmv een low-level mouse hook die je met SetWindowsHookEx() kunt zetten.
True; ik had er inderdaad even langer dan 10 sec. over moeten nadenken :P

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Cassius
  • Registratie: Januari 2002
  • Niet online
Alvast bedankt voor jullie hulp. Ik ben echt een beginner en kan deze goed gebruiken. Ik ben er van het weekend mee bezig geweest en heb mijn pseudo-achtige-code aangepast; maar ik ben nog een heel eind weg van waar ik moet zijn. Nogmaals het is erg moeilijk voor iemand die net begint, maar we komen er wel. Zeker met GoT, MSDN, Codeproject en cplusplus :) .

GetMouseMovePointsEx heb ik in dit geval niet gebruikt omdat het dus een system stopper is, maar ik begrijp de term leniency niet zo goed.

Ook wilde ik eigenlijk de hook lokaal houden, dus niet WH_MOUSE_LL, maar WH_MOUSE; dit omdat ik het in een enkele .exe zou willen exporteren en nog geen kaas heb gegeten van het hele verbinden met een .dll verhaal :( . Verder heb ik aan mijn linkerkant in VC+ geen balk om libraries toe te voegen aan mijn project, maar daar moet ik nog naar kijken. Overigens heb ik het .NET framework 3.0 op mijn laptop geïnstalleerd staan :) . Hieronder staat een lang stuk code, met commentaar heb ik veel vragen voor mezelf bijgevoegd. Mocht er iemand zijn die er naar wil kijken, heel graag!

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Tutorial.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "Windows.h"
#include <iostream>
using namespace std;

void main () {

    int mouseCoords[10][10];        //De dubbele array met de muispunten
    int sXCoord;
    int sYCoord;
    
    trigger(
        //De listener zou hier moeten komen die newData invult
    );

    getData(
        //Hier moet een functie komen die wordt gestart door de listener en de coordinaten ophaalt
    );

    HHOOK SetWindowsHookEx(          
        int WH_MOUSE,               //geen WH_MOUSE_LL, die kan alleen global zijn en ik begrijp nog niet hoe dat werkt met DLL's en dergelijke
        HOOKPROC lpfn,              //lpfn = pointer to the hook procedure <-- wat is hier neer te zetten?
        HINSTANCE NULL,             //de hMod staat op NULL omdat ik een localHook gebruik in alleen deze code, correct?
        DWORD dwThreadId            //Naar welke thread deze hook moet kijken, ik weet nog niet hoe ik die ID instel.
    );

    LRESULT CALLBACK MouseProc(     //Als een applicatie GetMessage or PeekMessage roept heb ik deze nodig. Maar ik hou het intern ..? En moet toch die hook hebben..
        int nCode,                  //HC_ACTION of HC_NOREMOVE <-- als ik de waarde ook uit HC_ACTION kan lezen, waarom dan PeekMessage gebruiken bij HC_NOREMOVE?
        WPARAM wParam,              //De ID van het muis bericht opgeven ... moet ik nog uitzoeken.
        LPARAM lParam               //De pointer naar een MOUSEHOOKSTRUCT, als ik hier nou Alpha invul voor lParam
    );

    typedef struct{                 //komt hier dan 'typedef struct Alpha{' te staan?
        POINT pt;                   //komt er voor 'pt' hier dan 'tagPOINT' te staan?
        HWND hwnd;                  //wie krijgt de message ... cout :/ ?
        UINT wHitTestCode;          //weet niet wat ik hier in moet vullen, misschien WM_NCHITTEST
        ULONG_PTR dwExtraInfo;      //geen idee welke extra info ik zou toevoegen
    }
    
    MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT; //Wat deze regel doet weet ik helaas niet

    WM_NCHITTEST                    //Heeft te maken met wHiteTestCode, maar hoe het gelinkt is weet ik niet, waar is de ';'? Kan deze de listener aanschoppen?

    WPARAM wParam                   //wordt niet gebruikt
    LPARAM lParam;                  //LO-word heeft x-coord vanaf linksboven hoek en HO-word heeft y-coord van linksboven hoek

    typedef struct tagPOINT {       //Hierin zit het totale coordinaat
        LONG x;                     //Hierin komt het getal van mijn muis x-coord
        LONG y;                     //Hierin komt het getal van mijn muis x-coord
    }

    POINT, *PPOINT                  //Wat deze regel doet weet ik helaas niet (pointen naar 'POINT'?)

    LRESULT DefWindowProc(          //Hier zit een waarde in die een 'hot-spot' positie van de cursor weergeeft  
        HWND hWnd,                  //lijkt op hwnd, maar is ook weer een handle naar een window ... cout :/ ? Of kan ik hiermee een array gaan volgooien?
        UINT Msg,                   //"Your mouse is now on coords <x> and <y>"?
        WPARAM wParam,              //Extra info ... kan ik daar ook NULL invullen als die info er niet is?
        LPARAM lParam               //Extra info ... kan ik daar ook NULL invullen als die info er niet is?
    );

    trigger(newData){                   //Hiermee bedoel ik dus een soort listener, "bij nieuwe data op <z> locatie, ga deze functie in"
        sXCoord = getData(sXCoord);     //Het coord van x wordt ingevuld
        sYCoord = getData(sYCoord);     //Het coord van y wordt ingevuld
        mouseCoords[][] = fill[sXCoord],fill[sYCoord]; //Vul de array met meer punten, dit klopt nog niet! Laat staan dat de fill functie bestaat..

        if(mouseCoord[n][n] =! mouseCoord[n + 1][n + 1]){
            cout = "Your mouse is moving"           //bijvoorbeeld dan
        }
        else{
            cout = "Your mouse is not moving right" //bijvoorbeeld dan ...
        }
    }   
}


Gelieve mij niet uit te lachen of te posten in slechte progcode ooit; ik heb het er al moeilijk genoeg mee }:| . Ik ben al lang blij dat al deze functies allemaal in Windows.h zitten; nu moet ik ze nog begrijpend zien te doorgronden en zien te koppelen aan een event trigger / handler / listener.

Mijn hoofdvraag is hoe ik al deze functies dus aan elkaar koppel, ik begrijp dat ik hiermee veel uitlegvermogen vraag; ik hoop dat iemand die moeite kan missen. Als ik -veel- te moeilijk denk hoor ik het ook graag en over de volgorde moet ik nog nadenken.

Hartstikke bedankt (al is het maar voor de moeite van het doorlezen!), ik zal zo hard mogelijk eraan werken!

De meeste mensen deugen!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Cassius schreef op maandag 11 juni 2007 @ 14:18:
GetMouseMovePointsEx heb ik in dit geval niet gebruikt omdat het dus een system stopper is, maar ik begrijp de term leniency niet zo goed.
Dit maakt je PC vrij onresponsive (tenzij je meerdere cores hebt, maar het zal 1 core vrijwel altijd helemaal bezetten):
C++:
1
2
3
4
5
while (!stop)
{
    GetMousePosition();
    DoeIets();
}


Dit zou je kunnen laten 'vieren' door steeds te wachten:
C++:
1
2
3
4
5
6
while (!stop)
{
    GetMousePosition();
    DoeIets();
    Sleep(100); // wacht 100 ms
}


Het nadeel is dan dat je bepaalde events kunt missen, zoals bijvoorbeeld een muisklik.
Ook wilde ik eigenlijk de hook lokaal houden, dus niet WH_MOUSE_LL, maar WH_MOUSE; dit omdat ik het in een enkele .exe zou willen exporteren en nog geen kaas heb gegeten van het hele verbinden met een .dll verhaal :(
Dat is juist de reden dat ik de low-level hook had gesuggereerd, want die worden aangeroepen in je eigen proces. Dan hoef je dus niet moeilijk te doen met DLLs enzo (zie LowLevelMouseProc voor meer info) :). Maar idd, voor normale hooks hoef je idd ook niet met DLLs te werken, zolang je maar geen globale hook wilt zetten (dus gewoon GetCurrentThreadId() opgeven als de thread id). Ik dacht even dat je dan alleen events kreeg voor muisberichten die zich binnen jouw applicatie bevinden, maar dat is natuurlijk niet zo.

Over de opbouw van je applicatie, dat kan ongeveer zo:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
HHOOK mouseHookHandle;

LRESULT CALLBACK MyMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // handel elke mouseevent hier af
}

int main()
{
    // installeer de hook
    mouseHookHandle = SetWindowsHookEx(WH_MOUSE, MyMouseProc, 0, GetCurrentThreadId());

    // message loop
    MSG msg;
    while (GetMessage(&msg, 0, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    // uninstall de hook
    UnhookWindowsHookEx(mouseHookHandle);
}


Je app stopt nu als hij een WM_QUIT ontvangt. Dit is bijvoorbeeld als Windows vraagt je app te sluiten, of als je zelf PostQuitMessage() aanroept. Het is wellicht handig om andere stopcriteria te implementeren :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Cassius
  • Registratie: Januari 2002
  • Niet online
.oisyn schreef op maandag 11 juni 2007 @ 14:57:
Over de opbouw van je applicatie, dat kan ongeveer zo:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
HHOOK mouseHookHandle;

LRESULT CALLBACK MyMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // handel elke mouseevent hier af
}

int main()
{
    // installeer de hook
    mouseHookHandle = SetWindowsHookEx(WH_MOUSE, MyMouseProc, 0, GetCurrentThreadId());

    // message loop
    MSG msg;
    while (GetMessage(&msg, 0, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    // uninstall de hook
    UnhookWindowsHookEx(mouseHookHandle);
}


Je app stopt nu als hij een WM_QUIT ontvangt. Dit is bijvoorbeeld als Windows vraagt je app te sluiten, of als je zelf PostQuitMessage() aanroept. Het is wellicht handig om andere stopcriteria te implementeren :)
Even kort: als ik het goed begrijp simplificeer je de code door in plaats van een event code gebruik te maken van een loop die steeds de muisdata pollt. Dit is makkelijker coden, maar loop je dan niet het gevaar dat je data misloopt?

Alsnog bedankt voor de tip en de moeite, ik ben er mee bezig :) !

De meeste mensen deugen!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, die hele GetMessage() is de basis van event code :). Als er een event optreedt, dan stuurt Windows een message naar je thread. Al die messages komen in een queue terecht, die je kunt ophalen met GetMessage() (en DispatchMessage() zorgt er voor dat de juiste handler aangeroepen wordt - MyMouseProc() in het geval van je mouse hook messages dus). Je mist dus nooit een event - als je ze niet afhandelt dan loopt je queue alleen maar vol.

[ Voor 18% gewijzigd door .oisyn op 13-06-2007 11:59 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1