Aplikacja MFC - pomocy

0

Jako, że jestem nowym użytkownikiem chciałbym się ze wszystkimi przywitać, tak więc... cześć Wszystkim :)
A teraz kilka słów o mnie i moim problemie...

Otworzyłem ten temat gdyż jestem początkującym programistą i mam pewien problem z napisaniem aplikacji w C++ bazując na bibliotekach MFC. Aplikacja ma przetwarzać plik tekstowy, który jest swoistą bazą danych pomiarowych z urządzenia rejestrującego. Aplikacja ma tworzyć wykres oraz dawać możliwość obliczania podstawowych danych statystycznych, tj. średnia, odchylenie, itp. oraz po części ma posiadać funkcję prostego systemu eksperckiego.
Otóż pisałem jakiś czas temu aplikacje konsolowe w C++, ale były to proste aplikacje ułatwiające mi liczenie pewnych elementów konstrukcyjnych. Aplikacje okienkowe pisałem za to w VisualBasic-u.
Podejrzewam, że większość powie "po co zawracać sobie głowę C++ z MFC, jak istnieje wiele łatwiejszych aplikacji do pisania aplikacji okienkowych, jak chociażby C# czy Java. Otóż jestem studentem i język programowania został mi narzucony. Ale za to temat aplikacji jest to mój wymysł (i tutaj chyba strzeliłem sobie w stopy). Do wyboru tematu kierowałem się potrzebą przetwarzania danych z rejestratora, który posiadam w pracy.
Dodam tylko, że nigdy nie programowałem aplikacji okienkowych w C++ z użyciem MFC. Oczywiście próbowałem się już orientować i coś tam "liznąłem" aczkolwiek podejrzewam, że moje podejście może być niezbyt profesjonalne w niektórych przypadkach i tutaj proszę o słowa krytyki i ewentualne porady.
Ufff...ale się rospisałem...:/

Teraz kilka słów na temat tego co zrobiłem. Otóż aplikację rozpocząłem od utworzenia pustej aplikacji pod WIN32 w której zmieniłem jedną z opcji dodając biblioteki MFC (zdecydowałem się na to ze względu na to, że lubię wiedzieć co robię, a kreator VisualStudio dorzuca od groma swoich danych). Początkowo myślałem napisać aplikację opartą na formularzu, ale nie mogłem znaleźć nigdzie informacji na temat jak to zrobić, dlatego zdecydowałem się na zrobienie głównego okna jako okno dialogowe, w którym otwieram plik, i wstępnie go przetwarzam, a następnie trzema przyciskami przechodzę do "modułów" które mnie interesują(m.in. jeden oparty na formularzu, w którym będzie rysowany wykres z możliwością wyliczania tego co chcę. Zdecydowałem się na takie rozwiązanie gdyż chciałem już jakoś ruszyć temat, bo czas na oddanie projektu się kurczy.

O to foto wyglądem programu:
user image

Do tej pory natrafiłem na kilka problemów. Niektóre rozwiązałem, ...jakoś, ale jest też kilka z którymi nie wiem jak sobie poradzić:

  1. Otwieram plik tekstowy (ważący 12MB), którego poszczególne wiersze są dodawane do tablicy klasy CStringArray. Później zajmę przetwarzaniem poszczególnych "rekordów" tablicy. Moje pytanie brzmi: jak zrobić progress bar, który będzie wskazywał postęp z otwieraniem pliku.. Kontrolka jest dodana, ale gdy próbowałem coś z nią zrobić zawieszało mi system podczas pracy programu.
  2. Mam również problem z umieszczeniem zmiennych globalnych. Otóż chciałem aby część zmiennych była globalna, jak chociażby tablica, której zawartość chciałbym wykorzystać do pokazania danych w tabeli w nowym oknie dialogowym, które będzie się otwierało po wciśnięciu buttona. Utworzyłem osobny plik nagłówkowy "Globals.h", ale dodając w nim zmienne globalne są widziane w funkcji, ale program nie chcę się skompilować. Dodam tylko, że klasę okna dialogowego dodałem przy pomocy Class Wizard, a zmienne przypisane do kontrolek dodałem przy pomocy polecenia "Add Varible"
  3. Kolejny problem mam z przypisaniem zawartości tablicy edit boxa wiersz po wierszu. Chcąc użyć w funkcji zmiennej przypisanej do editBoxa wyświetla, że nie jest zdeklarowana:/ Poniżej kawałek kodu, który napisałem. Miejsce z którym ma problem oznaczyłem komentarzem. Funkcja ma być użyta w głównym oknie aby przekazać do niej tablicę z odczytanymi rekordami.
void DATA_TABLE_DLG::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EXIT_DATA_DLG, btnCloseDataDlg);
	DDX_Control(pDX, IDC_DISPLAY_RECORD, edbDisplayRecord);
}


