Bitmap blitten (Screenshot) Fehler: Bitmap ist verzerrt



  • Hi,
    Ich hab ein Dialog, das ganz leer ist

    folgender Code:
    Allgemein:
    CDC screen;
    CBitmap bmp;

    In OnInitDialog()

    CRect rect;
    FindNotepadWnd()->GetWindowRect(&rect);
    /* das hier jetzt nur zu testzwecken */
    POINT x;
    x.x = 0;
    x.y = 0;
    POINT y;
    y.x = 1024;
    y.y = 768;
    rect.SetRect(x,y);
    /* das hier jetzt nur zu testzwecken - Ende*/
    
    bmp.DeleteObject();
    
    this->SetWindowPos( NULL, rect.TopLeft().x, rect.TopLeft().y, rect.Width(), rect.Height(), NULL );
    
    FindNotepadWnd()->SetForegroundWindow();
    CDC *dc = GetDC();
    
    bmp.CreateCompatibleBitmap(dc,rect.Width(),rect.Height());
    screen.SelectObject(&bmp);
    screen.BitBlt(0,0,rect.Width(),rect.Height(),dc,0,0,SRCCOPY);
    this->ReleaseDC(dc);
    
    CStatic *s = (CStatic*)GetDlgItem(IDC_SHOW);
    /* Nur zu Testzwecken*/
    if(s->SetBitmap(bmp)==NULL) MessageBox("fehler");
    /* Nur zu Testzwecken - Ende*/
    
    this->SetForegroundWindow();
    

    Es kommt die Fehlermeldung "fehler" und dann wird ein Bitmap auf dem Dialog gezeigt, dass ganz verzerrt und komisch aussieht.

    Was habe ich falsch gemacht 😕 😕
    Bitte helft mir.

    mfg. twisty



  • Hi,

    einen Screenshot mache ich folgender maßen:

    int dc2bitmap(HDC hdc, int width, int height, char *filename)
    {
        HDC hdc2;
        HBITMAP aBmp;
        BITMAPINFO bi;
        HGDIOBJ OldObj;
        void *dibvalues;
        HANDLE fileHandle;
    
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
            DWORD bytes_write;
        DWORD bytes_written;
    
        hdc2=CreateCompatibleDC(hdc);
    
        ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
        bmih.biSize=sizeof(BITMAPINFOHEADER);
          bmih.biHeight=height;
            bmih.biWidth=width;
            bmih.biPlanes=1;
            bmih.biBitCount=24;
        bmih.biCompression=BI_RGB;
        bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight;
            bmih.biXPelsPerMeter = 0;
            bmih.biYPelsPerMeter = 0;
            bmih.biClrImportant = 0;
        //bmih.biSizeImage=(3*bmih.biHeight*bmih.biWidth);
            //bmih.biSizeImage = 0;
    
        bi.bmiHeader=bmih;
    
        aBmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL)
        {
            OutputDebugString("CreateDIBSection failed!\n");
            return 0;
        }
    
        OldObj=SelectObject(hdc2,aBmp);
        BitBlt(hdc2,0,0,width,height,hdc,0,0,SRCCOPY);
    
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
        bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
            bmfh.bfType=0x4d42;
            bmfh.bfReserved1 = 0;
            bmfh.bfReserved2 = 0;
    
        fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,
                                                        CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
        if (fileHandle==INVALID_HANDLE_VALUE)
        {
            OutputDebugString("CreateFile failed!\n");
            return 0;
        }
    
            // Write the BITMAPFILEHEADER
            bytes_write=sizeof(BITMAPFILEHEADER);
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the BITMAPINFOHEADER
        bytes_write=sizeof(BITMAPINFOHEADER);
        if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the Color Index Array???
            bytes_write=bmih.biSizeImage;//3*bmih.biHeight*bmih.biWidth;
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
        CloseHandle(fileHandle);
    
        DeleteObject(SelectObject(hdc2,OldObj));
        DeleteDC(hdc2);
    
        return 1;
    }
    

    ok ist ein wenig mehr als nur der Screenshot.

    MFG
    Kai



  • Hi,
    deine Funktion speichert, wenn ich mich nicht irre, nur den Inhalt eines Device Context's in eine .bmp Datei.
    ich benutzt grad folgenden Code:

    In OnInitDialog von dem leeren Dialog

    CRect rect;
    GetNotepadWnd()->GetWindowRect(&rect);
    
    /* das hier jetzt nur zu testzwecken */
    GetNotepadWnd()->SetForegroundWindow();
    /* das hier jetzt nur zu testzwecken - Ende*/
    
    bmp.DeleteObject();
    this->SetWindowPos( NULL, rect.TopLeft().x, rect.TopLeft().y, rect.Width(), rect.Height(), NULL );
    /* Bis hier funktioniert alles Perfekt, der Dialog wird über Notepad plaziert */
    
    GetNotepadWnd()->SetForegroundWindow();
    CDC *dc = GetNotepadWnd()->GetDC();
    
    bmp.CreateCompatibleBitmap(dc,rect.Width(),rect.Height());
    screen.SelectObject(&bmp);
    screen.BitBlt(0,0,rect.Width(),rect.Height(),dc,0,0,SRCCOPY);
    
    GetNotepadWnd()->ReleaseDC(dc);
    
    CStatic *s = (CStatic*)GetDlgItem(IDC_SHOW);
    //if(s->SetBitmap(bmp)==NULL) MessageBox("ERRRRROR");
    s->SetBitmap(bmp);
    this->SetForegroundWindow();
    CDialog::OnInitDialog();
    return TRUE;
    

    Wenn ich das Programm starte und auf den Button klick, der das leere Dialogfeld aufruft, überdeckt mein Dialogfeld Notepad komplett. Notepad wird dann logischerweise in den Vordergrund geholt. Das sieht dann so aus:
    [http://mitglied.lycos.de/dave2m/notepad.gif](http://<a href=)">http://mitglied.lycos.de/dave2m/notepad.gif

    Doch der Screenshot ist ganz verzerrt:
    [http://mitglied.lycos.de/dave2m/screenshot.gif](http://<a href=)">http://mitglied.lycos.de/dave2m/screenshot.gif

    Wenn ich das Bild interpretiere, erinnert es mich eher an die Oberfläche von VC++, die extrem verzerrt ist. 😃

    Irgendwas muss ich in meinem Code übersehen haben 😕 😕 😕

    Bitte helft mir,

    Tausend Dank



  • Entschuldigt, dass ich so ungeduldig bin, aber hat keiner ne Lösung?
    😞 😞



  • Ich weis zwar nicht ob es etwas Hilft, aber du Selectest das bmp Objekt, und "lässt es nicht mehr los".

    Und warum versucht du es nicht mal mit DIB's ??

    MFG
    Kai



  • sorry, muss mich entschuldigen, ich hab bis jetzt noch nichts mit Bitmaps gemacht.
    Wie kann ich das Bitmap von dem DC wieder "loslösen"?
    Und eine sehr gute Frage: Was sind DIB's? 😕 😕 😕

    mfg. Twisty



  • also:

    DIB's sind Geräte unabhänige Bitmaps.

    int dc2bitmap(HDC hdc, int width, int height)
    {
        HDC hdc2;
        HBITMAP aBmp;
    
        hdc2=CreateCompatibleDC(hdc);
    
        // Erstellen eines DIB'S
        aBmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL)
        {
            OutputDebugString("CreateDIBSection failed!\n");
            return 0;
        }
    
        // DIB Selecten & Das vorher Selectete Objekt speichern
        OldObj=SelectObject(hdc2,aBmp);
        BitBlt(hdc2,0,0,width,height,hdc,0,0,SRCCOPY);
    
        // Hier mit dem DIB etwas machen
    
        // hier wird das alte objekt wieder selectet und das dib gelöscht
        DeleteObject(SelectObject(hdc2,OldObj));
        DeleteDC(hdc2);
    
        return 1;
    }
    

    Falls irgendwelche Parameter jetzt fehlen sollten, siehe oben in meinem ersten Post.

    MFG
    Kai

    [ Dieser Beitrag wurde am 18.12.2002 um 14:42 Uhr von KaiE editiert. ]



  • Danke euch, es klapt perfekt 🙂
    Noch 2 Fragen:
    1. wie "konvertiere" ich HBITMAP in ein CBitmap Objekt?
    2. Wenn ich mich nicht irre löschte deine Funktion das Bitmap wieder:
    DeleteObject(SelectObject(hdc2,OldObj));
    Ich möchte aber das Bitmap erst wieder löschen, wenn sich der Dialog schließt.
    Reicht folgende Methode:
    DeleteObject(SelectObject(hdc2,OldObj)) auskommentieren und bei OnClose
    DeleteObject(bmp); einfügen

    Ist dann alles wieder richtig aufgeräumt?

    danke euch alle 🙂 🙂



  • Hi,

    1. sollte mit "CBitmap::FromHandle()" gehen.

    2. nein, wenn du das so machst vergisst du dies Zeile:
    SelectObject(hdc2,OldObj);

    Wenn du dies Zeile noch einfügst, sollte es funktionieren.

    MFG
    Kai


Anmelden zum Antworten