При запуске программы Switch текст в нижней части меню подсказывает, какие клавиши управляют работой приложения. Клавиши со стрелками изменяют текущий выделенный видеорежим, клавиша Enter активизирует его (если он не является текущим), а клавиша Escape завершает работу программы. Все эти клавиши обрабатываются функцией OnKeyDown(), создаваемой ClassWizard. Ее код приведен в листинге 4.5.
Листинг 4.5. Функция SwitchWin::OnKeyDown()
| void SwitchWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { int newindex; int nmodes=GetNumDisplayModes(); if (nmodes>maxmodes) nmodes=maxmodes; int rows=nmodes/menucols; if (nmodes%menucols) rows++;
switch (nChar) { case VK_ESCAPE: PostMessage( WM_CLOSE ); break; case VK_UP: newindex=selectmode-1; if (newindex>=0) { selectmode=newindex; UpdateMenuSurface(); } break; case VK_DOWN: newindex=selectmode+1; if (newindex<nmodes) { selectmode=newindex; UpdateMenuSurface(); } break; case VK_LEFT: newindex=selectmode-rows; if (newindex>=0) { selectmode=newindex; UpdateMenuSurface(); } break; case VK_RIGHT: newindex=selectmode+rows; if (newindex<nmodes) { selectmode=newindex; UpdateMenuSurface(); } break; case VK_RETURN: if (selectmode != GetCurDisplayMode()) { ActivateDisplayMode( selectmode ); x=y=0; } break; case 'S': SaveSurface( primsurf, "switch.bmp" ); break; case 'M': SaveSurface( menusurf, "menusurf.bmp" ); break; case 'F': SaveSurface( fpssurf, "fpssurf.bmp" ); break; case 'T': SaveSurface( bmpsurf, "trisurf.bmp" ); break; default: DirectDrawWin::OnKeyDown(nChar, nRepCnt, nFlags); } } |
Теперь в программу необходимо включить код для обработки пользовательского ввода при работе с меню частот. Мы воспользуемся функцией OnKeyDown() (листинг 4.7).
Листинг 4.7. Функция SuperSwitch::OnKeyDown()
| void SuperSwitchWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { int newindex; int nmodes=GetNumDisplayModes(); if (nmodes>maxmodes) nmodes=maxmodes; int rows=nmodes/menucols; if (nmodes%menucols) rows++;
switch (nChar) { case VK_ESCAPE: if (!include_refresh || !ratemenu_up) { PostMessage( WM_CLOSE ); break; } if (ratemenu_up) { ratemenu_up=FALSE; if (ratemenusurf) ratemenusurf->Release(), ratemenusurf=0; } break; case VK_UP: if ( include_refresh && ratemenu_up) { if (selectrate>0) { selectrate--; UpdateRateMenuSurface(); } } else { newindex=selectmode-1; if (newindex>=0) { selectmode=newindex; UpdateModeMenuSurface(); } } break; case VK_DOWN: if (include_refresh && ratemenu_up) { if (selectrate<numrates-1) { selectrate++; UpdateRateMenuSurface(); } } else { newindex=selectmode+1; if (newindex<nmodes) { selectmode=newindex; UpdateModeMenuSurface(); } } break; case VK_LEFT: if (include_refresh && ratemenu_up) break; newindex=selectmode-rows; if (newindex>=0) { selectmode=newindex; UpdateModeMenuSurface(); } break; case VK_RIGHT: if (include_refresh && ratemenu_up) break; newindex=selectmode+rows; if (newindex<nmodes) { selectmode=newindex; UpdateModeMenuSurface(); } break; case VK_RETURN: if (include_refresh) { if (ratemenu_up) { int rate=refresh_rates[selectmode][selectrate]; ActivateDisplayMode( selectmode, rate ); x=y=0; ratemenu_up=FALSE; } else { CreateRateMenuSurface(); UpdateRateMenuSurface(); ratemenu_up=TRUE; } } else { if (selectmode!=GetCurDisplayMode()) { ActivateDisplayMode( selectmode ); x=y=0; } } break; case 'S': SaveSurface( primsurf, "SuperSwitch.bmp" ); break; default: DirectDrawWin::OnKeyDown(nChar, nRepCnt, nFlags); } } |
Давайте посмотрим, как в нашей программе организована обработка ввода. Нажатые клавиши обрабатываются функций OnKeyDown(), которая выглядит так:
| void BmpViewWin::OnKeyDown(UINT key, UINT nRepCnt, UINT nFlags) { switch (key) { case VK_UP: Up(); break; case VK_DOWN: Down(); break; case VK_LEFT: Left(); break; case VK_RIGHT: Right(); break; case VK_HOME: Home(); break; case VK_END: End(); break; case VK_PRIOR: PageUp(); break; case VK_NEXT: PageDown(); break; case VK_ESCAPE: case VK_SPACE: case VK_RETURN: ShowDialog(); break; }
DirectDrawWin::OnKeyDown(key, nRepCnt, nFlags); } |
Остальные восемь функций, вызываемых функцией OnKeyDown(), изменяют положение поверхности во время прокрутки:
Каждая из этих функций определяет положение поверхности по значениям переменных x, y, xlimit, ylimit, xscroll и yscroll. Код всех восьми функций приведен в листинге 5.9.
Листинг 5.9. Функции смещения поверхности
| void BmpViewWin::Up(int inc) { if (!yscroll) return;
if (y+inc<0) { y+=inc; update_screen=TRUE; } else { y=0; update_screen=TRUE; } } void BmpViewWin::Down(int inc) { if (!yscroll) return; if (y-inc>=ylimit) { y-=inc; update_screen=TRUE; } else { y=ylimit; update_screen=TRUE; } } void BmpViewWin::Left(int inc) { if (!xscroll) return; if (x+inc<0) { x+=inc; update_screen=TRUE; } else { x=0; update_screen=TRUE; } } void BmpViewWin::Right(int inc) { if (!xscroll) return; if (x-inc>=xlimit) { x-=inc; update_screen=TRUE; } else { x=xlimit; update_screen=TRUE; } } void BmpViewWin::Home() { if (xscroll && x!=0) { x=0; update_screen=TRUE; } if (yscroll && y!=0) { y=0; update_screen=TRUE; } } void BmpViewWin::End() { if (yscroll) { y=-(bmprect.Height()-displayrect.Height()); update_screen=TRUE; } if (xscroll) { x=-(bmprect.Width()-displayrect.Width()); update_screen=TRUE; } } void BmpViewWin::PageUp() { if (yscroll) { if (y-displayrect.Height()>0) { y-=displayrect.Height(); update_screen=TRUE; } else { y=0; update_screen=TRUE; } } } void BmpViewWin::PageDown() { if (yscroll) { if (y+displayrect.Height()<=ylimit) { y+=displayrect.Height(); update_screen=TRUE; } else { y=ylimit; update_screen=TRUE; } } } |
В программе AviPlay ввод не играет особой роли. Программа реагирует всего на три клавиши, причем одинаково. Ввод с клавиатуры обрабатывается функцией OnKeyDown():
| void AviPlayWin::OnKeyDown(UINT key, UINT nRepCnt, UINT nFlags) { switch (key) { case VK_ESCAPE: case VK_SPACE: case VK_RETURN: ShowDialog(); break; }
DirectDrawWin::OnKeyDown(key, nRepCnt, nFlags); } Все три клавиши вызывают функцию ShowDialog(). Аналогично обрабатывается и ввод от мыши, это происходит в функции OnRButtonDown(): void AviPlayWin::OnRButtonDown(UINT nFlags, CPoint point) { ShowDialog(); DirectDrawWin::OnRButtonDown(nFlags, point); } |
| void AviPlayWin::OnRButtonDown(UINT nFlags, CPoint point) { ShowDialog(); DirectDrawWin::OnRButtonDown(nFlags, point); } |