41
Lekcija 17. Programiranje za Windows GUI 1 17. Programiranje za Windows GUI 17.1 Pristup programiranju Windows GUI programa pomoću API "C" funkcija 17.1.1 "Hello World" Da bi se na zaslonu dobio pozdrav iz naslova, u DOS okruženju bilo je dovoljno napisati jednostavan program: void main() { printf("Hello World!"); } Ekvivalent ovom programu na operacijskom sustavu Windows je sljedeći program: #include <windows.h> const char g_szClassName[] = "mojaKlasa"; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; // karakteristike prozora HWND hwnd; // identifikacija prozora MSG Msg; // poruka //Korak 1: Registriranje klase za kreiranje prozora wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Korak 2: kreiranje prozora hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "Primjer prozora", WS_OVERLAPPEDWINDOW,

17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

  • Upload
    leanh

  • View
    239

  • Download
    1

Embed Size (px)

Citation preview

Page 1: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 1

17. Programiranje za Windows GUI

17.1 Pristup programiranju Windows GUI programa pomoću

API "C" funkcija

17.1.1 "Hello World"

Da bi se na zaslonu dobio pozdrav iz naslova, u DOS okruženju bilo je dovoljno napisati

jednostavan program: void main() { printf("Hello World!"); }

Ekvivalent ovom programu na operacijskom sustavu Windows je sljedeći program:

#include <windows.h>

const char g_szClassName[] = "mojaKlasa";

int WINAPI WinMain( HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

WNDCLASSEX wc; // karakteristike prozora

HWND hwnd; // identifikacija prozora

MSG Msg; // poruka

//Korak 1: Registriranje klase za kreiranje prozora

wc.cbSize = sizeof(WNDCLASSEX);

wc.style = 0;

wc.lpfnWndProc = WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

wc.lpszMenuName = NULL;

wc.lpszClassName = g_szClassName;

wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&wc))

{

MessageBox(NULL, "Window Registration Failed!", "Error!",

MB_ICONEXCLAMATION | MB_OK);

return 0;

}

// Korak 2: kreiranje prozora

hwnd = CreateWindowEx(

WS_EX_CLIENTEDGE,

g_szClassName,

"Primjer prozora",

WS_OVERLAPPEDWINDOW,

Page 2: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 2

CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,

NULL, NULL, hInstance, NULL);

if(hwnd == NULL) {

MessageBox(NULL, "Window Creation Failed!", "Error!",

MB_ICONEXCLAMATION | MB_OK);

return 0;

}

// Korak 3. Prokaz prozora

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

// Korak 4: Petlja koja procesira poruke

while(GetMessage(&Msg, NULL, 0, 0) > 0)

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

return Msg.wParam;

}

// Korak 5: funkcija koja obraduje poruke pristigle za prozor

LRESULT CALLBACK

WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT ps;

RECT rect;

switch(msg)

{

case WM_PAINT:

hdc = BeginPaint(hwnd,&ps);

GetClientRect(hwnd,&rect);

DrawText(hdc,"Hello world!",-1,&rect,

DT_SINGLELINE | DT_CENTER | DT_VCENTER);

EndPaint(hwnd,&ps);

break;

case WM_CLOSE:

DestroyWindow(hwnd);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hwnd, msg, wParam, lParam);

}

return 0;

}

Page 3: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 3

Slika 1 – Jednostavni prozor

Funkciju main() zamijenila je funkcija WinMain(), kojom započima svaki Windows

program. Grafičko sučelje Windows-a temelji se na grafičkom elementu – prozoru - po kojem

su i dobili ime. To je uokvirena pravokutna površina , koja se može pomicati na zaslonu i

kojoj se može mijenjati veličina. U zaglavlju prozora zapisan je naziv (naslov) prozora,

osnovni sistemski meni i gumbi za povećanje, minimiziranje i zatvaranje prozora. Ova

funkcionalnost je podržana od samog operacijskog ustava, i ne mora se posebno

implementirati u kodu (iako se može promijeniti predefinirana svojstva prozora).

17.1.2 Kreiranje prozora

Za kreiranje prozora koristi se funkcija CreateWindowEx, primjerice:

CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"Primjer

prozora",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,NULL,

NULL, hInstance, NULL);

stvata prozor imena "Primjer prozora".

Prvi argument ove funkcije je konstanta WS_EX_CLIENTEDGE koja definira izgled okvira

prozora, drugi je ime klase na kojoj se prozor temelji, a treći argument je string koji sadrži

tekst koji će biti ispisan u zaglavlju prozora kao njegov naslov. Konstanta

WS_OVERLAPPEDWINDOWS definira izgled i ponašanje prozora, a definirana je u

WINUSER.H datoteci. Sljedeća četiri parametra su koordinate ishodišta prozora X i Y te

širina i visina prozora. Parametri koji sljede su handle na prozor roditelj (handle je

cjelobrojna vrijednost koja jednoznačno definira aplikacijske komponente u operacijskom

sustavu), handle na meni, handle na instancu aplikacije, i pokazivač na podatke koji se

kreiraju prilikom stvaranja prozora.

Na početku funkcije WinMain(), deklarirana je varijabla wc tipa WNDCLASSEX

strukture. To je drugi argument pri pozivu funkcije CreateWindowEx(). WNDCLASSEX

struktura sadrži članove koji opisuju opće značajke prozora: veliku i malu ikonu, meni, boju

pozadine, stil prozora itd. ... Ta klasa, prije nego se upotrijebi za stvaranje prozora, mora se

registrirati u operacijskom sustavu, koristeći funkciju RegisterClassEx(). Tako registrirana

klasa poslije može biti upotrijebljena za stvaranje proizvoljnog broja prozora temeljenih na

njoj (tj. prozora s istim karakteristikama). Da bi, tako stvoreni prozor bio prikazan na zaslonu,

pozivaju se funkcije ShowWindow() i UpdateWindow().

U DOS konzolnom okruženju, kada je tipkovnica bila osnovni ulazni uređaj,

interakcija s korisnikom i unos podataka svodio se na testiranje pritisnute tipke na tipkovnici,

ili parsiranje unesenog stringa. U grafičkog okružju, gdje tekst nije glavni nositelj informacija,

Page 4: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 4

i kad se uz tipkovnicu pojavljuje i miš kao ravnopravan ulazni uređaj, način komunikacije na

relaciji korisnik – aplikacija – operacijski sustav se promijenio.

