//-------------------------------------------------------------------
// OWL Extensions (OWLEXT) Class Library
// Copyright(c) 1996 by Manic Software.
// All rights reserved.
//
// TOWLEXTDll (and friends) implementation
//-------------------------------------------------------------------
#include <owlext/pch.h>
#pragma hdrstop
#include <owlext/owlext.h>
#include <owlext/util.h>
#include <owlext/version.h>
#include <owl/bitset.h>
using namespace owl;
//
// Diagnostic group declarations/definitions
//
DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlExtModule, 1, 0);
#if defined (_BUILDOWLEXTDLL)
#if !defined(BI_COMP_BORLANDC)
int WINAPI
DllMain(HINSTANCE hInstance, uint32 reason, void* lpreserved);
#else
int WINAPI
DllEntryPoint(HINSTANCE hInstance, uint32 reason, void* lpreserved);
#endif
#endif //#if defined (_BUILDOWLEXTDLL)
#if defined(BI_COMP_BORLANDC)
//
// Fixing BUG in BC 5.x with templates
//
static void NeverCallThisDummyFunction()
{
typedef TBitFlags<uint> ___type1;
___type1 dummy1;
}
#endif
namespace OwlExt {
#if defined (_BUILDOWLEXTDLL)
static LPCTSTR OwlExtName = _T("OWLEXT");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// TOWLEXTDll
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TOWLEXTDll::TOWLEXTDll(bool shouldLoad, bool mustLoad)
:
TModule(OwlExtName, shouldLoad, mustLoad),
GetOWLEXTVersion(*this, "GetOWLEXTVersion")
{
TRACEX(OwlExtModule, 1, "TOWLEXTDll external constructor invoked");
}
TOWLEXTDll::TOWLEXTDll(HINSTANCE instance)
:
TModule(OwlExtName, instance),
GetOWLEXTVersion(*this, "GetOWLEXTVersion")
{
TRACEX(OwlExtModule, 1, "TOWLEXTDll internal constructor invoked");
}
TOWLEXTDll::~TOWLEXTDll()
{
TRACEX(OwlExtModule, 1, "TOWLEXTDll destructor invoked");
}
TModuleVersionInfo& TOWLEXTDll::GetVersionInfo()
{
TRACEX(OwlExtModule, 1, "TOWLEXTDll::GetVersionInfo invoked");
static TModuleVersionInfo verInfo(*this);
return verInfo;
}
// Localized method to obtain this DLL's HINSTANCE value
HINSTANCE
GetThisHINSTANCE()
{
MEMORY_BASIC_INFORMATION mbi;
#if defined(BI_COMP_BORLANDC)
if (VirtualQuery(DllEntryPoint, &mbi, sizeof(mbi)))
#else
if (VirtualQuery(DllMain, &mbi, sizeof(mbi)))
#endif
return (HINSTANCE)mbi.BaseAddress;
else
return 0;
}
TOWLEXTDll&
TOWLEXTDll::Instance()
{
// This is amended slightly from the text, since I figured it would be a small
// performance increase to check the global owl::Module TModule pointer,
// for the (normal) case where DllEntryPoint() is called (and TOWLEXTDll is
// safely initialized) before anybody calls TOWLEXTDll::Instance(). It also
// helps to offer another way of doing this DLL-initialization thing.
//
if(owl::Module == NULL){
TRACEX(OwlExtModule, 1, "TOWLEXTDll::Instance creating TOWLEXTDll object");
static TOWLEXTDll theModule(GetThisHINSTANCE());
owl::Module = &theModule;
}
return *((TOWLEXTDll*)owl::Module);
// Need to return a type of 'TOWLEXTDll&', and '*Module' is a 'TModule&'; cast
// explicitly to a TOWLEXTDll* so when we dereference, it's of the right type
}
//
int
TOWLEXTDll::ThreadAttach()
{
// If this module depended on maintaining separate data for each thread, we'd
// do the necessary initialization here
TRACEX(OwlExtModule, 1, "TOWLEXTDll::ThreadAttach invoked");
return 1;
}
//
int
TOWLEXTDll::ThreadDetach()
{
// If this module depended on maintaining separate data for each thread, we'd
// do the necessary uninitialization here
TRACEX(OwlExtModule, 1, "TOWLEXTDll::ThreadDetach invoked");
return 1;
}
#endif //#if defined (_BUILDOWLEXTDLL)
} // OwlExt namespace
#if defined (_BUILDOWLEXTDLL)
//
// Exported method to obtain OWLEXT's version number
//
extern "C" OWLEXTFUNC(long WINAPI) GetOWLEXTVersion()
{
return OWLEXT_FILEVERSION;
}
namespace OwlExt {
// OWLEXTEntryPoint is our TOWLEXTDll-friendly function to take care of all DLL-
// notification responses
//
int OWLEXTEntryPoint(HINSTANCE hInstance, uint32 reason, LPVOID)
{
TRACEX(OwlExtModule, 1, "OWLEXTEntryPoint called");
switch (reason)
{
// DLL_PROCESS_ATTACH--a process has LoadLibrary()'ed us
//
case DLL_PROCESS_ATTACH:
{
// First see if we need to create the TOWLEXTDll instance
if (!owl::Module){
// Yep, so create it
static TOWLEXTDll theModule(hInstance);
owl::Module = &theModule;
}
return ::OWLInitUserDLL(hInstance, 0) ? 1 : 0;
}
// DLL_THREAD_ATTACH--a process which loaded this DLL has spun off a thread
//
case DLL_THREAD_ATTACH:
return TOWLEXTDll::Instance().ThreadAttach();
// DLL_THREAD_DETACH--a process which loaded this DLL has a thread ending
//
case DLL_THREAD_DETACH:
return TOWLEXTDll::Instance().ThreadDetach();
// DLL_PROCESS_DETACH--a process which loaded this DLL is unloading us
//
case DLL_PROCESS_DETACH:
{
return 1;
}
}
return 0;
}
} // OwlExt namespace
// DllEntryPoint is called whenever 'something' happens to the DLL. Defer all actions
// to the global function OWLEXTEntryPoint
//
#if !defined(BI_COMP_BORLANDC)
int WINAPI
DllMain(HINSTANCE hInstance, uint32 reason, void* lpreserved)
#else
int WINAPI
DllEntryPoint(HINSTANCE hInstance, uint32 reason, void* lpreserved)
#endif
{
return OwlExt::OWLEXTEntryPoint(hInstance, reason, lpreserved);
}
// Singleton accessor method; does the same as TOWLEXTDll::Instance(), but
// some may find the global function syntax to be cleaner
//
#if defined(BI_COMP_BORLANDC)
extern "C" OWLEXTFUNC(TModule* WINAPI)
#else
STDAPI_(TModule*)
#endif
GetOWLEXTModule()
{
return &(OwlExt::TOWLEXTDll::Instance());
}
#endif //#if defined (_BUILDOWLEXTDLL)
namespace OwlExt {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Functions
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///////////////////////////////////////////////////////////////////////
// Activates (brings to top and sets focus) the first window found
// (by searching up the parent chain from the specified window) that
// either has a caption or is a top-level window.
//
void ActivateWindow (TWindow* tWindow)
{
HWND parent;
LONG style;
HWND window = tWindow->GetHandle();
parent = window;
do{
window = parent;
parent = ::GetParent (window);
style = ::GetWindowLong (window, GWL_STYLE);
}while (parent && !(style & WS_CAPTION));
::BringWindowToTop (window);
}
////////////////////////////////////////////////////////////////////////////
// Function: CenterScreenRectOnRect
//
// Params: rc - RECT* to the rectangle of window being
// centered
//
// rcOver - RECT* to the rectangle of the window being
// centered over.
//
// NOTE: Both RECT's should be GetWindowRect() values,
// i.e., screen coordinates.
//
// Returns: Nothing
//
// Comments: This function will set the members of 'rc' such that it
// is centered over 'rcOver'. The members of 'rc' will be
// adjusted for the screen size so that the window will be
// visible.
//
////////
void CenterScreenRectOnRect (TRect* rc, TRect* rcOver)
{
int cxPopup = rc->Width();
int cyPopup = rc->Height();
int cxParent = rcOver->Width();
int cyParent = rcOver->Height();
int cxScreen = GetSystemMetrics (SM_CXSCREEN);
int cyScreen = GetSystemMetrics (SM_CYSCREEN);
// Center it:
int xPopup = rcOver->left + ((cxParent - cxPopup) / 2);
int yPopup = rcOver->top + ((cyParent - cyPopup) / 2);
// Adjust popup location for screen size:
if (xPopup+cxPopup > cxScreen)
xPopup = cxScreen - cxPopup;
if (yPopup+cyPopup > cyScreen)
yPopup = cyScreen - cyPopup;
rc->left = xPopup * (xPopup > 0);
rc->top = yPopup * (yPopup > 0);
rc->right = rc->left + cxPopup;
rc->bottom = rc->top + cyPopup;
}
////////////////////////////////////////////////////////////////////////////
// This function will center hWnd over hwndOver. If hwndOver is NULL,
// then hWnd will be centered on the screen.
//
void CenterWindowOver (HWND hWnd, HWND hwndOver)
{
TRect rcOver, rcWnd;
if (!hwndOver)
hwndOver = ::GetDesktopWindow();
::GetWindowRect (hwndOver, &rcOver);
::GetWindowRect (hWnd, &rcWnd);
CenterScreenRectOnRect (&rcWnd, &rcOver);
::SetWindowPos (hWnd, NULL, rcWnd.left, rcWnd.top, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
}
////////////////////////////////////////////////////////////////////////////
// This function updates the mouse cursor after forcing it to something
// else via SetCursor
//
void UpdateCursor ()
{
TPoint pt;
::GetCursorPos (&pt);
::SetCursorPos (pt.x, pt.y);
}
// MFC style function, that draw the frame of a 3d rect with given colors
void Draw3dRect(TDC& dc, const TRect& rect, TColor clrTopLeft,
TColor clrBottomRight)
{
Draw3dRect(dc, rect.left, rect.top, rect.Width(),
rect.Height(), clrTopLeft, clrBottomRight);
}
void Draw3dRect(TDC& dc, int x, int y, int cx, int cy, TColor clrTopLeft,
TColor clrBottomRight)
{
FillSolidRect(dc, x, y, cx - 1, 1, clrTopLeft);
FillSolidRect(dc, x, y, 1, cy - 1, clrTopLeft);
FillSolidRect(dc, x + cx, y, -1, cy, clrBottomRight);
FillSolidRect(dc, x, y + cy, cx, -1, clrBottomRight);
}
// MFC style function, that draws a filled rect. Is this faster???
void
FillSolidRect(TDC& dc, int x, int y, int cx, int cy, TColor clr)
{
TColor oldColor = dc.SetBkColor(clr);
TRect rect(x, y, x + cx, y + cy);
dc.TextRect(rect);
dc.SetBkColor(oldColor);
}
void
FillMaskRect(TDC& dc, TRect rect)
{
THatch8x8Brush br(THatch8x8Brush::Hatch11F1, TColor::Sys3dHilight,
TColor::Sys3dFace);
dc.FillRect(rect, br);
}
void DrawDisabledButton(TDC& dc, const TRect& rc)
{
// create a monochrome memory DC
//
TMemoryDC ddc;
TBitmap bmp(ddc, rc.Width(), rc.Height());
ddc.SelectObject(bmp);
// build a mask
//
ddc.PatBlt(0, 0, rc.Width(), rc.Height(), WHITENESS);
dc.SetBkColor(TColor::Sys3dFace);
ddc.BitBlt(0, 0, rc.Width(), rc.Height(), dc, rc.left, rc.top, SRCCOPY);
dc.SetBkColor(TColor::Sys3dHilight);
ddc.BitBlt(0, 0, rc.Width(), rc.Height(), dc, rc.left, rc.top, SRCPAINT);
// Copy the image from the toolbar into the memory DC
// and draw it (grayed) back into the toolbar.
//
dc.FillRect(rc, TBrush(TColor::Sys3dFace));
dc.SetBkColor(RGB(0, 0, 0));
dc.SetTextColor(RGB(255, 255, 255));
TBrush brShadow(TColor::Sys3dShadow);
TBrush brHilight(TColor::Sys3dHilight);
dc.SelectObject(brHilight);
dc.BitBlt(rc.left+1, rc.top+1, rc.Width(), rc.Height(), ddc, 0, 0, 0x00E20746L);
dc.SelectObject(brShadow);
dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), ddc, 0, 0, 0x00E20746L);
// reset DCs
//
dc.RestoreBrush();
dc.RestoreBrush();
ddc.RestoreBitmap();
}
owl::tstring GetHintText(TWindow* win, uint id, THintText hintType)
// Search the parent frame window of win and return the result of GetHintText
{
TWindow* parent= win->GetParentO();
TDecoratedFrame* frame= parent ?
TYPESAFE_DOWNCAST(parent, TDecoratedFrame) : 0;
while (parent && !frame) {
parent = parent->GetParentO();
if (parent)
frame = TYPESAFE_DOWNCAST(parent, TDecoratedFrame);
}
return frame ? frame->GetHintText(id, hintType) : owl::tstring();
}
//
// Find resource module
//
TModule*
FindResourceModule(TWindow* parent, TModule* module, TResId resId, LPCTSTR type)
{
if(module && module->FindResource(resId, type))
return module;
if(parent && parent->GetModule() && parent->GetModule()->FindResource(resId, type))
return parent->GetModule();
return TModule::FindResModule(resId, type);
}
} // OwlExt namespace
/*============================================================================*/
↑ V813 Decreased performance. The 'rect' argument should probably be rendered as a constant reference.