|
楼主 |
发表于 2016-6-25 18:03
|
显示全部楼层
======================================================
从函数向导,或替换对话框中怎样调用 XLL 函数
======================================================
Excel 通常在 workbook 的重计算期间调用 XLL 函数。牢记,函数可能不存在单元格公式中,但可能会存在于命名的单元格区域中或条件格式表达式。
在两种情况下,函数可以从 Excel 对话框中调用。一种情况是 粘贴函数参数 对话框,在这里每次用户都可以在创建函数时,调用一个参数。另一种情况是, 通过替换对话框重新编辑公式时。由于粘贴函数 对话框,你可能不想你的函数正常执行。这也许是因为需要很长的时间来执行,你不想很久才能关闭对话框。
粘贴函数对话框,和 替换对话框 拥有窗口类名 bosa_sdm_XLn,n 是数值。Windows 提供 API 函数,GetClassName ,可以从窗口句柄中获取窗口名称,此名称是一个 HWND 变量类型。Windows 还支持 函数 EnumWindows , 该函数枚举所有屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数
回调函数需要执行,只需要通过以下几步:
* 检查当前窗口的父窗口是否为当前Excel实例(指的是同时运行多个Excel实例的情况)
* 从窗口句柄获取类型名。
* 检查类型名是否为为 bosa_sdm_XLn 的形式
* 如果你需要区分两个窗口对话框,可以通过检查对话框标题文本,进行识别。标题栏可以使用 Windows API GetWindowText 函数来获取。
下面的 C++ 代码将展示 类和回调传送到 Windows 的步骤。
注意:
未来的 Excel 版本,Windows 标题可能会发生改变,导致此代码无效。需要注意的还有,设置 windows_title_text 为 NULL,在回调查询中忽略标题的大小写效果。
#define CLASS_NAME_BUFFSIZE 50
#define WINDOW_TEXT_BUFFSIZE 50
// Data structure used as input to xldlg_enum_proc(), called by
// called_from_paste_fn_dlg(), called_from_replace_dlg(), and
// called_from_Excel_dlg(). These functions tell the caller whether
// the current worksheet function was called from one or either of
// these dialog boxes.
typedef struct
{
bool is_dlg;
short low_hwnd;
char *window_title_text; // set to NULL if don't care
}
xldlg_enum_struct;
// The callback function called by Windows for every top-level window.
BOOL CALLBACK xldlg_enum_proc(HWND hwnd, xldlg_enum_struct *p_enum)
{
// Check if the parent window is Excel.
if(LOWORD((DWORD)GetParent(hwnd)) != p_enum->low_hwnd)
return TRUE; // keep iterating
char class_name[CLASS_NAME_BUFFSIZE + 1];
// Ensure that class_name is always null terminated for safety.
class_name[CLASS_NAME_BUFFSIZE] = 0;
GetClassName(hwnd, class_name, CLASS_NAME_BUFFSIZE);
// Do a case-insensitve comparison for the Excel dialog window
// class name with the Excel version number truncated.
size_t len; // The length of the window's title text
if(_strnicmp(class_name, "bosa_sdm_xl", 11) == 0)
{
// Check if a searching for a specific title string
if(p_enum->window_title_text)
{
// Get the window's title and see if it matches the given text.
char buffer[WINDOW_TEXT_BUFFSIZE + 1];
buffer[WINDOW_TEXT_BUFFSIZE] = 0;
len = GetWindowText(hwnd, buffer, WINDOW_TEXT_BUFFSIZE);
if(len == 0) // No title
{
if(p_enum->window_title_text[0] != 0)
return TRUE; // No match, so keep iterating
}
// Window has a title so do a case-insensitive comparison of the
// title and the search text, if provided.
else if(p_enum->window_title_text[0] != 0
&& _stricmp(buffer, p_enum->window_title_text) != 0)
return TRUE; // Keep iterating
}
p_enum->is_dlg = true;
return FALSE; // Tells Windows to stop iterating.
}
return TRUE; // Tells Windows to continue iterating.
}
粘贴函数对话框,没有标题,因此接下来的函数传递的标题字符为 “”,代表这是一个空字符,通知回调函数,没有可以匹配的 标题。
bool called_from_paste_fn_dlg(void)
{
XLOPER xHwnd;
// Calls Excel4, which only returns the low part of the Excel
// main window handle. This is OK for the search however.
if(Excel4(xlGetHwnd, &xHwnd, 0))
return false; // Couldn't get it, so assume not
// Search for bosa_sdm_xl* dialog box with no title string.
xldlg_enum_struct es = {FALSE, xHwnd.val.w, ""};
EnumWindows((WNDENUMPROC)xldlg_enum_proc, (LPARAM)&es);
return es.is_dlg;
}
|
|