17.1.3 Windows procedure i poruke

Postavlja se pitanje kako prozor, nakon što je kreiran i prikazan na zaslonu, prima

korisnički unos bilo tipkovnicom bilo mišem. U Windowsima je taj problem riješen

sistemom poruka. Operacijski sustav prati sve aktivnosti ulaznih jedinica, te šalje

odgovarajuće poruke prozorima na koje se pojedini unos odnosi (klik mišem, prelazak

kursorom preko prozora, pritisak tipke na tipkovnici). Za svaki prozor Windowsi kreiraju red

poruka, iz kojeg petlja: while(GetMessage(&Msg, NULL, 0, 0) > 0)

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

uzima jednu po jednu poruku i prosljeđuje je odgovarajućoj proceduri na daljnju obradu.

Funkcija GetMessage() uvijek vraća pozitivnu vrijednost 0 u slučaju kada je iz reda

dohvaćena poruka WM_QUIT , ili –1 u slučaju greške. WM_QUIT (WM- windows

message) signalizira izlazak iz programa ( klik na Close gumb, ili Alt+F4). U tom slučaju

while petlja se prekida, izlazi se iz WinMain() funkcije i program se prekida.

Treći član WNDCLASSEX strukture, deklariran kao lpfnWndproc (long pointer to

function), definira funkciju – windows proceduru - koja je zadužena za obradu svih pristiglih

poruka za prozore koji su kreirani na temelju te klase. Ta funkcija sadrži svu logiku aplikacije.

Realizacija windows procedure za prihvat događaja temelji se na switch-case strukturi, u kojoj

se u ovisnosti o vrsti poruke, događa neka akcija. Npr. ako želimo da se, kad korisnik klikne

na naš prozor, prikaže neka poruka, kodu s početka poglavlja u switch-case strukturi funkcije

WndProc treba dodati sljedeći kod: case WM_LBUTTONDOWN:

MessageBox(hwnd,"Prozor je kliknut" , "Poruka", MB_ICONINFORMATION);

break;

Ovo je jedan od najjednostavnijih primjera korisničke interakcije s aplikacijom i ne

odražava pravu složenost strukture Windows programa. I za relativno jednostavna korisnička

sučelja, ako se ne koriste posebne grafičke biblioteke, potrebno je detaljno poznavanje

funkcioniranja operacijskog sustava, načina slanja i obrade pristiglih poruka, brojnih API

funkcija i njihovih još brojnijih parametara. To u konačnici čini programiranje grafičkog

sučelja, putem direktnih Win32 API funkcijskih poziva, vrlo složenim zadatkom. Da bi se

doskočilo tom problemu razvijena su brojne biblioteka i razvojne okoline, MFC, Visual Basic

ili Borland Delphi, koje na više ili manje uspješan način enkapsuliraju složenost unutaranje

strukture Windows-a.

17.1.4 Kompajliranje i izvršenje programa

Kompajliranje programa se provodi pomoću IDE Visual Studio. Projekt se oformi na sljedeći

način:

Page 5: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 5

1) Komandom File->New->Project otvori se dijalog u kojeme se odabebre Project

Type: Win32 i Project->template : Win32 project. Odredi se staza foldera za

projekt i upiše ime projekta, primjerice "WinHello". Potvrdi se odabir s dugmetom

OK.

2) Otvori se novi dijalog u kojem se odabere dugme 'Next' i zatim se odabere

stavka 'Windows application' , postavi chek-box Empty project i klikne dugme

Finish.

3) U folder projekta kopiraje datoteku "WinHello.cpp" i dodajte projektu u

"Solution Explorer" na način da kliknete desni miš na ime projekta. To otvara meni

u kojem se komandom Add->Existing Item doda ova datoeka.

4) Kompajliranje se provodi komandom Project->Build

5) Kada je program kompajliran, može se izvršiti komandom Debug->Start

without Debugging.

17.2 Primjer izrade programa pomoću IDE Visual Studio i MFC

klasa

Upoznat ćemo se s MFC klasama i kako se pomoću njih piše GUI program. MFC

(Microsoft Foundation Classes) predstavlja skup klasa koje potpuno enkapsuliraju API

Win32. Većina današnjih profesionalnih programa je napisana pomoću ove bibilioteke.

17.2.1 Prvi program s MFC bibliotekom

Da bi napravili program pomoću MFC biblioteke potrebno je da se deklariraju barem

dvije klase: Jedna klasa koja predstavlja aplikaciju ( program) – nazovimo je sada

CMfcHelloApp i druga klasa koja predstavlja prozor (ili okvir) u kojem se ispisuje grafički

oblik programa – nazovimo je CmainFrame. Također ćemo upoznati klasu CDC pomoću koje

se vrše grafičke operacije (crtanje, bojanje i ispis teksta), te kako se deklariraju poruke

prozoru.

Korisničke klase su deklarirane u datoteci „MfcHello.h“:

#include <afxwin.h>

class CMainFrame : public CFrameWnd

{

public:

CMainFrame();

~CMainFrame();

afx_msg void OnPaint();

DECLARE_MESSAGE_MAP()

};

class CMfcHelloApp : public CWinApp

{

public:

virtual BOOL InitInstance();

};

Page 6: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 6

CmainFrame nasljeđuje MFC klasu CframeWnd, CMfcHelloApp nasljeđuje MFC klasu

CwinApp.

Kod programa je u datoteci „MfcHello.cpp“

#include "MFCHello.h"

CMfcHelloApp MyApplication;

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

ON_WM_PAINT()

END_MESSAGE_MAP()

BOOL CMfcHelloApp::InitInstance()

{

CMainFrame* pFrame = new CMainFrame;

m_pMainWnd = pFrame;

pFrame->ShowWindow(SW_SHOW);

pFrame->UpdateWindow();

return TRUE;

}

CMainFrame::CMainFrame()

{

Create(NULL,_T("MFC Skeleton"),

WS_OVERLAPPEDWINDOW,CRect(0,0,400,200),NULL);

}

CMainFrame::~CMainFrame()

{}

void CMainFrame::OnPaint()

{

CPaintDC dc(this);

dc.TextOut(100,50,"Hello World");

}

Kompajliranje programa se provodi pomoću IDE Visual Studio. Projekt se oformi na sljedeći

način:

1) Komandom File->New->Project otvori se dijalog u kojeme se odabebre Project

