Вы находитесь на странице: 1из 120

Napredno Windows

Visoka škola za informacijske tehnologije

programiranje

Nenad Čaklović
nenad.caklovic@vsite.hr
NWP
1. predavanje

• WinMain
• klase prozora
• procedura prozora
• poruke, petlja poruka
WinMain

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,


PSTR lpCmdLine, int nShowCmd)
{
return 0;
}

#define WINAPI __stdcall


Win32 tipovi

// wtypes.h
typedef char CHAR;
typedef CHAR* PSTR;
typedef const CHAR* PCSTR;

typedef int INT;


typedef unsigned int UINT;
typedef unsigned short WORD;

typedef long LONG;


typedef unsigned long DWORD;
typedef DWORD ULONG;

typedef int BOOL;


typedef unsigned char BYTE;
typedef void* PVOID;
...
HANDLE

typedef void* HANDLE;

#ifdef STRICT
#define DECLARE_HANDLE(name) struct name##__ { int unused; };
#else
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif

DECLARE_HANDLE(HINSTANCE);
DECLARE_HANDLE(HICON);
DECLARE_HANDLE(HCURSOR);
DECLARE_HANDLE(HBRUSH);
DECLARE_HANDLE(HWND);
WNDCLASS

typedef struct
{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
PCTSTR lpszMenuName;
PCTSTR lpszClassName;
}
WNDCLASS;

• RegisterClass prijavljuje novu klasu operativnom sustavu


CreateWindow

HWND CreateWindow(
PCTSTR lpClassName,
PCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
PVOID lpParam
);

• CW_USEDEFAULT za x, y, nWidth, nHeight

#define CW_USEDEFAULT ((int)0x80000000)


procedura prozora (window procedure)

LRESULT CALLBACK WndProc(


HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam);

// windef.h
#define CALLBACK __stdcall

typedef UINT WPARAM;


typedef LONG LPARAM;
typedef LONG LRESULT;
petlja poruka (message loop)

MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

typedef struct
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}
MSG;

• GetMessage vraća 0 samo ako je poruka WM_QUIT


slanje poruka

• svaki program ima svoj red poruka (message queue)

• PostMessage stavlja poruku u red poruka

BOOL PostMessage(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam);

• SendMessage ide direktno na obradu poruke


procedura prozora (window procedure)

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,


WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
...
return 0;
case WM_SIZE:
...
return 0;
case WM_DESTROY:
...
return 0;
}
return DefWindowProc(hwdn, message, wParam, lParam);
}
poruke

#define WM_CREATE 0x0001


#define WM_DESTROY 0x0002
#define WM_MOVE 0x0003
#define WM_SIZE 0x0005
#define WM_PAINT 0x000F
#define WM_CLOSE 0x0010
#define WM_QUIT 0x0012
...

• PostQuitMessage stavlja WM_QUIT u red poruka


2. predavanje

• resursi
Resursi (resources)

vrste:
• ikona (icon)
• kursor (cursor)
• tekst (string)
• prečica (accelerator)
• novi (custom)
• meni (menu)
• dijalog (dialog box)
• slika (bitmap)
Datoteka sa resursima

• tekstualna datoteka sa ekstenzijom .rc

• kompilira se zasebno u .res datoteku (compiler - rc.exe)

• .res datoteka se linka zajedno sa obj. datotekama

• resursi su dio izvršne datoteke (.exe)

• učitavaju se posebnim Win32 funkcijama

• sadržaj datoteke:

nameID TYPE value

• TYPE - vrsta resursa

• nameID - broj, ime ili preprocesorski #define

• često se koristi .h datoteka koja se koristi (#include) i u kodu (.cpp)


Ikona

• slika standardne veličine sa podrškom za transparentnost


• .ico datoteka može sadržavati više slika

// app.rc
#include "resource.h"
IDI_MAIN ICON "ikona.ico"

// resource.h
#define IDI_MAIN 101

• učitavanje: HICON LoadIcon(HINSTANCE, LPCTSTR);

#include "resource.h"
HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));

#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))


Kursor

• slika standardne veličine sa naznačenom ključnom točkom (hot-spot)


• .cur datoteka

IDC_MAIN CURSOR "kursor.cur"

• učitavanje:

HCURSOR LoadCursor(HINSTANCE, LPCTSTR);

• učitavanje standardnog Windows kursora

HCURSOR hCur = LoadCursor(NULL, IDC_ARROW);


Tekst

• svi tekstovi u programu bi trebali biti u resursima radi lakšeg mijenjanja i


prevođenja

STRINGTABLE
BEGIN
IDS_STRING1 "prvi tekst"
IDS_STRING2 "drugi tekst"
...
END
• tekst može sadržavati \t i \n, maksimalna duljina je 4097 znakova

• učitavanje: int LoadString(HINSTANCE, UINT, LPTSTR, int);

char s[128];
LoadString(hInstance, IDS_STRING1, s, sizeof s);
Prečica

• kombinacije tipki koje generiraju poruku WM_COMMAND

ID_ACCEL ACCELERATORS
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
VK_F1, ID_SOMETHING, VIRTKEY, CONTROL, ALT
...
END

• učitavanje i korištenje:

HANDLE hAcc = LoadAccelerators(hInstance, MAKEINTRESOURCE(ID_ACCEL));


while (GetMessage (&msg, NULL, 0, 0)) {
if (!TranslateAccelerator (hwnd, hAcc, &msg)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
Novi tip (custom, user-defined)

• binarni podaci ili zasebna datoteka

ID_BIN MYTYPE ID_BIN MYTYPE "file.dat"


BEGIN
0x776e, 0x2070, 0x6576, 0x7473
END

• učitavanje i korištenje:

HRSRC hRc = FindResource(hInstance, MAKEINTRESOURCE(ID_BIN), "MYTYPE");


HGLOBAL h = LoadResource(hInstance, hRc);
void* pData = LockResource(h);
char* pText = reinterpret_cast<char*>(pData);
...
FreeResource(h);
Meni

IDM_MAIN MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New", ID_FILE_NEW
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&Index", ID_HELP_INDEX, GRAYED
MENUITEM "&Tooltips", ID_HELP_TIPS, CHECKED
MENUITEM "&About", ID_HELP_ABOUT
END
END
Meni

• učitavanje

HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDM_MAIN));

• pridjeljivanje prozoru:
kao parametar u CreateWindow ili
SetMenu(hWnd, hMenu);

• promjena karakteristika menuitem-a iz koda:

HMENU hMenu = GetMenu(hWnd);


CheckMenuItem(hMenu, ID_HELP_TIPS, bTips ? MF_CHECKED : MF_UNCHECKED);
EnableMenuItem(hMenu, ID_HELP_INDEX, bIndex ? MF_ENABLED : MF_GRAYED);

• može i po indeksu itema unutar menija


HMENU hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, 1, MF_BYPOSITION | MF_CHECKED);
EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
Meni bez resursa

HMENU hMenu = CreateMenu();


