Seltsames Problem bei C++ / WinAPI Programmen

Fragen zu allen anderen Programmiersprachen.
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Seltsames Problem bei C++ / WinAPI Programmen

Beitrag von Ynnus »

Hallöchen,

bei einigen meiner Programme stelle ich in letzter Zeit seltsames Verhalten fest. Dies tritt immer auf wenn man zu viele Bitmaps auf ein Fenster zeichnet. Ich hab zuerst vermutet, dass es daran liegen könnte, dass ich die DeviceContexts nicht freigegeben hatte nach jeder Zeichenoperation, aber der Fehler tritt immer noch auf trotz (afaik) korrekt freigegebener DCs.

Was genau ist denn der Fehler, werdet ihr euch fragen. Das kann ich auch nicht so recht beantworten. Nach einiger Zeit wird plötzlich das ganze Bild weiß und alle GUIs der laufenden Programme sind für kurze Zeit zerschossen ("invalid" und müssen neugezeichnet werden, etwa durch minimieren und erneut wiederherstellen) (Also keine schlimmen Fehler die Schäden hinterlassen könnten, nur eben seltsam und keinesfalls akzeptabel.)
Probiert es bitte mal aus, ob es bei euch genauso aussieht und vielleicht findet ja jemand hier den Fehler. Um diesen Fehler hervorzurufen müsst ihr im Programm wie in einem Zeichenprogramm mit der Maus in dem grauen Kästchen "malen". Also linke Maustaste gedrückt halten und innerhalb des Kästchens rumfahren. Dann zeichnen sich dort Bitmaps ab. Wenn ihr das lange genug macht tritt plötzlich dieser Fehler auf.
(EDIT: Es reicht sogar aus wenn man nur das Fenster eine Zeit lang hin und her verschiebt. Irgendwann flimmert die GUI und das Fenster wird seltsam zerstückelt).

Wie im Titel geschrieben verwende ich C++ mit der WinAPI. (DevC++ IDE v. 4.9.8.0)

Das Programm zum Download: http://derfeind2k.de/daten/project1.exe

Dies ist der Programmcode:

Code: Alles auswählen

/*  Programm: First Window
    Author:   Stefan Hof
    Date:     5. January 2004
*/

#include <windows.h>
#include <iostream.h>
#include <fstream.h>
#include <string.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE h_areainstance;
HWND hwnd, hwnd_maparea;

char cords[20][20];

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int showpref)
{
    static char AppName[] = "WinTextedit 1.0";
    MSG msg;
    WNDCLASS wndclass;

    wndclass.style = NULL;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) COLOR_MENU + 3;
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = AppName;
    
    if (RegisterClass(&wndclass) == false)
    {
        MessageBox(NULL, "Es ist ein Fehler aufgetreten. ", "Error! ", MB_ICONERROR);
        return 0;
    }
    
    hwnd = CreateWindow (AppName,
                         TEXT("WinProgramm 1.0"),
                         WS_OVERLAPPEDWINDOW,
                         100,
                         100,
                         500,
                         500,
                         NULL,
                         NULL,
                         hInstance,
                         NULL);

    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);
    
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    HDC hdc_winclient, hdc_bmp_mem;
    HBITMAP hbitmap;
    hbitmap = LoadBitmap(NULL, (char*)OBM_CHECK);
    int mouse_x, mouse_y;

    PAINTSTRUCT ps;

    switch(message)
    {
   
    case WM_CREATE:

        hwnd_maparea = CreateWindow("STATIC",
                                    "maparea",
                                    WS_CHILD | WS_VISIBLE | SS_GRAYFRAME,
                                    100, 30, 200, 200,
                                    hwnd,
                                    HMENU(0),
                                    h_areainstance,
                                    NULL);

        return 0;


    case WM_COMMAND:
        return 0;
        
    
    case WM_PAINT:
        hdc_winclient = BeginPaint(hwnd, &ps);
        hdc_bmp_mem = CreateCompatibleDC(hdc_winclient);
        SelectObject(hdc_bmp_mem, hbitmap);


        for(int x = 0; x<20; x++)
        {
            for(int y = 0; y<20; y++)
            {
                if (cords[x][y] == 1)
                {
                    BitBlt(hdc_winclient, (x * 10) +100, (y * 10)+30, 40, 40, hdc_bmp_mem, 0, 0, SRCCOPY);                    
                }
            }
        }
    
        EndPaint(hwnd, &ps);
        DeleteDC(hdc_bmp_mem);
        return 0;


    case WM_LBUTTONDOWN:
        mouse_x = LOWORD(lParam);
        mouse_y = HIWORD(lParam);

        if ((mouse_x >= 100) and (mouse_x <= 290) and (mouse_y >= 30) and (mouse_y <= 220))
        {
        
            cords[(mouse_x - 100) / 10][(mouse_y - 30) / 10] = 1;
            
            hdc_winclient = GetDC(hwnd);
            hdc_bmp_mem = CreateCompatibleDC(hdc_winclient);
            SelectObject(hdc_bmp_mem, hbitmap);
            BitBlt(hdc_winclient, (mouse_x / 10)*10, (mouse_y / 10) *10, 40, 40, hdc_bmp_mem, 0, 0, SRCCOPY);
            ReleaseDC(hwnd, hdc_winclient);
            DeleteDC(hdc_bmp_mem);
        }
        return 0;
        
        
    case WM_MOUSEMOVE:
        if (wParam == MK_LBUTTON)
        {
            mouse_x = LOWORD(lParam);
            mouse_y = HIWORD(lParam);
        
            if ((mouse_x >= 100) and (mouse_x <= 290) and (mouse_y >= 30) and (mouse_y <= 220))
            {
        
                cords[(mouse_x - 100) / 10][(mouse_y - 30) / 10] = 1;
                
                hdc_winclient = GetDC(hwnd);
                hdc_bmp_mem = CreateCompatibleDC(hdc_winclient);
                SelectObject(hdc_bmp_mem, hbitmap);
                BitBlt(hdc_winclient, (mouse_x / 10)*10, (mouse_y / 10) *10, 40, 40, hdc_bmp_mem, 0, 0, SRCCOPY);
                ReleaseDC(hwnd, hdc_winclient);
                DeleteDC(hdc_bmp_mem);

            }   
        }
        return 0;     

    case WM_DESTROY:
        DeleteObject(hbitmap);
        PostQuitMessage(0);    
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
Bitte überprüft das mal, ob der Fehler nur bei mir auftritt oder woran es liegen könnte.

mfg.

Sunny
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Kann den Fehler bei mir reproduzieren. Was mich irritiert: wenn ich mit Dev-C++ 4.9.9.1 den Code compilieren möchte findet er schon die iostream.h nicht (ist auch nicht im Paket enthalten). Leider hab ich keine Version 4.9.8.0 da... Ich schau mal, ob ich die noch finde.

Was sowohl bei der Version 4.9.9.1 als auch beim Lccwin32-Compiler angemeckert wird ist der WindowStyle, den Du auf NULL gesetzt hast. Gib hier mal CS_HREDRAW|CS_VREDRAW oder sowas an...

Was noch seltsam ist: Beim Start Deiner Project1.exe öffnet sich die Konsole! Hast Du nicht beim Compiler angegeben, dass Du eine Windows-Anwendung erstellen möchtest? Dennoch sollte dies nicht das Problem sein.
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

Jup, ich nutze die Console als Debugger. ;)

