Textfolge im Hauptfenster ausgeben (doofe noob frage /Kopfeinzieh/)



  • oh man bin blutiger Anfänger und ich glaube einach überarbeitet ...

    Erstmal danke für den Buchtip ist mir vorher in der Büchersektion gar nicht aufgefallen habe ich mir gleich erstmal bestellt. 🙂

    dann zu der Nicht modalen dialog Box ...

    Bisher habe ich meine Dialogboxen so erzeugt.

    DialogBox( KIT_instance, MAKEINTRESOURCE( IDD_ONLINE_AUSGABE), KIT_window, KIT_Online_dialog);
    

    + die entsprechende Callback funktion.

    Aber die ist dann ja laut doku Modal... 😉

    daher nutze ich jetzt die von dir Vorgeschlagene Funktion. (Hätte ich auch selber sehen können ärger)

    HWND test= CreateDialog( KIT_instance, MAKEINTRESOURCE( IDD_ONLINE_DATEN), KIT_window, KIT_Online_dialog);	
    		if (test ==0)
    			MessageBox(KIT_window, "ONLINE DIALOGBOX FEHLER ","Fehler", MB_OK);
    

    Ich weiß ist nicht die beste Methode festzustellen welcher fehler vorliegt..
    hab nur noch nicht ganz rausbekommen wie das mit GetLastError Funktioniert 🤡
    Auf jedenfall wird der Dialog nicht aufgerufen.
    Werd da wohl morgen weiter machen da ich heute nix mehr in meinen Kopf bekomme

    Wenn noch jemand einen Tip hat oder mir die Funktion für das Printen eines Textes als string in das Hauptfenster an einer beliebeigen XY Pos verraten kann wäre ich dankbar

    MFG Wastman



  • TextOut / DrawText in WM_PAINT oder du erstellst dir an der Stelle ein Control und setzt dann per SetDlgItemText den Inhalt (finde ich eleganter)



  • äh, hallo! ich bin grad mit nem ähnlichen problem am start!
    ich programmiere schon ewig, aber mit der windows api beschäftige ich mich erst ernsthaft seit ner woche 😉 und mir kommt eins grad mega-unlogisch vor:

    hab das hier in der WM_PAINT:

    case WM_PAINT:
            {
                MessageBox(0, "WM_PAINT", /*Inhalt Dlg.-Box*/
                            "DebugMessage",/*Titelleiste*/
                            MB_OK | MB_ICONEXCLAMATION); /*OK-Button+!Bild*/
    
                hdc = BeginPaint(hwnd,&ps); // returns the device context to the
                                            // given window and marks the start of
                                            // the paint procedure
                LPSTR text = integerToString(counter);
                TextOut(hdc, 50, 80, text, sizeof(text));
                EndPaint(hwnd,&ps);         // end of painting
    
                return(0);                  // returns -  Message handled
    
            }
    

    wenn ich das programm jetzt ausführe passiert folgendes:
    erst erscheint zig-mal das popUp (ich sende nirgendwo selbst die MESSAGE) und dann erscheint jedesmal wenn ich das window resize der neue text (einfach ne zahl). (das popup ist NUR debug)

    schön und gut. ich hätte das aber gerne dauernd refresht!

    also hab ich mal son BeginPaint/TextOut/EndText im MainLoop eingebaut. es ändert sich dann NIX! es wird trotzdem nur bei resize refreshed.

    hab dann versucht jede runde ein SendMessage(main_window_handle,WM_PAINT,0,0); abzuschicken. ändert sich auch nix. es scheint mir, als würde das komplett ignoriert.

    Meine Fragen:

    1. Was mache ich falsch? Warum kann ich nicht refreshen wann ich will?
    2. Warum springt er mehrmals in WM_PAINT? Wozu so viele Messages bei start und resize? Würde nicht eine WM_PAINT reichen?

    Ich nutze Dev-Cpp!

    Danke von einem WindowsAPI-N00b 😞

    HILFE 😕

    ps.: dos war doch damals viel einfacher 😉



  • adsci schrieb:

    äh, hallo! ich bin grad mit nem ähnlichen problem am start!
    ich programmiere schon ewig, aber mit der windows api beschäftige ich mich erst ernsthaft seit ner woche 😉 und mir kommt eins grad mega-unlogisch vor:

    hab das hier in der WM_PAINT:

    case WM_PAINT:
            {
                MessageBox(0, "WM_PAINT", /*Inhalt Dlg.-Box*/
                            "DebugMessage",/*Titelleiste*/
                            MB_OK | MB_ICONEXCLAMATION); /*OK-Button+!Bild*/
    
                hdc = BeginPaint(hwnd,&ps); // returns the device context to the
                                            // given window and marks the start of
                                            // the paint procedure
                LPSTR text = integerToString(counter);
                TextOut(hdc, 50, 80, text, sizeof(text));
                EndPaint(hwnd,&ps);         // end of painting
                
                return(0);                  // returns -  Message handled
    
            }
    

    wenn ich das programm jetzt ausführe passiert folgendes:
    erst erscheint zig-mal das popUp (ich sende nirgendwo selbst die MESSAGE) und dann erscheint jedesmal wenn ich das window resize der neue text (einfach ne zahl). (das popup ist NUR debug)

    schön und gut. ich hätte das aber gerne dauernd refresht!

    also hab ich mal son BeginPaint/TextOut/EndText im MainLoop eingebaut. es ändert sich dann NIX! es wird trotzdem nur bei resize refreshed.

    hab dann versucht jede runde ein SendMessage(main_window_handle,WM_PAINT,0,0); abzuschicken. ändert sich auch nix. es scheint mir, als würde das komplett ignoriert.

    Meine Fragen:

    1. Was mache ich falsch? Warum kann ich nicht refreshen wann ich will?
    2. Warum springt er mehrmals in WM_PAINT? Wozu so viele Messages bei start und resize? Würde nicht eine WM_PAINT reichen?

    Ich nutze Dev-Cpp!

    Danke von einem WindowsAPI-N00b 😞

    HILFE 😕

    ps.: dos war doch damals viel einfacher 😉

    hallo,

    mit:

    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);

    kannst Du eine WM_PAINT-Nachricht forcieren.
    MessageBox in WM_PAINT zu nutzen macht nicht wirklich Sinn wie Du wohl schon selbst festgestellt hast.



  • warum erstellst du dir kein timer und bei jedem timeraufruf rufst du :

    SendMessage(hwnd, WM_PAINT, 0, 1);

    mit z.B. dem lParam Wert als 1. Dann prüfst du in WM_PAINT ob lParam == 1 und verarbeitest das dann...so gehst du zumindst nur auf die WM_PAINT Nachrichten ein die vom Timer kommmen, und nicht die, die z.B. beim vergrößern des Fensters auftreten...



  • Maikel schrieb:

    SendMessage(hwnd, WM_PAINT, 0, 1);

    Um Himmels Willen!

    MSDN schrieb:

    The WM_PAINT message is generated by the system and should not be sent by an application.

    Quelle



  • ich vergaß, wenn Du ein dauerhaftes refresh willst gibts die Möglichkeit einen Timer zu setzen, der je nach Bedarf das Fenster alle x Millisekunden erneuert.

    du schreibst dann z.B.

    #define Timer1 100 // global definieren

    case WM_CREATE:
    {
    SetTimer(hwnd, Timer1, 100); // sendet alle 100ms eine WM_TIMER-Nachricht

    return 0;
    }

    und fügst

    case WM_TIMER:
    {
    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);

    return 0;
    }

    in die Mainloop ein.

    beim verlassen des Programms oder wenn der Timer nicht mehr benötigt wird

    KillTimer(hwnd, Timer1);

    hoffe das hilft!

    und sorry, formatieren geht hier irgendwie nicht.



  • MSDN schrieb:

    The WM_PAINT message is generated by the system and should not be sent by an application.

    Ja man kann auch alles stur aus der MSDN lernen...
    aber die Funktionen zum Refreshen machen eigentlich nicht viel mehr außer die WM_PAINT Methode aufzurufen, oder?
    außerdem fällt mir jetzt keine Möglichkeit ein, wo es schädlich sein kann die Nachricht selbst zu senden...

    und das wichtigste ist ja es funktioniert...



  • o~o schrieb:

    ich vergaß, wenn Du ein dauerhaftes refresh willst gibts die Möglichkeit einen Timer zu setzen, der je nach Bedarf das Fenster alle x Millisekunden erneuert.

    du schreibst dann z.B.

    #define Timer1 100 // global definieren

    case WM_CREATE:
    {
    SetTimer(hwnd, Timer1, 100); // sendet alle 100ms eine WM_TIMER-Nachricht

    return 0;
    }

    und fügst

    case WM_TIMER:
    {
    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);

    return 0;
    }

    in die Mainloop ein.

    beim verlassen des Programms oder wenn der Timer nicht mehr benötigt wird

    KillTimer(hwnd, Timer1);

    hoffe das hilft!

    und sorry, formatieren geht hier irgendwie nicht.

    danke! das funktioniert :)))
    aber trotzdem:

    1. Warum kann ich nicht refreshen wann ich will?
    2. Warum springt er mehrmals in WM_PAINT? Wozu so viele Messages bei start und resize? Würde nicht eine WM_PAINT reichen?

    Kann mir wer jemand die fragen beantworten?

    es scheint, als wenn der paint sandwich NUR im WM_PAINT case funktioniert.
    warum nicht wenn ichs woanders im Programmcode mache?

    // MAIN MESSAGE LOOP
        while(TRUE) // Nachrichtenweiterleitung
        {
                if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
                {
                    if(msg.message == WM_QUIT) // on quit break loop
                        break;
    
                    TranslateMessage(&msg); // translate
                    DispatchMessage(&msg); // dispatch to WindowProc
                }
            Appl_Main(); // HIER DRIN WOLLTE ICH DEN REFRESH MACHEN ;-) WARUM GEHTS NICHT?
        }
    

    tut mir leid fürs löcher in den bauch fragen, ich bin jemand der sich nicht wohl dabei fühlt einfach nur zu wissen was man schreiben muss damits geht, sondern auch wissen will warum es anders nicht geht. 🙂



  • adsci schrieb:

    1. Warum kann ich nicht refreshen wann ich will?

    InvalidateRect kannst du eigentlcih aufrufen, wo du willst - nur Begin-/EndPaint darfst du eben nur in WM_PAINT aufrufen 😉

    adsci schrieb:

    2. Warum springt er mehrmals in WM_PAINT? Wozu so viele Messages bei start und resize? Würde nicht eine WM_PAINT reichen?

    Immer wenn Bereiche deines Client-Bereiches ungültig werden bekommst du eben eine WM_PAINT NAchricht, die dir die Möglichkeit gibt, den Fensterinhal neu zu zeichnen. Das kann eben z.B. durch InvalidateRect sein, oder aber auch dadurch, dass du dein Fenster in der Größe änderst, oder Teile zuvor durch ein anderes Fenster verdeckt waren und jetzt wieder sichtbar werden (wobei Windows hier auch teilweise den alten Inhalt speichert und dann selbstständig wiederherstellt).



  • Hmm an diesem Problem hänge ich jetzt auch oder jedenfalls so ähnlich

    kann jetzt ein nicht Modales Fenster aufrufen 😃 und darstellen.
    Nun ändern sich in meiner Berechnung dauernt Werte die dort angzeigt werden sollen. Also habe ich entsprechende Textfelder angelegt die ich in WM_Paint über eine Variable[] neu befülle und rufe in meiner Berechnung regelmäßig Update_Window()auf ... Nur leider werden die Textfelder nicht aktualiesiert. erst wenn ich das Fenster komplett schließe und wieder öffne sehe ich die geänderten Textausgaben.

    Gebt mir bitte mal nen tip was ich da schon wieder falsch mache.. 😕

    Callback Funktion des Dialogs

    HWND Online_dialog;
    float Auswertung[8]; // global nicht die beste Lösung aber erstmal zum testen
    
    BOOL CALLBACK KIT_Online_dialog (HWND Online_dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
    	{
    	char Text[100];
    	switch (uMsg)
    		{
    		case WM_INITDIALOG:
    
    			ShowWindow(Online_dialog,SW_SHOW);
    				//EndDialog(hwndDlg,wParam);
    		case WM_COMMAND:
    			 if ((wParam == IDOK)||(wParam == IDCANCEL))
    				{
    				EndDialog(Online_dialog,wParam);
    				return TRUE;
    				}
    		case WM_PAINT:
    			//MessageBox(Online_dialog, "ONLINE DIALOGBOX PRINT","Online Print", MB_OK);
    
    			sprintf(Text, "V: \t\t %f" ,Auswertung[0] );			
    			SetDlgItemText(Online_dialog,6000, Text );
    
    			sprintf(Text, "A: \t\t %f" , Auswertung[1]);			
    			SetDlgItemText(Online_dialog,6001, Text );
    
    			sprintf(Text, "S: \t\t %f" , Auswertung[2]);			
    			SetDlgItemText(Online_dialog,6002, Text );
    
    			sprintf(Text, "U_Min: \t\t %f" , Auswertung[3]);			
    			SetDlgItemText(Online_dialog,6003, Text );
    
    			sprintf(Text, "M_Kraft: \t %f" , Auswertung[4]);			
    			SetDlgItemText(Online_dialog,6004, Text );
    
    			sprintf(Text, "Delta S Fahrzeuge: \t %f" , Auswertung[5]);			
    			SetDlgItemText(Online_dialog,6005, Text );
    
    			sprintf(Text, "Delta V Fahrzeuge: \t %f" , Auswertung[6]);			
    			SetDlgItemText(Online_dialog,6006, Text );
    
    			sprintf(Text, "Pedale: \t\t\t %f" , Auswertung[7]);			
    			SetDlgItemText(Online_dialog,6007, Text );
    
    			//ShowWindow(Online_dialog,SW_SHOWNA);		
    		}
    	return FALSE;
    	}
    

    Aufruf der Update funktion bei jedem Rechendurchgang

    void BeschattenSim::Print(float dD, float dV,float P, float U_min, float M_Kraft, float V, float A, float S)
    {
    	Auswertung[0] = V;
    	Auswertung[1] = A;
    	Auswertung[2] = S;
    	Auswertung[3] = U_min;
    	Auswertung[4] = M_Kraft;
    	Auswertung[5] = dD;
    	Auswertung[6] = dV;
    	Auswertung[7] = P;
    	UpdateWindow(Online_dialog);
    }
    

    Gruß wastman



  • Nein! SetDlgItemText gehört doch nicht in WM_PAINT - das kannst du z.B. direkt in BeschattenSim::Print packen. Außerdem wäre es wohl sinnvoll für die IDs der Edit-Felder entsprechend Konstanten mit sprechenden Namen zu definieren.

    Zu WM_PAINT: Du bräuchtest InvalidateRect (+ ggf. anschließend noch UpdateWindow wenn du nicht warten willst)

    Aber jetzt bitte nicht aus bequemlichkeit einfach aus deinem UpdateWindow einen InvalidateRect-Aufruf machen - wie schon gesagt: SetDlgItemText hat nichts in WM_PAINT zu suchen!



  • Ok jetzt sieht es so aus:

    void BeschattenSim::Print(float dD, float dV,float P, float U_min, float M_Kraft, float V, float A, float S)
    {
    	char Text[100];
    
    	sprintf(Text, "V: \t\t %f" ,V );			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_V, Text );
    
    	sprintf(Text, "A: \t\t %f" , A);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_A, Text );
    
    	sprintf(Text, "S: \t\t %f" , S);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_S, Text );
    
    	sprintf(Text, "U_Min: \t\t %f" , U_min);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_U_MIN, Text );
    
    	sprintf(Text, "M_Kraft: \t %f" , M_Kraft);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_M_KRAFT, Text );
    
    	sprintf(Text, "Delta S Fahrzeuge: \t %f" , dD);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_DS, Text );
    
    	sprintf(Text, "Delta V Fahrzeuge: \t %f" , dV);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_DV, Text );
    
    	sprintf(Text, "Pedale: \t\t\t %f" , P);			
    	SetDlgItemText(Online_dialog,IDC_ONLINE_Pedale, Text );
    
    	InvalidateRect(Online_dialog,NULL,FALSE);
    	//UpdateWindow(Online_dialog);
    }
    
    BOOL CALLBACK KIT_Online_dialog (HWND Online_dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
    	{
    	switch (uMsg)
    		{
    		case WM_INITDIALOG:
    			Sim.Print(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); // Initaliesieren mit Null werten des Dialogs
    			ShowWindow(Online_dialog,SW_SHOW);
    				//EndDialog(hwndDlg,wParam);
    		case WM_COMMAND:
    			 if ((wParam == IDOK)||(wParam == IDCANCEL))
    				{
    				EndDialog(Online_dialog,wParam);
    				return TRUE;
    				}
    	//	case WM_PAINT:
    			//ShowWindow(Online_dialog,SW_SHOWNA);		
    	//		return TRUE;
    		}
    	return FALSE;
    	}
    

    Folgende 2 Probleme:
    SetDlgItemText scheint nicht mehr zu Funktionieren. Jedenfals bleibt jetzt immer der standart Anfangstext "Static" in den Textfelden stehen. Obwohl laut Debugger die Strings richtig gesetzt sind in der Var. Text[]

    InvalidateRect(Online_dialog,NULL,FALSE); Bei dieser Fkt bin ich mir auch noch nicht so ganz sicher ob das sooo richtig ist, da momentan der gesammte Bildschirm bei einer holen wiederholrate flackert, was mir sagt, dass nicht nur das Dialogfenster neu gezeichnet wird. Liegt sicher an der NULL die ich übergeben habe für RECT...... 😕 oder? Wenn ja wie stelle ich das am besten ab.

    Warscheinlich wäre auch noch ein timer sinnvoll, damit nur jeder 10 rechendurchgang bzw nur alle paar sek ein neuzeichnen stattfindet auf preformance gründen oder?



  • Ist Online_dialog gültig? Das InvalidateRect brauchst du übrigens gar nicht 😉



  • Ja Online_dialog ist eine globale Variable vom Typ HWND

    HWND Online_dialog;
    

    vondaher sollte sie eigendlich gültig sein....
    Oder ist das in diesem Fall doppelt gemoppelt mit der lokalen Variablen def. im Funktionsrumpf der Callback Funktion der DialogBox??
    BZW. Überschreibe ich die globale Variable Online_dialog in diesem Fall nicht mit der lokalen in der Funktion..... zumindest im Bereich der Funktion...
    ah gerade voll unsicher ... *zurück ans zeichenbrett* 🙂

    Wenn jemand die Lösung des Problems kennt bin ganz ohr dafür und lernfähig 🙂



  • wastman schrieb:

    BZW. Überschreibe ich die globale Variable Online_dialog in diesem Fall nicht mit der lokalen in der Funktion..... zumindest im Bereich der Funktion...

    Du überdeckst damit die globale Variable - merke aber gerade, dass du ja geschrieben hattest, dass des Fenster flackert, also scheint der InvalidateRect-Aufruf gültig gewesen zu sein (und damit auch das Dialog-Hnalde).

    Bei case WM_INITDIALOG fehlt dir übrigens noch das return am Ende - so springt er ja auch gleich noch mit in WM_COMMAND hinein 😉

    Hast du mal den Rückgabewert von SetDlgItemText angeschaut - und dann evtl. GetLastError?!



  • Hmm genau genommen flackert nicht das Dialog Fenster sondern der gesammte Bildschirm. Daher tipp ich mal das der Handle nicht richtig ist.

    Der fehler Bestätigt es auch nochmal

    void BeschattenSim::Print(float dD, float dV,float P, float U_min, float M_Kraft, float V, float A, float S)
    {
    	if (OnlineDialog== true) // Wenn Dialog offen
    	{
    		char Text[100];
    		bool fehler;	
    
    		sprintf(Text, "V: \t\t %f" ,V );			
    		fehler = SetDlgItemText(Online_dialog,IDC_ONLINE_V, Text );
    		if(fehler == false)
    		{
    			LPVOID lpMsgBuf;
    			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
    							GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
    			MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
    		// Free the buffer.
    		LocalFree( lpMsgBuf );
    		}
    
    		sprintf(Text, "A: \t\t %f" , A);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_A, Text );
    
    		sprintf(Text, "S: \t\t %f" , S);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_S, Text );
    
    		sprintf(Text, "U_Min: \t\t %f" , U_min);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_U_MIN, Text );
    
    		sprintf(Text, "M_Kraft: \t %f" , M_Kraft);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_M_KRAFT, Text );
    
    		sprintf(Text, "Delta S Fahrzeuge: \t %f" , dD);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_DS, Text );
    
    		sprintf(Text, "Delta V Fahrzeuge: \t %f" , dV);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_DV, Text );
    
    		sprintf(Text, "Pedale: \t\t\t %f" , P);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_Pedale, Text );
    
    		sprintf(Text, "Durchlauf Nummer:  %d" , RnR);			
    		SetDlgItemText(Online_dialog,IDC_ONLINE_RNR, Text );
    
    		UpdateWindow(Online_dialog);
    	}
    }
    

    Fehler: Ungültiges Fensterhandle

    Wie kann ich dem sinnvoll abhilfe schaffen??
    würde jetzt einfach ganz naiv probieren im INIT des Dialogs den Lokalen Handle in einen Globalen speichern (natürlich nicht mit dem selben namen 😉 )

    BOOL CALLBACK KIT_Online_dialog (HWND Online_Dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
    	{
    	switch (uMsg)
    		{
    		case WM_INITDIALOG:
    			Online_dialog = Online_Dialog;
    			Sim.OnlineDialog= true;
    			Sim.Print(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); // Initaliesieren mit Null werten
    			ShowWindow(Online_dialog,SW_SHOW);
    			return TRUE;
    				//EndDialog(hwndDlg,wParam);
    		case WM_COMMAND:
    			 if ((wParam == IDOK)||(wParam == IDCANCEL))
    				{
    				 Sim.OnlineDialog=false;
    				EndDialog(Online_dialog,wParam);
    				return TRUE;
    				}
    	//	case WM_PAINT:
    			//ShowWindow(Online_dialog,SW_SHOWNA);		
    	//		return TRUE;
    		}
    	return FALSE;
    	}
    

    Funktioniert im übrigen auch supi solange man vor dem Start der Sim das Fenster auch aufmacht 🙂 ansonsten kommt wie zu erwarten der Fehler , das kein Fenster Handle vorhanden ist. 🕶
    [Edit] das hab ich jetzt erstmal mit einem Flag abgefangen... [/Edit]


Anmelden zum Antworten