HMENU hPopup = CreatePopupMenu()
AppendMenu(hPopup, MF_STRING, ID_FILE_NEW, "&New”);
AppendMenu(hPopup, MF_SEPARATOR, 0, NULL);
AppendMenu(hPopup, MF_STRING, ID_FILE_EXIT, ”E&xit”);
AppendMenu(hMenu, MF_POPUP, hPopup, "&File") ;
...

• ako nije pridjeljen prozoru, na kraju obavezno DestroyMenu


• funkcije za promjenu menija:
– AppendMenu (na kraj)
– InsertMenu (unutar)
– DeleteMenu (briše)
– RemoveMenu (ne briše)
– ModifyMenu
Meni bez prozora

• tipično na desnu tipku miša, Shift+F10, ili posebnu tipku


• dobije se poruka WM_CONTEXTMENU

...
case WM_CONTEXTMENU:
HMENU hPopup = GetSubMenu(GetMenu(hwnd), 0); // ili Create
DWORD pos = GetMessagePos();
int x = GET_X_LPARAM(pos), y = GET_Y_LPARAM(pos);
UINT id = TrackPopupMenu(hPopup, TPM_RETURNCMD,
x, y, 0, hwnd, 0);
return 0;
...
3. predavanje

• dijalozi
– modalni
– nemodalni
– standardni
Dijalog

• pop-up prozor koji sadrži kontrole (djecu)


• nastaje na osnovu predloška (dialog box template) u resursima

nameID DIALOG x, y, width, height


STYLE style
CAPTION "text"
FONT 8, "MS Sans Serif"
BEGIN
... kontrole ...
END

• koordinate:
po x-u 1/4 prosječne širine znaka
po y-u 1/8 prosječne visine znaka

• operativni sistem kreira prozor, kreira kontrole na prozoru i sadrži proceduru


prozora - dialog box manager

• neke od poruka se prosljeđuju proceduri dijaloga - dialog box procedure (dialog


procedure)
Procedura dijaloga (dialog procedure)

BOOL CALLBACK DlgProc(


HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);

• isti parametri kao procedura prozora


• razlike:
– vraća BOOL, a ne LRESULT
– nema poziva DefWindowProc
– vraća TRUE (1) ako obrađuje poruku, FALSE (0) ako ne
– ne obrađuju se poruke WM_PAINT, WM_DESTROY, WM_CREATE, postoji
posebna poruka WM_INITDIALOG
Modalni dijalog (modal)

• znatno češće korišten od nemodalnog

• najjednostavniji način za napraviti komplicirane prozore

• modalni - nijedan drugi prozor u programu se ne može aktivirati

• modalni za sistem (system-modal) - nijedan drugi prozor se ne može aktivirati


• aktiviranje dijaloga:

int DialogBox(HINSTANCE hInstance, LPCTSTR template,


HWND parent, DLGPROC dlgProc);

• poziv funkcije se ne vraća sve dok je dijalog otvoren


• poruke za modalne dijaloge ne idu kroz petlju poruka
• zatvaranje dijaloga:

BOOL EndDialog(HWND hDlg, int retVal);


Procedura modalnog dijaloga

BOOL CALLBACK DlgProc(HWND hDlg, UINT message,


WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
// inicijaliziraj kontrole
return TRUE; // postavi fokus na prvu kontrolu
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
// upotrijebi vrijednosti sa kontrola
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
Kontrole

kontrola klasa stil

PUSHBUTTON button BS_PUSHBUTTON ¦ WS_TABSTOP


DEFPUSHBUTTON button BS_DEFPUSHBUTTON ¦ WS_TABSTOP
CHECKBOX button BS_CHECKBOX ¦ WS_TABSTOP
RADIOBUTTON button BS_RADIOBUTTON ¦ WS_TABSTOP
GROUPBOX button BS_GROUPBOX ¦ WS_TABSTOP
LTEXT static SS_LEFT ¦ WS_GROUP
CTEXT static SS_CENTER ¦ WS_GROUP
RTEXT static SS_RIGHT ¦ WS_GROUP
ICON static SS_ICON
EDITTEXT edit ES_LEFT ¦ WS_BORDER ¦ WS_TABSTOP
SCROLLBAR scrollbar SBS_HORZ
LISTBOX listbox LBS_NOTIFY ¦ WS_BORDER ¦ WS_VSCROLL
COMBOBOX combobox CBS_SIMPLE ¦ WS_TABSTOP
Upotreba kontrola

• red u predlošku dijaloga


control-type "text", id, x, y, width, height [, style]

• za EDITTEXT, SCROLLBAR, LISTBOX, COMBOBOX nema teksta


• za bilo koju kontrolu
CONTROL "text", id, "class", style, x, y, width, height
• primjeri:
DEFPUSHBUTTON "OK",IDOK,236,111,50,14
PUSHBUTTON "Cancel",IDCANCEL,236,128,50,14
LTEXT "&Name:",IDC_STATIC,15,9,52,11
ICON IDI_MAIN,IDC_STATIC,7,7,21,20
RADIOBUTTON "&Ellipse",IDC_ELLIPSE,116,188,64,8
EDITTEXT IDC_EDIT1,77,8,48,13,ES_AUTOHSCROLL
CONTROL "List1",IDC_LIST1,"SysListView32",WS_BORDER |
WS_TABSTOP, 18,81,78,49
Funkcije za rad s kontrolama

• GetDlgItem(hDlg, id) - vraća HWND kontrole sa id


• SendDlgItemMessage(hDlg, id, msg, wParam, lParam)
• EnableWindow(hwCtrl, TRUE/FALSE)
• CheckDlgButton(hDlg, id, BST_CHECKED/BST_UNCHECKED),
IsDlgButtonChecked(hDlg, id) - za checkbox

• CheckRadioButton(hDlg, idFirst, idLast, idChecked)


- za grupu radiobutton-a

• SetDlgItemText(hDlg, id, string),


GetDlgItemText(hDlg, id, &string, count)
• SetDlgItemInt(hDlg, id, value, TRUE),
GetDlgItemInt(hDlg, id, &success, TRUE)
Nemodalni dijalog (modeless)

• koriste se kad korisnik mora moći obaviti i neku drugu operaciju dok je dijalog
prikazan (primjer: "Find/Replace" dijalog)
• aktiviranje dijaloga:
HWND CreateDialog(HINSTANCE hInstance, LPCTSTR template,
HWND parent, DLGPROC dlgProc);

• poziv funkcije se vraća odmah i vraća HWND dijaloga


• STYLE u predlošku treba imati i WS_VISIBLE ili treba pozvati
ShowWindow(hDlg, SW_SHOW);

• zatvaranje dijaloga (tipično na WM_CLOSE):

DestroyWindow(hDlg);
Promjene u petlji poruka

• poruke za nemodalne dijaloge idu kroz petlju poruka, zato se petlja poruka mora
promijeniti

HWND hDlgModeless = CreateDialog(...); // ili globalna varijabla

while (GetMessage (&msg, NULL, 0, 0))


{
if (hDlgModeless == 0 ¦¦ !IsDialogMessage (hDlgModeless, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}

• ako je poruka za nemodalni dijalog (IsDialogMessage vrati TRUE), ne smije se


pozvati TranslateMessage/DispatchMessage
Standardni dijalozi (common dialog boxes)

postoje sljedeći standardni dijalozi:


• Color
• Find
• Font
• Open
• Page Setup
• Print
• Replace
• Save As
Dijalog za boju

COLORREF myCol = RGB(255,128,0);

COLORREF custCols[16] = {0};


CHOOSECOLOR cc;
ZeroMemory(&cc, sizeof cc);
cc.lStructSize = sizeof cc;
cc.Flags = CC_FULLOPEN|CC_RGBINIT;
cc.lpCustColors = custCols;
cc.rgbResult = myCol;
if(ChooseColor(&cc))
myCol = cc.rgbResult;
Dijalog za font

LOGFONT lf = {0};
strcpy(lf.lfFaceName, "Arial");

CHOOSEFONT cf;
ZeroMemory(&cf, sizeof cf);
cf.lStructSize = sizeof cf;
cf.Flags = CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS | CF_EFFECTS;
cf.lpLogFont = &lf;
if(ChooseFont(&cf))
CreateFontIndirect(&lf);
Dijalog za otvaranje/spremanje datoteke

char path[MAX_PATH]; *path = 0;

char filter[] = "Text Files


(*.txt)\0*.txt\0All Files
(*.*)\0*.*\0\0" ;
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof ofn);
ofn.lStructSize = sizeof ofn;
ofn.lpstrFile = path;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = filter;

ofn.Flags = OFN_HIDEREADONLY;
if(GetOpenFileName(&ofn))
// otvori "path"

ofn.Flags = OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT;
if(GetSaveFileName(&ofn))
// spremi u "path"
4. predavanje

• subclassing
• Unicode
Parametri klase

• LONG GetClassLong(HWND hw, int index);


• LONG SetClassLong(HWND hw, int index, LONG newval);
• mogući indeksi:
– GCL_CBCLSEXTRA
– GCL_CBWNDEXTRA
– GCL_HBRBACKGROUND
– GCL_HCURSOR
– GCL_HICON
– GCL_HICONSM
– GCL_HMODULE
– GCL_MENUNAME
– GCL_STYLE
– GCL_WNDPROC
Parametri prozora

• LONG GetWindowLong(HWND hw, int index);


• LONG SetWindowLong(HWND hw, int index, LONG newval);
• mogući indeksi:
– GWL_EXSTYLE
– GWL_STYLE
– GWL_WNDPROC
– GWL_HINSTANCE
– GWL_ID
– GWL_USERDATA
Subclassing

• kada želimo hvatati poruke postojećeg prozora

WNDPROC origWndProc;

// subclass hwnd
origWndProc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(LONG)AlterWndProc);

LRESULT CALLBACK AlterWndProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp)
{
if(msg == WM_KEYDOWN)
// something
return CallWindowProc(origWndProc, hw, msg, wp, lp) ;
}

• na kraju obavezno zove originalnu proceduru prozora

• najmoćnije oružje Windowsa - kao izvođenje u objektnim jezicima


Setovi znakova (character sets)

• preteče današnjih setova: Braille oko 1820, Morse oko 1850, telex kodovi
• 1967. 7-bitni ASCII standard (26 malih slova, 26 velikih slova, 10 brojki, 32
simbola, 33 kontrol-koda i razmak = 128)
• 1981. 8-bitni standard za IBM PC - popunjeno još 128 znakova
• 1987 (MS DOS 3.3) uvodi kodne stranice, koncept preuzimaju i Windowsi -
gornjih 128 znakova se mapiraju preko tablice

• DBCS (double-byte character set) - za ideografske jezike (CJK)


• neki znakovi su 1 byte, neki 2 (za posebne vrijednosti 1. bytea)

• Unicode - konačno rješenje


• wide characters - svaki znak je velik 2 bytea, ukupno 65536 znakova
• prvih 128 Unicode znakova su ASCII, sljedećih 128 su ISO 8859-1
Setovi znakova u C/C++

• normalni karakteri (char):

char c = 'M';
char* s = "VEST";
char a[] = "NWP";

• 2-byte karakteri (wchar_t):


typedef unsigned short wchar_t;

wchar_t c = L'M'; sizeof c = 2 // 1 karakter


wchar_t* s = L"VEST"; sizeof s = 4 // pointer!
wchar_t a[] = L"NWP"; sizeof a = 8 // 3+1 karakter

• standardne funkcije:

strlen wcslen
strcpy wcscpy
strcat wcscat
...
TCHAR

• za održavanje istog koda za dvije moguće verzije - ASCII, Unicode


• u datoteci tchar.h

#ifdef _UNICODE #else // _UNICODE

typedef wchar_t TCHAR; typedef char TCHAR;


#define _tcslen wcslen #define _tcslen strlen
#define _tcscpy wcscpy #define _tcscpy strcpy
... ...
#define __T(x) L##x #define __T(x) x

• novi način pisanja koda:

TCHAR c = _T('M');
TCHAR* s = _T("VEST");
TCHAR a[] = _T("NWP");
Setovi znakova u Windowsima

• Windows NT potpuno podržava Unicode, Windows 98 samo djelomično


// winnt.h
typedef wchar_t WCHAR;
typedef CONST WCHAR* PCWSTR;

• za svaku Win32 funkciju koja prima tekst postoje dvije verzije

MessageBox(HWND par, PCTSTR txt, PCTSTR caption, UINT type);

MessageBoxA(HWND par, PCSTR txt, PCSTR caption, UINT type);


MessageBoxW(HWND par, PCWSTR txt, PCWSTR caption, UINT type);

// winuser.h
#ifdef _UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
Tipkovnica

• poruke sa tipkovnice idu prozoru koji ima fokus


• to je aktivni prozor ili neki od njegove djece

// funkcije // poruke
HWND GetFocus(); WM_SETFOCUS // prozor dobiva fokus
HWND SetFocus(HWND); WM_KILLFOCUS // prozor gubi fokus

• poruke sa tipkovnice i miša prvo idu u posebni red poruka - system message queue
• GetKeyState() - da li je tipka pritisnuta, obično se koristi za Ctrl, Shift

// poruke
WM_KEYDOWN
• u WPARAM virtualni kod tipke
WM_KEYUP

WM_SYSKEYDOWN • u kombinaciji sa Alt tipkom, obično ne obrađujemo


WM_SYSKEYUP

WM_CHAR • u WPARAM karakter - posljedica TranslateMessage


Miš

// funkcije
GetSystemMetrics(SM_MOUSEPRESENT); • da li je miš prisutan

ShowCursor(TRUE/FALSE); • pokaži/sakrij kursor

RECT r; ClipCursor(&r); • ograniči kretanje kursora

POINT p; GetCursorPos(&p);
• pozicija kursora na ekranu
SetCursorPos(x, y);

SetCapture(hwnd); • kako dobiti poruke kad kursor nije


ReleaseCapture(); iznad prozora (capture)
Miš

// poruke
WM_LBUTTONDOWN WM_RBUTTONDOWN WM_MBUTTONDOWN
WM_LBUTTONUP WM_RBUTTONUP WM_MBUTTONUP
WM_LBUTTONDBLCLK WM_RBUTTONDBLCLK WM_MBUTTONDBLCLK

WM_MOUSEMOVE
WM_MOUSEWHEEL

• u LPARAM su koordinate unutar prozora

x = GET_X_LPARAM(lParam);
y = GET_Y_LPARAM(lParam);

• u WPARAM su oznake da li je pritisnuta tipka (MK_CONTROL, MK_SHIFT, ...)


Mjerač (timer)

• baziran na BIOS prekidu koji hvataju Windowsi

// funkcije
SetTimer(hwnd, idTimer, milisec, timerProc);
KillTimer(hwnd, idTimer);

• dva načina korištenja


• 1. način: poruka prozoru
// poruka
WM_TIMER

• 2. način: procedura mjerača


void CALLBACK TimerProc (HWND hwnd, UINT message,
UINT TimerID, DWORD dwTime);
5. predavanje

• GDI - osnove
Dijelovi prozora

title bar
menu bar
0, 0

klijentsko
područje

status bar

// funkcije
GetClientRect(hwnd, &rect);
GetWindowRect(hwnd, &rect); // koordinate na ekranu

// poruke
WM_SIZE • u LPARAM nova veličina klijentskog područja
WM_GETMINMAXINFO • za postavljanje ograničenja (min, max veličina prozora)
Crtanje po prozoru

• Windows programi crtaju "na zahtjev"

// poruka
WM_PAINT

• šalje se u sljedećim slučajevima:


– kada dio prozora postane vidljiv zbog micanja prozora
– kada prozor promijeni veličinu (CS_HREDRAW, CS_VREDRAW)
– pri skrolanju (pozivu ScrollWindow)
– nakon eksplicitnog poziva InvalidateRect

• može biti poslana kad dio prozora postane vidljiv zbog:


– micanja dijaloga
– zatvaranja menija
– nestajanja tooltip-a

• sigurno neće biti poslana (Windowsi čuvaju potrebno područje) zbog:


– micanja kursora preko prozora
– nošenja ikone preko prozora
Nevažeća (invalid) područja

• nevažeće područje (invalid region, update region) - onaj dio koji se mora
ponovno iscrtati

• kada nastane nevažeće područje Windowsi šalju poruku WM_PAINT i zapamte


nevažeći pravokutnik (invalid rectangle) - minimalni pravokutnik koji opisuje
nevažeće područje

• ako se pojavi novo nevažeće područje dok poruka još nije obrađena, Windowsi
izračunaju novi nevažeći pravokutnik (ne šalje se nova poruka)

// funkcije
GetUpdateRect • vraća nevažeći pravokutnik

InvalidateRect • označava pravokutnik nevažećim

ValidateRect • označava pravokutnik važećim

UpdateWindow • ako postoji nevažeće područje, odlazi direktno na


obradu WM_PAINT poruke
Obrada poruke WM_PAINT

// WindowProc
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// GDI funkcije
EndPaint(hwnd, &ps);
return 0;

• BeginPaint briše pozadinu nevažećeg područja (WM_ERASEBKGND), popunjava


članove PAINTSTRUCT strukture i vraća HDC
• BeginPaint validira nevažeće područje

• nevažeće područje služi i kao ograničavajuće područje (clipping area) -


GDI funkcije ne crtaju van tog područja
Device context (DC)

• apstrakcija koja omogućuje crtanje na istovjetan način na ekranu i štampaču

GetDeviceCaps(hdc, index);

• mogućnosti DC-a:
– rezolucija (HORZRES, VERTRES)
– broj boja (BITSPIXEL, PLANES)
– broj piksela po inchu (LOGPIXELSX, LOGPIXELSY)
– mogućnosti pri ispisu teksta (TEXTCAPS), crtanju linija (LINECAPS), crtanju krivulja
(CURVECAPS), crtanju bitmapa(RASTERCAPS), ...

• funkcije koje vraćaju sistemske veličine

GetSystemMetrics(index);
// SM_CXFRAME, SM_CYCAPTION, SM_CYMENU, SM_NETWORK, ...
SystemParametersInfo(index, ...)
// SPI_GETSCREENSAVEACTIVE, SPI_GETDRAGFULLWINDOWS,
SPI_GETNONCLIENTMETRICS, SPI_GETDESKWALLPAPER, ...
Device context bez WM_PAINT

• device context za klijentski dio prozora se može dobiti uvijek

HDC hdc = GetDC(hwnd);


// GDI funkcije
ReleaseDC(hwnd, hdc);

• za ovakav device context nema ograničavajućih i nevažećih područja

• ostali načini za dobiti HDC:

GetWindowDC(hwnd); • cijeli prozor (WM_NCPAINT)


ReleaseDC(hwnd, hdc);

CreateDC(driver, device, ...); • bilo koji uređaj


DeleteDC();

HDC hmemdc = CreateCompatibleDC(hdc); • "memorijski" DC


DeleteDC(hmemdc);
Svojstva DC-a
svojstvo default funkcije za promjenu funkcije za dohvat
Mapping Mode MM_TEXT SetMapMode GetMapMode
Window Origin (0, 0) SetWindowOrgEx GetWindowOrgEx
OffsetWindowOrgEx
Viewport Origin (0, 0) SetViewportOrgEx GetViewportOrgEx
OffsetViewportOrgEx
Window Extents (1, 1) SetWindowExtEx GetWindowExtEx
SetMapMode
ScaleWindowExtEx
Viewport Extents (1, 1) SetViewportExtEx GetViewportExtEx
SetMapMode
ScaleViewportExtEx
Pen BLACK_PEN SelectObject SelectObject
Brush WHITE_BRUSH SelectObject SelectObject
Font SYSTEM_FONT SelectObject SelectObject
Bitmap - SelectObject SelectObject
Current Position (0, 0) MoveToEx GetCurrentPositionEx
LineTo
PolylineTo
PolyBezierTo
Background Mode OPAQUE SetBkMode GetBkMode
Background Color White SetBkColor GetBkColor
Text Color Black SetTextColor GetTextColor
Drawing Mode R2_COPYPEN SetROP2 GetROP2
Stretching Mode BLACKONWHITE SetStretchBltMode GetStretchBltMode
Polygon Fill Mode ALTERNATE SetPolyFillMode GetPolyFillMode
Intercharacter Spacing 0 SetTextCharacterExtra GetTextCharacterExtra
Brush Origin (0, 0) SetBrushOrgEx GetBrushOrgEx
Clipping Region - SelectObject GetClipBox
SelectClipRgn
Spremanje DC-a

• prije promjena svojstava može se sačuvati stanje DC-a

int id = SaveDC(hdc);
// funkcije za promjenu svojstava
RestoreDC(hdc, id);

• ako je potrebno obnoviti samo zadnji sačuvani DC

SaveDC(hdc);
// funkcije za promjenu svojstava
RestoreDC(hdc, -1);

• klasa prozora može čuvati svojstva DC-a

WNDCLASS wc;
wc.style = CS_OWNDC;
SelectObject

• selektira GDI objekt "u" DC


• vraća prethodni objekt istog tipa

HPEN hpen = (HPEN)GetStockObject(WHITE_PEN);


HGDIOBJ holdpen = SelectObject(hdc, hpen);
// GDI funkcije crtaju sa bijelom olovkom
SelectObject(hdc, holdpen);

• kako dobiti trenutno selektirani objekt:

HGDIOBJ GetCurrentObject(hdc, type);


// type = OBJ_PEN, OBJ_BRUSH, OBJ_FONT, OBJ_BITMAP, ...
6. predavanje

• GDI
Piksel

• vrlo rijetko korištene funkcije zbog sporosti

// funkcije
COLORREF GetPixel(hdc, x, y);
SetPixel(hdc, x, y, color);

• ako se točna boja ne može prikazati, prikazat će se najbliža moguća


Linija

• funkcije za crtanje linija:

LineTo(hdc, x, y);
Polyline(hdc, arrPts, count);
PolyPolyline(hdc, arrPts, arrCnt, numPol);
PolyBezier(hdc, arrPts, count);

• primjeri:

MoveToEx(hdc, 100, 100, NULL);


LineTo(hdc, 200, 200);

POINT p[] = { 20, 20, 50, 20, 50, 50, 20, 50, 20, 20 };
Polyline(hdc, p, sizeof(p)/sizeof(p[0]));
Olovka (pen)

• funkcije za crtanje linija koriste trenutno selektiranu olovku

HPEN CreatePen(style, width, color);

• style:

• kada više nije potreban, GDI objekt se mora obrisati

DeleteObject(HGDIOBJ);
SelectObject (2)

• kreirani objekt se ne smije obrisati dok je selektiran

HPEN hpen = CreatePen(PS_SOLID, 1, RGB(255,0,0));


HGDIOBJ holdpen = SelectObject(hdc, hpen);
MoveToEx(hdc, 0, 0, NULL);
LineTo(hdc, 300, 300);
SelectObject(hdc, holdpen);
DeleteObject(hpen);

• isto, ali kraće (koristi što SelectObject uvijek vraća prethodno selektirani)

HGDIOBJ holdpen = SelectObject(hdc,


CreatePen(PS_SOLID, 1, RGB(255,0,0)));
MoveToEx(hdc, 0, 0, NULL);
LineTo(hdc, 300, 300);
DeleteObject(SelectObject(hdc, holdpen));
Područja

• funkcije za crtanje (ispunjavanje) područja:

Rectangle(hdc, left, top, right, bottom);


Ellipse(hdc, left, top, right, bottom);
RoundRect(hdc, left, top, right, bottom, width, height);
Chord(hdc, left, top, right, bottom, x1, y1, x2, y2);
Pie(hdc, left, top, right, bottom, x1, y1, x2, y2);
Polygon(hdc, arrPts, count);
PolyPolygon(hdc, arrPts, arrCnt, numPol);

• primjeri:

Rectangle(hdc, 20, 20, 50, 50);


Ellipse(hdc, 20, 20, 50, 50);

POINT p[] = { 20, 20, 50, 20, 50, 50, 20, 50, 20, 20 };
Polygon(hdc, p, sizeof(p)/sizeof(p[0]));
Četka (brush)

• funkcije za crtanje područja ispunjavaju područje koristeći


trenutno selektirani brush

HBRUSH CreateSolidBrush(color);
HBRUSH CreateHatchBrush(style, color);
• style:

• funkcije za koje brush ne treba selektirati:

FillRect(hdc, &rect, hbrush);


FrameRect(hdc, &rect, hbrush);
InvertRect(hdc, &rect);
Način punjenja (fill mode)

• kako se pune poligoni koji sijeku sami sebe

SetPolyFillMode(hdc, mode);

• mode:

ALTERNATE WINDING
Tekst

• funkcije za ispis teksta:

TextOut(hdc, x, y, string, count);


TabbedTextOut(hdc, x, y, string, count, num, arrPts, start);
DrawText(hdc, string, count, &rect, format)
ExtTextOut(hdc, x, y, options, &rect, string, count, &arrDist);

• dodatne funkcije:
SetTextAlign(hdc, mode); • poravnanje (TA_LEFT, TA_TOP, ...)
SetTextColor(hdc, col);
SetBkColor(hdc, col);
SetBkMode(hdc, mode); • pozadina (OPAQUE, TRANSPARENT)

• primjeri:
std::basic_string<TCHAR> s = _T("NWP");
TextOut(hdc, 100, 100, s.c_str(), s.length());

DrawText(hdc, s.c_str(), -1, &rc,


DT_CENTER|DT_VCENTER|DT_SINGLELINE);
Font

• funkcije za ispis teksta pišu sa trenutno selektiranim fontom

HFONT CreateFont(height, width, escapement, orientation,


weight, italic, underline, strikeout, charset, outprec,
clipprec, quality, pitch_family, name);

• parametri:
– height: pozitivna = ukupna visina reda,
negativna = -pointSize*GetDeviceCaps(hdc, LOGPIXELSY)/72
– escapement: nagib u desetinama stupnja
– weight: FW_NORMAL, FW_BOLD
– italic, underline, strikeout: TRUE/FALSE
– charset: ANSI_CHARSET, EASTEUROPE_CHARSET, GREEK_CHARSET, ...
– pitch_family: FIXED_PITCH/VARIABLE_PITCH, FF_ROMAN, FF_SWISS, ...
– name: "Arial", "Times New Roman", ...
Regije

• funkcije za pravljenje regija:

HRGN CreateRectRgn(left, top, right, bottom);


HRGN CreateEllipticRgn(left, top, right, bottom);
HRGN CreatePolygonRgn(arrPts, cnt, fillmode);
int CombineRgn(hDestRgn, hSrcRgn1, hSrcRgn2, combmode);

• način komibiranja: RGN_AND, RGN_OR, RGN_XOR, RGN_DIFF, RGN_COPY


• crtanje po regiji:

FillRgn(hdc, hrgn, hbrush);


FrameRgn(hdc, hrgn, hbrush, x, y);
InvertRgn(hdc, hrgn);
PaintRgn(hdc, hrgn);

• ograničavanje crtanja regijom (clipping):

SelectObject(hdc, hrgn);
SelectClipRgn(hdc, hrgn);
Način crtanja (drawing mode)

• crtanje može ovisiti i o trenutnom sadržaju DC-a

// funkcija
P: 1 1 0 0
SetROP2(hdc, mode); mode:
D: 1 0 1 0
R2_BLACK 0 0 0 0 0
R2_NOTMERGEPEN 0 0 0 1 ~(P ¦ D)
• ROP2 - binarna raster operacija
R2_MASKNOTPEN 0 0 1 0 ~P & D
– P (pen)
R2_NOTCOPYPEN 0 0 1 1 ~P
– D (destination)
R2_MASKPENNOT 0 1 0 0 P & ~D
R2_NOT 0 1 0 1 ~D
R2_XORPEN 0 1 1 0 P ^ D
R2_NOTMASKPEN 0 1 1 1 ~(P & D)
R2_MASKPEN 1 0 0 0 P & D
R2_NOTXORPEN 1 0 0 1 ~(P ^ D)
R2_NOP 1 0 1 0 D
R2_MERGENOTPEN 1 0 1 1 ~P ¦ D
R2_COPYPEN 1 1 0 0 P
R2_MERGEPENNOT 1 1 0 1 P ¦ ~D
R2_MERGEPEN 1 1 1 0 P ¦ D
R2_WHITE 1 1 1 1 1
Način mapiranja (mapping mode)

• kako Windowsi transformiraju logičke koordinate u koordinate uređaja (piksele)


• prozor (window) i pogled (viewport) imaju ishodište (origin) i raspon (extent)

xViewExt
xViewport  (xWindow - xWinOrg) *  xViewOrg
xWinExt

// funkcije SetViewportExtEx(hdc, cx, cy, 0);


DPtoLP(hdc, arrPts, count); SetViewportOrgEx(hdc, x, y, 0);
LPtoDP(hdc, arrPts, count); SetWindowExtEx(hdc, cx, cy, 0);
SetWindowOrgEx(hdc, x, y, 0);

• načini mapiranja:
– jedinica piksel, y raste prema dole - MM_TEXT
– jedinica proizvoljna, y raste prema gore - MM_LOMETRIC (0.1 mm), MM_HIMETRIC (0.01
mm), MM_LOENGLISH (0.01 inch), MM_HIENGLISH (0.001 inch), MM_TWIPS (1/1440
inch)
– sve proizvoljno - MM_ISOTROPIC (x = y), MM_ANISOTROPIC (x != y)

// funkcija
SetMapMode(hdc, mode);
Način mapiranja - primjer

SetMapMode(hdc, MM_ISOTROPIC); SetMapMode(hdc, MM_ANISOTROPIC);

RECT rc; GetClientRect(hwnd, &rc);


SetViewportExtEx(hdc, rc.right, rc.bottom, NULL);
SetWindowExtEx(hdc, 10, 10, NULL);
Ellipse(hdc, 0, 0, 10, 10);
7. predavanje

• MFC - uvod
Povijest

• Microsoft Foundation Class Library


– 1.0 - sa C/C++ 7.0 (DOS): Windows API, kolekcije, datoteke, MDI, OLE podrška
– 2.0 - sa VC 1.0: MRU, printanje, skrolanje, toolbar, scrollbar, DDX
– 2.5 - sa VC 1.5: ODBC, OLE automation
– 3.0 - sa VC 2.0 (32-bitni): property sheet, docking control bar, OLE kontrole
– 3.1 - sa VC 2.1: Win95 common controls, Winsock
– 3.2 - sa VC 2.2
– 4.0 - sa VC 4.0: DAO, thread sinkronizacija, container OLE kontrola
– 4.1 - sa VC 4.1
– 4.2 - sa VC 4.2: WinInet, bolji ODBC, ActiveX kontrole
– 4.21 - sa VC 5.0: popravke (mfc42.dll)
– 6.0 - sa VC 6.0: nove common controls, OLE DB, DHTML (mfc42.dll)
– 7.0 - sa VC.NET
– 7.1 – sa VC.NET 2003
– 8.0 – sa VC 2005
– 9.0 – sa VC 2008

• application framework - arhitektura cijelog programa ovisi o biblioteci


CWnd
• bazna klasa za sve prozore
• član:
public:
HWND m_hWnd;

• metode:

virtual BOOL Create(...);


virtual BOOL DestroyWindow();

BOOL Attach(HWND hw);


HWND Detach();
CWnd

• metode:

CWnd* GetParent();
CWnd* GetDlgItem(int id) const;
BOOL ModifyStyle(DWORD remove, DWORD add, UINT flags);
void CenterWindow(CWnd* altParent = NULL);

void GetClientRect(RECT*) const;


BOOL EnableWindow(BOOL enable = TRUE);
void Invalidate(BOOL erase = TRUE);
...
CWinApp

• članovi:

public:
HINSTANCE m_hInstance; // ili AfxGetInstanceHandle();
LPTSTR m_lpCmdLine;
LPCTSTR m_pszAppName; // ili AfxGetAppName();
// iz resursa (AFX_IDS_APP_TITLE)
...

• virtualne metode:

BOOL InitInstance();
int ExitInstance();
int Run();
BOOL OnIdle(LONG count);
...
• uvijek postoji (jedan) globalni objekt klase izvedene iz CWinApp
• globalna funkcija za dohvat (izvedenog) CWinApp objekta

CWinApp* AfxGetApp();
Minimalni program

#include <afxwin.h>

class MyApp : public CWinApp


{
public:
BOOL InitInstance() // virtual
{
CFrameWnd* pFrame = new CFrameWnd;
pFrame->Create(NULL,_T("NWP"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE);
m_pMainWnd = pFrame;
return TRUE;
}
};

MyApp theApp;
Poruke
• prozor koji želi primati poruke mora imati mapu poruka

DECLARE_MESSAGE_MAP() // u tijelu klase

// u .cpp
BEGIN_MESSAGE_MAP(klasa, bazna_klasa)
// poruke
END_MESSAGE_MAP()

• u mapi poruka:

ON_WM_xxx
ON_COMMAND(id, funkcija)

• funkcija = message handler


Primjer sa porukama

class MainWindow : public CFrameWnd


{
protected:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

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


{
MessageBox(_T("Click"));
}
AppWizard
• najbrži način za napraviti novi MFC program
• File/New ... Projects ...MFC AppWizard (exe)
ClassWizard
• modalni dijalog za: dodavanje klasa, dodavanje funkcija za poruke, pronalaženje
postojećih funkcija...
WizardBar
• toolbar sa dijelom funkcionalnosti ClassWizarda
8. predavanje

• MFC
– dijalozi
– kontrole
CDialog
• bazna klasa za sve dijaloge (modalne i nemodalne)
• modalni:
– konstruktor sa resursnim ID (LPCTSTR ili UINT)
– kreiranje prozora - DoModal()
– zatvaranje - EndDialog()

• nemodalni:
– prazni konstruktor
– kreiranje prozora - Create() sa resursnim ID (LPCTSTR ili UINT)
– zatvaranje - DestroyWindow()
primjer modalnog dijaloga

class SimpleDialog : public CDialog {


public:
SimpleDialog(CWnd* parent=NULL) :
CDialog(IDD_DIALOG, parent) {}
protected:
BOOL OnInitDialog(){ // virtual
return CDialog::OnInitDialog();
}
void OnOK() { // virtual
CDialog::OnOK(); // zove EndDialog
}
};
void ShowDialog(){
SimpleDialog dlg;
if(dlg.DoModal() == IDOK){
// ...
}
}
standardni dijalozi
• svi su izvedeni iz klase CCommonDialog:
– CColorDialog
– CFileDialog
– CFindReplaceDialog
– CFontDialog
– CPrintDialog

• primjeri:

COLORREF GetColor tstring GetFile(const TCHAR* filter)


(COLORREF curr) {
{ CFileDialog dlg(TRUE);
CColorDialog dlg(curr); dlg.m_ofn.lpstrFilter = filter;
if(dlg.DoModal() != IDOK) if(dlg.DoModal() != IDOK)
return curr; return tstring()
return dlg.m_cc.rgbResult; return tstring(dlg.GetPathName());
} }
CPropertySheet / CPropertyPage

• dijalog mora imati WS_CHILD (umjesto WS_POPUP)

class Page1 : public CPropertyPage {


public:
Page1() : CPropertyPage(IDD_PAGE1) {}
};

class Page2 : public CPropertyPage {


public:
Page2() : CPropertyPage(IDD_PAGE2) {}
};
void ShowSheet(){
CPropertySheet sheet;
sheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;
Page1 p1; sheet.AddPage(&p1);
Page2 p2; sheet.AddPage(&p2);
sheet.DoModal();
}
kontrole

• kontrole šalju WM_COMMAND

BEGIN_MESSAGE_MAP(SomeDialog, CDialog)
ON_CONTROL(BN_CLICKED, IDC_BUTTON1, OnButtonClicked)
ON_CONTROL(EN_CHANGE, IDC_EDIT1, OnEditChanged)
END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(SomeDialog, CDialog)
ON_BN_CLICKED(IDC_BUTTON1, OnButtonClicked)
ON_EN_CHANGE(IDC_EDIT1, OnEditChanged)
END_MESSAGE_MAP()

• za svaku kontrolu postoji MFC klasa:


– CButton
– CStatic
– CEdit
– CScrollBar
– CListBox
– CComboBox
kontrole

BOOL SomeDialog::OnInitDialog(){
CDialog::OnInitDialog();
CEdit* pEdit = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
pEdit->SetWindowText(_T("abc"));
CListBox* pListBox=static_cast<CListBox*>(GetDlgItem(IDC_LIST1));
pListBox->AddString(_T("prvi"));
pListBox->AddString(_T("drugi"));
return TRUE;
}

void SomeDialog::OnOK() {
CEdit* pEdit = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
CString s; pEdit->GetWindowText(s);
CListBox* pListBox=static_cast<CListBox*>(GetDlgItem(IDC_LIST1));
int selected = pListBox->GetCurSel();
CDialog::OnOK();
}
DDX

class SimpleDialog : public CDialog {


public:
...
CEdit edit;
void DoDataExchange(CDataExchange* pDX){ // virtual
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, edit);
}

BOOL SomeDialog::OnInitDialog(){
CDialog::OnInitDialog();
edit.SetWindowText(_T("abc"));
return TRUE;
}
void SomeDialog::OnOK() {
CString s; edit.GetWindowText(s);
CDialog::OnOK();
}
};
DDX - vrijednosti

class SimpleDialog : public CDialog {


...
public:
CString text;
void DoDataExchange(CDataExchange* pDX){ // virtual
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, text);
}
};

void SomeWnd::ShowDialog(){
SimpleDialog dlg(this);
dlg.text = _T("abc");
if(dlg.DoModal() == IDOK)
MessageBox(dlg.text);
}
DDV

class SimpleDialog : public CDialog {


public:
int n;
double d;
void DoDataExchange(CDataExchange* pDX){ // virtual
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT2, n);
DDV_MinMaxInt(pDX, n, 0, 100);
DDX_Text(pDX, IDC_EDIT1, d);
DDV_MinMaxDouble(pDX, d, -3.14, 3.14);
}

void SomeWnd::ShowDialog(){
SimpleDialog dlg(this);
dlg.n = 15;
dlg.d = -1.25;
dlg.DoModal();
}
"nove" kontrole (common controls)

• obavezan poziv InitCommonControlsEx

• za svaku kontrolu postoji MFC klasa (u zagradi je registrirano ime klase):


– CListCtrl ("SysListView32")
– CTreeCtrl ("SysTreeView32")
– CSpinButtonCtrl ("msctls_updown32")
– CHeaderCtrl ("SysHeader32")
– CSliderCtrl ("msctls_trackbar32")
– CProgressCtrl ("msctls_progress32")
– CComboBoxEx ("ComboBoxEx32")
– CHotKeyCtrl ("msctls_hotkey32")
– CToolTipCtrl ("tooltips_class32")
– CTabCtrl ("SysTabControl32")
– CAnimateCtrl ("SysAnimate32")
– CToolBarCtrl ("ToolbarWindow32")
– CStatusBarCtrl ("msctls_statusbar32")
– CRichEditCtrl ("RICHEDIT")
– CIPAddressCtrl ("SysIPAddress32")
– CDateTimeCtrl ("SysDateTimePick32")
WM_NOTIFY

• nove kontrole šalju WM_NOTIFY


• LPARAM sadrži pointer na NMHDR ili neku strukturu koja sadrži NMHDR

struct NMHDR struct NMLISTVIEW


{ {
HWND hwndFrom; NMHDR hdr;
UINT idFrom; int iItem;
UINT code; int iSubItem;
}; UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
};
WM_NOTIFY

BEGIN_MESSAGE_MAP(SomeDialog, CDialog)
ON_NOTIFY(NM_CLICK, IDC_LIST1, OnListClick)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, OnListItemChanged)
END_MESSAGE_MAP()

