Anständige Lösung für OnTimer gesucht - Laufschrift in MFC?



  • Hallo

    Mal eine etwas andere Frage:
    Ist es theoretisch oder praktisch möglich in einem Editfeld den Text als eine Art "Laufschrift" durchlaufen zu lassen? Beispielsweise von unten nach oben?

    Nun zu der Timerfrage:

    Wie man einen Timer macht ist mir durchaus bekannt. Allerdings wollte ich mittels dem Timer laufend über das Internet eine PHP-Datei ansprechen und das Ergebnis in einem Listenfeld anzeigen ohne die anderen Programmprzesse zu beeinträchtigen. Leider ist dies bisher nicht möglich, da durch diesen Timer (SetTimer wird in OnInitDialog gesetzt, da er automatisch gleich starten soll) das Programm verlangsamt wird und man kaum eine Chance hat weiterzuarbeiten!

    Gibt es dazu eine besser Lösung? Und wie mache ich das denn mit 3 oder mehr Timern? Einerseits möchte ich das tun wie oben soeben beschrieben, gleichzeitg noch 2 Bilder alle 5 Minuten neu laden und Uhrzeit / Datum aktuell am laufen halten (sekundentakt), später eventuell noch mehr.

    Wie stelle ich das am besten an?? Ich hab mal hier was mit der Suche gefunden mittels ID_TIMER und if(nIDEvent == 1) usw, aber damit komm ich nicht klar! Da ist es ja entweder der einte oder der andere, aber was, wenn alle Timer gleichzeitig laufen sollen OHNE die Programmgeschwindigkeit und Intensität zu beeinträchtigen ?

    Hat da jemand eine anständige Lösung??

    Lg
    Wolf



  • wenn du deinen timer in der OnInitDialog startest läuft der Timer im Haupthread deines Programmes.

    ich denke das du deine Timergeschichte in einem extra Thread laufen lassen must.
    den kannst du dann auch in der OnInitDialog starten ohne dein Programm zu beeinträchtigen.



  • Hm, habe ich mir auch schon überlegt. Gibt es irgendwo ein ausführliches und verständliches Tutorial über Timer und Threads? Ich wurde bisher noch nicht fündig da ich mich mit dem Thema Thread noch nicht auseinandergesetzt habe...

    😕



  • wüste jetzt nicht welches tut beides behandelt.

    in die *.h

    static UINT	ThreadFunction	(LPVOID pParam);
    
    BOOL OnInitDialog(...)
    {
    
    LPVOID lpParam  = NULL;//Hier ist der Punkt wenn du Werte an die Threadfunktion übergeben willst
    
    ::AfxBeginThread(ThreadFunction,lpParam);//Starte den Thread
    
    ...
    }
    
    UINT CDlg::ThreadFunction(LPVOID pParam)
    {
    
    //Starte hier deinen Timer oder verweise auf eine Funktion die den Timer Startet.
       return 0;
    }
    


  • So also ich hab das jetzt mal so gelöst:

    In der HauptDlg.h

    static UINT WarnList (LPVOID pParam);
    

    In der HauptDlg.cpp

    UINT CHauptDlg::WarnList(LPVOID pParam)
    {
    	//Aktuelle Warnungen laden und im Editfeld anzeigen
    	CString somecode, s;      
         CInternetSession session("Warnlist",1,INTERNET_OPEN_TYPE_PRECONFIG);
    
         CStdioFile* pFile = NULL;   
    	 CString strUrl("http://www.nfws.ch/inc/warnlist.php");
    
       try  
       {  
               pFile = session.OpenURL(strUrl,1,INTERNET_FLAG_TRANSFER_BINARY,NULL,0);
    
            if(pFile)  
            {           
                while (pFile->ReadString(somecode) != NULL)  
                {  
                    s = s + somecode;  
                }  
                pFile->Close();  
            }       
       }  
       catch (CInternetException* e)  
       {        
            e->Delete();
            session.Close();
            CloseHandle(session);  
       }
       m_ctlListTxt.SetWindowTextA(s);
    	return 0;
    }
    

    Und in OnInitDialog hab ich

    //Timer / Thread starten
       LPVOID pParam = NULL;
       ::AfxBeginThread(WarnList,pParam);
    

    Soweit so gut, allerdings bekomm ich nun folgende Fehlermeldung:

    1>c:\users\wolf\documents\visual studio 2008\projects\scmt\scmt\hauptdlg.cpp(201) : error C2228: left of '.SetWindowTextA' must have class/struct/union

    Wenn diese m_ctlListTxt.SetWindowTextA(s) normal in OnInitiDialog oder sonst irgendwo steht, funktioniert alles Problemlos. Aber sobald das in der ThreadFunct steht, geht nichts. Muss ich da noch etwas zusätzliches beachten??

    Die m_ctlListTxt Variable ist auf jedenfall schon Public..

    lg
    Wolf



  • ich glaube das SetWindowTextA falsch ist.
    versuch es erst mal mit
    m_ctlListTxt.SetWindowText(s);

    wenn dann immer noch der fehler passiert, dann wegen

    [u]static[/u] UINT WarnList (LPVOID pParam);
    

    deine variable m_ctlListTxt wäre jetzt son Parameter den du an den thread übergeben müßtest.

    LPVOID pParam = &m_ctlListTxt;
    ::AfxBeginThread(WarnList,pParam);
    

    in deiner Threadfunktion rufst du die liste wieder auf

    UINT CHauptDlg::WarnList(LPVOID pParam)
    {
    
        CListCtrl *pListCtrl = (CListCtrl*)pParam;
    
        ...
    
        pListCtrl->SetWindowText(s);
    
    }
    


  • LPVOID pParam = &m_ctlListTxt;
    

    Das war's 🙂

    Danke

    Allerdings wird zwar jetzt die PHP-Datei ausgelesen und der Text angezeigt. Nur, ändere ich den Eintrag in der Datenbank, so wird aber der Text nun NICHT mehr geändert.. Eigentlich sollte der ja permanent überprüfen und den Text wiedergeben, was aber nicht der Fall ist. Nur beim Programmstart lädt er den aktuellen Text...

    UpdateData hab ich schon versucht, keine Chance.



  • den thread den du mit

    ::AfxBeginThread(WarnList,pParam);
    

    startest beendet sich natürlich sofern du ihn nicht am laufen hälst.

    du müstest es mal so versuchen

    ...
    do
    {
      try  
       {  
               pFile = session.OpenURL(strUrl,1,INTERNET_FLAG_TRANSFER_BINARY,NULL,0);
    
            if(pFile)  
            {           
                while (pFile->ReadString(somecode) != NULL)  
                {  
                    s = s + somecode;  
                }  
                pFile->Close();  
            }       
       }  
       catch (CInternetException* e)  
       {        
            e->Delete();
            session.Close();
            CloseHandle(session);  
       }
    
       m_ctlListTxt.SetWindowTextA(s);
    
        Sleep(1000);//Nur der Thread wird an dieser Stelle Schlafen geschickt
                    //Der rest vom Programm wird dadurch nicht beeinträchtigt
    
    }while(//Eine bedingung die dir Sinnvoll erscheint);
    
    ...
    


  • So. ich hab jetzt bei While 1+1 reingeschrieben. Jetzt läuft er zwar, aber das Problem ist, dass die Aktuelle Warnung immer dazugefügt werden.

    Sprich zuerst sieht es normal aus:
    Testwarnung 1

    später dann so:
    Testwarnung 1 Testwarnung 1 Testwarnung 1 ... und es hört nicht mehr auf...

    Ich versuchte es damit, dass ich ein Sleep von 10 Sekunden mache, dann das Listfeld lösche und dann erneut die Variable reinschreibe. Das geht auch nicht.. Dann steht einfach nach 10 sekunden Testwarnung 1 Testwarnung 1...

    Dabei sollte es einfach beim einen bleiben... was mach ich da wiederum falsch??



  • must halt ne abfrage machen, das erst dann der Text in der Liste geändert wird, wenn er unterschiedlich zum vorherigen eintrag ist.

    und While 1+1 ist jetzt nicht unbedingt eine sinnvolle bedingung
    wäre eher eine Boolische Member Variable die du von auserhalb des Threads steuern kannst.



  • @rT!f@Ct schrieb:

    must halt ne abfrage machen, das erst dann der Text in der Liste geändert wird, wenn er unterschiedlich zum vorherigen eintrag ist.

    und While 1+1 ist jetzt nicht unbedingt eine sinnvolle bedingung
    wäre eher eine Boolische Member Variable die du von auserhalb des Threads steuern kannst.

    HM.. naja auf die schnelle find ich keine sinnvolle bedingung.. 🙂

    Also ich hab jetzt folgende Abfrage gemacht, respektive wie geht das denn mit GetWindowText?

    CListCtrl *pListCtrl = (CListCtrl*)pParam; 
       if(!pListCtrl->GetWindowTextA() == s)
       {
       pListCtrl->SetWindowTextA(s);
       }
       else
       {
    	   //Rien ne vas plus!
       }
    

    Ich muss ja von dem erneut gelesenen Wert überprüfen ob der schon drin steht, also in "s". Mit GetWindowText möcht ich eigentlich den vorhandenen Text auslesen. Soweitsogut, wäre da nicht wieder die Fehlermeldung:

    1>c:\users\wolf\documents\visual studio 2008\projects\scmt\scmt\hauptdlg.cpp(205) : error C2661: 'CWnd::GetWindowTextA' : no overloaded function takes 0 arguments
    

    Und frag mich nicht wieso immer A kommt.. egal ob Postmessage, SetWindowText egal was, überall kann ich nur das mit dem A am ende auswählen.. entferne ich das A erhalte ich zwar keine FEhlermeldung, aber wird trotzdem als bsp. GetwindowtextA behandelt..



  • Du solltest dir mal die Member der Klasse CListCtrl anschauen. Set- und GetWindowText sind nicht unbedingt die geeigneten Funktionen und den Inhalt deines ListCtrl auszulesen.

    Und nebenbei eine Sinnvolle Variable währe eine Boolsche Membervariable deine Klasse die du vor dem start deines Threads auf True setzt und beim beenden deines Dialoges auf False damit der Thread auch Beendet wird wenn dein Dialog geschlossen wird, sonnst knallt es da eventuell.



  • Hm jo ok.. mag sein, allerdings stellte ich jetzt fest dass es ein STATIC-Text feld ist und kein Listenfeld?? ... Komisch komisch 🙂 Oder bin ich nun falsch? Sonst würde ja ListCtrl nicht funktionieren...

    Und wenn GetWindowTextA keine richtige variante wäre.. was dann?
    Hab schon GetItemData o.Ä versucht, null Chance,



  • CTecS schrieb:

    Du solltest dir mal die Member der Klasse CListCtrl anschauen.

    LOL hast recht, is mir jetzt nicht aufgefallen. 🙄
    spätestens aber mit pListCtrl->GetWindowText 😮

    Wolf1985 schrieb:

    HM.. naja auf die schnelle find ich keine sinnvolle bedingung.. 🙂

    hudeln bringt nix, dadurch passiern dir ja die fehler pListCtrl->SetWindowText/GetWindowText.

    den Letzten eintrag in der Liste bekommst du mit

    int iCount = pListCtrl->GetItemCount( )-1;
    
    CString sText =  pListCtrl->GetItemText( iCount , 0);
    

    Wolf1985 schrieb:

    Und frag mich nicht wieso immer A kommt

    bin mir jetzt nicht sicher, aber ich halte das fürn bug von vc.
    SetWindowTextA ist die Ansi Version und SetWindowTextW ist die Unicode Version von SetWindowText je nach Kompiler einstellung ist
    SetWindowText = SetWindowTextA;
    bzw.
    SetWindowText = SetWindowTextW;

    wenn du das A bzw. das W der jeweiligen funktion wegläst, schadet das nix und du hast in jedem fall die richtige funktion.

    [NEW EDIT]
    mit GetItemData kannst du dir werte holen die NICHT SICHTBAR an das jeweilige element der Liste gehängt wurden. diese must du allerdings mit SetItemData vorher setzen.

    bist du dir denn sicher, das du deine anderen versuche, an das Listenelement zu kommen, richtig ausgeführt hast 😕


  • Mod

    @rT!f@Ct schrieb:

    bin mir jetzt nicht sicher, aber ich halte das fürn bug von vc.

    Wieso ein Bug? Alle Vorkommen von GetWindowtext werden in GetWindowTextA bei einer MBCS und in GetWindowTextW bei einer Unicode Version getauscht.
    Das gilt eben für alle Vorkommen dieses Identifiers!

    Entsprechend gilt dasauch für Memberfunktionen in den Klassen wie bei CWnd::GetWindowText!



  • Ich war die ganze Zeit falsch.. 🙂 LOL

    Grund: Das angebliche Listenfeld war ein Textfeld! *g* hab es jetzt mit einem Listenfeld ersetzt. Allerdings wenn ich da nun SetWindowText("Test"); mache, dann wird nichts angezeigt, respektive der Text ist ev weiss??

    Langsam verwirr ich mich glaub selbst... 😃



  • Wie schon mehrfach gesagt, wenn du ein Listenfeld hast, wobei es wieder drauf an kommt was für eins, solltest du doch in der lage sein die Member der entsprechenden Klasse in der MSDN anzuschauen und dir die entsprechenden Fuinktion Raussuchen zu können. SetWindowText und GetWindowText sind nun mal nicht die alles heilenden Methoden um in jeden Objekt scvhreiben bzw. Lesen zu können.

    An sonsten schau dir Beispiele an wie das gemacht wird im Netz findest du genügend dazu. Solange wie du selbst nicht einmal weisst ob das nun ein CStatic, CListCtrl oder CListBox oder was auch immer das ist wird dir nicht wirklich jemand helfen können



  • Hi Martin,
    du hast mich glaub ich falsch verstanden, das mit dem bug beziehe ich darauf das SetWindowTextA/W in der liste steht, die aufpopt, wenn ich eine Klassenvariable habe und den punkt oder den zeiger darauf anwende.
    Bei VS 6 stand SetWindowTextA/W nicht in dieser list.



  • Da CListCtrl von CWnd abgeleitet ist und CWnd Methoden für Get/SetWindowText enthält, zeigt die Codevervollständigung diese natürlich auch für CListCtrl an. Nur dass diese dann eben nicht das machen, was man erwartet, weil die Fensterklasse sich anders verhält.



  • Hab jetzt ein Editfeld genommen. Allerdings bekomm ich beim Programm folgende Warnmeldung:

    Hier der Code:

    UINT CHauptDlg::WarnList(LPVOID pParam)
    {
    	//Aktuelle Warnungen laden und im Editfeld anzeigen
    	CString somecode, s;      
         CInternetSession session("Warnlist",1,INTERNET_OPEN_TYPE_PRECONFIG);
    
         CStdioFile* pFile = NULL;   
    	 CString strUrl("http://www.nfws.ch/inc/warnlist.php");
    do
    {
    
       try  
       {  
               pFile = session.OpenURL(strUrl,1,INTERNET_FLAG_TRANSFER_BINARY,NULL,0);
    
            if(pFile)  
            {           
                while (pFile->ReadString(somecode) != NULL)  
                {  
                    s = s + somecode;  
                }  
                pFile->Close();  
            }       
       }  
       catch (CInternetException* e)  
       {        
            e->Delete();
            session.Close();
            CloseHandle(session);  
       }
    
       CEdit *pEdit = (CEdit*)pParam;
       CEdit *pEdit = (CEdit*)pParam;
       int iCount = pEdit->GetLineCount()-1;
    
       CString sText =  pEdit->GetWindowTextA ( iCount , 0);
       if(!sText == s)
       {
       pEdit->SetWindowText(s);
       }
    
       else
       {
    	   //RIEN NE VAS PLUS
       }
       pEdit->SetWindowText(s);
    
    }while(1+1);
    
    return 0;
    }
    

    Was muss ich jetzt beim Editfeld verwenden?? Beim ListCtrl war die Variable sText jeweils immer leer, hat also nicht geklappt. Beim EditCtrl werd ich auch aus der MSDN nicht so ganz schlau weil GetWindowText (die Fehlermeldung kommt) entweder hier bei mir nicht constchar ist oder sonst keine 0 Parameter akzeptiert..


  • Mod

    Wie wäre es einfach mal mit MSDN lesen?
    CEdit::GetWindowText nimmt als ersten Parameter ein CString oder einen LPSTR und als zweiten die Länge und es gibt nur im zweiten Fall die Länge zurück.
    http://msdn.microsoft.com/de-de/library/db50wx7h.aspx


Anmelden zum Antworten