TN003. Сопоставление дескрипторов Windows с объектами
В этом примечании описываются подпрограммы MFC, поддерживающие сопоставление объектов Windows с объектами C++ .
Проблема
Объекты Windows обычно представлены различными объектами HANDLE , классы MFC упаковывают дескриптор объектов Windows с объектами C++. Функции оболочки библиотеки классов MFC позволяют найти объект C++, который упаковывает объект Windows с определенным дескриптором. Однако иногда объект не имеет объекта оболочки C++ и в эти времена система создает временный объект для действия в качестве оболочки C++.
Объекты Windows, использующие карты дескрипторов, приведены ниже.
HWND (CWnd и
CWnd
производные классы)HDC (CDC и
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++ из одного потока в другой часто приводит к непредвиденным результатам.
См. также
Технические примечания по номеру
Технические примечания по категории