Prüfen der Version der WinAPI
-
Hängt das wirklich nur vom Betriebssystem ab? Es gibt also keine Möglichkeit, diese Dateien upzudaten (so daß ich unter Windows 98 zum Beispiel auf die WinAPI update, die in Windows 2000 genutzt wird)?
-
Schau doch einfach in der Doku zu der Funktion nach!!! Da steht doch genau drin, wann welche Funktion verfügbar ist!!!
Z.B. "GetUserNameEx":
Client Requires Windows "Longhorn", Windows XP, or Windows 2000 Professional.
Server Requires Windows Server "Longhorn", Windows Server 2003, or Windows 2000 Server.Was ist da so schwierig für Dich zu erkennen??????
Oder "SHGetDiskFreeSpace":
Windows 2000, Windows NT 4.0 with Internet Explorer 4.0, Windows 98, Windows 95 with Internet Explorer 4.0
Updaten kannst Du natürlich immer, indem Du Dein OS (oder teilweise IE) updatest.
-
Es geht hier nicht darum, ob eine Funktion verfügbar ist. Es geht mir um folgendes: Manche Funktionen liefen unter Windows 98 noch etwas anders. Zum Beispiel füllte GetBitmapBits die nicht benutzten Bits mit relativ zufälligen Werten (meistens eine 0, aber manchmal auch eine 1) aus. Wenn ich also die Felder, die damit erstellt wurden, Und-verknüpfen will, muß ich diese Bits wegshiften. Sowas ist natürlich nicht dokumentiert, da es letztendlich ein Bug ist. Unter Windows 2000 werden die nicht benutzten Bits nämlich immer mit Nullen gefüllt, so daß die Und-Verknüpung dadurch nicht beeinflußt wird. Und nun habe ich vor, zur Laufzeit zu prüfen, ob ich das mit dem Wegshiften machen muß (wobei dann noch etwas mehr da dranhängt) oder ob ich es lassen kann. Und da wollte ich wissen, ob es jeweils eine WinAPI-Version pro Betriebssystem gibt, die sich auch nicht mehr ändert, oder ob die Frage, wie die GetBitmapBits-Funktion nun intern arbeitet, eher durch direktes Überprüfen der WinAPI-Version geklärt werden soll. Und deshalb war meine Frage im wesentlichen: Wie kann ich die installierte WinAPI-Version (bzw. die Version von diesen ganzen zugehörigen DLL-Dateien) abfragen? Das hat also überhaupt nichts damit zu tun, rauszufinden, ob eine Funktion unter diesem oder jenen Betriebssystem generell verfügbar ist.
-
GetVersionEx
-
Das liefert mir aber nur die Version des Betriebssystems. Doch mir ging es darum, die installierten WinAPI-Dateien zu prüfen. Wenn ich Windows 98 habe und, sofern das geht, die WinAPI-DLL-Dateien update, dann brauch ich nicht auf das Betriebssystem zu prüfen, sondern muß auf die DLL-Versionen prüfen.
-
Ich glaube, kaum, dass diese DLLs zu den Redistributables gehören. Deswegen reicht es völlig, wenn du die Betriebssystemversion prüfst.
-
Und im Zweifelsfall schreibst du den Code halt so, daß dir die unterliegende WinAPI-Version egal sein kann (um bei deinem Beispiel zu bleiben - du kannst auch bei einem Win2K-System die unbenutzten Bits "wegshiften").
-
NES-Spieler schrieb:
Das liefert mir aber nur die Version des Betriebssystems. Doch mir ging es darum, die installierten WinAPI-Dateien zu prüfen. Wenn ich Windows 98 habe und, sofern das geht, die WinAPI-DLL-Dateien update, dann brauch ich nicht auf das Betriebssystem zu prüfen, sondern muß auf die DLL-Versionen prüfen.
Ich versehe es nicht. Und was ich verstehe würde ich mit "Quark" titulieren!
Es gibt nur ganz wenige API-DLLs die vom OS losgelöst sind. SHELL32 als Beispiel. Ansonsten: Wenn es um USER32 und sonstige DLLs geht sind die OS gebunden! Für Dich muss immer GetVersionEx der Ausgangspunkt sein. Diese Funktion sagt Dir auch welches OS es ist und welche Version es ist.
-
@Martin Richter:
ich denke ihm ist halt nicht ganz klar dass viele Windows DLLs (speziell die "core" DLLs ala KERNEL32, USER32, GDI32 etc.) Bestandteil des OS sind, bzw. sehr eng damit verknüpft, und dass man die daher nicht austauschen kann.Andrerseits... es gibt ja viele DLLs die bei diversen Updates/Packages ausgetauscht werden, z.B. kann man TryEnterCriticalSection unter Windows 95 verwenden (ist denke ich mitm OSR2 dabei) genauso wie CoInitializeEx (kommt mit DCOM mit).
Anscheinen laufen sogar zumindest einige GDI+ Sachen unter Windows 95 wenn man einfach bloss die DLL draufkopiert (wobei ich die Frage ob das "ok" im Sinne der Lizenz ist mal ignoriere).
Und wieder andere Sachen bekommt man z.T. wenn man den neuesten IE installiert, wie z.B. wieder im Falle Windows 95 man die uniscribe DLL dazubekommt, die's sonst auch nicht gibt.
Die meisten dieser Möglichkeiten sind in der MSDN dokumentiert, aber leider nicht alle

-
NES-Spieler schrieb:
Es geht hier nicht darum, ob eine Funktion verfügbar ist. Es geht mir um folgendes: Manche Funktionen liefen unter Windows 98 noch etwas anders. Zum Beispiel füllte GetBitmapBits die nicht benutzten Bits mit relativ zufälligen Werten (meistens eine 0, aber manchmal auch eine 1) aus. Wenn ich also die Felder, die damit erstellt wurden, Und-verknüpfen will, muß ich diese Bits wegshiften. Sowas ist natürlich nicht dokumentiert, da es letztendlich ein Bug ist. Unter Windows 2000 werden die nicht benutzten Bits nämlich immer mit Nullen gefüllt, so daß die Und-Verknüpung dadurch nicht beeinflußt wird.
Die Funktion GetBitmapBits ist laut MSDN veraltet. Die alternative Funktion gibt es seit Windows 95.
Die Funktion GetBitmapBits wird sicherlich nicht irgendwelche Bits mit zufälligen Werten "füllen", das geschieht höchstens beim Erstellen des Bitmaps, sofern es nicht initialisiert wird. Wenn die API-Dokumentation nicht erwähnt, ob die Daten eines Bitmaps beim Erstellen mit 0 initialisiert werden, bedeutet das für den Programmierer, dass man sich auch nicht darauf verlassen darf, wie das Verhalten eines bestimmten Betriebssystems ist. Initialisierst du dein Bitmap nach dem Erstellen also einfach selbst, wirst du auf allen Betriebssystemen das gewünschte Verhalten erreichen ohne eine in diesem Fall unschöne Prüfung der Betriebssystemversion.
-
Es gibt nur ganz wenige API-DLLs die vom OS losgelöst sind.
Na also! Das hätte man mir von Anfang an sagen müssen: "Du kannst direkt die Betriebssystemversion prüfen, da die DLLs nicht austauschbar sind, sondern am Betriebssystem hängen." Dann hätte ich auch nicht weiter nachgefragt und solchen "Quark" geschrieben.
Die Funktion GetBitmapBits wird sicherlich nicht irgendwelche Bits mit zufälligen Werten "füllen"
Doch, tut sie. Muß sie ja auch. Denn sie macht aus einem fertigen Bild ein Feld. Und da sind immer ein paar Bits, die nicht gebraucht werden, die dann gefüllt werden müssen. Das hat nichts mit dem Bild selbst oder seiner Initialisierung zu tun. Mal ein vereinfachtes Beispiel (die Funktion arbeitet noch etwas anders, aber das Prinzip sollte deutlich werden): Du hast ein monochromes Bild mit 5x5=25 Pixeln. Da es monochrom ist, kann jeder Pixel in einem Bit gespeichert werden. Die Größe eines Feldeintrages ist 1 Byte, also 8 Bit. Wenn die Umwandlung vom Bitmap ins Feld stattgefunden hat, haben wir also ein Feld mit 4 Einträgen. Der erste Eintrag speichert die ersten 8 Pixel, der zweite speichert die Pixel 9 bis 16, der dritte ist für 17 bis 24 zuständig und der vierte speichert den 25. Pixel. Aber im vierten Eintrag sind die restlichen Werte unbenutzt. Und die werden unter Windows 98 nicht in jedem Fall mit 0 gefüllt. Das heißt, wenn ich über zwei gleich große Felder pro Index eine Und-Verknüpfung rüberlaufen lasse, um zu gucken, ob zwei Bilder an derselben Stelle einen weißen Punkt haben, könnte das Ergebnis verfälscht werden.
-
Windows speichert seine Bitmaps immer mit Ausrichtung der Scanlines an 16, bzw. 32 Bit. Die alten Funktionen wie SetBitmapBits, die noch aus der 16-Bit-Zeit stammen, verlangen, dass die Scanlines an 16 Bit ausgerichtet sind. Die Padding-Bits haben laut Definition den Wert 0. In der GetBitmapBits-Dokumentation steht es zwar nicht ausdrücklich, aber ich denke, dass diese Funktion die Scanlines nicht aufwändig zusammenstaucht sondern einfach den Buffer kopiert. Demnach müsste dein 5*5 Monochrom-Bitmap 10 Byte groß sein. Sollten die Padding-Bits nicht 0 sein, muss "irgendjemand" dafür verantwortlich sein, dass sie den falschen Wert haben.
Deshalb ist die Frage, woher die Daten dieses Bitmaps stammen. Hast du direkt mit den Daten des Bitmaps rumhantiert, könntest du versehentlich die Bits nicht berücksichtigt haben. Hast du das Bitmap allerdings nur durch Nutzung anderer Grafikfunktionen erhalten, könnte es tatsächlich ein Bug in Windows 98 sein.
-
Sollten die Padding-Bits nicht 0 sein, muss "irgendjemand" dafür verantwortlich sein, dass sie den falschen Wert haben.
Deshalb ist die Frage, woher die Daten dieses Bitmaps stammen.Die Daten für das Bitmap stammen direkt aus einer BMP-Datei, die mit Paint erstellt wurde.
Hast du direkt mit den Daten des Bitmaps rumhantiert, könntest du versehentlich die Bits nicht berücksichtigt haben. Hast du das Bitmap allerdings nur durch Nutzung anderer Grafikfunktionen erhalten, könnte es tatsächlich ein Bug in Windows 98 sein.
Ich habe eigentlich nichts weiter damit gemacht, sondern, wenn überhaupt, lediglich die entsprechenden Windows-Funktionen aufgerufen. Hätte ich selbst etwas im Speicher geändert, dann wäre das ja sicher auch bei den anderen Betriebssystemen so.
Ich habe dazu mal ein Testprogramm geschrieben. Das Bild, das dafür verwendet wird, ist folgendes:
http://img184.imageshack.us/img184/8278/mariofq5.png
Das müßte dann ins Bitmap-Format umgewandelt und als "Mario.bmp" gespeichert werden. Gut, hier ist der Code:#include <windows.h> int WINAPI WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { HBITMAP bitmap, monochrome, inverted, oldBitmap, oldMonochrome, oldInverted; HDC dc, monochromeDC, invertedDC; BITMAP bm; //Das Bild wird aus der Datei geladen und bekommt einen Device Context. bitmap=static_cast<HBITMAP> (LoadImage (instance, TEXT ("Mario.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)); dc=CreateCompatibleDC (NULL); oldBitmap=static_cast<HBITMAP> (SelectObject (dc, bitmap)); //Die Bitmap-Werte werden gespeichert. GetObject (bitmap, sizeof (bm), &bm); //Die Hintergrundfarbe wird auf Zyan festgelegt. SetBkColor (dc, RGB (0, 128, 128)); //Ein gleichgroßes monochromes Bild wird erstellt. monochrome=CreateBitmap (bm.bmWidth, bm.bmHeight, 1, 1, NULL); monochromeDC=CreateCompatibleDC (NULL); oldMonochrome=static_cast<HBITMAP> (SelectObject (monochromeDC, monochrome)); //Ein weiteres gleichgroßes monochromes Bild wird erstellt. inverted=CreateBitmap (bm.bmWidth, bm.bmHeight, 1, 1, NULL); invertedDC=CreateCompatibleDC (NULL); oldInverted=static_cast<HBITMAP> (SelectObject (invertedDC, inverted)); //Das Bild wird auf das monochrome Bild kopiert, und zwar so, daß der Hintergrund (zyan) als schwarz gewertet wird. BitBlt (monochromeDC, 0, 0, bm.bmWidth, bm.bmHeight, dc, 0, 0, NOTSRCCOPY); //Das ganze passiert nochmal invertiert mit dem zweiten monochromen Bild BitBlt (invertedDC, 0, 0, bm.bmWidth, bm.bmHeight, dc, 0, 0, SRCCOPY); /*Zum Test: Um zu gucken, ob die Bilder auch richtig geladen wurden, werden die direkt auf den Bildschirm gezeichnet. (Ich hatte keine Lust, extra ein Fenster zu erstellen.) Dazu bitte die 0 in eine 1 ändern.*/ #if 0 HDC windowDC=GetDC (NULL); StretchBlt (windowDC, 100, 150, bm.bmWidth*5, bm.bmHeight*5, dc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); StretchBlt (windowDC, 300, 150, bm.bmWidth*5, bm.bmHeight*5, monochromeDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); StretchBlt (windowDC, 500, 150, bm.bmWidth*5, bm.bmHeight*5, invertedDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); ReleaseDC (NULL, windowDC); #endif //Erstellen von Feldern. const UINT SIZE=bm.bmWidthBytes*bm.bmHeight; BYTE *array1=new BYTE [SIZE], *array2=new BYTE [SIZE]; bool collision=false; //Aufrufen der besagten Funktionen. GetBitmapBits (monochrome, SIZE, array1); GetBitmapBits (inverted, SIZE, array2); //Testen auf Kollision for (UINT i=0; i<SIZE && !collision; i++) { if ((array1 [i]&array2 [i])!=0) collision=true; } MessageBox (NULL, collision?TEXT ("Kollision"):TEXT ("Keine Kollision"), TEXT ("Abfrage"), MB_OK); //Alles wird wieder gelöscht. delete [] array1; delete [] array2; SelectObject (invertedDC, oldInverted); SelectObject (monochromeDC, oldMonochrome); SelectObject (dc, oldBitmap); DeleteDC (invertedDC); DeleteDC (monochromeDC); DeleteDC (dc); DeleteObject (inverted); DeleteObject (monochrome); DeleteObject (bitmap); return 0; }Ich habe also zwei monochrome Bilder, die komplett invertiert sind. Das heißt, bei einer Und-Verknüpfung dürfte niemals ein anderer Wert als 0 rauskommen. Und bei Windows 2000 und XP funktioniert das auch. Nur bei Windows 98 registriert er eine Kollision. Daraus folgt: Die Füllbits sind nicht immer 0, sondern haben auch gelegentlich irgendwo eine 1. Und wenn zwei Einsen an derselben Stelle aufeinandertreffen, gibt es eine Kollision. (Ich hab das auch damals mal im Debug-Modus nachgeprüft, aber für dieses Mal habe ich eben das Programm hier geschrieben.)
-
- Du lädst ein in einer BMP-Datei gespeichertes geräteunabhängiges Bitmap
- Du erstellst einen zu deiner Grafikkarte/aktuellen Farbtiefe passenden DC
- Du selektierst das Bitmap in diesen DC, das Bitmap wird dadurch in ein für den DC passendes Pixelformat umgewandelt
- Du fragst die Bitmap-Informationen des umgewandelten Bitmaps ab, bmBitsPixel enthält die aktuelle Farbtiefe deines Grafikmodus, bmWidthBytes ist dementsprechend berechnet.
- Du erstellst ein Monochrom-Bitmap und kopierst die Pixeldaten dorthin. Durch den DC kann das Pixelformat automatisch konvertiert werden.
- Du nutzt die alte GetBitmapBits-Funktion, die von Gerätekontexten keine Ahnung hat und deshalb auch nicht überprüfen kann, ob das Pixelformat kompatibel ist
- Du berechnest die Größe deines Buffers anhand der Bitmap-Informationen des ersten Bitmaps und liest somit über den Buffer hinaus. Die Werte dort haben einen undefinierten Zustand, der sich wie von dir beschrieben auswirkt.Der Fehler liegt zwar nicht direkt in der Verwendung der alten API, aber es ist auf jeden Fall sinnvoller, GetDIBits zu verwenden um generell Inkompatibilitäten in den Pixelformaten vorzubeugen.

-
masterofx32 schrieb:
Die Funktion GetBitmapBits ist laut MSDN veraltet. Die alternative Funktion gibt es seit Windows 95.
Nur als Anmerkung: Microsoft deklariert viel Funktionen als verlaltet, solange nicht steht "nicht unterstützt" ist das ganze kein Problem. Alle diese Funktionen arbeiten tadellos.
Eines der besten Beispiele sind die Funktionen WritePrivateProfile... und GetPrivateProfile... Irgendwann hat MS mit der Registry angefangen, also weg von der einzelnen Konfigurationsdatei. Jetzt wird wirder langsam zurückgerudert mit all den config Dateien, die überall rumschwirren.
Solange es WinAPI gibt wird es auch diese Funktionen geben.EDIT: Quote gefixt!
-
Martin Richter schrieb:
Nur als Anmerkung: Microsoft deklariert viel Funktionen als verlaltet, solange nicht steht "nicht unterstützt" ist das ganze kein Problem. Alle diese Funktionen arbeiten tadellos.
Ja, das stimmt, Microsoft würde nicht einfach die Unterstützung dieser Funktion aufgeben, wenn dadurch Inkompatibilität mit Programmen, die diese API nutzen entstünde.
Speziell mit diesen Funktionen gibt es aber das Problem, dass sie nur mit geräteabhängigen Bitmaps arbeiten. Das bedeutet, dass das Format der Bitmapdaten allein vom Grafiktreiber und der Grafikhardware abhängig ist und beim Selektieren in einen Gerätekontext beliebig umgewandelt werden kann. Sofern man sich doch auf ein auf heutigen PCs übliches Pixelformat verlässt, gibt es noch die von der internen DWORD-Ausrichtung abweichende WORD-Ausrichtung der Scanlines. Das kann zu geringfügigen Performanceeinbußen führen, da es wahrscheinlich von Windows vor Benutzung noch einmal umgewandelt wird.
-
Irgendwie sehe ich bei dieser GetDIBits-Funktion mit ihren Scanlines und Bitmapheadern nicht durch. Gibt es irgendwo ein praktisches Beispiel, wo mal erläutert wird, wie ich so ein Bild in ein Feld kopiere?
P.S.: Ist das Bild, wenn es im Speicher des Programms liegt (so daß man mit einer HBITMAP-Variable drauf zugreifen kann) nicht geräteabhangig? In dem Fall dürfte es doch viel logischer sein, mit der GetBitmapBits-Funktion zu arbeiten, die von geräteabhängigen Bitmaps ausgeht, statt es nochmal extra wieder geräteunabhängig zu machen oder liege ich da falsch?
-
NES-Spieler schrieb:
P.S.: Ist das Bild, wenn es im Speicher des Programms liegt (so daß man mit einer HBITMAP-Variable drauf zugreifen kann) nicht geräteabhangig? In dem Fall dürfte es doch viel logischer sein, mit der GetBitmapBits-Funktion zu arbeiten, die von geräteabhängigen Bitmaps ausgeht, statt es nochmal extra wieder geräteunabhängig zu machen oder liege ich da falsch?
Ja, das Bild im Speicher ist ein geräteabhängiges Bitmap. Damit man sich auf das Format der Pixeldaten verlassen darf, ist aber die Umwandlung in ein geräteunabhängiges Bitmap erforderlich. Die GetBitmapBits-Funktion tut dies nicht sondern liefert einfach die aktuellen Daten des geräteabhängigen Bitmaps, und die können in einem beliebigen Format vorliegen, das sich abhängig von der Hardware von dem von dir erwarteten Format unterscheiden kann und auch nicht zwischen verschiedenen Geräten kompatibel sein muss.
Wenn das Pixelformat kompatibel ist, wird zur Umwandlung von abhängigen zu unabhängigen Bitmaps nur der Buffer kopiert, ansonsten erfolgt eine etwas aufwändigere Konvertierung, die Windows vom Grafikkartentreiber(oder dem eines Druckers, etc) durchführen lässt, da nur dieser das Format der geräteabhängigen Bitmaps verlässlich kennt.Du kannst ja mal schauen, ob du mit diesem Beispiel was anfangen kannst. Das ist allerdings etwas komplexer als das, was du in deinem Fall brauchst.