c++fontsdialogatlwtl

Change dialog font at runtime


I'd like to change the font of a few dialogs. The fonts of these dialogs are not to be changed using the ressource editor they are to be changed at runtime.

The dialogs in question are all based on ATL/WTL and they're declared pretty much like the following example:

class CDiscardErrorDlg :
public CDialogImpl<CDiscardErrorDlg>,
public CDialogResize<CDiscardErrorDlg>
{
}

My question is how to change the font for a whole CDialogImpl derived class. As far as I know, changing the DLGTEMPLATE is the way to go. But I have no idea on how to achieve that!?! Where do I have access to DLGTEMPLATE's? Is CDialogImpl the correct class to solve my problem?

Do you have an idea or web reference which might help me on that problem?


Solution

  • just wanted to let you know that I have found a solution to the problem:

    Here's what to do:

    1. derive a class from CDialogImpl

    2. overwrite DoModal

    3. load the DLGTEMPLATE template in memory and

    4. take an instance of CDialogTemplate to change the template's font

    5. pass the modified template to DialogBoxIndirectParam

      template <class T, class TBase = CWindow > class ATL_NO_VTABLE CDialogImplEx : public CDialogImpl<T, TBase> { public:

       INT_PTR DoModal(
           _In_ HWND hWndParent = ::GetActiveWindow(),
           _In_ LPARAM dwInitParam = NULL)
       {
           T* pT = static_cast<T*>(this);
           ATLASSERT(pT->m_hWnd == NULL);
      
           LPDLGTEMPLATE pTemplate = nullptr;
      
           HINSTANCE hInstance = AfxGetResourceHandle();
           HRSRC hDlg = AtlFindResource(hInstance, MAKEINTRESOURCE(static_cast<T*>(this)->IDD), RT_DIALOG);
           if (hDlg != NULL)
           {
               HRSRC hDlgInit = AtlFindResource(hInstance, MAKEINTRESOURCE(static_cast<T*>(this)->IDD), _ATL_RT_DLGINIT);
               HGLOBAL hData = NULL;
               BYTE* pInitData = NULL;
      
               if (hDlgInit)
               {
                   hData = ::LoadResource(hInstance, hDlgInit);
                   ATLASSUME(hData != nullptr);
                   pInitData = (BYTE*) ::LockResource(hData);
               }
      
               DWORD dwLastError = 0;
               HGLOBAL hResource = LoadResource(hInstance, hDlg);
               if (hResource != nullptr)
               {
                   DLGTEMPLATE* pTempl = (DLGTEMPLATE*)LockResource(hResource);
                   CDialogTemplate DialogTempl(pTempl);
      
                   DialogTempl.SetFont(_T("Segoe UI"), 20); // Set a huge font
      
                   HGLOBAL hDialogTemplate = DialogTempl.Detach();
      
                   pTemplate = (DLGTEMPLATE*)::GlobalLock(hDialogTemplate);
      
                   ::FreeResource(hResource);
                   hResource = nullptr;
               }
               else
               {
                   dwLastError = ::GetLastError();
               }
           }
      

      #if (_ATL_VER >= 0x0800) // Allocate the thunk structure here, where we can fail gracefully. BOOL bRet = m_thunk.Init(nullptr, nullptr); if (bRet == FALSE) { ::SetLastError(ERROR_OUTOFMEMORY); return -1; } #endif // (_ATL_VER >= 0x0800)

           _AtlWinModule.AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBaseT< TBase >*)pT);
      

      #ifdef _DEBUG m_bModal = true; #endif // _DEBUG

           INT_PTR nRet = ::DialogBoxIndirectParam(hInstance, pTemplate, hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
      
           if (nRet == -1)
           {
               DWORD dwErr = ::GetLastError();
               dwErr = 0;
           }
      
           return nRet;
           //return CDialogImpl<T>::DoModal(hWndParent, dwInitParam);
       }
      

      };

    Hope it'll be helpful to someone, too. Best regards,