Type: Win32 i Project->template : Win32 project. Odredi se staza foldera za

projekt i upiše ime projekta, primjerice MfcHello. Potvrdi se odabir s dugmetom

OK.

2) Otvori se novi dijalog u kojem se odabere dugme Next i zatim se odabere

stavka 'Windows application' , postavi chek box Empty project i klikne dugme

Finish.

3) U folder projekta kopiraje datoteke "MfcHello.cpp" i "MfcHello.h" i dodajte

projektu u "Solution Explorer" na način da kliknete desni miš na ime projekta. To

otvara meni u kojem se komandom Add->Existing Item dodaju ove datoeke.

4) Još je potrebno u dijalogu konfiguracije, koji se otvori komandom Project-

>Properties->Configuration properties odabrat stavkui: Use of MFC -> Use MFC in

static Library

Page 7: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 7

5) Kompajliranje se provodi komandom Project->Build

6) Kada je program kompajliran, može se izvršiti komandom Debug->Start

without Debugging.

Dobije se prikaz:

U programu je najprije je deklarirana aplikacija MyApplication kao objekt klase

CMfcHelloApp.Zatim je u sekciji deklaracije poruka

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

ON_WM_PAINT()

END_MESSAGE_MAP()

označeno da će prozor primati poruku ON_WM_PAINT(). Kada se to ostvari automatski će

biti pozvana funkcija za crtanje: CMainFrame::OnPaint().

Pored ove poruke često se koriste sljedeće poruke: ON_WM_LBUTTONDOWN – klik na lijevi tipku miša

ON_WM_RBUTTONDOWN - klik na desnu tipku miša

ON_WM_MOUSEMOVE – poruka da je pomaknut miš

ON_WM_KEYDOWN – pritisnuta tipka na tipkovnici

ON_BN_CLICKED - pritisnuto dugme u grafičkom sučelje

ON_COMMAND – odabrana stavka menija

Moraju biti definirane i pripadne funkcije (to će biti objašnjeno kasnije)

U funkciji CMfcHelloApp::InitInstance() vrši se dinamičko stvaranje prozora:

CMainFrame* pFrame = new CMainFrame;

čiji se pokazivač pFrame sprema u aplikaciju, klao glavni prozor.

m_pMainWnd = pFrame;

Naredbe pFrame->ShowWindow(SW_SHOW);

pFrame->UpdateWindow();

prikazuju prozor i osvježavaju prikaz (zapravo se pošalje poruka WM_PAINT).

Crtanje grafičkog sadržaja vrši se u funkciji OnPaint(). U toj funkciji se za potrebe grafičkih

operacije otvara se objekt klase CPaintDC, i pomoću njega se ispisuje string "Hello World"

na koordinati prozora x=100, y=50.

Page 8: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 8

CPaintDC dc(this);

dc.TextOut(100,50,"Hello World");

CDC je temeljna klasa za grafički izlaz, a iz nje se definiraju izvedene klase: CWindowDC - Device context for the whole window

CPaintDC - Device context for the server area in Windows

CClientDC - Device context for the client area in Windows

CMetaFileDC - Device context for representing a Windows metafile for presenting pictures

Koordinatni sustav u Windows-ima je definiran tako da pixel u gornjem, lijevom kutu

predstavlja ishodite (x=0, y=0), a pixel u donjem, desnom kutu određuje maksimalnu

vrijednost x i y koordinate:

Svaki pixel je određen položajem i bojom. Za postavljanje boje (tip COLORREF), koristi se

makro RGB(r,g,b) - koji kombinira r- red, g-green, i b-blue indikatore, svaki u rasponu

od 0 do 255.

Primjerice: COLORREF crvena = RGB(255,0,0)

Odnos komponenti (crvene, zelene i plave boje) pri postavljanju proizvoljne boje.

U grafičkim operacijama intezivno se koriste klase:

Page 9: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 9

CPen – određuje boju i oblik pera za crtanje

CBrush – određuje oblik četke (šrafure i boje pozadine)

CFont – određuje font

