Implement issue 905 to make Find window remember its position across runs

Close #905, close #7898
This commit is contained in:
Scott Sumner 2020-01-28 09:15:54 -05:00 committed by Don HO
parent fcf00c7f53
commit 4cc6215e63
No known key found for this signature in database
GPG Key ID: 6C429F1D8D84F46E
6 changed files with 170 additions and 24 deletions

View File

@ -790,6 +790,16 @@ bool Notepad_plus::saveGUIParams()
nppGUI._appPos.bottom = posInfo.rcNormalPosition.bottom - posInfo.rcNormalPosition.top;
nppGUI._isMaximized = ((IsZoomed(_pPublicInterface->getHSelf()) != 0) || (posInfo.flags & WPF_RESTORETOMAXIMIZED));
if (_findReplaceDlg.getHSelf() != NULL)
{
::GetWindowPlacement(_findReplaceDlg.getHSelf(), &posInfo);
nppGUI._findWindowPos.left = posInfo.rcNormalPosition.left;
nppGUI._findWindowPos.top = posInfo.rcNormalPosition.top;
nppGUI._findWindowPos.right = posInfo.rcNormalPosition.right;
nppGUI._findWindowPos.bottom = posInfo.rcNormalPosition.bottom;
}
saveDockingParams();
(NppParameters::getInstance()).createXmlTreeFromGUIParams();
return true;

View File

@ -4511,6 +4511,39 @@ void NppParameters::feedGUIParameters(TiXmlNode *node)
if (val)
_nppGUI._isMaximized = (lstrcmp(val, TEXT("yes")) == 0);
}
else if (!lstrcmp(nm, TEXT("FindWindowPosition")))
{
RECT oldRect = _nppGUI._findWindowPos;
bool incomplete = true;
int i;
if (element->Attribute(TEXT("left"), &i))
{
_nppGUI._findWindowPos.left = i;
if (element->Attribute(TEXT("top"), &i))
{
_nppGUI._findWindowPos.top = i;
if (element->Attribute(TEXT("right"), &i))
{
_nppGUI._findWindowPos.right = i;
if (element->Attribute(TEXT("bottom"), &i))
{
_nppGUI._findWindowPos.bottom = i;
incomplete = false;
}
}
}
}
if (incomplete)
{
_nppGUI._findWindowPos = oldRect;
}
}
else if (!lstrcmp(nm, TEXT("NewDocDefaultSettings")))
{
int i;
@ -5567,6 +5600,16 @@ void NppParameters::createXmlTreeFromGUIParams()
GUIConfigElement->SetAttribute(TEXT("isMaximized"), _nppGUI._isMaximized ? TEXT("yes") : TEXT("no"));
}
// <GUIConfig name="FindWindowPosition" left="134" top="320" right="723" bottom="684" />
{
TiXmlElement* GUIConfigElement = (newGUIRoot->InsertEndChild(TiXmlElement(TEXT("GUIConfig"))))->ToElement();
GUIConfigElement->SetAttribute(TEXT("name"), TEXT("FindWindowPosition"));
GUIConfigElement->SetAttribute(TEXT("left"), _nppGUI._findWindowPos.left);
GUIConfigElement->SetAttribute(TEXT("top"), _nppGUI._findWindowPos.top);
GUIConfigElement->SetAttribute(TEXT("right"), _nppGUI._findWindowPos.right);
GUIConfigElement->SetAttribute(TEXT("bottom"), _nppGUI._findWindowPos.bottom);
}
// <GUIConfig name="noUpdate" intervalDays="15" nextUpdateDate="20161022">no</GUIConfig>
{
TiXmlElement *element = insertGUIConfigBoolNode(newGUIRoot, TEXT("noUpdate"), !_nppGUI._autoUpdateOpt._doAutoUpdate);

View File

@ -772,6 +772,11 @@ struct NppGUI final
_appPos.right = 1100;
_appPos.bottom = 700;
_findWindowPos.left = 0;
_findWindowPos.top = 0;
_findWindowPos.right = 0;
_findWindowPos.bottom = 0;
_defaultDir[0] = 0;
_defaultDirExp[0] = 0;
}
@ -803,6 +808,8 @@ struct NppGUI final
RECT _appPos;
RECT _findWindowPos;
bool _isMaximized = false;
bool _isMinimizedToTray = false;
bool _rememberLastSession = true; // remember next session boolean will be written in the settings

