Обработка пользовательского ввода



Теперь в программу необходимо включить код для обработки пользовательского ввода при работе с меню частот. Мы воспользуемся функцией 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); } }

Все case-секции оператора switch были изменены для работы с новым меню. При нажатии клавиши Escape программа по-прежнему завершает работу, если меню частот в данный момент не отображается; тем не менее, если меню присутствует на экране, клавиша Escape просто скрывает его. Действие клавиш со стрелками также зависит от состояния меню. Если меню частот отображается, стрелки ­ и изменяют выделенную частоту, а если нет — выделенный пункт в меню видеорежимов.
Самые существенные различия связаны с обработкой клавиши Enter. Если во время нажатия клавиши Enter меню частот не отображается, мы вызываем функции CreateRateMenuSurface() и UpdateRateMenuSurface() и присваиваем флагу ratemenu_up значение TRUE. Давайте рассмотрим эти две функции. Функция CreateRateMenuSurface() выглядит так:

BOOL SuperSwitchWin::CreateRateMenuSurface() { if (ratemenusurf) ratemenusurf->Release(), ratemenusurf=0; int rates=refresh_rates[selectmode].GetSize(); ratemenusurf=CreateSurface( 80, rates*12+22 ); return TRUE; }

Сначала эта функция освобождает существующую поверхность (если таковая была создана ранее). Затем она определяет количество частот для выделенного в меню видеорежима и рассчитывает по ним размеры поверхности меню частот. Поверхность создается версией CreateSurface(), которой передаются ширина и высота новой поверхности.
Функция UpdateRateMenuSurface() отвечает за отображение текста меню. Выглядит она так:

BOOL SuperSwitchWin::UpdateRateMenuSurface() { RECT rect; GetSurfaceRect( ratemenusurf, rect ); rect.left++; rect.top++; rect.right--; rect.bottom--; if (!ClearSurface( ratemenusurf, 0, 200, 132 )) TRACE("first Clear failed\n"); if (!ClearSurface( ratemenusurf, 0,128,100, &rect )) TRACE("second Clear failed\n"); HDC hdc; ratemenusurf->GetDC( &hdc ); SelectObject( hdc, smallfont ); SetBkMode( hdc, TRANSPARENT ); SetTextColor( hdc, ratetextshadow ); ExtTextOut(hdc, 6, 4, 0, 0, rateheader, strlen(rateheader), 0 ); SetTextColor( hdc, ratetextcolor ); ExtTextOut(hdc, 5, 3, 0, 0, rateheader, strlen(rateheader), 0 ); CArray<DWORD,DWORD>& ratelist=refresh_rates[selectmode]; numrates=ratelist.GetSize(); for (int i=0; i<numrates; i++) { char buf[10]; int len=sprintf( buf, "%d hz", ratelist[i] ); SetTextColor( hdc, ratetextshadow ); ExtTextOut(hdc, 11, i*12+18, 0, 0, buf, len, 0 ); if (i==selectrate) SetTextColor( hdc, ratehighlightcolor ); else SetTextColor( hdc, ratetextcolor ); ExtTextOut(hdc, 10, i*12+17, 0, 0, buf, len, 0 ); } ratemenusurf->ReleaseDC( hdc ); return TRUE; }

Прежде всего функция очищает поверхность, вызывая ClearSurface(). Затем содержимое массива refresh_rates используется для вывода текстовых строк, связанных с каждым пунктом меню. Вывод текста, как обычно, осуществляется функцией GetDC() интерфейса DirectDrawSurface в сочетании с текстовыми функциями Win32. Перед выходом из функции UpdateRateMenuSurface() контекст устройства, полученный функцией GetDC(), освобождается с помощью функции ReleaseDC().


Содержание Назад Вперед