CPoint – definira točku u 2D ravnini (članovi: x,y

CSize – definira veličinu u 2D ravnini (članovi: sx-širina, sy-visina)

CRect – definira pravokutnik u 2D ravnini (clanovi: x,y, width, height)

Funkcije koje su enkapsulirane u CDC klasi se često nazivaju GDI funkcijama (GDI –

graphical device interface). Često korištene funkcije su:

SelectObject(GDIobjekt) – GDIobjekt postaje aktivni objekt (pen, brush ili font)

Arc() – crta luk

Ellipse() – crta elipsi i kružnicu

Rectangle() – crta pravokutnik aktivnim perom i ispunjava ga aktivnom četkom

FillRect() - Fills a rectangular region with the indicated color

FillSolidRect() - Creates a rectangle using the specified fill color

GetPixel() - Gets the pixel value at the current position

SetPixel() - Draws a pixel according to the chosen color

LineTo() - Draws a line to the given coordinates

MoveTo() - Sets the current pen position to the indicated coordinates

Polyline() - Draws a series of lines passing through the given points

Za ispis teksta se koristi funkcije : SetBkColor() - Sets the background color of the text

SetTextColor() - Sets the color for the text

TextOut() - Displays a text message at the indicated coordinates

BitBlt() - Copies a bitmap to the current device context

Evo primjera primjene CDC operacija. U prethodnom program ćemo zamijeniti funkciju

OnPaint() sa sljedećom funkcijom:

void CMainFrame::OnPaint() { // Definiraj device context dc CPaintDC dc(this); // crtaj pravokutni okvir: //Najprije odredi tip četke za bojane unutarnje povrsine pravokutnika CBrush brushGray(RGB(192, 192, 192)); //Zatim postavi tu četku u dc i zapamti prethodnu četku

CBrush* brushOld = dc.SelectObject(&brushGray); //Zatim odredi tip pera za crtanje CPen penBlue(PS_SOLID,5,RGB(0,0,255)); //Zatim postavi to pero u device context dc CPen *oldPen = dc.SelectObject(&penBlue); //formiraj object klase CRect //(za definiranje koordineta pravokutnika koristi // objekte klase CPoint i CSize) CRect rc; rc=CRect(CPoint(10,30),CSize(300,200));

Page 10: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 10

// nacrtaj pravokutnik dc.Rectangle(rc); // Zatim ispiši text // definiraj boju pozadine i boju teksta dc.SetBkColor(RGB(192, 192, 192)); // gray background dc.SetTextColor(RGB(255,0,0)); // red text // ispiši tekst dc.TextOut(50,80, "Hello World"); // first message // i dodatni tekst zelene boje dc.SetTextColor(RGB(0,255,0)); // green text dc.TextOut(50,115, "MFC pomaze!"); // second message dc.SelectObject(brushOld); dc.SelectObject(oldPen); }

Dobije se prikaz:

17. 2.2 Glavne Klase u MFC biblioteci

Tipični windows program, pored definiranog glavnog prozora, ima mnoštvo definiranih

podprozora koji predstavljaju tzv. windows kontrole (menu bar, dijalog bar, status bar

dugmad, list box, edit box itd.) Za svaki od ovih prozora predviđena je posebna klase.

Najčešće koristene MFC klase su prikazane na sljedećoj slici.

Page 11: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 11

Hijerarhija “glavnih” MFC klasa

Često se koristi i klasa CString – za rad sa stringovima.

CFile se koristi za pristup datotekama.

U sljećem odjeljku će biti pokazano kako se pomoću IDE Visual Studio, tzv. vizuelnim

programiranjem kreira izgled i funkcionalnost tipičnog Windows programa. Također upoznat

ćemo programski oblik izgradnje softvera koji se naziva Dokument-View arhitektura.

Page 12: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 12

17.2.3 Document-View Arhitektura

MFC se temelji na tzv. Document-View programskoj arhitekturi.

CWinApp - aplikacijaCFrameWnd

CMenu

CStatusBar

CToolbar

CView

prikazuje dokument u

grafičkom obliku na

ekranu

CDocument

sadržava podatke

koje sprema na disk i/ili šalje u CView

Disk

Distributor poruka

za

Frame

View

Document

Cdialog, CDialogBar

CEdit ,CButton,

CListBox, CCombo

CStatic, itd.

Slika 2.

CWinApp je klasa kojom se generira aplikacija. Iz nje se kreiraju ostali objekti i vrši slanje

poruka.

CDocument klasa stvara objekte koji sadržavaju podatke koji se spremaju na disk (u tu svrhu

se koristi klasa CArchive) ili se u grafičkom obliku prikazuju u nekom prozoru.

CView klasa kontrolira grafički prozor koji je na raspolaganju korisniku (tzv. klijentu)

CFrameWnd je prozor oblika okvira koji sadrži objekte klase CView, te prozore za izbornik,

status bar, toolbar i dijalog bar.

CDialog klasa služi stvaranju dijaloga za unos podataka. Dijalozi sadrže različite

elemente, tzv. kontrole: CButton- botune, CListBox – liste, CCombo – kombo

liste, CEdit – prozore za unos teksta itd.

Page 13: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 13

17.2.3 Formiranje kostura MDI programa

Kreiranje programa se većim dijelom provodi vizulenim programiranjem pomoću IDE

Visual Studio. Omogućeno je generiranje i početnog kôda Windows programa. Pozivom

menija; New->Project dobije se dijalog u kojeg se unosi staza i ime projekta:

Uočite da je odabrana ikona koja pokazuje da će biti generiran program koji koristi

MFC klase.

Unesite:

Name: Fesb

Location: neka postojeća staza gdje spremate izvorni kod

Ako upišete c:\src Visual Studio će kreirati direktorij c:\src\Fesb, u kojeg će biti

upisane sve datoteke koje pripadaju projektu.

Nakon unosa, pritisnite botun OK. Tada ćete dobiti dijalog za postavljanje tipa

aplikacije:

Page 14: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 14

Četiri su temeljna tipa:

SDI - single document ( jedan dokument koji se prikazuje u jednom prozoru)

MDI – multiple document ( više dokumenta svaki sa svojim prozorom)

Multiple top level (a la Internet Explorer)

Dialog ( za jednostavne programe, koji ne obrađuju komplicirane podatke)

Odaberite drugu opciju, koja je tipična za većinu windows programa, i odaberite

standardnu MFC Document /View arhitekturu programa.

Nako pritiska botuna Finish, pojavljuje se treći dijalog u kojeg se unose podaci o sučelju

s korisnikom:

Page 15: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 15

Nakon pritiska botuna Finish: Visual Studio 7 generira 19 datoteka koje pridjeljuje

projektu. Pregled tih datoteka se dobije u "Solution" prozoru:

Korištene klase – hijerarhija

MFC klase -> ova aplikacija

CObject

CCmdTarget

CWinApp -> CFesbApp(u Fesb.Cpp)

CWnd

CFrameWnd

CChildFrame -> ChildFrm.cpp

CMDIFrameWnd -> MainFrm.Cpp

CWnd

CWiew ->CFesbView

CDocument ->CFesbDoc

CMDIDocument

CDialog

CAboutDlg ->Fesb.cpp

CControlBar

CToolBar -> MainFrm.Cpp

CStatusBar -> MainFrm.Cpp

Page 16: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 16

Kompilirajte program s komandom menija:

Project->Build Fesb

Zatim pozovite izvršenje programa komandom menija:

Project->Execute without Debug

Dobit ćete sljedeći izgled programa:

Dalje će biti pokazano:

kako korisnik u generirane datoteke umeće vlastiti kod.

kako podatke zapisuje u CDocument

kako grafički prikazuje sadržaj dokumenta u CView

kako povezuje komande – miša, tipkovnice, menija – s sistemom razmjene poruka

kako generira različite dijaloge

Najprije upoznajmo "glavni program", kako ga je generirao Visual studio

// Fesb.h : main header file for the Fesb application

#pragma once

#include "resource.h" // main symbols

// CFesbApp:See Fesb.cpp for the implementation of this class

class CFesbApp : public CWinApp

{

public:

CFesbApp();

// Overrides

public: virtual BOOL InitInstance();

// Implementation

afx_msg void OnAppAbout();

DECLARE_MESSAGE_MAP()

};

Page 17: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 17

extern CFesbApp theApp;

// Fesb.cpp : Defines the class behaviors for the application.

//

#include "stdafx.h"

#include "Fesb.h"

#include "MainFrm.h"

#include "ChildFrm.h"

#include "FesbDoc.h"

#include "FesbView.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CFesbApp sustav razmjene poruka

BEGIN_MESSAGE_MAP(CFesbApp, CWinApp)

ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

// Standard file based document commands

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

// Standard print setup command

ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

END_MESSAGE_MAP()

// CFesbApp construction

CFesbApp::CFesbApp()

{

// TODO: add construction code here,

// Place all significant initialization in InitInstance

}

// The one and only CFesbApp object

CFesbApp theApp;

// CFesbApp initialization

BOOL CFesbApp::InitInstance()

{

// InitCommonControls() is required on Windows XP if an application

// manifest specifies use of ComCtl32.dll version 6 or later to

// enable visual styles. Otherwise, any window creation will fail.

InitCommonControls();

CWinApp::InitInstance();

// Initialize OLE libraries

if (!AfxOleInit())

{

AfxMessageBox(IDP_OLE_INIT_FAILED);

return FALSE;

}

AfxEnableControlContainer();

// Standard initialization

Page 18: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 18

// If you are not using these features and wish to reduce the size

// of your final executable, you should remove from the following

// the specific initialization routines you do not need

// Change the registry key under which our settings are stored

// TODO: You should modify this string to be something appropriate

// such as the name of your company or organization

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

// Load standard INI file options (including MRU)

LoadStdProfileSettings(4);

// Register the application's document templates. Document

templates

// serve as the connection between documents, frames and views

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_FesbTYPE,

RUNTIME_CLASS(CFesbDoc),

RUNTIME_CLASS(CChildFrame), // custom MDI child frame

RUNTIME_CLASS(CFesbView));

AddDocTemplate(pDocTemplate);

// create main MDI Frame window

CMainFrame* pMainFrame = new CMainFrame;

if (!pMainFrame->LoadFrame(IDR_MAINFRAME))

return FALSE;

m_pMainWnd = pMainFrame;

// call DragAcceptFiles only if there's a suffix

// In an MDI app, this should occur immediately after

// setting m_pMainWnd

// Parse command line for standard shell commands, DDE, file open

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

// Dispatch commands specified on the command line.

// Will return FALSE if

// app was launched with

// /RegServer, /Register, /Unregserver or /Unregister.

if (!ProcessShellCommand(cmdInfo))

return FALSE;

// The main window has been initialized, so show and update it

pMainFrame->ShowWindow(m_nCmdShow);

pMainFrame->UpdateWindow();

return TRUE;

}

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// Dialog Data

enum { IDD = IDD_ABOUTBOX };

protected:

virtual void DoDataExchange(CDataExchange* pDX);

// Implementation

protected:

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

Page 19: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 19

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

END_MESSAGE_MAP()

// App command to run the dialog

void CFesbApp::OnAppAbout()

{

CAboutDlg aboutDlg;

aboutDlg.DoModal();

}

// CFesbApp message handlers

Najvažnija fukcija CFesbApp klasi je BOOL InitInstance() kojom se starta program.

U njoj je najvažniji dio:

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_FesbTYPE,

RUNTIME_CLASS(CFesbDoc),

1. RUNTIME_CLASS(CChildFrame), // custom MDI child frame

RUNTIME_CLASS(CFesbView));

