txt-File auslesen und in Listbox anzeigen?



  • Hallo,

    ich habe heute folgendes Problemchen.
    Ich bin neu in der WinAPI Welt und muss mich für die Schule in die Materie einarbeiten (und das ganze in 5 Tagen 😞 )

    Also ich habe bis jetzt folgendes Grundgerüst:

    //----------------------------------------------------------
    // Besondere Lernleistung - Physik/TeWi - Stephan Liebig
    // Projekt: Digitaler Fahrtenschreiber
    // Tool: Auslesen des Mikrokontrollers (Anzeige der IDs)
    // Last Build: 23.03.2007   v.0.0.2
    //----------------------------------------------------------
    
    #include <windows.h>
    #include <exception>
    
    #define ID_ladedaten 1001 // Button: Lade Daten aus Mikrokontroller
    #define ID_speichern 1002 // Button: Speicher geladene Daten 
    #define ID_listbox 1003 // Ausgabeliste fuer die IDs, die vom mC aufgezeichnet wurden
    #define ID_about 1004 // Button: about 
    
    bool Running = true;
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch(msg)
    	{
    	case WM_CREATE:
    		{
    
    			CreateWindowA("button", "Daten Laden", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 100, 40, hwnd, (HMENU)ID_ladedaten, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			CreateWindowA("button", "Speichern", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 120, 10, 100, 40, hwnd, (HMENU)ID_speichern, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			CreateWindowA("button", "Projekt", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 230, 10, 100, 40, hwnd, (HMENU)ID_about, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			CreateWindowA("listbox", NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD ^ LBS_SORT | LBS_HASSTRINGS, 10, 60, 300, 500, hwnd, (HMENU)ID_listbox, ((LPCREATESTRUCT)lParam)->hInstance, NULL); 
    
    		}
    	case WM_KEYDOWN:
    		switch(wParam)
    		{
    		case VK_ESCAPE:
    			SendMessage(hwnd, WM_CLOSE, 0, 0);
    			break;
    		}
    		case WM_COMMAND:
    		{
    			if (HIWORD(wParam) == BN_CLICKED)
    			{
    				switch(LOWORD(wParam))
    				{
    				case ID_ladedaten:
    					//Eine Txt Laden
    					break;
    
    				case ID_speichern:
    					//Daten in einer *.txt abspeichern
    					SendMessage(hwnd, WM_CLOSE, 0, 0); //Für Testzwecke Fenster schließen
    					break;
    
    				case ID_\1:
    					//Übers Projekt
    					break;
    				}
    			}
    		}
    		break;
    
    	case WM_CLOSE:
    		{
    			DestroyWindow(hwnd);
    			return TRUE;
    		}
    		break;
    
    	case WM_DESTROY:
    		{
    			Running = false;
    			PostQuitMessage(0);
    			return 0;
    		}
    		break;
    	}
    
    	return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow)
    {
    	try
    	{
    		unsigned int hr;
    		HWND hwnd;
    
    		WNDCLASSEX winclass;
    		memset(&winclass, 0, sizeof(winclass));
    
    		winclass.cbSize        = sizeof(winclass);
    		winclass.style         = CS_HREDRAW | CS_VREDRAW;
    		winclass.lpfnWndProc   = WindowProc;
    		winclass.cbClsExtra    = 0;
    		winclass.cbWndExtra    = 0;
    		winclass.hInstance     = GetModuleHandle(NULL);
    		winclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    		winclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    		winclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    		winclass.lpszMenuName  = NULL;
    		winclass.lpszClassName = L"WindowClass";
    		winclass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    		if(!(hr = ::RegisterClassEx(&winclass)))
    		{
    			// error
    		}
    
    		hwnd = ::CreateWindow(L"WindowClass", L"Digitaler Fahrtenschreiber | Testtool", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 300, 600, 700, GetDesktopWindow(), NULL, winclass.hInstance, NULL);
    		if(!hwnd)
    		{
    			// error
    		}
    
    		MSG msg;
    		memset(&msg, 0, sizeof(msg));
    
    		while(Running)
    		{
    			if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    			{
    				TranslateMessage(&msg);
    				DispatchMessage(&msg);
    			}
    			else
    			{
    			}
    		}
    	}
    	catch(const std::exception &e)
    	{
    		MessageBoxA(0, "exception", e.what(), MB_OK);
    	}
    	catch(...)
    	{
    		MessageBoxA(0, "unknown exception", "eroor", MB_OK);
    	}
    
    	return 0;
    }
    

    Die txt-File, die ausgelesen wird, liegt dabei immer an einer Stelle, die nicht verändert wird. Daher möchte ich diese schon im Programmcode festlegen.
    Die Datei enthält dabei 3 Informationen pro Zeile.
    Kann mir jemand helfen, wie ich solch eine Auslese und in meiner Listbox anzeige?



  • Zeig mal genau wie das Textfile aussehen soll ...
    Brauchst ne Lösung in C oder C++?



  • Ich bräuchte die Lösung in C++

    Die Textfile (save_logs.txt) sieht z.B. so aus:

    24.03.2007 | 12:42:45 | 56
    24.03.2007 | 12:42:55 | 57
    24.03.2007 | 12:43:20 | 54
    24.03.2007 | 12:43:25 | 50
    24.03.2007 | 12:43:45 | 35
    24.03.2007 | 12:44:15 | 45



  • ja das ist doch gut ... dann guck dir mal std::fstream und std::getline und std::string an (s. http://www.cppreference.com/cppio/index.html, http://www.cppreference.com/cppstring/getline.html, http://www.cppreference.com/cppstring/index.html) 🙂



  • Danke für deine Links, wobei dort nur der letzte geht 🙂

    Also um die txt zu öffnen brauche ich noch:

    #include <fstream>
      void open( const char *filename );
      void open( const char *filename, openmode mode = default_mode );
    

    und dann noch

    ifstream inputStream;
    inputStream.open("file.txt");
       if( !inputStream ) {
    	//error "Error opening input stream";
    	return 0;
       }
    

    Allerdings bekomme ich dann folgende Fehler:

    error C2061: syntax error : identifier 'openmode'
    error C2065: 'ifstream' : undeclared identifier
    error C2146: syntax error : missing ';' before identifier 'inputStream'
    error C2065: 'inputStream' : undeclared identifier
    error C2228: left of '.open' must have class/struct/union



  • ja ka was du da machst ^^

    #include <iostream> // für std::cout
    #include <fstream> // für std::fstream
    #include <string> // für std::string und std::getline
    
    int main()
    {
        std::ifstream file_stream("file.txt", std::ios::in); // Datei zum Lesen öffnen
        if (!file_stream) // Konnte die Datei geöffnet werden?
        {
            std::cout << "Could not open file \"file.txt\"!" << std::endl;
            return 0;
        }
    
        std::string string_input;
        while (std::geline(file_stream, string_input)) // Solange getline klappt immer eine Zeile aus der Datei auslesen ...
            std::cout << string_input << std::endl; // Und einfach ausgeben ... kannst hier auch was anderes machen ;)
    
        file_stream.close(); // Datei auch wieder schließen!
    
        return 0;
    }
    


  • Bitte schlag mich jetzt, wenn ich falsch liege.
    Dein Code ist doch jetzt für eine Konsolenapllikation oder?



  • hmm ja das std::cout und das int main ... ^^
    mach halt aus

    std::ifstream file_stream("file.txt", std::ios::in);
    if (!file_stream)
    {
        std::cout << "Could not open file \"file.txt\"!" << std::endl;
        return 0;
    }
    

    einfach

    std::ifstream file_stream("file.txt", std::ios::in);
    if (!file_stream)
    {
        MessageBox(NULL, "Could not open file \"file.txt\"!", NULL, MB_OK | MB_ICONERROR);
        return 0;
    }
    

    und anstelle von

    std::cout << string_input << std::endl;
    

    packst du das was in string_input steht in deine ListBox ... und fertig. Allerdings muss du den Code noch anpassen ... so das der nicht die ganze Zeile ausließt sondern nur das was du brauchst 🙂



  • Also habe ich jetzt folgendes:

    case ID_ladedaten:
    	//Daten aus einer txt lesen
    	std::ifstream file_stream("C:/Dokumente und Einstellungen/Odenwaelder/Desktop/Stephan/13bgdw/besondere lernleistung/programme/opener/txtopener/save_logs.txt", std::ios::in);
    	if (!file_stream)
    	{
    	    //MessageBox(NULL, "Could not open file \"file.txt\"!", NULL, MB_OK | MB_ICONERROR);
    	    MessageBox(hwnd,TEXT("Die Datei konnte nicht geladen werden"), TEXT("ERROR: Lade Daten"), MB_OK | MB_ICONERROR);
    	    return 0;
    	}
    break;
    

    Aber ich bekomme noch folgende Fehlermeldungen:

    error C2360: initialization of 'file_stream' is skipped by 'case' label



  • hmm ja scheinst ja noch nicht soo gefestigt in den Grundlagen zu sein ...

    case ID_ladedaten:
    { // !!! Wenn du Variablen deklarieren willst !!!
        std::ifstream file_stream("C:\\Dokumente und Einstellungen\\Odenwaelder\\Desktop\\Stephan\\13bgdw\\besondere lernleistung\\programme\\opener\\txtopener\\save_logs.txt", std::ios::in);
        if (!file_stream)
        {
            MessageBox(hwnd,TEXT("Die Datei konnte nicht geöffnet werden"), NULL, MB_OK | MB_ICONERROR);
            break;
        }
        file_stream.close() // Nicht vergessen ;)
    } break; // !!! Und wieder schließen !!!
    


  • Hopla, das die geschweiften Klammern fehlen, hätte mir eigentlich auffallen müssen. Aber irgendwie...

    Ich bin auch wirklich noch ein Anfänger, aber ich hoffe das ich das bald ändern kann 🙂

    Okay, das funktioniert anscheind.
    Jetzt fehlt mir noch die Weitergabe an die Listbox 😕
    Das geht dann über SendMessage() ?



  • Hmm könnte Probleme geben, dass c_str nicht Null-Terminiert ist ... naja:

    case ID_ladedaten:
    {
        std::ifstream file_stream("C:\\Dokumente und Einstellungen\\Odenwaelder\\Desktop\\Stephan\\13bgdw\\besondere lernleistung\\programme\\opener\\txtopener\\save_logs.txt", std::ios::in);
        if (!file_stream)
        {
            MessageBox(hwnd,TEXT("Die Datei konnte nicht geöffnet werden"), NULL, MB_OK | MB_ICONERROR);
            break;
        }
        std::string string_input;
        while (std::getline(file_stream, string_input))
            SendMessage(hWndList, LB_ADDSTRING, 0, string_input.c_str());
    
        file_stream.close()
    } break;
    

    so in etwa ..

    Referenz:
    LB_ADDSTRING Message



  • Bekomme den Fehler:

    error C2664: 'SendMessageW' : cannot convert parameter 4 from 'const char *' to 'LPARAM'

    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static HWND        hwndlist; 
    	switch(msg)
    	{
    	case WM_CREATE:
    		{
    
    			CreateWindowA("button", "Daten Laden", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 100, 40, hwnd, (HMENU)ID_ladedaten, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			CreateWindowA("button", "Speichern", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 120, 10, 100, 40, hwnd, (HMENU)ID_speichern, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			CreateWindowA("button", "Projekt", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 230, 10, 100, 40, hwnd, (HMENU)ID_about, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
    			hwndlist = CreateWindowA("listbox", NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD ^ LBS_SORT | LBS_HASSTRINGS, 10, 60, 300, 500, hwnd, (HMENU)ID_listbox, ((LPCREATESTRUCT)lParam)->hInstance, NULL); 
    
    		}
    
    case ID_ladedaten:
    					{
    					//Daten aus einer txt lesen
    					std::ifstream file_stream("C:/Dokumente und Einstellungen/Odenwaelder/Desktop/Stephan/13bgdw/besondere lernleistung/programme/opener/txtopener/save_logs.txt", std::ios::in);
    					if (!file_stream)
    					{
    						//MessageBox(NULL, "Could not open file \"file.txt\"!", NULL, MB_OK | MB_ICONERROR);
    						MessageBox(hwnd,TEXT("Die Datei konnte nicht geladen werden"), TEXT("ERROR: Lade Daten"), MB_OK | MB_ICONERROR);
    						return 0;
    					}
    					else
    					{
    						std::string string_input;
    						while (std::getline(file_stream, string_input)) // Solange getline klappt immer eine Zeile aus der Datei auslesen
    						{
    							//Daten werden an die Listbox geschickt
    							SendMessage(hwndlist, LB_ADDSTRING, 0, string_input.c_str()); 
    						}
    						file_stream.close(); //Datei wird nicht mehr gebraucht, also schließen!
    					}
    					}
    					break;
    


  • ich hab keine Lust dir alles vor zu kauen ... musst de halt casten ... hättest de in der Doc nachgeguckt, hättest de das auch selbst rausbekommen ...

    reinterpret_cast<LPARAM>(string_line.c_str()) ... anstelle von string_line.c_str() ...



  • @stephan²: Du weißt, aber das WinAPI C-basiert ist und daher keine Exceptions auswirft, nech ?! ... Vergleiche hier:

    stephan² schrieb:

    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow)
    {
        try
        {
            // ...
        }
        catch(const std::exception &e)
        {
            MessageBoxA(0, "exception", e.what(), MB_OK);
        }
        catch(...)
        {
            MessageBoxA(0, "unknown exception", "eroor", MB_OK);
        }
    }
    


  • @CodeFinder

    Ich glaube, ich kapiere gerade nicht, was mir das sagen soll.



  • stephan² schrieb:

    @CodeFinder

    Ich glaube, ich kapiere gerade nicht, was mir das sagen soll.

    Naja, Deine catch-Handler kommen nie zur Ausführung da Funktionen wie RegisterClass(Ex) und CreateWindow(Ex), etc ( ➡ WinAPI-Funktionen) keine Exceptions auswerfen. Daher ist Dein Exceptions-Handling bei Deinem derzeitigen Code überflüssig 😉 .



  • Naja, vielleicht brauche ich sie irgendwann noch 🙂

    Womit ich grad gar nicht klar komme, egal wie ich den ausdruck

    Ob ich das so schreibe:

    char test[40];
    strcpy(test,"hello world");
    SendMessage( hwndList,(UINT)LB_ADDSTRING,(WPARAM)0,(LPARAM)test);
    

    oder so:

    TCHAR* test = "test";
    SendMessage( hwndList,(UINT)LB_ADDSTRING,(WPARAM)0,(LPARAM)test);
    

    oder so:

    SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)string_input.c_str());
    

    Ich bekomme in meiner Listbox nur "??????d" z.b. angezeigt.
    Woran liegt das ?



  • Versuch mal das:

    SendMessage(hwndList, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(TEXT("Diese Zeichenkette wird hinzugefügt.")));
    


  • Jap, das macht er...

    aber wenn ich dann

    SendMessage(hwndList, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(TEXT(string_input.c_str())) );
    

    daraus mache, geht das wieder nicht 😞



  • Damit hat sich das wohl bestätigt *grinz* ...:

    (D)Evil schrieb:

    hmm ja scheinst ja noch nicht soo gefestigt in den Grundlagen zu

    Ähm, ja entweder Du verwendest ANSI oder nur UNICODE. Denke mal 'string_input' ist ein std::string, kein std::wstring. Wenn es ein std::wstring ist, brauchst Du auch das Makro TEXT nicht mehr. Dieses sorgt dafür, dass Dein Compiler den in dem doppelten Anführungszeichen eingeschlossenen Text als UNICODE-String interpretiert, falls UNICODE aktiviert ist, andernfalls als ANSI-String. Falls Du auf ein std::string-Objekt angewiesen bist, musst Du den Inhalt entsprechend in einen UNICODE-String umwandeln.


Anmelden zum Antworten