Diverse Fragen bzgl Win32 API - VS2011



  • Hallo!
    Ich versuche mich gerade an einem Win32 Unicode (WCHAR) Projekt und habe neben ein paar Grundfragen auch das eine oder andere Problem, wo ich mich hiermit schon jetzt für Hilfe bedanken möchte.

    1. Welcher Code ist richtig?
    Im Netz finde ich diverse Ansätze wie man ein Win32-Fenster Projekt programmiert. Leider bin ich daher etwas irritiert, welcher Weg denn nun richtig bzw der bessere ist oder nicht.

    MSG	msg;
    //	ZeroMemory(&msg, sizeof(MSG));
    
    	while( GetMessage( &msg, NULL, 0, 0 ))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage( &msg );
    	}
    
    	return msg.wParam;
    

    Das ist die Variante, die ich derzeit nutze. Einige Leute benutzen ZeroMemory() und andere nicht. Auch schreiben einige Leute

    while( GetMessage( &msg, NULL, 0, 0 ))
    

    und andere

    while( GetMessage( &msg, NULL, 0, 0 ) > 0)
    

    . Ebenso schreiben einige

    return msg.wParam;
    

    und andere einfach

    return 0;
    

    . Was ist nun dir richtige bzw saubere Lösung?

    2. Prüfen von RegisterClass und hWnd?
    Ist es notwendig oder macht es Sinn, RegisterClassEx() und hWnd von CreateWindowEx() auf ==NULL zu überprüfen und dann mit "return 0" oder evtl. mit vorheriger MessageBox() zu beenden? In vielen Sources wird dieses gar nicht überprüft, daher die Frage, ob man das machen sollte oder nicht.

    3. Loop mit mehr als ein Fenster?
    Mein Programm (ein Fenster) läuft soweit und alle Buttons usw werden angezeigt. Leider bin ich bisher nicht wirklich fündig geworden, wie ich den MessageLoop aufbauen muss, damit ich auch mehr als ein Fenster gleichzeitig anzeigen und auswerten kann.

    4. Array mit WCHAR Strings erstellen:
    Leider habe ich es noch nicht herausgefunden, wie ich ein WCHAR Array mit Strings füllen kann. Compiler zeigt immer Fehler an. Habe schon einiges versucht aber es klappt nicht.

    WCHAR Buttons_Text[10]    = {TEXT("String 1"),TEXT("String 2"),TEXT("String 3"),TEXT("String 4"))};
    

    5. Zwei WCHAR Strings zu einem verbinden.
    Zwei WCHAR Strings mittels "newString = String1 + String2;" geht leider nicht.



  • va!n schrieb:

    1. Welcher Code ist richtig?

    Siehe z.B hier unter "Return Value" oder hier 😉

    va!n schrieb:

    2. Prüfen von RegisterClass und hWnd?
    Ist es notwendig oder macht es Sinn, RegisterClassEx() und hWnd von CreateWindowEx() auf ==NULL zu überprüfen und dann mit "return 0" oder evtl. mit vorheriger MessageBox() zu beenden?

    Fehlerbehandlung ist sicherlich sinnvoll, auch wenn sie oft ignoriert wird.

    va!n schrieb:

    3. Loop mit mehr als ein Fenster?
    Mein Programm (ein Fenster) läuft soweit und alle Buttons usw werden angezeigt. Leider bin ich bisher nicht wirklich fündig geworden, wie ich den MessageLoop aufbauen muss, damit ich auch mehr als ein Fenster gleichzeitig anzeigen und auswerten kann.

    Gleich wie sonst. Wenn du nicht gerade bei GetMessage() explizit nur ein bestimmtes Fenster oder irgendeine Filterung angegeben hast, dann behandelt deine Schleife alle Messages aller Fenster die in deinem Thread erzeugt wurden.

    va!n schrieb:

    4. Array mit WCHAR Strings erstellen:
    Leider habe ich es noch nicht herausgefunden, wie ich ein WCHAR Array mit Strings füllen kann. Compiler zeigt immer Fehler an. Habe schon einiges versucht aber es klappt nicht.

    WCHAR MetroButtons_Text[10]    = {TEXT("String 1"),TEXT("String 2"),TEXT("String 3"),TEXT("String 4"))};
    

    WCHAR ist nur ein einzelnes Zeichen und kein String. Wenn du explizit mit WCHAR arbeitest, dann würde ich überhaupt dazu raten, direkt die entsprechenden WinAPI Funktionen aufzurufen, also die Varianten deren Namen auf *W enden, wie z.B. CreateWindowExW(), RegisterClassExW() mit WNDCLASSEXW usw. In dem Fall verwend auch nicht TEXT(), sondern einfach direkt Wide String Literale, also z.B. L"blub" .

    va!n schrieb:

    5. Zwei WCHAR Strings zu einem verbinden.
    Zwei WCHAR Strings mittels "newString = String1 + String2;" geht leider nicht.

    Wie gesagt, WCHAR ist kein String, sondern nur ein Zeichen. Du arbeitest hier mit stinknormalen WCHAR Arrays, für die gibts natürlich keinen operator +.
    Du kannst aber z.B. std::wstring bzw. std::basic_string<WCHAR> verwenden.



  • @dot:
    Vielen Dank für deine Antworten!

    zu 1. Mein Source ist nun wie auf der MSDN Seite aufgebaut! Danke!

    zu 2. Habe erstmal nur "if (!hWNd) return FLASE;" eingebaut.

    zu 3. Hier werde ich mal probieren müssen, ob und wie ich das hinbekomme... Wenn ich dich richtig verstanden habe, dann bei GetMessage() beim zweiten Parameter kein HWnd des Fensters, sondern einfach NULL schreiben, dann sollte das irgendwie möglich sein, ja?

    zu 4. und 5. Der Compiler scheint automatisch alle API Befehle auf der Endung W umzustellen. Habe jetzt meine Text auf Wide String Literale, also z.B. L"blub" umgestellt. (Kann mir evtl. jemand kurz den Unterschied zwischen TEXT und L nennen? Weil beide scheinen zu funktionieren, ohne dass ich eine Änderung merke. Zumindest ist die L Variante viel schneller und einfacher zu schreiben 😉

    Kann mir evtl. jemand zeigen, wie die Codezeile bei Punkt 4 aussehen muss, um WCHAR Strings in einem entsprechendem array als Unicode zu speichern?

    Bzgl Strings verbinden muss ich mir auch nochmal genauer anschauen.

    Vielen Dank!



  • va!n schrieb:

    zu 3. Hier werde ich mal probieren müssen, ob und wie ich das hinbekomme... Wenn ich dich richtig verstanden habe, dann bei GetMessage() beim zweiten Parameter kein HWnd des Fensters, sondern einfach NULL schreiben, dann sollte das irgendwie möglich sein, ja?

    ja

    va!n schrieb:

    zu 4. und 5. Der Compiler scheint automatisch alle API Befehle auf der Endung W umzustellen.

    Ja, weil dein Projekt auf Unicode steht. Die "Funktionen" ohne Endung sind einfach nur Makros, die in etwa so aussehen:

    #ifdef UNICODE
    #define CreateWindowEx CreateWindowExW
    #else
    #define CreateWindowEx CreateWindowExA
    #endif
    

    Wenn du mit den "Funktionen" ohne Endung arbeiten willst, dann solltest du nicht direkt WCHAR, sondern besser TCHAR und TEXT() verwenden.
    Ich würde dir aber einfach zu WCHAR und den Funktionen mit der *W Endung raten.

    va!n schrieb:

    Habe jetzt meine Text auf Wide String Literale, also z.B. L"blub" umgestellt. (Kann mir evtl. jemand kurz den Unterschied zwischen TEXT und L nennen?

    Ganz einfach:

    #ifdef UNICODE
    #define TEXT(a) L##a
    #else
    #define TEXT(a) a
    #endif
    

    Sowie

    #ifdef UNICODE
    typedef WCHAR TCHAR;
    #else
    typedef char TCHAR
    #endif
    

    Um vielleicht endgültig Ordnung in den ganzen Kram zu bringen, hier zusammengefasst was die Idee dahinter ist:
    Ein CHAR ist ein normales 8 Bit ANSI Zeichen, während WCHAR ein 16 Bit Unicode Zeichen ist. Prinzipiell gibt es in der WinAPI von den ganzen entsprechenden Funktionen nun immer zwei Varianten: Eine die auf *W endet und Unicode Strings nimmt und eine die auf *A endet und einfache ANSI Strings nimmt. Die "Funktion" (genaugenommen ist es leider ein Makro) ohne Endung leitet einfach, je nachdem ob UNICODE definiert ist oder nicht, zur entsprechenden *W oder *A Funktion weiter.
    Damit du nun Code schreiben kannst der mit und ohne UNICODE kompiliert, gibt es TCHAR. TCHAR ist wieder einfach je nachdem ob UNICODE definiert ist oder nicht entweder ein WCHAR oder ein CHAR. Das TEXT() Makro erlaubt es dir, entsprechende Stringliterale zu definieren (wenn UNICODE definiert ist, macht es einfach ein L vorne hin und sonst nicht).

    Damit ergeben sich also drei sinnvolle Möglichkeiten:

    1. Du verwendest durchgehend immer CHAR und die *A Varianten.
    2. Du verwendest durchgehend immer WCHAR und die *W Varianten.
    3. Du verwendest durchgehend immer TCHAR, TEXT() und die Varianten ohne Endung. Dein Code lässt sich dann wahlweise für ANSI oder für UNICODE kompilieren.

    Ich würde zu Variante 2) oder 3) raten. Da ich heutzutage keinen besonderen Grund mehr seh, überhaupt noch etwas anderes als Unicode zu unterstützen, würde ich mich wohl einfach für Variante 2) entscheiden und durchgehend direkt alles mit Unicode machen. Da Windows intern mit Unicode arbeitet, sind die ganzen *A Funktionen unter der Haube auch nix anderes als Wrapper, die die übergebenen Strings in Unicode umwandeln und dann die entsprechende Unicode Funktion aufrufen und existieren wohl hauptsächlich nur noch aus Kompatibilitätsgründen.

    va!n schrieb:

    Kann mir evtl. jemand zeigen, wie die Codezeile bei Punkt 4 aussehen muss, um WCHAR Strings in einem entsprechendem array als Unicode zu speichern?

    Nachdem es nur Literale sind, würd ich es so machen:

    const WCHAR* MetroButtons_Text[] = { L"String 1", L"String 2", L"String 3", L"String 4" };
    

    va!n schrieb:

    Bzgl Strings verbinden muss ich mir auch nochmal genauer anschauen.

    typedef std::basic_string<WCHAR> string;
    
    // ...
    
    string newString = string(String1) + string(String1);
    


  • Ich hoffe ich stell meine Frage im richtigen Teil des Forums..Naja da hier diverse Fragen zum Thema API dissktutiert werden werd ich wohl richtig sein.
    Gibt es eine Funktion, die das Symbol an dem sich der Cursor befindet auslesen und zurückgeben kann?? Danke schonmal im Voraus 😉



  • Zero07 schrieb:

    Ich hoffe ich stell meine Frage im richtigen Teil des Forums..Naja da hier diverse Fragen zum Thema API dissktutiert werden werd ich wohl richtig sein.

    Im richtigen Teil des Forums schon, aber nicht im richtigen Thread.
    Mach bitte einen eigenen Thread auf wenn du etwas fragen willst - es sei denn es passt so richtig gut zum Thema eines aktuellen Threads, was hier aber sicherlich nicht gegeben ist.

    Danke schonmal im Voraus 😉

    Ich hasse es wenn Leute "Danke schonmal im Voraus" sagen/schreiben.


Anmelden zum Antworten