AddDocTemplate(pDocTemplate);

// create main MDI Frame window

2. CMainFrame* pMainFrame = new CMainFrame;

if (!pMainFrame->LoadFrame(IDR_MAINFRAME))

return FALSE;

m_pMainWnd = pMainFrame;

3. pMainFrame->ShowWindow(m_nCmdShow);

pMainFrame->UpdateWindow();

Prvo se formira veza između dokumenta (CFesbDoc), i prozora u kojem će se grafički

prikazati njegov sadržaj (CChildFrame i CView).

Zatim se inicira glavni MDI prozor i konačno se prikazuje sve prozore koje sarži taj

glavni prozor.

Za sada, ne morate znati funkcionalnost ovog dijela programa.

MAIN FRAME je prozor koji osim prozora za prikaz dokumenata sadrži menije,

status bara i toolbar.

// MainFrm.h : interface of the CMainFrame class

//

#pragma once

class CMainFrame : public CMDIFrameWnd

{

DECLARE_DYNAMIC(CMainFrame)

public:

Page 20: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 20

CMainFrame();

// Attributes

public:

// Operations

public:

// Overrides

public:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

// Implementation

public:

virtual ~CMainFrame();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected: // control bar embedded members

CStatusBar m_wndStatusBar;

CToolBar m_wndToolBar;

// Generated message map functions

protected:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

DECLARE_MESSAGE_MAP()

};

Deklaracija CStatusBar m_wndStatusBar;

CToolBar m_wndToolBar;

formira dva objekta koji predstavljaju status bar i toolbar. Oni se iniciraju u funkciji

CMainFrame::OnCreate

// MainFrm.cpp : implementation of the CMainFrame class

//

#include "stdafx.h"

#include "Fesb.h"

#include "MainFrm.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)

ON_WM_CREATE()

END_MESSAGE_MAP()

static UINT indicators[] =

{

ID_SEPARATOR, // status line indicator

ID_INDICATOR_CAPS,

ID_INDICATOR_NUM,

Page 21: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 21

ID_INDICATOR_SCRL,

};

// CMainFrame construction/destruction

CMainFrame::CMainFrame()

{ // TODO: add member initialization code here

}

CMainFrame::~CMainFrame()

{

}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)

return -1;

if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE

| CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |

CBRS_SIZE_DYNAMIC) ||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators,

sizeof(indicators)/sizeof(UINT)))

{

TRACE0("Failed to create status bar\n");

return -1; // fail to create

}

// Delete these 3 lines if you don't want the toolbar to be dockable

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

return 0;

}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CMDIFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

return TRUE;

}

// CMainFrame diagnostics

#ifdef _DEBUG

void CMainFrame::AssertValid() const

{ CMDIFrameWnd::AssertValid();

}

void CMainFrame::Dump(CDumpContext& dc) const

{ CMDIFrameWnd::Dump(dc);

Page 22: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 22

}

#endif //_DEBUG

17.2.4 CHILD FRAME - je okvir za prikaz pojedinog dokumenta

// ChildFrm.h : interface of the CChildFrame class

//

#pragma once

class CChildFrame : public CMDIChildWnd

{

DECLARE_DYNCREATE(CChildFrame)

public:

CChildFrame();

// Attributes

public:

// Operations

public:

// Overrides

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

// Implementation

public:

virtual ~CChildFrame();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

// Generated message map functions

protected:

DECLARE_MESSAGE_MAP()

};

