Title: Set position of MFC dialog-based application window
Tags: mfc;cdialog
Question: I have a CDialog based MFC application. I save the window's current position when the program ends. When the program starts, I want to restore the previous position. I'm currently trying to do this in OnInitDialog(), however, the program asserts when I call SetWindowPos() from within OnInitDialog(). My call to SetWindowPos() is similar to:
SetWindowPos(&amp;CWn75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0wndTop, 10, 10, 500, 500, SWP_NOREDRAW | SWP_NOZORDER);
The assertion relates to a null m_hWnd handle.
Is this the correct place to re-position a dialog-based application's window?
Any ideas on why I'm asserting?
Comment: @IInspectable Not in a `CDialog` based application.

Comment: As I remember, MFC saves window positions (and restores them) for you already. Has that changed?

Comment: It is valid to call `SetWindowPos()` from `OnInitDialog()`, as the window handle already exists. Need to see [mcve] for further assitance.


Here is another answer: This is how I do it:
#include "stdafx.h"
#include "resource.h"
#include "ResizingDialog.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ResizingDialog(const CString&amp; strWindowID, UINT nIDTemplate, CWnd* pParent /* nullptr */, bool bOnlyStorePosition /* false */)
: CDialogEx(nIDTemplate, pParent)
, m_strWindowID(strWindowID)
, m_bOnlyStorePosition(bOnlyStorePosition)
, m_bDoNotShowResizeIcon(false)
m_rcInit.SetRect(0, 0, 0, 0);
CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0~CResizingDialog()
= default;
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0oDataExchange(CDataExchange* pDX)
CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0oDataExchange(pDX);
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_GETMINMAXINFO()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_NCHITTEST()
ON_WM_SIZE()
END_MESSAGE_MAP()
BOOL CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnInitDialog()
CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnInitDialog();
// Save Initial window size to m_rcInit
GetWindowRect(&amp;m_rcInit);
//if (!m_bOnlyStorePosition &amp;&amp; !m_bDoNotShowResizeIcon)
//InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
RestoreWindowPosition(m_strWindowID, this, true);
return TRUE;  // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnGetMinMaxInfo(MINMAXINFO* lpMMI)
// Set the minimum window size to initial size.
lpMMI-&gt;ptMinTrackSize.x = m_rcInit.Width();
lpMMI-&gt;ptMinTrackSize.y = m_rcInit.Height();
CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnGetMinMaxInfo(lpMMI);
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState)
int     max_x, max_y;
RECT    rtWindow;
if (pWindow == nullptr)
return;
// Only restore if there is a previously saved position
if ((rtWindow.top = AfxGetApp()-&gt;GetProfileInt(strWindow, _T("Top"), -1)) != -1 &amp;&amp;
(rtWindow.left = AfxGetApp()-&gt;GetProfileInt(strWindow, _T("Left"), -1)) != -1 &amp;&amp;
(rtWindow.bottom = AfxGetApp()-&gt;GetProfileInt(strWindow, _T("Bottom"), -1)) != -1 &amp;&amp;
(rtWindow.right = AfxGetApp()-&gt;GetProfileInt(strWindow, _T("Right"), -1)))
max_x = rtWindow.right - rtWindow.left;
max_y = rtWindow.bottom - rtWindow.top;
// Get a handle to the monitor
HMONITOR hMonitor = 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0MonitorFromPoint(
CPoint(rtWindow.left, rtWindow.top), MONITOR_DEFAULTTONEAREST);
// Get the monitor info
MONITORINFO monInfo;
monInfo.cbSize = sizeof(MONITORINFO);
if (75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0GetMonitorInfo(hMonitor, &amp;monInfo) == 0)
AfxMessageBox(_T("GetMonitorInfo failed"));
else
{
// Adjust for work area
rtWindow.left += monInfo.rcWork.left - monInfo.rcMonitor.left;
rtWindow.top += monInfo.rcWork.top - monInfo.rcMonitor.top;
// Ensure top left point is on screen
if (CRect(monInfo.rcWork).PtInRect(CPoint(rtWindow.left, rtWindow.top)) == FALSE)
{
rtWindow.left = monInfo.rcWork.left;
rtWindow.top = monInfo.rcWork.top;
}
rtWindow.right = rtWindow.left + max_x;
rtWindow.bottom = rtWindow.top + max_y;
// Restore window size
pWindow-&gt;MoveWindow(&amp;rtWindow, FALSE);
}
if (bOverrideState)
{
// Let us override by restoring the window state
int iState = AfxGetApp()-&gt;GetProfileInt(strWindow, _T("ShowCmd"), SW_SHOWNORMAL);
pWindow-&gt;ShowWindow(iState);
}
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0SaveWindowPosition(CString strWindow, CWnd* pWindow)
WINDOWPLACEMENT wp;
if (pWindow == nullptr)
return;
pWindow-&gt;GetWindowPlacement(&amp;wp);
// Commit to registry
AfxGetApp()-&gt;WriteProfileInt(strWindow, _T("Top"), wp.rcNormalPosition.top);
AfxGetApp()-&gt;WriteProfileInt(strWindow, _T("Left"), wp.rcNormalPosition.left);
AfxGetApp()-&gt;WriteProfileInt(strWindow, _T("Bottom"), wp.rcNormalPosition.bottom);
AfxGetApp()-&gt;WriteProfileInt(strWindow, _T("Right"), wp.rcNormalPosition.right);
AfxGetApp()-&gt;WriteProfileInt(strWindow, _T("ShowCmd"), wp.showCmd);
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0InitialiseResizeIcon(CBitmap&amp; rBmpResize, CStatic&amp; rLblResize, CWnd* pDialog)
CRect rcIcon, rcClient;
if (pDialog != nullptr)
rBmpResize.LoadOEMBitmap(OBM_SIZE);
rLblResize.Create(nullptr, WS_CHILD | WS_VISIBLE | SS_BITMAP,
CRect(0, 0, 16, 16), pDialog, IDC_STATIC_RESIZE);
rLblResize.SetBitmap(rBmpResize);
//theApp.UpdateBitmapBackground(rLblResize.GetBitmap(), true, GetSysColor(COLOR_ACTIVECAPTION));
pDialog-&gt;GetClientRect(rcClient);
rLblResize.GetClientRect(rcIcon);
rLblResize.SetWindowPos(&amp;CWn75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0wndTop,
rcClient.right - rcIcon.Width(),
rcClient.bottom - rcIcon.Height(), 0, 0, SWP_NOSIZE);
CMFCDynamicLayout *pDynamicLayout = pDialog-&gt;GetDynamicLayout();
if (pDynamicLayout != nullptr)
{
CMFCDynamicLayout75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0MoveSettings moveSettings = CMFCDynamicLayout75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0MoveHorizontalAndVertical(100, 100);
CMFCDynamicLayout75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0SizeSettings sizeSettings = CMFCDynamicLayout75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0SizeNone();
pDynamicLayout-&gt;AddItem(rLblResize.GetSafeHwnd(), moveSettings, sizeSettings);
}
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnDestroy()
CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnDestroy();
SaveWindowPosition(m_strWindowID, this);
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0oNotShowResizeIcon()
m_bDoNotShowResizeIcon = true;
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnPaint()
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnPaint() for painting messages
if (!m_bOnlyStorePosition &amp;&amp; !m_bDoNotShowResizeIcon)
CRect rc;
GetClientRect(&amp;rc);
rc.left = rc.right - 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0GetSystemMetrics(SM_CXHSCROLL);
rc.top = rc.bottom - 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0GetSystemMetrics(SM_CYVSCROLL);
HTHEME ht = OpenThemeData(GetSafeHwnd(), L"STATUS");
if (ht)
{
DrawThemeBackground(ht, dc, SP_GRIPPER, 0, &amp;rc, nullptr);
CloseThemeData(ht);
}
else
{
dc.DrawFrameControl(rc, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
}
LRESULT CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnNcHitTest(CPoint point)
CRect rc;
GetWindowRect(rc);
rc.left = rc.right - 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0GetSystemMetrics(SM_CXHSCROLL);
rc.top = rc.bottom - 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0GetSystemMetrics(SM_CYVSCROLL);
if (rc.PtInRect(point))
return HTBOTTOMRIGHT;
return CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnNcHitTest(point);
void CResizingDialog75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnSize(UINT nType, int cx, int cy)
CDialogEx75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0OnSize(nType, cx, cy);
Invalidate(TRUE);
I don't know how you are storing the window position but my code factors in for multiple monitor configurations.

Here is another answer: In the process of providing more information to my initial question, I discovered that calling SetWindowPos() passed messages to toolbars within the dialog that hadn't been created, yet. I moved the SetWindowPos() to the end of OnInitiDialog() and it worked.
Thanks for the encouragement, @zett42.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 3, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2019:00:04/23/19', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<mfc><cdialog>', 'Title': 'Set position of MFC dialog-based application window', 'ViewCount': 695, 'id': 55817368, 'user_AboutMe': '<p>Merge keep</p>\n', 'user_AccountId': 200667.0, 'user_DisplayName': 'Steve A', 'user_Reputation': 1627.0, 'user_Views': 169.0, 'user_id': 446647.0}}