Jist∞ jste ji₧ n∞kdy potkali aplikaci, kterß se sklßdala z n∞kolika oken a kdy₧ jste pohli hlavnφm oknem, tak se zßrove≥ pohla i ostatnφ okna. Klasick²m p°φkladem je Winamp. Mo₧nß jste i p°em²Üleli jak to naprogramovat. Pokud jste to nevymysleli sami, tak tady se doΦtete jak se to dß ud∞lat.
Asi nejlepÜφm zp∙sobem jak to vysv∞tlit je vypsat zm∞n∞nΘ Φßsti zdrojovΘho k≤du a popsat je.
Zdrojov² k≤d si m∙₧ete stßhnout zde.
ZaΦal jsem vygenerovßnφm aplikace pomocφ AppWizardu s nastavenφm architektura dokument/pohled, SDI
Potom jsem p°idal do t°φdy hlavnφho okna aplikace (CMainFrame) t°i prom∞nnΘ:
...
private:
CFrameWnd* pWnd; // Ukazatel na naÜe p°ipojenΘ okno
int rx,ry; // Relativnφ poloha p°ipojenΘho okna k hlavnφmu oknu aplikace
...
V konstruktoru jsem nastavil jejich v²chozφ hodnoty:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
...
...
...
CRect rc;
GetWindowRect(rc); // Zjistφme polohu hlavnφho okna
rx = rc.Width(); // Nastavφme relativnφ polohu v x na Üφ°ku hlavnφho okna
ry = 0; // Nastavφme relativnφ polohu v y na nulu
// alokace pam∞ti
pWnd = new CFrameWnd;
if (!pWnd)
{
return -1;
}
/*
Vytvo°enφ p°ipojenΘho okna
Parametry funkce CreateEx znamenajφ toto (v po°adφ jak jsou ve funkci):
0 - EX styl okna
AfxRegisterWndClass(...) - funkce pro registraci t°φdy okna
"Nßhled" - titulek okna
WS_BORDER|WS_VISIBLE - styl okna - s rßmeΦkem a viditelnΘ
CRect(rc.left+rx,rc.top+ry,rc.left+rx+100,rc.top+ry+100)
- poloha p°ipojenΘho okna
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x + po₧adovanß Üφ°ka p°ipojenΘho okna
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y + po₧adovanß v²Üka p°ipojenΘho okna
this - ukazatel na rodiΦovskΘ okno
- m∙₧ete dßt na NULL, ale v tom p°φpad∞ se vßm i p°ipojenΘ okno zobrazφ na hlavnφm panelu
0 - identifikßtor okna
*/
if(!pWnd->CreateEx(0,AfxRegisterWndClass(0,0,::GetSysColorBrush(COLOR_WINDOW),0),"Nßhled",WS_BORDER|WS_VISIBLE,CRect(rc.left+rx,rc.top+ry,rc.left+rx+100,rc.top+ry+100),this,0))
{
delete pWnd;
return -1;
}
return 0;
}
Nßsleduje vlastnφ pohyb p°ipojen²m oknem. Ten se provßdφ ve funkci OnMove hlavnφho okna. (Reakce na WM_MOVE, kterß se volß v₧dy, kdy₧ se pohne hlavnφ okno.
void CMainFrame::OnMove(int x, int y)
{
CFrameWnd::OnMove(x, y);
// Zkontrolujeme zda mßme platn² ukazatel, zda je p°ipojenΘ okno inicializovanΘ a zda je viditelnΘ
if (pWnd&&::IsWindow(pWnd->m_hWnd)&&::IsWindowVisible(pWnd->m_hWnd))
{
CRect rc,rcp;
GetWindowRect(rcp); // Zφskßme novou polohu hlavnφho okna
pWnd->GetWindowRect(rc); // Zφskßme polohu p°ipojenΘho okna
/*
VypoΦteme novou polohu p°ipojenΘho okna
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x + Üφ°ka p°ipojenΘho okna
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y + v²Üka p°ipojenΘho okna
*/
rc.SetRect(rcp.left+rx,rcp.top+ry,rcp.left+rx+rc.Width(),rcp.top+ry+rc.Height());
pWnd->MoveWindow(rc); // Nastavφme novou polohu p°ipojenΘho okna
}
}
Pokud chceme, aby se p°ipojenΘ okno stßle dot²kalo hlavnφho okna, musφme jeÜt∞ reagovat na zm∞nu velikosti hlavnφho okna. To provßdφme ve funkci OnSize hlavnφho okna. (Reakce na WM_SIZE.)
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
/*
Tato funkce je volßna p°i zm∞n∞ velikosti hlavnφho okna.
Je upravovßna aby se p°ipojenΘ okno dr₧elo vpravo hned vedle hlavnφho okna
Pokud chcete aby se p°ipojenΘ okno dr₧elo v zadanΘ poloze vzhledem k levΘmu
hornφmu rohu hlavniho okna a ne vpravo hned vedle n∞j, tak sma₧te (nebo zakomentß°ujte
nßsledujφcφ k≤d).
Zkontrolujeme zda mßme platn² ukazatel,
zda je p°ipojenΘ okno inicializovanΘ a zda je viditelnΘ
*/
if (pWnd&&::IsWindow(pWnd->m_hWnd)&&::IsWindowVisible(pWnd->m_hWnd))
{
CRect rc,rcp;
GetWindowRect(rcp); // Zφskßme novou polohu hlavnφho okna
rx = rcp.Width(); // Zm∞nφme relativnφ polohu v x na novou Üφ°ku okna
pWnd->GetWindowRect(rc); // Zφskßme polohu p°ipojenΘho okna
/*
VypoΦteme novou polohu p°ipojenΘho okna
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y
- poloha levΘ strany hlavnφho okna + relativnφ poloha v x + Üφ°ka p°ipojenΘho okna
- poloha hornφ strany hlavnφho okna + relativnφ poloha v y + v²Üka p°ipojenΘho okna
*/
rc.SetRect(rcp.left+rx,rcp.top+ry,rcp.left+rx+rc.Width(),rcp.top+ry+rc.Height());
pWnd->MoveWindow(rc); // Nastavφme novou polohu p°ipojenΘho okna
}
}
A to je vÜe.