void SomeDialog::OnListClick(NMHDR* pnh, LRESULT* pResult) {


...
*pResult = 0;
}

void SomeDialog::OnListItemChanged(NMHDR* pnh, LRESULT* pResult) {


NM_LISTVIEW* pNMListView = reinterpret_cast<NM_LISTVIEW*>(pnh);
...
}
9. predavanje

• dokument/pogled
• MDI
dokument/pogled
• razdvajanje sadržaja (podataka) od prikaza

CDocument CView
CDocument
• komunikacija prema svim pogledima
void UpdateAllViews(CView* sender,LPARAM msg=0,CObject* param=0);

• virtualne funkcije

BOOL OnNewDocument();
BOOL OnOpenDocument(LPCTSTR path);
void DeleteContents()
void SetModifiedFlag(BOOL flag=TRUE);
CView

• pristup svom dokumentu:


CDocument* GetDocument(); // static_cast do izvedenog

• virtualne funkcije:
void OnUpdate(CView* sender, LPARAM msg, CObject* param);
void OnInitialUpdate();
void OnDraw(CDC*);
klase izvedene iz CView
• izvedene iz CCtrlView:
– CEditView
– CRichEditView
– CListView
– CTreeView

• CScrollView
• CFormView - spojena na resurs dijaloga, podržan DDX i DDV