BEGIN_MESSAGE_MAP(DATA_TABLE_DLG, CDialog)
	ON_BN_CLICKED(IDC_EXIT_DATA_DLG, &DATA_TABLE_DLG::OnBnClickedExitDataDlg)
END_MESSAGE_MAP()


// DATA_TABLE_DLG message handlers


void DATA_TABLE_DLG::OnBnClickedExitDataDlg()
{
	EndDialog(IDC_EXIT_DATA_DLG);
}
void readDataFromArray(CStringArray data)
{
	int numElements;
	int i;
	CString temp;
	
	numElements = data.GetSize();
	for (int i = 9; i <= numElements-9; i++)
	{
		temp = data[i];
		edbDisplayRecord.SetWindowTextW(temp); //mam problem ze zmienną "edbDisplayRecord"
	}

}

Wiem, że trochę się rozpisałem, ale chciałem w miarę dokładnie opisać mój problem i pokazać mniej więcej poziom wiedzy jaki reprezentuje.
Będę wdzięczny za wszelkie wskazówki, ewentualnie poprawki moich błędów.

0

No dobra co do trzeciego to już sobie poradziłem. Powód błędu był banalny: nie zaczytałem pliku nagłówkowego w tym pliku .cpp.

0
  1. Czemu nie Qt?
  1. Otwieram plik tekstowy (ważący 12MB), którego poszczególne wiersze są dodawane do tablicy klasy CStringArray. Później zajmę przetwarzaniem poszczególnych "rekordów" tablicy. Moje pytanie brzmi: jak zrobić progress bar, który będzie wskazywał postęp z otwieraniem pliku.. Kontrolka jest dodana, ale gdy próbowałem coś z nią zrobić zawieszało mi system podczas pracy programu.

Musisz wczytywać to w nowym wątku i mieć tam podpiętego Observera którego będziesz informował o postępach. Observer będzie podpięty do progressbara i będzie zmieniał jego wartość.

  1. Mam również problem z umieszczeniem zmiennych globalnych. Otóż chciałem aby część zmiennych była globalna, jak chociażby tablica, której zawartość chciałbym wykorzystać do pokazania danych w tabeli w nowym oknie dialogowym, które będzie się otwierało po wciśnięciu buttona.

ABSOLUTNIE tak nie rób. Zrób ten program jak normaly człowiek, z użyciem OOP. Zaprojektuj sensowny podział tego na klasy.

0

AD0. Tak jak mówiłem MFC został mi narzucony. Nie wiem czemu prowadzący się tak na to uparł, ale w momencie, kiedy chiałem zaproponować coś co znam troszeczkę lepiej odparł "nie" ;p

AD1.

Musisz wczytywać to w nowym wątku i mieć tam podpiętego Observera którego będziesz informował o postępach. Observer będzie podpięty do progressbara i będzie zmieniał jego wartość.

Co masz na myśli mówiąc "nowy wątek" i jak podpiąć "observera", ale tak dokładniej. Wiem...zadaje trywialne pytania, ale tak jak wspomniałem zaczynam swoją przygodę z MFC, i szczerze mówiąc nie znam wszystkich "myków".

AD2.

ABSOLUTNIE tak nie rób. Zrób ten program jak normaly człowiek, z użyciem OOP. Zaprojektuj sensowny podział tego na klasy.

