Index: src/ch/CfgProperties.h =================================================================== diff -u -N -rf25056c67d674c9491c8b23354236a253037132d -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/CfgProperties.h (.../CfgProperties.h) (revision f25056c67d674c9491c8b23354236a253037132d) +++ src/ch/CfgProperties.h (.../CfgProperties.h) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -102,8 +102,12 @@ PP_SHORTCUTS, PP_RECENTPATHS, + // dialog box "do not show" info + PP_HIDE_SHELLEXT_UNREGISTERED, + PP_HIDE_SHELLEXT_VERSIONMISMATCH, + // invisible options - PP_LAST_UPDATE_TIMESTAMP + PP_LAST_UPDATE_TIMESTAMP, }; enum EUpdatesFrequency @@ -118,6 +122,13 @@ eFreq_Max }; +enum EDoNotShowDialog_ShellExtension +{ + eDNS_AlwaysShow = 0, + eDNS_HideAndRegister = 1, + eDNS_HideAndDontRegister = 2 +}; + /////////////////////////////////////////////////////////////////////////////////////////////// // specific branches in configuration @@ -245,6 +256,10 @@ PROPERTY(PP_SHINTERCEPTKEYACTIONS, bool, _T("CHConfig.ShellExtension.InterceptKeyboardActions"), true); PROPERTY(PP_SHINTERCEPTCTXMENUACTIONS, bool, _T("CHConfig.ShellExtension.InterceptDefaultContextMenuActions"), false); +// "do not show" dialog boxes +PROPERTY(PP_HIDE_SHELLEXT_UNREGISTERED, int, _T("CHConfig.GUI.ShowHideDialogs.ShellExtensionUnregistered"), eDNS_AlwaysShow); +PROPERTY(PP_HIDE_SHELLEXT_VERSIONMISMATCH, int, _T("CHConfig.GUI.ShowHideDialogs.ShellExtensionVersionMismatch"), eDNS_AlwaysShow); + // Invisible options PROPERTY_MINMAX(PP_LAST_UPDATE_TIMESTAMP, long long, _T("CHConfig.RuntimeState.LastCheckedForUpdates"), 0, 0, LLONG_MAX); Index: src/ch/OptionsDlg.cpp =================================================================== diff -u -N -rf25056c67d674c9491c8b23354236a253037132d -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision f25056c67d674c9491c8b23354236a253037132d) +++ src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -279,6 +279,10 @@ PROP_BOOL(IDS_CFGINTERCEPTKEYACTION_STRING, GetPropValue(GetConfig())); PROP_BOOL(IDS_CFGINTERCEPTCONTEXTMENU_STRING, GetPropValue(GetConfig())); + PROP_SEPARATOR(IDS_DIALOGS_SHOW_HIDE_STRING); + PROP_COMBO(IDS_SHELLEXT_REGISTER_SHOWHIDE_STRING, MakeCompoundString(IDS_ALWAYS_SHOW_STRING, 3, _T("!")), GetPropValue(GetConfig())); + PROP_COMBO(IDS_SHELLEXT_VERSIONMISMATCH_SHOWHIDE_STRING, MakeCompoundString(IDS_ALWAYS_SHOW_STRING, 3, _T("!")), GetPropValue(GetConfig())); + PROP_SEPARATOR(IDS_PROCESSINGTHREAD_STRING); PROP_BOOL(IDS_SETDESTATTRIB_STRING, GetPropValue(GetConfig())); PROP_BOOL(IDS_SETDESTTIME_STRING, GetPropValue(GetConfig())); @@ -384,6 +388,10 @@ SetPropValue(rConfig, GetBoolProp(iPosition++)); SKIP_SEPARATOR(iPosition); + SetPropValue(rConfig, GetIndexProp(iPosition++)); + SetPropValue(rConfig, GetIndexProp(iPosition++)); + + SKIP_SEPARATOR(iPosition); SetPropValue(rConfig, GetBoolProp(iPosition++)); SetPropValue(rConfig, GetBoolProp(iPosition++)); SetPropValue(rConfig, GetBoolProp(iPosition++)); Index: src/ch/TMsgBox.cpp =================================================================== diff -u -N -r2648234e4e3ce1cf79d1bad88a94d07315e1e694 -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/TMsgBox.cpp (.../TMsgBox.cpp) (revision 2648234e4e3ce1cf79d1bad88a94d07315e1e694) +++ src/ch/TMsgBox.cpp (.../TMsgBox.cpp) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -38,7 +38,9 @@ m_eButtons(eButtons), m_eIcon(eIcon), m_rcRichEdit(0,0,0,0), - m_rcDialogMinSize(0,0,0,0) + m_rcDialogMinSize(0,0,0,0), + m_bCheckboxChecked(false), + m_iCheckBoxHeight(0) { m_strMessageText = GetResManager().LoadString(uiMsgResourceID); } @@ -47,7 +49,11 @@ CLanguageDialog(IDD_MSGBOX_DIALOG, pParent), m_strMessageText(strMessage), m_eButtons(eButtons), - m_eIcon(eIcon) + m_eIcon(eIcon), + m_rcRichEdit(0,0,0,0), + m_rcDialogMinSize(0,0,0,0), + m_bCheckboxChecked(false), + m_iCheckBoxHeight(0) { } @@ -74,6 +80,8 @@ m_ctlMeasureRichEdit.SetEventMask(m_ctlRichEdit.GetEventMask() | ENM_REQUESTRESIZE); + InitRichEdit(); + AddResizableControl(IDC_IMAGE_STATIC, 0.0, 0.0, 0.0, 0.0); AddResizableControl(IDC_MSG_RICHEDIT, 0.0, 0.0, 1.0, 1.0); AddResizableControl(IDC_FIRST_BUTTON, 1.0, 1.0, 0.0, 0.0); @@ -86,7 +94,7 @@ m_ctlRichEdit.GetWindowRect(&m_rcRichEdit); ScreenToClient(&m_rcRichEdit); - GetWindowRect(&m_rcDialogMinSize); + CalculateMinimumDlgSize(); // initialize controls' texts InitializeControls(); @@ -98,6 +106,8 @@ { const int iUndefinedResult = IDCANCEL; + m_bCheckboxChecked = m_ctlCheck.GetCheck() == BST_CHECKED; + switch(m_eButtons) { case eOk: @@ -128,6 +138,8 @@ { const int iUndefinedResult = IDCANCEL; + m_bCheckboxChecked = m_ctlCheck.GetCheck() == BST_CHECKED; + // the middle button switch(m_eButtons) { @@ -159,6 +171,8 @@ { const int iUndefinedResult = IDCANCEL; + m_bCheckboxChecked = m_ctlCheck.GetCheck() == BST_CHECKED; + // the rightmost button switch(m_eButtons) { @@ -265,22 +279,30 @@ { if(pNMHDR->idFrom == IDC_MEASURE_RICHEDIT) { - // get current monitor's resolution (and an aspect ratio) - CSize sizeMax = GetMaxSize(); + // get the difference in sizes between richedit and dialog + CSize sizeDiffDlgRichEdit(m_rcDialogMinSize.Width() - m_rcRichEdit.Width(), m_rcDialogMinSize.Height() - m_rcRichEdit.Height()); // new rich edit control width/height suggestion int iSuggestedWidth = pResize->rc.right - pResize->rc.left; int iSuggestedHeight = pResize->rc.bottom - pResize->rc.top; - int iSuggestedArea = iSuggestedWidth * iSuggestedHeight; - // calculate approximate new height/width of a control with monitor's aspect ratio + // projected dialog size when using the recommended richedit size + CSize sizeProjectedDlgSize(iSuggestedWidth + sizeDiffDlgRichEdit.cx, iSuggestedHeight + sizeDiffDlgRichEdit.cy); + + // get current monitor's resolution (and an aspect ratio) + CSize sizeMax = GetMaxSize(); + CSize sizeAspectRatio(sizeMax.cx, (int)(sizeMax.cy / 1.5)); + + int iSuggestedArea = sizeProjectedDlgSize.cx * sizeProjectedDlgSize.cy; + + // calculate approximate new height/width of a dialog with monitor's aspect ratio // with total area similar to the suggested one - int iCalcWidth = (int)sqrt((double)sizeMax.cx * (double)iSuggestedArea / (double)sizeMax.cy); - int iCalcHeight = (int)sqrt((double)sizeMax.cy * (double)iSuggestedArea / (double)sizeMax.cx); + int iCalcWidth = (int)sqrt((double)sizeAspectRatio.cx * (double)iSuggestedArea / (double)sizeAspectRatio.cy); + int iCalcHeight = (int)sqrt((double)sizeAspectRatio.cy * (double)iSuggestedArea / (double)sizeAspectRatio.cx); // calculate control size difference to apply to the dialog size - int iWidthDiff = iCalcWidth - m_rcRichEdit.Width(); - int iHeightDiff = iCalcHeight - m_rcRichEdit.Height(); + int iWidthDiff = iCalcWidth - sizeDiffDlgRichEdit.cx - m_rcRichEdit.Width(); + int iHeightDiff = iCalcHeight - sizeDiffDlgRichEdit.cy - m_rcRichEdit.Height(); // and apply the diff CRect rcThis(0,0,0,0); @@ -317,7 +339,7 @@ CRect rcThis(0,0,0,0); GetWindowRect(&rcThis); - SetWindowPos(NULL, 0, 0, rcThis.Width() + iWidthDiff, rcThis.Height() + iHeightDiff, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE); + SetWindowPos(NULL, 0, 0, rcThis.Width() + iWidthDiff, rcThis.Height() + iHeightDiff + (m_iCheckBoxHeight / 2), SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE); m_ctlRichEdit.SetEventMask(m_ctlRichEdit.GetEventMask() & ~ENM_REQUESTRESIZE); } @@ -365,3 +387,66 @@ lpMMI->ptMinTrackSize.y = m_rcDialogMinSize.Height(); } } + +void TMsgBox::OnCancel() +{ + m_bCheckboxChecked = m_ctlCheck.GetCheck() == BST_CHECKED; + + EndDialog(IDCANCEL); +} + +bool TMsgBox::WasChecked() const +{ + return m_bCheckboxChecked; +} + +INT_PTR TMsgBox::MsgBox(UINT uiMsgResourceID, EButtonConfig eButtons, EIconConfig eIcon, UINT uiCheckboxResourceID /*= 0*/, bool* pbWasChecked, CWnd* pParent /*= NULL*/) +{ + TMsgBox msgBox(uiMsgResourceID, eButtons, eIcon, pParent); + msgBox.SetCheckBoxMessage(uiCheckboxResourceID); + INT_PTR iResult = msgBox.DoModal(); + if(pbWasChecked) + *pbWasChecked = msgBox.WasChecked(); + return iResult; +} + +INT_PTR TMsgBox::MsgBox(const CString& strMessage, EButtonConfig eButtons, EIconConfig eIcon, const CString& strCheckboxText /*= CString()*/, bool* pbWasChecked, CWnd* pParent /*= NULL*/) +{ + TMsgBox msgBox(strMessage, eButtons, eIcon, pParent); + msgBox.SetCheckBoxMessage(strCheckboxText); + INT_PTR iResult = msgBox.DoModal(); + if(pbWasChecked) + *pbWasChecked = msgBox.WasChecked(); + return iResult; +} + +void TMsgBox::InitRichEdit() +{ + COLORREF crTextColor = GetSysColor(COLOR_BTNTEXT); + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + + m_ctlRichEdit.GetDefaultCharFormat(cf); + cf.dwMask |= CFM_COLOR; + cf.dwEffects &= ~CFE_AUTOCOLOR; + cf.crTextColor = crTextColor; + m_ctlRichEdit.SetDefaultCharFormat(cf); +} + +void TMsgBox::CalculateMinimumDlgSize() +{ + // remember the initial size of the dialog as this is the minimal size + GetWindowRect(&m_rcDialogMinSize); + + // if the checkbox is to be shown then increase minimum height so that the + // checkbox is placed a little more below richedit + if(!m_strCheckboxText.IsEmpty()) + { + CRect rcCheck(0,0,0,0); + + m_ctlCheck.GetWindowRect(&rcCheck); + m_iCheckBoxHeight = rcCheck.Height(); + + m_rcDialogMinSize.bottom += m_iCheckBoxHeight; + } +} Index: src/ch/TMsgBox.h =================================================================== diff -u -N -r2648234e4e3ce1cf79d1bad88a94d07315e1e694 -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/TMsgBox.h (.../TMsgBox.h) (revision 2648234e4e3ce1cf79d1bad88a94d07315e1e694) +++ src/ch/TMsgBox.h (.../TMsgBox.h) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -48,9 +48,20 @@ void SetCheckBoxMessage(UINT uiMsgResourceID); void SetCheckBoxMessage(const CString& strCheckboxMessage); + bool WasChecked() const; + + static INT_PTR MsgBox(UINT uiMsgResourceID, EButtonConfig eButtons, EIconConfig eIcon, UINT uiCheckboxResourceID = 0, bool* pbWasChecked = NULL, CWnd* pParent = NULL); + static INT_PTR MsgBox(const CString& strMessage, EButtonConfig eButtons, EIconConfig eIcon, const CString& strCheckboxText = CString(), bool* pbWasChecked = NULL, CWnd* pParent = NULL); + protected: virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnInitDialog(); + + void CalculateMinimumDlgSize(); + + void InitRichEdit(); + + virtual void OnCancel(); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void InitializeControls(); @@ -80,7 +91,10 @@ CRect m_rcRichEdit; CRect m_rcDialogMinSize; + int m_iCheckBoxHeight; + bool m_bCheckboxChecked; + protected: DECLARE_MESSAGE_MAP() DECLARE_DYNAMIC(TMsgBox) Index: src/ch/ch.cpp =================================================================== diff -u -N -r2648234e4e3ce1cf79d1bad88a94d07315e1e694 -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/ch.cpp (.../ch.cpp) (revision 2648234e4e3ce1cf79d1bad88a94d07315e1e694) +++ src/ch/ch.cpp (.../ch.cpp) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -424,20 +424,6 @@ return FALSE; } - // tmp -/* - CString strShortText = _T("Short info only"); - TMsgBox msgBox1(strShortText, TMsgBox::eOk, TMsgBox::eIcon_Info); - if(msgBox1.DoModal()) - strShortText;// return -1; - - CString strLongText = _T("This is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big. This is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big. This is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line. This is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\nThis is some very very long text to be displayed in the text message box. There is no formatting applied (unfortunately) and we don't have any plans to incorporate it. This text should be split into multiple lines to avoid making dialog box too big.\nThere is also a shorter second line.\n"); - TMsgBox msgBox(strLongText, TMsgBox::eOkCancel, TMsgBox::eIcon_Warning); - if(msgBox.DoModal()) - return -1; -*/ - // /tmp - // ================================= Shell extension ======================================== LOG_INFO(_T("Checking shell extension compatibility")); @@ -476,8 +462,14 @@ // validate ch version against extension version CString strExtensionStringVersion; long lExtensionVersion = 0; - int iDlgResult = IDNO; + INT_PTR iDlgResult = IDNO; + chcore::TConfig& rConfig = GetConfig(); + + int iDoNotShowAgain_Unregistered = GetPropValue(rConfig); + int iDoNotShowAgain_VersionMismatch = GetPropValue(rConfig); + bool bDontShow = false; + // first try to just enable the extension (assume that it has already been registered) HRESULT hResult = m_tShellExtClient.EnableExtensionIfCompatible(PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4, lExtensionVersion, strExtensionStringVersion); if(FAILED(hResult)) @@ -486,17 +478,54 @@ strMsg.Format(_T("Shell extension is not registered.")); LOG_WARNING(strMsg); - iDlgResult = MsgBox(IDS_SHELL_EXTENSION_UNREGISTERED_STRING, MB_ICONWARNING | MB_YESNO); + switch(iDoNotShowAgain_Unregistered) + { + case eDNS_HideAndRegister: + iDlgResult = IDYES; + break; + + case eDNS_HideAndDontRegister: + iDlgResult = IDNO; + break; + + case eDNS_AlwaysShow: + default: + { + iDlgResult = TMsgBox::MsgBox(IDS_SHELL_EXTENSION_UNREGISTERED_STRING, TMsgBox::eYesNo, TMsgBox::eIcon_Warning, IDS_DO_NOT_SHOW_AGAIN_STRING, &bDontShow); + if(bDontShow) + SetPropValue(rConfig, (iDlgResult == IDYES) ? eDNS_HideAndRegister : eDNS_HideAndDontRegister); + } + } } else if(hResult == S_FALSE) { CString strMsg; strMsg.Format(_T("Shell extension has different version (0x%lx) than Copy Handler (0x%lx)."), lExtensionVersion, PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4); LOG_WARNING(strMsg); - iDlgResult = MsgBox(IDS_SHELL_EXTENSION_MISMATCH_STRING, MB_ICONWARNING | MB_YESNO); + switch(iDoNotShowAgain_VersionMismatch) + { + case eDNS_HideAndRegister: + iDlgResult = IDYES; + break; + + case eDNS_HideAndDontRegister: + iDlgResult = IDNO; + break; + + case eDNS_AlwaysShow: + default: + { + iDlgResult = TMsgBox::MsgBox(IDS_SHELL_EXTENSION_MISMATCH_STRING, TMsgBox::eYesNo, TMsgBox::eIcon_Warning, IDS_DO_NOT_SHOW_AGAIN_STRING, &bDontShow); + if(bDontShow) + SetPropValue(rConfig, (iDlgResult == IDYES) ? eDNS_HideAndRegister : eDNS_HideAndDontRegister); + } + } } + if(bDontShow) + rConfig.Write(); + // we didn't succeed, but want to fix this if(iDlgResult == IDYES) { Index: src/ch/ch.rc =================================================================== diff -u -N -r2648234e4e3ce1cf79d1bad88a94d07315e1e694 -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/ch.rc (.../ch.rc) (revision 2648234e4e3ce1cf79d1bad88a94d07315e1e694) +++ src/ch/ch.rc (.../ch.rc) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -1115,6 +1115,13 @@ IDS_TASK_CREATE_FAILED "Cannot create new task. Reason: %reason." IDS_TASKMANAGER_LOAD_FAILED "Failed to load task list database. Copy Handler will create a new, empty database for you." + IDS_DO_NOT_SHOW_AGAIN_STRING "Do not show this message again" + IDS_ALWAYS_SHOW_STRING "Always show" + IDS_HIDE_AND_REGISTER "Hide and register extension" + IDS_HIDE_AND_DONT_REGISTER "Hide and do not register extension" + IDS_DIALOGS_SHOW_HIDE_STRING "Show/hide dialogs" + IDS_SHELLEXT_REGISTER_SHOWHIDE_STRING "Show message about shell extension not registered" + IDS_SHELLEXT_VERSIONMISMATCH_SHOWHIDE_STRING "Show message about shell extension version mismatch" END STRINGTABLE Index: src/ch/resource.h =================================================================== diff -u -N -r096451721a732567aad7e103bfe2d0a9f2f32c95 -r75318f0d3808d8d3c02dbc333c80b6d6e07fae13 --- src/ch/resource.h (.../resource.h) (revision 096451721a732567aad7e103bfe2d0a9f2f32c95) +++ src/ch/resource.h (.../resource.h) (revision 75318f0d3808d8d3c02dbc333c80b6d6e07fae13) @@ -383,6 +383,13 @@ #define IDS_TASK_IMPORT_FAILED 5031 #define IDS_TASK_CREATE_FAILED 5032 #define IDS_TASKMANAGER_LOAD_FAILED 5033 +#define IDS_DO_NOT_SHOW_AGAIN_STRING 5034 +#define IDS_ALWAYS_SHOW_STRING 5035 +#define IDS_HIDE_AND_REGISTER 5036 +#define IDS_HIDE_AND_DONT_REGISTER 5037 +#define IDS_DIALOGS_SHOW_HIDE_STRING 5040 +#define IDS_SHELLEXT_REGISTER_SHOWHIDE_STRING 5041 +#define IDS_SHELLEXT_VERSIONMISMATCH_SHOWHIDE_STRING 5042 #define IDS_ONECOPY_STRING 6000 #define IDS_REGISTEROK_STRING 6001 #define IDS_REGISTERERR_STRING 6002