void ScintillaAccelerator::updateMenuItemByID(ScintillaKeyMap skm, int id) { const int commandSize = 64; TCHAR cmdName[commandSize]; ::GetMenuString(_hAccelMenu, id, cmdName, commandSize, MF_BYCOMMAND); int i = 0; while(cmdName[i] != 0) { if (cmdName[i] == '\t') { cmdName[i] = 0; break; } ++i; } generic_string menuItem = cmdName; if (skm.isEnabled()) { menuItem += TEXT("\t"); //menuItem += TEXT("Sc:"); //sc: scintilla shortcut menuItem += skm.toString(); } ::ModifyMenu(_hAccelMenu, id, MF_BYCOMMAND, id, menuItem.c_str()); ::DrawMenuBar(_hMenuParent); }
BOOL CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG : { initBabyGrid(); initTabs(); fillOutBabyGrid(); _babygrid.display(); goToCenter(); return TRUE; } case WM_NOTIFY: { NMHDR nmh = *((NMHDR*)lParam); if (nmh.hwndFrom == _hTabCtrl) { if (nmh.code == TCN_SELCHANGE) { int index = TabCtrl_GetCurSel(_hTabCtrl); switch (index) { case 0: _currentState = STATE_MENU; break; case 1: _currentState = STATE_MACRO; break; case 2: _currentState = STATE_USER; break; case 3: _currentState = STATE_PLUGIN; break; case 4: _currentState = STATE_SCINTILLA; break; } fillOutBabyGrid(); } } break; } case WM_COMMAND : { switch (LOWORD(wParam)) { case IDCANCEL : { ::EndDialog(_hSelf, -1); return TRUE; } case IDOK : { ::EndDialog(_hSelf, 0); return TRUE; } case IDM_BABYGRID_MODIFY : { NppParameters *nppParam = NppParameters::getInstance(); int row = _babygrid.getSelectedRow(); switch(_currentState) { case STATE_MENU: { //Get CommandShortcut corresponding to row vector<CommandShortcut> & shortcuts = nppParam->getUserShortcuts(); CommandShortcut csc = shortcuts[row - 1], prevcsc = shortcuts[row - 1]; csc.init(_hInst, _hSelf); if (csc.doDialog() != -1 && prevcsc != csc) { //shortcut was altered nppParam->addUserModifiedIndex(row-1); shortcuts[row - 1] = csc; _babygrid.setText(row, 2, csc.toString().c_str()); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); } break; } case STATE_MACRO: { //Get MacroShortcut corresponding to row vector<MacroShortcut> & shortcuts = nppParam->getMacroList(); MacroShortcut msc = shortcuts[row - 1], prevmsc = shortcuts[row - 1]; msc.init(_hInst, _hSelf); if (msc.doDialog() != -1 && prevmsc != msc) { //shortcut was altered shortcuts[row - 1] = msc; _babygrid.setText(row, 1, msc.getName()); _babygrid.setText(row, 2, msc.toString().c_str()); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); } break; } case STATE_USER: { //Get UserCommand corresponding to row vector<UserCommand> & shortcuts = nppParam->getUserCommandList(); UserCommand ucmd = shortcuts[row - 1], prevucmd = shortcuts[row - 1]; ucmd.init(_hInst, _hSelf); prevucmd = ucmd; if (ucmd.doDialog() != -1 && prevucmd != ucmd) { //shortcut was altered shortcuts[row - 1] = ucmd; _babygrid.setText(row, 1, ucmd.getName()); _babygrid.setText(row, 2, ucmd.toString().c_str()); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); } break; } case STATE_PLUGIN: { //Get PluginCmdShortcut corresponding to row vector<PluginCmdShortcut> & shortcuts = nppParam->getPluginCommandList(); PluginCmdShortcut pcsc = shortcuts[row - 1], prevpcsc = shortcuts[row - 1]; pcsc.init(_hInst, _hSelf); prevpcsc = pcsc; if (pcsc.doDialog() != -1 && prevpcsc != pcsc) { //shortcut was altered nppParam->addPluginModifiedIndex(row-1); shortcuts[row - 1] = pcsc; _babygrid.setText(row, 2, pcsc.toString().c_str()); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); unsigned long cmdID = pcsc.getID(); ShortcutKey shortcut; shortcut._isAlt = pcsc.getKeyCombo()._isAlt; shortcut._isCtrl = pcsc.getKeyCombo()._isCtrl; shortcut._isShift = pcsc.getKeyCombo()._isShift; shortcut._key = pcsc.getKeyCombo()._key; ::SendMessage(_hParent, NPPM_INTERNAL_PLUGINSHORTCUTMOTIFIED, cmdID, (LPARAM)&shortcut); } break; } case STATE_SCINTILLA: { //Get ScintillaKeyMap corresponding to row vector<ScintillaKeyMap> & shortcuts = nppParam->getScintillaKeyList(); ScintillaKeyMap skm = shortcuts[row - 1], prevskm = shortcuts[row-1]; skm.init(_hInst, _hSelf); if (skm.doDialog() != -1 && prevskm != skm) { //shortcut was altered nppParam->addScintillaModifiedIndex(row-1); shortcuts[row-1] = skm; _babygrid.setText(row, 2, skm.toString().c_str()); //Notify current Accelerator class to update key nppParam->getScintillaAccelerator()->updateKeys(); } break; } } return TRUE; } case IDM_BABYGRID_DELETE : { NppParameters *nppParam = NppParameters::getInstance(); if (::MessageBox(_hSelf, TEXT("Are you sure you want to delete this shortcut?"), TEXT("Are you sure?"), MB_OKCANCEL) == IDOK) { const int row = _babygrid.getSelectedRow(); int shortcutIndex = row-1; DWORD cmdID = 0; // Menu data size_t posBase = 0; size_t nbElem = 0; HMENU hMenu = NULL; int modifCmd = IDM_SETTING_SHORTCUT_MAPPER_RUN; switch(_currentState) { case STATE_MENU: case STATE_PLUGIN: case STATE_SCINTILLA: { return FALSE; //this is bad } case STATE_MACRO: { vector<MacroShortcut> & theMacros = nppParam->getMacroList(); vector<MacroShortcut>::iterator it = theMacros.begin(); cmdID = theMacros[shortcutIndex].getID(); theMacros.erase(it + shortcutIndex); fillOutBabyGrid(); // preparing to remove from menu posBase = 6; nbElem = theMacros.size(); hMenu = ::GetSubMenu((HMENU)::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0), MENUINDEX_MACRO); modifCmd = IDM_SETTING_SHORTCUT_MAPPER_MACRO; for (size_t i = shortcutIndex ; i < nbElem ; i++) //lower the IDs of the remaining items so there are no gaps { MacroShortcut ms = theMacros[i]; ms.setID(ms.getID() - 1); //shift all IDs theMacros[i] = ms; } break; } case STATE_USER: { vector<UserCommand> & theUserCmds = nppParam->getUserCommandList(); vector<UserCommand>::iterator it = theUserCmds.begin(); cmdID = theUserCmds[shortcutIndex].getID(); theUserCmds.erase(it + shortcutIndex); fillOutBabyGrid(); // preparing to remove from menu posBase = 2; nbElem = theUserCmds.size(); hMenu = ::GetSubMenu((HMENU)::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0), MENUINDEX_RUN); modifCmd = IDM_SETTING_SHORTCUT_MAPPER_RUN; for (size_t i = shortcutIndex ; i < nbElem ; i++) //lower the IDs of the remaining items so there are no gaps { UserCommand uc = theUserCmds[i]; uc.setID(uc.getID() - 1); //shift all IDs theUserCmds[i] = uc; } break; } } // updateShortcuts() will update all menu item - the menu items will be shifted nppParam->getAccelerator()->updateShortcuts(); // All menu items are shifted up. So we delete the last item ::RemoveMenu(hMenu, posBase + nbElem - 1, MF_BYPOSITION); if (nbElem == 0) { ::RemoveMenu(hMenu, modifCmd, MF_BYCOMMAND); //remove separator ::RemoveMenu(hMenu, posBase-1, MF_BYPOSITION); ::RemoveMenu(hMenu, posBase-1, MF_BYPOSITION); } } return TRUE; } case IDD_BABYGRID_ID1: { if(HIWORD(wParam) == BGN_CELLDBCLICKED) //a cell was clicked in the properties grid { return ::SendMessage(_hSelf, WM_COMMAND, IDM_BABYGRID_MODIFY, LOWORD(lParam)); } else if(HIWORD(wParam) == BGN_CELLRCLICKED) //a cell was clicked in the properties grid { POINT p; ::GetCursorPos(&p); if (!_rightClickMenu.isCreated()) { vector<MenuItemUnit> itemUnitArray; itemUnitArray.push_back(MenuItemUnit(IDM_BABYGRID_MODIFY, TEXT("Modify"))); itemUnitArray.push_back(MenuItemUnit(IDM_BABYGRID_DELETE, TEXT("Delete"))); _rightClickMenu.create(_hSelf, itemUnitArray); } switch(_currentState) { case STATE_MACRO: case STATE_USER: { _rightClickMenu.enableItem(IDM_BABYGRID_DELETE, true); break; } case STATE_MENU: case STATE_PLUGIN: case STATE_SCINTILLA: { _rightClickMenu.enableItem(IDM_BABYGRID_DELETE, false); break; } } _rightClickMenu.display(p); return TRUE; } } } } default: return FALSE; } return FALSE; }
BOOL CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG : { initTabs(); initList(); populateShortCuts(); goToCenter(); GetWindowRect(_hSelf,&default_sm_size); AnchorInit(_hSelf,ShortcutAnchors,sizeof(ShortcutAnchors)/sizeof(CONTROL_ANCHOR)); RestoreWinRelPosition(_hParent,_hSelf,&WinRelPos); return TRUE; } case WM_DESTROY: SaveWinRelPosition(_hParent,_hSelf,&WinRelPos); break; case WM_SIZE: AnchorResize(_hSelf,ShortcutAnchors,sizeof(ShortcutAnchors)/sizeof(CONTROL_ANCHOR)); break; case WM_SIZING: return ClampMinWindowSize(&default_sm_size,wParam,(RECT*)lParam); break; case WM_NOTIFY: { NMHDR nmh = *((NMHDR*)lParam); if (nmh.hwndFrom == _hTabCtrl) { if (nmh.code == TCN_SELCHANGE) { int index = TabCtrl_GetCurSel(_hTabCtrl); switch (index) { case 0: _currentState = STATE_MENU; break; case 1: _currentState = STATE_MACRO; break; case 2: _currentState = STATE_USER; break; case 3: _currentState = STATE_PLUGIN; break; case 4: _currentState = STATE_SCINTILLA; break; } populateShortCuts(); } } else if(nmh.hwndFrom==hlistview){ switch(nmh.code){ case NM_DBLCLK: return ::SendMessage(_hSelf, WM_COMMAND, IDC_SHORTCUT_MODIFY, LOWORD(lParam)); case NM_RCLICK: { POINT p; ::GetCursorPos(&p); if (!_rightClickMenu.isCreated()) { vector<MenuItemUnit> itemUnitArray; itemUnitArray.push_back(MenuItemUnit(IDC_SHORTCUT_MODIFY, TEXT("Modify"))); itemUnitArray.push_back(MenuItemUnit(IDC_SHORTCUT_DISABLE, TEXT("Disable"))); itemUnitArray.push_back(MenuItemUnit(0, 0)); itemUnitArray.push_back(MenuItemUnit(IDC_SHORTCUT_DELETE, TEXT("Delete"))); _rightClickMenu.create(_hSelf, itemUnitArray); } switch(_currentState) { case STATE_MACRO: case STATE_USER: { _rightClickMenu.enableItem(IDC_SHORTCUT_DELETE, true); break; } case STATE_MENU: case STATE_PLUGIN: case STATE_SCINTILLA: { _rightClickMenu.enableItem(IDC_SHORTCUT_DELETE, false); break; } } _rightClickMenu.display(p); return TRUE; } } } break; } case WM_COMMAND : { switch (LOWORD(wParam)) { case IDCANCEL : { ::EndDialog(_hSelf, -1); return TRUE; } case IDOK : { if(GetFocus()==hlistview) return ::SendMessage(_hSelf, WM_COMMAND, IDC_SHORTCUT_MODIFY, LOWORD(lParam)); else ::EndDialog(_hSelf, 0); return TRUE; } case IDC_SHORTCUT_FILTER2: case IDC_SHORTCUT_FILTER1: if(HIWORD(wParam)==EN_CHANGE) populateShortCuts(); break; case IDC_SHORTCUT_DISABLE: { int sel=0; sel=disable_selected(FALSE); if(sel!=0){ if(IDOK==MessageBox(_hSelf,TEXT("Ok to disable selected shortcuts?"),TEXT("Warning!"),MB_OKCANCEL|MB_SYSTEMMODAL)){ disable_selected(TRUE); populateShortCuts(); } } } break; case IDC_SHORTCUT_MODIFY : { NppParameters *nppParam = NppParameters::getInstance(); int index; int selected_row=getselectedrow(); if(selected_row<0) break; index=getitemindex(selected_row); switch(_currentState) { case STATE_MENU: { //Get CommandShortcut corresponding to index vector<CommandShortcut> & shortcuts = nppParam->getUserShortcuts(); CommandShortcut csc = shortcuts[index], prevcsc = shortcuts[index]; csc.init(_hInst, _hSelf); csc.set_shortcut_info(_currentState,index); if (csc.doDialog() != -1 && prevcsc != csc) { //shortcut was altered generic_string keys=csc.toString(); nppParam->addUserModifiedIndex(index); shortcuts[index] = csc; ListView_SetItemText(hlistview,selected_row,2,(LPWSTR)keys.c_str()); update_col_width(keys.c_str(),2); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); TCHAR str[255]; if(0<check_in_use(_currentState,index,&csc.getKeyCombo(),nppParam,str,sizeof(str)/sizeof(TCHAR))) MessageBox(_hSelf,str,L"Duplicates found",MB_OK); } break; } case STATE_MACRO: { //Get MacroShortcut corresponding to index vector<MacroShortcut> & shortcuts = nppParam->getMacroList(); MacroShortcut msc = shortcuts[index], prevmsc = shortcuts[index]; msc.init(_hInst, _hSelf); msc.set_shortcut_info(_currentState,index); if (msc.doDialog() != -1 && prevmsc != msc) { //shortcut was altered generic_string name=msc.getName(); generic_string keys=msc.toString(); shortcuts[index] = msc; ListView_SetItemText(hlistview,selected_row,1,(LPWSTR)name.c_str()); ListView_SetItemText(hlistview,selected_row,2,(LPWSTR)keys.c_str()); update_col_width(keys.c_str(),2); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); TCHAR str[255]; if(0<check_in_use(_currentState,index,&msc.getKeyCombo(),nppParam,str,sizeof(str)/sizeof(TCHAR))) MessageBox(_hSelf,str,L"Duplicates found",MB_OK); } break; } case STATE_USER: { //Get UserCommand corresponding to index vector<UserCommand> & shortcuts = nppParam->getUserCommandList(); UserCommand ucmd = shortcuts[index], prevucmd = shortcuts[index]; ucmd.init(_hInst, _hSelf); ucmd.set_shortcut_info(_currentState,index); prevucmd = ucmd; if (ucmd.doDialog() != -1 && prevucmd != ucmd) { //shortcut was altered generic_string name=ucmd.getName(); generic_string keys=ucmd.toString(); shortcuts[index] = ucmd; ListView_SetItemText(hlistview,selected_row,1,(LPWSTR)name.c_str()); ListView_SetItemText(hlistview,selected_row,2,(LPWSTR)keys.c_str()); update_col_width(name.c_str(),1); update_col_width(keys.c_str(),2); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); TCHAR str[255]; if(0<check_in_use(_currentState,index,&ucmd.getKeyCombo(),nppParam,str,sizeof(str)/sizeof(TCHAR))) MessageBox(_hSelf,str,L"Duplicates found",MB_OK); } break; } case STATE_PLUGIN: { //Get PluginCmdShortcut corresponding to index vector<PluginCmdShortcut> & shortcuts = nppParam->getPluginCommandList(); if(shortcuts.empty()) break; PluginCmdShortcut pcsc = shortcuts[index], prevpcsc = shortcuts[index]; pcsc.init(_hInst, _hSelf); pcsc.set_shortcut_info(_currentState,index); prevpcsc = pcsc; if (pcsc.doDialog() != -1 && prevpcsc != pcsc) { //shortcut was altered nppParam->addPluginModifiedIndex(index); generic_string keys=pcsc.toString(); shortcuts[index] = pcsc; ListView_SetItemText(hlistview,selected_row,2,(LPWSTR)keys.c_str()); update_col_width(keys.c_str(),2); //Notify current Accelerator class to update everything nppParam->getAccelerator()->updateShortcuts(); TCHAR str[255]; if(0<check_in_use(_currentState,index,&pcsc.getKeyCombo(),nppParam,str,sizeof(str)/sizeof(TCHAR))) MessageBox(_hSelf,str,L"Duplicates found",MB_OK); unsigned long cmdID = pcsc.getID(); ShortcutKey shortcut; shortcut._isAlt = pcsc.getKeyCombo()._isAlt; shortcut._isCtrl = pcsc.getKeyCombo()._isCtrl; shortcut._isShift = pcsc.getKeyCombo()._isShift; shortcut._key = pcsc.getKeyCombo()._key; ::SendMessage(_hParent, NPPM_INTERNAL_PLUGINSHORTCUTMOTIFIED, cmdID, (LPARAM)&shortcut); } break; } case STATE_SCINTILLA: { //Get ScintillaKeyMap corresponding to index vector<ScintillaKeyMap> & shortcuts = nppParam->getScintillaKeyList(); ScintillaKeyMap skm = shortcuts[index], prevskm = shortcuts[index]; skm.init(_hInst, _hSelf); skm.set_shortcut_info(_currentState,index); if (skm.doDialog() != -1 && prevskm != skm) { //shortcut was altered nppParam->addScintillaModifiedIndex(index); shortcuts[index] = skm; int i,max; TCHAR str[40]={0}; max=skm.getSize(); for(i=0;i<max;i++){ generic_string keys=skm.toString(i); _sntprintf_s(str,sizeof(str)/sizeof(TCHAR),_TRUNCATE,L"%s%s%c",str,keys.c_str(),i<(max-1)?L';':L''); } ListView_SetItemText(hlistview,selected_row,2,(LPWSTR)str); update_col_width(str,2); if(max>0){ TCHAR str[255]; KeyCombo skmkc=skm.getKeyComboByIndex(0); if(0<check_in_use(_currentState,index,&skmkc,nppParam,str,sizeof(str)/sizeof(TCHAR))) MessageBox(_hSelf,str,L"Duplicates found",MB_OK); } //Notify current Accelerator class to update key nppParam->getScintillaAccelerator()->updateKeys(); } break; } } return TRUE; } case IDC_SHORTCUT_DELETE : { NppParameters *nppParam = NppParameters::getInstance(); int index,selected_row=getselectedrow(); TCHAR str[255]={0},msg[255]={0}; if(selected_row<0) break; index=getitemindex(selected_row); ListView_GetItemText(hlistview,selected_row,1,str,sizeof(str)/sizeof(TCHAR)); _sntprintf_s(msg,sizeof(msg)/sizeof(TCHAR),_TRUNCATE, TEXT("%s\r\n%s"), TEXT("Are you sure you want to delete this shortcut?"), str); if (::MessageBox(_hSelf, msg, TEXT("Are you sure?"), MB_OKCANCEL) == IDOK) { int shortcutIndex = index; DWORD cmdID = 0; // Menu data size_t posBase = 0; size_t nbElem = 0; HMENU hMenu = NULL; int modifCmd = IDM_SETTING_SHORTCUT_MAPPER_RUN; switch(_currentState) { case STATE_MENU: case STATE_PLUGIN: case STATE_SCINTILLA: { return FALSE; //this is bad } case STATE_MACRO: { vector<MacroShortcut> & theMacros = nppParam->getMacroList(); vector<MacroShortcut>::iterator it = theMacros.begin(); cmdID = theMacros[shortcutIndex].getID(); theMacros.erase(it + shortcutIndex); populateShortCuts(); // preparing to remove from menu posBase = 6; nbElem = theMacros.size(); hMenu = ::GetSubMenu((HMENU)::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0), MENUINDEX_MACRO); modifCmd = IDM_SETTING_SHORTCUT_MAPPER_MACRO; for (size_t i = shortcutIndex ; i < nbElem ; i++) //lower the IDs of the remaining items so there are no gaps { MacroShortcut ms = theMacros[i]; ms.setID(ms.getID() - 1); //shift all IDs theMacros[i] = ms; } break; } case STATE_USER: { vector<UserCommand> & theUserCmds = nppParam->getUserCommandList(); vector<UserCommand>::iterator it = theUserCmds.begin(); cmdID = theUserCmds[shortcutIndex].getID(); theUserCmds.erase(it + shortcutIndex); populateShortCuts(); // preparing to remove from menu posBase = 2; nbElem = theUserCmds.size(); hMenu = ::GetSubMenu((HMENU)::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0), MENUINDEX_RUN); modifCmd = IDM_SETTING_SHORTCUT_MAPPER_RUN; for (size_t i = shortcutIndex ; i < nbElem ; i++) //lower the IDs of the remaining items so there are no gaps { UserCommand uc = theUserCmds[i]; uc.setID(uc.getID() - 1); //shift all IDs theUserCmds[i] = uc; } break; } } // updateShortcuts() will update all menu item - the menu items will be shifted nppParam->getAccelerator()->updateShortcuts(); // All menu items are shifted up. So we delete the last item ::RemoveMenu(hMenu, posBase + nbElem, MF_BYPOSITION); if (nbElem == 0) { ::RemoveMenu(hMenu, modifCmd, MF_BYCOMMAND); //remove separator ::RemoveMenu(hMenu, posBase-1, MF_BYPOSITION); ::RemoveMenu(hMenu, posBase-1, MF_BYPOSITION); } } return TRUE; } } } default: return FALSE; } return FALSE; }