STS Homepage
3D VIRTUAL DEVELOPMENT SERVICES:
http://homepages.internet.lu/absolute3d/default.htm
Einführung in die Win32-API unter C/C++
Win32-API Tutorial in C/C++
copyright 2013: Claude Jacobs
from original site:
http://homepages.internet.lu/absolute3/tronic/default.htm
PREVIOUS NEXT

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;}
PREVIOUS NEXT
© 2013 by Claude Jacobs URL: http://homepages.internet.lu/absolute3/tronic/default.htm

Weiterführende Links:
http://cplus.kompf.de/links.html (Umfangreiche Linksammlung: C/C++ in versch. Bereiche untergliedert)
http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html (Bücher zum Download: C u. C++)
http://openbook.galileocomputing.de/c_von_a_bis_z/ ("C von A bis Z")
http://www.cplusplus.com/ (C/C++, allgemein)
http://www.carabez.com/downloads.html (u.a. versch. win32api Help-Dateien)
http://www.cs.virginia.edu/~lcc-win32/ download: Windows API documentation (win32api Help-Datei)
http://win32asm.rxsp.com/download.html (Win32.hlp, including graphics)

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.