Podstawy programowania z wykorzystaniem klas MFC w Visual C++

autor: Kuba Bieszke

MFC są to stworzone przez programistów Microsoft'u klasy, które pomagają nam pisać aplikacje pod Windows. Stanowią one niezwykły pakiet wcześniej stworzonego, gotowego do użycia kodu. Na przykład, zamiast pisania nowego kodu do obsługi kolejnego okna, możemy polegać na kodzie klasy CWnd z biblioteki MFC, która zajmie się za nas wszystkimi szczegółami.

Podstawa aplikacji

Dodatkowe obiekty:

Message maps:

 

Podstawa aplikacji:

Aby rozpocząć pisanie programu tworzymy nowy projekt Win32 Application, w menu Project/Settings... klikamy na zakładce General i wybieramy z listy Use MFC in a Shared DLL. Następnie dodajemy plik *.cpp, w którym zamieszczamy kod (poniższe kody dodajemy stopniowo w kolejności w jakiej są przedstawione).

1.Aby pisać aplikacje korzystając z klas MFC należy zadeklarować na początku plik afxwin.h poleceniem:

#include <afxwin.h>

2.Kręgosłup aplikacji składa się z następującego kodu:

// Deklaracja klasy aplikacji
class CNazwaApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};

W sekcji publicznej jest odwołanie do funkcji InitInstance, gdzie zadeklarowane będą polecenia wykorzystywane przy każdym ładowaniu aplikacji.

3.Następnie kreowane jest wyjście aplikacji, w miejsce Nazwa w NazwaApp wpisujemy tytuł aplikacji:

// Stworz wyjscie dla klasy aplikacji
CNazwaApp NazwaApp;

4.Deklaracja klasy głównego okna. Tu deklarujemy wszystkie klasy użyte w naszym oknie (głównie dla obiektów, kontrolek, menu itp.)

// Deklaracja klasy glownego okna
class CNazwaWindow : public CFrameWnd
{
public:
CNazwaWindow();
};

Tutaj zadeklarowano CNazwaWindow co później posłuży do zbudowania okna.

5.Funkcja InitInstance zdeklarowana w punkcie 2.

// Funkcja InitInstance jest wywoływana
// kiedy uruchamia sie aplikacja
CBOOL NazwaApp::InitInstance()
{
m_pMainWnd = new NazwaWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}

Wyżej podane polecenia nadają nazwę naszemu nowemu oknu (m_pMainWnd) oraz zmuszają je do ukazania się.

6.Budowanie okna wywołane w punkcie 4.

