Windows2003-3790/windows/advcore/duser/engine/winapi/dwpex.cpp
2020-09-30 16:53:55 +02:00

256 lines
6.8 KiB
C++

#include "stdafx.h"
#include "WinAPI.h"
#include "DwpEx.h"
/***************************************************************************\
*****************************************************************************
*
* DefWindowProcEx Extensions
*
*****************************************************************************
\***************************************************************************/
//------------------------------------------------------------------------------
struct ExtraInfo
{
HWND hwnd; // For easy reference
WNDPROC pfnOldWndProc; // Original wndproc before subclassing
HWndContainer * pconOwner; // Gadget container for this window
};
//------------------------------------------------------------------------------
ExtraInfo *
RawGetExtraInfo(HWND hwnd)
{
return (ExtraInfo *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
LRESULT ExtraInfoWndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
/***************************************************************************\
*
* GetExtraInfo
*
* GetExtraInfo() returns an ExtraInfo block for a given window. If the
* window does not already have an EI block, a new one is allocated, attached
* to the window and subclassed.
*
\***************************************************************************/
ExtraInfo *
GetExtraInfo(HWND hwnd)
{
if (!ValidateHWnd(hwnd)) {
return NULL;
}
// First, check if the info already exists
ExtraInfo * pei = RawGetExtraInfo(hwnd);
if (pei != NULL) {
return pei;
}
pei = ProcessNew(ExtraInfo);
if (pei != NULL) {
pei->hwnd = hwnd;
pei->pfnOldWndProc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
pei->pconOwner = NULL;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) pei);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) ExtraInfoWndProc);
}
return pei;
}
/***************************************************************************\
*
* RemoveExtraInfo
*
* RemoveExtraInfo() cleans up any objects allocated in a HWND's ExtraInfo data
* block.
*
\***************************************************************************/
void
RemoveExtraInfo(HWND hwnd)
{
if (!ValidateHWnd(hwnd)) {
return;
}
ExtraInfo * pei = RawGetExtraInfo(hwnd);
if (pei == NULL) {
return;
}
if (pei->pconOwner != NULL) {
pei->pconOwner->xwUnlock();
}
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) pei->pfnOldWndProc);
SetWindowLongPtrW(hwnd, GWLP_USERDATA, NULL);
ProcessDelete(ExtraInfo, pei);
}
//---------------------------------------------------------------------------
void
DestroyContainer(ExtraInfo * pei)
{
if (pei->pconOwner != NULL) {
pei->pconOwner->xwUnlock();
pei->pconOwner = NULL;
}
}
/***************************************************************************\
*
* ExtraInfoWndProc
*
* ExtraInfoWndProc() provides a TEMPORARY mechanism of adding ExtraInfo into
* an HWND. Eventually, this should be moved into DefWindowProc().
*
\***************************************************************************/
LRESULT
ExtraInfoWndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
//
// Check if the window has ExtraInfo (without allocating any if it
// doesn't). If we don't "own" it, just pass on to DefWindowProc().
//
ExtraInfo * pei = RawGetExtraInfo(hwnd);
if (pei == NULL) {
return DefWindowProc(hwnd, nMsg, wParam, lParam);
}
//
// This window has ExtraInfo, so handle as necessary.
//
// Also, grab any info that we will need to call the original windowproc
// later.
//
WNDPROC pfnOldWndProc = pei->pfnOldWndProc;
switch (nMsg)
{
case WM_NCDESTROY:
//
// This is the last message that we will get, so need to clean-up now.
// We need to be very careful since we will detatch ourself from the
// window.
//
RemoveExtraInfo(hwnd);
break;
default:
if (pei->pconOwner != NULL) {
LRESULT r;
if (pei->pconOwner->xdHandleMessage(nMsg, wParam, lParam, &r, 0)) {
return r;
}
}
}
return CallWindowProc(pfnOldWndProc, hwnd, nMsg, wParam, lParam);
}
//**************************************************************************************************
//
// Public Functions
//
//**************************************************************************************************
/***************************************************************************\
*
* GdGetContainer (Public)
*
* GdGetContainer() returns the associated Gadget Container for a given
* window. If the window does not yet have a gadget container, NULL is
* returned.
*
\***************************************************************************/
HWndContainer *
GdGetContainer(HWND hwnd)
{
ExtraInfo * pei = RawGetExtraInfo(hwnd);
if (pei == NULL) {
return NULL;
}
return pei->pconOwner;
}
/***************************************************************************\
*
* GdCreateHwndRootGadget (Public)
*
* GdCreateHwndRootGadget() creates a new RootGadget for an existing HWND. If
* the HWND already has a gadget or container, this function will destroy
* the previous container and gadget and create new instances.
*
\***************************************************************************/
HRESULT
GdCreateHwndRootGadget(
IN HWND hwndContainer, // Window to be hosted inside
IN CREATE_INFO * pci, // Creation information
OUT DuRootGadget ** ppgadNew) // New Gadget
{
HRESULT hr;
ExtraInfo * pei = GetExtraInfo(hwndContainer);
if (pei == NULL) {
return NULL;
}
DestroyContainer(pei);
//
// Build a new container and top gadget
//
HWndContainer * pconNew;
hr = HWndContainer::Build(pei->hwnd, &pconNew);
if (FAILED(hr)) {
return hr;
}
DuRootGadget * pgadNew;
hr = DuRootGadget::Build(pconNew, FALSE, pci, &pgadNew);
if (FAILED(hr)) {
pconNew->xwUnlock();
return hr;
}
pgadNew->SetFill(GetStdColorBrushI(SC_White));
pei->pconOwner = pconNew;
*ppgadNew = pgadNew;
return S_OK;
}
//------------------------------------------------------------------------------
BOOL
GdForwardMessage(DuVisual * pgadRoot, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT * pr)
{
DuContainer * pcon = pgadRoot->GetContainer();
return pcon->xdHandleMessage(nMsg, wParam, lParam, pr, DuContainer::mfForward);
}