Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sheddex

unregistriert

1

15.03.2007, 21:15

Die File Management Funktionen der WinAPI (1)

Die File Management Funktionen der WinAPI (1)

Allgemeines
In diesem Tutorial wird eine Klasse namens „File“ erstellt, mit der es möglich ist Daten in Dateien zu schreiben und sie wieder auszulesen. Die ganze Klasse
verwendet die File Management Funktionen der WinAPI, es muss also lediglich die windows.h Datei eingebunden werden. Die vollständige Liste der Funktionen
welche die WinAPI zum Umgang mit Dateien bereitstellt findet man hier.

Die Klasse
Zuerst wird das Grundgerüst der Klasse deklariert. Sie enthält das Handle der Datei als private Membervariable sowie verschiedene Methoden. Diese werden
später implementiert. Um die Kompatibilität zu sowohl ANSI als auch UNICODE zu gewährleisten wird das TCHAR- und TEXT-Makro verwendet. Wird UNICODE
definiert, nimmt TCHAR den Typ "wchar_t" an, andernfalls "char". TEXT("String") würde bei UNICODE in L"String" umgewandelt werden, andernfalls in "String".

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class File
{
  private:

    //Dateihandle

    void* FileHandle;

  public:

    //Konstruktor

    File(void);

    //Destruktor

    ~File(void);

    //Methoden

    bool IsOpen(void) const;
    bool Close(void);
    bool Open(const TCHAR* Filename, unsigned long Creation);
    bool Write(const void* Data, unsigned int Size, unsigned long* WrittenBytes = NULL);
    bool Read(void* Data, unsigned int Size, unsigned long* ReadBytes = NULL);

    unsigned long GetSize(void) const;

    bool SetPointerPosition(long Distance, unsigned long StartingPoint = FILE_CURRENT);
    long GetPointerPosition(void) const;
};


Der Konstruktor
Im Kontruktor wird lediglich das Handle der Datei auf NULL gesetzt:


C-/C++-Quelltext

1
2
3
4
File::File(void)
{
  FileHandle = NULL;
}



Der Destruktor
Der Destruktor prüft ob die Datei noch geöffnet ist. Ist dies der Fall wird sie geschlossen. Beide hier verwendeten Methoden werden später implementiert.

C-/C++-Quelltext

1
2
3
4
5
File::~File(void)
{
  if (IsOpen() == true)
    Close();
}


IsOpen
Diese Methode ist unerlässlich um Fehler abzufangen. Man weiß nie was passiert wenn man versucht mit einer noch nicht geöffneten Datei herumzuhantieren.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
bool File::IsOpen(void) const
{
  if (FileHandle != INVALID_HANDLE_VALUE && FileHandle != NULL)
    return true;

  else
    return false;
}


Wie man sieht prüft die Methode ob "FileHandle" gültig ist und ob es NULL ist. Ist es weder ungültig noch NULL gibt die Methode "true" zurück und
signalisiert damit dass die Datei geöffnet ist. Andernfalls wird "false" zurückgegeben.

Close
Wider Erwarten wird jetzt nicht erklärt wie eine Datei geöffnet wird, sondern erst wie man diese schließt. Nicht dass jemand auf die Idee kommt die
Funktion zum Öffnen schonmal zu testen ohne die Datei dann wieder zu schließen ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
bool File::Close(void)
{
  if (IsOpen() == false)
    return false;

  if (CloseHandle(FileHandle) == FALSE)
    return false;

  FileHandle = NULL;

  return true;
}


Zuerst wird wieder überprüft ob die Datei überhaupt geöffnet ist. Wenn nicht gibt die Methode "false" zurück. Ist sie geöffnet wird das Handle mithilfe
der Funktion "CloseHandle" geschlossen. Am Ende wird das Handle noch auf NULL gesetzt.

