Constantin Kaplinsky | 729598c | 2006-05-25 05:12:25 +0000 | [diff] [blame] | 1 | /* Copyright (C) 2005 TightVNC Team. All Rights Reserved. |
| 2 | * |
| 3 | * This is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License as published by |
| 5 | * the Free Software Foundation; either version 2 of the License, or |
| 6 | * (at your option) any later version. |
| 7 | * |
| 8 | * This software is distributed in the hope that it will be useful, |
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | * GNU General Public License for more details. |
| 12 | * |
| 13 | * You should have received a copy of the GNU General Public License |
| 14 | * along with this software; if not, write to the Free Software |
| 15 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
| 16 | * USA. |
| 17 | */ |
| 18 | |
| 19 | // -=- PlayerToolBar.cxx |
| 20 | |
| 21 | #include <rfbplayer/rfbplayer.h> |
| 22 | #include <rfbplayer/resource.h> |
| 23 | |
| 24 | PlayerToolBar::PlayerToolBar() |
| 25 | : ToolBar(), hFont(0), timeStatic(0), speedEdit(0), posTrackBar(0), |
| 26 | speedUpDown(0), sliderDragging(false), sliderStepMs(0) |
| 27 | { |
| 28 | } |
| 29 | |
| 30 | void PlayerToolBar::create(RfbPlayer *player_, HWND parentHwnd_) { |
| 31 | HDC hdc; |
| 32 | SIZE sz; |
| 33 | RECT tRect; |
| 34 | NONCLIENTMETRICS nonClientMetrics; |
| 35 | |
| 36 | player = player_; |
| 37 | |
| 38 | // Get the default font for the main menu |
| 39 | nonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS); |
| 40 | if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nonClientMetrics, 0)) |
| 41 | MessageBox(0, "Can't access to the system font.", |
| 42 | "RfbPlayer", MB_OK | MB_ICONERROR); |
| 43 | nonClientMetrics.lfMenuFont.lfHeight = 16; |
| 44 | hFont = CreateFontIndirect(&nonClientMetrics.lfMenuFont); |
| 45 | |
| 46 | // Create the toolbar panel |
| 47 | ToolBar::create(ID_TOOLBAR, parentHwnd_, |
| 48 | WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | CCS_NORESIZE); |
| 49 | addBitmap(4, IDB_TOOLBAR); |
| 50 | |
| 51 | // Create the control buttons |
| 52 | addButton(0, ID_PLAY); |
| 53 | addButton(1, ID_PAUSE); |
| 54 | addButton(2, ID_STOP); |
| 55 | addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 56 | |
| 57 | // Create the static control for the time output |
| 58 | timeStatic = CreateWindowEx(0, "Static", "00m:00s (00m:00s)", |
| 59 | WS_CHILD | WS_VISIBLE, 0, 0, 20, 20, getHandle(), (HMENU)ID_TIME_STATIC, |
| 60 | GetModuleHandle(0), 0); |
| 61 | SendMessage(timeStatic, WM_SETFONT,(WPARAM) hFont, TRUE); |
| 62 | hdc = GetDC(timeStatic); |
| 63 | SelectObject(hdc, hFont); |
| 64 | GetTextExtentPoint32(hdc, "00m:00s (00m:00s)", 16, &sz); |
| 65 | addButton(sz.cx + 10, 0, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 66 | addButton(0, 10, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 67 | getButtonRect(4, &tRect); |
| 68 | MoveWindow(timeStatic, tRect.left, tRect.top+2, tRect.right-tRect.left, |
| 69 | tRect.bottom-tRect.top, FALSE); |
| 70 | |
| 71 | // Create the trackbar control for the time position |
| 72 | addButton(200, 0, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 73 | getButtonRect(6, &tRect); |
| 74 | posTrackBar = CreateWindowEx(0, TRACKBAR_CLASS, "Trackbar Control", |
| 75 | WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, |
| 76 | tRect.left, tRect.top, tRect.right-tRect.left, tRect.bottom-tRect.top, |
| 77 | parentHwnd, (HMENU)ID_POS_TRACKBAR, GetModuleHandle(0), 0); |
| 78 | // It's need to send notify messages to toolbar parent window |
| 79 | SetParent(posTrackBar, getHandle()); |
| 80 | addButton(0, 10, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 81 | |
| 82 | // Create the label with "Speed:" caption |
| 83 | HWND speedStatic = CreateWindowEx(0, "Static", "Speed:", WS_CHILD | WS_VISIBLE, |
| 84 | 0, 0, 5, 5, getHandle(), (HMENU)ID_SPEED_STATIC, GetModuleHandle(0), 0); |
| 85 | SendMessage(speedStatic, WM_SETFONT,(WPARAM) hFont, TRUE); |
| 86 | hdc = GetDC(speedStatic); |
| 87 | SelectObject(hdc, hFont); |
| 88 | GetTextExtentPoint32(hdc, "Speed:", 6, &sz); |
| 89 | addButton(sz.cx + 10, 0, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 90 | getButtonRect(8, &tRect); |
| 91 | MoveWindow(speedStatic, tRect.left, tRect.top+2, tRect.right-tRect.left, |
| 92 | tRect.bottom-tRect.top, FALSE); |
| 93 | |
| 94 | // Create the edit control and the spin for the speed managing |
| 95 | addButton(60, 0, TBSTATE_ENABLED, TBSTYLE_SEP); |
| 96 | getButtonRect(9, &tRect); |
| 97 | speedEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "1.00", |
| 98 | WS_CHILD | WS_VISIBLE | ES_RIGHT, tRect.left, tRect.top, |
| 99 | tRect.right-tRect.left, tRect.bottom-tRect.top, parentHwnd, |
| 100 | (HMENU)ID_SPEED_EDIT, GetModuleHandle(0), 0); |
| 101 | SendMessage(speedEdit, WM_SETFONT,(WPARAM) hFont, TRUE); |
| 102 | // It's need to send notify messages to toolbar parent window |
| 103 | SetParent(speedEdit, getHandle()); |
| 104 | |
| 105 | speedUpDown = CreateUpDownControl(WS_CHILD | WS_VISIBLE |
| 106 | | WS_BORDER | UDS_ALIGNRIGHT, 0, 0, 0, 0, getHandle(), |
| 107 | ID_SPEED_UPDOWN, GetModuleHandle(0), speedEdit, 20, 1, 2); |
| 108 | |
| 109 | // Resize the toolbar window |
| 110 | autoSize(); |
| 111 | } |
| 112 | |
| 113 | void PlayerToolBar::init(long sessionTimeMs_) { |
| 114 | sessionTimeMs = sessionTimeMs_; |
| 115 | |
| 116 | setSessionTimeStr(sessionTimeMs); |
| 117 | SendMessage(posTrackBar, TBM_SETRANGE, |
| 118 | TRUE, MAKELONG(0, min(sessionTimeMs / 1000, MAX_POS_TRACKBAR_RANGE))); |
| 119 | if (sessionTimeMs == 0) { |
| 120 | sliderStepMs = 1; |
| 121 | } else { |
| 122 | sliderStepMs = sessionTimeMs / SendMessage(posTrackBar, TBM_GETRANGEMAX, 0, 0); |
| 123 | } |
| 124 | updatePos(0); |
| 125 | } |
| 126 | |
| 127 | void PlayerToolBar::enable() { |
| 128 | enableButton(ID_PLAY, true); |
| 129 | enableButton(ID_PAUSE, true); |
| 130 | enableButton(ID_STOP, true); |
| 131 | enableButton(ID_FULLSCREEN, true); |
| 132 | EnableWindow(posTrackBar, true); |
| 133 | EnableWindow(speedEdit, true); |
| 134 | EnableWindow(speedUpDown, true); |
| 135 | } |
| 136 | |
| 137 | void PlayerToolBar::disable() { |
| 138 | enableButton(ID_PLAY, false); |
| 139 | enableButton(ID_PAUSE, false); |
| 140 | enableButton(ID_STOP, false); |
| 141 | enableButton(ID_FULLSCREEN, false); |
| 142 | EnableWindow(posTrackBar, false); |
| 143 | EnableWindow(speedEdit, false); |
| 144 | EnableWindow(speedUpDown, false); |
| 145 | } |
| 146 | |
| 147 | LRESULT PlayerToolBar::processWM_COMMAND(WPARAM wParam, LPARAM lParam) { |
| 148 | switch (LOWORD(wParam)) { |
| 149 | |
| 150 | case ID_RETURN: |
| 151 | // Update the speed if return pressed in speedEdit |
| 152 | if (getSpeedEditHwnd() == GetFocus()) { |
| 153 | char speedStr[20], *stopStr; |
| 154 | GetWindowText(getSpeedEditHwnd(), speedStr, sizeof(speedStr)); |
| 155 | double speed = strtod(speedStr, &stopStr); |
| 156 | if (speed > 0) { |
| 157 | speed = min(MAX_SPEED, speed); |
| 158 | } else { |
| 159 | speed = player->getSpeed(); |
| 160 | } |
| 161 | player->setSpeed(speed); |
| 162 | return FALSE; |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | return TRUE; |
| 167 | } |
| 168 | |
| 169 | LRESULT PlayerToolBar::processWM_HSCROLL(WPARAM wParam, LPARAM lParam) { |
| 170 | long Pos = SendMessage(posTrackBar, TBM_GETPOS, 0, 0); |
| 171 | Pos *= sliderStepMs; |
| 172 | |
| 173 | switch (LOWORD(wParam)) { |
| 174 | case TB_PAGEUP: |
| 175 | case TB_PAGEDOWN: |
| 176 | case TB_LINEUP: |
| 177 | case TB_LINEDOWN: |
| 178 | case TB_THUMBTRACK: |
| 179 | sliderDragging = true; |
| 180 | updatePos(Pos); |
| 181 | return FALSE; |
| 182 | case TB_THUMBPOSITION: |
| 183 | case TB_ENDTRACK: |
| 184 | player->setPos(Pos); |
| 185 | player->setPaused(player->isPaused());; |
| 186 | updatePos(Pos); |
| 187 | sliderDragging = false; |
| 188 | return FALSE; |
| 189 | default: |
| 190 | break; |
| 191 | } |
| 192 | |
| 193 | return TRUE; |
| 194 | } |
| 195 | |
| 196 | LRESULT PlayerToolBar::processWM_NOTIFY(WPARAM wParam, LPARAM lParam) { |
| 197 | switch (((NMHDR*)lParam)->code) { |
| 198 | case UDN_DELTAPOS: |
| 199 | if ((int)wParam == ID_SPEED_UPDOWN) { |
| 200 | char speedStr[20] = "\0"; |
| 201 | DWORD speedRange = SendMessage(speedUpDown, UDM_GETRANGE, 0, 0); |
| 202 | LPNM_UPDOWN upDown = (LPNM_UPDOWN)lParam; |
| 203 | double speed; |
| 204 | |
| 205 | // The out of range checking |
| 206 | if (upDown->iDelta > 0) { |
| 207 | speed = min(upDown->iPos + upDown->iDelta, LOWORD(speedRange)) * 0.5; |
| 208 | } else { |
| 209 | // It's need to round the UpDown position |
| 210 | if ((upDown->iPos * 0.5) != player->getSpeed()) { |
| 211 | upDown->iDelta = 0; |
| 212 | } |
| 213 | speed = max(upDown->iPos + upDown->iDelta, HIWORD(speedRange)) * 0.5; |
| 214 | } |
| 215 | player->setSpeed(speed); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | // We always return TRUE to prevent the change in the updown contol |
| 220 | // position. The control's position changes in the RfbPlayer::setSpeed(). |
| 221 | return TRUE; |
| 222 | } |
| 223 | |
| 224 | void PlayerToolBar::updatePos(long newPos) { |
| 225 | // Update time pos in static control |
| 226 | char timePos[30] = "\0"; |
| 227 | long time = newPos / 1000; |
| 228 | sprintf(timePos, "%.2um:%.2us (%s)", time/60, time%60, fullSessionTimeStr); |
| 229 | SetWindowText(timeStatic, timePos); |
| 230 | |
| 231 | // Update the position of slider |
| 232 | if (!sliderDragging) { |
| 233 | double error = SendMessage(posTrackBar, TBM_GETPOS, 0, 0) * |
| 234 | sliderStepMs / double(newPos); |
| 235 | if (!((error > 1 - CALCULATION_ERROR) && (error <= 1 + CALCULATION_ERROR))) { |
| 236 | SendMessage(posTrackBar, TBM_SETPOS, TRUE, newPos / sliderStepMs); |
| 237 | } |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | void PlayerToolBar::setSessionTimeStr(long sessionTimeMs) { |
| 242 | sprintf(fullSessionTimeStr, "%.2um:%.2us", |
| 243 | sessionTimeMs / 1000 / 60, sessionTimeMs / 1000 % 60); |
| 244 | } |
| 245 | |
| 246 | void PlayerToolBar::setTimePos(long pos) { |
| 247 | SendMessage(posTrackBar, TBM_SETPOS, TRUE, pos); |
| 248 | } |