655 lines
20 KiB
C++
655 lines
20 KiB
C++
// Filename: winStatsGraph.cxx
|
|
// Created by: drose (03Dec03)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "winStatsGraph.h"
|
|
#include "winStatsMonitor.h"
|
|
#include "winStatsLabelStack.h"
|
|
|
|
bool WinStatsGraph::_graph_window_class_registered = false;
|
|
const char * const WinStatsGraph::_graph_window_class_name = "graph";
|
|
|
|
DWORD WinStatsGraph::graph_window_style =
|
|
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
WinStatsGraph::
|
|
WinStatsGraph(WinStatsMonitor *monitor, int thread_index) :
|
|
_monitor(monitor),
|
|
_thread_index(thread_index)
|
|
{
|
|
_window = 0;
|
|
_graph_window = 0;
|
|
_sizewe_cursor = LoadCursor(NULL, IDC_SIZEWE);
|
|
_hand_cursor = LoadCursor(NULL, IDC_HAND);
|
|
_bitmap = 0;
|
|
_bitmap_dc = 0;
|
|
|
|
_graph_left = 0;
|
|
_graph_top = 0;
|
|
_bitmap_xsize = 0;
|
|
_bitmap_ysize = 0;
|
|
|
|
_dark_color = RGB(51, 51, 51);
|
|
_light_color = RGB(154, 154, 154);
|
|
_user_guide_bar_color = RGB(130, 150, 255);
|
|
_dark_pen = CreatePen(PS_SOLID, 1, _dark_color);
|
|
_light_pen = CreatePen(PS_SOLID, 1, _light_color);
|
|
_user_guide_bar_pen = CreatePen(PS_DASH, 1, _user_guide_bar_color);
|
|
|
|
_drag_mode = DM_none;
|
|
_potential_drag_mode = DM_none;
|
|
_drag_scale_start = 0.0f;
|
|
|
|
_pause = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
WinStatsGraph::
|
|
~WinStatsGraph() {
|
|
_monitor = (WinStatsMonitor *)NULL;
|
|
release_bitmap();
|
|
|
|
DeleteObject(_dark_pen);
|
|
DeleteObject(_light_pen);
|
|
DeleteObject(_user_guide_bar_pen);
|
|
|
|
Brushes::iterator bi;
|
|
for (bi = _brushes.begin(); bi != _brushes.end(); ++bi) {
|
|
HBRUSH brush = (*bi).second;
|
|
DeleteObject(brush);
|
|
}
|
|
|
|
if (_graph_window) {
|
|
DestroyWindow(_graph_window);
|
|
_graph_window = 0;
|
|
}
|
|
|
|
if (_window) {
|
|
DestroyWindow(_window);
|
|
_window = 0;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::get_thread_index
|
|
// Access: Public
|
|
// Description: Returns the thread index associated with this
|
|
// particular graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
int WinStatsGraph::
|
|
get_thread_index() const {
|
|
return _thread_index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::new_collector
|
|
// Access: Public, Virtual
|
|
// Description: Called whenever a new Collector definition is
|
|
// received from the client.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
new_collector(int new_collector) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::new_data
|
|
// Access: Public, Virtual
|
|
// Description: Called whenever new data arrives.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
new_data(int thread_index, int frame_number) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::force_redraw
|
|
// Access: Public, Virtual
|
|
// Description: Called when it is necessary to redraw the entire graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
force_redraw() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::changed_graph_size
|
|
// Access: Public, Virtual
|
|
// Description: Called when the user has resized the window, forcing
|
|
// a resize of the graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
changed_graph_size(int graph_xsize, int graph_ysize) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::set_time_units
|
|
// Access: Public, Virtual
|
|
// Description: Called when the user selects a new time units from
|
|
// the monitor pulldown menu, this should adjust the
|
|
// units for the graph to the indicated mask if it is a
|
|
// time-based graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
set_time_units(int unit_mask) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::set_scroll_speed
|
|
// Access: Public
|
|
// Description: Called when the user selects a new scroll speed from
|
|
// the monitor pulldown menu, this should adjust the
|
|
// speed for the graph to the indicated value.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
set_scroll_speed(float scroll_speed) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::set_pause
|
|
// Access: Public
|
|
// Description: Changes the pause flag for the graph. When this flag
|
|
// is true, the graph does not update in response to new
|
|
// data.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
set_pause(bool pause) {
|
|
_pause = pause;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::user_guide_bars_changed
|
|
// Access: Public
|
|
// Description: Called when the user guide bars have been changed.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
user_guide_bars_changed() {
|
|
InvalidateRect(_window, NULL, TRUE);
|
|
InvalidateRect(_graph_window, NULL, TRUE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::clicked_label
|
|
// Access: Public, Virtual
|
|
// Description: Called when the user single-clicks on a label.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
clicked_label(int collector_index) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::close
|
|
// Access: Protected
|
|
// Description: Should be called when the user closes the associated
|
|
// window. This tells the monitor to remove the graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
close() {
|
|
WinStatsMonitor *monitor = _monitor;
|
|
_monitor = (WinStatsMonitor *)NULL;
|
|
if (monitor != (WinStatsMonitor *)NULL) {
|
|
monitor->remove_graph(this);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::setup_label_stack
|
|
// Access: Protected
|
|
// Description: Sets up the label stack on the left edge of the
|
|
// frame.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
setup_label_stack() {
|
|
_label_stack.setup(_window);
|
|
move_label_stack();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::move_label_stack
|
|
// Access: Protected
|
|
// Description: Repositions the label stack if its coordinates or
|
|
// size have changed.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
move_label_stack() {
|
|
if (_label_stack.is_setup()) {
|
|
RECT rect;
|
|
GetClientRect(_window, &rect);
|
|
|
|
rect.left += 8;
|
|
rect.right = _left_margin - 8;
|
|
rect.bottom -= _bottom_margin;
|
|
|
|
_label_stack.set_pos(rect.left, rect.top,
|
|
rect.right - rect.left, rect.bottom - rect.top);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::get_collector_brush
|
|
// Access: Protected
|
|
// Description: Returns a brush suitable for drawing in the indicated
|
|
// collector's color.
|
|
////////////////////////////////////////////////////////////////////
|
|
HBRUSH WinStatsGraph::
|
|
get_collector_brush(int collector_index) {
|
|
Brushes::iterator bi;
|
|
bi = _brushes.find(collector_index);
|
|
if (bi != _brushes.end()) {
|
|
return (*bi).second;
|
|
}
|
|
|
|
// Ask the monitor what color this guy should be.
|
|
RGBColorf rgb = _monitor->get_collector_color(collector_index);
|
|
int r = (int)(rgb[0] * 255.0f);
|
|
int g = (int)(rgb[1] * 255.0f);
|
|
int b = (int)(rgb[2] * 255.0f);
|
|
HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
|
|
|
|
_brushes[collector_index] = brush;
|
|
return brush;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::window_proc
|
|
// Access: Protected
|
|
// Description: This window_proc should be called up to by the
|
|
// derived classes for any messages that are not
|
|
// specifically handled by the derived class.
|
|
////////////////////////////////////////////////////////////////////
|
|
LONG WinStatsGraph::
|
|
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
switch (msg) {
|
|
case WM_DESTROY:
|
|
close();
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
move_label_stack();
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
break;
|
|
|
|
case WM_SIZING:
|
|
set_drag_mode(DM_sizing);
|
|
break;
|
|
|
|
case WM_EXITSIZEMOVE:
|
|
set_drag_mode(DM_none);
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
{
|
|
// Why is it so hard to ask for the cursor position within the
|
|
// window's client area?
|
|
POINT point;
|
|
GetCursorPos(&point);
|
|
WINDOWINFO winfo;
|
|
GetWindowInfo(hwnd, &winfo);
|
|
const RECT &rect = winfo.rcClient;
|
|
int x = point.x - rect.left;
|
|
int y = point.y - rect.top;
|
|
int width = rect.right - rect.left;
|
|
int height = rect.bottom - rect.top;
|
|
|
|
_potential_drag_mode = consider_drag_start(x, y, width, height);
|
|
|
|
switch (_potential_drag_mode) {
|
|
case DM_left_margin:
|
|
case DM_right_margin:
|
|
SetCursor(_sizewe_cursor);
|
|
return TRUE;
|
|
|
|
case DM_guide_bar:
|
|
SetCursor(_hand_cursor);
|
|
return TRUE;
|
|
|
|
default:
|
|
case DM_none:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
if (_potential_drag_mode != DM_none) {
|
|
set_drag_mode(_potential_drag_mode);
|
|
_drag_start_x = (PN_int16)LOWORD(lparam);
|
|
_drag_start_y = (PN_int16)HIWORD(lparam);
|
|
SetCapture(_window);
|
|
}
|
|
return 0;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (_drag_mode == DM_left_margin) {
|
|
PN_int16 x = LOWORD(lparam);
|
|
_left_margin += (x - _drag_start_x);
|
|
_drag_start_x = x;
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
move_label_stack();
|
|
return 0;
|
|
|
|
} else if (_drag_mode == DM_right_margin) {
|
|
PN_int16 x = LOWORD(lparam);
|
|
_right_margin += (_drag_start_x - x);
|
|
_drag_start_x = x;
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
set_drag_mode(DM_none);
|
|
ReleaseCapture();
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hwnd, &ps);
|
|
|
|
// First, draw a frame around the graph.
|
|
RECT rect;
|
|
GetClientRect(hwnd, &rect);
|
|
|
|
rect.left += _left_margin;
|
|
rect.top += _top_margin;
|
|
rect.right -= _right_margin;
|
|
rect.bottom -= _bottom_margin;
|
|
|
|
if (rect.right > rect.left && rect.bottom > rect.top) {
|
|
DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
|
|
|
|
int graph_xsize = rect.right - rect.left;
|
|
int graph_ysize = rect.bottom - rect.top;
|
|
if (_bitmap_dc == 0 ||
|
|
graph_xsize != _bitmap_xsize ||
|
|
graph_ysize != _bitmap_ysize) {
|
|
// Oops, we need to change the bitmap (and graph) size.
|
|
changed_graph_size(graph_xsize, graph_ysize);
|
|
move_graph_window(rect.left, rect.top, graph_xsize, graph_ysize);
|
|
force_redraw();
|
|
}
|
|
}
|
|
|
|
additional_window_paint(hdc);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::graph_window_proc
|
|
// Access: Protected, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
LONG WinStatsGraph::
|
|
graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
switch (msg) {
|
|
case WM_DISPLAYCHANGE:
|
|
setup_bitmap(_bitmap_xsize, _bitmap_ysize);
|
|
force_redraw();
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
// Vector any uncaught WM_LBUTTONDOWN into the main window, so we
|
|
// can drag margins, etc.
|
|
if (_potential_drag_mode != DM_none) {
|
|
PN_int16 x = LOWORD(lparam) + _graph_left;
|
|
PN_int16 y = HIWORD(lparam) + _graph_top;
|
|
return window_proc(_window, msg, wparam, MAKELPARAM(x, y));
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
set_drag_mode(DM_none);
|
|
ReleaseCapture();
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
// Repaint the graph by copying the backing pixmap in.
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hwnd, &ps);
|
|
|
|
BitBlt(hdc, 0, 0,
|
|
_bitmap_xsize, _bitmap_ysize,
|
|
_bitmap_dc, 0, 0,
|
|
SRCCOPY);
|
|
|
|
additional_graph_window_paint(hdc);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::additional_window_paint
|
|
// Access: Protected, Virtual
|
|
// Description: This is called during the servicing of WM_PAINT; it
|
|
// gives a derived class opportunity to do some further
|
|
// painting into the window (the outer window, not the
|
|
// graph window).
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
additional_window_paint(HDC hdc) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::additional_graph_window_paint
|
|
// Access: Protected, Virtual
|
|
// Description: This is called during the servicing of WM_PAINT; it
|
|
// gives a derived class opportunity to do some further
|
|
// painting into the graph window.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
additional_graph_window_paint(HDC hdc) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::consider_drag_start
|
|
// Access: Protected, Virtual
|
|
// Description: Based on the mouse position within the window's
|
|
// client area, look for draggable things the mouse
|
|
// might be hovering over and return the apprioprate
|
|
// DragMode enum or DM_none if nothing is indicated.
|
|
////////////////////////////////////////////////////////////////////
|
|
WinStatsGraph::DragMode WinStatsGraph::
|
|
consider_drag_start(int mouse_x, int mouse_y, int width, int height) {
|
|
if (mouse_x >= _left_margin - 2 && mouse_x <= _left_margin + 2) {
|
|
return DM_left_margin;
|
|
} else if (mouse_x >= width - _right_margin - 2 && mouse_x <= width - _right_margin + 2) {
|
|
return DM_right_margin;
|
|
}
|
|
|
|
return DM_none;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::set_drag_mode
|
|
// Access: Protected, Virtual
|
|
// Description: This should be called whenever the drag mode needs to
|
|
// change state. It provides hooks for a derived class
|
|
// to do something special.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
set_drag_mode(WinStatsGraph::DragMode drag_mode) {
|
|
_drag_mode = drag_mode;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::move_graph_window
|
|
// Access: Protected, Virtual
|
|
// Description: Repositions the graph child window within the parent
|
|
// window according to the _margin variables.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) {
|
|
if (_graph_window == 0) {
|
|
create_graph_window();
|
|
}
|
|
|
|
_graph_left = graph_left;
|
|
_graph_top = graph_top;
|
|
|
|
SetWindowPos(_graph_window, 0,
|
|
_graph_left, _graph_top,
|
|
graph_xsize, graph_ysize,
|
|
SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
|
|
if (graph_xsize != _bitmap_xsize || graph_ysize != _bitmap_ysize) {
|
|
setup_bitmap(graph_xsize, graph_ysize);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::setup_bitmap
|
|
// Access: Private
|
|
// Description: Sets up a backing-store bitmap of the indicated size.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
setup_bitmap(int xsize, int ysize) {
|
|
release_bitmap();
|
|
_bitmap_xsize = max(xsize, 0);
|
|
_bitmap_ysize = max(ysize, 0);
|
|
|
|
HDC hdc = GetDC(_graph_window);
|
|
_bitmap_dc = CreateCompatibleDC(hdc);
|
|
_bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize);
|
|
SelectObject(_bitmap_dc, _bitmap);
|
|
|
|
RECT rect = { 0, 0, _bitmap_xsize, _bitmap_ysize };
|
|
FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
|
|
|
ReleaseDC(_window, hdc);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::release_bitmap
|
|
// Access: Private
|
|
// Description: Frees the backing-store bitmap created by
|
|
// setup_bitmap().
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
release_bitmap() {
|
|
if (_bitmap) {
|
|
DeleteObject(_bitmap);
|
|
_bitmap = 0;
|
|
}
|
|
if (_bitmap_dc) {
|
|
DeleteDC(_bitmap_dc);
|
|
_bitmap_dc = 0;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::create_graph_window
|
|
// Access: Private
|
|
// Description: Creates the child window that actually holds the graph.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
create_graph_window() {
|
|
if (_graph_window) {
|
|
return;
|
|
}
|
|
|
|
HINSTANCE application = GetModuleHandle(NULL);
|
|
register_graph_window_class(application);
|
|
|
|
string window_title = "graph";
|
|
DWORD window_style = WS_CHILD | WS_CLIPSIBLINGS;
|
|
|
|
_graph_window =
|
|
CreateWindow(_graph_window_class_name, window_title.c_str(), window_style,
|
|
0, 0, 0, 0,
|
|
_window, NULL, application, 0);
|
|
if (!_graph_window) {
|
|
nout << "Could not create graph window!\n";
|
|
exit(1);
|
|
}
|
|
|
|
SetWindowLongPtr(_graph_window, 0, (LONG_PTR)this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::register_graph_window_class
|
|
// Access: Private, Static
|
|
// Description: Registers the window class for the stripChart window, if
|
|
// it has not already been registered.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsGraph::
|
|
register_graph_window_class(HINSTANCE application) {
|
|
if (_graph_window_class_registered) {
|
|
return;
|
|
}
|
|
|
|
WNDCLASS wc;
|
|
|
|
ZeroMemory(&wc, sizeof(WNDCLASS));
|
|
wc.style = CS_DBLCLKS;
|
|
wc.lpfnWndProc = (WNDPROC)static_graph_window_proc;
|
|
wc.hInstance = application;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = NULL;
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = _graph_window_class_name;
|
|
|
|
// Reserve space to associate the this pointer with the window.
|
|
wc.cbWndExtra = sizeof(WinStatsGraph *);
|
|
|
|
if (!RegisterClass(&wc)) {
|
|
nout << "Could not register graph window class!\n";
|
|
exit(1);
|
|
}
|
|
|
|
_graph_window_class_registered = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsGraph::static_graph_window_proc
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
LONG WINAPI WinStatsGraph::
|
|
static_graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
WinStatsGraph *self = (WinStatsGraph *)GetWindowLongPtr(hwnd, 0);
|
|
if (self != (WinStatsGraph *)NULL && self->_graph_window == hwnd) {
|
|
return self->graph_window_proc(hwnd, msg, wparam, lparam);
|
|
} else {
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
}
|
|
}
|