256 lines
6.8 KiB
C++
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);
|
||
|
}
|
||
|
|
||
|
|