Text aus Edit-Feld auslesen



  • Hallo, Forum-Gemeinde!

    Ich habe mal ein Problem, das sich nicht auf Fensterdarstellung beschränkt: Ich habe ein kleines Programm entworfen, um u. A. Text aus einem Edit-Feld im Hauptfenster anzuzeigen. Das Editfeld ist eine Resource mit 2 Buttons: "OK" und "Abbrechen". Bei "OK" soll der Text aus dem Feld in &TextPuffer zwischengelagert und nachher im Hauptfenster angezeigt werden.

    Dazu übergebe ich an die Unterfunktion bool CALLBACK TextProc(...) eine Referenz auf TextPuffer, aus der nachher in der WndProc der Text ausgelesen werden soll:

    #include <windows.h>
    #include <stdlib.h>
    #include <time.h>
    #include "04_texte_und_graphik.h"
    #define STRICT
    
    WORD wparam;
    HINSTANCE hInst;
    char TextPuffer[256];
    bool CALLBACK TextProc (HWND, UINT, WPARAM, LPARAM, char &TextPuffer);
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    const char szAppName[] = "Geräte-Context";
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
    //Das übliche, funktioniert auch;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    
    {
    
       PAINTSTRUCT ps;
       HDC hDC;
       int i, j, x, y, x2, y2;
    
       char szPuffer [] = "ein Teststring";
    
    	switch (msg)
       {
       	case WM_PAINT:
    
          	hDC = BeginPaint(hWnd, &ps);
             TextOut(hDC, 50, 50, szPuffer, sizeof(szPuffer)-1);
             switch (wparam)
             {
             	EndPaint(hWnd, &ps);
             return 0;
    
          case WM_DESTROY:
            			PostQuitMessage (0);	//Beendung der Anwendung
             		return 0;
          case WM_COMMAND:
          	switch (LOWORD(wParam))
             {
             	case IDM_WRITE:
                	DialogBox(hInst, MAKEINTRESOURCE(IDD_EDITTEXT),
                   			hWnd, (DLGPROC)TextProc);
                   break;
    
             	case IDM_QUIT:
          			DestroyWindow(hWnd);
                break;
    
                case WISCHEN:
                   wparam = LOWORD(wParam);
                   InvalidateRect(hWnd, 0, TRUE);
                	return 0;
             }
       }
       return DefWindowProc(hWnd, msg, wParam, lParam); 	//DefaultWindowProcedure, Standardbearbeitung.
    
    }
    ////////////////////////////////////////////////////////////////////////////////
    
    bool CALLBACK TextProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam, char &TextPuffer)
    {
    
       switch (msg)
       {
       	case WM_INITDIALOG:
        		SetDlgItemText(hDlg, IDC_TEXT, "Maximal 255 Zeichen");
             break;
    
          case WM_COMMAND:
          	switch (LOWORD(wParam))
             {
             	case IDOK:
                     GetDlgItemText(hDlg, IDC_TEXT, &TextPuffer, sizeof(TextPuffer)-1);
    
                case IDCANCEL:
                	EndDialog(hDlg, IDCANCEL);
                break;
          	}
          default:
          	return FALSE;
       }
       return TRUE;
    }
    

    Den Teil zur Textausgabe im Hauptfenster habe ich noch nicht fertig. Mein Problem ist: Die Zeile mit GetDlgItemText in TextProc() verursacht zur Laufzeit einen Zugriffsfehler (tritt nicht auf, wenn ich die Zeile auskommentiere). D. h. vermutlich, daß der Text nicht richtig in &TextPuffer abgelegt wird, oder daß die Referenz auf TextPuffer nicht richtig übergeben wird.

    Welchen Fehler mache ich hier? Muß ich den Speicher mit malloc erst anfordern, oder funktioniert das mit einer Referenzübernahme? Helft mir mal auf die Sprünge!

    Danke schon mal im Voraus.



  • Du darfst nicht einfach Parameter zu einer WndProc hinzufügen. Wie soll das auch funktioneren? Glaubst du, dieser Referenzparameter verweist auf magische Weise auf dein globales Array, nur weil er denselben Namen hat?



  • Du darfst nicht einfach Parameter zu einer WndProc hinzufügen. Wie soll das auch funktioneren?

    Ja, wie? In C kann man einer Unterfunktion beliebig viele Parameter übergeben, hauptsache, sie werden auf der anderen Seite auch übernommen. Daß die Zahl der Parameter bei einer WndProc festgelegt ist, wußte ich bisher nicht.

    Ok, jetzt weiß ich, wie es nicht geht. Aber wie geht es dann. Irgendwie muß ich ja den Text in die Haupt- WndProc bekommen.



  • Da du TextPuffer als globale Variable deklariert hast, musst du das doch eh nicht mehr in den Methodenkopf aufnehmen...

    Und lass bei GetDlgItemText vor TextPuffer mal das & weg - TextPuffer ist schon ein Pointer 😉



  • Elektronix schrieb:

    Ja, wie? In C kann man einer Unterfunktion beliebig viele Parameter übergeben, hauptsache, sie werden auf der anderen Seite auch übernommen.

    Es reicht nicht, dass sie übernommen werden. Sie müssen auch übergeben werden. Und das passiert in deinem Fall nicht. Windows ruft deine TextProc-Funktion auf, mit den Parametern, die jede Fensterprozedur bekommt. Dafür hat die ja eine ganz bestimmte Signatur.

    Du musstest doch bestimmt irgendwo den Funktionszeiger auf TextProc casten, oder? Das allein hätte dir schon zeigen müssen, dass da etwas nicht stimmt.

    Daß die Zahl der Parameter bei einer WndProc festgelegt ist, wußte ich bisher nicht.

    Nicht nur die Zahl, sondern auch die Typen und die Aufrufkonvention.

    Ok, jetzt weiß ich, wie es nicht geht. Aber wie geht es dann. Irgendwie muß ich ja den Text in die Haupt- WndProc bekommen.

    TextPuffer ist doch schon global. Wo ist das Problem?

    flenders schrieb:

    Und lass bei GetDlgItemText vor TextPuffer mal das & weg - TextPuffer ist schon ein Pointer 😉

    Nö. TextPuffer ist ein Array. Das & ist zwar nicht notwendig, aber auch nicht falsch.



  • MFK schrieb:

    Es reicht nicht, dass sie übernommen werden. Sie müssen auch übergeben werden. Und das passiert in deinem Fall nicht. Windows ruft deine TextProc-Funktion auf, mit den Parametern, die jede Fensterprozedur bekommt. Dafür hat die ja eine ganz bestimmte Signatur.

    Du musstest doch bestimmt irgendwo den Funktionszeiger auf TextProc casten, oder? Das allein hätte dir schon zeigen müssen, dass da etwas nicht stimmt.

    Ok, ist das hier denn richtiger?

    case IDM_WRITE:
    
       DialogBox(hInst, MAKEINTRESOURCE(IDD_EDITTEXT),
                               hWnd, (DLGPROC)TextProc(HWND, UINT, WPARAM, LPARAM, char &TextPuffer));
    

    Nicht nur die Zahl, sondern auch die Typen und die Aufrufkonvention.

    Also wie jetzt? 😕 Heißt das, daß ich gar keine zusätzlichen Parameter übergeben kann? Dann müßte ich das ja ganz anders anfangen.

    Flenders schrieb:

    Und lass bei GetDlgItemText vor TextPuffer mal das & weg - TextPuffer ist schon ein Pointer

    Ich persönlich finde es halt übersichtlicher, wenn eine Referenz auch in Unterfunktionen immer als solche gekennzeichnet ist und nicht mit lokalen Variablen verwechselt wird. Aber das ist natürlich Geschmacksache.



  • Elektronix schrieb:

    Ok, ist das hier denn richtiger?

    Nein, das ist komplett falsch. Da darf nur TextProc stehen, ohne irgendeine Parameterliste (das wäre syntaktisch falsch), und vor allem ohne den Cast auf DLGPROC.

    Also wie jetzt? 😕 Heißt das, daß ich gar keine zusätzlichen Parameter übergeben kann?

    Richtig. Wie soll das denn auch funktionieren? Du rufst die Funktion ja gar nicht selbst auf.

    Ich persönlich finde es halt übersichtlicher, wenn eine Referenz auch in Unterfunktionen immer als solche gekennzeichnet ist und nicht mit lokalen Variablen verwechselt wird. Aber das ist natürlich Geschmacksache.

    Das & kennzeichnet in diesem Fall keine Referenz, sondern ist der Adressoperator. Wenn es hier nicht um ein Array ginge, wäre das ein ziemlich großer Unterschied, nicht "Geschmackssache".



  • @MFK

    Da darf nur TextProc stehen, ohne irgendeine Parameterliste (das wäre syntaktisch falsch), und vor allem ohne den Cast auf DLGPROC.

    Hmmm, dann hätte doch der Kompiler meckern müssen (Borland C++ 5.05). Die Idee mit dem Zeiger stammt nicht von mir, sondern aus einem Tutorial. Da wird übrigens auch die DlgProc nicht extra aufgerufen, sondern zusammen mit der DialogBox:

    http://pronix.linuxdelta.de/C/win32/win32_5.shtml#3

    Ist das ein Unterschied zwischen C und C++? Kann eigentlich nicht sein, ich habe das Tut mit der gleichen IDE durchgeackert, hat problemlos funktioniert.



  • Elektronix schrieb:

    Hmmm, dann hätte doch der Kompiler meckern müssen (Borland C++ 5.05).

    Mit dem Cast auf DLGPROC hast du dem Compiler jegliche Möglichkeit der Fehlerprüfung genommen. Ein solcher Cast bedeutet immer: "Ich weiß es besser als der Compiler". Darum hält der brav den Mund.



  • Ahaaaaa! 👍
    Danke für den Hinweis. Werde es mal ausprobieren.

    Was ist mit meinen anderen Fragen?



  • Elektronix schrieb:

    Was ist mit meinen anderen Fragen?

    Welche meinst du?



  • Du hast geschrieben, ich müßte die TextProc extra aufrufen. In dem Tutorial, von dem ich das Prog abgeleitet habe, gibt es keinen gesonderten Aufruf. Der steht nur im Aufruf der DialogBox als Parameter. (Ich habe mein vorletztes Posting noch einmal überarbeitet, hat sich mit Deiner Antwort überschnitten).

    Wie also dann? Muß ich die Funktion nur dann gesondert aufrufen, wenn ich zusätzliche Parameter übergebe? Und wenn ja, wo? Dann würde ich sie ja zweimal aufrufen.



  • Elektronix schrieb:

    Du hast geschrieben, ich müßte die TextProc extra aufrufen.

    Nein. Ich habe nur geschrieben, dass du es nicht tust. Das bedeutet nicht, dass du es musst. Es ist sinnlos, diese Funktion aufzurufen.



  • Hier ist Quellcode, der zeigt wie man Text aus einer Textbox ließt und das ganze noch halbwegs in ordentlichen C++ OOP Style:
    http://turing.fh-landshut.de/~jamann/IMB/IMB.html



  • MFK schrieb:

    Nein. Ich habe nur geschrieben, dass du es nicht tust. Das bedeutet nicht, dass du es musst. Es ist sinnlos, diese Funktion aufzurufen.

    Also, irgendwie hat mir das jetzt nicht wirklich geholfen.

    @Vertexwahn

    Danke, nett von dir. Aber hast Du das Ganze nicht auch für WinAPI? Ist ja auch das entsprechende Fourum.



  • Danke, nett von dir. Aber hast Du das Ganze nicht auch für WinAPI?

    das ist WinAPI! 😉



  • @Vertexwahn

    Sorry, hab nicht richtig geguckt in der Eile. Danke für den Link, den werde ich mir genauer zu Gemüte führen.

    Bis dahin derweil...


Log in to reply