// ChildFrm.cpp : implementation of the CChildFrame class

//

#include "stdafx.h"

#include "Fesb.h"

#include "ChildFrm.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CChildFrame

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)

END_MESSAGE_MAP()

Page 23: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 23

// CChildFrame construction/destruction

CChildFrame::CChildFrame()

{

// TODO: add member initialization code here

}

CChildFrame::~CChildFrame()

{

}

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying the

CREATESTRUCT cs

if( !CMDIChildWnd::PreCreateWindow(cs) )

return FALSE;

return TRUE;

}

// CChildFrame diagnostics

#ifdef _DEBUG

void CChildFrame::AssertValid() const

{

CMDIChildWnd::AssertValid();

}

void CChildFrame::Dump(CDumpContext& dc) const

{

CMDIChildWnd::Dump(dc);

}

#endif //_DEBUG

// CChildFrame message handlers

17.2.5 Klasa CFesbDoc sadrži podatke dokumenta koji se obrađuje

Dodat ćemo podatke u string m_text:

1. CString m_text;

kojeg ćemo inicijalizirati u konstruktoru na vrijednost "Hello World", i klasu CPoint

2. CPoint m_pos;

koja sadrževa poziciju točke (u x,y koordinatana, koje iniciramo na 0,0)

// FesbDoc.h : interface of the CFesbDoc class

#pragma once

class CFesbDoc : public CDocument

{

protected: // create from serialization only

CFesbDoc();

Page 24: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 24

DECLARE_DYNCREATE(CFesbDoc)

// Attributes

public:

// Operations

public:

// Overrides

public:

virtual BOOL OnNewDocument();

virtual void Serialize(CArchive& ar);

// Implementation

public:

virtual ~CFesbDoc();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// Generated message map functions

protected:

DECLARE_MESSAGE_MAP()

// dodano

public:

CString m_text;

CPoint m_pos;

};

17.2.6 Klasa CView se koristi za ispis u klijentovom prozoru ChildFrm okvira

Dodajmo Klasi CView dva člana , za određivanje boje ispisa teksta i linija

COLORREF m_txtColor;

COLORREF m_penColor;

// FesbView.h : interface of the CFesbView class

//

#pragma once

class CFesbView : public CView

{

protected: // create from serialization only

CFesbView();

DECLARE_DYNCREATE(CFesbView)

// Attributes

public:

CFesbDoc* GetDocument() const;

Page 25: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 25

// Operations

public:

// Overrides

public:

virtual void OnDraw(CDC* pDC); // overridden to draw this view

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Implementation

public:

virtual ~CFesbView();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// Generated message map functions

protected:

DECLARE_MESSAGE_MAP()

// dodano

COLORREF m_txtColor;

COLORREF m_penColor;

};

#ifndef _DEBUG // debug version in FesbView.cpp

inline CFesbDoc* CFesbView::GetDocument() const

{ return reinterpret_cast<CFesbDoc*>(m_pDocument); }

#endif

Crtanje se vrši u predefiniranoj virtualnoj funkciji OnDraw(CDC *pDC) (pDC

je pokazivač na "device context – klasu" koja sadrži stanje grafičkog pogona – boju,

pen, rutine za ispis teksta, crtanje linija i poligona )

Mi ćemo dodati funkcionalnost kojom se u "iscrtava" tekst koji sadrži dokument i

ispisuje linija preko dijagonale klijentovog prozora. (Taj dio kôda je napisan "bold")

// FesbView.cpp : implementation of the CFesbView class

#include "stdafx.h"

#include "Fesb.h"

#include "FesbDoc.h"

#include "FesbView.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CFesbView

IMPLEMENT_DYNCREATE(CFesbView, CView)

BEGIN_MESSAGE_MAP(CFesbView, CView)

Page 26: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 26

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

END_MESSAGE_MAP()

// CFesbView construction/destruction

CFesbView::CFesbView()

{ // TODO: add construction code here

m_txtColor = RGB(0,0,0); // crna

m_penColor = RGB(128,0,0); // crvena

}

CFesbView::~CFesbView()

{}

// CFesbView drawing

void CFesbView::OnDraw(CDC* pDC)

{

CFesbDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

//ispisi text

pDC->SetTextColor(m_txtColor);

pDC->TextOut(pDoc->m_pos.x,pDoc->m_pos.y,pDoc->m_text);

//nacrtaj liniju dijagonalno preko cijelog prikaza

CRect r;

GetClientRect(&r);

CPen pen;

pen.CreatePen(PS_SOLID,1,m_penColor);

CPen *oldpen= pDC->SelectObject(&pen);

pDC->MoveTo(r.left,r.bottom);

pDC->LineTo(r.right,r.top);

pDC->SelectObject(oldpen); // vrati staro stanje

}

BOOL CFesbView::PreCreateWindow(CREATESTRUCT& cs)

{ // TODO: Modify the Window class by modifying the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

// CFesbView printing

BOOL CFesbView::OnPreparePrinting(CPrintInfo* pInfo)

{ // default preparation

return DoPreparePrinting(pInfo);

}

void CFesbView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{ // TODO: add extra initialization before printing

}

void CFesbView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{ // TODO: add cleanup after printing

}

// CFesbView diagnostics

Page 27: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 27

#ifdef _DEBUG

void CFesbView::AssertValid() const

{ CView::AssertValid();

}

void CFesbView::Dump(CDumpContext& dc) const

{ CView::Dump(dc);

}

CFesbDoc* CFesbView::GetDocument() const // non-debug version is

inline

{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFesbDoc)));

return (CFesbDoc*)m_pDocument;

}

#endif //_DEBUG

Interesira nas kako se vrši korisnička interakcija pomoću miša, tipkovnice, menija i

dijaloga .

17.2.7. Interakcija pomoću miša i tipkovnice

Za svaku interaktivnu klasu, u ovom

slučaju CView:

"Properties prozor" – omogućuju

generiranje koda za prihvat poruka

Lijevo je popis standardnih poruka,

kojima se može pridijeliti funkcija (desno)

koja će se izvršiti kada prozor primi tu

poruku.

Mi ćemo obraditi poruke

WM_KEYDOWN – pritisnuta tipka

WM_LBUTTONDOWN – pritisnut

lijevi botun na mišu

za koje e generiraju funkcije:

OnKeyDown() – pritisnuta tipka

OnLButtonDown() – pritisnut lijevi

