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

1

21.09.2009, 15:48

Listing 2.51: Ausgabe Problem

HI!
Hab folgendes Problem:
Habe den Code aus Listing 2.51 (Auflisten & anzeigen aller auf dem System verfügbaren Direct3D-Adapter) abgeschrieben & kompiliert!

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
57
58
59
60
61
62
#include <Windows.h>
#include <StdIO.h>
#include <D3D9.h>
#include <d3dx9.h> 
#include <dxerr.h> 
#include <tchar.h>

int WINAPI WinMain (HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    char* pcCmdLine,
                    int iShowCmd)
{
    // Schnittstelle erzeugen

    PDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION );
    MessageBox(NULL,(LPCWSTR)pD3D,(LPCWSTR)L"Fehler", MB_OK | MB_ICONEXCLAMATION);
    if(!pD3D)
    {
        // Fehler beim Erstellen der Schnittstelle

        MessageBox(NULL, (LPCWSTR)L"Direct3D 9 konnte nicht initialisiert werden!\n Installieren Sie bitte die neueste DirectX-Version.",
                         (LPCWSTR)L"Fehler", MB_OK |MB_ICONEXCLAMATION);
        return 1;
    }
    
    // Anzahl der Adapter ermitteln

    int iNumAdapters = pD3D->GetAdapterCount();

    // Speicher reservieren & Informationen über jeden Adapter sammeln

    D3DADAPTER_IDENTIFIER9* pAdapters = new D3DADAPTER_IDENTIFIER9[iNumAdapters];

    for (int iAdapter=0; iAdapter<iNumAdapters; iAdapter++)
    {
        if (FAILED(pD3D->GetAdapterIdentifier(iAdapter, 0, &pAdapters[iAdapter])))
        {
            // Fehler

            MessageBox(NULL, (LPCWSTR)L"Adapterinformationen konnten nicht abgefragt werden!",
                             (LPCWSTR)L"Fehler", MB_OK | MB_ICONEXCLAMATION);

            // Aufräumen

            pD3D->Release();
            delete[] pAdapters;
            return 1;
        }
    
        // Adapterinformationen anzeigen

        char acAdapterInfo[1024];
        sprintf_s(acAdapterInfo, "Adapter-ID: %d\n"
                               "Name: %s\n"
                               "Treiber: %s\n"
                               "nTreiberversion: %d",
                               iAdapter,
                               pAdapters[iAdapter].Description,
                               pAdapters[iAdapter].Driver,
                               pAdapters[iAdapter].DriverVersion);

        MessageBox(NULL, (LPCWSTR)acAdapterInfo, (LPCWSTR)L"Adapter gefunden", MB_OK | MB_ICONINFORMATION);
    }
    
    // Aufräumen

    pD3D->Release();
    delete[] pAdapters;
    return 0;
}


Läuft alles ganz gut bis auf das tatsächliche Ergebnis, was in etwa so aussieht:


(Link)


Kann mir jemand sagen was falsch ist, oder worin der Fehler liegt??
:?:

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

21.09.2009, 16:06

C-/C++-Quelltext

1
MessageBox(NULL, (LPCWSTR)acAdapterInfo  /* <- */, (LPCWSTR)L"Adapter gefunden", MB_OK | MB_ICONINFORMATION); 


Da liegt mal ein Fehler: acAdapterInfo ist kein wide string sondern nur ein normales char Array. Der Compiler regt sich ja auch auf aber du hast ihn durch den cast da wohl gezwungen das zu kompillieren.
Lösung: wchar_t oder TCHAR statt char verwenden...

Abgesehen davon:

C-/C++-Quelltext

1
MessageBox(NULL,(LPCWSTR)pD3D,(LPCWSTR)L"Fehler", MB_OK | MB_ICONEXCLAMATION); 


Ich frage mich wo du so eine Zeile abgeschrieben hast, das is nämlich komplett falsch. pD3D ist doch kein string!?

Ich würd dir empfehlen mal die ganzen (LPCWSTR) casts wegzumachen. Wenn der Compiler sich da aufregt tut er das zurecht (wie du ja selber gesehen hast) und du solltest den Fehler beheben anstatt den Compiler mit casts zum Schweigen zu bringen ;)

3

21.09.2009, 16:26

Ok, danke mal für die schnelle Antwort!

Hab alle casts entfernt...
...jetzt kommt jedoch der Fehler :

sprintf': Konvertierung des Parameters 1 von 'wchar_t [1024]' in 'char *' nicht möglich

bei folgender Code-Zeile:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
sprintf(acAdapterInfo, "Adapter-ID: %d\n"
                               "Name: %s\n"
                               "Treiber: %s\n"
                               "nTreiberversion: %d",
                               iAdapter,
                               pAdapters[iAdapter].Description,
                               pAdapters[iAdapter].Driver,
                               pAdapters[iAdapter].DriverVersion);


Wie kann ich diesen Fehler beheben (ohne einen Cast zu machen)?

& des Weiteren....

C-/C++-Quelltext

1
MessageBox(NULL, _T("bla"), _T("Fehler"), MB_OK | MB_ICONEXCLAMATION);


Wenn ich bei einem "Text" nicht das Makro _T(x) oder einen LPCWSTR cast mache kommt sowieso ein compiler-fehler....

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

21.09.2009, 16:47

Zitat von »"hermi999"«

sprintf': Konvertierung des Parameters 1 von 'wchar_t [1024]' in 'char *' nicht möglich
[...]
Wie kann ich diesen Fehler beheben (ohne einen Cast zu machen)?


Du kannst den Fehler beheben indem du die richtige Funktion verwendest, in dem Fall wär das wsprintf() anstatt sprintf(). Ein cast würde den Compiler zwingen es zu kompilieren, das Programm wär aber trozdem immer noch falsch ;)


