From 6ecf80c8fc8b3815e192a8565d95b162e3efd6de Mon Sep 17 00:00:00 2001 From: Johannes Schultz Date: Thu, 19 Sep 2024 13:30:32 +0000 Subject: [PATCH] [Mod] Implement custom context menu key handling through regular keyboard handling instead of special-casing it everywhere. [Mod] In addition to the Application key, custom context menu key handling now adds Shift+F10 as a default shortcut, which is what Windows uses by default as a substitute for keyboards without an Application key (https://bugs.openmpt.org/view.php?id=1815). [Mod] Invert logic when to skip new default keyboard shortcuts: If the conflicting existing shortcut is in a more specific context, the new shortcut is added because it will be ignored anyway. [Mod] OpenMPT: Version is now 1.32.00.25 git-svn-id: https://source.openmpt.org/svn/openmpt/trunk/OpenMPT@21624 56274372-70c3-4bfc-bfc3-4c3a0b034d27 --- common/versionNumber.h | 2 +- mptrack/CommandSet.cpp | 7 +++-- mptrack/CommandSet.h | 3 +- mptrack/Ctrl_ins.cpp | 69 +++++++++++++++++++----------------------- mptrack/Ctrl_seq.cpp | 33 ++++++++++---------- mptrack/Ctrl_smp.cpp | 7 ++--- mptrack/MainFrm.cpp | 12 +------- mptrack/Mainbar.cpp | 16 ---------- mptrack/Mainbar.h | 2 -- mptrack/Mainfrm.h | 2 -- mptrack/View_ins.cpp | 23 +++++++------- mptrack/View_pat.cpp | 8 ++--- mptrack/View_smp.cpp | 9 ++---- mptrack/View_tre.cpp | 41 ++++++++++++++----------- 14 files changed, 97 insertions(+), 137 deletions(-) diff --git a/common/versionNumber.h b/common/versionNumber.h index cfa6a6bbda..394ceaa1b6 100644 --- a/common/versionNumber.h +++ b/common/versionNumber.h @@ -16,4 +16,4 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 32 #define VER_MINOR 00 -#define VER_MINORMINOR 24 +#define VER_MINORMINOR 25 diff --git a/mptrack/CommandSet.cpp b/mptrack/CommandSet.cpp index 05c82e0571..7c16e9a9d9 100644 --- a/mptrack/CommandSet.cpp +++ b/mptrack/CommandSet.cpp @@ -89,6 +89,8 @@ constexpr struct {kcViewMIDImapping, VK_F3, ModCtrl, kKeyEventDown, kCtxAllContexts, MPT_V("1.31")}, {kcSwitchToInstrLibrary, 'I', ModAlt, kKeyEventDown | kKeyEventRepeat, kCtxAllContexts, MPT_V("1.31")}, {kcHelp, VK_F1, ModNone, kKeyEventDown, kCtxAllContexts, MPT_V("1.31")}, + {kcContextMenu, VK_APPS, ModNone, kKeyEventDown, kCtxAllContexts, MPT_V("1.32.00.25")}, + {kcContextMenu, VK_F10, ModShift, kKeyEventDown, kCtxAllContexts, MPT_V("1.32.00.25")}, {kcPrevInstrument, VK_DIVIDE, ModCtrl, kKeyEventDown | kKeyEventRepeat, kCtxAllContexts, MPT_V("1.31")}, {kcPrevInstrument, VK_UP, ModCtrl, kKeyEventDown | kKeyEventRepeat, kCtxAllContexts, MPT_V("1.31")}, {kcNextInstrument, VK_MULTIPLY, ModCtrl, kKeyEventDown | kKeyEventRepeat, kCtxAllContexts, MPT_V("1.31")}, @@ -1390,6 +1392,7 @@ static constexpr struct {2098, kcGotoVolumeColumn, _T("Go to volume effect column")}, {2099, kcGotoCommandColumn, _T("Go to effect command column")}, {2100, kcGotoParamColumn, _T("Go to effect parameter column")}, + {2101, kcContextMenu, _T("Open Context Menu")}, }; // clang-format on @@ -2387,10 +2390,10 @@ void CCommandSet::ApplyDefaultKeybindings(const Version onlyCommandsAfterVersion if(auto conflictCmd = IsConflicting(kc, kb.cmd, false); conflictCmd.first != kcNull) { - // Allow cross-context conflicts in case the newly added shortcut is in a more specific context + // Allow cross-context conflicts in case the newly added shortcut is in a more generic context // - unless the conflicting shortcut is the reserved dummy shortcut (which was used to prevent // default shortcuts from being added back before default key binding versioning was added). - if(conflictCmd.first == kcDummyShortcut || !m_isParentContext[conflictCmd.second.Context()][kb.ctx]) + if(conflictCmd.first == kcDummyShortcut || !m_isParentContext[kb.ctx][conflictCmd.second.Context()]) continue; } diff --git a/mptrack/CommandSet.h b/mptrack/CommandSet.h index 8f603ea0de..32e270dac4 100644 --- a/mptrack/CommandSet.h +++ b/mptrack/CommandSet.h @@ -161,7 +161,8 @@ enum CommandID kcEndView = kcHelp, kcStartMisc, - kcPrevInstrument = kcStartMisc, + kcContextMenu = kcStartMisc, + kcPrevInstrument, kcNextInstrument, kcPrevOctave, kcNextOctave, diff --git a/mptrack/Ctrl_ins.cpp b/mptrack/Ctrl_ins.cpp index 70183123de..b2c762104d 100644 --- a/mptrack/Ctrl_ins.cpp +++ b/mptrack/Ctrl_ins.cpp @@ -71,55 +71,42 @@ END_MESSAGE_MAP() BOOL CNoteMapWnd::PreTranslateMessage(MSG *pMsg) { - if(!pMsg) - return TRUE; - uint32 wParam = static_cast(pMsg->wParam); - + //We handle keypresses before Windows has a chance to handle them (for alt etc..) + if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || + (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) { - //We handle keypresses before Windows has a chance to handle them (for alt etc..) - if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || - (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) - { - CInputHandler *ih = CMainFrame::GetInputHandler(); - const auto event = ih->Translate(*pMsg); + CInputHandler *ih = CMainFrame::GetInputHandler(); + const auto event = ih->Translate(*pMsg); - if (ih->KeyEvent(kCtxInsNoteMap, event) != kcNull) - return true; // Mapped to a command, no need to pass message on. + if (ih->KeyEvent(kCtxInsNoteMap, event, this) != kcNull) + return TRUE; // Mapped to a command, no need to pass message on. - // a bit of a hack... - if (ih->KeyEvent(kCtxCtrlInstruments, event) != kcNull) - return true; // Mapped to a command, no need to pass message on. - } + // a bit of a hack... + if (ih->KeyEvent(kCtxCtrlInstruments, event, this) != kcNull) + return TRUE; // Mapped to a command, no need to pass message on. + + // For context menu shortcut + if(ih->KeyEvent(kCtxAllContexts, event, this) != kcNull) + return TRUE; // Mapped to a command, no need to pass message on. } //The key was not handled by a command, but it might still be useful - if (pMsg->message == WM_CHAR) //key is a character + uint32 wParam = static_cast(pMsg->wParam); + if(pMsg->message == WM_CHAR && CInputHandler::GetKeyEventType(*pMsg) == kKeyEventDown) // Key is a character { - if(CInputHandler::GetKeyEventType(*pMsg) == kKeyEventDown) - if(HandleChar(wParam)) - return true; - } - else if (pMsg->message == WM_KEYDOWN) //key is not a character + if(HandleChar(wParam)) + return TRUE; + } else if(pMsg->message == WM_KEYDOWN) // Key is not a character { if(HandleNav(wParam)) - return true; - - // Handle Application (menu) key - if(wParam == VK_APPS) - { - CRect clientRect; - GetClientRect(clientRect); - clientRect.bottom = clientRect.top + mpt::align_up(clientRect.Height(), m_cyFont); - OnRButtonDown(0, clientRect.CenterPoint()); - } - } - else if (pMsg->message == WM_KEYUP) //stop notes on key release + return TRUE; + } else if(pMsg->message == WM_KEYUP) // Stop notes on key release { - if (((pMsg->wParam >= '0') && (pMsg->wParam <= '9')) || (pMsg->wParam == ' ') || + if(((pMsg->wParam >= '0') && (pMsg->wParam <= '9')) || (pMsg->wParam == ' ') || ((pMsg->wParam >= VK_NUMPAD0) && (pMsg->wParam <= VK_NUMPAD9))) { StopNote(); - return true; + return TRUE; } } @@ -272,7 +259,6 @@ void CNoteMapWnd::OnSetFocus(CWnd *pOldWnd) { CStatic::OnSetFocus(pOldWnd); Invalidate(FALSE); - CMainFrame::GetMainFrame()->m_pNoteMapHasFocus = this; m_undo = true; } @@ -281,7 +267,6 @@ void CNoteMapWnd::OnKillFocus(CWnd *pNewWnd) { CStatic::OnKillFocus(pNewWnd); Invalidate(FALSE); - CMainFrame::GetMainFrame()->m_pNoteMapHasFocus = nullptr; } @@ -615,6 +600,14 @@ LRESULT CNoteMapWnd::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) switch(wParam) { + case kcContextMenu: + { + CRect clientRect; + GetClientRect(clientRect); + clientRect.bottom = clientRect.top + mpt::align_up(clientRect.Height(), m_cyFont); + OnRButtonDown(0, clientRect.CenterPoint()); + } + return wParam; case kcInsNoteMapTransposeDown: MapTranspose(-1); return wParam; case kcInsNoteMapTransposeUp: MapTranspose(1); return wParam; case kcInsNoteMapTransposeOctDown: MapTranspose(-12); return wParam; diff --git a/mptrack/Ctrl_seq.cpp b/mptrack/Ctrl_seq.cpp index 91fd4b72d2..9f9ca9b33e 100644 --- a/mptrack/Ctrl_seq.cpp +++ b/mptrack/Ctrl_seq.cpp @@ -446,26 +446,17 @@ BOOL COrderList::PreTranslateMessage(MSG *pMsg) CInputHandler *ih = CMainFrame::GetInputHandler(); const auto event = ih->Translate(*pMsg); - if(ih->KeyEvent(kCtxCtrlOrderlist, event) != kcNull) + if(ih->KeyEvent(kCtxCtrlOrderlist, event, this) != kcNull) return TRUE; // Mapped to a command, no need to pass message on. //HACK: masquerade as kCtxViewPatternsNote context until we implement appropriate // command propagation to kCtxCtrlOrderlist context. - if(ih->KeyEvent(kCtxViewPatternsNote, event) != kcNull) + if(ih->KeyEvent(kCtxViewPatternsNote, event, this) != kcNull) return TRUE; // Mapped to a command, no need to pass message on. - // Handle Application (menu) key - if(pMsg->message == WM_KEYDOWN && event.key == VK_APPS) - { - const auto selection = GetCurSel(); - auto pt = (GetRectFromOrder(selection.firstOrd) | GetRectFromOrder(selection.lastOrd)).CenterPoint(); - CRect clientRect; - GetClientRect(clientRect); - if(!clientRect.PtInRect(pt)) - pt = clientRect.CenterPoint(); - OnRButtonDown(0, pt); - } + if(ih->KeyEvent(kCtxAllContexts, event, this) != kcNull) + return TRUE; // Mapped to a command, no need to pass message on. } return CWnd::PreTranslateMessage(pMsg); @@ -474,9 +465,21 @@ BOOL COrderList::PreTranslateMessage(MSG *pMsg) LRESULT COrderList::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) { - bool isPlaying = IsPlaying(); + const bool isPlaying = IsPlaying(); switch(wParam) { + case kcContextMenu: + { + const auto selection = GetCurSel(); + auto pt = (GetRectFromOrder(selection.firstOrd) | GetRectFromOrder(selection.lastOrd)).CenterPoint(); + CRect clientRect; + GetClientRect(clientRect); + if(!clientRect.PtInRect(pt)) + pt = clientRect.CenterPoint(); + OnRButtonDown(0, pt); + } + return wParam; + case kcEditCopy: OnEditCopy(); return wParam; case kcEditCut: @@ -888,7 +891,6 @@ void COrderList::OnSetFocus(CWnd *pWnd) CWnd::OnSetFocus(pWnd); InvalidateSelection(); UpdateInfoText(); - CMainFrame::GetMainFrame()->m_pOrderlistHasFocus = this; } @@ -896,7 +898,6 @@ void COrderList::OnKillFocus(CWnd *pWnd) { CWnd::OnKillFocus(pWnd); InvalidateSelection(); - CMainFrame::GetMainFrame()->m_pOrderlistHasFocus = nullptr; } diff --git a/mptrack/Ctrl_smp.cpp b/mptrack/Ctrl_smp.cpp index 1c7d2f1694..d64ac8542b 100644 --- a/mptrack/Ctrl_smp.cpp +++ b/mptrack/Ctrl_smp.cpp @@ -1900,11 +1900,8 @@ class DoPitchShiftTimeStretch : public CProgressDialog : CProgressDialog{&parent} , m_updateInterval{std::max(uint32(15), TrackerSettings::Instance().GUIUpdateInterval.Get())} { - const auto updateFunc = std::bind(&DoPitchShiftTimeStretch::UpdateProgress, this, std::placeholders::_1, std::placeholders::_2); - const auto prepareUndo = [&parent]() - { - return parent.PrepareUndo("Pitch Shift / Time Stretch", sundo_replace); - }; + const auto updateFunc = [this](SmpLength current, SmpLength maximum) { return UpdateProgress(current, maximum); }; + const auto prepareUndo = [&parent]() { return parent.PrepareUndo("Pitch Shift / Time Stretch", sundo_replace); }; CSoundFile &sndFile = modDoc.GetSoundFile(); if(loFi) diff --git a/mptrack/MainFrm.cpp b/mptrack/MainFrm.cpp index af63235202..a20983082b 100644 --- a/mptrack/MainFrm.cpp +++ b/mptrack/MainFrm.cpp @@ -2520,7 +2520,6 @@ LRESULT CMainFrame::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) case kcPrevDocument: MDIPrev(); break; case kcFileCloseAll: theApp.OnFileCloseAll(); break; - //D'oh!! moddoc isn't a CWnd so we have to handle its messages and pass them on. case kcFileSaveAs: @@ -2581,17 +2580,8 @@ LRESULT CMainFrame::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) m_wndTree.SetFocus(); break; - //if handled neither by MainFrame nor by ModDoc... default: - //If the treeview has focus, post command to the tree view - if (m_bModTreeHasFocus) - return m_wndTree.SendMessageToModTree(WM_MOD_KEYCOMMAND, wParam, lParam); - if (m_pNoteMapHasFocus) - return m_pNoteMapHasFocus->SendMessage(WM_MOD_KEYCOMMAND, wParam, lParam); - if (m_pOrderlistHasFocus) - return m_pOrderlistHasFocus->SendMessage(WM_MOD_KEYCOMMAND, wParam, lParam); - - //Else send it to the active view + // If handled neither by MainFrame nor by ModDoc, send it to the active view CMDIChildWnd *pMDIActive = MDIGetActive(); CWnd *wnd = nullptr; if(pMDIActive) diff --git a/mptrack/Mainbar.cpp b/mptrack/Mainbar.cpp index 0a03351eef..af9d5d7b8f 100644 --- a/mptrack/Mainbar.cpp +++ b/mptrack/Mainbar.cpp @@ -1291,22 +1291,6 @@ void CModTreeBar::OnLButtonUp(UINT, CPoint) } -HWND CModTreeBar::GetModTreeHWND() -{ - return m_pModTree->m_hWnd; -} - - -LRESULT CModTreeBar::SendMessageToModTree(UINT cmdID, WPARAM wParam, LPARAM lParam) -{ - if(::GetFocus() == m_pModTree->m_hWnd) - return m_pModTree->SendMessage(cmdID, wParam, lParam); - if(::GetFocus() == m_pModTreeData->m_hWnd) - return m_pModTreeData->SendMessage(cmdID, wParam, lParam); - return 0; -} - - bool CModTreeBar::SetTreeSoundfile(FileReader &file) { return m_pModTree->SetSoundFile(file); diff --git a/mptrack/Mainbar.h b/mptrack/Mainbar.h index 4305d42111..d51229f279 100644 --- a/mptrack/Mainbar.h +++ b/mptrack/Mainbar.h @@ -173,8 +173,6 @@ class CModTreeBar: public CDialogBar void OnDocumentClosed(CModDoc *pModDoc); void OnUpdate(CModDoc *pModDoc, UpdateHint hint, CObject *pHint = nullptr); void UpdatePlayPos(CModDoc *pModDoc, Notification *pNotify); - HWND GetModTreeHWND(); //rewbs.customKeys - LRESULT SendMessageToModTree(UINT cmdID, WPARAM wParam, LPARAM lParam); bool SetTreeSoundfile(FileReader &file); void StartTreeFilter(CModTree &source); diff --git a/mptrack/Mainfrm.h b/mptrack/Mainfrm.h index aa69a89afd..25c73cf090 100644 --- a/mptrack/Mainfrm.h +++ b/mptrack/Mainfrm.h @@ -208,8 +208,6 @@ class CMainFrame CAutoSaver m_AutoSaver; public: - CWnd *m_pNoteMapHasFocus = nullptr; - CWnd *m_pOrderlistHasFocus = nullptr; bool m_bModTreeHasFocus = false; public: diff --git a/mptrack/View_ins.cpp b/mptrack/View_ins.cpp index 9960bca944..94d6d0efa4 100644 --- a/mptrack/View_ins.cpp +++ b/mptrack/View_ins.cpp @@ -2260,18 +2260,6 @@ BOOL CViewInstrument::PreTranslateMessage(MSG *pMsg) const auto event = ih->Translate(*pMsg); if(ih->KeyEvent(kCtxViewInstruments, event) != kcNull) return TRUE; // Mapped to a command, no need to pass message on. - - // Handle Application (menu) key - if(pMsg->message == WM_KEYDOWN && event.key == VK_APPS) - { - CPoint pt(0, 0); - if(m_nDragItem > 0) - { - uint32 point = DragItemToEnvPoint(); - pt.SetPoint(PointToScreen(point), ValueToScreen(EnvGetValue(point))); - } - OnRButtonDown(0, pt); - } } } @@ -2288,6 +2276,17 @@ LRESULT CViewInstrument::OnCustomKeyMsg(WPARAM wParam, LPARAM) switch(wParam) { + case kcContextMenu: + { + CPoint pt(0, 0); + if(m_nDragItem > 0) + { + uint32 point = DragItemToEnvPoint(); + pt.SetPoint(PointToScreen(point), ValueToScreen(EnvGetValue(point))); + } + OnRButtonDown(0, pt); + } + return wParam; case kcPrevInstrument: OnPrevInstrument(); return wParam; case kcNextInstrument: OnNextInstrument(); return wParam; case kcEditCopy: OnEditCopy(); return wParam; diff --git a/mptrack/View_pat.cpp b/mptrack/View_pat.cpp index 2737497b0b..d2d400e086 100644 --- a/mptrack/View_pat.cpp +++ b/mptrack/View_pat.cpp @@ -710,12 +710,6 @@ BOOL CViewPattern::PreTranslateMessage(MSG *pMsg) } } //end HACK. - - // Handle Application (menu) key - if(pMsg->message == WM_KEYDOWN && event.key == VK_APPS) - { - OnRButtonDown(0, GetPointFromPosition(m_Cursor)); - } } else if(pMsg->message == WM_MBUTTONDOWN) { // Open quick channel properties dialog if we're middle-clicking a channel header. @@ -4334,6 +4328,8 @@ LRESULT CViewPattern::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) switch(wParam) { + case kcContextMenu: OnRButtonDown(0, GetPointFromPosition(m_Cursor)); return wParam; + case kcPrevInstrument: OnPrevInstrument(); return wParam; case kcNextInstrument: OnNextInstrument(); return wParam; case kcPrevOrder: GotoPreviousOrder(); return wParam; diff --git a/mptrack/View_smp.cpp b/mptrack/View_smp.cpp index d2e1d06430..28cdc62155 100644 --- a/mptrack/View_smp.cpp +++ b/mptrack/View_smp.cpp @@ -3656,13 +3656,6 @@ BOOL CViewSample::PreTranslateMessage(MSG *pMsg) const auto event = ih->Translate(*pMsg); if (ih->KeyEvent(kCtxViewSamples, event) != kcNull) return true; // Mapped to a command, no need to pass message on. - - // Handle Application (menu) key - if(pMsg->message == WM_KEYDOWN && event.key == VK_APPS) - { - int x = Util::ScalePixels(32, m_hWnd); - OnRButtonDown(0, CPoint(x, x)); - } } } @@ -3679,6 +3672,8 @@ LRESULT CViewSample::OnCustomKeyMsg(WPARAM wParam, LPARAM lParam) switch(wParam) { + case kcContextMenu: OnRButtonDown(0, CPoint(0, TimelineHeight(m_hWnd))); return wParam; + case kcSampleTrim: TrimSample(false); return wParam; case kcSampleTrimToLoopEnd: TrimSample(true); return wParam; case kcSampleZoomUp: OnZoomUp(); return wParam; diff --git a/mptrack/View_tre.cpp b/mptrack/View_tre.cpp index 950898ea81..85fae4d2e6 100644 --- a/mptrack/View_tre.cpp +++ b/mptrack/View_tre.cpp @@ -276,17 +276,6 @@ BOOL CModTree::PreTranslateMessage(MSG *pMsg) { switch(pMsg->wParam) { - case VK_APPS: - // Handle Application (menu) key - if(HTREEITEM item = GetSelectedItem()) - { - CRect rect; - GetItemRect(item, &rect, FALSE); - ClientToScreen(rect); - OnItemRightClick(item, rect.TopLeft() + CPoint{rect.Height() / 2, rect.Height() / 2}); - } - return TRUE; - case VK_ESCAPE: GetParent()->PostMessage(WM_COMMAND, ID_CLOSE_LIBRARY_FILTER); break; @@ -315,7 +304,12 @@ BOOL CModTree::PreTranslateMessage(MSG *pMsg) (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) { CInputHandler *ih = CMainFrame::GetInputHandler(); - if(ih->KeyEvent(kCtxViewTree, ih->Translate(*pMsg)) != kcNull) + const auto event = ih->Translate(*pMsg); + if(ih->KeyEvent(kCtxViewTree, event, this) != kcNull) + return TRUE; // Mapped to a command, no need to pass message on. + + // For context menu shortcut + if(ih->KeyEvent(kCtxAllContexts, event, this) != kcNull) return TRUE; // Mapped to a command, no need to pass message on. } return CTreeCtrl::PreTranslateMessage(pMsg); @@ -525,31 +519,31 @@ void CModTree::RefreshMidiLibrary() HTREEITEM parent = GetChildItem(m_hMidiLib); for(UINT iMidi = 0; iMidi < 128; iMidi++) { - DWORD dwImage = IMAGE_INSTRMUTE; + int image = IMAGE_INSTRMUTE; s = mpt::cfmt::val(iMidi) + _T(": ") + mpt::ToCString(mpt::Charset::ASCII, szMidiProgramNames[iMidi]); const LPARAM param = (MODITEM_MIDIINSTRUMENT << MIDILIB_SHIFT) | iMidi; if(!midiLib[iMidi].empty()) { s += _T(": ") + midiLib[iMidi].GetFilename().ToCString(); - dwImage = IMAGE_INSTRUMENTS; + image = IMAGE_INSTRUMENTS; } if(!m_tiMidi[iMidi]) { m_tiMidi[iMidi] = InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM, - s, dwImage, dwImage, 0, 0, param, parent, TVI_LAST); + s, image, image, 0, 0, param, parent, TVI_LAST); } else { tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvi.hItem = m_tiMidi[iMidi]; tvi.pszText = stmp.GetBuffer(s.GetLength() + 1); tvi.cchTextMax = stmp.GetAllocLength(); - tvi.iImage = tvi.iSelectedImage = dwImage; + tvi.iImage = tvi.iSelectedImage = image; GetItem(&tvi); s.ReleaseBuffer(); - if(s != stmp || tvi.iImage != (int)dwImage) + if(s != stmp || tvi.iImage != image) { SetItem(m_tiMidi[iMidi], TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM, - s, dwImage, dwImage, 0, 0, param); + s, image, image, 0, 0, param); } } if((iMidi % 8u) == 7u) @@ -4191,6 +4185,17 @@ LRESULT CModTree::OnCustomKeyMsg(WPARAM wParam, LPARAM /*lParam*/) switch(wParam) { + case kcContextMenu: + if(HTREEITEM item = GetSelectedItem()) + { + CRect rect; + GetItemRect(item, &rect, FALSE); + ClientToScreen(rect); + OnItemRightClick(item, rect.TopLeft() + CPoint{ rect.Height() / 2, rect.Height() / 2 }); + return wParam; + } + break; + case kcTreeViewStopPreview: note = NOTE_NOTECUT; break;