Доступ к дескрипторам экземпляра 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

Разработка XLL-файлов для Excel