botun miša

Generirane su dvije funkciju u CView:

void CFesbView::OnLButtonDown(UINT nFlags, CPoint point)

{ // TODO: Add your message handler code here and/or call default

Page 28: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 28

CView::OnLButtonDown(nFlags, point);

}

void CFesbView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{ // TODO: Add your message handler code here and/or call default

CView::OnKeyDown(nChar, nRepCnt, nFlags);

}

Zadatak: napisati program koji će reagirati na ova dva događaja:

1. Pritisnut lijevi botun miša Akcija: koordinate miša zapiši u koordinate ispisa teksta i

obnovi prikaz na ekranu

2. Pritisak kursorskih tipki (strelica) - koje imaju "defines": VK_UP, VK_DOWN, VK_RIGHT, VK_LEFT

Akcija: pomakni ispis teksta za jedno mjesto u smjeru strelice

void CFesbView::OnLButtonDown(UINT nFlags, CPoint point)

{

CFesbDoc* pDoc = GetDocument();

pDoc->m_pos = point; // point sadrži koordinate miša

Invalidate(); // poruka da se treba obnoviti crtanje View-a

CView::OnLButtonDown(nFlags, point);

}

void CFesbView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

CFesbDoc* pDoc = GetDocument();

CPoint curr_pos = pDoc->m_pos;

switch(nChar)

{

case VK_UP: curr_pos.y--; break;

case VK_DOWN: curr_pos.y++;break;

case VK_LEFT: curr_pos.x--; break;

case VK_RIGHT: curr_pos.x++;break;

}

// osiguraj se da je ispis u klijentovom prozoru

CRect r;

GetClientRect(&r);

if(curr_pos.y > r.top && curr_pos.y < r.bottom)

pDoc->m_pos.y = curr_pos.y;

if(curr_pos.x > r.left && curr_pos.x < r.right)

pDoc->m_pos.x = curr_pos.x;

Invalidate(); // poruka da se treba obnoviti crtanje View-a

CView::OnKeyDown(nChar, nRepCnt, nFlags);

}

Ponovo kompilirajte program i provjerite da li se izvršava prema predviđenim akcijama.

Uočite da je Visual studio u FesbView.h generirao dvije deklaracije

Page 29: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 29

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

Prefiks afx_msg je oznaka kompilatoru da se ova funkcija koristi kao "event handler"

Implementacija ovih funkcija, i njihova veza s "događajima" (event handler) je u

datoteci FesbView.cpp, kako slijedi:

BEGIN_MESSAGE_MAP(CFesbView, CView)

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

ON_WM_LBUTTONDOWN()

ON_WM_KEYDOWN()

END_MESSAGE_MAP()

čime se omogućuje razmjena poruka s tipkovnicom i mišom.

17.2.8 Interakcija pomoću menija

Menije se kreira pomoću "resource editora", sljedećim postupkom:

Postavite se u resource editor i kliknite na "meni"- IDR_FesbTYPE. Dobit će te prikaz

menija:

U kockicu "Type here" otkucajte

&Novi tekst

Zatim kliknite na Properties box i

zapišite identifikaciju ovog menija kao

ID_EDIT_NOVITEXT

Page 30: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 30

U rubrici prompt se zapisuje tekst koji

se ispisuje u na status baru, kada se selektira

ovaj meni.

Ponovo kompjlirajte program, i izvršite ga. Primjetit ćete da se pojavio ovaj meni, ali u

neaktivnom stanju.

Da bi ovi meniji postali aktivni mora se svakom meniju pridijeliti poruka i funkcija koja

se izvršava kada se primi komanda iz menija. tj. mora se definirati "event handler"

Event handler funkcija za komande

menija se automatski formira tako da se

klikne desnim mišom na stavku menija – tada

se otvori izbornik u kojem treba odabrati

stavku

Add Event handler

kada se to izvrši dobije se sljedeći

dijalog

Page 31: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 31

Odaberite klasu CFesbView i kliknite Add and Edit.

Visual studio tada automatski generira funkciju

void CFesbView::OnEditNovitext()

{

// TODO: Add your command handler code here

}

čiju deklaraciju zapisuje u obliku

afx_msg void OnEditNovitext();

Također je generiran kod

BEGIN_MESSAGE_MAP(CFesbView, CView)

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

ON_WM_LBUTTONDOWN()

ON_WM_KEYDOWN()

ON_COMMAND(ID_EDIT_NOVITEXT, OnEditNovitext)

END_MESSAGE_MAP()

čime je uspostavljen event handler.

U funkciju sada upišite:

void CFesbView::OnEditNovitext()

{

// TODO: Add your command handler code here

Page 32: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 32

AfxMessageBox("Pritisnut je meni: NOVI text")

}

Kompilirajte program i izvršite ga. Aktivirajte meni Edit->Novi text

i na ekranu će biti prikaz:

dakle, funkcija AfxMessageBox(char *str), je jednostavni način da se ispiše poruka

korisniku.

17.2.9 Interakcija pomoću dijaloga

Najprije formirajmo predložak za dijalog. Postavite se u resource editor i izvršite desni

klik na Dialog-Insert new dialog. Dobit će te dialog

njemu je prodjeljen identifikator IDD_DIALOG1. Otvorite properies i promijenite ovaj

identifikator u IDD_DIALOG1_TEXT. Ako želite promijenite i ime dijaloga u stavci

"Caption".

Page 33: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 33

Ovaj dijalog se povezuje s programom tako da se za njega formira posebna klasa tipa

CDialog.

Kliknite desnim botunom miša u području dijaloga. Pojavit će se sljedeći meni:

Odaberite

Add Class

Page 34: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 34

i Visula Studio vam nudi dijalog:

Ispunite ga kako je prikazano, kliknite "Finish" i Visual Studio generira klasu CTxtDlg.

#pragma once

#include "afxwin.h"

// CTxtDlg dialog

class CTxtDlg : public CDialog

{

DECLARE_DYNAMIC(CTxtDlg)

public:

CTxtDlg(CWnd* pParent = NULL); // standard constructor

virtual ~CTxtDlg();

// Dialog Data

enum { IDD = IDD_DIALOG_TEXT };

protected:

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

support

DECLARE_MESSAGE_MAP()

};

// TxtDlg.cpp : implementation file

Page 35: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 35

//

#include "stdafx.h"

#include "Fesb.h"

#include "TxtDlg.h"

