|
Home - Programmieren - Windows - Windows Programmierung
Hinweis: Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich. Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren. [Druckansicht] [Als E-Mail senden] [Kommentar verfassen] Windows-Programmierung: das GrundgerüstUnd wieder einmal ein Rahmenprogramm für ein einfaches Windowsprogramm. Diesmal ist es mit Hyperlinks ausgestattet, so daß man zwischen Erklärung und Source hin- und herspringen kann. Vielleicht veranschaulicht das etwas, zumindest macht es Spaß. MainWinMainWin heißt das Hauptprogramm unter Windows. Per Parameter erhält es seine Instanz, auf der es seine Initialisierung aufsetzt. Es registriert die Fensterklasse, erzeugt das Hauptfenster und läuft in eine Schleife, in der es alle Messages verteilt, bis die "Null-Message" die Schleife beendet. Dies führt das zum Ende des Programms.
Die InstanzPer Parameter erhält MainWin die Instanz von Windows. Diese Variable wird bei Aufrufen von diversen Funktionen benötigt, die an Windows gehen. An dieser Variablen erkennt Windows die Applikation wieder, auch dann, wenn sie kein Fenster geöffnet hat. Aus diesem Grund wird sie von den meisten Windowsprogrammen in einer globalen Variable gespeichert und direkt zugegriffen.MyRegisterClassDas Hauptfenster wird registriert und bei Windows angemeldet. Die Registrierung ist die Anmeldung einer Fensterklasse. Es können also auch mehrere Fenster der gleichen Klasse angemeldet werden.Der RegisterClass-StringWelches Fenster zu welcher Klasse gehört, wird nicht durch ein Handle, sondern durch eine Zeichenkette beschrieben. Da diese Zeichenkette exakt identisch sein muß, wird dieser String zu Anfang in einem define-Statement festgelegt oder sogar in den Ressourcen abgelegt. Wichtig ist, daß er das Fenster im laufenden System eindeutig bezeichnet. Er wird einmal bei der Registrierung der Klasse und dann noch einmal beim Erzeugen des Fensters verwendet.
Festlegen der EigenschaftenDas Registrieren der Klasse gibt Windows bekannt, welche Eigenschaften die Fenster dieser Klasse haben werden. Die wichtigste Information ist dabei die Adresse der Fensterfunktion WndProc. Da die Fensterklasse auf alle Ereignisse reagiert, bestimmt sie maßgeblich das Verhalten des Fensters.InitMainWindowIn InitMainWindow wird das Fenster erzeugt (create) und angezeigt. In vielen Beispielen wird diese Funktion als InitInstance benannt.Das Fenster wird durch den RegisterClass-String als zu der registrierten Klasse gehöriges Fenster erzeugt. Als zweiten String hat das Fenster szTitle. Das ist der Text, der im blauen Balken zu sehen ist. Er hat nur informellen Charakter und könnte auch leer sein. Da dieser String oft sprachenabhängig ist, würde es Sinn machen, ihn in der Ressource abzulegen. Die FensterfunktionDie Fensterfunktion behandelt diejenigen Ereignisse, die auf das Fenster einstürmen. Die Funktion wird von Windows gerufen, wenn immer ein Ereignis für dieses Fenster vorliegt.Windows liefert vier Parameter mit. Der erste ist das Handle (HWND) des Fensters Dies ist besonders wichtig, wenn es mehrere Fenster gleichen Typs gibt. Der zweite Parameter ist der Typ der Message. Typischerweise besteht eine Fensterfunktion in erster Linie aus einer großend Fallunterscheidung über diese Variable. Die beiden restlichen Variablen sind Parameter des Typs. So liefert die WM_SIZE in diesen Parametern die neue Ausdehnung des Fensters.
Die Default-Fensterfunktion DefWindowProcWerden Nachrichten nicht behandelt oder werden nur Teilaspekte des Ereignisses verarbeitet, so ruft die Fensterfunktion die Funktion DefWindowProc und übergibt ihr die Parameter, die sie von Windows erhalten hat. DefWindowProc ist die Default-Fensterfunktion und behandelt alle Ereignisse mit der Standardreaktion. So wird beispielsweise das Fenster vergrößert oder mit der Hintergrundfarbe weiß versehen.Das MenüDefinitionIn der Ressource wird das Menü beschriebenAnmeldungDas Menü wird beim Registrieren der Fensterklasse dem Fenster zugeordnet. Dazu wird dem Element lpszMenuName der Fensterklassenstruktur der in der Ressource definierte Namen des Menüs zugewiesen.Ereignis der MenüauswahlDas Anklicken eines Menüpunktes löst eine Nachricht WM_COMMAND aus, die in der Fensterfunktion verarbeitet wird. Welcher Menüpunkt ausgewählt wurde, ist im niedrigeren Teil des ersten Parameters wParam kodiert. Für das Extrahieren stellt Windows das Makro LOWORD zur Verfügung.Der FensterinhaltAlles, was im Fenster gezeichnet oder angezeigt werden soll, wird nicht direkt auf das Fenster gezeichnet. Das hätte den Nachteil, daß alles verschwunden ist, wenn das Fenster kurzzeitig überdeckt wurde. Ein Fenster erhält in dem Falle, daß der Inhalt neu zu zeichnen ist, die Nachricht WM_PAINT. Hier muß es seinen Inhalt neu darstellen. Den gleichen Mechanismus benutzt man, wenn man im Fenster zeichnen will. Man manipuliert die Daten, aus denen die Fensterfunktion das Fenster rekonstruiert und ruft die Funktion Invalidate auf, und täuscht so dem Fenster vor, daß eine Neuzeichnung notwendig sei.Beenden einer Windows-AnwendungDer Menüpunkt für das Ende der Applikation ruft WindowDestroy auf. Dies erzeugt wiederum die Nachricht WM_DESTROY an das eigene Fenster. Hier erst setzt die Anwendung den Befehl PostQuitMessage(0); ab, das wiederum eine Nachricht absetzt. Das "Post" führt aber im Gegensatz zu "Send" dazu, daß an dieser Stelle nicht auf die Abarbeitung gewartet wird.Die Quit-Nachricht wird nicht in der Fensterfunktion bearbeitet, sondern bewirkt ein Unterbrechen der Main-Loop und führt so zum Ende der Applikation. Der scheinbare Umweg über das Nachrichtensystem führt dazu, daß alle beteiligten Komponenten informiert sind, daß dieses Programm sich abbaut. Der Source
Die Resourcen
Die Headerdatei der Ressourcen
Windows Programmierung: RessourcenRessourcen werden heutzutage fast nur noch mit grafischen Editoren bearbeitet. Sie sind aber im Grunde ASCII-Quelltexte, die mit jedem einfachen Editor nachbearbeitet werden können. Bedauerlich ist lediglich, dass wenn einmal ein Fehler in die Ressource Quelldatei gekommen ist, der Ressouce-Compiler meist keine grosse Hilfe darstellt. Insofern sollte man Änderungen von Hand sehr vorsichtig und nie ohne Backup vornehmen.Strings aus Ressourcen ladenDer String wird in einem Stringtable in der Ressource definiert. Der Zweck dieses Tuns liegt darin, daß internationale Versionen allein durch Änderung der Ressourcen erstellbar sind.
Bitmap aus Ressourcen ladenMit der Funktion LoadBitmap kann eine Bitmap in der Ressource geladen werden. Als Ergebnis bekommt man das HBITMAP. Im Beispiel, das aus einer WM_PAINT-Bearbeitung stammt, wird der Hintergrund mit der Bitmap gekachelt.
Die Bitmap muss anschliessend per DeleteObject freigegeben werden. Windows Programmierung: MenüDie Ressourcendefinition
Dass ein Fenster ein Menü hat, wird bei der Registrierung der Fensterklasse angegeben. Empfangen eines MenüereignissesIn der Fensterfunktion wird die Nachricht WM_COMMAND empfangen. Am einfachsten unterscheidet man die Menüpunkt, indem man das niedrigere Halbwort des wParamters verwendet. Hier steht dieselbe ID, die bei der Ressourcendefinition verwendet worden ist.
Haken an das Menü setzenIm Fenster des Menüs ruft man die Funktion CheckMenuItem. Im letzten Parameter muss MF_CHECKED oder MF_UNCHECKED übergeben werden, je nachdem, ob man einen Haken will oder nicht. Es reicht nicht, dort 0 oder 1 zu übergeben. Hängt der Haken von einem booleschen Wert ab, geht man wie folgt vor, um das Menü-Item IDM_KONTEXTINDEX umzuschalten:
Um das Menü-Handle zu bekommen, ruft man GetMenu mit dem HWND des Fensters auf, das das Menü enthält. Menüpunkt deaktivierenIm Fenster des Menüs ruft man die Funktion EnableMenuItem. Im letzten Parameter muss MF_ENABLED oder MF_GRAYED übergeben werden. Es gibt auch ein MF_DISABLED, das auch den Menüpunkt deaktiviert. Allerdings liefert dies keine optische Rückmeldung. In den allermeisten Fällen macht dies aber keinen Sinn.
Windows Programmierung: KontextmenüDas Kontextmenü erscheint auf den Klick mit der rechten Maustaste.Die Ressourcendefinition
FensterfunktionIn der Fensterfunktion wird das Ereignis WM_CONTEXTMENU gefangen
Im Gegensatz zu WM_LBUTTONDBLCLK kommen hier die Koordinaten der Maus in Screen- und nicht in Client-koordinaten. Für unsere Zwecke wird sie mit der Windowsfunktion ScreenToClient umgewandelt.
Nachdem geprüft ist, ob der Cursor auch im Clientbereich des Fensters ist, kann nun das Menü erzeugt und bearbeitet werden.
Mit LoadMenu wird das in der Ressource definierte Menü geladen. TrackPopupMenu kann nicht das Toplevel-Menü anzeigen. Dieses wird nur als Dummy benötigt. Stattdessen wird mit GetSubMenu der erste Menüpunkt für die weitere Bearbeitung ermittelt. Nach der Verfolgung der Maus wird das Menü wieder zerstört. In der weiteren Bearbeitung wird durch das Auswählen eines Punktes ein WM_COMMAND ausgelöst. LiteraturNancy Cluts: Programmierung für die Benutzeroberfläche von Windows 95, Microsoft Press, 1995. Seite 247-248.Windows Programmierung: Dialogboxen
Eine einfache DialogboxDie Dialogbox wird im Ressource-Editor gestaltet. Das Ergebnis ist eine Datei mit der Endung rc, die zum Projekt hinzugebunden wird. Der Ressource-Compiler erstellt eine Datei mit der Endung res.Im Ressource-Editor erhält sowohl die Dialogbox als auch jedes Kontrollelement des Dialogs eine Kennung (SHORT), über die sie identifizierbar ist. Wie bei einem Fenster gibt es eine Fensterfunktion, die das Verhalten des Fensters festlegt. Eine Dialogfensterfunktion unterscheidet sich in einigen Details von der normalen Fensterfunktion. So lautet die Initialisierungsnachricht WM_INITDIALOG statt WM_CREATE. Das Ende der Dialogbox erfolgt durch den Aufruf von EndDialog. Dabei wird der zweite Parameter der von EndDialog der aufrufenden Funktion zurückgegeben.
Der Start der Dialogbox erfolgt durch den Aufruf der Funktion DialogBox oder einer ihrer Verwandten. Durch die Parameter wird festgelegt, welche Ressource-ID und welche Dialogfensterfunktion herangezogen wird. Das Programm erhält erst dann wieder die Kontrolle, wenn die Dialogfensterfunktion EndDialog aufruft und mit dieser Funktion auch den Rückgabewert von DialogBox bestimmt. Dialogbox mit ParameternIn vielen Fällen möchte man der Dialogbox Daten übergeben. Dies funktioniert natürlich auch mit globalen Variablen. Abgesehen von der mangelnden Eleganz scheitert diese Methode spätestens bei rekursiven Aufrufen der Dialogbox.Die Funktion DialogBoxParam verhält sich wie DialogBox. Sie erlaubt aber einen LONG als Parameter, der an die Dialogbox weitergereicht wird. Da man darüber auch einen Zeiger übergeben kann, sind beliebige Daten zu übermitteln.
In der Fensterfunktion wird er beim Eintreten der Message WM_INITDIALOG einfach aus dem lParam gelesen. Hierin befindet sich der übergebene Wert.
Da bei jedem Ereignis die Funktion erneut gestartet wird, muss sich die Dialogbox die übermittelten Daten merken. Da man globale Variablen vermeiden will, muss man mit lokalen Fensterdaten arbeiten. Dialogbox mit lokalen Fensterdaten
Hier werden Daten im WM_INITDIALOG als Parameter übernommen (siehe oben) und gleich in die lokalen Fensterdaten geschoben (SetWindowLong). Bei jedem Ereignis werden diese lokalen Daten wieder neu geladen (GetWindowLong). Dadurch können mehrere Fenster gleichzeitig existieren, die mit eigenen, unabhängigen Daten arbeiten. Nicht-modale DialogboxenEine normale Dialogbox wird durch den Aufruf von DialogBox gestartet. Das Programm bleibt an dieser Stelle stehen und wartet auf das Schließen der Dialogbox. Der Anwender kann nicht weiterarbeiten, bis der Dialog beendet ist. Dieses Verhalten nennt man modal.In bestimmten Situationen ist dieses Verhalten unerwünscht. Ein Beispiel ist ein Fortschrittsanzeiger, der nur Sinn macht, wenn im Hintergrund das Programm weiterläuft. Das gleiche gilt für alle Abbruch-Dialoge. Eine nicht-modale Dialogbox wird nicht mit DialogBox, sondern durch den Aufruf CreateDialog und ein anschließendes ShowWindow erzeugt. Die Parameter für CreateDialog entsprechen denen von DialogBox. Auch die Fensterfunktion ist weitgehend identisch. Lediglich das Ende der Dialogbox wird durch DestroyWindow statt mit EndDialog eingeleitet. Das Programm läuft nach der Erzeugung ungehindert weiter. Im Beispiel wird eine Dialogbox erzeugt, die Fehlermeldungen in einer Liste darstellen soll.
Windows Programmierung: Property SheetDas Property Sheet ist kein Kontrollelement, sondern ein kompletter Dialog. Man kann ihn also nicht einfach in einem normalen Fenster unterbringen. Ein Property Sheet besteht aus mehreren Seiten, die jeweils wie eine Dialogbox in den Ressourcen definiert wird. Es werden lediglich der Ok- und der Abbruch-Buttonweggelassen, da diese vom Property-Sheet geliefert werden.Erzeugung eines Property SheetsZunächst wird im Ressource Editor für jede Seite ein Dialog erzeugt. Auch eine Dialogfensterfunktion wird für jede der Seiten geschrieben. Für jede Seite wird eine Struktur PROPSHEETPAGE zur Beschreibung angelegt, die in einem Array organisiert sind. Die Adresse dieses Arrays wird in der Struktur PROPSHEETHEADER eingetragen und mit der Adresse dieser Variable als Parameter wird die Funktion PropertySheet aufgerufen.Zur Vereinfachung des Beispiels wird nur ein Dialog und eine Dialogfensterfunktion für mehrere Seiten verwendet. Die Ressource-ID ist IDD_PERSON und die Fensterfunktion des Dialoges ist DataInput.
SeitendefinitionJede Seite erhält die Information über den zugehörigen Dialog. Das ist die Ressource-ID in pszTemplate und die Dialogfensterfunktion in pfnDlgProc. Das Element dwFlags besagt, welche Elemente vom Anwender vom Standard abweichend behandelt werden. In diesem Fall ist das pszTitle mit dem Text, der in der zugehörigen Lasche erscheinen soll.HeaderdefinitionHier werden die Dialogseiten zusammengefasst. Die Adresse des Seiten-Arrays wird in ppsp angegeben und die Anzahl der Seiten in nPages hinterlegt. Der Textzeiger in pszCaption legt fest, welcher Text in der Titelleiste des Dialogs erscheint.Wird im dwFlags-Element PSH_NOAPPLYNOW hinzugenommen (durch Odern mit | ), erscheint der Apply-Button nicht. Bei der Bestimmung der Grösse der PROPSHEETHEADER-Struktur ist die Angabe ungewöhnlich. Hier verwendet man üblicherweise eine Konstruktion wie psh.dwSize = sizeof(PROPSHEETHEADER);Allerdings besteht das Problem, daß mit der Version 4.71 der COMCTL32.DLL die Struktur etwas größer geworden ist. Da sizeof eine Konstante zur Laufzeit liefert, würde ein Entwicklungssystem, das einen Update hat, ein Programm erzeugen, das unter alten Versionen nicht läuft. Man kann dies verhindern, indem man psh.dwSize = PROPSHEETHEADER_V1_SIZE;verwendet. Will man dynamisch arbeiten, muß die Funktion DllGetVersion verwendet werden, um zu ermitteln, welche Version auf dem aktuellen System läuft. RückgabewertBei modalen Dialogen wird ein positiver Wert zurückgegeben, wenn der Dialog mit OK verlassen wurde, ansonsten -1.FensterfunktionDie Fensterfunktion unterscheidet sich auf den ersten Blick nicht von der eines normalen Dialogs. Sie verwaltet eine Seite, nicht den gesamten PropertySheet.
Bei der Initialisierung wird der Zeiger auf die PropertyPage, also die Seite übergeben. Da dieser Dialog mehrfach verwendet wird, muss man die Daten für jedes Objekt in den Fensterdaten sichern. Dies wird an anderer Stelle beschrieben. Wird für jede Seite eine andere Dialogfensterfunktion verwendet, ist das nicht notwendig. Die Fensterfunktion darf nicht EndDialog aufrufen. Statt der Behandlung von OK und Abbruch werden die WM_NOTIFY-Ereignisse PSN_SETACTIVE, PSN_APPLY, PSN_KILLACTIVE und PSN_RESET bearbeitet PSN_APPLYDas Ereignis zeigt an, dass die Änderungen angewandt werden sollen. Es kann also OK, Apply oder der Schliess-Button angewählt worden sein. lParam enthält den Zeiger auf eine PSHNOTIFY-Struktur. In dessen lParam-Feld steht TRUE, wenn der Anwender OK gedrückt hat.Wird PSNRET_INVALID_NOCHANGEPAGE zurückgegeben, wird verhindert, dass die Daten übernommen werden und der Fokus wird auf diese Seite gebracht. Die Rückgabe von PSNRET_NOERROR akzeptiert die Änderungen. Die Rückgabe erfolgt in diesem Fall dadurch, dass SetWindowLong mit dem Parameter DWL_MSGRESULT gerufen wird. Der dritte Parameter sind die oben genannten PSNRET-Konstanten. Damit dies gelesen wird, muss TRUE returniert werden. PSN_KILLACTIVEDiese Seite verliert den aktiven Zustand. Sei es, weil eine andere Seite angewählt wird oder weil OK gewählt wurde.Auf die gleiche Weise wie bei PSN_APPLY kann ein Wechseln der Seite verhindert werden. Es sollte eine Messagebox erscheinen, die dieses Verhalten dem Anwender erläutert. PSN_RESETDer PropertySheet wird zerstört. Alle Änderungen seit dem letzten PSN_APPLY sind zu verwerfen.
PSN_SETACTIVEDiese Seite wird aktiviert. Hier erfolgen die Initialisierungen.Apply-ButtonDer Apply-Button ist zu Anfang disabled. Um ihn zu aktivieren, muss die Anwendung die Nachricht PSM_CHANGED an den Property Sheet senden. Durch Senden von PSM_UNCHANGED wird er wieder deaktiviert. Sollte der durch den Apply-Button gesetzte Zustand unumkehrbar sein, sollte die Seite PSM_CANCELTOCLOSE senden. Dadurch wird der Text des Ok-Buttons in Schliessen geändert.Wechseln der SeitenDurch Senden der Nachrichten PSM_ADDPAGE und PSM_REMOVEPAGE kann man dynamisch Seiten hinzufügen und löschen.
Hinzufügen
PSM_ADDPAGE
wParam = 0;
lParam = (LPARAM) (HPROPSHEETPAGE) hpage;
oder
BOOL PropSheet_AddPage(HWND hPropSheetDlg, HPROPSHEETPAGE hpage);
Löschen
PSM_REMOVEPAGE
wParam = (WPARAM) (int) index;
lParam = (LPARAM) (HPROPSHEETPAGE)
Windows Programmierung: DateiauswahlboxDie Dialogbox zur Auswahl von Dateien ist eine Errungenschaft von Windows 3.1. Bei vorigen Versionen war sie noch nicht verfügbar. Damit aber auch Windows 3.0-Anwender die Auswahlbox benutzen können, hat Microsoft es gestattet, die für die Standarddialoge zuständige Datei COMMDLG.DLL frei zu kopieren.Die Prototypen und Datentypen für diese Dialoge finden sich in der Datei COMMDLG.H und müssen im Programm eingebunden werden.
Ein BeipielTypischerweise wird die Dateiauswahlbox aufgerufen, wenn Datei-Öffnen vom Anwender aufgerufen wurde. Damit muß der Aufruf in die Fensterfunktion an die Stelle, wo die Menüauswertung geschieht. Vorher wird der Importfilter gesetzt und eine Variable der Datenstruktur OPENFILENAME definiert. Diese Variable wird nullgesetzt und sollte nicht jedesmal neu erzeugt werden, da dann das Programm weiß, wo das letzte Mal geladen wurde und dort wieder aufsetzen wird. Wie bei vielen Windows-Strukturen muß auch hier das Feld lStructSize mit der Größe der Struktur vorbesetzt sein.
Im String FileName wird nach dem Aufruf der Dialogbox der ausgewählte Dateiname stehen, da diese Adresse in lpstrFile festgelegt wurde. Die FunktionenDie Funktion GetOpenFileName eröffnet eine Dialogbox zur Auswahl einer Datei, die gelesen werden soll. Der Parameter enthält eine Struktur, in der die Dialogbox weitgehend konfiguriert wird. Das wichtigste Element dieser Strukur ist der Zeiger lpstrFile, der den Speicherbereich angibt, in dem anschließend die ausgewählte Datei benannt wird.Die Funktion GetSaveFileName dient der Selektion einer Datei zum Sichern. Die Funktion GetFileTitle isoliert aus der bezeichneten Datei den reinen Dateinamen ohne Laufwerkskennung und Pfadnamen. Die Prototypen der Funktionen GetOpenFileName, GetSaveFileName und GetFileTitle:
Die Struktur OPENFILENAMEWie man an den Parametern der Funktionen sieht, spielt die Struktur OPENFILENAME eine beson- dere Rolle. Sie dient als Struktur, um die Parameter der Funktion aufzunehmen.
Zunächst wird in lStructSize die Größe der OPENFILENAME-Struktur erwartet. Diese wird mit sizeof(OPENFILENAME) festgelegt. Der DateinameDie wichtigste Aufgabe der Dialogbox ist die Lieferung des Dateinamens.
lpstrFile zeigt auf eine Stringvariable. Die Variable mit ihrem Speicherraum muß vom Programmierer definiert werden. Wichtig: Der String muß bei Start der Dialogbox vorbesetzt sein, typischerweise mit einem Leerstring. Ansonsten kann es sein, daß die Dialogbox nicht startet. Die Läge dieses Strings wird im Element nMaxFile abgelegt. Nach Ende der Dialogbox befindet sich hier der ausgewählte Dateiname inklusive Laufwerksbuchstabe und Pfad. Beim Sichern ohne eine Angabe der Extension wird in den meisten Fällen erwartet, dass das Programm seine eigene Extension anhängt. Dies wird durch Vorbesetzen des Elements lpstrDefExt erreicht. Nicht ohne FilterLPCSTR lpstrFilterHier wird eine Liste der Dateimasken übergeben, die bei Benutzung der Dialogbox durch eine Klapplistbox ausgewählt werden kann. Dabei werden die Strings direkt hintereinander geschrieben. Anders ausgedrückt, werden die Teilstrings durch eine binäre Null getrennt. Das Ende des gesammten Filters wird durch das Auftreten zweier Nullen hintereinander kenntlich. Es bilden immer zwei Strings ein Paar. Das erste ist die Bezeichnung im Klartext, das zweite ist die Maske. Werden mehrere Masken für eine Auswahl benötigt, kann man sie einfach hintereinander schreiben. Wie üblich wird jeder String durch ein Nullbyte beendet. Das Ende des Filters wird durch zwei Nullen kenntlich gemacht. Hier zwei Beispielstrings: "Stammbaum (*.dbf)\0*.dbf\0GEDCOM (*.ged)\0*.ged\0\0" "Diary (*.dry)\0*.dry\0Address (*.adr)\0*.adr\0All Files(*.*)\0*.*\0\0" Die Maske in Klammern dient nur der Anzeige und hat keine inhaltliche Bedeutung.
DWORD nFilterIndexNach Bearbeiten der Dialogbox liefert nFilterIndex welcher Filter vom Anwender ausgewählt wurde. Damit kann beispielsweise bei Importen festgestellt werden, welcher Funktion aufgerufen werden muß, um die Datei richtig zu lesen. Beim Schreiben der Datei ist es noch wichtiger, da so bestimmt werden kann, in welchem Format oder welche Inhalte geschrieben werden sollen. Der Index beginnt übrigens bei 1! FlagsDWORD FlagsHier werden spezielle Optionen gesetzt, die die Dialogbox konfigurieren. Die folgenden Wer- te können dabei durch Addition kombiniert werden:
Windows Programmierung: OrdnerauswahlIm Gegensatz zum Selektieren von Dateien hat das Selektieren von Ordnern einen anderen typischen Dialog. Auch die Programmierung erfolgt anders. Der Zugang erfolgt per COM auf die Shell-Schnittstelle von Windows. Daraus leiten sich zwei Notwendigkeiten ab. Zunächst muss shlobj.h eingebunden werden. Zum anderen muss COM einmal initialisiert werden. Das kann beispielsweise bei WM_CREATE der Fensterfunktion passieren.
Die zentrale Funktion heisst SHBrowseForFolder und arbeitet mit einer Struktur BROWSEINFO.
WINSHELLAPI LPITEMIDLIST WINAPI
SHBrowseForFolder(LPBROWSEINFO lpbi);
Die folgende Routine startet einen Selektionsdialog
für Verzeichnisse.
Das Feld pszDisplayName muss auf einen Speicherplatz zeigen, in den die Dialogbox den "Anzeigenamen" ablegt. Dieser besteht aber aus dem nackten Verzeichnisnamen ohne Pfad. Das nutzt dem Programmierer meist wenig. Um den kompletten Pfadnamen zu erlangen, wird der Rückgabezeiger von SHBrowseForFolder an die Funktion SHGetPathFromIDList weitergegeben, der im Speicherbereich des zweiten Arguments den kompletten Pfad ablegt. Da der Displayname nicht gebraucht wird, wird hier der Einfachheit halber einfach der gleiche Speicher wiederverwendet. VariationenDas Flag ulFlags der BROWSEINFO kann mit Konstanten besetzt werden, die die Auswahl einschränken. Das wird durch Grauschalten des OK-Buttons erreicht. Eine Kombination durch Odern ist möglich.
Programmierung von KontrollelementenDie Kontrollelemente besitzen einige Gemeinsamkeiten. Es aus Sicht von Windows lediglich spezialisierte Fenster und gehorchen gleichen Gesetzen.
Übersicht
Erzeugung eines KontrollelementsKontrollelemente werden oft in Dialogboxen erstellt und werden durch den Dialogstart miterzeugt. Werden diese Elemente aber in Fenstern benötigt werden sie mit CreateWindow erzeugt. Die Parameter von CreateWindow sind:
Ein Beispiel zur Erzeugung eines Eingabefeldes:
Bei den Common Controls sollte noch der Aufruf von InitCommonControls() erfolgen. In der neueren Variante und lautet z. B. für Tree Views:
Ein Include von "commctrl.h" ist obligatisch. Ereignisse bearbeitenDie Ereignisse gelangen in die Fensterfunktion des Elternfensters. Dies kann ein Dialog oder ein gewöhnliches Fenster sein. Die Kontrollelemente lösen ein WM_COMMAND aus.
LOWORD(wParam) enthält die Ressource-ID
Einige der neueren Kontrollelemente verwenden nicht die Nachricht WM_COMMAND, sondern WM_NOTIFY. Bei diesem Ereignis wird im lParam ein Pointer auf eine Struktur NMHDR übergeben, die in den ersten Elementen bei allen Kontrolls gleich sind. Sie enthalten:
Eine typische Bearbeitung der Ereignisse sieht also so aus:
ManipulationEin Kontroll kann Befehle erhalten oder man kann Informationen erfragen. Der Kontakt des Programmes mit seinen Kontrollelementen geschieht durch das Senden von Nachrichten.Im Beispiel werden die Daten, die hinter dem ausgewählten Listboxelement abgelegt sind, angefragt. Dies benötigt zwei Schritte. Erst muß ermittelt werden, welches Element selektiert ist und anschließend erfragt man die Daten. Beide Vorgänge werden durch die Funktion SendMessage ausgelöst. Im ersten Parameter wird das HWND des Kontrollelements benoetigt, im Beispiel hListe. Der zweite Parameter enthält das Kommando. Das ist LB_CURSEL zum Ermitteln des aktuell selektierten Element und LB_GETITEMDATA zur Frage nach den Daten. Die folgenden beiden Parameter entsprechen dem wParam und lParam aus der Fensterfunktion.
Windows Programmierung: ButtonsEinführende Informationen über die Programmierung von Kontrollelementen werden hier vorausgesetzt.
StileDer Stil gibt an, welcher Art der Button ist. Es gibt drei grundsätzliche Ausprägungen: Pushbutton, Checkbox und Radiobutton.PushbuttonDies ist der gewöhnliche Button, der gedrückt wird und eine Aktion auslöst, indem er eine WM_COMMAND-Nachricht an das Elternfenster sendet. In der Variante Default-Pushbutton, ist er etwas stärker umrandet und reagiert, wenn der Anwender die Return-Taste drückt.
CheckboxEin kleines Rechteck, in dem man ein Kreuz erscheinen und verschwinden lassen kann. Ein Text befindet sich rechts davon (oder links, wenn man BS_LEFTTEXT angibt). Das 3-State Element kennt noch einen dritten Zustand: gedimmt zeigt an, daß der Button nicht anwählbar ist. Die AUTO-Variante schaltet selbstständig das Kreuz ein und aus.
RadiobuttonEin Radiobutton verhält sich einzeln gleich einer Checkbox. Lediglich im Aussehen ist ein Unterschied sichtbar, der Radiobutton ist rund und hat einen Punkt in der Mitte, wenn er ausgewählt ist.In Gruppen zusammengefaßt, kann aber nur maximal einer von Ihnen angewählt werden. In der AUTO-Variante braucht dies nicht einmal der Programmierer selbst zu realisieren. Zu einer Gruppe gehören diejenigen, die das gleiche Elternfenster besitzen. Dies wird üblicherweise durch den Einsatz eines Rahmens erreicht.
BS_RADIOBUTTON
GroupboxDies ist ein solcher Rahmen, um Radiobuttons zu gruppieren. In der linken oberen Ecke kann ein Text stehen, um eine gemeinsame Überschrift zu haben.BS_GROUPBOX Weitere Attribute
Ereignis Button angeklicktWährend andere Kontrollelemente noch prüfen müssen, welches Ereignis eingetroffen sein könnte, ist dies bei Buttons im Allgemeinen ein Klick. Dadurch ergibt sich eine vereinfachte Ereignisabfrage:
Buttons mit HakenPrüfen, ob ein Button mit einem Haken versehen ist. Funktioniert bei Radiobuttons und Checkboxes
Setzen eines Hakens
Da BST_CHECKED als 1 definiert ist und BST_UNCHECKED als 0, kann man auch den booleschen Ausdruck als Parameter verwenden. Windows Programmierung: Das EditfeldStileDer Stil des Elementes wird bei der Erzeugung festgelegt. Neben den allgemeinen Fensterstilen besitzt das Editfeld eigene Stile:
Ansteuerung
Ereignisse
BeispielDiese Fensterfunktion erzeugt beim Start des Fensters ein Eingabefeld und merkt sich in der statischen Variablen EdHwnd das Handle. Die 1201 ist die (beliebige) ID des Editfeldes. Sie muss allerdings im Fenster eindeutig sein. Wird der Menüpunkt mit der ID M_SHOW (in der Ressource zu erstellen) gedrückt, erscheint der aktuelle Text des Eingabefeldes in der Messagebox. Der Menüpunkt IDM_EXIT sorgt nur für ein reguläres Beenden des Programmes.
|