Ich möchte einen Text mit DirectX 9 (August) ausgeben
-
Hallo,
ich bin blutiger Anfänger mit DirectX, also ein bischen Gnade walten lassen.

Ich kann zwar ein blaues Fenster erzeugen, aber wenn ich dann die Schrift ausgeben will, gibt es einen Fehler.
Der Kompiler gibt mir folgende Meldung in einer MessageBox aus "Unbehandelte Ausnahme bei 0x004118c9 in erstes DirectX win.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000."
Wenn ich die Zeile
lpD3DFont->DrawTextA(NULL,reinterpret_cast<LPCSTR>(psz),-1, &r, DT_CALCRECT, TextColor);weglasse, dann wird das Programm normal ausgeführt. Allerdings ohne Schrift

Ich schätze mal, dass der fehler in der CreateD3DFont(void) liegt.Programmiert habe ich das ganze mit Visual Studio 2005
//für den Code siehe unten :-)
-
schreib einfach
lpD3DFont->DrawTextW(NULL,psz,-1, &r, DT_CALCRECT, TextColor);warum nutzt du überhaupt Unicode-Strings und nutzt aber Multibytefunktionen?
-
also scheinbar ist ja dein Prog eine Unicode-Anwendung, dann sollte es also auch reichen, wenn du nur DrawText schreibst, denn der Compiler kümmert sich dann drum
-
Hallo,
danke für die schnelle Antwort. Ich habe die besagte Zeile geändert und siehe da ich brauche keinen Cast anzustellen.
Jedoch tritt beim Ausführen die gleiche Exception auf. Irgendwas scheint noch nicht in Ordnung zu sein. Ich poste mal mein komplettes Programm (sobald die Textausgabe funktioniert, wollte ich DirectX in einer ersten DirectX Klasse auslagern).
Grüße
Fireball
// Headerdatei #include <d3d9.h> #include <d3dx9.h> #include <wchar.h> #include <string> #include <iostream> using namespace std; // Anwendungsfenster erzeugen HWND CreateMainWindow(HINSTANCE hInstance); // Callback Funktion zur Nachrichtenbehandlung LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); // Funktion zur Initialisierung von Direct3D BOOL InitDirect3D(HWND hWnd); // Direct3D-Objekte wieder freigeben void CleanUpDirect3D(void); // Font erstellen void CreateD3DFont(void); // Zeiger auf das Direct3D-Objekt (Interface) LPDIRECT3D9 lpD3D = NULL; // Zeiger auf das Direct3D-Device LPDIRECT3DDEVICE9 lpD3DDevice = NULL; // Das Fensterhandle HWND hWnd = 0; // Zeiger auf das Direct3D-Font-Objekt LPD3DXFONT lpD3DFont = NULL; int WINAPI WinMain(HINSTANCE hInstance,//instance der Anwendung HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // Fenster erzeugen und das Handle speichern hWnd = CreateMainWindow(hInstance); //prüfen ob das Fenster erzeugt werden konnte if(hWnd == 0) { MessageBox(0,TEXT("Das Fenster konnte nicht erzeugt werden"), TEXT("Fehler"),MB_OK); return -1; } //DirectX initialisieren if(!InitDirect3D(hWnd)) { MessageBox(0,TEXT("DirectX konnte nicht initialisiert werden"), TEXT("Fehler"),MB_OK); return -1; } else { MessageBox(0,TEXT("DirectX wurde initialisiert"), TEXT("Info"),MB_OK); } // Schrift erzeugen CreateD3DFont(); // Struktur, in der Informationen zur Nachricht gespeichert werden MSG msg; //Endlosschleife, die solange läuft, bis die Nachricht WM_QUIT empfangen wird while(GetMessage(&msg,NULL,0,0)) { // Nachricht dan die Callback Funktion senden TranslateMessage(&msg); DispatchMessage(&msg); //damit Windows die Callback Funktion aufrufen kann } CleanUpDirect3D(); return 0; } BOOL InitDirect3D(HWND hWnd) { lpD3D = Direct3DCreate9(D3D_SDK_VERSION); if(lpD3D == NULL) { return FALSE; } // Parameter für den Modus festlegen D3DPRESENT_PARAMETERS PParams; ZeroMemory(&PParams, sizeof(PParams)); PParams.SwapEffect = D3DSWAPEFFECT_DISCARD; PParams.hDeviceWindow = hWnd; PParams.Windowed = TRUE; PParams.BackBufferWidth = 800; PParams.BackBufferHeight = 600; PParams.BackBufferFormat = D3DFMT_A8R8G8B8; //Farbtiefe des BackBuffer ACHTUNG genau hingucken!!! //Direct3D-Gerät anlegen if(FAILED(lpD3D->CreateDevice( D3DADAPTER_DEFAULT, //primäre GFX karte, man kann auch mehrere nutzen!!! D3DDEVTYPE_HAL, //ja gib mir alles, GFX Hardwarebeschleunigung hWnd, //wo soll DirectX reinzeichnen, wie übergeben dazu das Handle unseres Fenster D3DCREATE_SOFTWARE_VERTEXPROCESSING, //bei Geometrieverarbeitung die GFX Karte nutzen &PParams, //Zeiger auf unsere Einstellung &lpD3DDevice ))) { return FALSE; } return TRUE; } LRESULT CALLBACK MessageHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { D3DCOLOR ClearColor = D3DCOLOR_XRGB(0,0,0xFF); //blau switch(msg) { case WM_DESTROY: PostQuitMessage(0); return 0; break; case WM_KEYDOWN: switch(wParam) { case VK_ESCAPE: //bei ESC beenden DestroyWindow(hWnd); break; } //Das Fenster soll gezeichnet werden case WM_PAINT: D3DCOLOR TextColor = D3DCOLOR_XRGB(0xFF,0,0); //blau zeichnen lpD3DDevice->Clear(0,0, D3DCLEAR_TARGET, ClearColor, 0,0); RECT r = {100, 100, 0, 0 }; wstring wstr = L"wide char string"; LPCWSTR psz = wstr.c_str(); lpD3DDevice->BeginScene(); lpD3DFont->DrawText(NULL,psz,-1, &r, DT_CALCRECT, TextColor); lpD3DDevice->EndScene(); lpD3DDevice->Present(0,0,0,0); break; } return DefWindowProc(hWnd,msg,wParam,lParam); } HWND CreateMainWindow(HINSTANCE hInstance) { TCHAR szAppName[] = TEXT ("WindowClass"); //name der Anwendung TCHAR szWindowName[] = TEXT ("DirectX"); //name des fensters WNDCLASSEX wndClass = { sizeof(WNDCLASSEX), //größe CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, //stile MessageHandler, //callback funktion 0, 0, hInstance, //Anwendungsinstance LoadIcon(NULL,IDI_WINLOGO), LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), NULL, szAppName, LoadIcon(NULL,IDI_WINLOGO) }; //Fensterklasse registrieren, damit CreateWindowEx diese nutzen kann RegisterClassEx(&wndClass); return CreateWindowEx( NULL, szAppName, szWindowName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 800, 600, NULL, NULL, hInstance, NULL); } void CleanUpDirect3D(void) { //Objekte müssen in der Reihenfolge freigegeben werden, wie sie auch angelegt worden sind! if(NULL != lpD3DFont) { lpD3DFont->Release(); lpD3DFont = NULL; } if(NULL != lpD3DDevice) { lpD3DDevice->Release(); lpD3DDevice = NULL; } if(NULL != lpD3D) { lpD3D->Release(); lpD3D = NULL; } } void CreateD3DFont(void) { // Struktur für das Font festlegen LOGFONT font = {0}; wchar_t *Widen = L"Arial"; wcscpy(font.lfFaceName,Widen); D3DXCreateFontIndirect(lpD3DDevice,reinterpret_cast<D3DXFONT_DESCW*>(&font),reinterpret_cast<LPD3DXFONT*>(lpD3DFont)); //es gibt 9 Möglichkeiten zu casten!!! *kotz* }
-
Ich hab den Fehler erst nicht gefunden, deshalb zunächst das, was ich erst schreiben wollte.
Also dein Problem ist, dass das D3DXCreateFontIndirect fehlschlägt. Probier vielleicht einmal D3DXCreateFont aus. Außerdem kommts mir etwas merkwürdig vor, die LOGFONT Struktur einfach komplett auf 0 zu setzen. Ach ja, und warum nimmst du überhaupt eine LOGFONT-Struktur anstatt einer D3DXFONT_DESC?
Der Error-Code, den D3DXCreateFontIndirect ausgibt, ist D3DERR_INVALIDCALL.So, aber dein eigentlicher Fehler: Hier
reinterpret_cast<LPD3DXFONT*>(lpD3DFont)
.
Casts sind schon eine gefährliche Sache, hm? Müsste eigentlich "&lpD3DFont" sein.
Text zeigts bei mir zwar auch nicht an, aber es gibt keine NULL-Pointer-Exception
-
Hallo!
Danke, danke, danke!!!
Es funktioniert nun, ich habe alle Ratschläge befolgt und bin nun an mein Ziel gelangt.
Nun woran lag es?
1. Unicode wurde in meinem Projekt verwendet, dass habe ich erstmal ausgestellt.
So konnte ich mir einige blöde Casts sparen.2. Meine CreateFont Methode sieht nun so aus ...
void CreateD3DFont(void) { // Create a colour for the text - in this case blue D3DCOLOR fontColor = D3DCOLOR_ARGB(255,0,0,0); // Create a rectangle to indicate where on the screen it should be drawn RECT rct; rct.left=2; rct.right=780; rct.top=10; rct.bottom=rct.top+20; //Das folgende habe ich von http://www.toymaker.info/Games/html/text.html D3DXCreateFont( lpD3DDevice, 20, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &lpD3DFont ); lpD3DFont->DrawText(NULL, "Hello World", -1, &rct, 0, fontColor ); }3. Der Aufruf fand dann wie folgt statt.
lpD3DDevice->BeginScene(); CreateD3DFont(); //Schriftzug ausgeben lpD3DDevice->EndScene();Grüße
Fireball
-
nur so ganz nebenbei ... ich hab da mein problem mit diesem D3DXFONT ... hab das aber auch schon anders gelösst ...
also jedes mal nen font zu generieren (CreateFont...) ist doch in 99,9% aller fälle das selbe -> es müsste doch nur einmal gemacht werden -> hab es bei der init prozedur reingenommen und das font objekt mit in die klasse wo die ganze DX-api aufrufe bearbeitet werden gelegt -> per cut & paste ... aber da kamms zum Error ähnlich wie zum anfang beschrieben also hab ich mir nix dir nixh die zwei sachen wieder vor DrawText gesetzt und was passiert - es funktioniert ... wieder zurück ... error;
also wenn ich das selbe bei Texturen, Vertexbuffer und etc mache hab ich am ende bei nur einem polygon doch nur noch eine 1fps und so musses doch beim font doch auch möglich sein den font vorzeitig zu initialisieren und dann nur noch zu "drawen"
aber wie gesagt ich hab jetzt meinen eigene "Drawtext"-api gemacht
und das ist auch für Console optimiert.ich mach das mit nem bmpfile im Speicher sobald was in die console kommt wird diese "aktuallisiert" und die consolen textur geupdated und wenn console an ist wird nur die textur gezeichnet - ok hat bislang den "bug" das es nur xzeichen lang sein darf aber das werd ich beim nächsten optimieren beheben
mir viel auch eben was ein 
-
FireballGFX schrieb:
Nun woran lag es?
Haettest du mal den Debugger genommen und selbst nach dem Fehler gesucht anstatt hier dumm zu fragen, dann wuesstest du es. Das hier keiner eine Glaskugel hat, ist dir schon klar. f'`8k
AutocogitoGruß, TGGC (\-/ has leading)
-
für dich mal so ganz neben bei TGGC:
es liegt daran das man
ID3DXFont myfont;
myfont->create(.......);
myfont->drawtext(.........);so nach einander aus führen muss, ich habs versucht myfont in die klasse von mein 3drenderer objekt zu definieren bei init3d als letztes myfont->create durch zufüren ... aber wie ichs schon beschrieben hatte funktionierte dies nicht, obwohl ichs per copy & paste verändert hatte
-
nur dumme Antworten!
Dieses Zitat finde ich passend, stand auf deinem tollen Link

"Falls du bereits gesucht hast, bist du wahrscheinlich falsch an die Sache herangegangen. Wenn du alle oben genannten Hinweise ausprobiert hast trotzdem noch keine Loesung gefunden hast, frag' einfach nach."
Aber ich bin trotzdem Froh, dass es doch noch nette Menschen gibt, die sich etwas Zeit genommen haben und mir zur Seite Standen!
Gruß
Fireball
-
@FireballGFX: np, verteile gerne meine Weisheit.
@LinkeT: Bitte hoer auf anderen Scheisse zu erzaehlen, nur weil du zu dumm zum Programmieren bist. f'`8k
AutocogitoGruß, TGGC (\-/ has leading)
-
Du hast Recht, ich sollte das nächste mal erstmal genauer hingucken und keine MessageBox ausgeben, bevor nicht wirklich alles initialisiert wurde. Nachdem ich diese rausgenommen hatte funktionierte es wie in meinem DirectX Buch beschrieben.
So und das soll es jetzt von meiner Seite aus gewesen sein.
Aber vielleicht trifft man sich ja mal auf der Breakpoint. Wer hat dicke E***?

Gruß
Fireball
-
TGGC schrieb:
@FireballGFX: np, verteile gerne meine Weisheit.
@LinkeT: Bitte hoer auf anderen Scheisse zu erzaehlen, nur weil du zu dumm zum Programmieren bist. f'`8k
AutocogitoGruß, TGGC (\-/ has leading)
ja aber mal nicht gleich beleidiggen

deine weisheiten helfen aber keinem weiter aber :psst: ich nems nich persönlich nicht jeder kann seine dumme kommentare einfachmal weglassen ....EDIT ich könnt auch in meinem Profil Softwareentwickler eintragn und keine fragen stellen und nur dumme Kommentare abgeben - würd gar net auffallen ...