• izvedene iz CFormView:
– CRecordView
– CDaoRecordView
– COleDBRecordView
– CHTMLView
– CHTMLEditView
CSingleDocTemplate
• odnos dokumenta, pogleda i okvira

BOOL MyApp::InitInstance(){
CSingleDocTemplate* pDocTemplate =
new CSingleDocTemplate(IDR_MAINFRAME,
RUNTIME_CLASS(MyDocument),
RUNTIME_CLASS(MainWindow), // MDI frame
RUNTIME_CLASS(MyView));
AddDocTemplate(pDocTemplate); // CWinApp member
...
}

• u resursima, u tablici stringova, pod IDR_MAINFRAME:

NWP 9\nDocument\nNWP 9\nText Files (*.txt)\n.txt\nNWP9.Doc\nNWP9 Doc

default filter u registriranje


naslov naziv tipa
ime FileOpen tipa
programa dokumenta
dokumenta dijalogu datoteke
MDI (multiple document interface)

MDI frame CMDIFrameWnd


(CMainFrame)

MDI client CMDIChildWnd


(CChildFrame)

CView
MDI child
(CxxxView)
CMultiDocTemplate

BOOL MyApp::InitInstance(){
CMultiDocTemplate* pDocTemplate =
new CMultiDocTemplate(IDR_TYPE1,
RUNTIME_CLASS(MyDocument),
RUNTIME_CLASS(CChildFrame), // MDI child
RUNTIME_CLASS(MyView));
AddDocTemplate(pDocTemplate); // CWinApp member
...
}