View File

@ -297,7 +297,17 @@ void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent)
if (enableDlgTheme)
enableDlgTheme(_hSelf, ETDT_ENABLETAB);
goToCenter();
NppParameters& nppParam = NppParameters::getInstance();
NppGUI& nppGUI = const_cast<NppGUI&>(nppParam.getNppGUI());
if (nppGUI._findWindowPos.bottom - nppGUI._findWindowPos.top != 0) // check height against 0 as a test of valid data from config
{
RECT rc = getViewablePositionRect(nppGUI._findWindowPos);
::SetWindowPos(_hSelf, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW);
}
else
{
goToCenter();
}
}
void FindReplaceDlg::fillFindHistory()
@ -2924,7 +2934,7 @@ void FindReplaceDlg::doDialog(DIALOG_TYPE whichType, bool isRTL, bool toShow)
enableReplaceFunc(whichType == REPLACE_DLG);
::SetFocus(::GetDlgItem(_hSelf, IDFINDWHAT));
display(toShow);
display(toShow, true);
}
LRESULT FAR PASCAL FindReplaceDlg::finderProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

View File

@ -77,37 +77,111 @@ void StaticDialog::goToCenter()
::SetWindowPos(_hSelf, HWND_TOP, x, y, _rc.right - _rc.left, _rc.bottom - _rc.top, SWP_SHOWWINDOW);
}
void StaticDialog::display(bool toShow) const
void StaticDialog::display(bool toShow, bool enhancedPositioningCheckWhenShowing) const
{
if (toShow)
{
// If the user has switched from a dual monitor to a single monitor since we last
// displayed the dialog, then ensure that it's still visible on the single monitor.
RECT workAreaRect = {0};
RECT rc = {0};
::SystemParametersInfo(SPI_GETWORKAREA, 0, &workAreaRect, 0);
::GetWindowRect(_hSelf, &rc);
int newLeft = rc.left;
int newTop = rc.top;
int margin = ::GetSystemMetrics(SM_CYSMCAPTION);
if (enhancedPositioningCheckWhenShowing)
{
RECT testPositionRc, candidateRc;
if (newLeft > ::GetSystemMetrics(SM_CXVIRTUALSCREEN)-margin)
newLeft -= rc.right - workAreaRect.right;
if (newLeft + (rc.right - rc.left) < ::GetSystemMetrics(SM_XVIRTUALSCREEN)+margin)
newLeft = workAreaRect.left;
if (newTop > ::GetSystemMetrics(SM_CYVIRTUALSCREEN)-margin)
newTop -= rc.bottom - workAreaRect.bottom;
if (newTop + (rc.bottom - rc.top) < ::GetSystemMetrics(SM_YVIRTUALSCREEN)+margin)
newTop = workAreaRect.top;
getWindowRect(testPositionRc);
if ((newLeft != rc.left) || (newTop != rc.top)) // then the virtual screen size has shrunk
// Remember that MoveWindow wants width/height.
::MoveWindow(_hSelf, newLeft, newTop, rc.right - rc.left, rc.bottom - rc.top, TRUE);
candidateRc = getViewablePositionRect(testPositionRc);
if ((testPositionRc.left != candidateRc.left) || (testPositionRc.top != candidateRc.top))
{
::MoveWindow(_hSelf, candidateRc.left, candidateRc.top,
candidateRc.right - candidateRc.left, candidateRc.bottom - candidateRc.top, TRUE);
}
}
else
{
// If the user has switched from a dual monitor to a single monitor since we last
// displayed the dialog, then ensure that it's still visible on the single monitor.
RECT workAreaRect = { 0 };
RECT rc = { 0 };
::SystemParametersInfo(SPI_GETWORKAREA, 0, &workAreaRect, 0);
::GetWindowRect(_hSelf, &rc);
int newLeft = rc.left;
int newTop = rc.top;
int margin = ::GetSystemMetrics(SM_CYSMCAPTION);
if (newLeft > ::GetSystemMetrics(SM_CXVIRTUALSCREEN) - margin)
newLeft -= rc.right - workAreaRect.right;
if (newLeft + (rc.right - rc.left) < ::GetSystemMetrics(SM_XVIRTUALSCREEN) + margin)
newLeft = workAreaRect.left;
if (newTop > ::GetSystemMetrics(SM_CYVIRTUALSCREEN) - margin)
newTop -= rc.bottom - workAreaRect.bottom;
if (newTop + (rc.bottom - rc.top) < ::GetSystemMetrics(SM_YVIRTUALSCREEN) + margin)
newTop = workAreaRect.top;
if ((newLeft != rc.left) || (newTop != rc.top)) // then the virtual screen size has shrunk
// Remember that MoveWindow wants width/height.
::MoveWindow(_hSelf, newLeft, newTop, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
}
Window::display(toShow);
}
RECT StaticDialog::getViewablePositionRect(RECT testPositionRc) const
{
HMONITOR hMon = ::MonitorFromRect(&testPositionRc, MONITOR_DEFAULTTONULL);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
bool rectPosViewableWithoutChange = false;
if (hMon != NULL)
{
// rect would be at least partially visible on a monitor
::GetMonitorInfo(hMon, &mi);
int margin = ::GetSystemMetrics(SM_CYBORDER) + ::GetSystemMetrics(SM_CYSIZEFRAME) + ::GetSystemMetrics(SM_CYCAPTION);
// require that the title bar of the window be in a viewable place so the user can see it to grab it with the mouse
if ((testPositionRc.top >= mi.rcWork.top) && (testPositionRc.top + margin <= mi.rcWork.bottom) &&
// require that some reasonable amount of width of the title bar be in the viewable area:
(testPositionRc.right - (margin * 2) > mi.rcWork.left) && (testPositionRc.left + (margin * 2) < mi.rcWork.right))
{
rectPosViewableWithoutChange = true;
}
}
else
{
// rect would not have been visible on a monitor; get info about the nearest monitor to it
hMon = ::MonitorFromRect(&testPositionRc, MONITOR_DEFAULTTONEAREST);
::GetMonitorInfo(hMon, &mi);
}
RECT returnRc = testPositionRc;
if (!rectPosViewableWithoutChange)
{
// reposition rect so that it would be viewable on current/nearest monitor, centering if reasonable
LONG testRectWidth = testPositionRc.right - testPositionRc.left;
LONG testRectHeight = testPositionRc.bottom - testPositionRc.top;
LONG monWidth = mi.rcWork.right - mi.rcWork.left;
LONG monHeight = mi.rcWork.bottom - mi.rcWork.top;
returnRc.left = mi.rcWork.left;
if (testRectWidth < monWidth) returnRc.left += (monWidth - testRectWidth) / 2;
returnRc.right = returnRc.left + testRectWidth;
returnRc.top = mi.rcWork.top;
if (testRectHeight < monHeight) returnRc.top += (monHeight - testRectHeight) / 2;
returnRc.bottom = returnRc.top + testRectHeight;
}
return returnRc;
}
HGLOBAL StaticDialog::makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate)
{
// Get Dlg Template resource

View File

@ -60,7 +60,9 @@ public :
void goToCenter();
void display(bool toShow = true) const;
void display(bool toShow = true, bool enhancedPositioningCheckWhenShowing = false) const;
RECT getViewablePositionRect(RECT testRc) const;
POINT getTopPoint(HWND hwnd, bool isLeft = true) const;