Zitat von »"hermi999"«

Wenn ich bei einem "Text" nicht das Makro _T(x) oder einen LPCWSTR cast mache kommt sowieso ein compiler-fehler....


Du musst das Makro TEXT() oder _T() verwenden oder vor das Literal ein L packen, z.B. L"Text". Alles andre ist falsch (auch wenn der cast eine Fehlermeldung umgeht wär der Code in dem Fall trozdem falsch).

5

21.09.2009, 17:02

OK!
Die Adapter-ID & nTreiberversion werden jetzt korrekt angezeigt.
Name & Treiber sind noch immer "irgenwelche Zeichen"...
...ich schätz mal hier liegt der Fehler begraben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
wchar_t acAdapterInfo[1024];
        wsprintf(acAdapterInfo, L"Adapter-ID: %d\n"
                               L"Name: %s\n"
                               L"Treiber: %s\n"
                               L"nTreiberversion: %d",
                               iAdapter,
                               pAdapters[iAdapter].Description,
                               pAdapters[iAdapter].Driver,
                               pAdapters[iAdapter].DriverVersion);

        MessageBox(NULL, acAdapterInfo, _T("Adapter gefunden"), MB_OK | MB_ICONINFORMATION);
    }

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

21.09.2009, 17:16

Ja klar pAdapters[iAdapter].Description, Driver, und DriverVersion sind ja normale char Arrays und keine wide strings. D.h. du musst die natürlich erst in wchar_t Arrays umwandeln, z.B. mit mbstowcs().
Alternativ könntest du dir die ganze Unicode Geschichte für den Anfang auch einfach mal schenken indem du in den Compilereinstellungen unter "General" den Punkt "Character Set" auf "Not Set" stellst und überall mit normalen char Arrays arbeitest...

7

22.09.2009, 15:49

So, danke mal für die Hilfe!!!

Hab jedoch jetzt noch eine Frage zur Fortsetzung:

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
.....
.....
.....
// -------------------------------------------------------------------------------------------

// Auflisten aller Videomodi, die zu einem bestimmten Format kompatibel sind

//--------------------------------------------------------------------------------------------


    // Ermitteln, vie viele 16-Bit-Videomodi verfügbar sind

    int iNumModes = pD3D->GetAdapterModeCount(iAdapter-1, D3DFMT_R5G6B5);
    if (iNumModes > 0)
    {
        // Speicherplatz reservieren & den String zurücksetzen

        D3DDISPLAYMODE* pModes = new D3DDISPLAYMODE[iNumModes];
        wchar_t acModes[16384];

        // Jeden Videomodus durchgehen

        for (int iMode=0; iMode<iNumModes; iMode++)
        {
            // Infos über diesen Modus abfragen

            pD3D->EnumAdapterModes(iAdapter, D3DFMT_R5G6B5, iMode, &pModes[iMode]);

            // Nummer, Breite, Höhe & Bildwiederholfrequenz in den String schreiben

            wsprintf(acModes, L"%s\nModus %d: %dx%d bei %d Hz (0: Standard)",
                    acModes,
                    iMode,
                    pModes[iMode].Width,
                    pModes[iMode].Height,
                    pModes[iMode].RefreshRate);
        }

        // Videomodi anzeigen

        MessageBox(NULL, acModes, _T("Verfügbare 16-Bit-Videomodi"), MB_OK | MB_ICONINFORMATION);
        
        // Speicher wieder freigeben

        delete[] pModes;
    }

    // Aufräumen

    pD3D->Release();
    delete[] pAdapters;
    return 0;
}


Warum schreibt man hier:

C-/C++-Quelltext

1
2
3
4
5
6
            wsprintf(acModes, L"%s\nModus %d: %dx%d bei %d Hz (0: Standard)",
                    acModes,
                    iMode,
                    pModes[iMode].Width,
                    pModes[iMode].Height,
                    pModes[iMode].RefreshRate);

als ersten Parameter acModes, wenn gar nichts drinnen steht???
Bei mir kommt dann nur Speichermüll raus!

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

22.09.2009, 15:59

Zitat von »"hermi999"«


Warum schreibt man hier:

C-/C++-Quelltext

1
2
3
4
5
6
            wsprintf(acModes, L"%s\nModus %d: %dx%d bei %d Hz (0: Standard)",
                    acModes,
                    iMode,
                    pModes[iMode].Width,
                    pModes[iMode].Height,
                    pModes[iMode].RefreshRate);

als ersten Parameter acModes, wenn gar nichts drinnen steht???
Bei mir kommt dann nur Speichermüll raus!


Du solltest das erste element von acModes auf '\0' setzen dann würd was sinnvolles rauskommen. Der Grund warum du da acModes als ersten Parameter verwendest ist wohl damit die einzelnen Modi hintereinandergehängt werden...

9

23.09.2009, 09:12

ok, die "chinesischen" Zeichen sind weg....das Ergebnis kann jedoch auch nicht wirklich stimmen, oder???

Modus 0: 3233664x3233352 bei 1724909938 Hz (0: Standard)
Modus 1: 1308010014x2004173573 Hz (0: Standard)
Modus 2: 1308010014x2004173573 Hz (0: Standard)
Modus 3: 1308010014x2004173573 Hz (0: Standard)
Modus 4: 1308010014x2004173573 Hz (0: Standard)
Modus 5: 1308010014x2004173573 Hz (0: Standard)
Modus 6: 1308010014x2004173573 Hz (0: Standard)
Modus 7: 1308010014x2004173573 Hz (0: Standard)

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

Werbeanzeige