Open
Jetzt ist es endlich soweit: Die Methode "Open" öffnet eine bereits vorhandene Datei oder erstellt eine neue.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
bool File::Open(const TCHAR* Filename, unsigned long Creation)
{
  //Wenn die Datei bereits geöffnet ist, wird sie nun geschlossen

  if (IsOpen() == true)
    Close();

  //Öffnen der Datei, "CreateFile" wird bei UNICODE zu "CreateFileW", andernfalls zu "CreateFileA"

  FileHandle = CreateFile(Filename, FILE_ALL_ACCESS, 0, NULL, Creation, FILE_ATTRIBUTE_NORMAL, NULL);

  //Ist die Datei nun geöffnet?

  return IsOpen();
}


Der erste Paramter ist der Name der Datei, der zweite beschreibt auf welche Weise die Funktion arbeiten soll. Zum Beispiel kann man
festlegen dass wenn eine Datei geöffnet werden soll aber noch nicht existiert diese neu erstellt wird. Die WinAPI definiert dafür
folgende Möglichkeiten:

CREATE_NEW
Erstellt eine neue Datei. Wennn bereits eine gleichnamige Datei existiert führt dies zu einem Fehler.

CREATE_ALWAYS
Erstellt immer eine neue Datei. Wenn bereits eine gleichnamige Datei existiert wird diese überschrieben.

OPEN_EXISTING
Öffnet eine bereits vorhandene Datei. Existiert diese nicht führt dies zu einem Fehler.

OPEN_ALWAYS
Öffnet immer eine Datei. Falls diese nicht existiert wird eine neue erstellt.

Zuerst wird nun überprüft ob die Datei bereits geöffnet wird. Ist sie das, wird sie geschlossen. So werden Fehler verhindert die auftreten könnten
falls versucht wird eine bereits geöffnete Datei nochmal zu öffnen.

Nun wird das Handle mit der Funktion "CreateFileW" gefüllt. Wirklich relevant sind hier nur 2 Parameter, wer etwas über die restlichen erfahren möchte
kann in der MSDN nachschauen.
Der erste Parameter ist der Name der Datei. Hier wird einfach "FileName" übergeben. der fünfte Parameter beschreibt, wie bereits oben beschrieben, wie die
Funktion arbeiten soll. Hier wird "Creation" übergeben.

Ist die Datei nach dieser Funktion nicht geöffnet ist wohl etwas schief gelaufen und die Funktion gibt "false" zurück.

Write
So, nun wird die Klasse endlich etwas leisten: Daten werden in eine Datei geschrieben.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool File::Write(const void* Data, unsigned int Size, unsigned long* WrittenBytes)
{
  unsigned long TemporaryWrittenBytes = 0;

  if (Data == NULL)
    return false;

  if (IsOpen() == false)
    return false;

  if (WriteFile(FileHandle, Data, Size, &TemporaryWrittenBytes, NULL) == FALSE)
    return false;

  if (TemporaryWrittenBytes != Size)
    return false;

  if (WrittenBytes != NULL)
    *WrittenBytes = TemporaryWrittenBytes;

  return true;
}


Der erste Parameter ist ein Zeiger auf das zu Schreibende. Man übergibt einfach die Adresse einer beliebigen Variable, Struktur oder Klasse. Der zweite
Paramter erwartet die Größe der zu schreibenden Daten in Bytes, meist genügt hier die Verwendung von "sizeof". Der dritte Parameter wiederum ist ein
Zeiger auf eine Variable die mit der Anzahl der tatsächlich geschriebenen Bytes gefüllt wird. Wird diese Information nicht benötigt kann dieser Parameter
NULL sein, was auch der Standardwert ist.

Mit der Prüfung von "Data" auf NULL wird überprüft ob überhaupt etwas zum Schreiben vorhanden ist. Wenn nicht wird "false" zurückgegeben. Danach folgt
wie immer "IsOpen".

