diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index a1f611bb..74f8c33c 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -348,6 +348,8 @@ static CFGSTRUCT fceuconfig[] = { AC(taseditor_config.findnote_matchcase), AC(taseditor_config.findnote_search_up), AC(taseditor_config.deselect_on_doubleclick), + AC(taseditor_config.doubleclick_affects_playback), + AC(taseditor_config.draw_input), AC(taseditor_config.silent_autosave), AC(taseditor_config.tooltips), AC(taseditor_config.current_pattern), diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 238b7aaf..0a189cdd 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -71,6 +71,10 @@ #include "utils/xstring.h" #include #include "taseditor/taseditor_window.h" +#include "taseditor/piano_roll.h" + +extern TASEDITOR_WINDOW taseditor_window; +extern PIANO_ROLL piano_roll; //--------------------------- //mbg merge 6/29/06 - new aboutbox @@ -308,7 +312,6 @@ int BlockingCheck() { //other accelerator capable dialogs could be added here extern HWND hwndMemWatch; - extern TASEDITOR_WINDOW taseditor_window; int handled = 0; @@ -336,12 +339,14 @@ int BlockingCheck() } } - - if(!handled && taseditor_window.hwndTasEditor) { if(IsChild(taseditor_window.hwndTasEditor, msg.hwnd)) + { handled = TranslateAccelerator(taseditor_window.hwndTasEditor, fceu_hAccel, &msg); + if (handled) + piano_roll.AcceleratorDispatched(); + } } if(!handled && taseditor_window.hwndFindNote) { diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index b2ea32a0..443adbe5 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -292,6 +292,8 @@ BEGIN MENUITEM MFT_SEPARATOR MENUITEM "Autofire Pattern skips Lag", ID_CONFIG_COLUMNSETPATTERNSKIPSLAG,MFT_STRING,MFS_ENABLED MENUITEM "Deselect on doubleclick", ID_CONFIG_DESELECTONDOUBLECLICK,MFT_STRING,MFS_ENABLED + MENUITEM "Doubleclick on Frame# affects Playback", ID_CONFIG_DOUBLECLICKONFRAME,MFT_STRING,MFS_ENABLED + MENUITEM "Draw Input by dragging", ID_CONFIG_DRAWINPUTBYDRAGGING,MFT_STRING,MFS_ENABLED MENUITEM MFT_SEPARATOR MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED MENUITEM "Mute Turbo", ID_CONFIG_MUTETURBO,MFT_STRING,MFS_ENABLED @@ -1391,56 +1393,56 @@ BEGIN EDITTEXT IDC_LABEL_NEWPPUUSED,76,166,155,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP END -TASEDITOR DIALOGEX 0, 0, 323, 351 +TASEDITOR DIALOGEX 0, 0, 325, 353 STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "TAS Editor" MENU TASEDITORMENU FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW,199,36,116,12 - CONTROL "",IDC_BRANCHES_BUTTON,"Button",BS_OWNERDRAW,206,167,104,11 - CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER,4,13,187,320 - GROUPBOX " Playback ",IDC_PLAYBACK_BOX,196,0,123,62,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Recorder ",IDC_RECORDER_BOX,196,63,123,46,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Splicer ",IDC_SPLICER_BOX,196,110,123,30,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Lua ",IDC_LUA_BOX,196,141,123,26,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,196,169,123,102,BS_CENTER,WS_EX_RIGHT - GROUPBOX " History ",IDC_HISTORY_BOX,196,272,123,56,BS_CENTER,WS_EX_RIGHT - PUSHBUTTON "<<",TASEDITOR_REWIND_FULL,200,9,23,14,NOT WS_TABSTOP - PUSHBUTTON "<",TASEDITOR_REWIND,223,9,23,14,NOT WS_TABSTOP - PUSHBUTTON "||",TASEDITOR_PLAYSTOP,246,9,23,14,NOT WS_TABSTOP - PUSHBUTTON ">",TASEDITOR_FORWARD,269,9,23,14,NOT WS_TABSTOP - PUSHBUTTON ">>",TASEDITOR_FORWARD_FULL,292,9,23,14,NOT WS_TABSTOP - CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,200,39,115,6 - CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,202,25,56,12 + CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW,200,36,116,12 + CONTROL "",IDC_BRANCHES_BUTTON,"Button",BS_OWNERDRAW,207,167,104,11 + CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER,5,13,187,320 + GROUPBOX " Playback ",IDC_PLAYBACK_BOX,197,0,123,62,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Recorder ",IDC_RECORDER_BOX,197,63,123,46,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Splicer ",IDC_SPLICER_BOX,197,110,123,30,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Lua ",IDC_LUA_BOX,197,141,123,26,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,197,169,123,102,BS_CENTER,WS_EX_RIGHT + GROUPBOX " History ",IDC_HISTORY_BOX,197,272,123,56,BS_CENTER,WS_EX_RIGHT + PUSHBUTTON "<<",TASEDITOR_REWIND_FULL,201,9,23,14,NOT WS_TABSTOP + PUSHBUTTON "<",TASEDITOR_REWIND,224,9,23,14,NOT WS_TABSTOP + PUSHBUTTON "||",TASEDITOR_PLAYSTOP,247,9,23,14,NOT WS_TABSTOP + PUSHBUTTON ">",TASEDITOR_FORWARD,270,9,23,14,NOT WS_TABSTOP + PUSHBUTTON ">>",TASEDITOR_FORWARD_FULL,293,9,23,14,NOT WS_TABSTOP + CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,201,39,115,6 + CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,203,25,56,12 CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK, - "Button",BS_AUTOCHECKBOX,202,48,105,12 - CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | NOT WS_VISIBLE | WS_BORDER,201,178,113,89 - CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,201,282,113,42 - CONTROL " All",IDC_RADIO_ALL,"Button",BS_AUTORADIOBUTTON,290,71,24,10 - CONTROL " 1P",IDC_RADIO_1P,"Button",BS_AUTORADIOBUTTON,202,83,25,10 - CONTROL " 2P",IDC_RADIO_2P,"Button",BS_AUTORADIOBUTTON,231,83,25,10 - CONTROL " 3P",IDC_RADIO_3P,"Button",BS_AUTORADIOBUTTON,261,83,24,10 - CONTROL " 4P",IDC_RADIO_4P,"Button",BS_AUTORADIOBUTTON,290,83,24,10 - CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTO3STATE,202,96,55,10 - PUSHBUTTON "<<",TASEDITOR_PREV_MARKER,201,332,23,14,NOT WS_TABSTOP - PUSHBUTTON "Similar",TASEDITOR_FIND_BEST_SIMILAR_MARKER,224,332,34,14,NOT WS_TABSTOP - PUSHBUTTON "More",TASEDITOR_FIND_NEXT_SIMILAR_MARKER,258,332,34,14,NOT WS_TABSTOP - PUSHBUTTON ">>",TASEDITOR_NEXT_MARKER,291,332,23,14,NOT WS_TABSTOP - CONTROL "",IDC_JUMP_PLAYBACK_BUTTON,"Button",BS_OWNERDRAW,4,0,59,13 - EDITTEXT IDC_PLAYBACK_MARKER_EDIT,64,0,127,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP - RTEXT "Marker 0",IDC_PLAYBACK_MARKER,3,2,58,10,0,WS_EX_RIGHT - CONTROL "",IDC_JUMP_SELECTION_BUTTON,"Button",BS_OWNERDRAW,4,333,59,13 - EDITTEXT IDC_SELECTION_MARKER_EDIT,64,333,127,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP - RTEXT "Marker 99999",IDC_SELECTION_MARKER,3,335,58,10,0,WS_EX_RIGHT - CONTROL "",IDC_BRANCHES_BITMAP,"Static",SS_OWNERDRAW | SS_NOTIFY | SS_REALSIZEIMAGE | NOT WS_VISIBLE,201,178,113,89 - CONTROL " Turbo seek",CHECK_TURBO_SEEK,"Button",BS_AUTOCHECKBOX,262,25,50,12 - LTEXT "Selection: 0 rows, 16 columns",IDC_TEXT_SELECTION,203,118,112,10 - LTEXT "Clipboard: 0 rows, 16 columns",IDC_TEXT_CLIPBOARD,202,128,114,10 - CONTROL " Recording",IDC_RECORDING,"Button",BS_AUTO3STATE,202,71,64,10 - PUSHBUTTON "Run function",TASEDITOR_RUN_MANUAL,201,150,54,14,WS_DISABLED | NOT WS_TABSTOP - CONTROL "Auto function",IDC_RUN_AUTO,"Button",BS_AUTOCHECKBOX,260,152,55,10 - CONTROL " Use pattern",IDC_USEPATTERN,"Button",BS_AUTOCHECKBOX,261,96,53,10 + "Button",BS_AUTOCHECKBOX,203,48,105,12 + CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | NOT WS_VISIBLE | WS_BORDER,202,178,113,89 + CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,202,282,113,42 + CONTROL " All",IDC_RADIO_ALL,"Button",BS_AUTORADIOBUTTON,291,71,24,10 + CONTROL " 1P",IDC_RADIO_1P,"Button",BS_AUTORADIOBUTTON,203,83,25,10 + CONTROL " 2P",IDC_RADIO_2P,"Button",BS_AUTORADIOBUTTON,232,83,25,10 + CONTROL " 3P",IDC_RADIO_3P,"Button",BS_AUTORADIOBUTTON,262,83,24,10 + CONTROL " 4P",IDC_RADIO_4P,"Button",BS_AUTORADIOBUTTON,291,83,24,10 + CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTO3STATE,203,96,55,10 + PUSHBUTTON "<<",TASEDITOR_PREV_MARKER,202,332,23,14,NOT WS_TABSTOP + PUSHBUTTON "Similar",TASEDITOR_FIND_BEST_SIMILAR_MARKER,225,332,34,14,NOT WS_TABSTOP + PUSHBUTTON "More",TASEDITOR_FIND_NEXT_SIMILAR_MARKER,259,332,34,14,NOT WS_TABSTOP + PUSHBUTTON ">>",TASEDITOR_NEXT_MARKER,292,332,23,14,NOT WS_TABSTOP + CONTROL "",IDC_JUMP_PLAYBACK_BUTTON,"Button",BS_OWNERDRAW,5,0,59,13 + EDITTEXT IDC_PLAYBACK_MARKER_EDIT,65,0,127,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + RTEXT "Marker 0",IDC_PLAYBACK_MARKER,4,2,58,10,0,WS_EX_RIGHT + CONTROL "",IDC_JUMP_SELECTION_BUTTON,"Button",BS_OWNERDRAW,5,333,59,13 + EDITTEXT IDC_SELECTION_MARKER_EDIT,65,333,127,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + RTEXT "Marker 99999",IDC_SELECTION_MARKER,4,335,58,10,0,WS_EX_RIGHT + CONTROL "",IDC_BRANCHES_BITMAP,"Static",SS_OWNERDRAW | SS_NOTIFY | SS_REALSIZEIMAGE | NOT WS_VISIBLE,202,178,113,89 + CONTROL " Turbo seek",CHECK_TURBO_SEEK,"Button",BS_AUTOCHECKBOX,263,25,50,12 + LTEXT "Selection: 0 rows, 16 columns",IDC_TEXT_SELECTION,204,118,112,10 + LTEXT "Clipboard: 0 rows, 16 columns",IDC_TEXT_CLIPBOARD,203,128,114,10 + CONTROL " Recording",IDC_RECORDING,"Button",BS_AUTO3STATE,203,71,64,10 + PUSHBUTTON "Run function",TASEDITOR_RUN_MANUAL,202,150,54,14,WS_DISABLED | NOT WS_TABSTOP + CONTROL "Auto function",IDC_RUN_AUTO,"Button",BS_AUTOCHECKBOX,261,152,55,10 + CONTROL " Use pattern",IDC_USEPATTERN,"Button",BS_AUTOCHECKBOX,262,96,53,10 END IDD_TASEDITOR_ABOUT DIALOGEX 0, 0, 238, 78 @@ -1982,6 +1984,8 @@ BEGIN "TASEDITOR", DIALOG BEGIN + RIGHTMARGIN, 323 + BOTTOMMARGIN, 351 END IDD_TASEDITOR_ABOUT, DIALOG diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 4ffa1672..cddc2f74 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -995,6 +995,8 @@ #define ID_EDIT_DESELECT 40536 #define ID_SELECTED_DESELECT 40537 #define ID_CONFIG_DESELECTONDOUBLECLICK 40538 +#define ID_CONFIG_DRAWINPUTBYDRAGGING 40539 +#define ID_CONFIG_DOUBLECLICKONFRAME 40540 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -1004,7 +1006,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 206 -#define _APS_NEXT_COMMAND_VALUE 40539 +#define _APS_NEXT_COMMAND_VALUE 40541 #define _APS_NEXT_CONTROL_VALUE 1281 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/taseditor.cpp b/src/drivers/win/taseditor.cpp index 0d78174c..af6cd67d 100644 --- a/src/drivers/win/taseditor.cpp +++ b/src/drivers/win/taseditor.cpp @@ -290,10 +290,10 @@ void UpdateTasEditor() // update all modules that need to be updated every frame taseditor_window.update(); + greenzone.update(); recorder.update(); piano_roll.update(); markers_manager.update(); - greenzone.update(); playback.update(); bookmarks.update(); popup_display.update(); diff --git a/src/drivers/win/taseditor/history.cpp b/src/drivers/win/taseditor/history.cpp index 9c3a4b6f..5b68ea71 100644 --- a/src/drivers/win/taseditor/history.cpp +++ b/src/drivers/win/taseditor/history.cpp @@ -83,7 +83,9 @@ char modCaptions[MODTYPES_TOTAL][20] = {" Init Project", " Marker Unset", " Marker Pattern", " Marker Rename", - " Marker Move", + " Marker Drag", + " Marker Swap", + " Marker Shift", " LUA Marker Set", " LUA Marker Unset", " LUA Marker Rename", @@ -445,10 +447,15 @@ void HISTORY::RegisterMarkersChange(int mod_type, int start, int end, const char _itoa(start, framenum, 10); strcat(inp.description, " "); strcat(inp.description, framenum); - if (end > start) + if (end > start || mod_type == MODTYPE_MARKER_DRAG || mod_type == MODTYPE_MARKER_SWAP) { + if (mod_type == MODTYPE_MARKER_DRAG) + strcat(inp.description, "=>"); + else if (mod_type == MODTYPE_MARKER_SWAP) + strcat(inp.description, "<=>"); + else + strcat(inp.description, "-"); _itoa(end, framenum, 10); - strcat(inp.description, "-"); strcat(inp.description, framenum); } // add comment if there is one specified @@ -838,8 +845,13 @@ bool HISTORY::CursorOverHistoryList() POINT p; if (GetCursorPos(&p)) { + RECT wrect; + GetWindowRect(hwndHistoryList, &wrect); ScreenToClient(hwndHistoryList, &p); - if (p.x >= 0 && p.y >= 0 && p.x < window_items[HISTORYLIST_IN_WINDOWITEMS].width && p.y < (taseditor_config.wndheight + window_items[HISTORYLIST_IN_WINDOWITEMS].height - window_items[HISTORYLIST_IN_WINDOWITEMS].y)) + if (p.x >= 0 + && p.y >= 0 + && p.x < window_items[HISTORYLIST_IN_WINDOWITEMS].width + && p.y < (wrect.bottom - wrect.top)) return true; } return false; diff --git a/src/drivers/win/taseditor/history.h b/src/drivers/win/taseditor/history.h index 7c13d595..ed346042 100644 --- a/src/drivers/win/taseditor/history.h +++ b/src/drivers/win/taseditor/history.h @@ -44,7 +44,9 @@ enum MODTYPE_MARKER_UNSET, MODTYPE_MARKER_PATTERN, MODTYPE_MARKER_RENAME, - MODTYPE_MARKER_MOVE, + MODTYPE_MARKER_DRAG, + MODTYPE_MARKER_SWAP, + MODTYPE_MARKER_SHIFT, MODTYPE_LUA_MARKER_SET, MODTYPE_LUA_MARKER_UNSET, MODTYPE_LUA_MARKER_RENAME, @@ -54,7 +56,6 @@ enum }; #define HISTORY_NORMAL_COLOR 0x000000 -#define HISTORYLIST_IN_WINDOWITEMS 18 #define WM_MOUSEWHEEL_RESENT WM_APP+123 #define HISTORY_ID_LEN 8 diff --git a/src/drivers/win/taseditor/markers_manager.cpp b/src/drivers/win/taseditor/markers_manager.cpp index 69e6ebdf..d99f9568 100644 --- a/src/drivers/win/taseditor/markers_manager.cpp +++ b/src/drivers/win/taseditor/markers_manager.cpp @@ -185,7 +185,7 @@ void MARKERS_MANAGER::ClearMarker(int frame) { // erase corresponding note markers.notes.erase(markers.notes.begin() + markers.markers_array[frame]); - // erase marker + // clear marker markers.markers_array[frame] = 0; // decrease following markers' ids int size = markers.markers_array.size(); diff --git a/src/drivers/win/taseditor/piano_roll.cpp b/src/drivers/win/taseditor/piano_roll.cpp index 819e15be..b3a21177 100644 --- a/src/drivers/win/taseditor/piano_roll.cpp +++ b/src/drivers/win/taseditor/piano_roll.cpp @@ -10,7 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Piano Roll - Piano Roll interface [Singleton] -* implements the working of Piano Roll List: creating, redrawing, scrolling, clicks +* implements the working of Piano Roll List: creating, redrawing, scrolling, mouseover, clicks, drag * on demand: scrolls visible area of the List to any given item: to Playback Cursor, to Selection Cursor, to "undo pointer", to a Marker * saves and loads current position of vertical scrolling from a project file. On error: scrolls the List to the beginning * implements the working of Piano Roll List Header: creating, redrawing, animating, mouseover, clicks @@ -18,6 +18,7 @@ Piano Roll - Piano Roll interface * regularly updates the size of the List according to current movie input, also updates lights in the List Header according to button presses data from Recorder and Alt key state * implements the working of mouse wheel: List scrolling, Playback cursor movement, Selection cursor movement * implements context menu on Right-click +* updates mouse cursor icon depending on item under cursor * stores resources: save id, ids of columns, widths of columns, tables of colors, gradient of Hot Changes, gradient of Header flashings, timings of flashes, all fonts used in TAS Editor, images ------------------------------------------------------------------------------------ */ @@ -43,21 +44,48 @@ extern HISTORY history; extern MARKERS_MANAGER markers_manager; extern SELECTION selection; +extern Window_items_struct window_items[]; extern int GetInputType(MovieData& md); LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); WNDPROC hwndList_oldWndProc = 0, hwndHeader_oldWndproc = 0; +LRESULT APIENTRY MarkerDragBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + // resources char piano_roll_save_id[PIANO_ROLL_ID_LEN] = "PIANO_ROLL"; char piano_roll_skipsave_id[PIANO_ROLL_ID_LEN] = "PIANO_ROLX"; COLORREF hot_changes_colors[16] = { 0x0, 0x5c4c44, 0x854604, 0xab2500, 0xc20006, 0xd6006f, 0xd40091, 0xba00a4, 0x9500ba, 0x7a00cc, 0x5800d4, 0x0045e2, 0x0063ea, 0x0079f4, 0x0092fa, 0x00aaff }; //COLORREF hot_changes_colors[16] = { 0x0, 0x661212, 0x842B4E, 0x652C73, 0x48247D, 0x383596, 0x2947AE, 0x1E53C1, 0x135DD2, 0x116EDA, 0x107EE3, 0x0F8EEB, 0x209FF4, 0x3DB1FD, 0x51C2FF, 0x4DCDFF }; COLORREF header_lights_colors[11] = { 0x0, 0x007313, 0x009100, 0x1daf00, 0x42c700, 0x65d900, 0x91e500, 0xb0f000, 0xdaf700, 0xf0fc7c, 0xfcffba }; +char markerDragBoxClassName[] = "MarkerDragBox"; PIANO_ROLL::PIANO_ROLL() { + hwndMarkerDragBox = 0; + // register MARKER_DRAG_BOX window class + wincl.hInstance = fceu_hInstance; + wincl.lpszClassName = markerDragBoxClassName; + wincl.lpfnWndProc = MarkerDragBoxWndProc; + wincl.style = CS_DBLCLKS; + wincl.cbSize = sizeof(WNDCLASSEX); + wincl.hIcon = 0; + wincl.hIconSm = 0; + wincl.hCursor = 0; + wincl.lpszMenuName = 0; + wincl.cbClsExtra = 0; + wincl.cbWndExtra = 0; + wincl.hbrBackground = 0; + if(!RegisterClassEx(&wincl)) + FCEU_printf("Error registering MARKER_DRAG_BOX window class\n"); + + // create blendfunction + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.AlphaFormat = 0; + blend.SourceConstantAlpha = 255; + } void PIANO_ROLL::init() @@ -97,6 +125,8 @@ void PIANO_ROLL::init() "Arial"); /*font name*/ bg_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); + marker_drag_box_brush = CreateSolidBrush(MARKED_FRAMENUM_COLOR); + marker_drag_box_brush_bind = CreateSolidBrush(BINDMARKED_FRAMENUM_COLOR); hwndList = GetDlgItem(taseditor_window.hwndTasEditor, IDC_LIST1); // prepare the main listview @@ -183,6 +213,20 @@ void PIANO_ROLL::init() lvc.mask = LVCF_WIDTH; lvc.cx = COLUMN_ICONS_WIDTH; ListView_InsertColumn(hwndList, 0, &lvc); + // find rows top/height (for mouseover hittest calculations) + ListView_SetItemCountEx(hwndList, 1, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL); + RECT temp_rect; + if (ListView_GetSubItemRect(hwndList, 0, 0, LVIR_BOUNDS, &temp_rect) && temp_rect.bottom != temp_rect.top) + { + list_row_top = temp_rect.top; + list_row_height = temp_rect.bottom - temp_rect.top; + } else + { + // couldn't get rect, set default values + list_row_top = 20; + list_row_height = 14; + } + ListView_SetItemCountEx(hwndList, 0, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL); hrmenu = LoadMenu(fceu_hInstance,"TASEDITORCONTEXTMENUS"); header_colors.resize(TOTAL_COLUMNS); @@ -190,7 +234,7 @@ void PIANO_ROLL::init() tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwndHeader; - + drag_mode = DRAG_MODE_NONE; } void PIANO_ROLL::free() { @@ -224,6 +268,21 @@ void PIANO_ROLL::free() DeleteObject(bg_brush); bg_brush = 0; } + if (marker_drag_box_brush) + { + DeleteObject(marker_drag_box_brush); + marker_drag_box_brush = 0; + } + if (marker_drag_box_brush_bind) + { + DeleteObject(marker_drag_box_brush_bind); + marker_drag_box_brush_bind = 0; + } + if (bg_brush) + { + DeleteObject(bg_brush); + bg_brush = 0; + } if (himglist) { ImageList_Destroy(himglist); @@ -233,6 +292,7 @@ void PIANO_ROLL::free() } void PIANO_ROLL::reset() { + must_check_item_under_mouse = true; vk_shift_release_time = vk_control_release_time = 0; next_header_update_time = header_item_under_mouse = 0; // delete all columns except 0th @@ -274,7 +334,136 @@ void PIANO_ROLL::update() if(currLVItemCount != movie_size) ListView_SetItemCountEx(hwndList, movie_size, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL); - // once per 40 milliseconds update colors alpha + // update dragging + if (drag_mode != DRAG_MODE_NONE) + { + // check if user released left button + if (GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON) >= 0) + FinishDrag(); + } + // also scroll Piano Roll if user is dragging cursor outside + if (drag_mode != DRAG_MODE_NONE) + { + POINT p; + if (GetCursorPos(&p)) + { + int scroll_dx = 0, scroll_dy = 0; + RECT wrect; + GetWindowRect(hwndList, &wrect); + ScreenToClient(hwndList, &p); + if (p.x < 0) + scroll_dx = p.x; + else if (p.x > (wrect.right - wrect.left)) + scroll_dx = p.x - (wrect.right - wrect.left); + if (p.y < 0) + scroll_dy = p.y; + else if (p.y > (wrect.bottom - wrect.top)) + scroll_dy = p.y - (wrect.bottom - wrect.top); + if (scroll_dx || scroll_dy) + ListView_Scroll(hwndList, scroll_dx, scroll_dy); + } + } + // perform drag + switch (drag_mode) + { + case DRAG_MODE_PLAYBACK: + { + if (!playback.pause_frame) + DragPlaybackCursor(); + break; + } + case DRAG_MODE_MARKER: + { + // if suddenly source frame lost its Marker, abort drag + if (!markers_manager.GetMarker(marker_drag_framenum)) + { + if (hwndMarkerDragBox) + { + DestroyWindow(hwndMarkerDragBox); + hwndMarkerDragBox = 0; + } + drag_mode = DRAG_MODE_NONE; + break; + } + // when dragging, always show semi-transparent yellow rectangle under mouse + POINT p = {0, 0}; + GetCursorPos(&p); + int window_x = p.x - marker_drag_box_dx; + int window_y = p.y - marker_drag_box_dy; + if (!hwndMarkerDragBox) + { + hwndMarkerDragBox = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, markerDragBoxClassName, markerDragBoxClassName, WS_POPUP, window_x, window_y, COLUMN_FRAMENUM_WIDTH, list_row_height, taseditor_window.hwndTasEditor, NULL, fceu_hInstance, NULL); + ShowWindow(hwndMarkerDragBox, SW_SHOWNA); + SetLayeredWindowAttributes(hwndMarkerDragBox, 0, MARKER_DRAG_BOX_ALPHA, LWA_ALPHA); + UpdateLayeredWindow(hwndMarkerDragBox, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); + } else + { + SetWindowPos(hwndMarkerDragBox, 0, window_x, window_y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + } + // force dragging cursor icon + SetCursor(LoadCursor(0, IDC_ARROW)); + must_check_item_under_mouse = false; + break; + } + case DRAG_MODE_SET: + case DRAG_MODE_UNSET: + { + POINT p; + if (GetCursorPos(&p)) + { + RECT wrect; + GetWindowRect(hwndList, &wrect); + ScreenToClient(hwndList, &p); + int drawing_current_x = p.x + GetScrollPos(hwndList, SB_HORZ); + int drawing_current_y = p.y + GetScrollPos(hwndList, SB_VERT) * list_row_height; + // draw (or erase) line from [drawing_current_x, drawing_current_y] to (drawing_last_x, drawing_last_y) + int total_dx = drawing_last_x - drawing_current_x, total_dy = drawing_last_y - drawing_current_y; + double total_len = sqrt((double)(total_dx * total_dx + total_dy * total_dy)); + LVHITTESTINFO info; + int row_index, column_index, joy, bit; + int min_row_index = currMovieData.getNumRecords(), max_row_index = -1; + bool changes_made = false; + for (double len = 0; len < total_len; len += DRAWING_MIN_LINE_LEN) + { + // perform hit test + info.pt.x = p.x + (len / total_len) * total_dx; + info.pt.y = p.y + (len / total_len) * total_dy; + ListView_SubItemHitTest(hwndList, &info); + row_index = info.iItem; + column_index = info.iSubItem; + if (row_index >= 0 && column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R) + { + joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS; + bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS; + if (drag_mode == DRAG_MODE_SET && !currMovieData.records[row_index].checkBit(joy, bit)) + { + currMovieData.records[row_index].setBit(joy, bit); + changes_made = true; + if (min_row_index > row_index) min_row_index = row_index; + if (max_row_index < row_index) max_row_index = row_index; + } else if (drag_mode == DRAG_MODE_UNSET && currMovieData.records[row_index].checkBit(joy, bit)) + { + currMovieData.records[row_index].clearBit(joy, bit); + changes_made = true; + if (min_row_index > row_index) min_row_index = row_index; + if (max_row_index < row_index) max_row_index = row_index; + } + } + } + if (changes_made) + { + if (drag_mode == DRAG_MODE_SET) + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, min_row_index, max_row_index)); + else + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, min_row_index, max_row_index)); + } + drawing_last_x = drawing_current_x; + drawing_last_y = drawing_current_y; + } + break; + } + } + // once per 40 milliseconds update colors alpha in the Header if (clock() > next_header_update_time) { next_header_update_time = clock() + HEADER_LIGHT_UPDATE_TICK; @@ -283,7 +472,7 @@ void PIANO_ROLL::update() // 1 - update Frame# columns' heads if (GetAsyncKeyState(VK_MENU) & 0x8000) light_value = HEADER_LIGHT_HOLD; - else if (header_item_under_mouse == COLUMN_FRAMENUM || header_item_under_mouse == COLUMN_FRAMENUM2) + else if (drag_mode == DRAG_MODE_NONE && (header_item_under_mouse == COLUMN_FRAMENUM || header_item_under_mouse == COLUMN_FRAMENUM2)) light_value = (selection.GetCurrentSelectionSize() > 0) ? HEADER_LIGHT_MOUSEOVER_SEL : HEADER_LIGHT_MOUSEOVER; if (header_colors[COLUMN_FRAMENUM] < light_value) { @@ -303,7 +492,7 @@ void PIANO_ROLL::update() light_value = 0; if (recorder.current_joy[(i - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS] & (1 << ((i - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS))) light_value = HEADER_LIGHT_HOLD; - else if (header_item_under_mouse == i) + else if (drag_mode == DRAG_MODE_NONE && header_item_under_mouse == i) light_value = (selection.GetCurrentSelectionSize() > 0) ? HEADER_LIGHT_MOUSEOVER_SEL : HEADER_LIGHT_MOUSEOVER; if (header_colors[i] < light_value) { @@ -319,6 +508,56 @@ void PIANO_ROLL::update() if (changes_made) RedrawHeader(); } + + // change mouse cursor depending on what it points at + if (must_check_item_under_mouse) + { + LPCSTR cursor_icon = IDC_ARROW; + switch (drag_mode) + { + case DRAG_MODE_NONE: + { + // normal mouseover + POINT p; + if (GetCursorPos(&p)) + { + RECT wrect; + GetWindowRect(hwndList, &wrect); + ScreenToClient(hwndList, &p); + if (p.x >= 0 && p.y >= 0 && p.x < (wrect.right - wrect.left) && p.y < (wrect.bottom - wrect.top)) + { + // perform hit test + LVHITTESTINFO info; + info.pt.x = p.x; + info.pt.y = p.y; + ListView_SubItemHitTest(hwndList, &info); + int row_index = info.iItem; + int column_index = info.iSubItem; + if (row_index >= 0 + && (column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) + && markers_manager.GetMarker(row_index)) + cursor_icon = IDC_SIZEALL; + } + } + break; + } + case DRAG_MODE_PLAYBACK: + { + // dragging Playback cursor - show either normal arrow or arrow+wait + if (playback.pause_frame) + cursor_icon = IDC_APPSTARTING; + break; + } + case DRAG_MODE_MARKER: + case DRAG_MODE_OBSERVE: + case DRAG_MODE_SET: + case DRAG_MODE_UNSET: + // show normal arrow + break; + } + SetCursor(LoadCursor(0, cursor_icon)); + must_check_item_under_mouse = false; + } } void PIANO_ROLL::save(EMUFILE *os, bool really_save) @@ -370,6 +609,7 @@ error: void PIANO_ROLL::RedrawList() { InvalidateRect(hwndList, 0, FALSE); + must_check_item_under_mouse = true; } void PIANO_ROLL::RedrawRow(int index) { @@ -483,6 +723,111 @@ void PIANO_ROLL::SetHeaderColumnLight(int column, int level) } } +void PIANO_ROLL::DragPlaybackCursor() +{ + POINT p; + if (GetCursorPos(&p)) + { + ScreenToClient(hwndList, &p); + // perform hit test + LVHITTESTINFO info; + info.pt.x = p.x; + info.pt.y = p.y; + ListView_SubItemHitTest(hwndList, &info); + int row_index = info.iItem; + if (row_index < 0) + row_index = ListView_GetTopIndex(hwndList) + (p.y - list_row_top) / list_row_height; + // send Playback there + if (currFrameCounter != row_index) + { + int lastCursor = currFrameCounter; + playback.jump(row_index); + if (lastCursor != currFrameCounter) + { + // redraw row where Playback cursor was (in case there's two or more drags before playback.update()) + RedrawRow(lastCursor); + bookmarks.RedrawChangedBookmarks(lastCursor); + } + } + } +} + +void PIANO_ROLL::FinishDrag() +{ + switch (drag_mode) + { + case DRAG_MODE_MARKER: + { + // place Marker here + if (markers_manager.GetMarker(marker_drag_framenum)) + { + POINT p; + if (GetCursorPos(&p)) + { + ScreenToClient(hwndList, &p); + // perform hit test + LVHITTESTINFO info; + info.pt.x = p.x; + info.pt.y = p.y; + ListView_SubItemHitTest(hwndList, &info); + int row_index = info.iItem; + int column_index = info.iSubItem; + if (row_index >= 0 && row_index != marker_drag_framenum && (column_index <= COLUMN_FRAMENUM || column_index >= COLUMN_FRAMENUM2)) + { + if (markers_manager.GetMarker(row_index)) + { + int dragged_marker_id = markers_manager.GetMarker(marker_drag_framenum); + int destination_marker_id = markers_manager.GetMarker(row_index); + // swap Notes of these Markers + char dragged_marker_note[MAX_NOTE_LEN]; + strcpy(dragged_marker_note, markers_manager.GetNote(dragged_marker_id).c_str()); + if (strcmp(markers_manager.GetNote(destination_marker_id).c_str(), dragged_marker_note)) + { + // notes are different, swap them + markers_manager.SetNote(dragged_marker_id, markers_manager.GetNote(destination_marker_id).c_str()); + markers_manager.SetNote(destination_marker_id, dragged_marker_note); + history.RegisterMarkersChange(MODTYPE_MARKER_SWAP, marker_drag_framenum, row_index); + selection.must_find_current_marker = playback.must_find_current_marker = true; + SetHeaderColumnLight(COLUMN_FRAMENUM, HEADER_LIGHT_MAX); + } + } else + { + // move Marker + int new_marker_id = markers_manager.SetMarker(row_index); + if (new_marker_id) + { + markers_manager.SetNote(new_marker_id, markers_manager.GetNote(markers_manager.GetMarker(marker_drag_framenum)).c_str()); + // and delete it from old frame + markers_manager.ClearMarker(marker_drag_framenum); + RedrawRow(marker_drag_framenum); + RedrawRow(row_index); + history.RegisterMarkersChange(MODTYPE_MARKER_DRAG, marker_drag_framenum, row_index, markers_manager.GetNote(markers_manager.GetMarker(row_index)).c_str()); + selection.must_find_current_marker = playback.must_find_current_marker = true; + SetHeaderColumnLight(COLUMN_FRAMENUM, HEADER_LIGHT_MAX); + } + } + } + } + } + + if (hwndMarkerDragBox) + { + DestroyWindow(hwndMarkerDragBox); + hwndMarkerDragBox = 0; + } + break; + } + } + drag_mode = DRAG_MODE_NONE; + must_check_item_under_mouse = true; +} + +void PIANO_ROLL::AcceleratorDispatched() +{ + // hack for tapping Ctrl twice - if first was accelerator, then it won't count as first tap + vk_control_release_time = -1; +} + void PIANO_ROLL::GetDispInfo(NMLVDISPINFO* nmlvDispInfo) { LVITEM& item = nmlvDispInfo->item; @@ -1063,6 +1408,18 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_CHAR: case WM_KILLFOCUS: return 0; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) + { + piano_roll.must_check_item_under_mouse = true; + return true; + } + break; + case WM_MOUSEMOVE: + { + piano_roll.must_check_item_under_mouse = true; + return 0; + } case WM_NOTIFY: { if (((LPNMHDR)lParam)->hwndFrom == piano_roll.hwndHeader) @@ -1082,9 +1439,18 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_KEYUP: { if (wParam == VK_SHIFT) - piano_roll.vk_shift_release_time = clock(); - else if (wParam == VK_CONTROL) - piano_roll.vk_control_release_time = clock(); + { + if (piano_roll.vk_shift_release_time >= 0) + piano_roll.vk_shift_release_time = clock(); + else // this was accelerator + piano_roll.vk_shift_release_time = 0; + } else if (wParam == VK_CONTROL) + { + if (piano_roll.vk_control_release_time >= 0) + piano_roll.vk_control_release_time = clock(); + else // this was accelerator + piano_roll.vk_control_release_time = 0; + } break; } case WM_KEYDOWN: @@ -1092,19 +1458,21 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (wParam == VK_SHIFT) { // double-tap of Shift key - if (piano_roll.vk_shift_release_time + GetDoubleClickTime() > clock()) + if ((int)(piano_roll.vk_shift_release_time + GetDoubleClickTime()) > clock()) piano_roll.FollowPlayback(); } else if (wParam == VK_CONTROL) { // double-tap of Ctrl key - if (piano_roll.vk_control_release_time + GetDoubleClickTime() > clock()) + if ((int)(piano_roll.vk_control_release_time + GetDoubleClickTime()) > clock()) piano_roll.FollowSelection(); } // only allow 8 keys if (taseditor_config.keyboard_for_piano_roll && (wParam == VK_LEFT || wParam == VK_UP || wParam == VK_RIGHT || wParam == VK_DOWN || wParam == VK_END || wParam == VK_HOME || wParam == VK_PRIOR || wParam == VK_NEXT)) + { + piano_roll.must_check_item_under_mouse = true; break; - else - return 0; + } + return 0; } case WM_TIMER: // disable timer of entering edit mode (there's no edit mode anyway) @@ -1118,25 +1486,32 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LVHITTESTINFO info; info.pt.x = GET_X_LPARAM(lParam); info.pt.y = GET_Y_LPARAM(lParam); - ListView_SubItemHitTest(hWnd, (LPARAM)&info); + ListView_SubItemHitTest(hWnd, &info); int row_index = info.iItem; int column_index = info.iSubItem; - if(row_index >= 0) + if(column_index == COLUMN_ICONS) { - if(column_index == COLUMN_ICONS) + // click on the "icons" column + piano_roll.DragPlaybackCursor(); + if (piano_roll.drag_mode == DRAG_MODE_NONE) + piano_roll.drag_mode = DRAG_MODE_PLAYBACK; + } else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) + { + // clicked on the "Frame#" column + if (msg == WM_LBUTTONDBLCLK && !alt_pressed) { - // click on the "icons" column - jump to the frame - playback.jump(row_index); - } else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) - { - // clicked on the "Frame#" column - if (msg == WM_LBUTTONDBLCLK && !alt_pressed) + // doubleclick - jump to the frame + if (taseditor_config.deselect_on_doubleclick) + selection.ClearSelection(); + if (taseditor_config.doubleclick_affects_playback) { - // doubleclick - jump to the frame - if (taseditor_config.deselect_on_doubleclick) - selection.ClearSelection(); - playback.jump(row_index); - } else + piano_roll.DragPlaybackCursor(); + if (piano_roll.drag_mode == DRAG_MODE_NONE) + piano_roll.drag_mode = DRAG_MODE_PLAYBACK; + } + } else + { + if (row_index >= 0) { // set marker if clicked with Alt if (alt_pressed) @@ -1148,14 +1523,39 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) else history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, row_index); piano_roll.RedrawRow(row_index); + } else if (piano_roll.drag_mode == DRAG_MODE_NONE) + { + // check if user clicked on a Marker + if (markers_manager.GetMarker(row_index)) + { + // start dragging the Marker + RECT temp_rect; + if (ListView_GetSubItemRect(piano_roll.hwndList, row_index, column_index, LVIR_BOUNDS, &temp_rect)) + { + piano_roll.marker_drag_box_dx = GET_X_LPARAM(lParam) - temp_rect.left; + piano_roll.marker_drag_box_dy = GET_Y_LPARAM(lParam) - temp_rect.top; + } else + { + piano_roll.marker_drag_box_dx = 0; + piano_roll.marker_drag_box_dy = 0; + } + piano_roll.drag_mode = DRAG_MODE_MARKER; + piano_roll.marker_drag_framenum = row_index; + } else + { + piano_roll.drag_mode = DRAG_MODE_OBSERVE; + } } // also select the row by calling hwndList_oldWndProc PostMessage(hWnd, WM_LBUTTONUP, 0, 0); // ensure that oldWndProc will exit its modal message loop immediately CallWindowProc(hwndList_oldWndProc, hWnd, msg, wParam, lParam); } - } else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R) + } + } else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R) + { + // clicked on input + if (row_index >= 0) { - // clicked on input // first call old wndproc to set selection on the row if (alt_pressed) wParam |= MK_SHIFT; // Alt should select region, just like Shift @@ -1170,6 +1570,25 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) } else { piano_roll.ToggleJoypadBit(column_index, row_index, GET_KEYSTATE_WPARAM(wParam)); + if (piano_roll.drag_mode == DRAG_MODE_NONE) + { + if (taseditor_config.draw_input) + { + // if clicked on empty cell - start drawing, else start erasing + int joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS; + int bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS; + if (currMovieData.records[row_index].checkBit(joy, bit)) + piano_roll.drag_mode = DRAG_MODE_SET; + else + piano_roll.drag_mode = DRAG_MODE_UNSET; + piano_roll.drawing_last_x = GET_X_LPARAM(lParam) + GetScrollPos(piano_roll.hwndList, SB_HORZ); + piano_roll.drawing_last_y = GET_Y_LPARAM(lParam) + GetScrollPos(piano_roll.hwndList, SB_VERT) * piano_roll.list_row_height; + } else + { + piano_roll.drag_mode = DRAG_MODE_OBSERVE; + } + } + } } } @@ -1195,7 +1614,6 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) playback.ForwardFull(-zDelta / 120); else if (zDelta > 0) playback.RewindFull(zDelta / 120); - return 0; } else if (fwKeys & MK_CONTROL) { // Ctrl + wheel = Selection rewind full(speed)/forward full(speed) @@ -1203,7 +1621,6 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) selection.JumpNextMarker(-zDelta / 120); else if (zDelta > 0) selection.JumpPrevMarker(zDelta / 120); - return 0; } else if (alt_pressed || fwKeys & MK_RBUTTON) { // Right button + wheel = Alt + wheel = rewind/forward @@ -1220,12 +1637,15 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) piano_roll.RedrawRow(lastCursor); bookmarks.RedrawChangedBookmarks(lastCursor); } - return 0; } else if (history.CursorOverHistoryList()) { return SendMessage(history.hwndHistoryList, WM_MOUSEWHEEL_RESENT, wParam, lParam); + } else + { + // normal scrolling + CallWindowProc(hwndList_oldWndProc, hWnd, msg, wParam, lParam); } - break; + return 0; } case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: @@ -1238,17 +1658,78 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LVHITTESTINFO info; info.pt.x = GET_X_LPARAM(lParam); info.pt.y = GET_Y_LPARAM(lParam); - ListView_SubItemHitTest(hWnd, (LPARAM)&info); + ListView_SubItemHitTest(hWnd, &info); // show context menu if user right-clicked on Frame# if(info.iSubItem <= COLUMN_FRAMENUM || info.iSubItem >= COLUMN_FRAMENUM2) piano_roll.RightClick(info); return 0; } - case WM_MOUSEACTIVATE: + case WM_NCLBUTTONDOWN: + { + if (wParam == HTBORDER) + { + POINT p; + p.x = GET_X_LPARAM(lParam); + p.y = GET_Y_LPARAM(lParam); + ScreenToClient(piano_roll.hwndList, &p); + if (p.x <= 0) + { + // user clicked on left border of the Piano Roll + // consider this as a "misclick" on Piano Roll's first column + piano_roll.DragPlaybackCursor(); + if (piano_roll.drag_mode == DRAG_MODE_NONE) + piano_roll.drag_mode = DRAG_MODE_PLAYBACK; + return 0; + } + } + break; + } + case WM_MOUSEACTIVATE: + { if (GetFocus() != hWnd) SetFocus(hWnd); break; + } + case LVM_ENSUREVISIBLE: + { + piano_roll.must_check_item_under_mouse = true; + break; + } } return CallWindowProc(hwndList_oldWndProc, hWnd, msg, wParam, lParam); } +// ---------------------------------------------------------------------------------------- +LRESULT APIENTRY MarkerDragBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + extern PIANO_ROLL piano_roll; + switch(message) + { + case WM_CREATE: + { + // create static bitmap placeholder + char framenum[DIGITS_IN_FRAMENUM + 1]; + U32ToDecStr(framenum, piano_roll.marker_drag_framenum, DIGITS_IN_FRAMENUM); + piano_roll.hwndMarkerDragBoxText = CreateWindow(WC_STATIC, framenum, SS_CENTER| WS_CHILD | WS_VISIBLE, 0, 0, COLUMN_FRAMENUM_WIDTH, piano_roll.list_row_height, hwnd, NULL, NULL, NULL); + SendMessage(piano_roll.hwndMarkerDragBoxText, WM_SETFONT, (WPARAM)piano_roll.hMainListSelectFont, 0); + return 0; + } + case WM_CTLCOLORSTATIC: + { + // change color of static text fields + if ((HWND)lParam == piano_roll.hwndMarkerDragBoxText) + { + SetTextColor((HDC)wParam, NORMAL_TEXT_COLOR); + SetBkMode((HDC)wParam, TRANSPARENT); + if (taseditor_config.bind_markers) + return (LRESULT)(piano_roll.marker_drag_box_brush_bind); + else + return (LRESULT)(piano_roll.marker_drag_box_brush); + } + break; + } + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + + diff --git a/src/drivers/win/taseditor/piano_roll.h b/src/drivers/win/taseditor/piano_roll.h index f637e8ab..d7d1d475 100644 --- a/src/drivers/win/taseditor/piano_roll.h +++ b/src/drivers/win/taseditor/piano_roll.h @@ -19,6 +19,9 @@ #define BOOST_WHEN_BOTH_RIGHTBUTTON_AND_ALT_PRESSED 4 +#define MARKER_DRAG_BOX_ALPHA 175 +#define DRAWING_MIN_LINE_LEN 14 // = min(list_row_width, list_row_height) in pixels + enum { COLUMN_ICONS, @@ -60,6 +63,16 @@ enum TOTAL_COLUMNS }; +enum DRAG_MODES +{ + DRAG_MODE_NONE, + DRAG_MODE_OBSERVE, + DRAG_MODE_PLAYBACK, + DRAG_MODE_MARKER, + DRAG_MODE_SET, + DRAG_MODE_UNSET, +}; + // when there's too many button columns, there's need for 2nd Frame# column at the end #define NUM_COLUMNS_NEED_2ND_FRAMENUM COLUMN_JOYPAD4_R @@ -139,6 +152,11 @@ public: void SetHeaderColumnLight(int column, int level); + void DragPlaybackCursor(); + void FinishDrag(); + + void AcceleratorDispatched(); + void GetDispInfo(NMLVDISPINFO* nmlvDispInfo); LONG CustomDraw(NMLVCUSTOMDRAW* msg); LONG HeaderCustomDraw(NMLVCUSTOMDRAW* msg); @@ -158,13 +176,22 @@ public: HWND hwndList, hwndHeader; TRACKMOUSEEVENT tme; + unsigned int drag_mode; + int list_row_top, list_row_height; + int marker_drag_box_dx, marker_drag_box_dy; + int marker_drag_framenum; + int drawing_last_x, drawing_last_y; + + bool must_check_item_under_mouse; + int vk_shift_release_time; int vk_control_release_time; + HWND hwndMarkerDragBox, hwndMarkerDragBoxText; // GDI stuff HIMAGELIST himglist; HFONT hMainListFont, hMainListSelectFont, hMarkersFont, hMarkersEditFont, hTaseditorAboutFont; - HBRUSH bg_brush; + HBRUSH bg_brush, marker_drag_box_brush, marker_drag_box_brush_bind; private: void CenterListAt(int frame); @@ -175,4 +202,7 @@ private: HMENU hrmenu; + WNDCLASSEX wincl; + BLENDFUNCTION blend; + }; diff --git a/src/drivers/win/taseditor/playback.cpp b/src/drivers/win/taseditor/playback.cpp index d600294b..09d95c77 100644 --- a/src/drivers/win/taseditor/playback.cpp +++ b/src/drivers/win/taseditor/playback.cpp @@ -68,7 +68,7 @@ void PLAYBACK::reset() { must_find_current_marker = true; shown_marker = 0; - lastCursor = -1; + lastCursor = currFrameCounter; lost_position_frame = pause_frame = old_pauseframe = 0; old_show_pauseframe = show_pauseframe = false; old_rewind_button_state = rewind_button_state = false; @@ -172,17 +172,29 @@ void PLAYBACK::update() emu_paused = (FCEUI_EmulationPaused() != 0); if (pause_frame) { - if (old_show_pauseframe != show_pauseframe) + if (old_show_pauseframe != show_pauseframe) // update progressbar from time to time SetProgressbar(currFrameCounter - seeking_start_frame, pause_frame - seeking_start_frame); } else if (old_emu_paused != emu_paused) { // emulator got paused/unpaused externally if (old_emu_paused && !emu_paused) - // externally unpaused - progressbar should be empty - SetProgressbar(0, 1); - else + { + // externally unpaused + if (currFrameCounter < currMovieData.getNumRecords()-1) + { + // don't forget to stop at the end of the movie + pause_frame = currMovieData.getNumRecords(); + seeking_start_frame = currFrameCounter; + } else + { + // unlimited emulation, appending the movie - progressbar should be empty + SetProgressbar(0, 1); + } + } else + { // externally paused - progressbar should be full SetProgressbar(1, 1); + } } // update the playback cursor @@ -278,6 +290,17 @@ void PLAYBACK::SeekingStart(int finish_frame) turbo = true; UnpauseEmulation(); } +void PLAYBACK::SeekingContinue() +{ + if (pause_frame) + { + if (taseditor_config.turbo_seek) + turbo = true; + UnpauseEmulation(); + } +} + + void PLAYBACK::SeekingStop() { pause_frame = 0; @@ -388,10 +411,16 @@ bool PLAYBACK::JumpToFrame(int index) // Returns true if a jump to the frame is made, false if started seeking outside greenzone or if nothing's done if (index < 0) return false; + if (index+1 == pause_frame && emu_paused) + { + SeekingContinue(); + return false; + } + if (index >= greenzone.greenZoneCount) { // handle jump outside greenzone - if (currFrameCounter == greenzone.greenZoneCount-1 || JumpToFrame(greenzone.greenZoneCount-1)) + if (currFrameCounter >= greenzone.greenZoneCount-1 || JumpToFrame(greenzone.greenZoneCount-1)) // seek from the end of greenzone SeekingStart(index+1); return false; diff --git a/src/drivers/win/taseditor/playback.h b/src/drivers/win/taseditor/playback.h index 1706c8ae..f2c9e098 100644 --- a/src/drivers/win/taseditor/playback.h +++ b/src/drivers/win/taseditor/playback.h @@ -21,6 +21,7 @@ public: void updateProgressbar(); void SeekingStart(int finish_frame); + void SeekingContinue(); void SeekingStop(); void ToggleEmulationPause(); void PauseEmulation(); @@ -43,6 +44,7 @@ public: bool JumpToFrame(int index); + int lastCursor; // but for currentCursor we use external variable currFrameCounter int lost_position_frame; int pause_frame; bool must_find_current_marker; @@ -53,7 +55,6 @@ public: private: - int lastCursor; // but for currentCursor we use external variable currFrameCounter bool old_emu_paused, emu_paused; int old_pauseframe; bool old_show_pauseframe, show_pauseframe; diff --git a/src/drivers/win/taseditor/popup_display.cpp b/src/drivers/win/taseditor/popup_display.cpp index 5fd04165..95bff54e 100644 --- a/src/drivers/win/taseditor/popup_display.cpp +++ b/src/drivers/win/taseditor/popup_display.cpp @@ -26,7 +26,7 @@ extern PIANO_ROLL piano_roll; extern MARKERS_MANAGER markers_manager; LRESULT CALLBACK ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT APIENTRY MarkerNoteTooltipWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT APIENTRY MarkerNoteDescrWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); // resources char szClassName[] = "ScrBmp"; @@ -34,6 +34,8 @@ char szClassName2[] = "MarketNoteTooltip"; POPUP_DISPLAY::POPUP_DISPLAY() { + hwndScrBmp = 0; + hwndMarkerNoteTooltip = 0; // create BITMAPINFO scr_bmi = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); // 256 color in palette scr_bmi->bmiHeader.biSize = sizeof(scr_bmi->bmiHeader); @@ -44,7 +46,7 @@ POPUP_DISPLAY::POPUP_DISPLAY() scr_bmi->bmiHeader.biCompression = BI_RGB; scr_bmi->bmiHeader.biSizeImage = 0; - // register MarketNoteTooltip window class + // register SCREENSHOT_DISPLAY window class wincl1.hInstance = fceu_hInstance; wincl1.lpszClassName = szClassName; wincl1.lpfnWndProc = ScrBmpWndProc; @@ -60,10 +62,10 @@ POPUP_DISPLAY::POPUP_DISPLAY() if(!RegisterClassEx(&wincl1)) FCEU_printf("Error registering SCREENSHOT_DISPLAY window class\n"); - // register ScrBmp window class + // register MARKER_NOTE_DESCRIPTION window class wincl2.hInstance = fceu_hInstance; wincl2.lpszClassName = szClassName2; - wincl2.lpfnWndProc = MarkerNoteTooltipWndProc; + wincl2.lpfnWndProc = MarkerNoteDescrWndProc; wincl2.style = CS_DBLCLKS; wincl2.cbSize = sizeof(WNDCLASSEX); wincl2.hIcon = 0; @@ -74,7 +76,7 @@ POPUP_DISPLAY::POPUP_DISPLAY() wincl2.cbWndExtra = 0; wincl2.hbrBackground = 0; if(!RegisterClassEx(&wincl2)) - FCEU_printf("Error registering MARKER_NOTE_TOOLTIP window class\n"); + FCEU_printf("Error registering MARKER_NOTE_DESCRIPTION window class\n"); // create blendfunction blend.BlendOp = AC_SRC_OVER; @@ -272,7 +274,7 @@ LRESULT APIENTRY ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lP return DefWindowProc(hwnd, message, wParam, lParam); } } -LRESULT APIENTRY MarkerNoteTooltipWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +LRESULT APIENTRY MarkerNoteDescrWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { extern POPUP_DISPLAY popup_display; switch(message) diff --git a/src/drivers/win/taseditor/splicer.cpp b/src/drivers/win/taseditor/splicer.cpp index 54132419..4ad530d4 100644 --- a/src/drivers/win/taseditor/splicer.cpp +++ b/src/drivers/win/taseditor/splicer.cpp @@ -144,7 +144,7 @@ void SPLICER::CloneFrames() greenzone.InvalidateAndCheck(first_changes); } else if (markers_changed) { - history.RegisterMarkersChange(MODTYPE_MARKER_MOVE, *current_selection->begin()); + history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, *current_selection->begin()); piano_roll.RedrawList(); } if (markers_changed) @@ -191,7 +191,7 @@ void SPLICER::InsertFrames() greenzone.InvalidateAndCheck(first_changes); } else if (markers_changed) { - history.RegisterMarkersChange(MODTYPE_MARKER_MOVE, *current_selection->begin()); + history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, *current_selection->begin()); piano_roll.RedrawList(); } if (markers_changed) @@ -239,7 +239,7 @@ void SPLICER::InsertNumFrames() greenzone.InvalidateAndCheck(first_changes); } else if (markers_changed) { - history.RegisterMarkersChange(MODTYPE_MARKER_MOVE, index); + history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, index); piano_roll.RedrawList(); } if (markers_changed) @@ -287,7 +287,7 @@ void SPLICER::DeleteFrames() else piano_roll.RedrawList(); if (markers_changed) - history.RegisterMarkersChange(MODTYPE_MARKER_MOVE, start_index); + history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, start_index); } } @@ -652,7 +652,7 @@ bool SPLICER::PasteInsert() greenzone.InvalidateAndCheck(first_changes); } else if (markers_changed) { - history.RegisterMarkersChange(MODTYPE_MARKER_MOVE, *current_selection->begin()); + history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, *current_selection->begin()); piano_roll.RedrawList(); } if (markers_changed) diff --git a/src/drivers/win/taseditor/taseditor_config.cpp b/src/drivers/win/taseditor/taseditor_config.cpp index e36006ac..acadb0c9 100644 --- a/src/drivers/win/taseditor/taseditor_config.cpp +++ b/src/drivers/win/taseditor/taseditor_config.cpp @@ -71,6 +71,8 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG() findnote_search_up = false; enable_auto_function = true; deselect_on_doubleclick = false; + doubleclick_affects_playback = true; + draw_input = true; silent_autosave = true; tooltips = true; current_pattern = 0; diff --git a/src/drivers/win/taseditor/taseditor_config.h b/src/drivers/win/taseditor/taseditor_config.h index eb96a7cd..3fe8b795 100644 --- a/src/drivers/win/taseditor/taseditor_config.h +++ b/src/drivers/win/taseditor/taseditor_config.h @@ -69,6 +69,8 @@ public: bool findnote_search_up; bool enable_auto_function; bool deselect_on_doubleclick; + bool doubleclick_affects_playback; + bool draw_input; bool silent_autosave; bool tooltips; int current_pattern; diff --git a/src/drivers/win/taseditor/taseditor_project.cpp b/src/drivers/win/taseditor/taseditor_project.cpp index 6d15e985..07d7bd89 100644 --- a/src/drivers/win/taseditor/taseditor_project.cpp +++ b/src/drivers/win/taseditor/taseditor_project.cpp @@ -60,7 +60,7 @@ void TASEDITOR_PROJECT::reset() void TASEDITOR_PROJECT::update() { // if it's time to autosave - pop Save As dialog - if (changed && taseditor_config.autosave_period && clock() >= next_save_shedule) + if (changed && taseditor_config.autosave_period && clock() >= next_save_shedule && piano_roll.drag_mode == DRAG_MODE_NONE) { if (taseditor_config.silent_autosave) SaveProject(); @@ -123,6 +123,8 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool ofs = FCEUD_UTF8_fstream(GetProjectFile().c_str(), "wb"); if (ofs) { + // change cursor to hourglass + SetCursor(LoadCursor(0, IDC_WAIT)); currMovieData.loadFrameCount = currMovieData.records.size(); currMovieData.emuVersion = FCEU_VERSION_NUMERIC; currMovieData.dump(ofs, save_binary); @@ -146,6 +148,8 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool // also reset autosave period if we saved the project to its current filename if (!different_name) this->reset(); + // restore cursor + piano_roll.must_check_item_under_mouse = true; return true; } else { @@ -162,6 +166,8 @@ bool TASEDITOR_PROJECT::load(char* fullname) return false; } + // change cursor to hourglass + SetCursor(LoadCursor(0, IDC_WAIT)); MovieData tempMovieData = MovieData(); extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); if (LoadFM2(tempMovieData, &ifs, ifs.size(), false)) @@ -227,6 +233,8 @@ bool TASEDITOR_PROJECT::load(char* fullname) popup_display.reset(); reset(); RenameProject(fullname); + // restore cursor + piano_roll.must_check_item_under_mouse = true; return true; } diff --git a/src/drivers/win/taseditor/taseditor_window.cpp b/src/drivers/win/taseditor/taseditor_window.cpp index 9801ad17..c0a48fa1 100644 --- a/src/drivers/win/taseditor/taseditor_window.cpp +++ b/src/drivers/win/taseditor/taseditor_window.cpp @@ -12,6 +12,7 @@ Window - User Interface * implements all operations with TAS Editor window: creating, redrawing, resizing, moving, tooltips, clicks * processes OS messages and sends signals from user to TAS Editor modules (also implements some minor commands on-site, like Greenzone capacity dialog and such) +* regularly checks if Shift or Ctrl key is held and sets keyboard focus to Piano Roll * switches off/on emulator's keyboard input when the window loses/gains focus * on demand: updates the window caption * updates all checkboxes and menu items when some settings change @@ -449,6 +450,8 @@ void TASEDITOR_WINDOW::UpdateCheckedItems() CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, taseditor_config.superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_COLUMNSETPATTERNSKIPSLAG, taseditor_config.pattern_skips_lag?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_DESELECTONDOUBLECLICK, taseditor_config.deselect_on_doubleclick?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_DOUBLECLICKONFRAME, taseditor_config.doubleclick_affects_playback?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_DRAWINPUTBYDRAGGING, taseditor_config.draw_input?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_HELP_TOOLTIPS, taseditor_config.tooltips?MF_CHECKED : MF_UNCHECKED); @@ -694,6 +697,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara case LVN_ODSTATECHANGED: selection.ItemRangeChanged((LPNMLVODSTATECHANGE) lParam); break; + case LVN_ENDSCROLL: + piano_roll.must_check_item_under_mouse = true; + break; } break; case IDC_BOOKMARKSLIST: @@ -1064,6 +1070,14 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara taseditor_config.deselect_on_doubleclick ^= 1; taseditor_window.UpdateCheckedItems(); break; + case ID_CONFIG_DOUBLECLICKONFRAME: + taseditor_config.doubleclick_affects_playback ^= 1; + taseditor_window.UpdateCheckedItems(); + break; + case ID_CONFIG_DRAWINPUTBYDRAGGING: + taseditor_config.draw_input ^= 1; + taseditor_window.UpdateCheckedItems(); + break; case ID_CONFIG_SILENTAUTOSAVE: taseditor_config.silent_autosave ^= 1; taseditor_window.UpdateCheckedItems(); @@ -1304,6 +1318,26 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara } case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + { + // if user clicked on a narrow space to the left of Piano Roll + // consider this as a "misclick" on Piano Roll's first column + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + RECT wrect; + GetWindowRect(piano_roll.hwndList, &wrect); + if (x > 0 + && x <= window_items[PIANOROLL_IN_WINDOWITEMS].x + && y > window_items[PIANOROLL_IN_WINDOWITEMS].y + && y < window_items[PIANOROLL_IN_WINDOWITEMS].y + (wrect.bottom - wrect.top)) + { + piano_roll.DragPlaybackCursor(); + if (piano_roll.drag_mode == DRAG_MODE_NONE) + piano_roll.drag_mode = DRAG_MODE_PLAYBACK; + } + if (GetFocus() != hWnd) + SetFocus(hWnd); + break; + } case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: { diff --git a/src/drivers/win/taseditor/taseditor_window.h b/src/drivers/win/taseditor/taseditor_window.h index 1c650221..eb94887b 100644 --- a/src/drivers/win/taseditor/taseditor_window.h +++ b/src/drivers/win/taseditor/taseditor_window.h @@ -1,6 +1,9 @@ // Specification file for TASEDITOR_WINDOW class #define TASEDITOR_WINDOW_TOTAL_ITEMS 43 +#define PIANOROLL_IN_WINDOWITEMS 2 +#define HISTORYLIST_IN_WINDOWITEMS 18 + #define TOOLTIP_TEXT_MAX_LEN 80 #define TOOLTIPS_AUTOPOP_TIMEOUT 30000