Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jun 01, 2024 00:39

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: Typumformung und Klassenstrukturen
BeitragVerfasst: Di Nov 29, 2011 19:35 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
Hallo,

ich bin in den letzten Tagen und Wochen auf C++ umgestiegen weil es kostenfrei ist und ich nicht ganz so viel naja ihr wisst schon was haben mag :D

Doch das ist nicht gerade einfach, die Initialisation von Opengl und einem Fenster ist viel größer, umformung von Datentypen nicht ganz so einfach.

Als erstes mein Hauptproblem ich möchte ein Char* zu einem LPCWSTR machen dazu habe ich folgenden Ansatz zusammengebastelt:
Code:
  1. LPCWSTR CharToLPCWSTR(char* s)
  2. {
  3.     WCHAR str[256];
  4.     MultiByteToWideChar(0,0,s,255,str,256);
  5.     LPCWSTR Returnstring=str;
  6.     return Returnstring;
  7. }


Dass endet aber in Ausnahme Acces Violations und am Ende kommen Kryptische Zeichen herraus.

Das Zweite ist sicher einfach, in Delphi war eine solche struktur möglich:

Code:
  1.  
  2. Klasse=class
  3.  private
  4.    Zahl1:Integer;
  5.  public
  6.     property Zahl1:Integer read Zahl1 write Zahl1;
  7. end;


Ziel war es von außen auf private Mitglieder einer Klasse zugreifen zu können, aber wie geht das in c++?

danke euch im Vorraus schonmal

lg Dropye


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 19:53 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Beim ersten Problem kann ich dir leider nicht helfen, da ich keine Ahnung habe was ein LPCWSTR sein soll. Es empfiehlt sich normalerweise die angebotene String-Klasse std::string oder die String-Klasse einer Library die man benutzt zu verwenden. Etwa mit dem QString von Qt kommt man schon extrem weit.

Zitat:
Das Zweite ist sicher einfach, in Delphi war eine solche struktur möglich:

Es gibt keine Properties in C++. Der übliche Weg ist Get- und Set-Methoden anzubieten.

Code:
  1. class Klasse {
  2. public:
  3.     int GetZahl() { return m_zahl; }
  4.     void SetZahl(int zahl1) { m_zahl1 = zahl; }
  5. private:
  6.     int m_zahl;
  7. };

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 20:07 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
LPCWSTR (Long Pointer Character Wide-STRing) ist eine Erfindung von Microsoft und das gibt es auch nur, wenn du für Windows entwickelst. Im Prinzip ist es einfach ein Zeiger, der auf ein Array von je 2 Byte großen Unicode-Zeichen verweißt. Wahrscheinlich ist es irgendwo so deklariert:
Code:
  1. #define LPCWSTR (unsigned short int*)

Das hat aber mit deinem Problem nichts zu tun. Dein Fehler liegt in Zeile 3. Du reservierst dort lokal Speicher, der automatisch wieder freigegeben wird, sobald die Funktion beendet wird. Der Zeiger, den du zurückgibst, verweist auf diesen Speicherberech, der sofort nach dem Ausführen der Funktion ungültig ist. Du müsstest den Speicher so reservieren:
Code:
  1. WCHAR* str = NULL;
  2. str = new WCHAR[256];
  3. if(str == NULL)
  4.   return NULL;
Nach dem Funktionsaufruf nicht vergessen, den Speicher mit delete[] wieder freizugeben.