Geschrieben werden die Daten mit "WriteFile". Der erste Parameter dieser Funktion ist das Handle. Hier wird natürlich "FileHandle" übergeben.
Der zweite Parameter sind die Daten die geschrieben werden soll, der dritte Paramter erwartet dann deren Größe in Bytes. Hier wird zuerst "Data" und
danach "Size" übergeben. Dem vierten Paramter wird die Variable "TemporaryWrittenBytes" übergeben um die Zahl der tatsächlich geschriebenen Bytes zu
erhalten. Hier wird nicht direkt "WrittenBytes" übergeben, da man ja nicht weiß ob "WrittenBytes" NULL ist oder nicht. Der fünfte Parameter wird auf
NULL gesetzt. Wer etwas über ihn erfahren möchte kann in der MSDN nachschauen.

Nach dem Schreibvorgang wird überprüft ob die Anzahl der Bytes die geschrieben werden sollten auch der Anzahl der Bytes die tatsächlich geschrieben
wurden entspricht. Ist dies nicht der Fall konnte nicht alles korrekt geschrieben werden und es wird "false" zurückgegeben.

Zum Schluss wird noch überprüft ob "WrittenBytes" NULL ist. Ist dem nicht so wird der Wert von "TemporaryWrittenBytes" in diese Variable übertragen.

Read
Hier gibt es kaum Unterschiede zu "Write".

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool File::Read(void* Data, unsigned int Size, unsigned long* ReadBytes)
{
  unsigned long TemporaryReadBytes = 0;

  if (Data == NULL)
    return false;

  if (IsOpen() == false)
    return false;

  if (ReadFile(FileHandle, Data, Size, &TemporaryReadBytes, NULL) == FALSE)
    return false;

  if (TemporaryReadBytes != Size)
    return false;

  if (ReadBytes != NULL)
    *ReadBytes = TemporaryReadBytes;

  return true;
}


Tatsächlich sieht der Ablauf genau gleich aus, mit dem Unterschied dass einige Variablen anders heißen, sowie die wichtigste Funktion natürlich nicht
"WriteFile" sondern "ReadFile" heißt.

GetSize
Mit der "GetSize"-Methode erhält man die Größe der geöffneten Datei.

C-/C++-Quelltext

1
2
3
4
unsigned long File::GetSize(void) const
{
   return GetFileSize(FileHandle, NULL);
}


Hier wird "GetFileSize" verwendet um an die Größe der Datei zu kommen. Der erste Paramter ist das Handle, der zweite wird auf NULL gesetzt.
Wer wissen möchte wozu dieser gut ist weiß wo er nachschauen soll ;)

SetPointerPosition
Der sogenannte Filepointer zeigt an, ab welcher Stelle der Datei geschrieben oder gelesen werden soll. Zu beginn befindet er sich an der Position 0 in
der Datei und "wandert" immer soviele Bytes weiter wie gerade geschrieben wurden. Demnach ist seine Position standardmäßig beim letzten Byte.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool File::SetPointerPosition(long Distance, unsigned long StartingPoint)
{
  if (IsOpen() == false)
    return false;

  if (Distance > static_cast<long>(GetSize()))
    return false;

  //"GetPointerPosition" wird später implementiert

  if (StartingPoint == FILE_CURRENT && (GetPointerPosition() + Distance) > static_cast<long>(GetSize()))
    return false;

  //Hier wird nun der Filepointer gesetzt

  SetFilePointer(FileHandle, Distance, NULL, StartingPoint);

  if (GetLastError() != NO_ERROR)
    return false;

  return true;
}


Der erste Paramter ist die Distanz die der Filepointer zurücklegen soll in Bytes. Jetzt stellt sich allerdings die Frage, von wo aus er sich bewegen soll.
Dies wird mit dem zweiten Parameter festgelegt. Auch hier definiert die WinAPI einige Möglichkeiten:

FILE_BEGIN
Der Pointer wird von der Position 0 aus bewegt.

FILE_CURRENT
Der Pointer wird von der aktuellen Position aus bewegt.