Ansonsten, ich habe den Fehler jetzt gefunden (bzw. in einem anderne Forum hat man mich darauf hingewiesen):
Dadurch dass der Befehl LoadBitmap() immer bei jeder Message ausgeführt wird, tritt dieser Fehler irgendwann auf. Warum weiß ich nicht genau, aber ab so vielleicht ein paar hundert oder tausend Messages = Laden des Bitmaps gibts irgendwann diesen Fehler.
Trotzdem Danke an diejenigen die sich da Gedanken gemacht haben.
Ansonsten, mit meiner Version lässt es sich gut compilieren, gibt zwar wegen dem Style = NULL; eine Warnung, aber keinen Fehler. Hast du die Datei in ein Projekt gepackt und dieses in den Optionen als Win32GUI geklariert? Dann sollte es keine Fehler geben, hoffe ich mal. Ansonsten mal <iostream> ohne das .h versucehen...

Das war's auch schon, mehr wollt ich nicht wissen. Ich melde mich bei weiteren Problemen, und die kommen bestimmt. ;)
MARTIN
Beiträge: 454
Registriert: 08.09.2004 14:03
Wohnort: Kiel

Beitrag von MARTIN »

Also vielleicht übersehe ich etwas aber ich sehe nichts in diesem Code wozu man iostream, fstream oder string bräuchte.
Amilo 1667|Suse Linux 10.1_64bit/WinXP |PB 4.00/3.94
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

IOstream für die Debug-Ausgabe (im vorliegenden Code gibts keine Debugausgaben, kommen aber ab und an mal dazu).
Fstream für Fileausgaben, kommen auch manchmal dazu und wieder raus.
String für lstrlen() Befehle, im vorliegenden Code rausgenommen da irrelevant für mein Problem.
Aber eigentlich kopiere ich mir den Window-Start meist von Programm zu Programm, da kann es schonmal sein dass ich ein paar zuviele Libs einbinde. :mrgreen:
Ist aber auch wurscht, eigentlich. Ist ja nur zu Testzwecken alles.
MARTIN
Beiträge: 454
Registriert: 08.09.2004 14:03
Wohnort: Kiel

Beitrag von MARTIN »

Das ist also nur Teil des Codes.Verstehe.
iotream.h fstream.h string.h sollte man eigentlich nicht verwenden weil veraltet ist.
Amilo 1667|Suse Linux 10.1_64bit/WinXP |PB 4.00/3.94
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

Was soll man denn anstelle dessen nehmen, wenn man die Console +cout und sowas verwenden will?
MARTIN
Beiträge: 454
Registriert: 08.09.2004 14:03
Wohnort: Kiel

Beitrag von MARTIN »

Code: Alles auswählen

#include <iostream>  <- das 

using namespace std;<- und das - stichwort namensräume

int main ( ....)
{
cout << .... usw.
Amilo 1667|Suse Linux 10.1_64bit/WinXP |PB 4.00/3.94
Antworten