Доступ к дескрипторам экземпляра Excel и главного окна
Область применения: Excel 2013 | Office 2013 | Visual Studio
Для программирования в среде Windows иногда необходимо знать дескриптор экземпляра Microsoft Excel или main дескриптор окна. Например, эти дескрипторы полезны при создании и отображении настраиваемых диалоговых окон Windows.
Существует две функции API C только XLL, которые предоставляют доступ к этим дескрипторам: функция xlGetInst и функция xlGetHwnd соответственно. В Win32 все дескрипторы являются 32-разрядными целыми числами. Однако при разработке XLOPER Windows была 16-разрядной системой. Таким образом, структура допускается только для 16-разрядных дескрипторов. В Win32 при вызове с помощью Excel4 или Excel4v функция xlGetInst и функция xlGetHwnd возвращают только низкую часть полного 32-разрядного дескриптора.
В Excel 2007 и более поздних версиях, когда эти функции вызываются с помощью Excel12 или Excel12v, возвращаемый XLOPER12 содержит полный 32-разрядный дескриптор.
Получить полный дескриптор экземпляра очень просто в любой версии Excel, так как он передается в обратный вызов Windows DllMain, который вызывается при загрузке библиотеки DLL. Если этот дескриптор экземпляра записывается в глобальную переменную, не нужно вызывать функцию xlGetInst .
Получение основного дескриптора Excel в Excel 2003 и более ранних версиях
Чтобы получить дескриптор Excel main в Excel 2003 и более ранних 32-разрядных версиях, необходимо сначала вызвать функцию xlGetHwnd, чтобы получить нижнее слово фактического дескриптора. Затем необходимо выполнить итерацию списка окон верхнего уровня, чтобы найти совпадение с возвращенным низким словом. Этот метод показан в следующем коде.
typedef struct _EnumStruct
{
HWND hwnd; // Return value for Excel main hWnd.
unsigned short wLoword; //Contains LowWord of the Excel main hWnd
} EnumStruct;
#define CLASS_NAME_BUFFER 50
BOOL CALLBACK EnumProc(HWND hwnd, EnumStruct * pEnum)
{
// First check the class of the window. Must be "XLMAIN".
char rgsz[CLASS_NAME_BUFFER];
GetClassName(hwnd, rgsz, CLASS_NAME_BUFFER);
if (!lstrcmpi(rgsz, "XLMAIN"))
{
// If that hits, check the loword of the window handle.
if (LOWORD((DWORD) hwnd) == pEnum->wLoword)
{
// We have a match, return Excel main hWnd.
pEnum->hwnd = hwnd;
return FALSE;
}
}
// No match - continue the enumeration.
return TRUE;
}
BOOL GetHwnd(HWND * pHwnd)
{
XLOPER x;
//
// xlGetHwnd only returns the LoWord of Excel hWnd
// so all the windows have to be enumerated to see
// which match the LoWord returned by xlGetHwnd.
//
if (Excel4(xlGetHwnd, &x, 0) == xlretSuccess)
{
EnumStruct enm;
enm.hwnd = NULL;
enm.wLoword = x.val.w;
EnumWindows((WNDENUMPROC) EnumProc, (LPARAM) &enm);
if (enm.hwnd != NULL)
{
*pHwnd = enm.hwnd;
return TRUE;
}
}
return FALSE;
}
См. также
Отображение диалоговых окон из библиотеки DLL или XLL
Функции API C, которые можно вызывать только из библиотеки DLL или XLL