• u resursima, u tablici stringova, pod IDR_TYPE1 su slične informacije kao za SDI


• ako je više puta pozvan AddDocTemplate (aplikacija podržava više tipova
dokumenata) CWinApp::OnFileNew() podiže dijalog sa listom naziva tipova
10. predavanje

• štampanje
• registrar
• baze podataka
štampanje

• dodatna metoda u klasi CDC


BOOL CDC::IsPrinting() const;
• kompletna podrška u klasi CView

• virtualne funkcije:

void OnPreparePrinting(CPrintInfo*);
void OnBeginPrinting(CDC*, CPrintInfo*);
void OnPrepareDC(CDC*, CPrintInfo*);
void OnPrint(CDC*, CPrintInfo*); // zove OnDraw()
void OnEndPrinting(CDC*, CPrintInfo*);
CPrintInfo

struct CPrintInfo {
CPrintDialog* m_pPD;
BOOL m_bPreview;
BOOL m_bDirect;
BOOL m_bContinuePrinting;
UINT m_nCurPage; • trenutna stranica
UINT m_nNumPreviewPages;
CString m_strPageDesc;
LPVOID m_lpUserData;
CRect m_rectDraw;
BOOL m_bDocObject;
void SetMinPage(UINT nMinPage);
void SetMaxPage(UINT nMaxPage);
UINT GetMinPage() const;
UINT GetMaxPage() const;
UINT GetFromPage() const;
UINT GetToPage() const;
UINT GetOffsetPage() const;
};
registrar / konfiguracijska datoteka (.ini file)