// Konstrukcja klasy okna
CNazwaWindow::CNazwaWindow()
{
// Stworzenie okna
Create(NULL,
"Test",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
}

Polecenie Create służy do budowy okna: parametr 1-parametry klas okna (u nas NULL, dla domyślnych), parametr 2-Nazwa okna do wyświetlenia, parametr 3-właściwości okna (u nas okno z paskiem zawierającym przycisk mini- i maksymalizacji oraz zamknięcia X), parametr 4-położenie okna (x, y, x1, y1).

Dodatkowe obiekty:

1. Obiekt String, w którym przechowywane będą znaki dla innych obiektów.

Na początku zadeklarowanie w Deklaracji klasy głównego okna poleceniem z klas MFC: CString znaki (nadana przez nas nazwa dla tego obiektu to znaki). Teraz część kodu wygląda następująco:

// Deklaracja klasy glownego okna
class CNazwaWindow : public CFrameWnd
{
CString znaki;
public:
CNazwaWindow();
};

W konstrukcji klasy okna przyporządkowujemy napis dla naszego obiektu, np. znaki = "napis". I wykorzystując nasz obiekt zamiast wpisywania nazwy okna w drugim parametrze Create wpisujemy znaki:

// Konstrukcja klasy okna
CNazwaWindow::CNazwaWindow()
{
// Stworzenie okna
znaki = "napis";
Create(NULL,
znaki,
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
}

2.Kontrolka Edit do wpisywania tekstu. Na początku pliku trzeba zdefiniować numer Id dal naszej kontrolki, który nie może być mniejszy od 100. Teraz początek wygląda tak:

#include <afxwin.h>
#define IDB_BUTTON 100

Tutaj podobnie jak w przypadku CString - CEdit* wpisz (gdzie wpisz to nasza nazwa):

// Deklaracja klasy glownego okna
class CNazwaWindow : public CFrameWnd
{
CString znaki;
CEdit* wpisz;
public:
CNazwaWindow();
};

Kontrolkę Edit buduje się podobnie jak okno:

// Konstrukcja klasy okna
CNazwaWindow::CNazwaWindow()
{
// Stworzenie okna
znaki = "napis";
Create(NULL,
znaki,
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));

// Stworzenie kontrolki Edit
wpisz = new CEdit();
wpisz->Create(WS_CHILD|WS_VISIBLE|WS_BORDER,
CRect(200,70,300,110),
this,
IDB_EDIT2);
}

Dla wpisz deklarujemy nowy obiekt CEdit, później dla wpisz deklarujemy właściwości używając ->Crete(1 parametr-wygląd kontrolki 2 pierwsze są wymagane aby była widoczna, a trzeci otacza ją czarną linią, 2 parametr-położenie kontrolki, 3 parametr-do jakiego okna należy kontrolka, 4 parametr-nazwa kontrolki zdefiniowana na początku.

W podobny sposób budujemy CStatic, CListBox, CComboBox, CButton itp.

Message Maps:

Służą do projektowania zdarzeń, które są wykonane po spełnieniu jakiegoś warunku, przykład budujemy aplikację składającą się z obiektów MFC: CButton(nazwany button) i CEdit(edit1):

#include <afxwin.h>

#define IDB_BUTTON 100
#define IDB_EDIT1 110

// Deklaracja klasy aplikacji
class CButtonApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// Stworz wyjscie dla klasy aplikacji
CButtonApp ButtonApp;
// Deklaracja klasy glownego okna
class CButtonWindow : public CFrameWnd
{
CButton *button;
CEdit* edit1;

public:
CButtonWindow();
afx_msg void KlikButton();
DECLARE_MESSAGE_MAP()
};

// Message map
BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
ON_BN_CLICKED(IDB_BUTTON, KlikButton)
END_MESSAGE_MAP()

// Funkcja InitInstance jest wywoływana
// kiedy uruchamia sie aplikacja

BOOL CButtonApp::InitInstance()
{
m_pMainWnd = new CButtonWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// Konstrukcja klasy okna
CButtonWindow::CButtonWindow()
{
// Stworzenie okna
Create(NULL,
"Naciśnij NAPIS",
WS_OVERLAPPEDWINDOW,
CRect(0,0,400,200));

button = new CButton();
button->Create("NAPIS",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(20,20,100,100),
this,
IDB_BUTTON);

edit1 = new CEdit();
edit1->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE,
CRect(200,10,300,50),
this,
IDB_EDIT1);
}
// Funkcja do wykonania
void CButtonWindow::KlikButton()
{
edit1->SetWindowText("Nowy tekst");
}

1. Jak widać w deklaracji klasy głównego okna dodaliśmy:

afx_msg void KlikButton();
DECLARE_MESSAGE_MAP()

Co buduje funkcję KlikButton() i włącza deklarację Message maps.

2. Następna zmiana to część:

// Message map
BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
ON_BN_CLICKED(IDB_BUTTON, KlikButton)
END_MESSAGE_MAP()

w której deklarujemy na jakie zdarzenia oczekujemy. Linia pierwsza i ostatnia są stałe dodajemy coś tylko w środku, u nas ON_BN_CLICKED, czyli w razie kliknięcia, a nawias: 1 parametr-nazwa obiektu, który odbierze zdarzenie, 2 prametr-funkcja do wykonania.

3. Stworzenie funkcji do wykonania to u nas:

// Funkcja do wykonania
void CButtonWindow::KlikButton()
{
edit1->SetWindowText("Nowy tekst");
}

::KlikButton() zostało zadeklarowane w punkcie 1.

edit1->SetWindowText("Nowy tekst");

Oznacza, że dla obiektu o nazwie edit1 wywołujemy parametr lub własność, u nas zmiana tekstu.