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._appPos.bottom = posInfo.rcNormalPosition.bottom - posInfo.rcNormalPosition.top;
nppGUI._isMaximized = ((IsZoomed(_pPublicInterface->getHSelf()) != 0) || (posInfo.flags & WPF_RESTORETOMAXIMIZED)); 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(); saveDockingParams();
(NppParameters::getInstance()).createXmlTreeFromGUIParams(); (NppParameters::getInstance()).createXmlTreeFromGUIParams();
return true; return true;

View File

@ -4511,6 +4511,39 @@ void NppParameters::feedGUIParameters(TiXmlNode *node)
if (val) if (val)
_nppGUI._isMaximized = (lstrcmp(val, TEXT("yes")) == 0); _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"))) else if (!lstrcmp(nm, TEXT("NewDocDefaultSettings")))
{ {
int i; int i;
@ -5567,6 +5600,16 @@ void NppParameters::createXmlTreeFromGUIParams()
GUIConfigElement->SetAttribute(TEXT("isMaximized"), _nppGUI._isMaximized ? TEXT("yes") : TEXT("no")); 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> // <GUIConfig name="noUpdate" intervalDays="15" nextUpdateDate="20161022">no</GUIConfig>
{ {
TiXmlElement *element = insertGUIConfigBoolNode(newGUIRoot, TEXT("noUpdate"), !_nppGUI._autoUpdateOpt._doAutoUpdate); TiXmlElement *element = insertGUIConfigBoolNode(newGUIRoot, TEXT("noUpdate"), !_nppGUI._autoUpdateOpt._doAutoUpdate);

View File

@ -772,6 +772,11 @@ struct NppGUI final
_appPos.right = 1100; _appPos.right = 1100;
_appPos.bottom = 700; _appPos.bottom = 700;
_findWindowPos.left = 0;
_findWindowPos.top = 0;
_findWindowPos.right = 0;
_findWindowPos.bottom = 0;
_defaultDir[0] = 0; _defaultDir[0] = 0;
_defaultDirExp[0] = 0; _defaultDirExp[0] = 0;
} }
@ -803,6 +808,8 @@ struct NppGUI final
RECT _appPos; RECT _appPos;
RECT _findWindowPos;
bool _isMaximized = false; bool _isMaximized = false;
bool _isMinimizedToTray = false; bool _isMinimizedToTray = false;
bool _rememberLastSession = true; // remember next session boolean will be written in the settings 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) if (enableDlgTheme)
enableDlgTheme(_hSelf, ETDT_ENABLETAB); 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() void FindReplaceDlg::fillFindHistory()
@ -2924,7 +2934,7 @@ void FindReplaceDlg::doDialog(DIALOG_TYPE whichType, bool isRTL, bool toShow)
enableReplaceFunc(whichType == REPLACE_DLG); enableReplaceFunc(whichType == REPLACE_DLG);
::SetFocus(::GetDlgItem(_hSelf, IDFINDWHAT)); ::SetFocus(::GetDlgItem(_hSelf, IDFINDWHAT));
display(toShow); display(toShow, true);
} }
LRESULT FAR PASCAL FindReplaceDlg::finderProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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); ::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 (toShow)
{ {
// If the user has switched from a dual monitor to a single monitor since we last if (enhancedPositioningCheckWhenShowing)
// displayed the dialog, then ensure that it's still visible on the single monitor. {
RECT workAreaRect = {0}; RECT testPositionRc, candidateRc;
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) getWindowRect(testPositionRc);
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 candidateRc = getViewablePositionRect(testPositionRc);
// Remember that MoveWindow wants width/height.
::MoveWindow(_hSelf, newLeft, newTop, rc.right - rc.left, rc.bottom - rc.top, TRUE); 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); 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) HGLOBAL StaticDialog::makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate)
{ {
// Get Dlg Template resource // Get Dlg Template resource

View File

@ -60,7 +60,9 @@ public :
void goToCenter(); 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; POINT getTopPoint(HWND hwnd, bool isLeft = true) const;