|
Maus-Ereignisse :
Anhand des vorigen Beispiels
(Haupt- mit Child-Fenster)
sollen nun die Aktivitäten der Maus in einem Fenster
in einer Statuszeile des anderen angezeigt werden.
Die Mausfunktionen ermöglichen ebenfalls eine Auswertung der Shift- und Ctrl-Tasten der Tastatur
(siehe
OpenGL
).
Um eine Statusleiste verwenden zu können, benötigt das Projekt die Bibliothek comctl32.lib
(in Dev-C++ libcomctl32.a im lib-Verzeichnis).
Außerdem muß dem Listing die Include-Datei commctrl.h beigefügt und mit der Anweisung
InitCommonControls(); die DLL (dynamic-link library) geladen werden.
Bei WM_SIZE in der Fensterprozedur läßt sich die Statusleiste automatisch an Größenveränderungen
des Fensters anpassen. Die Leiste ist hier gleich in mehrere Segmente unterteilt, die unabhängig voneinander
beschriftet werden können.
|
|
// Win32-API: Simple Window and mouse events (Author: Claude Jacobs, 2013)
// req.: comctl32.lib
#include <windows.h>
#include <winuser.h>
#include <stdio.h>
#include <commctrl.h>
//============== Globale Variablen deklarieren =====================
HWND hFenster, hChildFenster ; // Handles der Fenster deklarieren
HWND hStatusLeiste; // Handle der StatusLeiste deklarieren
#define idStatusLeiste 300
char STR[255]=""; RECT Rechteck;
int xmaus,ymaus, xmprev, ymprev, dxmaus, dymaus, MausRad;
//============== Prozeduren der einzelnen Fenster ==================
LRESULT CALLBACK FensterProzedur (HWND hFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{case WM_SIZE: {SendMessage(hStatusLeiste, WM_SIZE, 0, 0); break;} // StatusLeiste anpassen
case WM_DESTROY: {PostQuitMessage (0); break;} // Programm beenden
default: {return DefWindowProc (hFenster, Befehle, wParam, lParam);}
}
return 0; }
LRESULT CALLBACK ChildFensterProzedur (HWND hChildFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{
//-----
case WM_LBUTTONDOWN:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)"Links");
xmprev=xmaus; ymprev=ymaus;
wsprintf( STR, " %0.3d %0.3d [%0.3d] [%0.3d]", xmaus, ymaus, 0, 0);
SendMessage(hStatusLeiste, SB_SETTEXT, 0, (LPARAM)STR);
return 0;}
case WM_MBUTTONDOWN:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)"Mitte"); return 0;}
case WM_RBUTTONDOWN:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)"Rechts"); return 0;}
case WM_LBUTTONUP:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)""); return 0;}
case WM_MBUTTONUP:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)""); return 0;}
case WM_RBUTTONUP:{SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)""); return 0;}
//-----
case WM_MOUSEMOVE:{
xmaus = LOWORD(lParam); ymaus = HIWORD(lParam);
if(xmaus & 1 << 15) xmaus -= (1 << 16);
if(ymaus & 1 << 15) ymaus -= (1 << 16);
GetClientRect(hChildFenster, &Rechteck); ymaus=Rechteck.bottom-1-ymaus;
wsprintf( STR, " %2.0d %02.0d", xmaus, ymaus);
dxmaus=xmaus-xmprev; dymaus=ymaus-ymprev;
if (wParam & MK_LBUTTON)
{wsprintf( STR, " %0.3d %0.3d [%0.3d] [%0.3d]", xmaus, ymaus, dxmaus, dymaus);}
SendMessage(hStatusLeiste, SB_SETTEXT, 0, (LPARAM)STR);
return 0;}
//----
case WM_MOUSEWHEEL: {
if (((short)HIWORD(wParam))/120.0 > 0) {MausRad++;}
if (((short)HIWORD(wParam))/120.0 < 0) {MausRad--;}
wsprintf( STR, " %0.3d", MausRad);
SendMessage(hStatusLeiste, SB_SETTEXT, 1, (LPARAM)STR);
return 0;}
//-----
default: {return DefWindowProc (hChildFenster, Befehle, wParam, lParam);}
}
return 0; }
//========== HAUPTFUNKTION (und die beiden Fenster erzeugen) =======
int WINAPI WinMain (HINSTANCE hInstanz, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFensterStil)
{ MSG Befehle; // eine Message-Variable deklarieren
WNDCLASSEX Klasse; // eine Fensterklassen-Variable deklarieren (für wichtige Parameter des Fensters)
Klasse.lpszClassName = "Hauptfenster" ; // Klassenname
Klasse.lpfnWndProc = FensterProzedur ; // Name der Prozedur des Hauptfensters
Klasse.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
Klasse.hCursor = LoadCursor (NULL, IDC_ARROW);
Klasse.cbSize = sizeof (WNDCLASSEX);
Klasse.hInstance = hInstanz;
Klasse.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
Klasse.hIcon = LoadIcon (NULL, IDI_APPLICATION);
Klasse.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
Klasse.lpszMenuName = NULL; // Fenster hat kein Menü
Klasse.cbClsExtra = 0;
Klasse.cbWndExtra = 0;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"Fensterklasse konnte\n nicht rgistriert werden","Fehler", MB_OK); return 0;}
hFenster = CreateWindow ("Hauptfenster", "Titel des Fensters", WS_OVERLAPPEDWINDOW,
// Hauptfenster erzeugen :
40, 20, 400, 300, HWND_DESKTOP, NULL, hInstanz, NULL);
//----
InitCommonControls(); // DLL laden
hStatusLeiste = CreateWindowEx (0,STATUSCLASSNAME, "", WS_VISIBLE | WS_CHILD| SBARS_SIZEGRIP,
0, 0, 0, 0, hFenster, (HMENU)idStatusLeiste, hInstanz, NULL);
int StatusTeilung[] = {140, 200, -1};
SendMessage(hStatusLeiste, SB_SETPARTS, 3, (LPARAM)StatusTeilung);
SendMessage(hStatusLeiste, SB_SETTEXT, 1, (LPARAM)" 000"); MausRad=0;
SendMessage(hStatusLeiste, SB_SETTEXT, 2, (LPARAM)" Statusleiste 3. Eintrag");
//-------- Child-Fenster:
Klasse.lpszClassName = "Childfenster" ; // Klassenname
Klasse.lpfnWndProc = (WNDPROC)ChildFensterProzedur; // Name der Prozedur dieses Fensters
Klasse.hCursor = LoadCursor(NULL, IDC_CROSS); // Cursor als Kreuz
Klasse.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"ChildFensterklasse konnte\n nicht registriert werden","Fehler", MB_OK); return 0;}
hChildFenster = CreateWindowEx (0, "Childfenster", "Titel des ChildFensters",
WS_OVERLAPPEDWINDOW | WS_VISIBLE |WS_CLIPSIBLINGS,
300, 250, 250, 200, hChildFenster, NULL, hInstanz, NULL);
//--------
ShowWindow (hFenster, nFensterStil); // ... und sichtbar machen
while (GetMessage (&Befehle, NULL, 0, 0)) // Dauerschleife (sendet Befehle an die Fensterprozeduren)
{TranslateMessage(&Befehle); DispatchMessage(&Befehle);}
return Befehle.wParam; }
|
|
Tastatur und Toggle-Tasten :
Dieses Beispiel zeigt eine verallgemeinerte Lösung für Tastaturereignisse (benötigt die Include-Datei
stdbool.h).
Häufig möchte man einzelne Tasten dazu verwenden, um zwischen zwei
Modi zu wechseln. Die beiden Bool-Arrays Tasten und
ToggleTasten speichern den Tastenzustand und einen entsprechenden Schaltzustand ("ON/OFF") für
jede Taste. Diese globalen Variablen sind jederzeit und in jeder
Prozedur abrufbar. ESC beendet das Programm, weitere belegte Tasten sind:
Space: Toggel ON/OFF
F1: anzeigen
Buchstabe a: anzeigen
Linke Pfeil-Taste: anzeigen
|
|
// Win32-API: Simple Window and keyboard events (Author: Claude Jacobs, 2013)
// Space (=ON/OFF), F1, 'a', Linke Pfeil-Taste
#include <windows.h>
#include <stdbool.h>
//============== Globale Variablen deklarieren =====================
HWND hFenster ; // Handle des Fensters deklarieren
bool Tasten[256], ToggleTasten[256];
char STR[255]="";
//============== Prozedur des Fensters =============================
LRESULT CALLBACK FensterProzedur (HWND hFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{
case WM_KEYDOWN :
{strcpy(STR,"");
if (Tasten[wParam] == FALSE)
{Tasten[wParam] = TRUE; ToggleTasten[wParam] = Tasten[wParam]^ToggleTasten[wParam];}
if (ToggleTasten[VK_SPACE]) {strcpy(STR,"SPACE=ON ");} else {strcpy(STR,"SPACE=OFF ");}
if (Tasten[VK_F1]) {strcat(STR, "F1-Taste");}
if (Tasten[VK_LEFT]) {strcat(STR, "Pfeiltaste");}
if (Tasten['A']) {strcat(STR, "Taste a");}
if (Tasten[VK_ESCAPE]) {PostQuitMessage (0); break;} // Programm beenden
SendMessage(hFenster, WM_SETTEXT, 0, (LPARAM)STR); // Text auf Titelleiste
break;}
case WM_KEYUP : {Tasten[wParam] = FALSE; break;}
case WM_DESTROY: {PostQuitMessage (0); break;} // Programm beenden
default: {return DefWindowProc (hFenster, Befehle, wParam, lParam);}
}
return 0; }
//============== HAUPTFUNKTION (und das Fenster erzeugen) ===========
int WINAPI WinMain (HINSTANCE hInstanz, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFensterStil)
{ MSG Befehle; // eine Message-Variable deklarieren
WNDCLASSEX Klasse; // eine Fensterklassen-Variable deklarieren (für wichtige Parameter des Fensters)
Klasse.lpszClassName = "Hauptfenster" ; // Klassenname
Klasse.lpfnWndProc = FensterProzedur ; // Name der Prozedur dieses Fensters
Klasse.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
Klasse.hCursor = LoadCursor (NULL, IDC_ARROW);
Klasse.cbSize = sizeof (WNDCLASSEX);
Klasse.hInstance = hInstanz;
Klasse.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
Klasse.hIcon = LoadIcon (NULL, IDI_APPLICATION);
Klasse.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
Klasse.lpszMenuName = NULL; // Fenster hat kein Menü
Klasse.cbClsExtra = 0;
Klasse.cbWndExtra = 0;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"Fensterklasse konnte\n nicht registriert werden","Fehler", MB_OK); return 0;}
hFenster = CreateWindow ("Hauptfenster", "Titel des Fensters", WS_OVERLAPPEDWINDOW,
// Hauptfenster erzeugen :
40, 20, 400, 300, HWND_DESKTOP, NULL, hInstanz, NULL);
ShowWindow (hFenster, nFensterStil); // ... und sichtbar machen
while (GetMessage (&Befehle, NULL, 0, 0)) // Dauerschleife (sendet Befehle an obige Fensterprozedur)
{TranslateMessage(&Befehle); DispatchMessage(&Befehle);}
return Befehle.wParam; }
|
|
Timer :
Die Funktion SetTimer startet bezüglich dem angegebenen Intervall einen periodischen Aufruf der
betreffenden Prozedur (hier ZeitProzedur genannt).
Sie erzeugt ebenfalls eine Kennzahl (hier in der Integer-Variablen Timer1Nummer gespeichert),
die den Timer eindeutig identifiziert und beispielsweise als Parameter von KillTimer den
Vorgang beenden kann. Mehrere Timer -mit ihren entsprechenden Prozeduren- können gleichzeitig laufen.
Dieses Programm zeigt einen Zähler, der beim zehnten Intervall den Timer selbständig stoppt.
Um verwirrende zusätzliche Programmzeilen zu vermeiden, dient die
Titelleiste des Fensters in diesem Beispiel als Textausgabefeld.
|
|
// Win32-API: Simple Window with timer (Author: Claude Jacobs, 2013)
#include <windows.h>
#include <stdio.h>
//============== Globale Variablen deklarieren =====================
HWND hFenster ; // Handle des Fensters deklarieren
int Timer1Nummer; int Zahl; char STR[255]="";
//============== Prozedur des Fensters =============================
LRESULT CALLBACK FensterProzedur (HWND hFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{case WM_DESTROY: {PostQuitMessage (0); break;} // Programm beenden
default: {return DefWindowProc (hFenster, Befehle, wParam, lParam);}
}
return 0; }
//================= Timer-Prozedur ===============================
void CALLBACK ZeitProzedur(HWND hFenster, UINT Befehle, UINT idEvent, DWORD dwTime)
{Zahl++; sprintf(STR,"%d",Zahl);
SendMessage(hFenster, WM_SETTEXT, 0, (LPARAM)STR); // Zahl (als String) in Titelleiste
if (Zahl==10) {KillTimer(hFenster, Timer1Nummer);} // Timer abschalten
}
//============== HAUPTFUNKTION (und das Fenster erzeugen) ===========
int WINAPI WinMain (HINSTANCE hInstanz, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFensterStil)
{ MSG Befehle; // eine Message-Variable deklarieren
WNDCLASSEX Klasse; // eine Fensterklassen-Variable deklarieren (für wichtige Parameter des Fensters)
Klasse.lpszClassName = "Hauptfenster" ; // Klassenname
Klasse.lpfnWndProc = FensterProzedur ; // Name der Prozedur dieses Fensters
Klasse.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
Klasse.hCursor = LoadCursor (NULL, IDC_ARROW);
Klasse.cbSize = sizeof (WNDCLASSEX);
Klasse.hInstance = hInstanz;
Klasse.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
Klasse.hIcon = LoadIcon (NULL, IDI_APPLICATION);
Klasse.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
Klasse.lpszMenuName = NULL; // Fenster hat kein Menü
Klasse.cbClsExtra = 0;
Klasse.cbWndExtra = 0;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"Fensterklasse konnte\n nicht registriert werden","Fehler", MB_OK); return 0;}
hFenster = CreateWindow ("Hauptfenster", "Titel des Fensters", WS_OVERLAPPEDWINDOW,
// Hauptfenster erzeugen :
40, 20, 400, 300, HWND_DESKTOP, NULL, hInstanz, NULL);
ShowWindow (hFenster, nFensterStil); // ... und sichtbar machen
Timer1Nummer=SetTimer(hFenster, 1, 500, ZeitProzedur); // Timer "ZeitProzedur" starten (500 ms)
while (GetMessage (&Befehle, NULL, 0, 0)) // Dauerschleife (sendet Befehle an obige Fensterprozedur)
{TranslateMessage(&Befehle); DispatchMessage(&Befehle);}
return Befehle.wParam;}
|
DISCLAIMER: THIS SITE CONTAINS LINKS TO THIRD-PARTY WEBSITES, WHICH ARE NOT UNDER THE CONTROL OF STS.
THESE LINKS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
|
© 2013: STS Selected Technology Sites, all rights reserved.
|
|