bmp-Datei speichern funktioniert nicht

Die Erklärung für den Fehler 87 ist schnell gefunden. Die Funktion erwartet folgende Argumente
Code:
HBITMAP CreateCompatibleBitmap(
  HDC hdc,        // handle to DC
  int nWidth,     // width of bitmap, in pixels
  int nHeight     // height of bitmap, in pixels
);
Du schreibst aber
Code:
hbmp   = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
Damit hast du aber weder Breite noch Höhe des Rects.
Richtig müßte es heißen
Code:
hbmp   = CreateCompatibleBitmap(hdc, rect.Width(), rect.Height());
Versuch es erstmal damit - und dann sehen wir weiter.

Mfg

langer
 
Die Erklärung für den Fehler 87 ist schnell gefunden.
Ich denke der Part ist ok. Die Fenstergröße wird mit GetClientRect() geholt. Damit sind die Member "top" / "left" jeweils Null und "right" / "bottom" enthalten dann die korrekten Abmessungen des Fensterinhaltes. Außerdem wird eine RECT-Struktur gefüllt, die keine Member "Width()" / "Height()" enthält. Die gibt's nur bei CRect. Dein Vorschlag wird also nicht funktionieren.

Gruß
MCoder
 
Hallo, und erst mal vielen Dank für Eure Mühe – aber nun der Reihe nach. HDC hat den Wert CXX0017, während SaveWin und DDBToDIB durchlaufen werden. Später, in einer Zeile „return bResult;“ unter CCmdTarget ändert sich der Wert in CXX0030 = “Fehler: Ausdruck kann nicht ausgewertet werden“. Die Werte für rect.right, rect. bottom, hdc und hmemdc stehen im Word-Dokument BMP02. Das (+) bei hdc und hmemdc bedeutet, dass an diesen Stellen eine zweite Zeile mit dem Fehler CXX0030 hinzukommt.
Die Funktion von MCoder habe ich versucht mal schnell einzubinden, aber da waren noch ein paar Fehlermeldungen – das muss ich mir noch mal in Ruhe ansehen.
Mit (hdc, rect.Width(), rect.Height()); habe ich auch probiert, da kommt aber der Fehler: Width' / 'Height' : Ist kein Element von 'tagRECT'.

MfG bluejoky2
 

Anhänge

  • 26702attachment.doc
    21,5 KB · Aufrufe: 48
GetClientRect() in SaveWin liefert Murks zurück. Damit kann natürlich im weiteren Programmverlauf nix Gescheites mehr zustandekommen. Im Quellcode kann ich allerdings erstmal keinen Fehler erkennen.
Prüfe doch mal, ob das übergebene Fenster-Handle gültig ist:
C++:
if( !::IsWindow(hwnd) )
{
    // Fenster-Handle ist ungültig!!
}
Benutzt du die Funktionen eigentlich als Methoden innerhalb einer Fensterklasse? Dann solltest du die API-Funktionen lieber mit mit dem sog. Scope Resolution Operator "::" (siehe Codebeispiel) einleiten, um Huddeleien mit gleichnamigen Member-Funktionen der Fensterklasse aus dem Weg zu gehen.

Gruß
MCoder
 