Edit: Dieser Code ist allerdings nicht allzu schön, da er von einer festen Stringlänge von 255 Zeichen ausgeht. Sobald der String kürzer ist, kracht es. Besser macht man es so (Dabei muss der String Null-terminiert sein, was er normalerweise ist):
Code:
  1. LPCWSTR CharToLPCWSTR(char* s)
  2. {
  3.   int len = strlen(s);
  4.  
  5.   WCHAR* str = NULL;
  6.   str = new WCHAR[len+1];
  7.   if(str == NULL)
  8.     return NULL;
  9.   str[len] = '\0';
  10.  
  11.   MultiByteToWideChar(0,0,s,len,str,len);
  12.   LPCWSTR Returnstring=str;
  13.   return Returnstring;
  14. }


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 20:46 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
warum muss hier alles ein pointer sein? :(

bei c++ gibt es sowieso tausend typen und keine ist mit der anderen über einen einfachen weg kompatibel.

ich hab jetzt den code erstmal so übernommen wie er ist aber wie soll ich den speicher dann wieder löschen? bzw welchen?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 21:21 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
warum muss hier alles ein pointer sein? :(

Deswegen ja die/eine String-Klasse benutzen...die kümmert sich darum ;)

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 21:34 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
okay, also char* gegen std::string ersetzt und schon brauch ich eine umwandlung weniger, was mein problem aber leider noch nicht löst.

Code:
  1.     if(!(hWnd=CreateWindowEx(dwExStyle,
  2.         wc.lpszClassName,
  3.         ToLPCWSTR(title),
  4.         WS_CLIPSIBLINGS|WS_CLIPCHILDREN|dwStyle,
  5.         0,0,
  6.         WindowRect.right-WindowRect.left,
  7.         WindowRect.bottom-WindowRect.top,
  8.         NULL,
  9.         NULL,
  10.         hInstance,
  11.         NULL)))
  12.     {
  13.         MessageBox(NULL, L"Fenster konnte nicht erstellt werden.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  14.         KillGLWindow();
  15.         return false;
  16.     }


in dieser funktion (der ersten) funktioniert etwas nicht, ich bekomme keine compilerfehler aber er sagt, dass das Fenster nicht erstellt werden kann.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 21:45 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
Edit: Leider warst du schneller, trotzdem zum Verständnis des Posts davor:

Dropye hat geschrieben:
ich hab jetzt den code erstmal so übernommen wie er ist aber wie soll ich den speicher dann wieder löschen? bzw welchen?

Zu jeden new gehört immer ein delete und zu jedem new [] ein delete[]. Also nehmen wir an, du benutzt die Funktion aus meinem letzten Post:
Code:
  1. char* pAnsiStr = "ANSI braucht nur ein Byte pro Zeichen";
  2. LPCWSTR pUnicodeStr = CharToLPCWSTR(pAnsiStr);
  3. // irgendwas mit pUnicodeStr tun
  4. delete[] pUnicodeStr;
  5. pUnicodeStr = NULL; // Diese Zeile ist nicht zwingend noetig, beugt aber Fehlern vor

Der Speicher, auf den pUnicodeStr zeigt, wird in der Funktion CharToLPCWSTR reserviert (mit new []). Dieser wird erst dann wieder freigegeben, wenn du delete[] pUnicodeStr; aufrufst.

Coolcat hat aber Recht, normalerweise arbeitet man meistens nicht mit solchen Basistypen, sondern mit Klassen, die einem einiges an Arbeit abnehmen (Ist ja in Delphi nicht anders). Insbesondere von solchen Herstellerspezifischen Typen wie LPCWSTR würde ich die Finger lassen, weil es nicht nur scheußlich aussieht, sondern auch nicht portabel ist. Für das Verstehen von Pointern kann man aber eigentlich nichts besseres tun, als ein wenig "Handarbeit" anzulegen (also nicht alles von fertigen Klassen machen lassen).


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 21:51 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
Zu deinem letzten Post:
Diese if-Konstruktion sieht übel aus, ich weiß nicht, ob das überhaupt zulässig ist im C++-Standard. Probier mal das hier:
Code:
  1. hWnd = CreateWindowEx(/*hier die ganzen Parameter rein*/);
  2. if(hWnd == NULL)
  3. {
  4. //  MessageBox...
  5. }


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 21:53 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
wenn ich es nicht müsste würde ich es nicht nutzen aber es gibt nunmal keine mir bekannt alternative zu "CreateWindowEx" welche mir ja mein benötigtes Fenster erstellt damit ich was sehe und die will nunmal einen parameter in dieser form


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 22:03 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
Ich verstehe leider deinen letzten Post nicht. Vielleicht wunderst du dich, dass ich in abgekürzter Form geschrieben habe, mit den Kommentarzeichen /* */ und // ?
So war das gemeint:
Code:
  1. hWnd = CreateWindowEx(dwExStyle,
  2. wc.lpszClassName,
  3. ToLPCWSTR(title),
  4. WS_CLIPSIBLINGS|WS_CLIPCHILDREN|dwStyle,
  5. 0, 0,
  6. WindowRect.right-WindowRect.left,
  7. WindowRect.bottom-WindowRect.top,
  8. NULL,
  9. NULL,
  10. hInstance,
  11. NULL);
  12. if(hWnd == NULL)
  13. {
  14.   MessageBox(NULL, L"Fenster konnte nicht erstellt werden.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  15.   KillGLWindow();
  16.   return false;
  17. }


*Über die Forensoftware ärger, die ständig ein "  " in den zitierten Text einfügt :(*


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Nov 29, 2011 23:18 
Offline
DGL Member

Registriert: Di Sep 07, 2010 14:28
Beiträge: 34
Wohnort: Frankfurt
Programmiersprache: C++,C#,VB(,Delphi)
Hallo

zeig mal bitte, wie du deine WNDCLASSEX initzialiesierst, weil dass was du da machst so schon mal richtig aussieht
(na ja fast).

Du benutzt die Funktion ToLPCWSTR falsch. Es wird zwar funktioneren,
du brauchst ja aber den Pointer auf den Speicherbereich, denn du in der Funktion allokierst, damit du ihn auch wieder frei geben kannst, denn sonst geistert dir das die ganze Programmlaufzeit durch die Gegend und du kannst bei einem größeren Programm den Speicher komplett damit zumüllen, bis gar nichts mehr geht.

Edit. Fällt mir erst jetzt auf, was machst du mit dem WindowRect(Mit was hast du denn gefüllt)?

Jonathan

_________________
Das mit dem Dx tut mir leid.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Nov 30, 2011 10:03 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Dez 03, 2008 12:01
Beiträge: 167
Wohnort: /country/germany
Programmiersprache: C++ / FreeBASIC
Leute, macht euch doch das Leben nicht so schwer ;)
Code:
  1. #include <string>
  2. // ...
  3. std::string title = "Titel des Fensters";
  4. if(!(hWnd=CreateWindowEx(dwExStyle,
  5.     wc.lpszClassName,
  6.     title.c_str(),
  7.     WS_CLIPSIBLINGS|WS_CLIPCHILDREN|dwStyle,
  8.     0,0,
  9.     WindowRect.right-WindowRect.left,
  10.     WindowRect.bottom-WindowRect.top,
  11.     NULL,
  12.     NULL,
  13.     hInstance,
  14.     NULL)))
  15. {
  16.     MessageBox(NULL, L"Fenster konnte nicht erstellt werden.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  17.     KillGLWindow();
  18.     return false;
  19. }

Und das Problem ist gegessen.

_________________
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst -- Steve Wozniak


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Nov 30, 2011 11:07 
Offline
DGL Member
Benutzeravatar

Registriert: So Sep 26, 2010 12:54
Beiträge: 238
Wohnort: wieder in Berlin
Programmiersprache: Englisch
statt T"blabla" oder L"blabla" oder "blabla" kannst/solltest du das TEXT makro benutzen... TEXT("blabla") ... so ein L und/oder T oder S überliest man schnell an der Stelle....


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Nov 30, 2011 13:03 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Dropye hat geschrieben:
warum muss hier alles ein pointer sein? :(


Der Fluch der Objektorientierten Programmiersprachen ;) In Delphi sind das genauso alles Zeiger, wie in Java auch. Dort siehst du das nur nicht an der Syntax.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Nov 30, 2011 17:49 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
okay

Ich nutze keine WNDCLASSEX sondern nur eine WNDCLASS

Code:
  1.  
  2. WNDCLASS wc;
  3.  
  4.     wc.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  5.     wc.cbClsExtra=0;
  6.     wc.cbWndExtra=0;
  7.     wc.hInstance=hInstance;
  8.     wc.hIcon=LoadIcon(NULL, IDI_WINLOGO);
  9.     wc.hCursor=LoadCursor(NULL, IDC_ARROW);
  10.     wc.hbrBackground=NULL;
  11.     wc.lpszMenuName=NULL;
  12.     wc.lpszClassName=TEXT("OpenGL");
  13.  


die abfrage hab ich schonmal so verwendet das müsste eigentlich gehen aber ich werde es probieren

€: die geänderte abfrage bringt das selbe ergebniss, ich habe mir überlegt das die ausgabe des debuggers noch von interesse ist weil ihr da mal die genannten Access Violations seht.

Code:
  1.  
  2. Eine Ausnahme (erste Chance) bei 0xcccccccc in test.exe: 0xC0000005: Access violation.
  3. Eine Ausnahme (erste Chance) bei 0xcccccccc in test.exe: 0xC0000005: Access violation.
  4. Eine Ausnahme (erste Chance) bei 0xcccccccc in test.exe: 0xC0000005: Access violation.
  5. Der Thread 'Win32-Thread' (0x1174) hat mit Code 1964544 (0x1dfa00) geendet.
  6. Das Programm "[4456] test.exe: Systemeigen" wurde mit Code 1964544 (0x1dfa00) beendet.
  7.  


€: ach ja und darkinsanity dein vorschlag geht leider nicht
Code:
  1. error C2664: 'CreateWindowExW': Konvertierung des Parameters 3 von 'const char *' in 'LPCWSTR' nicht möglich


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 16 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.011s | 14 Queries | GZIP : On ]