FILE_END
Der Pointer wird vom letzten Byte aus nach vorne hin bewegt.

In der Methode wird zuerst mal wieder geprüft ob die Datei geöffnet ist, ist sie das nicht wird wie immer "false" zurückgegeben. Nun wird überprüft
ob die Distanz größer als die Dateigröße ist. Wenn dies der Fall ist wird "false" zurückgegeben. Nun folgt eine weitere Abfrage die
erstmal überprüft ob die Startposition des Filepointers den Wert "FiLE_CURRENT" hat. Ist dies der Fall wird überprüft ob der Filepointer eine
Position nach dem letzten Byte annehmen würde nachdem er die Distanz zurückgelegt hat. Ist dies der Fall wird "false" zurückgegeben.
Schließlich kommt die SetFilePointer-Funktion an die Reihe. Diese erwartet zuerst das Handle der Datei, dann die Distanz die der Filepointer zurücklegen
soll. Der dritte Parameter kann in der MSDN nachgeschaut werden, der 4. ist die Startposition des Filepointers.
Zu guter letzt wird noch per "GetLastError" überprüft ob ein Fehler aufgetreten ist. Ist dies der Fall wird "false" zurückgegeben, andernfalls
ist die Methode hiermit erfolgreich am Ende angelangt.

GetPointerPosition
Nun folgt die Methode "GetPointerPosition", ohne die "SetPointerPosition" garnicht funktionsfähig ist, außer wenn man die Sicherheitsabfrage ausbaut.
Die WinAPI stelltr keine seperate Funktion zum erhalten der aktuellen Position des Filepointers zur verfügung, weshalb man auch dies mithilfe von
"SetFilePointer" erledigt. Der Rückgabewert eben jener Funktion ist die Position des Filepointers nach der Bewegung. Nun gibt man einfach an dass man den
Filepointer um 0 Bytes von der aktuellen Position aus bewegt. Der Filepointer bewegt sich dadurch nicht, die Variable wird aber natürlich trotzdem gefüllt.
Und schon hat man die aktuelle Filepointer-Position :)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
long File::GetPointerPosition(void) const
{
  long Position = 0;

  if (IsOpen() == false)
    return -1;

  Position = SetFilePointer(FileHandle, 0, NULL, FILE_CURRENT);

  if (GetLastError() != NO_ERROR)
    return -1;

  return Position;
}


Ist die Datei nicht geöffnet wird "-1" zurückgegeben. Da der Filepointer keine negative Position haben kann eignet sich dieser Wert als Fehlercode.
Danach wird wie oben bereits beschrieben "SetFilePointer" aufgerufen und mit "GetLastError" auf Erfolg geprüft. zum Schluss wird die aktuelle Position
des Filepointers zurückgegeben.

Beispielprogramm
Hier noch ein kleines Beispiel Programm welches die Verwendung der Klasse demonstriert.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <windows.h>
#include <iostream>

//An dieser Stelle steht die File-Klasse


int main(void)
{
  //Variablen

  unsigned int i = 4;
  unsigned int j = 8;
  File         f;

  //Variablenwerte ausgeben

  std::wcout << L"Wert 1 (Standard): " << i << std::endl;
  std::wcout << L"Wert 2 (Standard): " << j << std::endl;

  //Datei erstellen

  f.Open(TEXT("Datei.file"), CREATE_ALWAYS);

  //Variablen hintereinander in die Datei schreiben

  f.Write(&i, sizeof(unsigned int));
  f.Write(&j, sizeof(unsigned int));

  //Datei schließen

  f.Close();

  //Variablen auf 0 setzen

  i = j = 0;

  //Variable ausgeben nach dem Nullen ausgeben

  std::wcout << L"Wert 1 (Nach dem Nullen): " << i << std::endl;
  std::wcout << L"Wert 2 (Nach dem Nullen): " << j << std::endl;

  //Datei öffnen

  f.Open(TEXT("Datei.file"), OPEN_EXISTING);

  //Den Filepointer 4 Bytes weiterverschieben und "j" auslesen

  f.SetPointerPosition(4, FILE_BEGIN);
  f.Read(&j, sizeof(unsigned int));

  //Den Filepointer auf Position 0 verschieben und "i" auslesen

  f.SetPointerPosition(0, FILE_BEGIN);
  f.Read(&i, sizeof(unsigned int));

  //Variablenwerte ausgeben

  std::wcout << L"Wert 1 (nach dem Lesen aus der Datei): " << i << std::endl;
  std::wcout << L"Wert 2 (nach dem Lesen aus der Datei): " << j << std::endl;

  //Datei schließen

  f.Close();

  //5 Sekunden warten damit man Zeit hat die Textmeldungen zu lesen ;)

  Sleep(5000);

  return 0;
}