; nwp10.ini
[Font]
Height=12
FaceName=Arial

• jednak pristup registraru i konfiguracijskoj datoteci - članovi CWinApp:

UINT GetProfileInt(LPCTSTR section, LPCTSTR entry, int def);


CString GetProfileString(LPCTSTR section, LPCTSTR entry, LPSTSTR def=0);
BOOL WriteProfileInt(LPCTSTR section, LPCTSTR entry, int value);
BOOL WriteProfileString(LPCTSTR section, LPCTSTR entry, LPCTSTR value);

• ako se pozove SetRegistryKey koristi se registrar

SetRegistryKey(_T("VEST"));
baze podataka
• 3 načina pristupa bazama podataka:
– ODBC
– DAO
– OLE DB

• MFC ima podršku za


– ODBC: CDatabase, CRecordset
– DAO: CDaoWorkspace, CDaoDatabase, CDaoRecordset

• za pristup preko OLE DB koriste se OLE DB templates iz ATL-a :


CDataSource, CSession, CAccessor<>, CRowset<>
CRecordset
• CDatabase se uglavnom koristi direktno, a iz CRecordset se izvodi
• virtualne funkcije CRecordset:
CString GetDefaultConnect();
CString GetDefaultSQL();
void DoFieldExchange(CFieldExchange*);

