Considerations for the Function Wizard

The Function Wizard allows the user to construct an expression's arguments interactively. As a part of this process, the Function Wizard evaluates functions with the user's proposed arguments and displays the result. Each time an argument is entered the function is recalculated. For simple functions that quickly calculate a value this process does not cause a problem. Unfortunately, functions that access external data as a part of calculations, or functions that require a significant amount of time in order to calculate, don't work well, because the time required to calculate or retrieve external data is annoyingly long.

The Function Wizard cannot automatically determine which functions should not be calculated during expression construction. It is therefore up to each XLL function to refuse to calculate if it is called at an inappropriate time. Use the following code to determine if the function wizard window is showing.

#define CLASS_NAME_BUFFER    50

typedef struct _EnumStruct {
    BOOL bFuncWiz;
    short hwndXLMain;
} EnumStruct, FAR * LPEnumStruct;

double WINAPI FuncWiz(double FAR * pdOne, double FAR * pdTwo)
{
    double dResult;
    
    if(IsCalledByFuncWiz())
        return 0;
    
    dResult = *pdOne * *pdTwo;
    return dResult; 
}

BOOL IsCalledByFuncWiz(void)
{
    XLOPER xHwndMain;
    EnumStruct    enm;

    if (Excel4(xlGetHwnd, &xHwndMain, 0) == xlretSuccess) 
    {
        enm.bFuncWiz = FALSE;
        enm.hwndXLMain = xHwndMain.val.w;
        EnumWindows((WNDENUMPROC) EnumProc,
            (LPARAM) ((LPEnumStruct)  &enm)); 
        return enm.bFuncWiz;
    }
    return FALSE;    //safe case: Return False if not sure
} 

BOOL CALLBACK EnumProc(HWND hwnd, LPEnumStruct pEnum)
{
    // first check the class of the window.  Will be szXLDialogClass
    // if function wizard dialog is up in Excel
    char rgsz[CLASS_NAME_BUFFER];
    GetClassName(hwnd, (LPSTR)rgsz, CLASS_NAME_BUFFER);
    if (2 == CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH,
        SUBLANG_ENGLISH_US),SORT_DEFAULT), NORM_IGNORECASE,
        (LPSTR)rgsz,  (lstrlen((LPSTR)rgsz)>lstrlen("bosa_sdm_XL")) 
        ? lstrlen("bosa_sdm_XL"):-1, "bosa_sdm_XL", -1)) 
    {
        if(LOWORD((DWORD) GetParent(hwnd)) == pEnum->hwndXLMain) 
        {
            pEnum->bFuncWiz = TRUE;
            return FALSE;
        }
    }
    // no luck - continue the enumeration
    return TRUE;
}