more dragging controls

This commit is contained in:
David Rose 2004-01-12 03:38:32 +00:00
parent 86985aaa84
commit 35d8dead9e
12 changed files with 150 additions and 39 deletions

View File

@ -21,6 +21,10 @@
winStatsServer.cxx winStatsServer.h \
winStatsStripChart.cxx winStatsStripChart.h
#if $[DEVELOP_WINSTATS]
#define EXTRA_CDEFS $[EXTRA_CDEFS] DEVELOP_WINSTATS
#endif
#define WIN_SYS_LIBS Imm32.lib winmm.lib kernel32.lib oldnames.lib user32.lib gdi32.lib
#end bin_target

View File

@ -62,7 +62,7 @@ create_toplevel_window(HINSTANCE application) {
wc.lpfnWndProc = (WNDPROC)toplevel_window_proc;
wc.hInstance = application;
wc.lpszClassName = toplevel_class_name;
if (!RegisterClass(&wc)) {
nout << "Could not register window class!\n";
exit(1);
@ -70,8 +70,11 @@ create_toplevel_window(HINSTANCE application) {
DWORD window_style = WS_POPUP | WS_SYSMENU | WS_ICONIC;
char window_name[128];
sprintf(window_name, "PStats %d", pstats_port);
HWND toplevel_window =
CreateWindow(toplevel_class_name, "PStats", window_style,
CreateWindow(toplevel_class_name, window_name, window_style,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, application, 0);
if (!toplevel_window) {
@ -87,7 +90,7 @@ create_toplevel_window(HINSTANCE application) {
// but it is sometimes more convenient during development to use
// main() instead, which doesn't squelch the stderr output.
#ifdef USE_WINMAIN
#ifndef DEVELOP_WINSTATS
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
#else
int main(int argc, char *argv[])

View File

@ -59,7 +59,7 @@ get_menu_handle() {
// Description: Adds the menu to the end of the indicated menu bar.
////////////////////////////////////////////////////////////////////
void WinStatsChartMenu::
add_to_menu_bar(HMENU menu_bar) {
add_to_menu_bar(HMENU menu_bar, int before_menu_id) {
const PStatClientData *client_data = _monitor->get_client_data();
string thread_name;
if (_thread_index == 0) {
@ -77,7 +77,7 @@ add_to_menu_bar(HMENU menu_bar) {
mii.fType = MFT_STRING;
mii.hSubMenu = _menu;
mii.dwTypeData = (char *)thread_name.c_str();
InsertMenuItem(menu_bar, GetMenuItemCount(menu_bar), TRUE, &mii);
InsertMenuItem(menu_bar, before_menu_id, FALSE, &mii);
}
////////////////////////////////////////////////////////////////////

View File

@ -38,7 +38,7 @@ public:
~WinStatsChartMenu();
HMENU get_menu_handle();
void add_to_menu_bar(HMENU menu_bar);
void add_to_menu_bar(HMENU menu_bar, int before_menu_id);
void check_update();
void do_update();

View File

@ -23,6 +23,9 @@
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
@ -35,6 +38,7 @@ WinStatsGraph(WinStatsMonitor *monitor, int thread_index) :
{
_window = 0;
_graph_window = 0;
_sizewe_cursor = LoadCursor(NULL, IDC_SIZEWE);
_bitmap = 0;
_bitmap_dc = 0;
@ -49,6 +53,10 @@ WinStatsGraph(WinStatsMonitor *monitor, int thread_index) :
_dark_pen = CreatePen(PS_SOLID, 1, RGB(51, 51, 51));
_light_pen = CreatePen(PS_SOLID, 1, RGB(154, 154, 154));
_drag_mode = DM_none;
_potential_drag_mode = DM_none;
_drag_vscale_start = 0.0f;
}
////////////////////////////////////////////////////////////////////
@ -156,12 +164,6 @@ void WinStatsGraph::
setup_label_stack() {
_label_stack.setup(_window);
move_label_stack();
/*
if (_label_stack()->get_ideal_width() > _label_stack->get_width()) {
_left_margin = _label_stack->get_ideal_width() + 16;
move_label_stack();
}
*/
}
////////////////////////////////////////////////////////////////////
@ -229,6 +231,64 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_SETCURSOR:
{
// Why is it so hard to ask what the cursor position within the
// window's client area is?
POINT point;
GetCursorPos(&point);
WINDOWINFO winfo;
GetWindowInfo(hwnd, &winfo);
const RECT &rect = winfo.rcClient;
// Display a double-headed arrow to drag the left or right margins.
if (point.x >= rect.left + _left_margin - 1 && point.x <= rect.left + _left_margin + 1) {
SetCursor(_sizewe_cursor);
_potential_drag_mode = DM_left_margin;
return TRUE;
}
if (point.x >= rect.right - _right_margin - 2 && point.x <= rect.right - _right_margin) {
SetCursor(_sizewe_cursor);
_potential_drag_mode = DM_right_margin;
return TRUE;
}
_potential_drag_mode = DM_none;
}
break;
case WM_LBUTTONDOWN:
if (_potential_drag_mode != DM_none) {
_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:
_drag_mode = DM_none;
ReleaseCapture();
break;
case WM_PAINT:
{
PAINTSTRUCT ps;

View File

@ -70,6 +70,8 @@ protected:
HWND _graph_window;
WinStatsLabelStack _label_stack;
HCURSOR _sizewe_cursor;
HBITMAP _bitmap;
HDC _bitmap_dc;
@ -81,6 +83,18 @@ protected:
HPEN _dark_pen;
HPEN _light_pen;
// What is the user adjusting by dragging the mouse in a window?
enum DragMode {
DM_none,
DM_vscale,
DM_left_margin,
DM_right_margin,
};
DragMode _drag_mode;
DragMode _potential_drag_mode;
int _drag_start_x, _drag_start_y;
float _drag_vscale_start;
private:
void setup_bitmap(int xsize, int ysize);
void release_bitmap();
@ -93,6 +107,9 @@ private:
static bool _graph_window_class_registered;
static const char * const _graph_window_class_name;
protected:
static DWORD graph_window_style;
};
#endif

View File

@ -214,7 +214,7 @@ register_window_class(HINSTANCE application) {
WNDCLASS wc;
ZeroMemory(&wc, sizeof(WNDCLASS));
wc.style = CS_DBLCLKS;
wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)static_window_proc;
wc.hInstance = application;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);

View File

@ -30,6 +30,7 @@ enum WinStatsMenuId {
MI_none,
MI_time_ms,
MI_time_hz,
MI_frame_rate_label,
// This one is last and represents the beginning of the range for
// the various "new chart" menu options.

View File

@ -47,7 +47,6 @@ WinStatsMonitor() {
////////////////////////////////////////////////////////////////////
WinStatsMonitor::
~WinStatsMonitor() {
cerr << "WinStatsMonitor destructor\n";
Graphs::iterator gi;
for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
delete (*gi);
@ -65,8 +64,10 @@ WinStatsMonitor::
_window = 0;
}
// For now, exit when the first monitor closes.
#ifdef DEVELOP_WINSTATS
// For Winstats developers, exit when the first monitor closes.
exit(0);
#endif
}
////////////////////////////////////////////////////////////////////
@ -93,7 +94,6 @@ get_monitor_name() {
////////////////////////////////////////////////////////////////////
void WinStatsMonitor::
initialized() {
cerr << "Monitor initialized (refcount = " << get_ref_count() << ")\n";
}
////////////////////////////////////////////////////////////////////
@ -168,7 +168,7 @@ new_collector(int collector_index) {
void WinStatsMonitor::
new_thread(int thread_index) {
WinStatsChartMenu *chart_menu = new WinStatsChartMenu(this, thread_index);
chart_menu->add_to_menu_bar(_menu_bar);
chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
_chart_menus.push_back(chart_menu);
DrawMenuBar(_window);
}
@ -202,8 +202,7 @@ new_data(int thread_index, int frame_number) {
////////////////////////////////////////////////////////////////////
void WinStatsMonitor::
lost_connection() {
cerr << "Lost connection to " << get_client_hostname()
<< " (refcount = " << get_ref_count() << ")\n";
nout << "Lost connection to " << get_client_hostname() << "\n";
if (_window) {
DestroyWindow(_window);
@ -225,6 +224,22 @@ idle() {
for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
(*mi)->check_update();
}
// Update the frame rate label from the main thread (thread 0).
const PStatThreadData *thread_data = get_client_data()->get_thread_data(0);
float frame_rate = thread_data->get_frame_rate();
if (frame_rate != 0.0f) {
char buffer[128];
sprintf(buffer, "%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate);
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING;
mii.dwTypeData = buffer;
SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii);
DrawMenuBar(_window);
}
}
////////////////////////////////////////////////////////////////////
@ -326,7 +341,6 @@ set_time_units(int unit_mask) {
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fState = MFS_CHECKED;
mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
MFS_CHECKED : MFS_UNCHECKED;
@ -379,10 +393,11 @@ create_window() {
_menu_bar = CreateMenu();
setup_options_menu();
setup_frame_rate_label();
ChartMenus::iterator mi;
for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
(*mi)->add_to_menu_bar(_menu_bar);
(*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
}
_window_title = get_client_progname() + " on " + get_client_hostname();
@ -439,7 +454,28 @@ setup_options_menu() {
mii.wID = MI_time_hz;
mii.dwTypeData = "Hz";
InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsMonitor::setup_frame_rate_label
// Access: Private
// Description: Creates the frame rate label on the right end of the
// menu bar. This is used as a text label to display
// the main thread's frame rate to the user, although it
// is implemented as a right-justified toplevel menu
// item that doesn't open to anything.
////////////////////////////////////////////////////////////////////
void WinStatsMonitor::
setup_frame_rate_label() {
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
mii.wID = MI_frame_rate_label;
mii.dwTypeData = "";
InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
}
////////////////////////////////////////////////////////////////////

View File

@ -78,6 +78,7 @@ private:
void create_window();
void setup_options_menu();
void setup_frame_rate_label();
static void register_window_class(HINSTANCE application);
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);

View File

@ -40,8 +40,6 @@ WinStatsStripChart(WinStatsMonitor *monitor, int thread_index,
WinStatsGraph(monitor, thread_index)
{
_brush_origin = 0;
_drag_vscale = false;
_drag_vscale_start = 0.0f;
// Let's show the units on the guide bar labels. There's room.
set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
@ -284,7 +282,7 @@ end_draw(int from_x, int to_x) {
const GuideBar &bar = get_guide_bar(i);
int y = height_to_pixel(bar._height);
if (y >= 5) {
if (y > 0) {
// Only draw it if it's not too close to the top.
if (bar._is_target) {
SelectObject(_bitmap_dc, _light_pen);
@ -337,7 +335,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case WM_LBUTTONDOWN:
{
_drag_vscale = true;
_drag_mode = DM_vscale;
PN_int16 y = HIWORD(lparam);
_drag_vscale_start = pixel_to_height(y);
SetCapture(_graph_window);
@ -345,7 +343,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
return 0;
case WM_MOUSEMOVE:
if (_drag_vscale) {
if (_drag_mode == DM_vscale) {
PN_int16 y = HIWORD(lparam);
float ratio = 1.0f - ((float)y / (float)get_ysize());
if (ratio > 0.0f) {
@ -356,19 +354,13 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
break;
case WM_LBUTTONUP:
if (_drag_vscale) {
PN_int16 y = HIWORD(lparam);
float ratio = 1.0f - ((float)y / (float)get_ysize());
if (ratio > 0.0f) {
set_vertical_scale(_drag_vscale_start / ratio);
}
_drag_vscale = false;
if (_drag_mode == DM_vscale) {
_drag_mode = DM_none;
ReleaseCapture();
return 0;
}
break;
default:
break;
}
@ -448,7 +440,6 @@ create_window() {
register_window_class(application);
string window_title = get_title_text();
DWORD window_style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
RECT win_rect = {
0, 0,
@ -457,10 +448,10 @@ create_window() {
};
// compute window size based on desired client area size
AdjustWindowRect(&win_rect, window_style, FALSE);
AdjustWindowRect(&win_rect, graph_window_style, FALSE);
_window =
CreateWindow(_window_class_name, window_title.c_str(), window_style,
CreateWindow(_window_class_name, window_title.c_str(), graph_window_style,
CW_USEDEFAULT, CW_USEDEFAULT,
win_rect.right - win_rect.left,
win_rect.bottom - win_rect.top,

View File

@ -69,8 +69,6 @@ private:
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
int _brush_origin;
bool _drag_vscale;
float _drag_vscale_start;
static bool _window_class_registered;
static const char * const _window_class_name;