Winapi prog stürzt beim klicken auf nen Button ab.



  • Das hier ist der code.

    #include <windows.h>
    #include "main.h"
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <string>
    #include <cstdlib>
    #include <ctime>
    #include <time.h>
    using namespace std;
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "Vokabeltrainer 2.0";
    
    int WINAPI WinMain (HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
        HMENU menu;
    
            /* The Window structure */
        wincl.hInstance = hInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Ctach double-clicks */
        wincl.cbSize = sizeof(WNDCLASSEX);
    
        /* Use default icon and mousepointer */
        wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL; /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               WS_EX_CLIENTEDGE,                   /* Extended possibilites for variation */
               szClassName,         
               "Vokabeltrainer 2.0",       
               WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 
               CW_USEDEFAULT,       
               CW_USEDEFAULT,       
               600,                 
               400,                 
               HWND_DESKTOP,        
               NULL,                
               hInstance,       
               NULL                 
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
    
        menu = LoadMenu(hInstance, MAKEINTRESOURCE(ID_MENU));
        SetMenu(hwnd, menu);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HWND    hChild1; //Childwindow für ausgabe des Dateiinhalts
        static HWND hEdit1; // Editfeld zur eingabe der Englischen Vokabel
        static HWND hButtonEintragen; // Button zum eintragen in die datei
        const char szTextTest[] = " fgfg \r\n dsa daius \r\n nuinuin \r\n nuiniun \r\n esfghi uehf \r\n bzububbuzb \r\n nbuniiuni \r\n huihuhu \r\n nuiuniun \r\n bnzubuzbub \r\n niuniuin \r\n nbnnuniuni \r\n niuniuniounui \r\n uzb fgfg \r\n dsa daius \r\n nuinuin \r\n nuiniun \r\n esfghi uehf \r\n bzububbuzb \r\n fgfg \r\n dsa daius \r\n nuinuin \r\n nuiniun \r\n esfghi uehf \r\n bzububbuzb \r\n";
    
        switch (message)                  /* handle the messages */
        {
            case WM_COMMAND:
                {
                    switch (LOWORD(wParam)){
                    case IDM_NEWVOK :
                    case IDM_OPENVOK :
                    case IDM_SAVEVOK :    
                    case IDM_PRACTICEVOK :
                    case IDM_HELP :
                    {
                        MessageBox(hwnd, (LPSTR) "Funktion noch nicht eingebaut.", (LPSTR) szClassName, MB_ICONINFORMATION | MB_OK);
                        return 0;        
                    }
                    case IDM_ABOUT :
                        {
                            MessageBox(NULL, "Vokabeltrainer 2.0 \n Copyright bei Martin 'Arathorns Sohn' Alsfasser \n Dark Grass Software", "Über das Programm", MB_OK);
                            return 0;
                        }
                    case IDM_EXIT :
                        {
                          PostQuitMessage(0);
                          return 0;   
                        }
                 if (lParam == (LPARAM)hButtonEintragen)
                        {
                if (HIWORD(wParam) == BN_CLICKED){
                   MessageBox(NULL, "Funktion noch nicht eingebaut.",szClassName, MB_ICONINFORMATION | MB_OK);
                        }            
                 }    
                } 
                break;   
                }
    
                case WM_CTLCOLORSTATIC:
                {
                  switch (GetWindowLongPtr (reinterpret_cast<HWND> (lParam), GWL_ID))
                  {
                      case 1: //ID des Fensters
    
                      return (LRESULT) GetStockObject (WHITE_BRUSH);
    
                  }
                     return 0;  
                 }
    
            case WM_CREATE:
                {   
    
                    hEdit1 = CreateWindowEx(WS_EX_CLIENTEDGE,
                                            "edit",
                                            NULL,
                                            WS_CHILD | WS_VISIBLE | ES_READONLY | WS_VSCROLL | 
                                                  ES_AUTOVSCROLL | ES_MULTILINE,
                                            0, 0, 0, 0,
                                            hwnd,
                                            NULL,
                                            ((LPCREATESTRUCT) lParam) -> hInstance,
                                            NULL);
    
                    MoveWindow(hEdit1, 310, 10, 270, 330, TRUE);
                    SetWindowText(hEdit1, szTextTest);
    
                    hButtonEintragen = CreateWindow( "button",
                                                     "Eintragen",
                                                     WS_CHILD | WS_VISIBLE,
                                                     0, 0, 0, 0,
                                                     hwnd,
                                                     NULL,
                                                     ((LPCREATESTRUCT) lParam) -> hInstance,
                                                     NULL);
                    MoveWindow(hButtonEintragen, 70, 250, 160, 22, TRUE);
    
                    return 0;
                }    
    
            case WM_DESTROY:
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
    
        }
    
        return DefWindowProc (hwnd, message, wParam, lParam);
    }
    

    Die anordnung ist aber noch nicht perfekt, und auch z.b. das SetWindow text kommt noch woanders hin. das ist erstmal nur ein gui test( aja, invalidateRect und update window ham nicht gefunzt, daher sind sie wieder draußen, aber sie standen in der COLORSTATIC message.



  • Als erstes fällt mir auf, dass du dem EditControl keine ID vergibst, während du es anlegst - prüfst aber auf eine ID bei WM_CTLCOLORSTATIC.
    Ausserdem hast du ja schon ein statisches HWND auf das EditControl. Wieso benutzt du dieses nicht bei der Abfrage.
    InvalidateRect und UpdateWindow solltest du nicht bei Bearbeitung der Message aufrufen, dieses könnte ein dauerhaftes Neuzeichnen des Controls verursachen.

    A static control, or an edit control that is read-only or disabled, sends the WM_CTLCOLORSTATIC message to its parent window when the control is about to be drawn.

    Ein UpdateWindow(hwnd) solltest du allerdings noch in deiner WinMain vor der while-Schleife einfügen.

    Hier der (unvollständige) Code, wie es funktionieren sollte:

    static HBRUSH hbrush;
    
    case WM_CREATE:
    	// Brush für Hintergrundfarbe des EditControls anlegen
    	hbrush = CreateSolidBrush(RGB(255,255,255));
    
    	// weiterer Code
    
    	return 0;
    
    case WM_CTLCOLORSTATIC:
    	// prüfen, ob es sich um dein EditControl handelt
    	if((HWND)lParam == hEdit1)
    	{
    		// Hintergrundfarbe hinter Text setzen (gleiche Farbe, wie Hintergrundbrush)
    		SetBkColor((HDC)wParam, RGB(255, 255, 255));
    		// Optional, z.B. Textfarbe auf Blau
    		SetTextColor((HDC)wParam, RGB(0, 0, 255));
    		// Hintergrundbrush zurückgeben
    		return (LRESULT)hbrush;
    	}
    	return 0;
    
    case WM_DESTROY:
    	if(hbrush)
    		DeleteObject(hbrush);
    
    	// weiterer Code
    
    	return 0;
    

    Diese Lösung ist nicht mit GetStockObject (für Rückgabe des Brushhandles) realisiert, so kannst du jede beliebige Farbe einsetzen. Beachte jedoch, dass du bei CreateSolidBrush und SetBkColor die selben Farbwerte verwendest.



  • THX. hast mir echt geholfen. wenn das funzt, kann ich erstmal ne weile ohne probs arbeiten.( der Code für das prog liegt nämlich schon ne weile ferig auf meiner HDD( war erst ein konsolen proggie)).

    Edit: es funzt. ewnn ich das selbe auch mit anderen editfeldern machen will, muss ich nur das in der COLORSTATIC message ändern( brush soll gleich bleiben), oder?



  • Arathorns Sohn schrieb:

    Edit: es funzt. ewnn ich das selbe auch mit anderen editfeldern machen will, muss ich nur das in der COLORSTATIC message ändern( brush soll gleich bleiben), oder?

    Wenn es die EditControls diabled oder readonly sind, brauchst du nur die entsprechenden Handles abfragen und dementsprechend verarbeiten.
    Wenn die Controls allerdings enabled und nicht readonly sind, musst du das selbe bei WM_CTLCOLOREDIT machen.



  • Ok, das dachte ich mir aber schon.^^



  • Noch ne frage: wie komme ich an den rgb farbwert des aktuell verwendeeten hintergrundbrushes? ich hab nämlich das problem, dass der schrifthintergrund weiß ist( wo kann man den ändern? auch in der CRTCOLOREDIT?), der fensterhintergrund aber nicht.( benutzt die standart Hintergrundfarbe.) Und da die bei jedem User anders sein kann, hab ich keine ahnung, wie ich an den poassenden rgb wert komme. in der msdn hab ich auch schon geschaut, aber nix gefunden...



  • Wenn ich das richtig verstanden habe, möchtest du herausfinden, welche Farbe das System für ein Control standardmäßig verwendet.
    Siehe GetSysColor
    und GetSysColorBrush
    Das Setzen der Texthintergrundfarbe hatte ich bereits schon erwähnt



  • bevor ich meinen code vermurkse wollte ich mal fragen, wies den aussehen muss, im code. ich denke mal so:

    DWORD rgb;
    int iRed;
    int iGreen;
    int iBlue;
    
    rgb = DWORD WINAPI GetSysColor(5);
    iRed = GetRValue(rgb);
    iGreen = GetGValue(rgb);
    iBlue = GetBValue(rgb);
    

    Kann sein, dass der code totaler murks ist, aber ich arbeite noch nicht lange mit der winapi. das ganze muss dann in die WM_CREATE, oder?



  • Beim Arbeiten mit den 'Systemstandardfarben' geht das einfacher.
    Du brauchst hier kein HBRUSH in WM_CREATE zu erstellen. Damit auch das DestroyObject(hbrush) in WM_DESTROY.

    System color brushes are owned by the system and must not be destroyed.

    Ich würde bei GetSysColor auch kein Zahlenwert direkt einsetzen, sondern die entsprechende Definierung. so kannst du später besser nachvollziehen, um welche Farbe es sich handelt.

    case WM_CTLCOLORSTATIC: 
        if((HWND)lParam == hEdit1) 
        { 
            SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); 
            return (LRESULT)GetSysColorBrush(COLOR_WINDOW); 
        } 
        return 0;
    


  • kann ich das so auch für das hauptfenster verwenden, oder muss ich da was ändern? es geht mir nämlich um den texthintergrund im hauptfenster.



  • Schau dir dazu mal in der MSDN das Kapitel Drawing Text an. Bei vielen Funktionen befindet sich auch ein Link mit einem Beispiel.
    Außerdem wäre noch die Funktion SetBkMode interessant.



  • THX, ich schaus mir an.

    ps, gibts sowas wie die msdn nicht auf deutsch? Ich kann zwar englisch, aber deutsche texte sind einfach besser verständlich.



  • Es gibt Teile der MSDN in deutscher Sprache.
    Allerdings ist fast alles, was wirklich hilfreich ist, in englisch gehalten.

    Das ist das Problem in dieser Branche. Wenn man kein Englisch kann bzw. nicht bereit ist, sich durch englische Texte durchzubeißen, kommt man nicht wirklich weit. 🙄



  • ich bekomms einfach nicht hin. 😡

    Ich habs mit SetBkMode versucht, mit FillRect( und darin GetSysColorHbrush) es geht einfach nicht.... ( code hat sich nicht verändert)



  • Bevor wir aneinander vorbeireden - mit Hauptfenster meinst du das Fenster, welches du mit CreateWindowEx(WS_EX_CLIENTEDGE, szClassName, "Vokabeltrainer 2.0", ... erstellst?
    Hier muss du auf die Message WM_PAINT reagieren.

    case WM_PAINT:
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint(hwndDeinFenster, &ps);
      SetBkMode(hdc, TRANSPARENT);
      // Textausgabe via TextOut, DrawText, etc.
      EndPaint(hwndDeinFenster, &ps);
      return 0;
    

    Bei vielen Zeichenoperationen solltest du dir auch mal die Funktion CreateCompatibleDC ansehen.



  • THX, hat gefunst. ich konnte ja nicht ahnen, dass das nach Beginpaint eingefügt werden musste. ( war aus nem code in der msdn bei TextOut auch nicht ersichtlich...)

    Jetzt gehts ans innenleben.^^


Anmelden zum Antworten