Add "Show All Character" context menu on toolbar button
Fix #14832, close #15235
This commit is contained in:
parent
7a401cface
commit
e7e88a380a
|
@ -99,11 +99,21 @@ ToolBarButtonUnit toolBarIcons[] = {
|
|||
{IDM_VIEW_WRAP, IDI_VIEW_WRAP_ICON, IDI_VIEW_WRAP_ICON, IDI_VIEW_WRAP_ICON2, IDI_VIEW_WRAP_ICON2, IDI_VIEW_WRAP_ICON_DM, IDI_VIEW_WRAP_ICON_DM, IDI_VIEW_WRAP_ICON_DM2, IDI_VIEW_WRAP_ICON_DM2, IDR_WRAP},
|
||||
{IDM_VIEW_ALL_CHARACTERS, IDI_VIEW_ALL_CHAR_ICON, IDI_VIEW_ALL_CHAR_ICON, IDI_VIEW_ALL_CHAR_ICON2, IDI_VIEW_ALL_CHAR_ICON2, IDI_VIEW_ALL_CHAR_ICON_DM, IDI_VIEW_ALL_CHAR_ICON_DM, IDI_VIEW_ALL_CHAR_ICON_DM2, IDI_VIEW_ALL_CHAR_ICON_DM2, IDR_INVISIBLECHAR},
|
||||
{IDM_VIEW_INDENT_GUIDE, IDI_VIEW_INDENT_ICON, IDI_VIEW_INDENT_ICON, IDI_VIEW_INDENT_ICON2, IDI_VIEW_INDENT_ICON2, IDI_VIEW_INDENT_ICON_DM, IDI_VIEW_INDENT_ICON_DM, IDI_VIEW_INDENT_ICON_DM2, IDI_VIEW_INDENT_ICON_DM2, IDR_INDENTGUIDE},
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
{0, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON},
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
|
||||
{IDM_LANG_USER_DLG, IDI_VIEW_UD_DLG_ICON, IDI_VIEW_UD_DLG_ICON, IDI_VIEW_UD_DLG_ICON2, IDI_VIEW_UD_DLG_ICON2, IDI_VIEW_UD_DLG_ICON_DM, IDI_VIEW_UD_DLG_ICON_DM, IDI_VIEW_UD_DLG_ICON_DM2, IDI_VIEW_UD_DLG_ICON_DM2, IDR_SHOWPANNEL},
|
||||
{IDM_VIEW_DOC_MAP, IDI_VIEW_DOC_MAP_ICON, IDI_VIEW_DOC_MAP_ICON, IDI_VIEW_DOC_MAP_ICON2, IDI_VIEW_DOC_MAP_ICON2, IDI_VIEW_DOC_MAP_ICON_DM, IDI_VIEW_DOC_MAP_ICON_DM, IDI_VIEW_DOC_MAP_ICON_DM2, IDI_VIEW_DOC_MAP_ICON_DM2, IDR_DOCMAP},
|
||||
{IDM_VIEW_DOCLIST, IDI_VIEW_DOCLIST_ICON, IDI_VIEW_DOCLIST_ICON, IDI_VIEW_DOCLIST_ICON2, IDI_VIEW_DOCLIST_ICON2, IDI_VIEW_DOCLIST_ICON_DM, IDI_VIEW_DOCLIST_ICON_DM, IDI_VIEW_DOCLIST_ICON_DM2, IDI_VIEW_DOCLIST_ICON_DM2, IDR_DOCLIST},
|
||||
{IDM_VIEW_FUNC_LIST, IDI_VIEW_FUNCLIST_ICON, IDI_VIEW_FUNCLIST_ICON, IDI_VIEW_FUNCLIST_ICON2, IDI_VIEW_FUNCLIST_ICON2, IDI_VIEW_FUNCLIST_ICON_DM, IDI_VIEW_FUNCLIST_ICON_DM, IDI_VIEW_FUNCLIST_ICON_DM2, IDI_VIEW_FUNCLIST_ICON_DM2, IDR_FUNC_LIST},
|
||||
{IDM_VIEW_FILEBROWSER, IDI_VIEW_FILEBROWSER_ICON, IDI_VIEW_FILEBROWSER_ICON, IDI_VIEW_FILEBROWSER_ICON2, IDI_VIEW_FILEBROWSER_ICON2, IDI_VIEW_FILEBROWSER_ICON_DM, IDI_VIEW_FILEBROWSER_ICON_DM, IDI_VIEW_FILEBROWSER_ICON_DM2, IDI_VIEW_FILEBROWSER_ICON_DM2, IDR_FILEBROWSER},
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
{0, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON},
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
|
||||
{IDM_VIEW_MONITORING, IDI_VIEW_MONITORING_ICON, IDI_VIEW_MONITORING_DIS_ICON, IDI_VIEW_MONITORING_ICON2, IDI_VIEW_MONITORING_DIS_ICON2, IDI_VIEW_MONITORING_ICON_DM, IDI_VIEW_MONITORING_DIS_ICON_DM, IDI_VIEW_MONITORING_ICON_DM2, IDI_VIEW_MONITORING_DIS_ICON_DM2, IDR_FILEMONITORING},
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
|
@ -8964,4 +8974,106 @@ void Notepad_plus::changedHistoryGoTo(int idGoTo)
|
|||
if (!isSilent)
|
||||
::MessageBeep(MB_ICONEXCLAMATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HMENU Notepad_plus::createMenuFromMenu(HMENU hSourceMenu, std::vector<int>& commandIds)
|
||||
{
|
||||
HMENU hNewMenu = ::CreatePopupMenu();
|
||||
for (const auto& cmdID : commandIds)
|
||||
{
|
||||
if (cmdID == 0)
|
||||
{
|
||||
::AppendMenu(hNewMenu, MF_SEPARATOR, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
MENUITEMINFO mii{};
|
||||
mii.cbSize = sizeof(MENUITEMINFO);
|
||||
mii.fMask = MIIM_STRING | MIIM_STATE;
|
||||
mii.dwTypeData = nullptr;
|
||||
|
||||
if (::GetMenuItemInfo(hSourceMenu, cmdID, FALSE, &mii) == TRUE)
|
||||
{
|
||||
++mii.cch;
|
||||
wchar_t* szString = new wchar_t[mii.cch];
|
||||
mii.dwTypeData = szString;
|
||||
|
||||
if (::GetMenuItemInfo(hSourceMenu, cmdID, FALSE, &mii) == TRUE)
|
||||
{
|
||||
::AppendMenu(hNewMenu, MF_STRING | mii.fState, cmdID, mii.dwTypeData);
|
||||
delete[] szString;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] szString;
|
||||
::DestroyMenu(hNewMenu);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
::DestroyMenu(hNewMenu);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hNewMenu;
|
||||
}
|
||||
|
||||
BOOL Notepad_plus::notifyTBShowMenu(LPNMTOOLBARW lpnmtb, const char* menuPosId)
|
||||
{
|
||||
RECT rcItem{};
|
||||
::SendMessage(lpnmtb->hdr.hwndFrom, TB_GETRECT, static_cast<WPARAM>(lpnmtb->iItem), reinterpret_cast<LPARAM>(&rcItem));
|
||||
::MapWindowPoints(lpnmtb->hdr.hwndFrom, HWND_DESKTOP, reinterpret_cast<LPPOINT>(&rcItem), 2);
|
||||
|
||||
const MenuPosition& menuPos = getMenuPosition(menuPosId);
|
||||
HMENU hSubMenuView = ::GetSubMenu(_mainMenuHandle, menuPos._x);
|
||||
if (hSubMenuView != nullptr)
|
||||
{
|
||||
HMENU hPopupMenu = ::GetSubMenu(hSubMenuView, menuPos._y);
|
||||
if (hPopupMenu != nullptr)
|
||||
{
|
||||
TPMPARAMS tpm{};
|
||||
tpm.cbSize = sizeof(TPMPARAMS);
|
||||
tpm.rcExclude = rcItem;
|
||||
|
||||
const UINT flags = _nativeLangSpeaker.isRTL() ? (TPM_RIGHTALIGN | TPM_RIGHTBUTTON | TPM_LAYOUTRTL) : (TPM_LEFTALIGN | TPM_LEFTBUTTON);
|
||||
|
||||
::TrackPopupMenuEx(hPopupMenu,
|
||||
flags | TPM_VERTICAL,
|
||||
rcItem.left, rcItem.bottom, _pPublicInterface->getHSelf(), &tpm);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Notepad_plus::notifyTBShowMenu(LPNMTOOLBARW lpnmtb, const char* menuPosId, std::vector<int> cmdIDs)
|
||||
{
|
||||
if (cmdIDs.empty())
|
||||
return notifyTBShowMenu(lpnmtb, menuPosId);
|
||||
|
||||
RECT rcItem{};
|
||||
::SendMessage(lpnmtb->hdr.hwndFrom, TB_GETRECT, static_cast<WPARAM>(lpnmtb->iItem), reinterpret_cast<LPARAM>(&rcItem));
|
||||
::MapWindowPoints(lpnmtb->hdr.hwndFrom, HWND_DESKTOP, reinterpret_cast<LPPOINT>(&rcItem), 2);
|
||||
|
||||
HMENU hPopupMenu = createMenuFromMenu(_mainMenuHandle, cmdIDs);
|
||||
if (hPopupMenu != nullptr)
|
||||
{
|
||||
TPMPARAMS tpm{};
|
||||
tpm.cbSize = sizeof(TPMPARAMS);
|
||||
tpm.rcExclude = rcItem;
|
||||
|
||||
const UINT flags = _nativeLangSpeaker.isRTL() ? (TPM_RIGHTALIGN | TPM_RIGHTBUTTON | TPM_LAYOUTRTL) : (TPM_LEFTALIGN | TPM_LEFTBUTTON);
|
||||
|
||||
::TrackPopupMenuEx(hPopupMenu,
|
||||
flags | TPM_VERTICAL,
|
||||
rcItem.left, rcItem.bottom, _pPublicInterface->getHSelf(), &tpm);
|
||||
|
||||
::DestroyMenu(hPopupMenu);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -653,4 +653,8 @@ private:
|
|||
|
||||
void clearChangesHistory();
|
||||
void changedHistoryGoTo(int idGoTo);
|
||||
|
||||
HMENU createMenuFromMenu(HMENU hSourceMenu, std::vector<int>& commandIds);
|
||||
BOOL notifyTBShowMenu(LPNMTOOLBARW lpnmtb, const char* menuPosId);
|
||||
BOOL notifyTBShowMenu(LPNMTOOLBARW lpnmtb, const char* menuPosId, std::vector<int> cmdIDs);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// This file is part of Notepad++ project
|
||||
// This file is part of Notepad++ project
|
||||
// Copyright (C)2021 Don HO <don.h@free.fr>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
|
@ -2013,11 +2013,34 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
nmtbcd->nStringBkMode = TRANSPARENT;
|
||||
nmtbcd->nHLStringBkMode = TRANSPARENT;
|
||||
|
||||
RECT rcItem{ nmtbcd->nmcd.rc };
|
||||
RECT rcDrop{};
|
||||
|
||||
TBBUTTONINFO tbi{};
|
||||
tbi.cbSize = sizeof(TBBUTTONINFO);
|
||||
tbi.dwMask = TBIF_STYLE;
|
||||
::SendMessage(lpnmhdr->hwndFrom, TB_GETBUTTONINFO, nmtbcd->nmcd.dwItemSpec, reinterpret_cast<LPARAM>(&tbi));
|
||||
const bool isDropDown = (tbi.fsStyle & BTNS_DROPDOWN) == BTNS_DROPDOWN;
|
||||
if (isDropDown)
|
||||
{
|
||||
WPARAM idx = ::SendMessage(lpnmhdr->hwndFrom, TB_COMMANDTOINDEX, nmtbcd->nmcd.dwItemSpec, 0);
|
||||
::SendMessage(lpnmhdr->hwndFrom, TB_GETITEMDROPDOWNRECT, idx, reinterpret_cast<LPARAM>(&rcDrop));
|
||||
|
||||
rcItem.right = rcDrop.left;
|
||||
}
|
||||
|
||||
if ((nmtbcd->nmcd.uItemState & CDIS_HOT) == CDIS_HOT)
|
||||
{
|
||||
auto holdBrush = ::SelectObject(nmtbcd->nmcd.hdc, NppDarkMode::getHotBackgroundBrush());
|
||||
auto holdPen = ::SelectObject(nmtbcd->nmcd.hdc, NppDarkMode::getHotEdgePen());
|
||||
::RoundRect(nmtbcd->nmcd.hdc, nmtbcd->nmcd.rc.left, nmtbcd->nmcd.rc.top, nmtbcd->nmcd.rc.right, nmtbcd->nmcd.rc.bottom, roundCornerValue, roundCornerValue);
|
||||
|
||||
::RoundRect(nmtbcd->nmcd.hdc, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, roundCornerValue, roundCornerValue);
|
||||
|
||||
if (isDropDown)
|
||||
{
|
||||
::RoundRect(nmtbcd->nmcd.hdc, rcDrop.left, rcDrop.top, rcDrop.right, rcDrop.bottom, roundCornerValue, roundCornerValue);
|
||||
}
|
||||
|
||||
::SelectObject(nmtbcd->nmcd.hdc, holdBrush);
|
||||
::SelectObject(nmtbcd->nmcd.hdc, holdPen);
|
||||
|
||||
|
@ -2027,7 +2050,14 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
{
|
||||
auto holdBrush = ::SelectObject(nmtbcd->nmcd.hdc, NppDarkMode::getSofterBackgroundBrush());
|
||||
auto holdPen = ::SelectObject(nmtbcd->nmcd.hdc, NppDarkMode::getEdgePen());
|
||||
::RoundRect(nmtbcd->nmcd.hdc, nmtbcd->nmcd.rc.left, nmtbcd->nmcd.rc.top, nmtbcd->nmcd.rc.right, nmtbcd->nmcd.rc.bottom, roundCornerValue, roundCornerValue);
|
||||
|
||||
::RoundRect(nmtbcd->nmcd.hdc, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, roundCornerValue, roundCornerValue);
|
||||
|
||||
if (isDropDown)
|
||||
{
|
||||
::RoundRect(nmtbcd->nmcd.hdc, rcDrop.left, rcDrop.top, rcDrop.right, rcDrop.bottom, roundCornerValue, roundCornerValue);
|
||||
}
|
||||
|
||||
::SelectObject(nmtbcd->nmcd.hdc, holdBrush);
|
||||
::SelectObject(nmtbcd->nmcd.hdc, holdPen);
|
||||
|
||||
|
@ -2040,9 +2070,40 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
lr |= TBCDRF_NOBACKGROUND;
|
||||
}
|
||||
|
||||
if (isDropDown)
|
||||
{
|
||||
lr |= CDRF_NOTIFYPOSTPAINT;
|
||||
}
|
||||
|
||||
return lr;
|
||||
}
|
||||
|
||||
case CDDS_ITEMPOSTPAINT:
|
||||
{
|
||||
|
||||
const UINT dpi = DPIManagerV2::getDpiForWindow(hwnd);
|
||||
LOGFONT lf{ DPIManagerV2::getDefaultGUIFontForDpi(dpi) };
|
||||
HFONT hFont = CreateFontIndirect(&lf);
|
||||
auto holdFont = static_cast<HFONT>(::SelectObject(nmtbcd->nmcd.hdc, hFont));
|
||||
|
||||
RECT rcArrow{};
|
||||
WPARAM idx = ::SendMessage(lpnmhdr->hwndFrom, TB_COMMANDTOINDEX, nmtbcd->nmcd.dwItemSpec, 0);
|
||||
::SendMessage(lpnmhdr->hwndFrom, TB_GETITEMDROPDOWNRECT, idx, reinterpret_cast<LPARAM>(&rcArrow));
|
||||
rcArrow.left += DPIManagerV2::scale(1, dpi);
|
||||
rcArrow.bottom -= DPIManagerV2::scale(3, dpi);
|
||||
|
||||
COLORREF clrArrow = NppDarkMode::getTextColor();
|
||||
|
||||
::SetBkMode(nmtbcd->nmcd.hdc, TRANSPARENT);
|
||||
::SetTextColor(nmtbcd->nmcd.hdc, clrArrow);
|
||||
::DrawText(nmtbcd->nmcd.hdc, L"⏷", -1, &rcArrow, DT_NOPREFIX | DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
|
||||
::SelectObject(nmtbcd->nmcd.hdc, holdFont);
|
||||
::DeleteObject(hFont);
|
||||
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2050,6 +2111,40 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
case TBN_DROPDOWN:
|
||||
{
|
||||
auto lpnmtb = reinterpret_cast<LPNMTOOLBARW>(lParam);
|
||||
switch (lpnmtb->iItem)
|
||||
{
|
||||
case IDM_VIEW_ALL_CHARACTERS:
|
||||
{
|
||||
auto cmdIDs = { IDM_VIEW_TAB_SPACE, IDM_VIEW_EOL, IDM_VIEW_NPC, IDM_VIEW_NPC_CCUNIEOL, 0, IDM_VIEW_ALL_CHARACTERS };
|
||||
notifyTBShowMenu(lpnmtb, "view-showSymbol", cmdIDs);
|
||||
return TBDDRET_DEFAULT;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TBDDRET_NODEFAULT;
|
||||
}
|
||||
|
||||
case NM_RCLICK:
|
||||
{
|
||||
auto lpnmtb = reinterpret_cast<LPNMTOOLBARW>(lParam);
|
||||
switch (lpnmtb->iItem)
|
||||
{
|
||||
case IDM_VIEW_ALL_CHARACTERS:
|
||||
{
|
||||
return notifyTBShowMenu(lpnmtb, "view-showSymbol");
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -151,14 +151,27 @@ bool ToolBar::init( HINSTANCE hInst, HWND hPere, toolBarStatusType type, ToolBar
|
|||
for (; i < _nbButtons && i < _nbTotalButtons; ++i)
|
||||
{
|
||||
cmd = buttonUnitArray[i]._cmdID;
|
||||
if (cmd != 0)
|
||||
switch (cmd)
|
||||
{
|
||||
++bmpIndex;
|
||||
style = BTNS_BUTTON;
|
||||
}
|
||||
else
|
||||
{
|
||||
style = BTNS_SEP;
|
||||
case 0:
|
||||
{
|
||||
style = BTNS_SEP;
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_VIEW_ALL_CHARACTERS:
|
||||
{
|
||||
++bmpIndex;
|
||||
style = BTNS_DROPDOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
++bmpIndex;
|
||||
style = BTNS_BUTTON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_pTBB[i].iBitmap = (cmd != 0 ? bmpIndex : 0);
|
||||
|
@ -169,7 +182,7 @@ bool ToolBar::init( HINSTANCE hInst, HWND hPere, toolBarStatusType type, ToolBar
|
|||
_pTBB[i].iString = 0;
|
||||
}
|
||||
|
||||
if (_nbDynButtons > 0)
|
||||
if (_nbDynButtons > 0 && i < _nbTotalButtons)
|
||||
{
|
||||
//add separator
|
||||
_pTBB[i].iBitmap = 0;
|
||||
|
@ -181,7 +194,7 @@ bool ToolBar::init( HINSTANCE hInst, HWND hPere, toolBarStatusType type, ToolBar
|
|||
++i;
|
||||
|
||||
//add plugin buttons
|
||||
for (size_t j = 0; j < _nbDynButtons ; ++j, ++i)
|
||||
for (size_t j = 0; j < _nbDynButtons && i < _nbTotalButtons; ++j, ++i)
|
||||
{
|
||||
cmd = _vDynBtnReg[j]._message;
|
||||
++bmpIndex;
|
||||
|
@ -318,7 +331,7 @@ void ToolBar::reset(bool create)
|
|||
// Send the TB_BUTTONSTRUCTSIZE message, which is required for
|
||||
// backward compatibility.
|
||||
::SendMessage(_hSelf, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
|
||||
::SendMessage(_hSelf, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_DOUBLEBUFFER);
|
||||
::SendMessage(_hSelf, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_DOUBLEBUFFER);
|
||||
|
||||
change2CustomIconsIfAny();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue