From 9f147b2a78a19fe9f92f1d78bf1add58ab93e014 Mon Sep 17 00:00:00 2001 From: fancidev Date: Sat, 17 Oct 2015 13:50:03 +0800 Subject: [PATCH] Return #N/A if a heavy function is called from a dialog box. --- XllConnector/Invoke.cpp | 36 ++++++++++++++++++++++++++++++- XllConnector/Invoke.h | 4 ++++ XllConnector/Wrapper.h | 6 ++++++ XllExamples/ArithmeticExample.cpp | 2 +- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/XllConnector/Invoke.cpp b/XllConnector/Invoke.cpp index 3271099..5fff564 100644 --- a/XllConnector/Invoke.cpp +++ b/XllConnector/Invoke.cpp @@ -79,4 +79,38 @@ ExcelVariant ExcelCall(int xlfn, const T&... args) Excel12(xlFree, 0, 1, &result); return vResult; } -#endif \ No newline at end of file +#endif + +namespace XLL_NAMESPACE +{ + // How to: Call XLL Functions from the Function Wizard or Replace Dialog Boxes + // https://msdn.microsoft.com/EN-US/library/office/bb687909.aspx + + static BOOL CALLBACK IsDialogBoxOpen_Callback(HWND hwnd, LPARAM lParam) + { + bool *pFound = (bool*)lParam; + + DWORD dwProcessId = 0; + GetWindowThreadProcessId(hwnd, &dwProcessId); + if (dwProcessId == GetCurrentProcessId()) + { + WCHAR szClassName[100]; + if (GetClassNameW(hwnd, szClassName, ARRAYSIZE(szClassName))) + { + if (_wcsnicmp(szClassName, L"bosa_sdm_XL", 11) == 0) + { + *pFound = true; + return FALSE; // stop iterating + } + } + } + return TRUE; // keep iterating + } + + bool IsDialogBoxOpen() + { + bool bFoundDialog = false; + EnumWindows(IsDialogBoxOpen_Callback, (LPARAM)&bFoundDialog); + return bFoundDialog; + } +} \ No newline at end of file diff --git a/XllConnector/Invoke.h b/XllConnector/Invoke.h index b77f494..ce6fe2e 100644 --- a/XllConnector/Invoke.h +++ b/XllConnector/Invoke.h @@ -22,4 +22,8 @@ namespace XLL_NAMESPACE explicit ExcelException(int errorCode); const char* what() const override { return m_errorMessage; } }; + + // Returns true if the Function Wizard or Replace dialog box is + // open in the current Excel session. + bool IsDialogBoxOpen(); } diff --git a/XllConnector/Wrapper.h b/XllConnector/Wrapper.h index 0bd24cb..32d0c30 100644 --- a/XllConnector/Wrapper.h +++ b/XllConnector/Wrapper.h @@ -7,6 +7,7 @@ #include "FunctionInfo.h" #include "Conversion.h" #include "Marshal.h" +#include "Invoke.h" // // strip_cc, strip_cc_t @@ -179,6 +180,11 @@ namespace XLL_NAMESPACE { try { + if (IsHeavy && IsDialogBoxOpen()) + { + return const_cast(&Constants::ErrNA); + } + LPXLOPER12 pvRetVal = AllocateReturnValue(IsThreadSafe); HRESULT hr = CreateValue(pvRetVal, func(ArgumentMarshaler::Marshal(args)...)); diff --git a/XllExamples/ArithmeticExample.cpp b/XllExamples/ArithmeticExample.cpp index bc29595..4145d9a 100644 --- a/XllExamples/ArithmeticExample.cpp +++ b/XllExamples/ArithmeticExample.cpp @@ -18,7 +18,7 @@ namespace custom_ns } } -EXPORT_XLL_FUNCTION_AS(custom_ns::GetCircleArea, GetCircleArea); +EXPORT_XLL_FUNCTION_AS(custom_ns::GetCircleArea, GetCircleArea, XLL_LIGHT); namespace {