Поделиться через


TN003: сопоставление дескрипторов Windows с объектами

Замечание

Библиотека классов Microsoft Foundation (MFC) продолжает поддерживаться. Однако мы больше не добавляем функции или обновляем документацию.

В этом примечании описываются подпрограммы MFC, поддерживающие сопоставление объектов Windows с объектами C++ .

Проблема

Объекты Windows обычно представлены различными объектами HANDLE , классы MFC упаковывают дескриптор объектов Windows с объектами C++. Функции оболочки библиотеки классов MFC позволяют найти объект C++, который упаковывает объект Windows с определенным дескриптором. Однако иногда объект не имеет объекта оболочки C++ и в эти времена система создает временный объект для действия в качестве оболочки C++.

Объекты Windows, использующие карты дескрипторов, приведены ниже.

  • HWND (CWnd и CWnd, и производные классы)

  • HDC (CDC и классы, производные от них)

  • HMENU (CMenu)

  • HPEN (CGdiObject)

  • HBRUSH (CGdiObject)

  • HFONT (CGdiObject)

  • HBITMAP (CGdiObject)

  • HPALETTE (CGdiObject)

  • HRGN (CGdiObject)

  • HIMAGELIST (CImageList)

  • SOCKET (CSocket)

При наличии дескриптора для любого из этих объектов можно найти объект MFC, который упаковывает дескриптор, вызвав статический метод FromHandle. Например, если дан HWND с именем hWnd, следующая строка кода вернет указатель на объект CWnd, который обертывает hWnd:

CWnd::FromHandle(hWnd)

Если hWnd не имеет определенного объекта-оболочки CWnd , создается временная оболочка для переноса hWnd. Это позволяет получить валидный объект C++ из любого дескриптора.

Получив объект-оболочку, вы можете получить его дескриптор из общедоступной переменной члена класса-оболочки. В случае, когда CWnd, m_hWnd содержит HWND для этого объекта.

Присоединение дескрипторов к объектам MFC

Если у вас есть недавно созданный объект-оболочка дескриптора и дескриптор Windows-объекта, вы можете связать их, вызвав функцию Attach как в этом примере:

CWnd myWnd;
myWnd.Attach(hWnd);

Создает запись в постоянной карте, связывающей myWnd и hWnd. Теперь вызов CWnd::FromHandle(hWnd) возвращает указатель на myWnd. При удалении myWnd деструктор автоматически уничтожает hWnd путем вызова функции Windows DestroyWindow . Если это не нужно, hWnd необходимо отсоединить от myWnd до того, как myWnd будет уничтожен (обычно при выходе из области, в которой был определен myWnd). Этот Detach метод делает это.

myWnd.Detach();

Дополнительные сведения о временных объектах

Всякий раз, когда FromHandle выдается дескриптор, который еще не имеет объекта-обертки, создаются временные объекты. Эти временные объекты отсоединяются от их дескриптора и удаляются функциями DeleteTempMap . По умолчанию CWinThread::OnIdle автоматически вызывает DeleteTempMap для каждого класса, поддерживающего карты временных указателей. Это означает, что невозможно предположить, что указатель на временный объект будет допустимым после точки выхода из функции, в которой был получен указатель.

Объекты-оболочки и несколько потоков

Как временные, так и постоянные объекты поддерживаются для каждого потока. То есть один поток не может получить доступ к объектам-оболочкам C++ другого потока независимо от того, является ли он временным или постоянным.

Чтобы передать эти объекты из одного потока в другой, всегда отправляйте их в качестве собственного HANDLE типа. Передача объекта оболочки C++ из одного потока в другой часто приводит к непредвиденным результатам.

См. также

Технические примечания по номеру
Технические заметки по категориям