OK...nie będę tak robił. Co znaczy "zrób program jak normalny człowiek". Niestety nie mam jeszcze dużej praktyki w programowaniu obiektowym, w ogóle programowaniu. No może poza programowaniem maszyn. Będę wdzięczny za wskazówki. Nie oczekuje gotowych rozwiązań, a jedynie pomocy w porządnym nauczeniu i zrozumieniu.
Odnosząc się do tego punktu i chcąc przekazać dane do nowego okna mam pewien problem. Każde okno dialogowe ma swój plik nagłówkowy oraz plik .cpp. W głównym oknie wybieram i otwieram plik tekstowy, który jest przetwarzany do postaci -> każda linia tekstu dostaje swoją pozycję w tablicy klasy CStrongArray. Pod przyciskiem "otwórz tabelę danych" jest instrukcja, która otwiera drugie okno dialogowe jak również funkcja której jako argument przekazuję tą tablicę. Oczywiście początkowo miałem z tym problem więc utworzyłem kolejną zmienną i przekazałem tablicę jako referencję, gdyż tylko tak udało mi się skompilować program, a potem uruchomić, ale niestety w polu tekstowym nie widać, żadnych informacji, a podczas zamykania okna dialogowego, program się wywala. Poniżej wkleję kod programu, może doradziłbyś coś, ewentualnie powiedział co zrobić, żeby nie robić jakiś błędów w przyszłości.
a) kawałek kodu z pliku nagłówkowego otwieranego(drugiego) okna(deklaracja klasy okna standardowa zrobiona poprzez kreatora ClassWizard), z miejscem wstawienia prototypu funkcji oraz deklaracją zmiennej podpiętej do edit boxa.

 // Dialog Data
	enum { IDD = IDD_DATA_DLG };
	void readDataFromArray(CStringArray & data);


protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

	DECLARE_MESSAGE_MAP()
public:
	CButton btnCloseDataDlg;
	afx_msg void OnBnClickedExitDataDlg();
	CProgressCtrl prbProcessingData;
	CEdit cbxDataDisplay;
};

b) kawałek kodu z pliku .cpp tego samego okna z funkcją, która miałaby wyświetlać zawartość tabeli.

void DATA_TABLE_DLG::readDataFromArray(CStringArray & data)
{
	int numElements;
	int i;
	CString temp;
	

	numElements = data.GetCount();
	prbProcessingData.SetRange(0, numElements);

	for (int i = 9; i <= numElements-9; i++)
	{
		temp = data.GetAt(i);
		cbxDataDisplay.SetWindowTextW(temp);
		prbProcessingData.SetPos(i);
	}

}

c) i kawałek kodu z głównego okna, który zawiera funkcję wywołującą drugie okno oraz przekazuje funkcji z drugiego okna jako argument poprzez referencję tablicę z danymi.

void MAIN_WINDOW::OnBnClickedDataTableBtn()
{
	DATA_TABLE_DLG dataTableDlg;
	dataTableDlg.DoModal();

	CStringArray & DataTable = arrReadedLines;
	dataTableDlg.readDataFromArray(DataTable);
}

Nie wiem czy to istotne, ale sam plik tekstowy posiada jakieś 172000 rekordów, a w założeniu ma przetwarzać pliki, które mają tych rekordów nawet ponad 1milion. Czy taki sposób przekazywania danych jest dobrą metodą? Proszę o pomoc.

0

Witam wszystkich ponownie...

Jak widać nikt nie odpowiedział, ale z problemem sobie poradziłem sam. Niestety musiałem odłożyć pracę z aplikacją na pewien czas.

  1. Czy któryś z forumowiczów programował kiedyś w MFC SDI lub MDI. Chodziło by mi o przybliżenie tego zagadnienia. Gdzie jak i co się wpisuje, aby coś się gdzieś pokazało.
  2. Czy ma ktoś może pomysł jak rysować wykresy w MFC na podstawie punktów, które odczytałem z pliku, o którym była mowa wcześniej.

Z góry dziękuję za odpowiedź

1 użytkowników online, w tym zalogowanych: 0, gości: 1