|
|
@@ -1,354 +0,0 @@
|
|
|
-// Filename: p3dWinProgressWindow.cxx
|
|
|
-// Created by: drose (17Jun09)
|
|
|
-//
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-//
|
|
|
-// PANDA 3D SOFTWARE
|
|
|
-// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
|
-//
|
|
|
-// All use of this software is subject to the terms of the revised BSD
|
|
|
-// license. You should have received a copy of this license along
|
|
|
-// with this source code in a file named "LICENSE."
|
|
|
-//
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-#include "p3dWinProgressWindow.h"
|
|
|
-
|
|
|
-#ifdef _WIN32
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::Constructor
|
|
|
-// Access: Public
|
|
|
-// Description:
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-P3DWinProgressWindow::
|
|
|
-P3DWinProgressWindow(P3DPackage *package, P3DSession *session,
|
|
|
- P3DInstance *inst) :
|
|
|
- P3DProgressWindow(package, session, inst)
|
|
|
-{
|
|
|
- _thread = NULL;
|
|
|
- _hwnd = NULL;
|
|
|
- _progress_bar = NULL;
|
|
|
- _thread_running = false;
|
|
|
-
|
|
|
- INIT_LOCK(_progress_lock);
|
|
|
-
|
|
|
- assert(_wparams.get_window_type() != P3D_WT_hidden);
|
|
|
- start_thread();
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::Destructor
|
|
|
-// Access: Public, Virtual
|
|
|
-// Description:
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-P3DWinProgressWindow::
|
|
|
-~P3DWinProgressWindow() {
|
|
|
- stop_thread();
|
|
|
-
|
|
|
- DESTROY_LOCK(_progress_lock);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::install_progress
|
|
|
-// Access: Public, Virtual
|
|
|
-// Description: This callback is received during the download process
|
|
|
-// to inform us how much has been installed so far.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-install_progress(P3DPackage *package, double progress) {
|
|
|
- P3DProgressWindow::install_progress(package, progress);
|
|
|
-
|
|
|
- ACQUIRE_LOCK(_progress_lock);
|
|
|
- _progress = progress;
|
|
|
- RELEASE_LOCK(_progress_lock);
|
|
|
-
|
|
|
- // Post a silly message to spin the message loop.
|
|
|
- PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
|
|
-
|
|
|
- if (!_thread_running) {
|
|
|
- _inst->request_stop();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::start_thraed
|
|
|
-// Access: Private
|
|
|
-// Description: Spawns the sub-thread.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-start_thread() {
|
|
|
- _thread_continue = true;
|
|
|
- _thread = CreateThread(NULL, 0, &win_thread_run, this, 0, &_thread_id);
|
|
|
- if (_thread != NULL) {
|
|
|
- _thread_running = true;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::stop_thraed
|
|
|
-// Access: Private
|
|
|
-// Description: Terminates and joins the sub-thread.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-stop_thread() {
|
|
|
- _thread_continue = false;
|
|
|
- // Post a silly message to spin the message loop.
|
|
|
- PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
|
|
-
|
|
|
- WaitForSingleObject(_thread, INFINITE);
|
|
|
- CloseHandle(_thread);
|
|
|
- _thread = NULL;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::thread_run
|
|
|
-// Access: Private
|
|
|
-// Description: The sub-thread's main run method.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-thread_run() {
|
|
|
- make_window();
|
|
|
-
|
|
|
- double last_progress = -1.0;
|
|
|
-
|
|
|
- _loop_started = GetTickCount();
|
|
|
- MSG msg;
|
|
|
- int retval;
|
|
|
- retval = GetMessage(&msg, NULL, 0, 0);
|
|
|
- while (retval != 0 && _thread_continue) {
|
|
|
- if (retval == -1) {
|
|
|
- nout << "Error processing message queue.\n";
|
|
|
- break;
|
|
|
- }
|
|
|
- TranslateMessage(&msg);
|
|
|
- DispatchMessage(&msg);
|
|
|
-
|
|
|
- {
|
|
|
- ACQUIRE_LOCK(_progress_lock);
|
|
|
- double new_progress = _progress;
|
|
|
- RELEASE_LOCK(_progress_lock);
|
|
|
-
|
|
|
- if (new_progress != last_progress) {
|
|
|
- if (_progress_bar == NULL) {
|
|
|
- // Is it time to create the progress bar?
|
|
|
- int now = GetTickCount();
|
|
|
- if (now - _loop_started > 2000) {
|
|
|
- make_progress_bar();
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Update the progress bar. We do this only within the
|
|
|
- // thread, to ensure we don't get a race condition when
|
|
|
- // starting or closing the thread.
|
|
|
- SendMessage(_progress_bar, PBM_SETPOS, (int)(new_progress * 100.0), 0);
|
|
|
-
|
|
|
- last_progress = new_progress;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- retval = GetMessage(&msg, NULL, 0, 0);
|
|
|
- }
|
|
|
-
|
|
|
- close_window();
|
|
|
- _thread_running = false;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::win_thread_run
|
|
|
-// Access: Private, Static
|
|
|
-// Description: The OS-specific thread callback function.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-DWORD P3DWinProgressWindow::
|
|
|
-win_thread_run(LPVOID data) {
|
|
|
- ((P3DWinProgressWindow *)data)->thread_run();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::make_window
|
|
|
-// Access: Private
|
|
|
-// Description: Creates the window for displaying progress. Runs
|
|
|
-// within the sub-thread.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-make_window() {
|
|
|
- WNDCLASS wc;
|
|
|
-
|
|
|
- HINSTANCE application = GetModuleHandle(NULL);
|
|
|
-
|
|
|
- static bool registered_class = false;
|
|
|
- if (!registered_class) {
|
|
|
- ZeroMemory(&wc, sizeof(WNDCLASS));
|
|
|
- wc.lpfnWndProc = window_proc;
|
|
|
- wc.hInstance = application;
|
|
|
- wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
|
|
- wc.lpszClassName = "panda3d_progress";
|
|
|
-
|
|
|
- if (!RegisterClass(&wc)) {
|
|
|
- nout << "Could not register window class!\n";
|
|
|
- }
|
|
|
- registered_class = true;
|
|
|
- }
|
|
|
-
|
|
|
- int x = CW_USEDEFAULT;
|
|
|
- int y = CW_USEDEFAULT;
|
|
|
- if (_wparams.get_win_x() != 0 && _wparams.get_win_y() != 0) {
|
|
|
- x = _wparams.get_win_x();
|
|
|
- y = _wparams.get_win_y();
|
|
|
- }
|
|
|
-
|
|
|
- int width = 320;
|
|
|
- int height = 240;
|
|
|
- if (_wparams.get_win_width() != 0 && _wparams.get_win_height() != 0) {
|
|
|
- width = _wparams.get_win_width();
|
|
|
- height = _wparams.get_win_height();
|
|
|
- }
|
|
|
-
|
|
|
- if (_wparams.get_window_type() == P3D_WT_embedded) {
|
|
|
- // Create an embedded window.
|
|
|
- DWORD window_style =
|
|
|
- WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
|
-
|
|
|
- HWND parent_hwnd = _wparams.get_parent_window()._hwnd;
|
|
|
-
|
|
|
- _hwnd =
|
|
|
- CreateWindow("panda3d_progress", "Panda3D", window_style,
|
|
|
- x, y, width, height,
|
|
|
- parent_hwnd, NULL, application, 0);
|
|
|
-
|
|
|
- if (!_hwnd) {
|
|
|
- nout << "Could not create embedded window!\n";
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- // Create a toplevel window.
|
|
|
- DWORD window_style =
|
|
|
- WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
|
|
|
- WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
|
|
- WS_SIZEBOX | WS_MAXIMIZEBOX;
|
|
|
-
|
|
|
- _hwnd =
|
|
|
- CreateWindow("panda3d_progress", "Panda3D", window_style,
|
|
|
- x, y, width, height,
|
|
|
- NULL, NULL, application, 0);
|
|
|
- if (!_hwnd) {
|
|
|
- nout << "Could not create toplevel window!\n";
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // We don't initially show the toplevel window. We'll show it
|
|
|
- // when we create the actual progress bar, a few seconds later;
|
|
|
- // otherwise, it might be distracting if the window pops up and
|
|
|
- // then immediately disappears.
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::make_progress_bar
|
|
|
-// Access: Private
|
|
|
-// Description: Creates the progress bar and label. Runs
|
|
|
-// within the sub-thread. This is done a few seconds
|
|
|
-// after the main window is created, to give us a chance
|
|
|
-// to launch quickly without bothering the user.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-make_progress_bar() {
|
|
|
- if (_progress_bar != NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- HINSTANCE application = GetModuleHandle(NULL);
|
|
|
- DWORD window_style =
|
|
|
- WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
|
-
|
|
|
- RECT rect;
|
|
|
- GetClientRect(_hwnd, &rect);
|
|
|
- int width = rect.right - rect.left;
|
|
|
- int height = rect.bottom - rect.top;
|
|
|
-
|
|
|
- int bar_width = min((int)(width * 0.6), 400);
|
|
|
- int bar_height = min((int)(height * 0.1), 24);
|
|
|
- int bar_x = (width - bar_width) / 2;
|
|
|
- int bar_y = (height - bar_height) / 2;
|
|
|
-
|
|
|
- _progress_bar =
|
|
|
- CreateWindowEx(0, PROGRESS_CLASS, "", window_style,
|
|
|
- bar_x, bar_y, bar_width, bar_height,
|
|
|
- _hwnd, NULL, application, 0);
|
|
|
-
|
|
|
- // Create a static text label. What a major pain *this* is.
|
|
|
- string text_string = "Installing " + _package->get_package_display_name();
|
|
|
- const char *text = text_string.c_str();
|
|
|
- HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
|
|
-
|
|
|
- HDC dc = GetDC(_hwnd);
|
|
|
- SelectObject(dc, font);
|
|
|
- SIZE text_size;
|
|
|
- GetTextExtentPoint32(dc, text, strlen(text), &text_size);
|
|
|
- ReleaseDC(_hwnd, dc);
|
|
|
-
|
|
|
- int text_width = text_size.cx;
|
|
|
- int text_height = text_size.cy;
|
|
|
- int text_x = (width - text_width) / 2;
|
|
|
- int text_y = bar_y - text_height - 2;
|
|
|
-
|
|
|
- CreateWindowEx(0, "STATIC", text, SS_OWNERDRAW | window_style,
|
|
|
- text_x, text_y, text_width, text_height,
|
|
|
- _hwnd, NULL, application, 0);
|
|
|
-
|
|
|
- // Ensure the main window is visible now.
|
|
|
- ShowWindow(_hwnd, SW_SHOWNORMAL);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::close_window
|
|
|
-// Access: Private
|
|
|
-// Description: Closes the window created above.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void P3DWinProgressWindow::
|
|
|
-close_window() {
|
|
|
- if (_hwnd) {
|
|
|
- ShowWindow(_hwnd, SW_HIDE);
|
|
|
- CloseWindow(_hwnd);
|
|
|
- _hwnd = NULL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: P3DWinProgressWindow::window_proc
|
|
|
-// Access: Private, Static
|
|
|
-// Description: The windows event-processing handler.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-LONG P3DWinProgressWindow::
|
|
|
-window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
|
- switch (msg) {
|
|
|
- case WM_DESTROY:
|
|
|
- PostQuitMessage(0);
|
|
|
- break;
|
|
|
-
|
|
|
- case WM_DRAWITEM:
|
|
|
- {
|
|
|
- DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
|
|
|
- FillRect(dis->hDC, &(dis->rcItem), WHITE_BRUSH);
|
|
|
-
|
|
|
- static const int text_buffer_size = 512;
|
|
|
- char text_buffer[text_buffer_size];
|
|
|
- GetWindowText(dis->hwndItem, text_buffer, text_buffer_size);
|
|
|
-
|
|
|
- HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
|
|
- SelectObject(dis->hDC, font);
|
|
|
- SetBkColor(dis->hDC, 0x00ffffff);
|
|
|
-
|
|
|
- DrawText(dis->hDC, text_buffer, -1, &(dis->rcItem),
|
|
|
- DT_BOTTOM | DT_CENTER | DT_SINGLELINE);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#endif // _WIN32
|