Bild in Fenster



  • @CodeFinder

    Ich bemerke, daß Du sehr oft "reinterpret_cast" verwendest. Das scheint mir eine etwas unsichere Methode.

    Warum das? Ist das in dem Fall überhaupt nötig? Gibt es nicht auch eine andere Möglichkeit?



  • Elektronix schrieb:

    @CodeFinder

    Ich bemerke, daß Du sehr oft "reinterpret_cast" verwendest. Das scheint mir eine etwas unsichere Methode.

    Warum das? Ist das in dem Fall überhaupt nötig? Gibt es nicht auch eine andere Möglichkeit?

    Bei nem static_cast kackt mein Compiler^^.



  • Kannst Du mal sagen, was "reinterpret_cast" und "static_cast" macht? - Außer Verdauungsproblemen im Compiler 🤡 .



  • hi CodeFinder, vielen Dank für den Code.

    Beim Kompilieren gibt es bei mir immer Probleme. Kann es sein, dass dein Code C enthält? Ich wollte es in reinem C.
    Bei mir meckert er u.a. bei reinterpert_cast. Würde dein Beispiel gerne ausführen, so geht es aber leider noch nicht 😞

    Und dass das, was ich hier poste total falsch ist glaube ich nicht. Es sind bestimmt ein paar (Denk-)Fehler drin aber größtenteils hole ich mir die Beispiele aus Tutorien.

    Also, vielen Dank noch einmal, aber könnte ich dein Beispiel in C haben?

    Oder jemand vielleicht eine andere Lösung aufbauend auf meinem Beispiel?

    Grüße,
    molli



  • molli schrieb:

    ..., dass dein Code C enthält? ...

    ich meinte C++



  • Elektronix schrieb:

    Kannst Du mal sagen, was "reinterpret_cast" und "static_cast" macht? - Außer Verdauungsproblemen im Compiler 🤡 .

    Jo clör:

    static_cast
    static_cast can perform conversions between pointers to related classes, not only from the derived class to its base, but also from a base class to its derived. This ensures that at least the classes are compatible if the proper object is converted, but no safety check is performed during runtime to check if the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, the overhead of the type-safety checks of dynamic_cast is avoided.

    class CBase {};
    class CDerived: public CBase {};
    CBase * a = new CBase;
    CDerived * b = static_cast<CDerived*>(a);

    This would be valid, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.

    static_cast can also be used to perform any other non-pointer conversion that could also be performed implicitly, like for example standard conversion between fundamental types:

    double d=3.14159265;
    int i = static_cast<int>(d);

    Or any conversion between classes with explicit constructors or operator functions as described in "implicit conversions" above.

    reinterpret_cast
    **reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes.**The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.

    It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it, is granted to be able to be cast back to a valid pointer.

    The conversions that can be performed by reinterpret_cast but not by static_cast have no specific uses in C++ are low-level operations, whose interpretation results in code which is generally system-specific, and thus non-portable. For example:

    class A {};
    class B {};
    A * a = new A;
    B * b = reinterpret_cast<B*>(a);

    This is valid C++ code, although it does not make much sense, since now we have a pointer that points to an object of an incompatible class, and thus dereferencing it is unsafe.

    Kurz 💡 :
    Beispiel, static_cast<>():

    double dValue = 9.9;
    int iValue = static_cast<int>(dValue); // iValue ist gleich 9
    // --> hier würde aber auch eine implizite Typenumwandlung reichen.
    

    Beispiel, reinterpret_cast<>():

    void* pTransmitData = NULL;
    // Initialisierung von pTransmitData durch irgend eine gültige Speicheradresse,
    // die auf ein Objekt der Klasse CKlasse zeigt, zB durch eine CALLBACK-Funktion.
    CKlasse* pObject = reinterpret_cast<CKlasse*>(pTransmitData);
    


  • molli schrieb:

    Beim Kompilieren gibt es bei mir immer Probleme. Kann es sein, dass dein Code C enthält? Ich wollte es in reinem C.
    Bei mir meckert er u.a. bei reinterpert_cast. Würde dein Beispiel gerne ausführen, so geht es aber leider noch nicht 😞

    Hier ist der Code in C (stimmt da war C++ dabei, speziell die Typ-Casts):

    #include <windows.h>
    
    typedef enum
    {
       BMS_CAT,
       BMS_DOG
    } EBitmapStates /*, *PEBitmapStates*/ ;
    
    #define BTN_SHOW_CAT  (6001)
    #define BTN_SHOW_DOG  (6002)
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
       TCHAR szAppName[] = TEXT("EXAMPLE_CLASS");
       HWND         hWndMain;
       MSG          msg;
       WNDCLASSEX   wndclassex = {0};
    
       wndclassex.cbSize        = sizeof(WNDCLASSEX);
       wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
       wndclassex.lpfnWndProc   = WndProc;
       wndclassex.hInstance     = hInstance;
       wndclassex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       wndclassex.hCursor       = LoadCursor(NULL, IDC_ARROW);
       wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
       wndclassex.lpszClassName = szAppName;
       wndclassex.hIconSm       = wndclassex.hIcon;
    
       if(!RegisterClassEx(&wndclassex))
       {
          MessageBox(NULL, TEXT("RegisterClassEx fehlgeschlagen!"), szAppName, MB_ICONERROR);
          return (0);
       }
    
       hWndMain = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, // erweiterter Fensterstil
                      szAppName, // Name der Fensterklasse
                      TEXT ("Beispiel"), // Fenstertitel
                      WS_OVERLAPPEDWINDOW, // Fensterstil
                      CW_USEDEFAULT, // X-Position des Fensters                      
                      CW_USEDEFAULT, // Y-Position des Fensters      
                      CW_USEDEFAULT, // Fensterbreite                
                      CW_USEDEFAULT, // Fensterhöhe                
                      NULL, // übergeordnetes Fenster
                      NULL, // Menü          
                      hInstance, // Programm-Kopiezähler (Programm-ID)            
                      NULL); // zusätzliche Parameter
    
       ShowWindow(hWndMain, iCmdShow);
       UpdateWindow(hWndMain);
    
       while(GetMessage(&msg, NULL, 0, 0))
       {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
       return msg.wParam;
    }
    
    // Die Hauptnachrichtenschleife
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
    {
       static HBITMAP        hbmpCat,
                             hbmpDog;
       static EBitmapStates  bmState;
       static HWND           btnDog,
                             btnCat;
    
       switch(uiMessage)
       {
          case WM_CREATE:
              bmState = BMS_CAT;
              hbmpCat = LoadImage(NULL, TEXT("katze.bmp"), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_DEFAULTCOLOR | LR_LOADFROMFILE);
              hbmpDog = LoadImage(NULL, TEXT("hund.bmp"), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_DEFAULTCOLOR | LR_LOADFROMFILE);
              btnDog  = CreateWindow(TEXT("BUTTON"), TEXT("Hund anzeigen"),
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     10, 10, 120, 40, hWnd, (HMENU)BTN_SHOW_DOG,
                                     ((LPCREATESTRUCT)lParam)->hInstance, NULL);
              btnCat  = CreateWindow(TEXT("BUTTON"), TEXT("Katze anzeigen"),
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     10, 10, 120, 40, hWnd, (HMENU)BTN_SHOW_CAT,
                                     ((LPCREATESTRUCT)lParam)->hInstance, NULL);
              InvalidateRect(hWnd, NULL, TRUE);
              break;
    
          case WM_COMMAND:
              switch(LOWORD(wParam))
              {
                  case BTN_SHOW_DOG:
                      bmState = BMS_DOG;
                      InvalidateRect(hWnd, NULL, TRUE);
                      break;
                  case BTN_SHOW_CAT:
                      bmState = BMS_CAT;
                      InvalidateRect(hWnd, NULL, TRUE);
                      break;
                  // Weitere Command-Handler...
              }
              break;
    
          case WM_PAINT: {
              PAINTSTRUCT  psStruct;
              HDC          hdcMemory;
              HBITMAP      hbmpPrevBits;
              RECT         rcClient;
    
              GetClientRect(hWnd, &rcClient);
    
              BeginPaint(hWnd, &psStruct);
    
              hdcMemory = CreateCompatibleDC(psStruct.hdc);
              switch(bmState)
              {
                 case BMS_CAT:
                     hbmpPrevBits = (HBITMAP)SelectObject(hdcMemory, hbmpCat);
                     break;
                 case BMS_DOG:
                     hbmpPrevBits = (HBITMAP)SelectObject(hdcMemory, hbmpDog);
                     break;
              }
    
              BitBlt(psStruct.hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMemory, 0, 0, SRCCOPY);
    
              EndPaint(hWnd, &psStruct);
              SelectObject(hdcMemory, hbmpPrevBits);
              DeleteDC(hdcMemory);
              } break;
    
          case WM_DESTROY:
              DeleteObject(hbmpCat);
              DeleteObject(hbmpDog);
              PostQuitMessage(0);
              break;
    
          default:
              return (DefWindowProc(hWnd, uiMessage, wParam, lParam));
       }
    
       return (0L);
    }
    

    molli schrieb:

    Und dass das, was ich hier poste total falsch ist glaube ich nicht. Es sind bestimmt ein paar (Denk-)Fehler drin aber größtenteils hole ich mir die Beispiele aus Tutorien.

    Naja 'total falsch' ist relativ, aber dein GDI-Cleanup war zum bspw. n bissl kryptisch^^ ...egal!



  • @CodeFinder: vielen Dank an die Umwandlung.

    Ich glaube es muss in Zeile 71 heißen: switch(uiMessage)
    und die Deklarationen in Case WM_PAINT mag er auch nicht (parse error), die habe ich jetzt einfach vor den switch gestellt.
    Die ganze Sache klappt jetzt.

    Vielen Dank an alle, die daran beteiligt waren (besonders CodeFinder und Elektronix)

    Grüße,
    molli



  • molli schrieb:

    Ich glaube es muss in Zeile 71 heißen: switch(uiMessage)
    und die Deklarationen in Case WM_PAINT mag er auch nicht (parse error), die habe ich jetzt einfach vor den switch gestellt.
    Die ganze Sache klappt jetzt.

    Jo switch(uiMessage)...habs korrigiert 😉 ...Vertipper 🤡 .
    Dann zum Fehler bei WM_PAINT:
    Das kannste so machen, also die Vars vor das switch ziehen. So wie ich nachträglich korrigiert habe,
    ist es aber noch besser, da die Vars immer nur dann angelegt werden, wenn sie benötigt werden.
    Gucks dir einfach nochmal an.

    molli schrieb:

    Vielen Dank an alle, die daran beteiligt waren (besonders CodeFinder und Elektronix)

    Jo np 😉 👍 .



  • Dor nech för. 🕶



  • Geht so etwas auch mit MSVC++ 6.0, purem C und einem Bild im PNG-Format? 🙂


Anmelden zum Antworten