Hallo MCoder, habe Deine Funktion mal bei mir eingebaut, diesmal als Memberfunktion in der Doc-Klasse. In der 1. Variante hatte ich die Funktionen im Ordner „Global“. Jetzt bekomme ich nach Zeile „HDC memDC ::CreateCompatibleDC(hdc);“ den Fehler 87. Zuvor werden nWidth und nHeight bei „int nWidth = rc.right - rc.left;“ bzw. „int nHeight = rc.bottom - rc.top;“ von -858993460 auf 0 gesetzt. Nach „WriteFile(hfile, &bfh, sizeof(bfh), &dwWritten, NULL);“ erhalte ich dann noch den Fehler 6 (Die Zugriffsnummer ist nicht definiert.). Habe das Ganze auch noch mal in der Klasse View probiert – an den Fehlermeldungen ändert sich aber nichts. Der Compiler meldet, wie auch bei der 1. Variante, keine Fehler. In der 1. Variante habe ich mir den Wert von hwnd mal angesehen – ist null – also kein gültiges Fenster-Handle. Auch bei Deinem Code bleibt hWnd = 0. Kann es daran liegen, wie ich die Funktion eingebaut habe? Mit dem Assistenten habe ich ein SDI-Gerüst erstellt, etwas Code (aus dem Netz) um eine BMP-Datei zu laden und dann mit Rechtsklick auf die Klasse eine Memberfunktion hinzugefügt und den Code in die Funktion kopiert. Dann den Button in der Toolbar erstellt und damit die Funktion aufgerufen. Oder kann das so nicht funktionieren?

MfG bluejoky2
 
Hallo bluejoky,

der von mir gepostete Code unter dem Kommentar "Bild aufnehmen" ist dafür vorgesehen, beliebige (Haupt)Programmfenster zu capturen und ist daher für dich wohl eher weniger geeignet. So wie ich das verstehe, willst du den Inhalt (Client-Bereich) eines Child-Fensters haben. Dafür kannst du ruhig deinen Code verwenden, was dann etwa so aussehen sollte, wenn man den in meinem Code verwendet:
C++:
/////////////////////////////////////////////////////////////////
// Bild aufnehmen

RECT rc;
::GetClientRect(hWnd, &rc);
int nWidth  = rc.right;
int nHeight = rc.bottom;

HDC     hdc    = ::GetDC(hWnd);
HDC     memDC  = ::CreateCompatibleDC(hdc);
HBITMAP hbm    = ::CreateCompatibleBitmap(hdc, nWidth, nHeight);
HBITMAP hbmOld = (HBITMAP)::SelectObject(memDC, hbm);

::BitBlt(memDC, 0, 0, nWidth,  nHeight, hdc, 0, 0, SRCCOPY);
Der Knackpunkt dürfte das ungültige Fensterhandle sein, dass du an die jeweilige Funktion (SaveWindow) übergibst. Wie ermitteltst du denn das?

Gruß
MCoder
 
Es ist genau wie Du schon vermutet hast. Der Inhalt des Client-Bereiches (Bilder) soll als BMP-Datei abgespeichert werden. Das Ganze soll auch erst mal nur als Test dienen, wie viele Bilder man in der Sekunde abspeichern kann. Doch wie Du schon schreibst ist der Knackpunkt das Handle auf das Fenster. Da habe ich noch keinen richtigen Plan, wie das aussehen muss. Kannst Du mir da auf die Sprünge helfen?

MfG bluejoky2
 
Wie rufst du denn die Funktion "SaveWin()" im Moment auf? Dort musst du ja das Fensterhandle übergeben.

Gruß
MCoder
 
Die Funktion "SafeWin()" rufe ich mittels Button “Store” wie folgt auf:

Code:
HWND hwnd;
 
void CBitmapDoc::OnButtonStore() 
{
         // TODO: Code für Befehlsbehandlungsroutine hier einfügen
 
         SaveWin(hwnd);
 
}

und bei Deinem Code mit:

Code:
HWND hWnd;
LPCTSTR lpszFile;
 
void CBitmapDoc::OnButtonStore() 
{
         // TODO: Code für Befehlsbehandlungsroutine hier einfügen
 
         SaveWindowBitmap(hWnd, lpszFile);
 
}


Wahrscheinlich habe ich das mit der Deklaration falsch verstanden (HWND hwnd; bzw. HWND hWnd; und LPCTSTR lpszFile. Die habe ich eingefügt, weil ich sonst vom Compiler die Fehlermeldung „error C2065: '…' : nichtdeklarierter Bezeichner“ bekomme.

MfG bluejoky2
 

Neue Beiträge

Zurück