2019年3月12日火曜日

DPI change test (MFC dialog base applicatoin)

These codes are the result of try and error.
It means not so good codes.
SaveAppLayout and UpdateLayoutForDPI function should not be callback function.

Add to OnInitdialog
// save current size
 SaveAppLayout(this->m_hWnd,(LPARAM)this);
 // Resize child windows
// ::EnumChildWindows(this->m_hWnd, SaveAppLayout, (LPARAM)this); // Not necessary



Add to Header

afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();

 DECLARE_MESSAGE_MAP()
 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

Add to Dlg.cpp

BOOL CALLBACK SaveAppLayout(HWND hWnd,LPARAM lParam)
{
 CDPIChangeTestDlg* pParent = (CDPIChangeTestDlg*)lParam;
 int iDpi = GetDpiForWindow(hWnd);

 // Get current size(at 96 DPI base)
 CRect rect;
 ::GetWindowRect(hWnd, &rect);
 pParent->mResMap[hWnd] = rect;

 // recalc size
 double rate = iDpi / 96;
 rect.left *= rate;
 rect.top *= rate;
 rect.right  *= rate;
 rect.bottom *= rate;

 // resize
 SetWindowPos(hWnd, hWnd, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);

 return TRUE;
}

BOOL CALLBACK UpdateLayoutForDpi(HWND hWnd, LPARAM lParam)
{
 CDPIChangeTestDlg* pParent = (CDPIChangeTestDlg*)lParam;

 try {
  int iDpi = GetDpiForWindow(hWnd);
  // calc current DPI and rate from 96 DPI
  double rate = iDpi / 96;
  CRect rect = pParent->mResMap[hWnd];

  int dpiScaledX = rect.left / rate;
  int dpiScaledY = rect.top / rate;
  int dpiScaledWidth = rect.Width() / rate;
  int dpiScaledHeight = rect.Height() / rate;

  // resize
  SetWindowPos(hWnd, hWnd, dpiScaledX, dpiScaledY, dpiScaledWidth, dpiScaledHeight, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
 }
 catch (...) {
  return FALSE;
 }
 return TRUE;
}

void CDPIChangeTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialogEx::OnSysCommand(nID, lParam);
 }
}

LRESULT CDPIChangeTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 
 switch (message) {
 case WM_DPICHANGED:
 {
  // Resize
  UpdateLayoutForDpi(this->m_hWnd, (LPARAM)this);
  // Resize Child Windows
//  ::EnumChildWindows(this->m_hWnd, UpdateLayoutForDpi, (LPARAM)this); // Not necessary
 }
 break;

 }
 return CDialogEx::WindowProc(message, wParam, lParam);
}


download all source here