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
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
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& ratelist=refresh_rates[selectmode];
numrates=ratelist.GetSize();
for (int i=0; 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().
Читать дальше