|
|
#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); }
|