Tutorial
Lutz Ifers WinAPI Tutorial
von MOD | Seite 10 von 16 |
Kapitel 3.2: Maus
Nachdem wir nun wissen, wie wir kontrollieren können, ob der Benutzer eine Taste gedrückt hat, fehlen uns noch die Methoden, um in Erfahrung zu bringen, ob die Maus bewegt wurde, bzw. in unser Fenster geklickt wurde.
''' Lutz Ifers WinAPI-Tutorial
''' Lizenz: WTFPL
'''
''' Kapitel 3.2 - "Maus"
#include "windows.bi"
const ProgrammName = "Maus"
declare function Fenster(byval hWnd as HWND, byval message as UINTEGER,_
byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
dim as WNDCLASS wcMeinFenster
with wcMeinFenster
.style = CS_HREDRAW or CS_VREDRAW
.lpfnWndProc = ProcPtr(Fenster)
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = GetModuleHandle(NULL)
.hCursor = LoadCursor(NULL, IDC_ARROW)
.hIcon = LoadIcon(NULL, IDI_APPLICATION)
.hbrBackground = GetStockObject(WHITE_BRUSH)
.lpszClassName = StrPtr(ProgrammName)
.lpszMenuName = NULL
end with
RegisterClass @wcMeinFenster
dim as HWND hMeinFenster = CreateWindow(_
ProgrammName, "Titelzeile", WS_OVERLAPPEDWINDOW,_
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,_
NULL, NULL, GetModuleHandle(NULL), NULL)
ShowWindow hMeinFenster, SW_NORMAL
UpdateWindow hMeinFenster
dim as MSG msg
do while getmessage(@msg, NULL, 0, 0) <> 0
DispatchMessage @msg
loop
end msg.wParam
In der Callback-Funktion verwenden wir erstmals ein UDT namens POINT. Da dies auch ein Schlüsselwort von FreeBasic ist, gibt es häufiger Probleme, wenn die FreeBasic-Funktion point() verwendet wird und die windows.bi-Headerdatei eingebunden ist. Dies soll uns aber nicht weiter stören, da wir point() sowieso nicht auf Windows-Fenstern benutzen können.
Die Variable für den Device Context definieren wir ausnahmsweise nicht erst im WM_PAINT-Zweig der select case-Anweisung, sondern davor, damit wir die gleiche Variable in einem anderen Zweig verwenden können. Natürlich könnte man auch einfach zwei Variablen nehmen, oder eine C-ähnliche Umgebung mit scope ... end scope erzeugen - aber warum umständlicher als unbedingt notwendig.
function Fenster(byval hWnd as HWND, byval message as UINTEGER,_
byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
static as POINT ptStart, ptEnde
dim as HDC hDC
select case message
case WM_DESTROY
PostQuitMessage 0
return 0
case WM_LBUTTONDOWN
ptStart.x = LOWORD(lParam)
ptStart.y = HIWORD(lParam)
hDC = GetDC(hWnd)
Ellipse hDC, ptStart.x - 5, ptStart.y - 5,_
ptStart.x + 5, ptStart.y + 5
ReleaseDC hWnd, hDC
return 0
case WM_LBUTTONUP
ptEnde.x = LOWORD(lParam)
ptEnde.y = HIWORD(lParam)
hDC = GetDC(hWnd)
Ellipse hDC, ptEnde.x - 5, ptEnde.y - 5,_
ptEnde.x + 5, ptEnde.y + 5
ReleaseDC hWnd, hDC
return 0
Die Nachrichten WM_LBUTTONDOWN und WM_LBUTTONUP werden uns von Windows geschickt, wenn die linke Maustaste gedrückt bzw. losgelassen wird. Für die rechte Maustaste gelten die Nachrichten WM_RMOUSEBUTTONUP/DOWN. Sowohl die Nachrichten für Tastedrücke, als auch die Nachricht für Mausbewegungen enthalten Informationen über Zustand der Tasten als auch Position der Maus. Um den Unterschied der zwischen beiden Nachrichten besteht zu verdeutlichen, wird beim Klicken und Loslassen (allerdings nicht beim Gedrückthalten) der Maustaste ein Kreis um den Cursor gezeichnet.
case WM_MOUSEMOVE
if (wParam and MK_LBUTTON) <> 0 then
ptEnde.x = LOWORD(lParam)
ptEnde.y = HIWORD(lParam)
InvalidateRect hWnd, NULL, TRUE
end if
return 0
case WM_PAINT
dim as PAINTSTRUCT ps
dim as STRING sText = "Maus: "+str(ptEnde.x)+", "+str(ptEnde.y)
hDC = BeginPaint(hWnd, @ps)
TextOut hDC, 0, 0, sText, len(sText)
MoveToEx hDC, ptStart.x, ptStart.y, NULL
LineTo hDC, ptEnde.x, ptEnde.y
EndPaint(hWnd, @ps)
return 0
end select
return DefWindowProc( hWnd, message, wParam, lParam )
end function
Bei einer Bewegung der Maus wird der Zweite Punkt (also der Endpunkt der Linie) aktualisiert, und bei WM_PAINT-Nachrichten wird diese Linie neugezeichnet.
Links:
In der MSDN: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, WM_MOUSEMOVE, GetDC
In der FreeBasic-Referenz: POINT
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|