/* Copyright (C) 2005 TightVNC Team. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ // -=- PlayerToolBar.cxx #include <rfbplayer/rfbplayer.h> #include <rfbplayer/resource.h> PlayerToolBar::PlayerToolBar() : ToolBar(), hFont(0), timeStatic(0), speedEdit(0), posTrackBar(0), speedUpDown(0), sliderDragging(false), sliderStepMs(0) { } void PlayerToolBar::create(RfbPlayer *player_, HWND parentHwnd_) { HDC hdc; SIZE sz; RECT tRect; NONCLIENTMETRICS nonClientMetrics; player = player_; // Get the default font for the main menu nonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS); if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nonClientMetrics, 0)) MessageBox(0, "Can't access to the system font.", "RfbPlayer", MB_OK | MB_ICONERROR); nonClientMetrics.lfMenuFont.lfHeight = 16; hFont = CreateFontIndirect(&nonClientMetrics.lfMenuFont); // Create the toolbar panel ToolBar::create(ID_TOOLBAR, parentHwnd_, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | CCS_NORESIZE); addBitmap(4, IDB_TOOLBAR); // Create the control buttons addButton(0, ID_PLAY); addButton(1, ID_PAUSE); addButton(2, ID_STOP); addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); // Create the static control for the time output timeStatic = CreateWindowEx(0, "Static", "00m:00s (00m:00s)", WS_CHILD | WS_VISIBLE, 0, 0, 20, 20, getHandle(), (HMENU)ID_TIME_STATIC, GetModuleHandle(0), 0); SendMessage(timeStatic, WM_SETFONT,(WPARAM) hFont, TRUE); hdc = GetDC(timeStatic); SelectObject(hdc, hFont); GetTextExtentPoint32(hdc, "00m:00s (00m:00s)", 16, &sz); addButton(sz.cx + 10, 0, TBSTATE_ENABLED, TBSTYLE_SEP); addButton(0, 10, TBSTATE_ENABLED, TBSTYLE_SEP); getButtonRect(4, &tRect); MoveWindow(timeStatic, tRect.left, tRect.top+2, tRect.right-tRect.left, tRect.bottom-tRect.top, FALSE); // Create the trackbar control for the time position addButton(200, 0, TBSTATE_ENABLED, TBSTYLE_SEP); getButtonRect(6, &tRect); posTrackBar = CreateWindowEx(0, TRACKBAR_CLASS, "Trackbar Control", WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, tRect.left, tRect.top, tRect.right-tRect.left, tRect.bottom-tRect.top, parentHwnd, (HMENU)ID_POS_TRACKBAR, GetModuleHandle(0), 0); // It's need to send notify messages to toolbar parent window SetParent(posTrackBar, getHandle()); addButton(0, 10, TBSTATE_ENABLED, TBSTYLE_SEP); // Create the label with "Speed:" caption HWND speedStatic = CreateWindowEx(0, "Static", "Speed:", WS_CHILD | WS_VISIBLE, 0, 0, 5, 5, getHandle(), (HMENU)ID_SPEED_STATIC, GetModuleHandle(0), 0); SendMessage(speedStatic, WM_SETFONT,(WPARAM) hFont, TRUE); hdc = GetDC(speedStatic); SelectObject(hdc, hFont); GetTextExtentPoint32(hdc, "Speed:", 6, &sz); addButton(sz.cx + 10, 0, TBSTATE_ENABLED, TBSTYLE_SEP); getButtonRect(8, &tRect); MoveWindow(speedStatic, tRect.left, tRect.top+2, tRect.right-tRect.left, tRect.bottom-tRect.top, FALSE); // Create the edit control and the spin for the speed managing addButton(60, 0, TBSTATE_ENABLED, TBSTYLE_SEP); getButtonRect(9, &tRect); speedEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "1.00", WS_CHILD | WS_VISIBLE | ES_RIGHT, tRect.left, tRect.top, tRect.right-tRect.left, tRect.bottom-tRect.top, parentHwnd, (HMENU)ID_SPEED_EDIT, GetModuleHandle(0), 0); SendMessage(speedEdit, WM_SETFONT,(WPARAM) hFont, TRUE); // It's need to send notify messages to toolbar parent window SetParent(speedEdit, getHandle()); speedUpDown = CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER | UDS_ALIGNRIGHT, 0, 0, 0, 0, getHandle(), ID_SPEED_UPDOWN, GetModuleHandle(0), speedEdit, 20, 1, 2); // Resize the toolbar window autoSize(); } void PlayerToolBar::init(long sessionTimeMs_) { sessionTimeMs = sessionTimeMs_; setSessionTimeStr(sessionTimeMs); SendMessage(posTrackBar, TBM_SETRANGE, TRUE, MAKELONG(0, min(sessionTimeMs / 1000, MAX_POS_TRACKBAR_RANGE))); if (sessionTimeMs == 0) { sliderStepMs = 1; } else { sliderStepMs = sessionTimeMs / SendMessage(posTrackBar, TBM_GETRANGEMAX, 0, 0); } updatePos(0); } void PlayerToolBar::enable() { enableButton(ID_PLAY, true); enableButton(ID_PAUSE, true); enableButton(ID_STOP, true); enableButton(ID_FULLSCREEN, true); EnableWindow(posTrackBar, true); EnableWindow(speedEdit, true); EnableWindow(speedUpDown, true); } void PlayerToolBar::disable() { enableButton(ID_PLAY, false); enableButton(ID_PAUSE, false); enableButton(ID_STOP, false); enableButton(ID_FULLSCREEN, false); EnableWindow(posTrackBar, false); EnableWindow(speedEdit, false); EnableWindow(speedUpDown, false); } LRESULT PlayerToolBar::processWM_COMMAND(WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { case ID_RETURN: // Update the speed if return pressed in speedEdit if (getSpeedEditHwnd() == GetFocus()) { char speedStr[20], *stopStr; GetWindowText(getSpeedEditHwnd(), speedStr, sizeof(speedStr)); double speed = strtod(speedStr, &stopStr); if (speed > 0) { speed = min(MAX_SPEED, speed); } else { speed = player->getSpeed(); } player->setSpeed(speed); return FALSE; } } return TRUE; } LRESULT PlayerToolBar::processWM_HSCROLL(WPARAM wParam, LPARAM lParam) { long Pos = SendMessage(posTrackBar, TBM_GETPOS, 0, 0); Pos *= sliderStepMs; switch (LOWORD(wParam)) { case TB_PAGEUP: case TB_PAGEDOWN: case TB_LINEUP: case TB_LINEDOWN: case TB_THUMBTRACK: sliderDragging = true; updatePos(Pos); return FALSE; case TB_THUMBPOSITION: case TB_ENDTRACK: player->setPos(Pos); player->setPaused(player->isPaused());; updatePos(Pos); sliderDragging = false; return FALSE; default: break; } return TRUE; } LRESULT PlayerToolBar::processWM_NOTIFY(WPARAM wParam, LPARAM lParam) { switch (((NMHDR*)lParam)->code) { case UDN_DELTAPOS: if ((int)wParam == ID_SPEED_UPDOWN) { char speedStr[20] = "\0"; DWORD speedRange = SendMessage(speedUpDown, UDM_GETRANGE, 0, 0); LPNM_UPDOWN upDown = (LPNM_UPDOWN)lParam; double speed; // The out of range checking if (upDown->iDelta > 0) { speed = min(upDown->iPos + upDown->iDelta, LOWORD(speedRange)) * 0.5; } else { // It's need to round the UpDown position if ((upDown->iPos * 0.5) != player->getSpeed()) { upDown->iDelta = 0; } speed = max(upDown->iPos + upDown->iDelta, HIWORD(speedRange)) * 0.5; } player->setSpeed(speed); } } // We always return TRUE to prevent the change in the updown contol // position. The control's position changes in the RfbPlayer::setSpeed(). return TRUE; } void PlayerToolBar::updatePos(long newPos) { // Update time pos in static control char timePos[30] = "\0"; long time = newPos / 1000; sprintf(timePos, "%.2um:%.2us (%s)", time/60, time%60, fullSessionTimeStr); SetWindowText(timeStatic, timePos); // Update the position of slider if (!sliderDragging) { double error = SendMessage(posTrackBar, TBM_GETPOS, 0, 0) * sliderStepMs / double(newPos); if (!((error > 1 - CALCULATION_ERROR) && (error <= 1 + CALCULATION_ERROR))) { SendMessage(posTrackBar, TBM_SETPOS, TRUE, newPos / sliderStepMs); } } } void PlayerToolBar::setSessionTimeStr(long sessionTimeMs) { sprintf(fullSessionTimeStr, "%.2um:%.2us", sessionTimeMs / 1000 / 60, sessionTimeMs / 1000 % 60); } void PlayerToolBar::setTimePos(long pos) { SendMessage(posTrackBar, TBM_SETPOS, TRUE, pos); }