..::Konstantnφ poloha okna vzhledem k jinΘmu oknu::..

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.