|
lite-C 101 |
Top Previous Next |
|
In diesem Monat wollen wir die wundervolle Welt von Win32 API (Application Programming Interface) erforschen. Stellen Sie sich einfach vor, dass API ein Interface zwischen Ihnen und Windows ist und es Ihnen erlaubt, viele Funktionen des Betriebssystems zu nutzen.
Wieviele dieser Funktionen stehen uns zur Verfügung? Ich weiß es nicht genau, aber Sie können sich einfach die api.def Datei in Ihrem 3DGS / lite-C Verzeichnis ansehen. Ich würde schätzen, dass wir etwa 3000 verschiedene Funktionen zur Verfügung haben und Conitec sorgt dafür, dass sich diese Liste von Zeit zu Zeit um weitere brandneue Funktionen erweitert.
Sind Sie ebenso aufgeregt wie ich zu erfahren wie die Kraft von lite-C mit den Windowsfunktionen kombiniert werden kann? Lassen Sie uns gleich beginnen, indem Sie die Datei winapi1.c öffnen und starten.
Das erste Beispiel zeigt die Anzahl der Sekunden an seit der Computer gestartet wurde; ich verwende hierfür die API Funktion mit Namen GetTickCount().
#include <acknex.h> #include <default.c> #include <windows.h>
float time_passed;
STRING* time_str = "#30";
TEXT* time_txt = { layer = 15; pos_x = 10; pos_y = 20; string (time_str); flags = VISIBLE; }
function main() { video_mode = 6; // create a program window of 640x480 pixels vec_set(screen_color, vector(55, 55, 55)); // make the background color dark while (1) { time_passed = GetTickCount() * 0.001; str_for_num(time_str, time_passed); wait (1); } }
Beachten Sie bitte, dass ich eine weitere Datei mit include einbinde - windows.h. In dieser befinden sich die API Funktionen, stellen Sie also sicher, dass Sie diese jedesmal einbinden, wenn Sie das API nutzen wollen. MSDN - Microsoft's Developer Network - ist DER Ort, an dem Sie mehr Informationen über das API finden; Google hilft Ihnen sicher weiter.
Wir deklarieren eine Variable vom Typ "float", eine Fließkommazahl, die große Zahlen speichern kann; time_str ist ein String, der bis zu 30 Zeichen enthält.
Die main Funktion ruft GetTickCount in einer Schleife auf und multipliziert das Ergebnis mit 0,001, damit der endgültige Wert die Form Sekunden,Millisekunden hat. Das Resultat wird dann in einen String umgewandelt und dargestellt. Vergessen Sie nicht, dass "digit"-Felder nicht so geeignet sind, wenn Werte mit großer Präzision gezeigt werden sollen.
Können wir etwas Nützliches mit GetTickCount anstellen? Wie wäre es mit Timern, die eine große Genauigkeit haben, zum Beispiel Rundenzeitmesser für Rennspiele und so weiter? Alles was wir brauchen ist die GetTickCount Diffeenz zwischen den Zeitpunkten, die uns interessieren (Start und Ende einer Runde zum Beispiel).
Sehen wir uns ein anderes lustiges Beispiel an.
#include <acknex.h> #include <default.c> #include <windows.h>
function swap_them() { SwapMouseButton(TRUE); }
function restore_them() { SwapMouseButton(FALSE); }
function main() { video_mode = 6; // create a program window of 640x480 pixels vec_set(screen_color, vector(55, 55, 55)); // make the background color dark on_s = swap_them; on_r = restore_them; }
SwapMouseButton(TRUE) vertauscht die Funktionen der beiden Maustasten, während SwapMouseButton(FALSE) den alten Zustand wiederherstellt. Unser Beispiel kehrt die Maustasten um, wenn wir "S" drücken und stellt den alten Zustand durch Drücken der "R" Taste wieder her.
Starten Sie winapi2.c und drücken Sie die "S" Taste; Sie werden feststellen, dass sich das Fenster nichtmehr durch einen Klick mit der linken Maustaste schließen lässt. Schließen Sie es mit der rechten Maustaste und starten Sie die Anwendung erneut, natürlich ebenfalls mit der rechten Maustaste und drücken Sie dann "R". Alles sollte wieder funktionieren wie vorher.
Und wenn Sie jetzt glauben, dass diese Funktion zum Spaß eingebaut wurde, um anderen Streiche zu spielen, dann sollten Sie wissen, dass der Tausch der Maustasten für Personen bereitgestellt wurde, die zum Beispiel die Mausmit der linken Hand verwenden. Also veralbern Sie nicht Ihre Familie mit dieser Funktion!
Das folgende Beispiel erstellt Dialogboxen und lässt uns auf die verschiedenen Knöpfe reagieren.
Sehen wir uns die Datei winapi3.c einmal an:
#include <acknex.h> #include <default.c> #include <windows.h>;
var answer;
STRING* decision_str = "#30";
TEXT* decision_txt = { layer = 15; pos_x = 10; pos_y = 20; string (decision_str); flags = VISIBLE; }
function main() { video_mode = 6; // create a program window of 640x480 pixels vec_set(screen_color, vector(55, 55, 55)); // make the background color dark wait (-3); answer = MessageBox(NULL, "Start the offensive?", "Nuclear Button", MB_YESNO); if (answer == IDYES) { str_cpy(decision_str, "The war has started!"); } else { str_cpy(decision_str, "The war has ended."); } }
Wie Sie sehen hat MessageBox eine einfache Syntax: MessageBox(owner_window_handle, text_to_be_displayed, title, message_box_style). Das Handle zum "Owner Windows" identifizert das Fenster, zu dem die Box gehört; ein Wert von NULL ist erlaubt und sorgt dafür, dass die Box kein übergeordnetes Fenster hat, was für viele Zwecke ausreicht. Der "Style" kann die Zahl der Knöpfe (1 bis 3), das Icon, die Buttons, etc. manipulieren. Wiederum ist MSDN Ihr bester Freund, wenn es darum geht, die Details nachzulesen.
Desweiteren liefert MessageBox einen Wert wie IDYES, IDNO, IDABORT etc. zurück, je nachdem welcher Knopf gedrückt wurde. Bei diesen handelt es sich natürlich um Zahlen, die also in einer Variablen gespeichert werden können, was wir in einapi3.c auch tun.
Wenn der Spieler auf "Ja" klickt, dann zeigen wir "The war has started!" an; andernfalls wenn die "Nein" Taste gedrückt wurde den Text "The war has ended."
Zeit für ein weiteres nützliches, kleines Beispiel.
#include <acknex.h> #include <default.c> #include <windows.h>
FONT* morpheus_font = "Morpheus#36"; // new truetype font with a size of 36
TEXT* newfont_txt = { layer = 15; pos_x = 10; pos_y = 20; font = morpheus_font; string ("This demonstrates a new true type font"); }
function main() { video_mode = 6; // create a program window of 640x480 pixels vec_set(screen_color, vector(55, 55, 55)); // make the background color dark // AddFontResource("morpheus.ttf"); wait (3); set(newfont_txt, VISIBLE); }
Starten Sie winapi4.c und Sie sollten so etwas sehen:
Falls Ihnen das wie eine Arial Schrift vorkommt... es ist eine! Wir haben zwar morpheus_font für unseren Text angegeben, aber Windows kennt diese noch nicht. Entfernen wir also den Kommentar vor der AddFontResource Zeile und starten wir das Programm erneut.
Dieses Mal wird AddFontResource aufgerufen und fügt unsere Schriftart dem System hinzu. Wir können sie nun im Spiel verwenden, vorausgesetzt die Datei mit der Schriftart befindet sich im Verzeichnis des Spiels.
Nun da Sie jede TrueType Schriftart verwenden können, ein Wort der Warnung: Stellen Sie sicher, dass Sie auch das Recht haben, Ihre Lieblingsschriftart im Spiel zu verwenden. Nehmen Sie zum Beispiel die Morpheus Schriftart: in der readme steht, dass Sie dem Autor der Schriftat $5 schicken sollen, wenn Ihnen die Schriftart gefällt. Das ist nicht viel, aber wenn Sie irgendeine Star Wars Schriftart verwenden, könnten Sie verklagt werden.
Das letzte Beispiel befindet sich in winapi5.c und erstellt eine Liste aller logischen Laufwerke des Computers.
Wie Sie sehen habe ich einige auf meinem PC. Und so ermittelt man ihre Namen.
#include <acknex.h> #include <default.c> #include <windows.h>
DWORD operation_result;
char* drives_str[1024]; char* p;
STRING* temp_str = "#30";
TEXT* drives_txt = { layer = 15; pos_x = 10; pos_y = 20; string (temp_str); flags = VISIBLE; }
function main() { video_mode = 6; // create a program window of 640x480 pixels vec_set(screen_color, vector(55, 55, 55)); // make the background color dark // the function below would return zero if the operation wouldn't succeed if(operation_result = GetLogicalDriveStrings(1024, drives_str)) // the operation has succeeded? { p = drives_str; str_cpy(temp_str, "Local drives: "); while (*p) { str_cat(temp_str, p); str_cat(temp_str, " "); p += 4; } } else { str_cpy(temp_str, "The operation has failed"); } }
Zunächst definieren wir eine DWORd Variable, also eine 32-Bit ganze Zahl, die nur positive Werte annimmt; in ihr speichern wir das Ergebnis der GetLogicalDriveStrings Operation. Dann definieren wir zwei Pointer auf einen Char. Der erste wird auf einen Speicherbereich zeigen, der 1024 Zeichen aufnehmen kann und der zweite... das wird eine Überraschung.
Die Funktion, die uns die Namen der Laufwerke verrät heißt GetLogicalDriveStrings und hat zwei Argumente: die maximale Größe des Puffers, welcher die Buchstaben aufnimmt und der eigentliche Puffer, der dies tut (fragen Sie mich nicht, warum das so gehandhabt wird, ich habe die Information aus dem MSDN). Wenn die Operation glückt wird operation_result auf einen Wert ungleich 0 gesetzt, der "if" Teil wird ausgeführt und drives_str sieht in etwa so aus:
a:\<null>c:\<null>d:\<null><null>
In diesem Beispiel hat der Computer die Laufwerke a:\, c:\ und d:\ und der doppelte <null> character markiert das Ende des Strings. Die schlechte Nachricht: der Ausgabestring enthält einige <null> Zeichen in der Mitte, was es schwierig macht, das Resultat mit lite-C darzustellen.
Warum das so ist? Nun ja, falls wir etwas wie "str_cpy(temp-str, drives_str);" versuchen würden, um die Laufwerke anzuzeigen, sähe das Ergebnis so aus:
a:\
weil das erste <null> Zeichen str_cpy dazu verleitet zu glauben, dass schon das Ende des Strings srives_str erreicht ist, wodurch die c:\ und d:\ Laufwerke ignoriert werden. Wir müssen einen Weg finden, die <null> Zeichen zu überspringen und die Lösung ist einfach, wenn Sie meinen Workshop über Pointer gelesen haben - wir können das mit einem Pointer (unserem p) einfach tun!
Ich habe eine neuartige Digitalkamera, mit der ich einen Schnappschuss Ihres Speichers gemacht habe und so sieht drives_str aus:
Wie können wir die Buchstaben der Laufwerke extrahieren und die <null> Zeichen überspringen, die unsere str-Anweisungen verwirren würden? Sehen wir uns den relevanten Code nochmal an:
p = drives_str; str_cpy(temp_str, "Local drives: "); while (*p) { str_cat(temp_str, p); str_cat(temp_str, " "); p += 4; }
Die erste Zeile weist die Anfangsadresse von drives_str (die erste Zelle im Bild) dem Pointer p zu. Wenn Sie nicht wissen wie das funktioniert, lesen Sie zunächst den Workshop aus AUM 70.
Unsere Schleife läuft solange der Pointer gültig ist (bis er das "richtige" Ende, die doppelte <null> erreicht). Wir fügen die Laufwerksbuchstaben nacheinander in temp-str ein und beginnen mit a:\ (str_cat glaubt, dass drives_str endet, wenn <null> erreicht wird), fügen ein Leerzeichen zur besseren Lesbarkeit ein und springen dann vier Zeichen nach rechts, wobei das verwirrende <null> übersprungen wird.
Das Ergebnis siehr folgendermaßen aus: "Local drives: A:\ C:\ D:\ E:\" und kann noch weiter verfeinert werden. Mit GetDriveType könnten wir herausfinden, welches das CD-Rom Laufwerk ist und so weiter. Dies ist auch Ihre Hausaufgabe, wenn Sie nicht zu faul dafür sind... und vergessen Sie nicht, den "Plug & Play" Artikel in diesem Monat zu lesen, der ebenfalls das API nutzt.
|