tdlemu/TaskDialogEmu.h
2022-03-16 09:17:27 +01:00

2848 lines
148 KiB
C++

#if !defined(AFX_TASKDIALOGEMU_H__20073232_5AA0_1E88_3A6D_0080AD509054__INCLUDED_)
#define AFX_TASKDIALOGEMU_H__20073232_5AA0_1E88_3A6D_0080AD509054__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CTask98Dialog - Task Dialog for legacy Windows platforms
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2007 Bjarke Viksoe.
//
// Thanks to David Brown and Yarp of senosoft.com
// for submitting several fixes.
//
// This code may be used in compiled form in any way you desire.
//
// This source file may be redistributed by any means PROVIDING
// it is not sold for profit without the authors written consent,
// and providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//
// The dialog requires a few string and icon resources to be defined. Ironic isn't it: the dialog
// is dynamically constructed but we still need resources.
// Here is a list:
// IDS_TASKDLG_OK "&OK"
// IDS_TASKDLG_YES "&Yes"
// IDS_TASKDLG_NO "&No"
// IDS_TASKDLG_CANCEL "&Cancel"
// IDS_TASKDLG_RETRY "&Retry"
// IDS_TASKDLG_CLOSE "Close"
//
// IDI_TASKDLG_CHEVRON_LESS Expander icon (less)
// IDI_TASKDLG_CHEVRON_MORE Expander icon (more)
// IDI_TASKDLG_ARROW_NORMAL Green Link Arrow
// IDI_TASKDLG_ARROW_HOT Green Link Arrow (hover)
//
/*By Erich Willems: Small changes and fixes are applied to this version of the source code.
*The changed code is intended only to use in compiled form,
*so 'This code may be used in compiled form "in any way you desire".'
*is taking effect.
*The purpose of the small adaptions is to make the code better fit into
*the needs of the framework used in.
*/
#include "resource.h"
//#include "atlmisc.h"
//#include "VersWin.h"
//#define CString ATL::CString
/////////////////////////////////////////////////////////////////////////
// /// TaskDialogEmu declares
//
#include "TaskDialogEmu.h.WinXPDeclarations.incl"
#include "TaskDialogEmu.h.PreVistaDeclarations.incl"
#include "TaskDialogEmu.h.WTLPreBaseUnitsHelper.incl"
#include "TaskDialogEmu.h.TaskDialogConfig_X.incl" //support for mixed custom push and commandbuttons
#include "TaskDialogEmu.h.PixelRect.incl"
#include "TaskDialogEmu.h.DLURect.incl"
//some constants:
#ifndef PBM_SETSTATE
const UINT PBM_SETSTATE = WM_USER + 16;
#endif
#ifndef PBM_SETMARQUEE
const UINT PBM_SETMARQUEE = WM_USER + 10;
#endif
#ifndef PBS_MARQUEE
const DWORD PBS_MARQUEE = 0x08;
#endif
#ifndef WS_EX_LAYOUTRTL
const UINT WS_EX_LAYOUTRTL = 0x00400000L;
#endif
#ifndef BS_COMMANDLINK
const DWORD BS_COMMANDLINK = 0x0000000E;
const DWORD BS_DEFCOMMANDLINK = 0x0000000F;
#endif // BS_COMMANDLINK
#ifndef DECL_dThis
#define DECL_dThis const DERIVED* dThis = static_cast<const DERIVED*>(this) ///<In context of template virtualization. Declares the method-local dThis pointer
#endif
/////////////////////////////////////////////////////////////////////////
// TaskDialogEmu dialog implementation
//
void aligneByBaseUnitsSlope(LONG& what,double unitPre, double unitNow,int sign=1)
{//*if(unitPre == unitNow) */ return;
if(true) return;//as pragma warning disable will not work on unreachable code
double f =unitPre/unitNow;
double lns =what/unitNow;
if(f>1.0) {what+= sign*(LONG)(lns*f);
}
else {double f =unitNow/unitPre;
what-= sign*(LONG)(lns*f);
}
}
// -----------------------------------------------
void makeTxtColFromBackground(COLORREF& txt,COLORREF& backg)
{
int txt1=0x000000ff & (txt>>2*8);
int txt2=0x000000ff & (txt>>1*8);
int txt3=0x000000ff & (txt>>0*8);
txt1=0xff -txt1;
txt2=0xff -txt2;
txt3=0xff -txt3;
int bak1=0x000000ff & (backg>>2*8);
int bak2=0x000000ff & (backg>>1*8);
int bak3=0x000000ff & (backg>>0*8);
txt1=abs(bak1-txt1);
txt2=abs(bak2-txt2);
txt3=abs(bak3-txt3);
txt =txt1<<2*8
|txt2<<1*8
|txt3<<0*8
;
}
template< class DERIVED >
#if _WTL_VER < 0x0810
class CTask98DialogImpl : public CIndirectDialogImpl<DERIVED>, public CDialogBaseUnits
#else
class CTask98DialogImpl : public CIndirectDialogImpl<DERIVED>, public WTL::CDialogBaseUnits
#endif
{
public: typedef CTask98DialogImpl Tp;
typedef CIndirectDialogImpl<DERIVED> TpParent;
friend TpParent;
public:
enum
{IDC_TASKDLG_OK = IDOK,
IDC_TASKDLG_YES = IDYES,
IDC_TASKDLG_NO = IDNO,
IDC_TASKDLG_CANCEL = IDCANCEL,
IDC_TASKDLG_RETRY = IDRETRY,
IDC_TASKDLG_CLOSE = IDCLOSE,
//
IDC_TASKDLG_TITLETEXT = 0x7400,
IDC_TASKDLG_INSTRUCTIONSTEXT,
IDC_TASKDLG_INSTRUCTIONSICON,
IDC_TASKDLG_CONTENTTEXT,
IDC_TASKDLG_BOTTOMDIVIDER,
IDC_TASKDLG_VERIFYBUTTON,
IDC_TASKDLG_EXPANDERICON,
IDC_TASKDLG_EXPANDERTEXT,
IDC_TASKDLG_EXTRATEXT,
IDC_TASKDLG_FOOTERDIVIDER,
IDC_TASKDLG_FOOTERTEXT,
IDC_TASKDLG_FOOTERICON,
IDC_TASKDLG_PROGRESSBAR,
//
IDC_TASKDLG_CUSTOMBUTTON_FIRST,
IDC_TASKDLG_CUSTOMBUTTON_LAST = IDC_TASKDLG_CUSTOMBUTTON_FIRST + 20 //mutatebale
+ 20 //non mutatebale
,
IDC_TASKDLG_RADIOBUTTON_FIRST,
IDC_TASKDLG_RADIOBUTTON_LAST = IDC_TASKDLG_RADIOBUTTON_FIRST + 20,
};
enum {TIMERID_TIGGER = 4050,
TIMERID_HOVERLINK = 4051,
WIDTH_PROBE = 99999,
};
enum {MAX_TEXT_LENGTH = 2048
};
public:
CTask98DialogImpl() : m_bNavigated(false),ShowExpanderIcon(false)
{DECL_dThis;
::ZeroMemory(&m_cfg, sizeof(m_cfg));
m_cfg.cbSize = sizeof(TASKDIALOGCONFIG);
m_cfg.cbSize_X = sizeof(TASKDIALOGCONFIG_X);
m_cfg.hInstance = ModuleHelper::GetResourceInstance();
m_cfg.pfCallback = DERIVED::TaskDialogCallback; //use the one of the derived if defined otherwise the own as default
m_cfg.lpCallbackData = (LONG_PTR) dThis; //as callback owning instance use the defived
_Reset();
}
public:
BEGIN_MSG_MAP(CTask98DialogImpl)
MESSAGE_HANDLER(WM_INITDIALOG, OnWmInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnWmDestroy)
MESSAGE_HANDLER(WM_HELP, OnWmHelp)
MESSAGE_HANDLER(WM_TIMER, OnWmTimer)
MESSAGE_HANDLER(WM_ERASEBKGND, OnWmEraseBkgnd)
MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnWmCtlColor)
MESSAGE_HANDLER(WM_CTLCOLORBTN, OnWmCtlColor)
MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
MESSAGE_HANDLER(WM_DRAWITEM, OnWmDrawItem)
MESSAGE_HANDLER(TDM_CLICK_BUTTON, OnMsgClickButton)
MESSAGE_HANDLER(TDM_CLICK_VERIFICATION, OnMsgClickVerification)
MESSAGE_HANDLER(TDM_CLICK_RADIO_BUTTON, OnMsgClickRadioButton)
MESSAGE_HANDLER(TDM_ENABLE_BUTTON, OnMsgEnableButton)
MESSAGE_HANDLER(TDM_ENABLE_RADIO_BUTTON, OnMsgEnableRadioButton)
MESSAGE_HANDLER(TDM_SET_PROGRESS_BAR_POS, OnMsgSetProgressBarPos)
MESSAGE_HANDLER(TDM_SET_PROGRESS_BAR_RANGE, OnMsgSetProgressBarRange)
MESSAGE_HANDLER(TDM_SET_PROGRESS_BAR_STATE, OnMsgSetProgressBarState)
MESSAGE_HANDLER(TDM_SET_PROGRESS_BAR_MARQUEE, OnMsgSetProgressBarMarquee)
MESSAGE_HANDLER(TDM_SET_MARQUEE_PROGRESS_BAR, OnMsgSetMarqueeProgressBar)
MESSAGE_HANDLER(TDM_SET_ELEMENT_TEXT, OnMsgSetElementText)
MESSAGE_HANDLER(TDM_UPDATE_ELEMENT_TEXT, OnMsgUpdateElementText)
COMMAND_HANDLER(IDC_TASKDLG_EXPANDERICON, STN_CLICKED, OnMsgExpandoClick);
COMMAND_HANDLER(IDC_TASKDLG_EXPANDERTEXT, STN_CLICKED, OnMsgExpandoClick);
COMMAND_HANDLER(IDC_TASKDLG_EXPANDERICON, STN_DBLCLK, OnMsgExpandoClick);
COMMAND_HANDLER(IDC_TASKDLG_EXPANDERTEXT, STN_DBLCLK, OnMsgExpandoClick);
COMMAND_ID_HANDLER(IDC_TASKDLG_VERIFYBUTTON, OnMsgVerificationClick);
COMMAND_RANGE_HANDLER(1, 64, OnMsgCommonButtonClick)
COMMAND_RANGE_HANDLER(IDC_TASKDLG_CUSTOMBUTTON_FIRST, IDC_TASKDLG_CUSTOMBUTTON_LAST, OnMsgCustomButtonClick)
COMMAND_RANGE_HANDLER(IDC_TASKDLG_RADIOBUTTON_FIRST, IDC_TASKDLG_RADIOBUTTON_LAST, OnMsgRadioClick)
NOTIFY_HANDLER(IDC_TASKDLG_CONTENTTEXT, NM_CLICK, OnMsgHyperlinkClicked)
NOTIFY_HANDLER(IDC_TASKDLG_FOOTERTEXT, NM_CLICK, OnMsgHyperlinkClicked)
NOTIFY_HANDLER(IDC_TASKDLG_EXTRATEXT, NM_CLICK, OnMsgHyperlinkClicked)
END_MSG_MAP()
public:// Operations
bool SetConfig(const TASKDIALOGCONFIG* pConfig)
{ AXF_(IS(pConfig) ,return false);
m_cfg = *pConfig;
AXE_(m_cfg.cButtons <= 20 ,return false);
AXE_(m_cfg.cRadioButtons <= 20 ,return false);
AXE_(IMPLICATES(IS((TDF_USE_COMMAND_LINKS //command link buttos ==> defined buttons
|TDF_USE_COMMAND_LINKS_NO_ICON
) & m_cfg.dwFlags)
,IS(m_cfg.cButtons)) ,return false);
if( IS (m_cfg.pszExpandedInformation)
AND NOT(m_cfg.pszExpandedControlText)
)m_cfg.pszExpandedControlText = L"Hide details";
if( IS (m_cfg.pszExpandedInformation)
AND NOT(m_cfg.pszCollapsedControlText)
)m_cfg.pszCollapsedControlText= L"Show details";
return true;
}
bool SetConfig(const TASKDIALOGCONFIG_X* pConfig)
{ AXE_(IS(pConfig) ,return false);
m_cfg = *pConfig;
AXE_(m_cfg.cButtons <= 20 ,return false);
AXE_(m_cfg.cRadioButtons <= 20 ,return false);
AXE_(m_cfg.SzPushButtons <= 20 ,return false);
AXE_(IMPLICATES(IS((TDF_USE_COMMAND_LINKS //command link buttos ==> defined buttons
|TDF_USE_COMMAND_LINKS_NO_ICON
) & m_cfg.dwFlags)
,IS(m_cfg.cButtons)) ,return false);
if( IS (m_cfg.pszExpandedInformation)
AND NOT(m_cfg.pszExpandedControlText)
)m_cfg.pszExpandedControlText = L"Hide details";
if( IS (m_cfg.pszExpandedInformation)
AND NOT(m_cfg.pszCollapsedControlText)
)m_cfg.pszCollapsedControlText= L"Show details";
return true;
}
bool IsNavigated()const {return m_bNavigated;}
void GetDialogResult(int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked) const
{ AXE_(NOT(::IsWindow(m_hWnd)) ,if(IS(pnButton)) *pnButton =0;
if(IS(pnRadioButton))*pnRadioButton =0;
if(IS(pfVerificationFlagChecked)) *pfVerificationFlagChecked =false;
return);
if(IS(pnButton)) *pnButton = m_iButtonResult;
if(IS(pnRadioButton)) *pnRadioButton = m_iRadioResult;
if(IS(pfVerificationFlagChecked)) *pfVerificationFlagChecked= m_bVerificationResult;
}
BOOL NavigatePage(TASKDIALOGCONFIG* pTaskConfig)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
AXE_(SetConfig(pTaskConfig) ,return FALSE);
m_bNavigated = true;
// BUG: Unlike the real Task Dialog we destroy the window and recreate
// a new dialog. There will be flicker and possible reposition of window.
return EndDialog(IDCANCEL);
}
UINT GetButton(UINT uID)
{ AXE_(::IsWindow(m_hWnd) ,return 0);
bool found =false;
UINT idRes =uID;
UINT i = 0;
for( i = 0; (i < m_cfg.cButtons) AND NOT(found); i++
){if( m_cfg.pButtons[i].nButtonID == (int) uID ){idRes =(IDC_TASKDLG_CUSTOMBUTTON_FIRST + i);
found=true;
}
}
for( UINT j = 0; (j < m_cfg.SzPushButtons) AND NOT(found); j++
){if( m_cfg.PushButtons[j].nButtonID == (int) uID ){idRes =(IDC_TASKDLG_CUSTOMBUTTON_FIRST + i+j);
found=true;
}
}
return idRes;
}
BOOL ClickButton(UINT uID)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
CButton ctrl = GetDlgItem(GetButton(uID)); AXE_(IS(ctrl.IsWindow())
,return FALSE);
ctrl.Click();
return TRUE;
}
BOOL EnableButton(UINT uID, BOOL bEnable)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
CButton ctrl = GetDlgItem(GetButton(uID)); AXE_(IS(ctrl.IsWindow())
,return FALSE);
return ctrl.EnableWindow(bEnable);
}
BOOL ClickRadioButton(UINT uID)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
CButton ctrl;
for(UINT i = 0; i < m_cfg.cRadioButtons; i++
){
if(m_cfg.pRadioButtons[i].nButtonID == (int) uID
)ctrl = GetDlgItem(IDC_TASKDLG_RADIOBUTTON_FIRST +i);
} AXE_(IS(ctrl.IsWindow())
,return FALSE);
ctrl.Click();
return TRUE;
}
BOOL EnableRadioButton(UINT uID, BOOL bEnable)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
CButton ctrl;
for(UINT i = 0; i < m_cfg.cRadioButtons; i++
){
if(m_cfg.pRadioButtons[i].nButtonID == (int) uID
)ctrl = GetDlgItem(IDC_TASKDLG_RADIOBUTTON_FIRST +i);
} AXE_(IS(ctrl.IsWindow())
,return FALSE);
return ctrl.EnableWindow(bEnable);
}
BOOL ClickVerification(BOOL bChecked, BOOL bTakeFocus)
{BOOL bRes = CheckDlgButton(IDC_TASKDLG_VERIFYBUTTON
,bChecked ? BST_CHECKED : BST_UNCHECKED);
if(bRes AND bTakeFocus
)CWindow(GetDlgItem(IDC_TASKDLG_VERIFYBUTTON)).SetFocus();
return bRes;
}
BOOL SetElementText(TASKDIALOG_ELEMENTS Element, LPCWSTR pstrText)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
UINT uID = 0;
switch(Element)
{case TDE_CONTENT: uID = IDC_TASKDLG_CONTENTTEXT; break;
case TDE_MAIN_INSTRUCTION: uID = IDC_TASKDLG_INSTRUCTIONSTEXT; break;
case TDE_EXPANDED_INFORMATION: uID = IDC_TASKDLG_EXTRATEXT; break;
case TDE_FOOTER: uID = IDC_TASKDLG_FOOTERTEXT; break;
}
AXE_(IS(uID)
,return FALSE);
LPTSTR pstrBuffer = (LPTSTR)malloc(MAX_TEXT_LENGTH * sizeof(TCHAR)); AXE_(IS(pstrBuffer)
,return FALSE);
_LoadString(pstrText, pstrBuffer, MAX_TEXT_LENGTH);
SetDlgItemText(uID, pstrBuffer);
free(pstrBuffer);
// BUG: We need to reconstruct the dialog to make space for the new text
return TRUE;
}
BOOL UpdateElementText(TASKDIALOG_ELEMENTS Element, LPCWSTR pstrText)
{return SetElementText(Element, pstrText);
}
BOOL UpdateIcon(TASKDIALOG_ICON_ELEMENTS Element, LPCWSTR pstrIcon)
{ AXE_(::IsWindow(m_hWnd) ,return FALSE);
AXE_( (TDIE_ICON_FOOTER ==Element)
OR(TDIE_ICON_MAIN ==Element) ,return FALSE);
UINT nCtlId = 0;
switch(Element)
{case TDIE_ICON_FOOTER: {nCtlId = IDC_TASKDLG_FOOTERICON;
m_iconMain = _LoadIcon(pstrIcon, m_Metrics.cxyLargeIcon);
break;
}
case TDIE_ICON_MAIN: {nCtlId = IDC_TASKDLG_INSTRUCTIONSICON;
m_iconFooter = _LoadIcon(pstrIcon, m_Metrics.cxySmallIcon);
break;
}
}
CWindow wnd = GetDlgItem(nCtlId); AXE_(wnd.IsWindow()
,return FALSE);
return wnd.Invalidate();
}
BOOL SetProgressBarPos(UINT nPos)
{ AXE_(::IsWindow(GetDlgItem(IDC_TASKDLG_PROGRESSBAR)) ,return FALSE);
return SendDlgItemMessage(IDC_TASKDLG_PROGRESSBAR, PBM_SETPOS, nPos) != 0;
}
BOOL SetProgressBarRange(UINT nMin, UINT nMax)
{ AXE_(::IsWindow(GetDlgItem(IDC_TASKDLG_PROGRESSBAR)) ,return FALSE);
return SendDlgItemMessage(IDC_TASKDLG_PROGRESSBAR
,PBM_SETRANGE
,0
,MAKELPARAM(nMin, nMax)
) != 0;
}
BOOL SetProgressBarState(int nNewState)
{ AXE_(RunTimeHelper::IsVista() ,return FALSE);
AXE_(::IsWindow(GetDlgItem(IDC_TASKDLG_PROGRESSBAR)) ,return FALSE);
return SendDlgItemMessage(IDC_TASKDLG_PROGRESSBAR
,PBM_SETSTATE
,(WPARAM)nNewState
,0) != 0;
}
BOOL SetProgressBarMarquee(int iMarquee, UINT uTimer)
{ AXE_(RunTimeHelper::IsVista() ,return FALSE);
AXE_(::IsWindow(GetDlgItem(IDC_TASKDLG_PROGRESSBAR)) ,return FALSE);
CWindow wnd = GetDlgItem(IDC_TASKDLG_PROGRESSBAR); AXE_(IS(wnd.IsWindow())
,return FALSE);
return wnd.SendMessage(PBM_SETMARQUEE
,(WPARAM) iMarquee
,uTimer
) != 0;
}
void SetMarqueeProgressBar(BOOL bMarquee)
{ AXE_(RunTimeHelper::IsVista() ,return);
AXE_(::IsWindow(GetDlgItem(IDC_TASKDLG_PROGRESSBAR)) ,return);
CWindow wnd = GetDlgItem(IDC_TASKDLG_PROGRESSBAR); AXE_(IS(wnd.IsWindow())
,return);
wnd.ModifyStyle(bMarquee ?0
:PBS_MARQUEE
,bMarquee ?PBS_MARQUEE
:0
);
SetProgressBarMarquee(1, 30);
}
// Default TaskDialogEmu callback implementation
static HRESULT CALLBACK TaskDialogCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
{ AXE_(lpRefData!=0 ,E_Implementation);
DERIVED* dThis = (DERIVED*) lpRefData;
ATLASSERT(hwnd==dThis->m_hWnd); hwnd;
HRESULT bRet = Ok;
switch( msg )
{case TDN_DIALOG_CONSTRUCTED: {dThis->OnDialogConstructed(); break;}
case TDN_CREATED: {dThis->OnCreated(); break;}
case TDN_BUTTON_CLICKED: {bRet = dThis->OnButtonClicked((int) wParam); break;}
case TDN_RADIO_BUTTON_CLICKED: {dThis->OnRadioButtonClicked((int) wParam); break;}
case TDN_HYPERLINK_CLICKED: {dThis->OnHyperlinkClicked((LPCWSTR) lParam); break;}
case TDN_EXPANDO_BUTTON_CLICKED:{dThis->OnExpandoButtonClicked(wParam != 0); break;}
case TDN_VERIFICATION_CLICKED: {dThis->OnVerificationClicked(wParam != 0); break;}
case TDN_HELP: {dThis->OnHelp(); break;}
case TDN_TIMER: {bRet = dThis->OnTimer((DWORD) wParam); break;}
case TDN_NAVIGATED: {dThis->OnNavigated(); break;}
case TDN_DESTROYED: {dThis->OnDestroyed(); break;}
default: { AE(false
,_T("known: msg"));
LOGVALDWD(_T("TDL CallBack Notification")
,_T("unknown")
,msg); break;
}
}
return (HRESULT)bRet; //depends form th specific handler
}
// Overrideables - notification handlers
void OnDialogConstructed (){}
void OnCreated (){}
BOOL OnButtonClicked (int /*nButton*/){return FALSE;} // don't prevent dialog to close
void OnRadioButtonClicked (int /*nRadioButton*/){}
void OnHyperlinkClicked (LPCWSTR /*pszHREF*/){}
void OnExpandoButtonClicked(bool /*bExpanded*/){}
void OnVerificationClicked (bool /*bChecked*/){}
void OnHelp (){}
BOOL OnTimer (DWORD /*dwTickCount*/){return FALSE;} // don't reset counter
void OnNavigated (){}
void OnDestroyed (){}
public: // Data Members
TASKDIALOGCONFIG_X m_cfg; // Copy of configuration
bool m_bNavigated; // Dialog was navigated?
int m_iButtonResult; // Button result
int m_iRadioResult; // Radio-button result
BOOL m_bVerificationResult; // Verification button result
DWORD m_dwTick; // Start tick when dialog was shown
UINT m_nDefCtlId; // Default dialog button
UINT m_nHoverId; // Current hover Command Link button ID
DLUSize m_sizeDialog; // Recommended dialog size (in pixels)
CFont m_fontTitle; // Title font
CFont m_fontText; // Text font
CBrush m_brWhite; // Brush for white (top) background
CBrush m_brGrey; // Brush for grey (bottom) background
CIcon m_iconMain; // Icon in Main Instructions text
CIcon m_iconFooter; // Icon in Footer text
CIcon m_iconArrowNormal; // Command Link arrow
CIcon m_iconArrowHot; // Command Link arrow (hot)
CIcon m_iconChevronLess; // Chevron icon (less)
CIcon m_iconChevronMore; // Chevron icon (more)
bool m_bCreated; // Dialog fully initialized yet?
bool m_bExpanded; // Expando-area is expanded?
bool m_bHasCustomLinks; // Has custom Command Link buttons?
bool ShowExpanderIcon; ///< as it says.
struct Metrics {void init(Tp& dlg, CFont& m_fontText,HWND hwndParent)
{bool bIsCommCtrl6 = RunTimeHelper::IsCommCtrl6();
szCharTtl =DLUSize(4,8)/*DLU*/;
szChar =DLUSize(4,8)/*DLU*/;
RectDlg = DLURect();
dlg.InitDialogBaseUnits(dlg.m_fontText, hwndParent);
szCharTtl =PixSize(dlg.GetDialogBaseUnits().cx
,dlg.GetDialogBaseUnits().cy);
dlg.InitDialogBaseUnits(dlg.m_fontText, hwndParent);
BaseUnit = dlg.GetDialogBaseUnits();
ActBaseUnit::val() =BaseUnit;
szChar =BaseUnit;
RectDlgWork = DLURect();
sizeDialogPadding = DLUSize(szChar.cx *2//freier rand
,szChar.cy *1
);
cxySmallIcon = PixSize(::GetSystemMetrics(SM_CYSMICON)
,::GetSystemMetrics(SM_CYSMICON)
);
cxyLargeIcon = PixSize(::GetSystemMetrics(SM_CYICON)
,::GetSystemMetrics(SM_CYICON)
);
cxSmallIconGap = DLUSize(szChar.cx * 3 / 2
,0
);
RectTop = DLURect();
clrBkTop = ::GetSysColor((true || bIsCommCtrl6) ? COLOR_WINDOW : COLOR_BTNFACE);
RectIconMain = DLURect();
cyInstructionsGapTop = yDlu(szChar.cy * 1// / 5
);
RectContent = DLURect();
cxLargeIconGap = DLUSize(szChar.cx * 3 / 2
,0
);
RectTextMain = DLURect();
cxBestMainInstruction.n = szChar.cx * 10; //70 zeichen
//clrTitleText = bIsCommCtrl6 ? RGB(0,51,153) : ::GetSysColor(COLOR_BTNTEXT);
clrTitleText = RGB(0,51,153);
makeTxtColFromBackground(clrTitleText,clrBkTop);
RectTextSub = DLURect();
cyInstructionsGap = yDlu(szChar.cy * 1);// / 5;
cxBestContent = xDlu(szChar.cx * 10//10 zeichen weniger ls msg main
);
cyContentGap = yDlu(szChar.cy * 1 / 2
);
RectExpoInside = DLURect();
RectProgress = DLURect();
cyProgressBar = yDlu(szChar.cy * 1);
cxBestProgressBar = xDlu(szChar.cx * 25//55 zeichen lang
);
RectRadio = DLURect();
cxRadioIndent = xDlu(szChar.cx * 2// / 2;
);
sizeRadioButton.cx = ::GetSystemMetrics(SM_CXMENUCHECK) + 6;
sizeRadioButton.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
cxBestRadioButton = xDlu(szChar.cx * 50);
cyRadioGap = yDlu(szChar.cy * 0);//2;
RectCommand = DLURect();
cxyArrowIcon = PixSize(20,20);
cxMinCommandLink = xDlu(szChar.cx * 60);
cxBestCommandLink = xDlu(szChar.cx * 70);
sizeLinkPadding.cx = szChar.cx * 2;
sizeLinkPadding.cy = szChar.cy / 2;
clrCommandLinkText = ::GetSysColor(COLOR_BTNTEXT);
clrCommandLinkTextSelected= bIsCommCtrl6 ? RGB(0,51,153) : ::GetSysColor(COLOR_BTNTEXT);
clrCmdLinkSelect = bIsCommCtrl6 ? RGB(140,232,255) : RGB(140,140,140);
makeTxtColFromBackground(clrCmdLinkSelect,clrBkTop);
clrBkCommandSelect = ::GetSysColor(COLOR_BTNFACE);//RGB(0xf0,0xf0,0xf0);
DWORD c1=0x00ff0000 & clrBkCommandSelect;
c1=c1+3*((0x00ff0000-c1)/4);
DWORD c2=0x0000ff00 & clrBkCommandSelect;
c2=c2+3*((0x0000ff00-c2)/4);
DWORD c3=0x000000ff & clrBkCommandSelect;
c3=c3+2*((0x000000ff-c3)/3);
clrBkCommandSelect =c1|c2|c3,
RectBottom = DLURect();
clrDividerLight = ::GetSysColor(COLOR_BTNSHADOW);
if( IS(VersWin().asString().Find(_T("Windows 7"))+1)
OR IS(VersWin().asString().Find(_T("Windows Server 2008"))+1)
) clrBkBottom = clrBkTop;
else clrBkBottom = ::GetSysColor(COLOR_BTNFACE);
RectBottomContent = DLURect();
cyBottomGap = yDlu(szChar.cy *1);
RectButtonRow = DLURect();
RectExpoRow = DLURect();
RectExpoBtn = DLURect();
cxyExpanderIcon = PixSize(20,20);
RectExpoText = DLURect();
RectCheck = DLURect();
cxMaxVerification = xDlu(szChar.cx * 40);
/*RectExpoRow*/RectBtns= DLURect();
cxButtonsIndent = xDlu(szChar.cx * 8);
cxMinButton = xDlu(szChar.cx * 8); //
sizeButtonPadding.cx = szChar.cx * 1; //immer ingesamt zu ganzen dlus
sizeButtonPadding.cy = szChar.cy * 1/2;
cxButtonGap = xDlu(szChar.cx * 1);
RectFooter = DLURect();
cyExpanderGap = yDlu(szChar.cy / 1);//3;
cyButtonLineGap = yDlu(szChar.cy * 1);//2 / 3;//if RectButtonRow.cy
RectIconFooter = DLURect();
RectFooterText = DLURect();
RectExpoOutside = DLURect();
cyFooterGap = yDlu(szChar.cy / 1);//3; //if footertext.cy
RectExpoOutsideText = DLURect();
}
void reInitColors()
{bool bIsCommCtrl6 = RunTimeHelper::IsCommCtrl6();
clrBkTop = ::GetSysColor((true || bIsCommCtrl6) ? COLOR_WINDOW : COLOR_BTNFACE);
//clrTitleText = bIsCommCtrl6 ? RGB(0,51,153) : ::GetSysColor(COLOR_BTNTEXT);
clrTitleText = RGB(0,51,153);
makeTxtColFromBackground(clrTitleText,clrBkTop);
clrCmdLinkSelect = bIsCommCtrl6 ? RGB(140,232,255) : RGB(140,140,140);
makeTxtColFromBackground(clrCmdLinkSelect,clrBkTop);
if( IS(VersWin().asString().Find(_T("Windows 7"))+1)
OR IS(VersWin().asString().Find(_T("Windows Server 2008"))+1)
) clrBkBottom = clrBkTop;
else clrBkBottom = ::GetSysColor(COLOR_BTNFACE);
}
//Dlg
DLUSize szCharTtl;
DLUSize szChar;
DLURect RectDlg; //complete client rect
DLURect RectDlgWork; //working rect: leaving blank a border arround
DLUSize sizeDialogPadding;
DLUSize cxySmallIcon;
DLUSize cxyLargeIcon;
DLUSize cxLargeIconGap;
DLUSize cxSmallIconGap;
PixSize BaseUnit;
CLogFont LFMsgBox;
DLURect RectTop; //der main bereich
COLORREF clrBkTop;
DLURect RectIconMain;
yDlu cyInstructionsGapTop;//if iconmain.cy
DLURect RectContent; //bereich rechts vom main.icon für alles von oben bis ausschließlich der buttonregion
DLURect RectTextMain; //bereich rechts vom main.icon für alles von oben bis ausschließlich der buttonregion
xDlu cxBestMainInstruction;
COLORREF clrTitleText;
DLURect RectTextSub; //bereich rechts vom main.icon für alles von oben bis ausschließlich der buttonregion
yDlu cyInstructionsGap;//if textmain.cy
xDlu cxBestContent;
yDlu cyContentGap;//before next section after min or sub if something followes
DLURect RectExpoInside;
DLURect RectProgress;
yDlu cyProgressBar;
xDlu cxBestProgressBar;
DLURect RectRadio;
xDlu cxRadioIndent;
xDlu cxBestRadioButton;
DLUSize sizeRadioButton;
yDlu cyRadioGap;
DLURect RectCommand;
DLUSize cxyArrowIcon;
xDlu cxMinCommandLink;
xDlu cxBestCommandLink;
DLUSize sizeLinkPadding;
COLORREF clrCommandLinkText;
COLORREF clrCommandLinkTextSelected;
COLORREF clrBkCommandSelect;
COLORREF clrCmdLinkSelect;
DLURect RectBottom; //Bereich für alles was mit den push buttons oder expander titel beginnt
COLORREF clrDividerLight;
COLORREF clrBkBottom;
DLURect RectBottomContent; yDlu cyBottomGap; //if IS(RectContent.cx) ^RectContent.cy>RectIconMain.cy
DLURect RectButtonRow;
DLURect RectExpoRow;/**/
DLURect RectExpoBtn; DLURect RectExpoText;
DLUSize cxyExpanderIcon;
DLURect RectCheck;/**/
xDlu cxMaxVerification;
/**/DLURect RectBtns;
xDlu cxButtonsIndent;//separates from left dlg border or from expo row
xDlu cxMinButton;
DLUSize sizeButtonPadding;
xDlu cxButtonGap;
DLURect RectFooter;
yDlu cyExpanderGap;//if exorow.cy
yDlu cyButtonLineGap;//if buttonrow.cy
DLURect RectIconFooter;
DLURect RectFooterText;
DLURect RectExpoOutside; yDlu cyFooterGap;
DLURect RectExpoOutsideText;
}m_Metrics;
#define RectDlg m_Metrics.RectDlg
#define RectDlgWork m_Metrics.RectDlgWork
#define RectIconMain m_Metrics.RectIconMain
#define RectTop m_Metrics.RectTop
#define RectContent m_Metrics.RectContent
#define RectTextMain m_Metrics.RectTextMain
#define RectTextSub m_Metrics.RectTextSub
#define RectBottom m_Metrics.RectBottom
#define RectExpoInside m_Metrics.RectExpoInside
#define RectExpoOutside m_Metrics.RectExpoOutside
#define RectProgress m_Metrics.RectProgress
#define RectRadio m_Metrics.RectRadio
#define RectCommand m_Metrics.RectCommand
#define RectBottomContent m_Metrics.RectBottomContent
#define RectExpoRow m_Metrics.RectExpoRow
#define RectExpoBtn m_Metrics.RectExpoBtn
#define RectExpoText m_Metrics.RectExpoText
#define RectCheck m_Metrics.RectCheck
#define RectBtns m_Metrics.RectBtns
#define RectButtonRow m_Metrics.RectButtonRow
#define RectFooter m_Metrics.RectFooter
#define RectIconFooter m_Metrics.RectIconFooter
#define RectFooterText m_Metrics.RectFooterText
#define RectExpoOutsideText m_Metrics.RectExpoOutsideText
public: // Construction
void DoInitTemplate ()
{
m_Template.Reset();
AtlInitCommonControls(ICC_STANDARD_CLASSES
|ICC_ANIMATE_CLASS
|ICC_BAR_CLASSES
|ICC_COOL_CLASSES
|ICC_DATE_CLASSES
|ICC_HOTKEY_CLASS
|ICC_INTERNET_CLASSES
|ICC_LINK_CLASS
|ICC_LISTVIEW_CLASSES
|ICC_NATIVEFNTCTL_CLASS
|ICC_PAGESCROLLER_CLASS
|ICC_PROGRESS_CLASS
|ICC_TAB_CLASSES
|ICC_TREEVIEW_CLASSES
|ICC_UPDOWN_CLASS
|ICC_USEREX_CLASSES
);
bool bIsCommCtrl6 = RunTimeHelper::IsCommCtrl6();
CWindowDC dc = HWND_DESKTOP;
if( NOT(m_fontTitle.IsNull()) ) m_fontTitle.DeleteObject();
if( NOT(m_fontText.IsNull()) ) m_fontText.DeleteObject();
m_Metrics.LFMsgBox.SetMessageBoxFont();
m_fontText.CreateFontIndirect(&m_Metrics.LFMsgBox);
CLogFont lfTitle = m_Metrics.LFMsgBox;
lfTitle.MakeLarger(bIsCommCtrl6 ? 4 : 2);
lfTitle.MakeBolder(bIsCommCtrl6 ? 0 : 1);
m_fontTitle.CreateFontIndirect(&lfTitle);
m_Metrics.init(*this,m_fontText,m_cfg.hwndParent);
if( NOT(m_brWhite.IsNull()) ) m_brWhite.DeleteObject();
if( NOT(m_brGrey.IsNull()) ) m_brGrey.DeleteObject();
m_brWhite.CreateSolidBrush(m_Metrics.clrBkTop);
m_brGrey .CreateSolidBrush(m_Metrics.clrBkBottom);
// Determine size of dialog. First try to determine the optimal width of
// the dialog. Then calculate the height of the dialog based on that width.
const xDlu CX_MIN_DIALOG(m_Metrics.szChar.cy * 30);
m_sizeDialog = _LayoutControls(((m_cfg.cxWidth > 0) ?xDlu(m_cfg.cxWidth)
:xDlu(WIDTH_PROBE))
,false);
if( m_sizeDialog.cx < CX_MIN_DIALOG.n
) m_sizeDialog.cx = CX_MIN_DIALOG.n;
if( m_cfg.cxWidth > 0
) m_sizeDialog.cx = m_cfg.cxWidth;//stay in DLU//MapDialogUnitsX(m_cfg.cxWidth);
xDlu cxWidth = m_sizeDialog;
m_sizeDialog = _LayoutControls(cxWidth, false);
m_sizeDialog.cx = cxWidth.n;
if( NOT(m_cfg.dwCommonButtons)
AND NOT(m_cfg.cButtons)
AND NOT(m_cfg.SzPushButtons)
) m_cfg.dwCommonButtons = TDCBF_CLOSE_BUTTON; //at least one Closing Btn should be avail
if( IS(TDCBF_CANCEL_BUTTON & m_cfg.dwCommonButtons) //cancel button consitsently should also alolow ESC cancelation
) m_cfg.dwFlags |= TDF_ALLOW_DIALOG_CANCELLATION;
DWORD dwHelpID = 0;
DWORD dwExStyle = 0;
DWORD dwStyle = WS_POPUP
| WS_CAPTION
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| DS_MODALFRAME
| DS_ABSALIGN //tells the coordinates are screen instead of client coordinates
| WS_POPUP
//| DS_SETFOREGROUND
;
if( IS (TDF_CAN_BE_MINIMIZED & m_cfg.dwFlags)) dwStyle |= WS_MINIMIZEBOX;
if( IS (TDF_ALLOW_DIALOG_CANCELLATION & m_cfg.dwFlags)) dwStyle |= WS_SYSMENU;
/*if( NOT(TDF_POSITION_RELATIVE_TO_WINDOW& m_cfg.dwFlags))*/ dwStyle |= DS_CENTER;
if( IS (TDF_RTL_LAYOUT & m_cfg.dwFlags)) dwExStyle|= WS_EX_LAYOUTRTL | WS_EX_RIGHT;
TCHAR szCaption[120] = { 0 };
_LoadString(m_cfg.pszWindowTitle, szCaption, sizeof(szCaption) / sizeof(TCHAR));
WORD lfHeight = (WORD) m_Metrics.LFMsgBox.lfHeight;
if(m_Metrics.LFMsgBox.lfHeight < 0
)lfHeight = (WORD) (-MulDiv(72, m_Metrics.LFMsgBox.lfHeight, GetDeviceCaps(dc, LOGPIXELSY)));
//SIZE dluDialog = MapDialogPixels(m_sizeDialog);
//DLURect rc = _CenterDialog(dluDialog);
DLURect rc = _CenterDialog(m_sizeDialog);
doCreateTemplate ( true, szCaption
, xDlu(rc.left)
, yDlu(rc.top)
, xDlu(m_sizeDialog.cx)
, yDlu(m_sizeDialog.cy)
, dwStyle
, dwExStyle
, m_Metrics.LFMsgBox.lfFaceName
, lfHeight
, (WORD) m_Metrics.LFMsgBox.lfWeight
, m_Metrics.LFMsgBox.lfItalic
, m_Metrics.LFMsgBox.lfCharSet
, dwHelpID
);
}
void doCreateTemplate( bool bDlgEx
, LPCTSTR lpszCaption
, xDlu nX
, yDlu nY
, xDlu nWidth
, yDlu nHeight
, DWORD dwStyle = 0
, DWORD dwExStyle = 0
, LPCTSTR lpstrFontName = NULL
, WORD wFontSize = 0
, WORD wWeight = 0
, BYTE bItalic = 0
, BYTE bCharset = 0
, DWORD dwHelpID = 0
, ATL::_U_STRINGorID ClassName = 0U
, ATL::_U_STRINGorID Menu = 0U
){
m_Template.Create( true
, lpszCaption
, (short) nX.n
, (short) nY.n
, (short) nWidth.n
, (short) nHeight.n
, dwStyle
, dwExStyle
, lpstrFontName
, wFontSize
, wWeight
, bItalic
, bCharset
, dwHelpID
);
}
void DoInitControls ()
{_LayoutControls(m_sizeDialog, true);
}
// Message handler
LRESULT OnWmInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
ATBD(_T("accept also callbacks. {Not accepting callbacks at this moment...}"));
m_bCreated = false;
_Reset();
// Font assignment
SendMessageToDescendants(WM_SETFONT, (WPARAM) static_cast<HFONT>(m_fontText));
SendDlgItemMessage(IDC_TASKDLG_INSTRUCTIONSTEXT, WM_SETFONT, (WPARAM) (HFONT) m_fontTitle);
// Create a timer?
if( m_bHasCustomLinks ) SetTimer(TIMERID_HOVERLINK, 100);
if(IS(TDF_CALLBACK_TIMER & m_cfg.dwFlags)) SetTimer(TIMERID_TIGGER , 200);
// Set verification checkmark
if(IS(TDF_VERIFICATION_FLAG_CHECKED & m_cfg.dwFlags)) CheckDlgButton(IDC_TASKDLG_VERIFYBUTTON, BST_CHECKED);
// Set Marquee Progress Bar
if(IS(TDF_SHOW_MARQUEE_PROGRESS_BAR & m_cfg.dwFlags)) SetMarqueeProgressBar(TRUE);
// Set default radio button (may be first button)
if( NOT(TDF_NO_DEFAULT_RADIO_BUTTON & m_cfg.dwFlags)
AND (m_cfg.cRadioButtons > 0)
){
CButton ctrl;
for( UINT n = 0
; NOT(ctrl.IsWindow())
AND(n < m_cfg.cRadioButtons)
; n++
){
if( m_cfg.nDefaultRadioButton == m_cfg.pRadioButtons[n].nButtonID
) ctrl = GetDlgItem(IDC_TASKDLG_RADIOBUTTON_FIRST + n);
}
if( NOT(ctrl.IsWindow()) ) ctrl = GetDlgItem(IDC_TASKDLG_RADIOBUTTON_FIRST);
if( ctrl.IsWindow() ) ctrl.Click();
}
// Clear arrow image on lines?
if( NOT(m_bHasCustomLinks)
AND IS (TDF_USE_COMMAND_LINKS_NO_ICON & m_cfg.dwFlags)
) {
for( UINT n = 0; n < m_cfg.cButtons; n++
){
CButton ctrl = GetDlgItem(IDC_TASKDLG_CUSTOMBUTTON_FIRST + n);
BUTTON_IMAGELIST bil= { (HIMAGELIST) -1, 0 };
ctrl.SendMessage(BCM_SETIMAGELIST, 0, (LPARAM) &bil);
}
}
// Set expansion level
if( IS(m_cfg.pszExpandedInformation)
AND NOT(TDF_EXPANDED_BY_DEFAULT & m_cfg.dwFlags)
)SendMessage(WM_COMMAND, MAKEWPARAM(IDC_TASKDLG_EXPANDERICON, STN_CLICKED));
// Set default dialog button
if( (m_nDefCtlId > 0)
AND(m_nDefCtlId != (UINT) -1)
){
SendMessage(DM_SETDEFID, m_nDefCtlId);
CWindow(GetDlgItem(m_nDefCtlId)).SetFocus();
}
// Get icons...
m_iconMain = (HICON) (IS(TDF_USE_HICON_MAIN & m_cfg.dwFlags)
? m_cfg.hMainIcon
: _LoadIcon(m_cfg.pszMainIcon, m_Metrics.cxyLargeIcon));
m_iconFooter = (HICON) (IS(TDF_USE_HICON_FOOTER & m_cfg.dwFlags)
? m_cfg.hFooterIcon
: _LoadIcon(m_cfg.pszFooterIcon, m_Metrics.cxySmallIcon));
m_iconArrowHot = _LoadIcon(makeIntResourceW(IDI_TASKDLG_ARROW_HOT) , 20);
m_iconArrowNormal = _LoadIcon(makeIntResourceW(IDI_TASKDLG_ARROW_NORMAL), 20);
m_iconChevronLess = _LoadIcon(makeIntResourceW(IDI_TASKDLG_CHEVRON_LESS), 20);
m_iconChevronMore = _LoadIcon(makeIntResourceW(IDI_TASKDLG_CHEVRON_MORE), 20);
if( NOT(m_iconMain.IsNull())
AND NOT(GetParent())
) SetIcon(m_iconMain, FALSE);
// Play that funky music...
_PlaySound();
// Ready to accept user input.
m_bCreated = true;
// Send inital callback messages.
_DoCallback(TDN_DIALOG_CONSTRUCTED);
_DoCallback(m_bNavigated ? TDN_NAVIGATED : TDN_CREATED);
m_bNavigated = false;
return 0;
}
LRESULT OnWmDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
KillTimer(TIMERID_TIGGER);
KillTimer(TIMERID_HOVERLINK);
_DoCallback(TDN_DESTROYED);
m_bVerificationResult = IsDlgButtonChecked(IDC_TASKDLG_VERIFYBUTTON);
bHandled = FALSE;
return 0;
}
LRESULT OnWmHelp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
_DoCallback(TDN_HELP);
return 0;
}
LRESULT OnWmTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(TIMERID_TIGGER == wParam
){
BOOL bReset = (BOOL) _DoCallback(TDN_TIMER, ::GetTickCount() - m_dwTick);
if( bReset
) m_dwTick = ::GetTickCount();
}
if(TIMERID_HOVERLINK == wParam
){
POINT pt = { 0 };
::GetCursorPos(&pt);
ScreenToClient(&pt);
UINT nHoverId = 0;
HWND hWnd = ::ChildWindowFromPoint(m_hWnd, pt);
if( hWnd != NULL
){
UINT nCtlId = ::GetDlgCtrlID(hWnd);
if( (nCtlId >= IDC_TASKDLG_CUSTOMBUTTON_FIRST)
AND(nCtlId <= IDC_TASKDLG_CUSTOMBUTTON_LAST)
)nHoverId = nCtlId;
}
if(m_nHoverId != nHoverId
){
if(IS(m_nHoverId)
)CWindow(GetDlgItem(m_nHoverId)).Invalidate();
m_nHoverId = nHoverId;
if(IS(m_nHoverId)
)CWindow(GetDlgItem(m_nHoverId)).Invalidate();
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnWmEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
m_Metrics.reInitColors();
DLUSize rcOffset=RectExpoInside.size();
rcOffset.cx=0;
bool adapt = IS(RectExpoInside.size().cy)
AND NOT(m_bExpanded);
CClientDC dc = m_hWnd;
PixRect rcClient;
GetClientRect(&rcClient);
PixRect rDlg;rDlg =RectDlg;
PixRect rcWin;GetWindowRect(&rcWin);
PixSize szWin=rcWin.size();
PixSize szDlg=rDlg.size();
PixSize szCli=rcClient.size();
PixRect rcTop =rcClient;
rcTop.bottom =RectTop.pix().bottom;//{ 0, 0 , rcClient.right, m_Metrics.iButtonLinePos };
if(adapt)rcTop.bottom -=(rcOffset.pix().cy +m_Metrics.szChar.pix().cy);
dc.FillSolidRect(&rcTop, m_Metrics.clrBkTop);
PixRect rcBottom =rcClient;
rcBottom.top =RectBottom.pix().top;//{ 0, m_Metrics.iButtonLinePos, rcClient.right, rcClient.bottom };
if(adapt)rcBottom.top -=(rcOffset.pix().cy +m_Metrics.szChar.pix().cy);
dc.FillSolidRect(&rcBottom, m_Metrics.clrBkBottom);
if(false)
{LONG ctop(RGB(0xff,0xff,0x77));
LONG cbot(RGB(0xbb,0xbb,0xff));
PixRect rctmp;
rctmp=RectTop;
dc.FillSolidRect(&rctmp, ctop);
rctmp=RectBottom;
dc.FillSolidRect(&rctmp, cbot);
ctop=(RGB(0xff,0xff,0x88));
cbot=(RGB(0xcc,0xcc,0xff));
rctmp=RectContent;
dc.FillSolidRect(&rctmp, ctop);
rctmp=RectBottomContent;
dc.FillSolidRect(&rctmp, cbot);
ctop=(RGB(0xff,0xff,0x99));
rctmp=RectTextMain;
dc.FillSolidRect(&rctmp, ctop);
ctop=(RGB(0xff,0xfe,0x99));
rctmp=RectBottomContent;
dc.FillSolidRect(&rctmp, cbot);
ctop=(RGB(0xff,0xfd,0x99));
rctmp=RectTextSub;
dc.FillSolidRect(&rctmp, cbot);
ctop=(RGB(0xff,0xfc,0x99));
rctmp=RectExpoInside;
dc.FillSolidRect(&rctmp, cbot);
cbot=(RGB(0xdd,0xdd,0xff));
}
bool doGrid=false;
#ifdef TESTSETCONTEXTTONOTDEFINEATNORMAL
doGrid=true;
#else
doGrid =false;
#endif
if(doGrid)
{
//draw dlu grd:
PixRect pil;PixRect pitrc;
DWORD clrGrid =RGB(0xff,0,0) BIT_XOR ((m_Metrics.clrBkTop BIT_XOR m_Metrics.clrBkBottom));
dc.SetTextColor(clrGrid);
dc.SetBkMode(TRANSPARENT);
PixSize basU =ActBaseUnit().val();
CString n=_T("0");
DLURect clientDlu;clientDlu =rcClient;
DLURect l;l.top =0;
for(int z=0;l.top<clientDlu.bottom;)
{
l.bottom=l.top+1;
l.left=0;l.right =rcClient.right;
PixRect pil;pil=l;
dc.FillSolidRect(&pil, clrGrid);
DLURect trc;trc.left=0;
trc.right =l.right;
trc.top=l.top;
trc.bottom=trc.top+1;
// _AlignDLU(trc.bottom, HTBOTTOM);
PixRect pitrc;pitrc=trc;
dc.DrawText(n, 1, &pitrc, DT_WORDBREAK);
trc.left=l.right -basU.cx;
pitrc=trc;
// _AlignDLU(trc.left, HTRIGHT);
dc.DrawText(n, 1, &pitrc, DT_WORDBREAK);
if(z>0xf)z=0;
else z++;
n.Format(_T("%x"),Vx_(z));
l.top+=8/2;
//_AlignDLU(l.top, HTBOTTOM);
}
l.left =0;
for(int z=0;l.left<rcClient.right;)
{
l.right=l.left+1;
l.top=0;l.bottom =rcClient.bottom;
pil=l;
dc.FillSolidRect(&pil, clrGrid);
RECT trc;trc.top=0;
trc.bottom =l.bottom;
trc.left=l.left;
trc.right=trc.left+1;
pitrc=trc;
//_AlignDLU(trc.right, HTRIGHT);
dc.DrawText(n, 1, &pitrc, DT_WORDBREAK);
trc.top=l.bottom -8;
//_AlignDLU(trc.top, HTBOTTOM);
dc.DrawText(n, 1, &pitrc, DT_WORDBREAK);
if(z>0xf)z=0;
else z++;
n.Format(_T("%x"),Vx_(z));
l.left+=4/2;
//_AlignDLU(l.left, HTRIGHT);
}
}
return 1;
}
LRESULT OnWmCtlColor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
m_Metrics.reInitColors();
LRESULT lRes = DefWindowProc();
UINT nCtlID = ::GetDlgCtrlID((HWND) lParam);
CDCHandle dc = (HDC) wParam;
switch( nCtlID )
{
case IDC_TASKDLG_INSTRUCTIONSICON: {dc.SetBkMode(TRANSPARENT);
dc.SetBkColor(m_Metrics.clrBkTop);
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
break;
}
case IDC_TASKDLG_INSTRUCTIONSTEXT: {dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(m_Metrics.clrTitleText);
dc.SetBkColor(m_Metrics.clrBkTop);
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
break;
}
case IDC_TASKDLG_CONTENTTEXT: {dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
dc.SetBkColor(m_Metrics.clrBkTop);
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
break;
}
case IDC_TASKDLG_FOOTERICON:
case IDC_TASKDLG_FOOTERTEXT:
case IDC_TASKDLG_EXPANDERICON:
case IDC_TASKDLG_EXPANDERTEXT:
case IDC_TASKDLG_VERIFYBUTTON: {dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
dc.SetBkColor(m_Metrics.clrBkBottom);
lRes = (LRESULT) static_cast<HBRUSH>(m_brGrey);
break;
}
case IDC_TASKDLG_OK:
case IDC_TASKDLG_NO:
case IDC_TASKDLG_YES:
case IDC_TASKDLG_RETRY:
case IDC_TASKDLG_CLOSE:
case IDC_TASKDLG_CANCEL: {dc.SetBkMode(TRANSPARENT);
//dc.SetBkColor(m_Metrics.clrBkBottom);
lRes = (LRESULT) static_cast<HBRUSH>(m_brGrey);
break;
}
default: {dc.SetBkMode(TRANSPARENT);
COLORREF clrBack;
if( (nCtlID >= IDC_TASKDLG_RADIOBUTTON_FIRST)
AND(nCtlID <= IDC_TASKDLG_RADIOBUTTON_LAST)
) {
clrBack = m_Metrics.clrBkTop;
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
}
else if( (nCtlID >= IDC_TASKDLG_CUSTOMBUTTON_FIRST)
AND(nCtlID <= IDC_TASKDLG_CUSTOMBUTTON_LAST)
AND IS((TDF_USE_COMMAND_LINKS
|TDF_USE_COMMAND_LINKS_NO_ICON
)& m_cfg.dwFlags)
) {
clrBack = m_Metrics.clrBkTop;
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
}
else if( (IDC_TASKDLG_EXTRATEXT ==nCtlID)
AND NOT(TDF_EXPAND_FOOTER_AREA & m_cfg.dwFlags)
) {
clrBack = m_Metrics.clrBkTop;
lRes = (LRESULT) static_cast<HBRUSH>(m_brWhite);
}
else{
clrBack = m_Metrics.clrBkBottom;
lRes = (LRESULT) static_cast<HBRUSH>(m_brGrey);
}
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkMode(TRANSPARENT);
dc.SetBkColor(clrBack);
}
}
return lRes;
}
LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if( wParam == SC_CLOSE
){
if( NOT(TDF_ALLOW_DIALOG_CANCELLATION & m_cfg.dwFlags)
) return 0;
}
bHandled = FALSE;
return 0;
}
LRESULT OnWmDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
m_Metrics.reInitColors();
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam;
if( m_bHasCustomLinks
AND(lpDIS->CtlID >= IDC_TASKDLG_CUSTOMBUTTON_FIRST)
AND(lpDIS->CtlID <= IDC_TASKDLG_CUSTOMBUTTON_LAST )
){
_CustomDrawCommandLink(lpDIS);
return 0;
}
if(lpDIS->CtlID == IDC_TASKDLG_INSTRUCTIONSICON
){
_CustomDrawIcon(lpDIS, m_Metrics.clrBkTop, m_iconMain, m_Metrics.cxyLargeIcon);
return 0;
}
if(lpDIS->CtlID == IDC_TASKDLG_FOOTERICON
){
_CustomDrawIcon(lpDIS, m_Metrics.clrBkBottom, m_iconFooter, m_Metrics.cxySmallIcon);
return 0;
}
if(lpDIS->CtlID == IDC_TASKDLG_EXPANDERICON
){
if(ShowExpanderIcon
){
_CustomDrawIcon(lpDIS, m_Metrics.clrBkBottom
, m_bExpanded ? m_iconChevronLess
: m_iconChevronMore
, m_Metrics.cxyExpanderIcon);
}
return 0;
}
if(lpDIS->CtlID == IDC_TASKDLG_FOOTERDIVIDER
){
_CustomDrawDivider(lpDIS);
return 0;
}
bHandled = FALSE;
return 0;
}
// TaskDialogEmu API messages
LRESULT OnMsgClickButton(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
ClickButton((int)wParam);
return 0;
}
LRESULT OnMsgClickRadioButton(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
ClickRadioButton((int)wParam);
return 0;
}
LRESULT OnMsgClickVerification(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
ClickVerification((BOOL) wParam, (BOOL) lParam);
return 0;
}
LRESULT OnMsgEnableButton(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return (LRESULT) EnableButton((int)wParam, (BOOL) lParam);
}
LRESULT OnMsgEnableRadioButton(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return (LRESULT) EnableRadioButton((int)wParam, (BOOL) lParam);
}
LRESULT OnMsgSetElementText(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return (LRESULT) SetElementText((TASKDIALOG_ELEMENTS) wParam, (LPCWSTR) lParam);
}
LRESULT OnMsgUpdateElementText(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return (LRESULT) UpdateElementText((TASKDIALOG_ELEMENTS) wParam, (LPCWSTR) lParam);
}
LRESULT OnMsgSetProgressBarPos(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
SetProgressBarPos((UINT)wParam);
return 0;
}
LRESULT OnMsgSetProgressBarRange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
SetProgressBarRange(LOWORD(lParam), HIWORD(lParam));
return 0;
}
LRESULT OnMsgSetMarqueeProgressBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
SetMarqueeProgressBar((BOOL) wParam);
return 0;
}
LRESULT OnMsgSetProgressBarState(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return (LRESULT) SetProgressBarState((int) wParam);
}
LRESULT OnMsgSetProgressBarMarquee(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return (LRESULT) SetProgressBarMarquee((int)wParam, (UINT)lParam);
}
// Command message handlers
LRESULT OnMsgCommonButtonClick(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
UINT nBtnID = wID;
if( _DoCallback(TDN_BUTTON_CLICKED, nBtnID) == S_FALSE
) return 0;
m_iButtonResult = (int) nBtnID;
EndDialog(wID);
return 0;
}
LRESULT OnMsgCustomButtonClick(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
UINT idxBtn =wID - IDC_TASKDLG_CUSTOMBUTTON_FIRST;
int nBtnID = -1;
if(idxBtn < m_cfg.cButtons) nBtnID = m_cfg.pButtons[idxBtn].nButtonID;
else {idxBtn = wID - IDC_TASKDLG_CUSTOMBUTTON_FIRST -m_cfg.cButtons;
if(idxBtn < m_cfg.SzPushButtons
)nBtnID = m_cfg.PushButtons[idxBtn].nButtonID;
}
if( S_FALSE ==_DoCallback(TDN_BUTTON_CLICKED, nBtnID)
) return 0;
m_iButtonResult = (int) nBtnID;
EndDialog(wID);
return 0;
}
LRESULT OnMsgExpandoClick(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
m_bExpanded = NOT(m_bExpanded);
_DoCallback(TDN_EXPANDO_BUTTON_CLICKED, m_bExpanded);
_DoExpandCollapse();
return 0;
}
LRESULT OnMsgVerificationClick(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
_DoCallback(TDN_VERIFICATION_CLICKED
,BST_CHECKED ==IsDlgButtonChecked(IDC_TASKDLG_VERIFYBUTTON));
#ifdef _DEBUG
PixRect rc;rc=(DLURect()=DLUPoint(0,7*8))=DLUSize(5*4,2*8);//_AlignDLU(rc);
CStatic* s=new CStatic;
s->Create(m_hWnd,rc,_T("On the Flow Button"),WS_CHILD | WS_VISIBLE |BS_GROUPBOX ,0);
s->ShowWindow(SW_SHOW);
#endif
return 0;
}
LRESULT OnMsgRadioClick(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
m_iRadioResult = (int) m_cfg.pRadioButtons[wID - IDC_TASKDLG_RADIOBUTTON_FIRST].nButtonID;
_DoCallback(TDN_RADIO_BUTTON_CLICKED, (WPARAM) m_iRadioResult);
return 0;
}
LRESULT OnMsgHyperlinkClicked(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
NMLINK* pLink = (NMLINK*) pnmh;
_DoCallback(TDN_HYPERLINK_CLICKED, 0
,(LPARAM) static_cast<LPCWSTR>(('\0' !=pLink->item.szID[0]
) ? pLink->item.szID
: pLink->item.szUrl)
);
return 0;
}
// Implementation
void _Reset() {
m_iRadioResult = 0;
m_iButtonResult = IDCANCEL;
m_bExpanded = true;
m_nHoverId = 0;
m_dwTick = ::GetTickCount();
}
DLUSize _LayoutControls(xDlu cxMaxDialog, bool createControls)
{bool isProbe = (cxMaxDialog.n == WIDTH_PROBE);
xDlu cxMaxLineReal= xDlu(cxMaxDialog.n - m_Metrics.sizeDialogPadding.dluX().n);
m_cfg.dwFlags |= TDF_EXPAND_FOOTER_AREA; //expand in conten yet not supported
DLUSize sizeEmpty(0,0);
LPTSTR pstrBuffer = (LPTSTR) malloc(MAX_TEXT_LENGTH * sizeof(TCHAR)); AXE(IS(pstrBuffer)
,_T("pstrBuffer =malloc; {memory low}")
,return sizeEmpty);
DLUSize sizeText;
ActBaseUnit::val(m_Metrics.BaseUnit);
xDlu cxMaxText =xDlu(0);
DLUSize sizeTitle =(0,0);
DLUSize sizeTemp =(0,0);
DWORD dwStyle =0;
DWORD dwExStyle =0;
UINT n =0;
m_nDefCtlId =0;
bool bIsCommCtrl6 = RunTimeHelper::IsCommCtrl6();
bool bIsVista = RunTimeHelper::IsVista();
RectDlg =DLURect();
RectDlgWork =RectDlg;
#define ypos RectDlgWork.bottom//tmp, obsoleting
RectDlgWork =DLUPoint(m_Metrics.sizeDialogPadding);//top left free space of RectDlg
// _AlignDLU(RectDlgWork);
RectTop =RectDlgWork;
{ // Main icon
RectIconMain=DLURect();
if( IS(m_cfg.pszMainIcon)
OR IS(TDF_USE_HICON_MAIN & m_cfg.dwFlags)
){
RectIconMain =RectTop;
// _AlignDLU(RectIconMain);
RectIconMain =DLUSize()=m_Metrics.cxyLargeIcon;
//_AlignDLU(RectIconMain); dont align iconbox
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_OWNERDRAW |WS_EX_TRANSPARENT;
dwExStyle = 0;
//RectIconMain.top+=100;
_AddControl(CStatic::GetWndClassName()
, IDC_TASKDLG_INSTRUCTIONSICON
, RectIconMain
, dwStyle
, dwExStyle
, _T("")
);
}
RectTop.sizeMax(RectTop,RectIconMain);
// _AlignDLU(RectTop);
RectDlgWork.sizeMax(RectDlgWork,RectTop);
}
}
RectContent =RectTop;
RectContent.left+=RectIconMain.size().cx;
RectContent.left+=m_Metrics.cxLargeIconGap.cx; //content echts von main icon
RectContent.adjust();
{// Main Instructions text
RectTextMain=DLURect();
if(IS(m_cfg.pszMainInstruction)
){RectTextMain =RectContent;
// _AlignDLU(RectTextMain);
if( IS(RectIconMain.size().cx) //if we are the frist content start a little under icon top
AND NOT(RectContent.size().cx)
)RectTextMain.top = m_Metrics.cyInstructionsGapTop.n;
RectTextMain.adjust();
cxMaxText.n = cxMaxDialog.n - RectTextMain.left
- m_Metrics.sizeDialogPadding.cx;
if(isProbe
)cxMaxText.n = m_Metrics.cxBestMainInstruction.n;
sizeText = _GetTextSize(m_cfg.pszMainInstruction
,pstrBuffer
,MAX_TEXT_LENGTH
,DT_WORDBREAK | DT_NOPREFIX
,m_fontTitle
,cxMaxText
);
RectTextMain =sizeText;
if(NOT(isProbe)
)RectTextMain.right =cxMaxLineReal.n;
RectTextMain.adjust();
/*no, we ensure it in the followers
if(RectTextMain.bottom < RectIconMain.bottom //main msg takes at minimum complete con space
)RectTextMain.bottom = RectIconMain.bottom;
*///so: it should represent the real text size
// _AlignDLU(RectTextMain);
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX;
dwExStyle = 0;
//RectTextMain.left+=100;
_AddControl(CStatic::GetWndClassName()
,IDC_TASKDLG_INSTRUCTIONSTEXT
,RectTextMain
,dwStyle
,dwExStyle
,pstrBuffer);
}
RectContent.sizeMax(RectContent,RectTextMain);
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
{// Content text
RectTextSub=DLURect();
if(IS(m_cfg.pszContent)
){RectTextSub =RectContent;
RectTextSub.top=RectContent.bottom;
RectTextSub.adjust();
if( IS(RectIconMain.size().cx) //if we are the frist content start a little under icon top
AND NOT(RectContent.size().cx)
)RectTextSub.top = m_Metrics.cyInstructionsGapTop.n;
RectTextSub.adjust();
bool gapAvail =m_Metrics.cyContentGap.n
< (RectTextMain.size().cy -sizeText.cy);
if( NOT(gapAvail)
AND IS(RectIconMain.size().cx) //separate main text from sub text if they touch
AND IS(RectContent.size().cx)
AND(RectContent.bottom >= RectIconMain.bottom)
)RectTextSub.top+=m_Metrics.cyContentGap.n;
RectTextSub.adjust();
cxMaxText.n = cxMaxDialog.n - RectTextSub.left
- m_Metrics.sizeDialogPadding.cx;
if(isProbe
)cxMaxText.n = m_Metrics.cxBestContent.n;
sizeText = _GetTextSizeHREF( m_cfg.pszContent
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK | DT_NOPREFIX
, m_fontText
, cxMaxText
);
RectTextSub =sizeText;
if(NOT(isProbe)
)RectTextSub.right =cxMaxLineReal.n;
RectTextSub.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX;
dwExStyle = 0;
LPCTSTR pstrClassName = bIsCommCtrl6 ? CStatic/*CLinkCtrl*/::GetWndClassName()
: CStatic::GetWndClassName();
if(NOT(bIsCommCtrl6)
)_RemoveHREF(pstrBuffer);
//RectTextSub.left+=100;
_AddControl( pstrClassName
, IDC_TASKDLG_CONTENTTEXT
, RectTextSub
, dwStyle
, dwExStyle
, pstrBuffer
);
}
RectContent.sizeMax(RectContent,RectTextSub);
RectContent.bottom+=m_Metrics.cyContentGap.n;
RectContent.adjust();
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
{// Expando in Content area
RectExpoInside = DLURect();
if( IS(m_cfg.pszExpandedInformation)
AND NOT(TDF_EXPAND_FOOTER_AREA & m_cfg.dwFlags)
){RectExpoInside =RectContent;
RectExpoInside.top=RectContent.bottom;
RectExpoInside.adjust();
if( IS(RectIconMain.size().cx) //if we are the frist content start a little under icon top
AND NOT(RectContent.size().cx)
)RectExpoInside.top = m_Metrics.cyInstructionsGapTop.n;
RectExpoInside.adjust();
if( IS(RectIconMain.size().cx) //separate it from sub text if they touch
AND IS(RectContent.size().cx)
AND(RectContent.bottom >= RectIconMain.bottom)
)RectExpoInside.top+=2*m_Metrics.cyContentGap.n;
RectExpoInside.adjust();
cxMaxText.n = cxMaxDialog.n- RectExpoInside.left
- m_Metrics.sizeDialogPadding.cx;
if(isProbe
)cxMaxText.n = m_Metrics.cxBestContent.n;
sizeText = _GetTextSizeHREF( m_cfg.pszExpandedInformation
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK | DT_NOPREFIX
, m_fontText
, cxMaxText
);
RectExpoInside =sizeText;
if(NOT(isProbe)
)RectExpoInside.right =cxMaxLineReal.n;
RectExpoInside.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX;
dwExStyle = 0;
LPCTSTR pstrClassName = bIsCommCtrl6 ? CLinkCtrl::GetWndClassName()
: CStatic::GetWndClassName();
if(NOT(bIsCommCtrl6)
)_RemoveHREF(pstrBuffer);
_AddControl(pstrClassName
, IDC_TASKDLG_EXTRATEXT
, RectExpoInside, dwStyle, dwExStyle, pstrBuffer);
}
RectContent.sizeMax(RectContent,RectExpoInside); //inside must reduced from drawtop background if not to show
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
{// Progress Bar
RectProgress =DLURect();
if(IS((TDF_SHOW_PROGRESS_BAR
|TDF_SHOW_MARQUEE_PROGRESS_BAR) & m_cfg.dwFlags)
){RectProgress =RectContent;
RectProgress.top=RectContent.bottom;
RectProgress.top = max(RectProgress.top //no prgress in icon line
,RectIconMain.bottom);
RectProgress.top+=m_Metrics.cyContentGap.n; //progress allways needs the gap, at least from the icon
RectProgress.adjust();
cxMaxText.n = max(RectContent.size().cy
,m_Metrics.cxBestProgressBar.n);
if(NOT(isProbe)
)cxMaxText.n = RectDlgWork.right - RectContent.left;//footer or expanderoutside must be sized !!
RectProgress =DLUSize(cxMaxText.n,m_Metrics.cyProgressBar.n);
// _AlignDLU(RectProgress);
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | PBS_SMOOTH;
dwExStyle = 0;
_AddControl(CProgressBarCtrl::GetWndClassName(), IDC_TASKDLG_PROGRESSBAR, RectProgress, dwStyle, dwExStyle, pstrBuffer);
}
RectContent.sizeMax(RectContent,RectProgress);
RectContent.bottom+= m_Metrics.cyContentGap.n; //progress allways needs the gap, at least from the icon
RectContent.adjust();
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
{// Radio buttons
RectRadio =DLURect();
if(m_cfg.cRadioButtons > 0
){RectRadio =RectContent;
RectRadio .top =RectContent.bottom;
RectRadio.top = max(RectRadio.top //no radio in icon line
,RectIconMain.bottom);
RectRadio.adjust();
if(IS(RectContent.size().cx)
)RectRadio.top+=m_Metrics.cyContentGap.n;
if( IS(RectExpoInside.size().cy) //separate it from sub text if they touch
AND NOT(RectProgress.size().cy)
)RectRadio.top+= m_Metrics.cyContentGap.n;
RectRadio.left += m_Metrics.cxRadioIndent.n;
RectRadio.adjust();
for(n = 0; n < m_cfg.cRadioButtons; n++
){
cxMaxText.n = cxMaxDialog.n - RectRadio.left
- m_Metrics.sizeDialogPadding.cx
- m_Metrics.sizeRadioButton.cx;
if(isProbe
)cxMaxText.n = m_Metrics.cxBestRadioButton.n;
sizeText = _GetTextSize( m_cfg.pRadioButtons[n].pszButtonText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, cxMaxText
);
sizeText.cx += m_Metrics.sizeRadioButton.cx;
if( sizeText.cy < m_Metrics.sizeRadioButton.cy
) sizeText.cy = m_Metrics.sizeRadioButton.cy;
DLURect RectOneRadio =RectRadio;
RectOneRadio.top =RectOneRadio.bottom;
if(IS(RectRadio.size().cy)
)RectOneRadio.top+=m_Metrics.cyRadioGap.n;
RectOneRadio=sizeText;
if(NOT(isProbe)
)RectOneRadio.right =cxMaxLineReal.n;
RectOneRadio.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTORADIOBUTTON | BS_TOP | BS_MULTILINE;
dwExStyle = 0;
if(n == 0) dwStyle |= WS_GROUP;
_AddControl( CButton::GetWndClassName()
, (WORD) (IDC_TASKDLG_RADIOBUTTON_FIRST + n)
, RectOneRadio
, dwStyle
, dwExStyle
, pstrBuffer
);
}
RectRadio.sizeMax(RectRadio,RectOneRadio);
RectContent.sizeMax(RectContent,RectRadio);
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
}
{// Command Links
RectCommand =DLURect();
m_bHasCustomLinks = false;
if( (m_cfg.cButtons > 0)
AND IS((TDF_USE_COMMAND_LINKS
|TDF_USE_COMMAND_LINKS_NO_ICON) & m_cfg.dwFlags
)
){
//if(NOT(elementsAdded)) ypos -= m_Metrics.sizeDialogPadding.cy/2;
RectCommand =RectContent;
RectCommand .top=RectContent.bottom;
if( IS((DLUSize()=RectIconMain).cx)
AND NOT(RectContent.size().cx)
)RectCommand.top += m_Metrics.cyInstructionsGapTop.n; //start a little under icon top
RectCommand.adjust();
if(IS(RectRadio.size().cx)
)RectCommand.top += m_Metrics.cyContentGap.n;
RectCommand.adjust();
for( n = 0; n < m_cfg.cButtons; n++
){
DLURect rectCommandBtn=RectCommand;
rectCommandBtn.top=RectCommand.bottom;
rectCommandBtn.adjust();
_LoadString(m_cfg.pButtons[n].pszButtonText, pstrBuffer, MAX_TEXT_LENGTH);
LPCTSTR pstrTitle = NULL;
LPCTSTR pstrText = NULL;
SIZE_T cchTitle = 0;
SIZE_T cchText = 0;
_SplitCommandText(pstrBuffer, pstrTitle, cchTitle, pstrText, cchText);
DLUSize cxPadding;cxPadding = (m_Metrics.sizeLinkPadding * 2);
if((m_cfg.dwFlags & TDF_USE_COMMAND_LINKS_NO_ICON) == 0
)cxPadding += m_Metrics.cxyArrowIcon + m_Metrics.cxSmallIconGap;
cxMaxText.n = cxMaxDialog.n - RectCommand.left - m_Metrics.sizeDialogPadding.cx - cxPadding.cx;
if(cxMaxDialog.n == WIDTH_PROBE
)cxMaxText.n = m_Metrics.cxBestCommandLink.n - cxPadding.cx;
sizeTitle =PixSize()= _GetTextSize(pstrTitle, cchTitle, DT_WORDBREAK, m_fontTitle, cxMaxText);
DLUSize sizeSub;sizeSub =PixSize()= _GetTextSize(pstrText, cchText, DT_NOPREFIX | DT_WORDBREAK, m_fontText, cxMaxText);
DLUSize sizeText;
sizeText.cx=max(sizeTitle.cx,sizeSub.cx);
sizeText.cy=sizeTitle.cy +sizeSub.cy;
if(IS(sizeText.cx)) sizeText.cx += cxPadding.cx;
if(sizeText.cx < m_Metrics.cxMinCommandLink.n
)sizeText.cx = m_Metrics.cxMinCommandLink.n;
rectCommandBtn =sizeText;
if(NOT(isProbe)
)rectCommandBtn.right =cxMaxLineReal.n;
rectCommandBtn.adjust();
rectCommandBtn.bottom+=(m_Metrics.sizeLinkPadding.cy * 4);
rectCommandBtn.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CENTER|BS_VCENTER/*BS_TOP*/ | BS_MULTILINE;
dwExStyle = 0;
if(n == 0
)dwStyle |= WS_GROUP;
if(bIsVista AND bIsCommCtrl6
) {
if(m_cfg.pButtons[n].nButtonID == m_cfg.nDefaultButton
) {
dwStyle |= BS_DEFCOMMANDLINK;
m_nDefCtlId = (UINT) -1;
}
else{
dwStyle |= BS_COMMANDLINK;//??dwStyle |= BS_OWNERDRAW;
}
}
else{m_bHasCustomLinks = true;
if(m_cfg.pButtons[n].nButtonID == m_cfg.nDefaultButton
)m_nDefCtlId = IDC_TASKDLG_CUSTOMBUTTON_FIRST + n;
dwStyle |= BS_OWNERDRAW;
}
_AddControl(CButton::GetWndClassName()
, (WORD) (IDC_TASKDLG_CUSTOMBUTTON_FIRST + n)
, rectCommandBtn
, dwStyle, dwExStyle
, pstrBuffer);
}
RectCommand.sizeMax(RectCommand,rectCommandBtn);
//RectCommand.bottom +=m_Metrics.cyButtonLineGap.n;
RectContent.sizeMax(RectContent,RectCommand);
RectTop .sizeMax(RectTop ,RectContent);
RectDlgWork .sizeMax(RectDlgWork ,RectTop);
}
}
}
RectDlgWork.top +=m_Metrics.cyContentGap.n;
RectDlgWork.adjust();
RectBottom=RectDlgWork;
RectBottom.top =RectTop.bottom;
RectBottom.adjust();
RectBottomContent =RectBottom;
RectBottomContent.right =RectBottomContent.left;
//RectBottomContent.left =RectContent.left;
RectBottomContent.top +=m_Metrics.cyButtonLineGap.n;
RectBottomContent.adjust();
if(false AND createControls
){
dwStyle = WS_CHILD | WS_VISIBLE |WS_EX_CLIENTEDGE | BS_PUSHBUTTON |BS_GROUPBOX | SS_CENTER | SS_NOPREFIX;
dwExStyle = 0;
DLURect rcDivider =RectBottom;
rcDivider.bottom+=1;
_AddControl(CStatic::GetWndClassName()
,IDC_TASKDLG_FOOTERDIVIDER, rcDivider , dwStyle, dwExStyle, _T(""));
}
RectButtonRow=RectBottomContent;
RectExpoRow =RectButtonRow;
{// Expander area
if(IS(m_cfg.pszExpandedInformation)
){
RectExpoBtn =RectExpoRow;
if(ShowExpanderIcon
)RectExpoBtn =(DLUSize()=m_Metrics.cxyExpanderIcon);
// _AlignDLU(RectExpoBtn);
if(createControls AND ShowExpanderIcon
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_OWNERDRAW | SS_NOTIFY |WS_EX_TRANSPARENT;
dwExStyle = 0;
_AddControl(CStatic::GetWndClassName()
,IDC_TASKDLG_EXPANDERICON, RectExpoBtn, dwStyle, dwExStyle
,_T("")
);
}
RectExpoRow.sizeMax(RectExpoRow,RectExpoBtn);
xDlu xoffset;
if(ShowExpanderIcon
) xoffset.n = m_Metrics.cxyExpanderIcon.cx + m_Metrics.cxSmallIconGap.cx;
sizeTemp = _GetTextSize( m_cfg.pszCollapsedControlText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, m_Metrics.cxMaxVerification
);
sizeText = _GetTextSize( m_cfg.pszExpandedControlText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, m_Metrics.cxMaxVerification
);
if(sizeTemp.cx > sizeText.cx) sizeText.cx = sizeTemp.cx;
if(sizeTemp.cy > sizeText.cy) sizeText.cy = sizeTemp.cy;
sizeText.cx += xoffset.n;
RectExpoText =RectExpoBtn;
RectExpoText.left +=xoffset.n;
RectExpoText =sizeText;
//_AlignDLU(RectExpoText.bottom,HTBOTTOM);
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX | SS_NOTIFY;
dwExStyle = 0;
_AddControl(CStatic::GetWndClassName(), IDC_TASKDLG_EXPANDERTEXT, RectExpoText, dwStyle, dwExStyle, pstrBuffer);
}
RectExpoRow .sizeMax(RectExpoRow,RectExpoBtn);
RectExpoRow .sizeMax(RectExpoRow,RectExpoText);
RectButtonRow .sizeMax(RectButtonRow,RectExpoRow);
RectBottomContent .sizeMax(RectBottomContent,RectButtonRow);
RectBottom .sizeMax(RectBottom,RectBottomContent);
RectDlgWork .sizeMax(RectDlgWork ,RectBottom);
}
}
{// Verification text
RectCheck =DLURect();
if(IS(m_cfg.pszVerificationText)
){
RectCheck =RectButtonRow;
RectCheck.top =RectButtonRow.bottom;
if(IS(RectExpoRow.size().cy)
)RectCheck.top+=m_Metrics.cyContentGap.n;
RectCheck.adjust();
sizeText = _GetTextSize( m_cfg.pszVerificationText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, m_Metrics.cxMaxVerification
);
const LONG cxIndent = 2;
RectCheck.left+=cxIndent;
RectCheck=sizeText;
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX | BS_TOP | BS_LEFT | BS_MULTILINE;
dwExStyle = 0;
_AddControl(CButton::GetWndClassName(), IDC_TASKDLG_VERIFYBUTTON, RectCheck, dwStyle, dwExStyle, pstrBuffer);
}
RectButtonRow .sizeMax(RectButtonRow,RectCheck);
RectBottomContent .sizeMax(RectBottomContent,RectButtonRow);
RectBottom .sizeMax(RectBottom,RectBottomContent);
RectDlgWork .sizeMax(RectDlgWork ,RectBottom);
}
}
{// Buttons: mutateable
RectBtns =RectButtonRow;
RectBtns.left=RectButtonRow.right;
RectButtonRow.adjust();
if(IS(RectButtonRow.size().cx)) RectBtns.left +=m_Metrics.cxMinButton.n+(m_Metrics.sizeButtonPadding.cx * 2);
else RectBtns.left =RectContent.left;//2*m_Metrics.cxButtonsIndent.n;
RectBtns.adjust();
if( (m_cfg.cButtons > 0)
AND NOT((TDF_USE_COMMAND_LINKS
|TDF_USE_COMMAND_LINKS_NO_ICON) & m_cfg.dwFlags)
){
for(n = 0; n < m_cfg.cButtons; n++
){
sizeText = _GetTextSize( m_cfg.pButtons[n].pszButtonText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, xDlu(9999)
);
if(sizeText.cx < m_Metrics.cxMinButton.n
)sizeText.cx = m_Metrics.cxMinButton.n;
DLURect rcButton =RectBtns;
rcButton.left =RectBtns.right;
rcButton.bottom=RectBtns.top;
rcButton.adjust();
rcButton =DLUSize(sizeText.cx + (m_Metrics.sizeButtonPadding.cx * 2)
,sizeText.cy + (m_Metrics.sizeButtonPadding.cy * 2));
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_MULTILINE;
dwExStyle = 0;
_AddControl( CButton::GetWndClassName()
, (WORD) (IDC_TASKDLG_CUSTOMBUTTON_FIRST + n)
, rcButton
, dwStyle, dwExStyle
, pstrBuffer);
}
RectBtns.sizeMax(RectBtns,rcButton);
RectBtns.right+= m_Metrics.cxButtonGap.n;
RectBtns.adjust();
if(NOT(m_nDefCtlId)
)m_nDefCtlId = IDC_TASKDLG_CUSTOMBUTTON_FIRST + n;
if(m_cfg.nDefaultButton == m_cfg.pButtons[n].nButtonID
)m_nDefCtlId = IDC_TASKDLG_CUSTOMBUTTON_FIRST + n;
}
}
}
{// Buttons: none mutateable
if(m_cfg.SzPushButtons > 0
){
for(n = 0; n < m_cfg.SzPushButtons; n++
){
sizeText = _GetTextSize( m_cfg.PushButtons[n].pszButtonText
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, xDlu(9999)
);
if(sizeText.cx < m_Metrics.cxMinButton.n
)sizeText.cx = m_Metrics.cxMinButton.n;
DLURect rcButton =RectBtns;
rcButton.left =RectBtns.right;
rcButton.bottom=RectBtns.top;
rcButton.adjust();
rcButton =DLUSize(sizeText.cx + (m_Metrics.sizeButtonPadding.cx * 2)
,sizeText.cy + (m_Metrics.sizeButtonPadding.cy * 2));
// _AlignDLU(rcButton);
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_MULTILINE;
dwExStyle = 0;
_AddControl( CButton::GetWndClassName()
, (WORD) (IDC_TASKDLG_CUSTOMBUTTON_FIRST + n +m_cfg.cButtons)
, rcButton
, dwStyle, dwExStyle
, pstrBuffer);
}
RectBtns.sizeMax(RectBtns,rcButton);
RectBtns.right+= m_Metrics.cxButtonGap.n;
RectBtns.adjust();
if(NOT(m_nDefCtlId)
)m_nDefCtlId = IDC_TASKDLG_CUSTOMBUTTON_FIRST + n +m_cfg.cButtons;
if(m_cfg.nDefaultButton == m_cfg.PushButtons[n].nButtonID
)m_nDefCtlId = IDC_TASKDLG_CUSTOMBUTTON_FIRST + n +m_cfg.cButtons;
}
}
// common buttons
if(IS(m_cfg.dwCommonButtons)
){
int commonButtonsSupported[] ={TDCBF_OK_BUTTON ,IDOK ,IDS_TASKDLG_OK
,TDCBF_YES_BUTTON ,IDYES ,IDS_TASKDLG_YES
,TDCBF_NO_BUTTON ,IDNO ,IDS_TASKDLG_NO
,TDCBF_RETRY_BUTTON ,IDRETRY ,IDS_TASKDLG_RETRY
,TDCBF_CANCEL_BUTTON ,IDCANCEL ,IDS_TASKDLG_CANCEL
,TDCBF_CLOSE_BUTTON ,IDCLOSE ,IDS_TASKDLG_CLOSE
};
const UINT szCommonButtonsSupported =sizeof(commonButtonsSupported)
/sizeof(commonButtonsSupported[0]);
for(n = 0
;n < szCommonButtonsSupported
;n += 3
){
if( NOT(m_cfg.dwCommonButtons & commonButtonsSupported[n])
) continue;
DLUSize sizeText;sizeText=PixSize() = _GetTextSize( makeIntResourceW(commonButtonsSupported[n + 2])
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK
, m_fontText
, xDlu(9999)
);
if(sizeText.cx < m_Metrics.cxMinButton.n
)sizeText.cx = m_Metrics.cxMinButton.n;
DLURect rcButton =RectBtns;
rcButton.left =RectBtns.right;
rcButton.bottom=RectBtns.top;
rcButton.adjust();
rcButton =DLUSize(sizeText.cx + (m_Metrics.sizeButtonPadding.cx * 2)
,sizeText.cy + (m_Metrics.sizeButtonPadding.cy * 2));
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_MULTILINE;
dwExStyle = 0;
_AddControl( CButton::GetWndClassName()
, (WORD) commonButtonsSupported[n + 1]
, rcButton
, dwStyle
, dwExStyle
, pstrBuffer
);
}
RectBtns.sizeMax(RectBtns,rcButton);
RectBtns.right+= m_Metrics.cxButtonGap.n;
RectBtns.adjust();
if(NOT(m_nDefCtlId)
)m_nDefCtlId = (UINT) commonButtonsSupported[n + 1];
if(m_cfg.nDefaultButton == commonButtonsSupported[n + 1]
)m_nDefCtlId = (UINT) commonButtonsSupported[n + 1];
}
}
}//END: Buttons: none mutateable, END: all push buttons
//RectButtonRow=RectExpoRow;
RectButtonRow.sizeMax(RectButtonRow,RectBtns);
RectBottomContent .sizeMax(RectBottomContent,RectButtonRow);
RectBottom .sizeMax(RectBottom,RectBottomContent);
RectDlgWork .sizeMax(RectDlgWork ,RectBottom);
{// Footer text
RectFooter =RectButtonRow;
RectFooter.top =RectButtonRow.bottom;
RectFooter.adjust();
if(IS(m_cfg.pszFooter)
){if(IS(RectButtonRow.size().cy)
)RectFooter.top+=m_Metrics.cyButtonLineGap.n;
RectFooter.adjust();
RectIconFooter =RectFooter;
if( IS(m_cfg.pszFooterIcon)
OR IS(TDF_USE_HICON_FOOTER & m_cfg.dwFlags)
){
RectIconFooter=DLUSize()=m_Metrics.cxySmallIcon;
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_OWNERDRAW |WS_EX_TRANSPARENT;
dwExStyle = 0;
_AddControl(CStatic::GetWndClassName()
,IDC_TASKDLG_FOOTERICON, RectIconFooter, dwStyle, dwExStyle
, _T(""));
}
RectFooterText =RectIconFooter;
RectFooterText.left=RectIconFooter.right;
RectFooterText.left+=m_Metrics.cxSmallIconGap.cx;
RectFooterText.adjust();
}
cxMaxText.n = cxMaxDialog.n - RectFooterText.left - m_Metrics.sizeDialogPadding.cx;
if(isProbe
)cxMaxText = m_Metrics.cxBestContent;
sizeText = _GetTextSizeHREF( m_cfg.pszFooter
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK | DT_NOPREFIX
, m_fontText
, cxMaxText
);
if(sizeText.cy < m_Metrics.cxySmallIcon.cy
)sizeText.cy = m_Metrics.cxySmallIcon.cy;
RectFooterText=sizeText;
if(NOT(isProbe)
)RectFooterText.right =cxMaxLineReal.n;
RectFooterText.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX;
dwExStyle = 0;
LPCTSTR pstrClassName = bIsCommCtrl6 ? CLinkCtrl::GetWndClassName()
: CStatic::GetWndClassName();
if(NOT(bIsCommCtrl6)
)_RemoveHREF(pstrBuffer);
_AddControl(pstrClassName, IDC_TASKDLG_FOOTERTEXT, RectFooterText, dwStyle, dwExStyle, pstrBuffer);
}
}
RectFooter .sizeMax(RectFooter,RectIconFooter);
RectFooter .sizeMax(RectFooter,RectFooterText);
// _AlignDLU(RectFooter);
RectBottomContent .sizeMax(RectBottomContent,RectFooter);
RectBottom .sizeMax(RectBottom,RectBottomContent);
RectDlgWork .sizeMax(RectDlgWork ,RectBottom);
}
{// Expando in Footer area
RectExpoOutside =RectFooter;
RectExpoOutside.top=RectFooter.bottom;
RectExpoOutside.adjust();
if( IS(m_cfg.pszExpandedInformation)
AND IS(TDF_EXPAND_FOOTER_AREA & m_cfg.dwFlags)
){
RectExpoOutside.top+=m_Metrics.cyContentGap.n;
RectExpoOutside.adjust();
RectExpoOutsideText=RectExpoOutside;
cxMaxText.n = cxMaxDialog.n - RectExpoOutsideText.left
- m_Metrics.sizeDialogPadding.cx;
if(isProbe
)cxMaxText = m_Metrics.cxBestContent;
sizeText = _GetTextSizeHREF( m_cfg.pszExpandedInformation
, pstrBuffer
, MAX_TEXT_LENGTH
, DT_WORDBREAK | DT_NOPREFIX
, m_fontText
, cxMaxText
);
RectExpoOutsideText=sizeText;
if(NOT(isProbe)
)RectExpoOutsideText.right =cxMaxLineReal.n;
RectExpoOutsideText.adjust();
if(createControls
){
dwStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX;
dwExStyle = 0;
LPCTSTR pstrClassName = bIsCommCtrl6 ? CLinkCtrl::GetWndClassName()
: CStatic::GetWndClassName();
if(NOT(bIsCommCtrl6)
)_RemoveHREF(pstrBuffer);
_AddControl( pstrClassName
, IDC_TASKDLG_EXTRATEXT
, RectExpoOutsideText, dwStyle, dwExStyle
, pstrBuffer);
}
}
}
RectExpoOutside.sizeMax(RectExpoOutside,RectExpoOutsideText);
//RectFooter.sizeMax(RectFooter,RectExpoOutside);
RectBottomContent .sizeMax(RectBottomContent,RectExpoOutside);
RectBottom .sizeMax(RectBottom,RectBottomContent);
RectDlgWork .sizeMax(RectDlgWork ,RectBottom);
RectDlg .sizeMax(RectDlg ,RectDlgWork);
RectDlg =RectDlg.size() +m_Metrics.sizeDialogPadding;
free(pstrBuffer);
return RectDlg.size();
}
void _CustomDrawIcon(LPDRAWITEMSTRUCT lpDIS, COLORREF clrBack, HICON hIcon, DLUSize cxyIcon)
{CDCHandle dc = lpDIS->hDC;
PixRect rc = lpDIS->rcItem;
//_AlignDLU(rc);
dc.FillSolidRect(&rc, clrBack);
PixSize szp;szp=cxyIcon;
dc.DrawIconEx (rc.left, rc.top, hIcon, szp.cx, szp.cy);
}
void _CustomDrawCommandLink(LPDRAWITEMSTRUCT lpDIS)
{
m_Metrics.reInitColors();
CButton ctrl = lpDIS->hwndItem;
CDCHandle dc = lpDIS->hDC;
PixRect rcPix = lpDIS->rcItem;
HBRUSH hOldBrush = dc.GetCurrentBrush();
HFONT hOldFont = dc.GetCurrentFont();
HPEN hOldPen = dc.GetCurrentPen();
if(lpDIS->CtlID == m_nHoverId
) {
dc.DrawFrameControl(&rcPix, DFC_BUTTON, DFCS_BUTTONPUSH);
PixRect rcInteriour = rcPix;
::InflateRect(&rcInteriour, -2, -2);
dc.FillSolidRect(&rcInteriour, m_Metrics.clrBkCommandSelect);
}
else if( IS(ODA_DRAWENTIRE & lpDIS->itemAction)
) {
dc.FillSolidRect(&rcPix, m_Metrics.clrBkTop);
}
COLORREF clrBorder = CLR_INVALID;
if( m_nDefCtlId == lpDIS->CtlID
) clrBorder = m_Metrics.clrCmdLinkSelect;
if( IS(ODS_SELECTED & lpDIS->itemState)
) clrBorder = ::GetSysColor(COLOR_3DSHADOW);
if(NOT(CLR_INVALID == clrBorder)
){
CPen penBorder;
penBorder.CreatePen(PS_SOLID, 1, clrBorder);
dc.SelectPen (penBorder);
dc.SelectBrush((HBRUSH) ::GetStockObject(HOLLOW_BRUSH));
PixPoint ptArc( 6, 6 );
dc.RoundRect(&rcPix, ptArc);
}
::InflateRect(&rcPix, -m_Metrics.sizeLinkPadding.pix().cx, -m_Metrics.sizeLinkPadding.pix().cy);
xPix cxPix = xPix((rcPix.right - (rcPix.left + m_Metrics.cxyArrowIcon.pix().cx + m_Metrics.cxSmallIconGap.pix().cx)));
TCHAR szWindowText[300] = { 0 };
ctrl.GetWindowText(szWindowText, sizeof(szWindowText) / sizeof(TCHAR));
LPCTSTR pstrTitle = NULL;
LPCTSTR pstrText = NULL;
SIZE_T cchTitle = 0;//strlen
SIZE_T cchText = 0;//strlen
_SplitCommandText(szWindowText, pstrTitle, cchTitle, pstrText, cchText);
DLUSize sizeTitleDlu = _GetTextSize(pstrTitle, cchTitle, DT_WORDBREAK, m_fontTitle, xDlu()=cxPix);
DLUSize sizeTextDlu = _GetTextSize(pstrText , cchTitle, DT_WORDBREAK, m_fontTitle, xDlu()=cxPix);
{// vert center in command
yPix szRcYPix;szRcYPix =yPix(rcPix.bottom -rcPix.top); AE_(szRcYPix.n < sizeTitleDlu.cy +sizeTextDlu.cy + 1);
yPix topOffsetPix;
if(szRcYPix.n > sizeTitleDlu.pix().cy+sizeTextDlu.pix().cy+ yDlu(1).pix().n
){topOffsetPix.n =(szRcYPix.n -(sizeTitleDlu.pix().cy +sizeTextDlu.pix().cy + yDlu(1).pix().n))/2;
}
rcPix.top+=topOffsetPix.n; //center
}
if(NOT(TDF_USE_COMMAND_LINKS_NO_ICON & m_cfg.dwFlags)
){
dc.DrawIconEx( rcPix.left, rcPix.top + 2
, lpDIS->CtlID == m_nHoverId ? m_iconArrowHot
: m_iconArrowNormal
, 20, 20);
rcPix.left += m_Metrics.cxyArrowIcon.pix().cx + m_Metrics.cxSmallIconGap.pix().cx;
}
dc.SetTextColor((lpDIS->CtlID == m_nHoverId
) ?m_Metrics.clrCommandLinkTextSelected
:m_Metrics.clrCommandLinkText);
dc.SetBkMode (TRANSPARENT);
dc.SelectFont (m_fontTitle);
PixRect rcTitle( rcPix.left, rcPix.top, rcPix.right, rcPix.bottom );
dc.DrawText(pstrTitle, (int)cchTitle, &rcTitle, DT_WORDBREAK);
PixRect rcText( rcPix.left, rcPix.top + sizeTitleDlu.pix().cy + yDlu(1).pix().n
, rcPix.right,rcPix.bottom );
dc.SelectFont(m_fontText);
dc.DrawText (pstrText, (int)cchText, &rcText, DT_NOPREFIX | DT_WORDBREAK);
dc.SelectPen (hOldPen);
dc.SelectFont (hOldFont);
dc.SelectBrush(hOldBrush);
}
void _CustomDrawDivider(LPDRAWITEMSTRUCT lpDIS)
{
m_Metrics.reInitColors();
CButton ctrl = lpDIS->hwndItem;
CDCHandle dc = lpDIS->hDC;
PixRect rc = lpDIS->rcItem;
rc.bottom-=10;
//rc.bottom=rc.top+10;
dc.FillSolidRect(&rc, m_Metrics.clrDividerLight);
}
void _PlaySound() {if(TD_ERROR_ICON == m_cfg.pszMainIcon) ::MessageBeep(MB_ICONHAND);
if(TD_WARNING_ICON == m_cfg.pszMainIcon) ::MessageBeep(MB_ICONEXCLAMATION);
if(TD_INFORMATION_ICON == m_cfg.pszMainIcon) ::MessageBeep(MB_ICONASTERISK);
}
void _RemoveHREF(LPTSTR pstr) const
{
if(NOT(TDF_ENABLE_HYPERLINKS & m_cfg.dwFlags)) return;
LPTSTR p = pstr;
while(*p != '\0'
){
if(*p == '<'
) {LOGG(_T("W_ W_ W_ Will remove hyperlinks from TaskDialogEmu; no support on this platform"));
while( (*p != '\0')
AND(*p != '>' )
) p = ::CharNext(p);
if(*p == '>') p = ::CharNext(p);
}
else{*pstr = *p;
#ifdef _MBCS
if(::IsDBCSLeadByte(*p)
) pstr[1] = p[1];
#endif // _MBCS
p = ::CharNext(p);
pstr = ::CharNext(pstr);
}
}
*pstr = '\0';
}
DLURect _CenterDialog(DLUSize dluDialog) const
{
PixRect pixArea;
if( ::IsWindow(m_cfg.hwndParent)
AND IS(TDF_POSITION_RELATIVE_TO_WINDOW & m_cfg.dwFlags)
) ::GetWindowRect (m_cfg.hwndParent, &pixArea);
else ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &pixArea, NULL);
//pixArea = MapDialogPixels(pixArea);
DLURect dluArea;dluArea= pixArea;
DLURect rc;
rc.left = dluArea.left +((dluArea.right - dluArea.left)/ 2 - dluDialog.cx / 2);
rc.top = dluArea.top +((dluArea.bottom - dluArea.top) / 2 - dluDialog.cy / 2);
rc.right = rc.left + dluDialog.cx;
rc.bottom = rc.top + dluDialog.cy;
return rc;
}
HRESULT _DoCallback(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0)
{
if(NOT(m_bCreated)) return S_OK;
if(NOT(m_cfg.pfCallback)) return S_OK;
return m_cfg.pfCallback(m_hWnd, uMsg, wParam, lParam, m_cfg.lpCallbackData);
}
void _DoExpandCollapse()
{
/*if(NOT(TDF_EXPAND_FOOTER_AREA & m_cfg.dwFlags)
) {
CWindow wndText = GetDlgItem(IDC_TASKDLG_EXTRATEXT);
PixRect rcText;
wndText.GetWindowRect(&rcText);
yDlu cy = yDlu( (DLUSize()=rcText.size()).cy
+ m_Metrics.cyButtonLineGap.n);
if(NOT(m_bExpanded)
) cy.n = -cy.n;
HWND hWndFirst=NULL;
CWindow wndChild = hWndFirst = GetWindow(GW_CHILD);
while(IS(wndChild)
){
PixRect rcWin;
wndChild.GetWindowRect(&rcWin);
if( (wndChild != wndText)
AND(rcWin.top >= rcText.top)
){
::OffsetRect (&rcWin, 0, cy.pix().n);
::MapWindowPoints (HWND_DESKTOP, m_hWnd, (LPPOINT) &rcWin, 2);
wndChild.MoveWindow(&rcWin);
}
wndChild = wndChild.GetWindow(GW_HWNDNEXT);
if(wndChild == hWndFirst
)break;
}
wndText.ShowWindow(m_bExpanded ? SW_SHOWNOACTIVATE: SW_HIDE);
ResizeClient(-1, m_bExpanded ? m_sizeDialog.pixY().n
: m_sizeDialog.pixY().n
+cy.pix().n);
}
else*/ResizeClient(-1, m_bExpanded ? m_sizeDialog.pix().cy
: m_sizeDialog.pix().cy
-RectExpoOutside.size().pix().cy
-m_Metrics.sizeDialogPadding.pix().cy
/*yDlu(RectExpoOutside.top
+ 5*m_Metrics.szChar.cy
).pix().n
*/
);
// Change text in Expander label
LPTSTR pstrBuffer = (LPTSTR) malloc(MAX_TEXT_LENGTH * sizeof(TCHAR)); AXE(IS(pstrBuffer)
,_T("pstrBuffer =malloc; {memory low}")
,return);
_LoadString(m_bExpanded ? m_cfg.pszExpandedControlText
: m_cfg.pszCollapsedControlText
, pstrBuffer, MAX_TEXT_LENGTH);
SetDlgItemText(IDC_TASKDLG_EXPANDERTEXT, pstrBuffer);
free(pstrBuffer);
// Make sure we redraw stuff
CWindow(GetDlgItem(IDC_TASKDLG_EXPANDERICON)
).Invalidate();
CWindow(GetDlgItem(IDC_TASKDLG_EXPANDERTEXT)
).Invalidate();
this ->Invalidate();
}
void _AddControl(ATL::_U_STRINGorID ClassName, WORD wId, DLURect rc, DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text)
{
PixRect pix;pix=rc;
//RECT dlurc = MapDialogPixels(pix);
m_Template.AddControl(ClassName, wId, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle, Text);
}
HICON _LoadIcon(LPCWSTR pstr, DLUSize cxy) const
{ if(NOT(pstr)) return NULL;
USES_CONVERSION;
// Determine icon identifier and resource dll
HINSTANCE hInst = m_cfg.hInstance;
if(pstr == TD_ERROR_ICON
)pstr = (LPWSTR)(IDI_ERROR),hInst =NULL;
//#if _WIN32_WINNT >= 0x0600
else if( pstr == TD_SHIELD_ICON
){pstr = makeIntResourceW(32518)/*makeIntResourceW(IDI_SHIELD)*/, hInst = NULL;
#ifdef IDI_SHIELD
if(!(pstr)){pstr = (LPWSTR)(IDI_SHIELD), hInst = NULL;}
#endif
if(!(pstr)){pstr = makeIntResourceW(32515)/*warning instead than */,hInst = NULL;}
}
//#endif // _WIN_WINNT
else if( pstr == TD_WARNING_ICON ) pstr = (LPWSTR)(IDI_EXCLAMATION), hInst = NULL;
else if( pstr == TD_INFORMATION_ICON ) pstr = (LPWSTR)(IDI_ASTERISK), hInst = NULL;
else if( pstr == makeIntResourceW(IDI_TASKDLG_ARROW_HOT) ) hInst = ModuleHelper::GetResourceInstance();
else if( pstr == makeIntResourceW(IDI_TASKDLG_ARROW_NORMAL) ) hInst = ModuleHelper::GetResourceInstance();
else if( pstr == makeIntResourceW(IDI_TASKDLG_CHEVRON_LESS) ) hInst = ModuleHelper::GetResourceInstance();
else if( pstr == makeIntResourceW(IDI_TASKDLG_CHEVRON_MORE) ) hInst = ModuleHelper::GetResourceInstance();
// Load icon...
UINT fuLoad = LR_DEFAULTCOLOR | LR_LOADTRANSPARENT;
if(NOT(hInst)
) fuLoad |= LR_SHARED;
LPCTSTR pstrIcon = IS_INTRESOURCE(pstr) ? (LPCTSTR) pstr
: W2CT(pstr);
PixSize sz;sz=cxy;
HICON hIcon = (HICON) ::LoadImage(hInst, pstrIcon, IMAGE_ICON, sz.cx, sz.cy, fuLoad);
if(NOT(hIcon)
) hIcon = (HICON) ::LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, sz.cx, sz.cy, LR_DEFAULTCOLOR | LR_SHARED | LR_LOADTRANSPARENT);
cxy =sz;
return hIcon;
}
void _LoadString(LPCWSTR pstr, LPTSTR pszBuffer, SIZE_T cchMax) const
{ AXE_(IS(pstr) ,return);
AXE_(IS(pszBuffer) ,return);
::ZeroMemory(pszBuffer, cchMax * sizeof(TCHAR));
USES_CONVERSION;
if(IS_INTRESOURCE(pstr)) ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(pstr), pszBuffer, (int)cchMax);
else ::lstrcpyn (pszBuffer, W2CT(pstr), (int)cchMax);
}
void _SplitCommandText(LPTSTR pstrBuffer, LPCTSTR& pstrTitle, SIZE_T& cchTitle, LPCTSTR& pstrText, SIZE_T& cchText) const
{
LPTSTR pstrSel = pstrBuffer;
while( (*pstrSel != '\0')
AND(*pstrSel != '\n')
) pstrSel = ::CharNext(pstrSel);
if(*pstrSel == '\0'
) {
pstrTitle = pstrBuffer;
pstrText = NULL;
cchTitle = lstrlen(pstrTitle);
cchText = 0;
}
else{pstrTitle = pstrBuffer;
pstrText = pstrSel + 1;
cchText = lstrlen(pstrText);
cchTitle = lstrlen(pstrBuffer) - cchText - 1;
}
}
DLUSize _GetTextSize(LPCWSTR pstr, LPTSTR pszBuffer, SIZE_T cchMax, UINT uStyle, HFONT hFont, xDlu cxMax) const
{
_LoadString(pstr, pszBuffer, cchMax);
return _GetTextSize(pszBuffer, (UINT) -1, uStyle, hFont, cxMax);
}
DLUSize _GetTextSizeHREF(LPCWSTR pstr, LPTSTR pszBuffer, SIZE_T cchMax, UINT uStyle, HFONT hFont, xDlu cxMax) const
{
_LoadString(pstr, pszBuffer, cchMax);
_RemoveHREF(pszBuffer);
DLUSize sizeText = _GetTextSize(pszBuffer, (UINT) -1, uStyle, hFont, cxMax);
_LoadString(pstr, pszBuffer, cchMax);
return sizeText;
}
DLUSize _GetTextSize(LPCTSTR pstr, SIZE_T cchMax, UINT uStyle, HFONT hFont, xDlu cxMax) const
{
CClientDC dc = m_cfg.hwndParent;
PixSize sizeText;
if( pstr == NULL ) return DLUSize();
if( pstr[0] == '\0' ) return DLUSize();
HFONT hOldFont = dc.SelectFont(hFont);
PixRect rc( 0, 0, cxMax.pix().n, 9999 );
if( cchMax == MAX_TEXT_LENGTH
) cchMax = (SIZE_T) -1;
dc.DrawText (pstr, (int)cchMax, &rc, DT_CALCRECT | uStyle);
dc.SelectFont(hOldFont);
PixSize size( rc.right - rc.left + 1, rc.bottom - rc.top + 1 );
DLUSize erg;erg=size;
erg.cy+=erg.cy/3;
return DLUSize()=size;
}
public:
};
class CTask98Dialog : public CTask98DialogImpl<CTask98Dialog>
{
};
/////////////////////////////////////////////////////////////////////////
// TaskDialog 98 helpers
//
HRESULT Task98DialogIndirect(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked,bool iconExpanderShow=false)
{ AXE_(IS(pTaskConfig) ,return E_INVALIDARG);
AXE_(pTaskConfig->cbSize==sizeof(TASKDIALOGCONFIG) ,return E_INVALIDARG);
if(IS(pnButton)) *pnButton = 0;
CTask98Dialog dlg;
dlg.ShowExpanderIcon =iconExpanderShow; AXE_(IS(
dlg.SetConfig(pTaskConfig)) ,return E_FAIL);
do{dlg.DoModal(pTaskConfig->hwndParent);
}while( dlg.IsNavigated() );
dlg.GetDialogResult(pnButton, pnRadioButton, pfVerificationFlagChecked);
return S_OK;
}
inline HRESULT Task98DialogIndirect(const TASKDIALOGCONFIG_X* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked,bool iconExpanderShow=false)
{ AXE_(IS(pTaskConfig) ,return E_INVALIDARG);
AXE_(pTaskConfig->cbSize ==sizeof(TASKDIALOGCONFIG) ,return E_INVALIDARG);
AXE_(pTaskConfig->cbSize_X==sizeof(TASKDIALOGCONFIG_X) ,return E_INVALIDARG);
if(IS(pnButton)) *pnButton = 0;
CTask98Dialog dlg;
dlg.ShowExpanderIcon =iconExpanderShow; AXE_(IS(
dlg.SetConfig(pTaskConfig)) ,return E_FAIL);
do{dlg.DoModal(pTaskConfig->hwndParent);
}while( dlg.IsNavigated() );
dlg.GetDialogResult(pnButton, pnRadioButton, pfVerificationFlagChecked);
return S_OK;
}
inline HRESULT Task98Dialog(HWND hwndParent, HINSTANCE hInstance, LPCTSTR pszWindowTitle, LPCTSTR pszMainInstruction, LPCTSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, LPCTSTR pszIcon, int* pnButton,bool iconExpanderShow=false)
{
TASKDIALOGCONFIG cfg = { 0 };
cfg.cbSize = sizeof(cfg);
cfg.hInstance = hInstance;
cfg.hwndParent = hwndParent;
cfg.dwCommonButtons = dwCommonButtons;
USES_CONVERSION;
cfg.pszWindowTitle = IS_INTRESOURCE(pszWindowTitle) ? (LPCWSTR) pszWindowTitle : T2CW(pszWindowTitle);
cfg.pszMainInstruction = IS_INTRESOURCE(pszMainInstruction) ? (LPCWSTR) pszMainInstruction : T2CW(pszMainInstruction);
cfg.pszContent = IS_INTRESOURCE(pszContent) ? (LPCWSTR) pszContent : T2CW(pszContent);
cfg.pszMainIcon = IS_INTRESOURCE(pszIcon) ? (LPCWSTR) pszIcon : T2CW(pszIcon);
return Task98DialogIndirect(&cfg, pnButton, NULL, NULL,iconExpanderShow);
}
#endif // !defined(AFX_TASKDIALOGEMU_H__20073232_5AA0_1E88_3A6D_0080AD509054__INCLUDED_)