Wie man bei der Implementierung gesehen hat geben alle Funktionen "true" oder "false" - nach nach Erfolg - zurück. Dies zu nutzen habe ich mir hier jetzt
gespart, natürlich sollte man es aber sonst immer nutzen.

Das Programm speichert einfach zwei Variablen in eine Datei, setzt die Variable auf 0 und liest sie dann in umgekehrter Reihenfolge einzeln wieder aus,
um die Funktionsweise von "SetPointerPosition" zu demonstrieren.

Links
Code
MSDN

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

2

18.03.2007, 11:28

Hab mir das jetzt mal komplett durchgelesen... Es ist erstmal ne recht gute Basis, kann aber durchaus noch optimiert und ausgebaut werden.

C-/C++-Quelltext

1
2
3
4
   if (FileHandle != INVALID_HANDLE_VALUE && FileHandle != NULL)
      return true;
   else
      return false; 

könnte auch so aussehen:

C-/C++-Quelltext

1
   return (FileHandle != INVALID_HANDLE_VALUE && FileHandle != NULL);


Zum Destruktor: es wär evtl. sinnvoll, dort die Datei automatisch zu schließen falls sie noch offen ist.

Was auf jeden Fall noch fehlt ist eine Seekg(...) - oder wie es auch immer genau heißt - Funktion mit der man das Lesezeichen innerhalb der Datei verschieben kann.

Ansonsten bleibt natürlich die Frage, was an den Funktionen der STL so schlecht ist, dass man andere braucht.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

18.03.2007, 11:32

Schonmal was von const gehört? :?
Und lass das ZeroMemory weg. Im Destruktor hat das auch gar keinen Sinn. Im Konstruktor auch nicht (ja, ich weiß, dass ich das in meinem Buch so gemacht habe, aber es ist nicht empfehlenswert). Lieber die Elemente einzeln auf Standardwerte setzen (ist ja hier eh nur eins).

Vergleiche mit true, false, 0 (oder NULL) kann man sich sparen:

if(x == true) => if(x)
if(x == false) => if(!x)
if(x == NULL) => if(!x)

if(x) return true;
else return false;
=> return x;

4

18.03.2007, 12:01

Wo der selbe return-Wert ist, kannst du auch einfach mehrere Bedingungen zusammen setzen ;) Ist ne wenig kürzer ... also sowas:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
if (Data == NULL)
      return false;

   if (IsOpen() == false)
      return false;

   if (WriteFile(FileHandle, Data, Size, &TemporaryWrittenBytes, NULL) == FALSE)
      return false; 
zu ..

C-/C++-Quelltext

1
2
if (Data == NULL || IsOpen() == false || WriteFile(FileHandle, Data, Size, &TemporaryWrittenBytes, NULL) == FALSE)
      return false; 
...

@David Scherfgen: Hmm das mit dem true und false und NULL mach ich auch manchmal ganz gerne ... so weiß ich immer genau worauf ich prüfe ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

18.03.2007, 12:59

Zuerstmal, das Tutorial an sich ist recht gut. Schön aufgebaut, verständlich geschrieben usw... Allerdings hab ich einige Sachen zu bemängeln! ;)

