Tutorial
Lutz Ifers WinAPI Tutorial
von MOD | Seite 12 von 16 |
Kapitel 4.2: Childwindows
In Kapitel 4.1 hatte ich schon verraten, dass Buttons auch nur Fenster sind, und in diesem Kapitel, in dem es um Childwindows geht, werden wir etwas kreieren, dass schon sehr nach Button aussieht. Ich hatte ebenfalls im letzten Kapitel den Unterschied zwischen Fenster und Fensterklasse erwähnt, und werde das hier noch einmal verdeutlichen: Die Childwindows die wir erstellen werden, sehen alle unterschiedlich aus, haben unterschiedlichen Inhalt, aber haben alle die selbe Callback-Funktion, und damit auch die selbe Funktion.
''' Lutz Ifers WinAPI-Tutorial
''' Lizenz: WTFPL
'''
''' Kapitel 4.2 - "Childwindows"
#include "windows.bi"
const ProgrammName = "Childwindows"
const ChildfensterName = "Child"
declare function Fenster(byval hWnd as HWND, byval message as UINTEGER,_
byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare function ChildFenster(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(LTGRAY_BRUSH)
.lpszClassName = StrPtr(ProgrammName)
.lpszMenuName = NULL
end with
RegisterClass @wcMeinFenster
dim as WNDCLASS wcChildFenster
with wcChildFenster
.style = CS_HREDRAW or CS_VREDRAW
.lpfnWndProc = ProcPtr(Childfenster)
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = GetModuleHandle(NULL)
.hCursor = LoadCursor(NULL, IDC_ARROW)
.hIcon = LoadIcon(NULL, IDI_APPLICATION)
.hbrBackground = GetStockObject(WHITE_BRUSH)
.lpszClassName = StrPtr(ChildfensterName)
.lpszMenuName = NULL
end with
RegisterClass @wcChildFenster
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
Nachdem wir wieder zwei Fensterklassen (eine für unser Hauptfenster, eine für die Childwindows) erstellt haben, wenden wir uns der Callback-Funktion des Hauptfensters zu. Im Zweig der WM_CREATE-Message, die unserem Fenster nach erzeugen zugeschickt wird, lassen wir die Childfenster mit unterschiedlichen Styles erzeugen. Ein Style-Flag verdient denke ich besondere Aufmerksamkeit, und das ist WS_CLIPSIBLINGS: Wenn sich zwei Childwindows überlappen, und auf dem einen ChildWindow wird gezeichnet, wird in den Bereich des anderen Fensters gezeichnet. WS_CLIPSIBLINGS verursacht in diesem Fall, dass allen Überlappenden Fenstern eine WM_PAINT nachricht zugeschickt wird, damit ihre Inhalte ebenfalls aktualisiert werden. Besonders deutlich wird das, wenn in diesem Beispiel die WM_CLIPSIBLINGS-Flags gelöscht werden, und das verschiebbare Fenster über die Childfenster gezogen wird.
function Fenster(byval hWnd as HWND, byval message as UINTEGER,_
byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
static as HWND hFensterA, hFensterB, hFensterC, hFensterD
select case message
case WM_DESTROY
PostQuitMessage 0
return 0
case WM_CREATE
hFensterD = CreateWindow(ChildfensterName,_
"Schieb mich",_
WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or WS_OVERLAPPEDWINDOW ,_
10, 120, 320, 100,_
hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
hFensterA = CreateWindow(ChildfensterName,_
"Ohne Alles",_
WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS,_
10, 10, 100, 100,_
hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
hFensterB = CreateWindow(ChildfensterName,_
"Rand",_
WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or WS_BORDER,_
120, 10, 100, 100,_
hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
hFensterC = CreateWindow(ChildfensterName,_
"Viel Rand",_
WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or WS_DLGFRAME,_
230, 10, 100, 100,_
hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
return 0
end select
return DefWindowProc( hWnd, message, wParam, lParam )
end function
Nun sehen wir uns die Callback-Funktion der Childwindows an. Wir kümmern uns ausschließlich um die WM_PAINT-Nachrichten, und leiten alle anderen Nachrichten an die Default-Window-Procedure weiter. Mit der Funktion GetWindowText erfahren wir den Titel des Fensters, für das die Funktion grade aufgerufen wurde. Diesen Fenstertitel schreiben wir in das Fenster.
function Childfenster(byval hWnd as HWND, byval message as UINTEGER,_
byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
select case message
case WM_PAINT
dim as ZSTRING*100 text
dim as PAINTSTRUCT ps
dim as HDC hDC = BeginPaint(hWnd, @ps)
GetWindowText hWnd, text, sizeof(text)
TextOut hDC, 5, 5, text, len(text)
EndPaint hWnd, @ps
return 0
end select
return DefWindowProc(hWnd, message, wParam, lParam)
end function
Das dritte Childwindow, FensterC, sieht schon stark nach einem Button aus, funktioniert allerdings nicht wie einer. Wie man richtige Buttons erzeugt, ist Thema von Kapitel 4.5
Links:
In der MSDN: CreateWindow, Windowstyles
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|