• primjer (vest je System DSN, User je tablica)

class RecSet : public CRecordset


{
public:
CString GetDefaultConnect(){ return _T("ODBC;DSN=vest");}
CString GetDefaultSQL(){ return _T("[User]"); }
...
};
CRecordset
• iteriranje kroz record set
RecSet rs;
rs.Open();
while(!rs.IsEOF()){
...
rs.MoveNext();
}

• ako je potrebno postaviti filter ili sort, koriste se članovi CRecordeset

RecSet rs;
rs.m_strFilter = _T("[id] > 100");
rs.m_strSort = _T("[name] DESC");
rs.Open();
...
RFX (record field exchange)
class RecSet : public CRecordset {
public:
long id;
CString name;
BOOL manager;
...
};

void RecSet::DoFieldExchange(CFieldExchange* pFX)


{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Long(pFX, _T("[id]"), id);
RFX_Text(pFX, _T("[name]"), name);
RFX_Bool(pFX, _T("[manager]"), manager);
}
11. predavanje

• Fluent UI
• ribbon
Fluent User Interface

• uveden prvi puta u MS Office 2007

• korištenje je licencirano – licenca je besplatna, ali se ne može dobiti za aplikacije


koje konkuriraju Office aplikacijama

• uključuje:
– ribbon
– poboljšane context menije
– bolje screen-tips
– mini toolbar
– keyboard shortcuts
Windows Ribbon Framework

