Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

Lutz Ifers WinAPI Tutorial

von RedakteurMODSeite 11 von 16

Kapitel 4.1: Zweitfenster
Kap4.1

Ein Fenster ist gut, zwei Fenster sind besser und wenn man weiß, wie man sich beliebig viele Fenster macht, ist das am aller besten. Da der olle Lutz ein fauler Sack ist, demonstrieren wir hier nur, wie man die Fenster erzeugt - ansonsten machen die Fenster im Moment noch gar nichts, als CallBack-Funktion tragen wir in die Fensterklasse nämlich direkt die Default-Window-Procedure ein.

Nochmal zur Unterscheidung zwischen Fenster und Fensterklasse: Mehrere Fenster können die selbe Fensterklasse haben, aber kein Fenster mehrere Fensterklassen. Die Fensterklasse bestimmt die Callback-Funktion der Fenster, soll heißen: Selbe Callbackfunktion = selbe Funktion der Fenster. Trotzdem kann der Inhalt der Fenster unterschiedlich sein. Ein Beispiel: Buttons sind auch nur Fenster, wie wir später lernen werden. Sie teilen sich alle die selbe Fensterklasse, schicken beim Klicken also alle die selben Nachrichten ab. Ihr Inhalt (die Beschriftung, bzw. defacto ist es bei Buttons der Fenstertitel) kann unterschiedlich sein.

Für unserere Zweitfenster legen wir also eine eigene Fensterklasse an, die neben der anderen Callback-Funktion einen weiteren Unterschied zu Fensterklasse unseres (Haupt-)Fensters hat: Bei Style definieren wir zusätzlich "CS_NOCLOSE" - das kleine X wird also ausgegraut, ansonsten wäre es möglich, die Nebenfenster (einzeln) zu schließen.


''' Lutz Ifers WinAPI-Tutorial
''' Lizenz: WTFPL
'''
''' Kapitel 4.1 - "Zweitfenster"

#include "windows.bi"
const ProgrammName = "Zweitfenster"
const NebenfensterName = "Nebenfenster"

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 WNDCLASS wcNebenFenster
with wcNebenFenster
    .style         =  CS_HREDRAW or CS_VREDRAW or CS_NOCLOSE
    .lpfnWndProc   =  ProcPtr(DefWindowProc)
    .cbClsExtra    =  0
    .cbWndExtra    =  0
    .hInstance     =  GetModuleHandle(NULL)
    .hCursor       =  LoadCursor(NULL, IDC_ARROW)
    .hIcon         =  LoadIcon(NULL, IDI_APPLICATION)
    .hbrBackground =  GetStockObject(WHITE_BRUSH)
    .lpszClassName =  StrPtr(NebenfensterName)
    .lpszMenuName  =  NULL
end with
RegisterClass @wcNebenFenster

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

Trotz mehrerer Fenster und Fensterklassen benötigen wir nur eine Nachrichtenschleife: GetMessage empfängt alle Nachrichten eines Programmes (mit all seinen Fenstern); DispatchMessage sortiert die Nachrichten nach Fenster und leitet sie an die zugehörigen Callback-Funktionen weiter.

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
    static as POINT ptStart, ptEnde
    dim    as HDC   hDC

    select case message
        case WM_DESTROY
            PostQuitMessage 0
            return 0

        case WM_CREATE
            hFensterA = CreateWindow(NebenfensterName,_
                "Vollwertiges Zweitfenster",_
                WS_OVERLAPPEDWINDOW or WS_VISIBLE,_
                CW_USEDEFAULT, CW_USEDEFAULT, 200, 100,_
                hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
            hFensterB = CreateWindow(NebenfensterName,_
                "Ohne alles",_
                WS_VISIBLE,_
                CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,_
                hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
            hFensterC = CreateWindow(NebenfensterName,_
                "Vielleicht Menübar",_
                WS_VISIBLE or WS_OVERLAPPED or WS_SYSMENU,_
                CW_USEDEFAULT, CW_USEDEFAULT, 300, 150,_
                hWnd, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
            hFensterD = CreateWindow(NebenfensterName,_
                "Selbstständig",_
                WS_OVERLAPPEDWINDOW or WS_VISIBLE,_
                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,_
                NULL, NULL, cast(LPCREATESTRUCT,lParam)->hInstance, NULL)
            return 0
    end select
    return DefWindowProc( hWnd, message, wParam, lParam )
end function

Wir erzeugen die Fenster mit der gleichen Funktion, CreateWindow, wie unser Hauptfenster. Theoretisch hätten wir das auch im Hauptprogramm machen können, allerdings werden die Rückgabewerte der Funktion, die Handles zu den einzelnen Funktionen zunehmend interessanter (wir werden später lernen, wie man die Fenster bewegt, versteckt, wieder anzeigt, minimiert, maximiert, Nachrichten schickt usw.), weshalb wir diese Werte in der Callbackfunktion benötigen, daher werden die Variablen auch als static definiert.

Als Parentwindow geben wir bis auf FensterD das "große" Hauptfenster an - damit gehören diese Fenster zum Hauptfenster, FensterD ist eigenständig, und erscheint deshalb auch in der Taskleiste als eigenständiger Eintrag.

Aber das eigentlich interessante am ganzen Fenstererstellen sind die verschieden Styles, die wir für die Fenster verwenden können. WS_VISIBLE erzeugt die Fenster aktiv, wir müssen sie nicht wie das Hauptfenster erst mit ShowWindow aktivieren. OVERLAPPEDWINDOW, eine Kombination aus mehreren anderen Style-Flags steht für die "normalen" Fenster, mit verschiebbarer Größe, Systemmenü (dem Icon links oben), Maximieren- und Minimieren-Icon. Die Namen der Styles sind soweit selbsterklärend - eine vollständige Liste findet sich in der MSDN unter Windowstyles.

Links:

In der MSDN: Externer Link!CreateWindow, Externer Link!Windowstyles

 

Gehe zu Seite Gehe zu Seite  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  
Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 17.09.2009 von RedakteurMOD angelegt.
  • Die aktuellste Version wurde am 17.07.2013 von AdministratorSebastian gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen