..::Rozd∞lenφ okna II::..

╚asto pot°ebujete rozd∞lit okno na n∞kolik Φßstφ. Jednou mo₧nostφ je pou₧φt t°φdu CSplitterWnd, jak bylo popsßno v p°edchozφ Φßsti, nebo si to celΘ naprogramovat sßm, co₧ nenφ tak slo₧itΘ jak se zdß. Mß to jednu v²hodu a jednu nev²hodu. Nev²hoda je, ₧e nßmi rozd∞lenΘmu oknu nelze m∞nit pomocφ myÜi velikost jednotliv²ch Φßstφ. (Ale to n∞kdy p°φmo vy₧adujeme. V²hodou je, ₧e m∙₧eme nastavit po₧adovanΘ velikosti oken jako urΦit² dφl rßmcovΘho okna. To jde s CSplitterWnd takΘ, ale nenφ to tak elegantnφ. Postup si ukß₧eme na nßsledujφcφm p°φklad∞.

Vytvo°φme si aplikaci, kterß bude mφt okno rozd∞lenΘ na t°i Φßsti. Jedna bude od levΘho okraje okna do 1/5 jeho Üφ°ky a od hornφho okraje po dolnφ okraj mφnus padesßt pixel∙. DruhΘ bude od levΘho po prav² okraj okna a od dolnφho okraje bez padesßti pixel∙ po dolnφ okraj. A t°etφ je zbytek. Bude to vypadat asi takto:

ZaΦneme tφm, ₧e si pomocφ AppWizardu vytvo°φme kostru svojφ aplikace. M∙₧e to b²t libovoln² typ aplikace. Pro p°edchozφ obrßzek a pro vysv∞tlenφ bylo pou₧ito nastavenφ Single document bez architektury dokument/pohled. Pokud pou₧ijete architekturu dokument pohled, tak to co budu dßle popisovat pro t°φdu rßmce bude platit pro t°φdu pohledu a budete muset p°idat o okno vφce, proto₧e v p°φkladu vyu₧iji t°φdu pohledu implicitn∞ vytvo°enou AppWizardem.

Nejd°φve si vytvo°φme dalÜφ dv∞ t°φdy okna. Jako t°etφ vyu₧ijeme CChildView vygenerovanou AppWizardem. HlaviΦkovΘ soubory t∞chto dvou nov²ch t°φd p°idßme do hlaviΦkovΘho souboru naÜeho rßmcovΘho okna pomocφ p°φkazu include. Dßle p°idßme do t°φdy rßmce dv∞ prom∞nnΘ naÜich nov²ch t°φd okna. Tak₧e v rßmci mßme u₧ t°i prom∞nnΘ okna:

CChildView m_wndView;

CWnd1 w1;

CWnd2 w2;

Dßle do funkce OnCreate naÜeho rßmce dopφÜeme dva novΘ °ßdky pro vytvo°enφ naÜich dvou dalÜφch oken a upravφme vytvß°enφ p∙vodnφho d∞tskΘho okna m_wndView. Zm∞ny ve funkci generovanΘ AppWizardem jsou oznaΦeny podbarvenφm.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

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

return -1;

// create a view to occupy the client area of the frame

if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,

CRect(0, 0, 10, 10), this, AFX_IDW_PANE_FIRST, NULL))

{

TRACE0("Failed to create view window\n");

return -1;

}

 

if (!w1.Create(NULL,NULL,WS_CHILD|WS_VISIBLE,CRect(10,10,20,20),this,0,NULL)) return -1;

if (!w2.Create(NULL,NULL,WS_CHILD|WS_VISIBLE,CRect(30,30,40,40),this,0,NULL)) return -1;

...

...

...

}

Jist∞ jste si vÜimli, ₧e okna nevytvß°φme na t∞ch mφstech, kde je budeme po₧adovat. To proto, ₧e jejich poloha se bude m∞nit v reakci na zprßvu WM_SIZE. Ale jeÜt∞ ne₧ se k tomu dostaneme, musφme upravit vlastnosti okna, jinak nebudou zapuÜt∞na do hloubky jak majφ b²t a nebudou mφt ₧ßdnΘ pozadφ. Pro svß dv∞ novß okna p°etφ₧φme virtußlnφ funkci PreCreateWindow a zkopφrujeme do nφ k≤d okna m_wndView generovan² AppWizardem. Tak₧e bude vypadat takto:

BOOL CWnd1::PreCreateWindow(CREATESTRUCT& cs)

{

if (!CWnd::PreCreateWindow(cs)) return FALSE;

 

cs.dwExStyle |= WS_EX_CLIENTEDGE;    // P°idß urΦit² typ rßmeΦku (zapuÜt∞nφ do hloubky)

cs.style &= ~WS_BORDER;    // ZruÜφ jin² typ rßmeΦku (Φernß Φßra okolo) pokud je nastaven

cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,

::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);    // Zaregistruje t°φdu okna

 

return TRUE;

}

A te∩ se ji₧ dostßvßme k vlastnφmu nastavenφ pozice oken.  V naÜem rßmcovΘm okn∞ odchytφme zprßvu WM_SIZE (funkce OnSize), kterß se vyvolß v₧dy, kdy₧ se zm∞nφ velikost okna a upravφme ji, tak₧e bude vypadat takto:

void CMainFrame::OnSize(UINT nType, int cx, int cy)

{

CFrameWnd::OnSize(nType, cx, cy);

 

// TODO: Add your message handler code here

CRect rc,r;    // PomocnΘ prom∞nnΘ

GetClientRect(rc);    // ZjiÜt∞nφ velikosti klientskΘ plochy naÜeho rßmcovΘho okna

r.SetRect(0,24,rc.Width()/5,rc.Height()-50);    // V²poΦet obdΘlnφku prvnφho okna

w1.MoveWindow(r);    // P°esuneme prvnφ okno na vypoΦtenou pozici

r.SetRect(rc.left,rc.bottom-50,rc.right,rc.bottom);    // V²poΦet obdΘlnφku druhΘho okna

w2.MoveWindow(r);    // P°esuneme druhΘ okno na vypoΦtenou pozici

r.SetRect(rc.Width()/5,24,rc.Width(),rc.Height()-50);    // V²poΦet obdΘlnφku t°etφho (p∙vodnφho) okna

m_wndView.MoveWindow(r);    // P°esuneme t°etφ okno na vypoΦtenou pozici

}

Jist∞ se divφte proΦ jsou v k≤du podbarvenφm zv²razn∞nΘ Φφslice 24. Jsou zv²razn∞nΘ, proto₧e by mφsto nich m∞ly b²t nuly, ale to by naÜe okna p°ekryla panel nßstroj∙ a ten by nebyl vid∞t a ani by nefungoval. Proto jsou tam dvacetΦty°ky.

 

Jist∞ vßs napadlo, ₧e pomocφ funkce MoveWidnow a zprßvy WM_MOVE lze nastavit vzßjemnou pozici dvou oken. Pokud to budete d∞lat, tak je dobrΘ p°ed volßnφm MoveWindow zkontrolovat zda okno existuje a zda je zobrazenΘ. (Funkce IsWindow a IsWindowVisible.)

A to je pro dneÜek vÜe.