• dio Win32 API-a od Windows 7

• zasnovan na COM interface-ima

• implementira framework:
– IUIFramework
– IUIRibbon
– IUIContextualUI
– IUISimplePropertySet, IUICollection
– IUIImage, IUIImageFromBitmap

• implementira aplikacija:
– IUIApplication
– IUICommandHandler
– IUICollectionChangedEvent
Ribbon - dijelovi
CMFCRibbonCategory CMFCRibbonPanel

CMFCRibbonApplicationButton
(otvara CMFCRibbonMainPanel)

CMFCRibbonBar

CMFCRibbonStatusBar

ribbon gadgets
Ribbon gadgets

• kontrole:
– CMFCRibbonButton (small, large), CMFCRibbonButtonsGroup, CMFCRibbonGallery
– CMFCRibbonColorButton, CMFCRibbonUndoButton
– CMFCRibbonLabel, CMFCRibbonLinkCtrl
– CMFCRibbonCheckBox
– CMFCRibbonEdit
– CMFCRibbonComboBox, CMFCRibbonFontComboBox
– CMFCRibbonSlider
– CMFCRibbonProgressBar
Ribbon designer

• uveden prvi puta u VS 2010 kao dio editora resursa

• novi tip resursa: RT_RIBBON_XML

• sprema se u XML datoteku sa ekstenzijom .mfcribbon-ms

• CMFCRibbonBar::LoadFromResource() za učitavanje

• CMFCRibbonBar::SaveToXMLFile() za konverziju starog koda

Вам также может понравиться