1. Die Constcorrection sollte eingehalten werden! (Hat David ja bereits gesagt)

2. Wieso löst du alle Definitionen von Windows auf (HANDLE, ...), das ist nicht nur unnötig sondern auch unschön. Ich weiß das Patrick darauf total abgefahren ist, aber nicht alles was er gut geheißen hat war es gleichzeitig auch.

3. Das ZeroMemory im C'tor ist wirklich, wirklich gefährlich! Zum einen ist es kein schöner Stil da entsprechende Variablen in der Initialisierungsliste initialisiert werden zum anderen wird der (falls vorhanden) vfptr überschrieben, was unschöne auswirkungen auf deinen Programmablauf haben kann.

4. Wenn du UNICODE verwenden willst dann bleib doch auch compatibel zu ANSI. Das ist problemlos machbar, einfach die W Erweiterung der entsprechenden Funktionen entfernen und statt L"xyz" schreibst du TEXT( "xyz" ). Fertig.

5.

C-/C++-Quelltext

1
2
3
4
5
//Ist die Datei nun geöffnet?

   if (IsOpen() == false)
      return false;

   return true;


Sowas bitte zusammenfassen. Das hat irgendwie einen leicht unprofessionellen touch! ;)

6. WrittenBytes ist ein Zeiger bei dir. Per Referenz wär das ganze aber schöner gelöst, kannst ja defaultmäßig auf std::cerr verweißen.

So, das wars erstmal. Ansonsten bin ich gespannt auf die Fortsetzung! ;)
@D13_Dreinig

6

18.03.2007, 13:07

Hmm aja und warum nutzt du nicht einfach stl ?
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

18.03.2007, 13:25

Zitat von »"Deviloper"«

Hmm aja und warum nutzt du nicht einfach stl ?


War das auf meinen Post bezogen? Wenn ja seh ich keinen Zusammenhang...
@D13_Dreinig

Sheddex

unregistriert

8

18.03.2007, 13:31

Danke für's Feedback :)

1. Zusammenfassen... irgendwie hab' ich an sowas echt noch nie gedacht, ich mache das schon ewig so^^
Werde ich wohl dann doch mal tun, ist ja echt kürzer.

2. ANSI-Kompatibilität... naja, ich bin halt UNICODE-Fan, aber wenn's sein muss bau' ich das halt noch ein ;)

3. Die STL kapselt afaik auch nur diese Funktionen und zwar auf eine Weise die mir nicht so wirklich gefällt. Zum Beispiel diese Trennung zwischen i und o und die Tatsache dass ich keine GetSize-Funktion gefunden habe.
Außerdem bindet man windows.h eigentlich immer ein, fstream.h kann man sich imho jedoch sparen.

9

18.03.2007, 13:34

3. Die size bekommst de ganz einfach mit Funktionen der STL heraus. Das ist gar kein Problem. Und wer will denn z.B. nur für Windows programmieren?
2. Ja nur weil du Fan davon bist ... ;)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Sheddex

unregistriert

10

18.03.2007, 15:01

@David_pb: Ich löse ja nicht alles auf was die WinAPI definiert. Nur in diesem Tutorial ist es alles. Ich löse alles auf was mit Standarddatentypen zu tun hat, also HANDLE zu void*, UINT und DWORD zu unsigned int und unsigned long. Es gefällt mir so einfach besser. HWND__* schreibe ich aber nicht, da bevorzuge ich dann schon HWND ;)

Das mit den Written- und ReadBytes lass' ich erstmal so als Pointer, finde es auch eigentlich überhaupt nicht unschön ;)

FilePointer wollte ich zuerst in diesen Teil einbauen, habe mich aber dagegen entschlossen, da ich hier lieber die absoluten Basics behandeln wollte.

UPDATE: Konstruktor und Destruktor verbessert, ANSI Kompatibilität hergestellt.

Werbeanzeige