// CTxtDlg dialog

IMPLEMENT_DYNAMIC(CTxtDlg, CDialog)

CTxtDlg::CTxtDlg(CWnd* pParent /*=NULL*/)

: CDialog(CTxtDlg::IDD, pParent)

{

}

CTxtDlg::~CTxtDlg()

{

}

void CTxtDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(CTxtDlg, CDialog)

END_MESSAGE_MAP()

Page 36: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 36

Sada ćemo u ovaj dijalog dodati dvije "kontrole"

Static - za poruku korisniku

Edit – za unos teksta

Zatim ćemo dodati varijablu u dijalog box – tipa CEdit, koja ce poslužiti za prihvat

unesenog teksta; Da bi to napravili, na dijalog boxu, u području Edit kontrole pritisnite desni

botun miša... i odaberite -- Add variable

Page 37: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 37

Pojavljuje se sljedeći dijalog

Unesite ime varijable m_txtEdit i kliknite botun Finish.

Visual Studio u prethodni kod CTxtDlg klase generira varijablu tipa CEdit i imena

m_txtEdit. Mi ćemo dodati još jednu varijablu CString m_text;

Ta varijabla će sadržavati tekst koji unese korisnik, a dobavit ćemo ga pozivom

m_txtEdit.GetWindowText(m_text)

kada korisnik otkuca OK.

Page 38: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 38

Da bi to omogućili moramo instalirati event handler za tipku OK. To se postiže tako da

se

u Properties odabere ikona

i izvrši izbor predefinirane virtuele funkcije OnOk()

Nakon toga Visual Studio generira funkciju:

void CTxtDlg::OnOK()

{

// TODO: Add your specialized code here and/or call the base class

CDialog::OnOK();

}

u koji treba upisati kod:

void CTxtDlg::OnOK()

{

m_txtEdit.GetWindowText(m_text) ;

CDialog::OnOK();

}

Page 39: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 39

Zapamtite : Poruke se šalju pomoću event handlera preko poruka ili tako da se

preoptereti event handler iz predefiniranih klasa.

Da bi mogli koristiti ovaj dijalog treba još pokazati:

- kako se poziva dijalog box

- kako se dobavlja informacija iz dijalog boxa u glavni program.

Iniciranje dijalog boxa može biti prečicom (tipkovnicom) ili preko poruka koje se

distribuiraju putem menija.

Evo načina da se dijalog pozove preko menija. Iskoristit ćemo prije definirani meni:

Novi text i u njegov "event handler" upisati kod:

void CFesbView::OnEditNovitext()

{

CFesbDoc* pDoc = GetDocument();

CTxtDlg dlg; // deklariranje dijaloga

int response = dlg.DoModal(); //poziv dijaloga

if(IDOK == response) // samo ako je pritisnut botun OK

{

CString s;

// dobavi txt iz dijaloga

if(dlg.m_text.IsEmpty()) // ako je prazan

AfxMessageBox("Unijeli ste prazan tekst");

else

pDoc->m_text = dlg.m_text; // stavi tekst u dokument

Invalidate();

}

}

Također, u datoteku FesbView.cpp treba dodati:

#include "stdafx.h"

#include "Fesb.h"

#include "FesbDoc.h"

#include "FesbView.h"

#include "TxtDlg.h"

Sada Kompilirajte program i probajte funkcionalnost dijaloga. Vidjet će te da je ovo

jedan tipični Windows program, kojem još jedino nedostaje mogućnost da se podaci spreme

na disk.

Također, potrebno je pokazati kako se vrši interakcija pomoću toolbara.

Page 40: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 40

17.2.10 Interakcija pomoću toolbara

Pokazat ćemo kako se na toolbar dodaje ikona kojoj će biti namjena de se njome

aktivira komanda menija:Novi text.

U resource prozoru aktivirajte toolbar IDF_MAINFRAME. Kliknite na posljednju

praznu ikonu.

Nacrtajte u ovoj ikoni slovo T

i kliknite desnim btunom miša

Pokrenite meni Properties, i u stavku ID

otkucajte identifikator Novi text menija,

tj. ID_EDIT_NOVITEXT

Kompilirajte i pokrenite program.

Vidjet ćete da se sada može pozvati dijalog za unos teksta pritiskom na ovi ikonu.

Page 41: 17. Programiranje za Windows GUI - marjan.fesb.hrmarjan.fesb.hr/~mateljan/cpp/pog17-programiranje za windows... · Lekcija 17. Programiranje za Windows GUI 4 i kad se uz tipkovnicu

Lekcija 17. Programiranje za Windows GUI 41

17.2.11 Spremanje i čitanje dokumenta

Naš dokument sadrži samo dva podatka string m_text i poziciju m_pos:

Pored ova dva podatka na početak datoteke ćemo zapisati 4 znaka: "FESB" koji će

služiti identifikaciji datoteke.

MFC klase potpuno enkapsuliraju rad s binarnim datotekama. Jedino što korisnik mora

napraviti je ispuniti funkciju Serialize(CArchive& ar) koja je definirana u FesbDoc.cpp;

void CFesbDoc::Serialize(CArchive& ar)

{

if (ar.IsStoring()) {

// TODO: add storing code here

}

else {

// TODO: add loading code here

}

}

Klasa CArchive omogućuje pristup datoteci pomoću operatora >> i << s logikom kao

kod standardnih klasa, ali se zapis ne vrši formatirano već u binarnom obliku. U našem

slučaju kod izgleda ovako:

void CFesbDoc::Serialize(CArchive& ar)

{

if (ar.IsStoring()) // spremanje u datoteku

{

ar << 'F'<< 'E'<< 'S'<< 'B';

ar << m_pos;

ar << m_text;

}

else // citanje iz datoteke

{

char c1,c2,c3,c4;

ar >> c1 >> c2 >> c3 >> c4;

if(c1 != 'F' || c2 != 'E' || c3 != 'S' || c4 != 'B')

{

AfxMessageBox("Ovo nije fesb datoteka"); return;

}

// ok, citaj poziciju i string

ar >> m_pos;

ar >> m_text;

}

}

Probajte sada izvršiti ovaj kompletni Windows program.

Primjetit ćete da je potpuno podržan pristup datotekama: izbor direktorija, otvaranje i

zatvaranje datoteka, pamćenje prethodno otvorenih datoteka - sve je enkapsulirano unutar

MFC klasa i funkcija.