[c++] WIn api w okienku dos

0

Witam

W jaki sposób mogę w programie konsolowym przechwytywać zdarzenia windowsowe (czyli korzystając z winAPI) takie jak np pozycja myszy i ewentualnie wyświetlać współrzędne w konsoli ?

Dodam tylko że nie chodzi mi o zdarzenia związane z samym oknem konsoli, wręcz o zdarzenia poza oknem a ewentualne wyniki po jakiej obróbce w oknie konsolowym

0

Jeśli chodzi o wyświetlenie konsoli z wynikami to np:

[patrz -> nie artykuł tylko komentarz 'manfredka' dnia 29-04-2009 15:02]
Prosta konsola dla programów okienkowych w WinAPI
Przechwytywanie mychy - szukaj mouse hook...
Aby mieć pętle komunikatów w programie możesz utwożyć okno ale go nie wyświetlać ,
ma służyć tylko do podpięcia WinProc z message .

0
dzejo napisał(a)

Jeśli chodzi o wyświetlenie konsoli z wynikami to np:

[patrz -> nie artykuł tylko komentarz 'manfredka' dnia 29-04-2009 15:02]
Prosta konsola dla programów okienkowych w WinAPI
Jak słusznie crayze zauważył artykuł i komentarz manfredka są zbędne w tytułowym przypadku, wystarczy utworzyć projekt konsolowy, w nim też możemy robić okienka. A tak swoją drogą to autor nie chce mieć w ogóle okienek tylko samą konsolę.

dzejo napisał(a)

Przechwytywanie mychy - szukaj mouse hook...
jak najbardziej, poniżej zaprezentuję rozwiązanie

dzejo napisał(a)

Aby mieć pętle komunikatów w programie możesz utwożyć okno ale go nie wyświetlać , ma służyć tylko do podpięcia WinProc z message .
Nie trzeba mieć żadnego okna. Nawet jeśli by chcieć uchwyt okna tylko do komunikatów to robi się okno message-only.
Poniżej zaprezentuje samą kolejkę bo się przyda, z tego co zauważyłem wątek zakładający WH_JOURNALRECORD musi mieć kolejkę komunikatów. Kolejka ta przyda się również do gromadzenia wiadomości przechwytywanych przez hook. A o to kod:

#include <windows.h>
#include <iostream>
using namespace std;

HINSTANCE g_hInst;
HHOOK g_hHook;
DWORD g_dwMainThreadId;

//procedura hook'a
LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam);
//procedura sygnalu zamkniecia okna konsoli
BOOL WINAPI ConsoleCtrlHandle(DWORD dwCtrlType);
//wyswietla ostatni blad
DWORD ShowLastError(LPCSTR lpszFunction);

int main(int argc, char* argv[])
{
	g_hInst = GetModuleHandle(NULL);
	g_dwMainThreadId = GetCurrentThreadId();

	//zakaladamy hook
	g_hHook = SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProc, GetModuleHandle(NULL), 0);
	if (g_hHook == NULL) return ShowLastError("SetWindowsHookEx");

	//przechwytujemy sygnal zamkniecia okna konsoli
	SetConsoleCtrlHandler(ConsoleCtrlHandle, TRUE);

	//petla komuniaktow
	MSG msg;
	while(GetMessage(&msg, 0, 0, 0))
	{
		switch (msg.message)
		{
			//wyswietlamy przechwycony WM_MOUSEMOVE
			case WM_MOUSEMOVE:
				cout << "X: " << LOWORD(msg.lParam) << "   Y: " << HIWORD(msg.lParam) << endl;
				break;
		
			case WM_CANCELJOURNAL:
				//zakladamy hook ponownie jesli zostal zdjety
				g_hHook = SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProc, GetModuleHandle(NULL), 0);
				if (g_hHook == NULL) return ShowLastError("SetWindowsHookEx");
		}
	}

	//sciagamy hook
	if(g_hHook != NULL) UnhookWindowsHookEx(g_hHook);

	return msg.wParam;
}

LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode == HC_ACTION)    
	{
		//przesylamy kazdy komunikat WM_MOUSEMOVE
		if (((EVENTMSG*)lParam)->message == WM_MOUSEMOVE)
		{
			WORD x = ((EVENTMSG*)lParam)->paramL;
			WORD y = ((EVENTMSG*)lParam)->paramH;

			PostThreadMessage(g_dwMainThreadId, WM_MOUSEMOVE, 0, MAKELONG(x, y));
		}

		return 0;            
	}

	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

BOOL WINAPI ConsoleCtrlHandle(DWORD dwCtrlType)
{
	//wysylamy komunikat przerywajacy petle komunikatow
	PostThreadMessage(g_dwMainThreadId, WM_QUIT, 0, 0);
	return TRUE;
}

DWORD ShowLastError(LPCSTR lpszFunction) 
{ 
    LPSTR lpMsgBuf;
    DWORD dwError = GetLastError(); 

    FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dwError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR) &lpMsgBuf,
        0, NULL );

    cout << lpszFunction << " failed with error " << dwError << ": " << lpMsgBuf;

    LocalFree(lpMsgBuf);
    return dwError;
}

Jakby co niejasne było to pytaj.

0

A , tak nie zatrybiłem :

w programie konsolowym

6 rano ....
Fajne rozwiązanie [green] .
// Niestety ciągle mam Y czyli HIWORD(lParam) == 0
msg.lParam == LOWORD(msg.lParam) bez względu na położenie mychy ,
X działa .

Więc może :

cout << "X: " << LOWORD(msg.lParam) << "   Y: " << LOWORD(msg.wParam) << endl;

Event tak jak było :

cout << "X: " << LOWORD(msg.lParam) << "   Y: " <<HIWORD(msg.lParam) << endl;

i coś ala :

 
LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{


        if (nCode == HC_ACTION)
        {
                //przesylamy kazdy komunikat WM_MOUSEMOVE
                if (((EVENTMSG*)lParam)->message == WM_MOUSEMOVE)
                    {

      PostThreadMessage(g_dwMainThreadId, WM_MOUSEMOVE,0,
      (LPARAM(((EVENTMSG*)lParam)->paramH << 16))+((EVENTMSG*)lParam)->paramL);
                    }

                return 0;
        }     
                    
0

A widzisz :)
paramL i paramH struktury EWENTMSG to nie odpowiedniki lParam i wParam.
Szukałem na MSDN, ale nigdzie nie ma napisane co właściwie jest w tych parametrach, jedynie "The exact meaning depends on the message value" :/ . Przy JournalPlayback jest wzmianka:

If the hook procedure returns a message in the range WM_KEYFIRST to WM_KEYLAST, the following conditions apply:

  • The paramL member of the EVENTMSG structure specifies the virtual key code of the key that was pressed.
  • The paramH member of the EVENTMSG structure specifies the scan code.
  • There's no way to specify a repeat count. The event is always taken to represent one key event.

Jak słusznie zauważyłeś, przy myszy paramL to X, a paramH to Y.
Poprawiłem kod tak, że do kolejki komunikatów wysyłane są współrzędne zgodnie z formatem komunikatu WM_MOUSEMOVE, czyli w starszym i młodszym słowie lParam leżą współrzędne. Z wParam niestety nici.

0

Programik działa świetnie. Dokładnie o to mi chodziło tylko mam teraz pytanko.

Chcę przerobić program tak aby wyświetlał mi jedynie współrzędne myszki w momencie kliknięcia więc zmieniam fragment

case WM_MOUSEMOVE

na

case WM_LBUTTONDOWN

Ale wtedy nie mam już nic wyświetlane, co robię źle ?

0

Już wiem co jeszcze trzeba było zrobić, pytania nie było ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1