home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
- // source\owl\window.cpp
- // Defines type TWindow. This defines the basic behavior of all Windows.
- //----------------------------------------------------------------------------
- #include <owl\owlpch.h>
- #include <owl\window.h>
- #include <owl\applicat.h>
- #include <owl\scroller.h>
- #include <owl\gdiobjec.h>
- #include <stdlib.h>
-
- DIAG_DECLARE_GROUP(OwlMsg); // diagnostic group for message tracing
- DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlWin, 1, 0);
- // diagnostic group for windows
-
- //#define BUILDUP_CLASSNAME // to build registered classname with modulename
-
- //
- // Externs defined in owl.cpp
- //
- extern LRESULT FAR PASCAL _export InitWndProc(HWND, UINT, WPARAM, LPARAM);
-
- extern WNDPROC CreateInstanceThunk(TWindow*);
- extern void FreeInstanceThunk(WNDPROC);
- extern void _OWLFUNC SetCreationWindow(TWindow*);
- extern UINT _OWLDATA GetWindowPtrMsgId;
-
- struct TCurrentEvent {
- TWindow* win;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- };
- TCurrentEvent CurrentEvent;
-
-
- //$---------------------------------------------------------------------------
-
- DEFINE_RESPONSE_TABLE(TWindow)
- EV_WM_SETCURSOR,
- EV_WM_SIZE,
- EV_WM_MOVE,
- EV_WM_COMPAREITEM,
- EV_WM_DELETEITEM,
- EV_WM_DRAWITEM,
- EV_WM_MEASUREITEM,
- EV_WM_VSCROLL,
- EV_WM_HSCROLL,
- EV_WM_CHILDINVALID,
- EV_WM_ERASEBKGND,
- EV_WM_PAINT,
- EV_WM_LBUTTONDOWN,
- EV_WM_KILLFOCUS,
- #if defined(__WIN32__)
- EV_MESSAGE(WM_CTLCOLORMSGBOX, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLOREDIT, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLORLISTBOX, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLORBTN, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLORDLG, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLORSCROLLBAR, EvWin32CtlColor),
- EV_MESSAGE(WM_CTLCOLORSTATIC, EvWin32CtlColor),
- #endif
- EV_WM_CREATE,
- EV_WM_CLOSE,
- EV_WM_DESTROY,
- EV_WM_NCDESTROY,
- EV_COMMAND(CM_EXIT, CmExit),
- EV_WM_QUERYENDSESSION,
- EV_WM_SYSCOLORCHANGE,
- END_RESPONSE_TABLE;
-
-
- //$---------------------------------------------------------------------------
- //
- //
- TCommandEnabler::TCommandEnabler(UINT id, HWND hWndReceiver)
- : Id(id), HWndReceiver(hWndReceiver)
- {
- Handled = FALSE;
- }
-
- void
- TCommandEnabler::Enable(BOOL)
- {
- Handled = TRUE;
- }
-
- //$---------------------------------------------------------------------------
-
- //
- // constructor for a TWindow. if a parent window is passed, adds the TWindow
- // to its parent's list of children
- //
- TWindow::TWindow(TWindow* parent,
- const char far* title,
- TModule* module)
- {
- Thunk = 0; // remember that we still need to initialize
- Init(parent, title, module);
- }
-
- //$---------------------------------------------------------------------------
- //
- // constructor for a TWindow which is being used as an alias for a
- // non-OWL window. This ctor is generally not used by derived classes
- //
- TWindow::TWindow(HWND hWnd, TModule* module)
- {
- //
- // perform preliminary initialization
- //
- HWindow = hWnd;
- Title = 0;
- Thunk = 0; // remember that we still need to initialize
-
- //
- // if the receiver's parent is an OWL window then pass the window to Init()
- // so the receiver can be added to the parent's list of children
- //
- HWND hParent = GetParent();
- TWindow* parent = hParent ? GetWindowPtr(hParent) : 0;
- Init(parent, module);
-
- //
- // thunk the window
- //
- SubclassWindowFunction();
-
- //
- // copy over the title, styles, the coordinates & the id
- //
- GetWindowTextTitle();
- GetHWndState();
-
- //
- // Keep track that this is an alias object
- //
- SetFlag(wfAlias);
- }
-
- //$---------------------------------------------------------------------------
- //
- // Protected constructor for use by immediate virtually derived classes.
- // Immediate derivitives must call Init() before constructions are done.
- //
- TWindow::TWindow()
- {
- Thunk = 0; // remember that we still need to initialize
- }
-
- //
- // Normal initialization of a default constructed TWindow. Is ignored
- // if called more than once.
- //
- void
- TWindow::Init(TWindow* parent,
- const char far* title,
- TModule* module)
- {
- if (!Thunk) {
- Init(parent, module);
- Title = strnewdup(title);
- DefaultProc = 0;
- HWindow = 0;
- EnableAutoCreate();
-
- //
- // initialize creation attributes
- //
- Attr.Style = WS_CHILD | WS_VISIBLE;
- Attr.X = Attr.Y = Attr.W = Attr.H = 0;
- Attr.ExStyle = 0;
- Attr.Id = 0;
- }
- }
-
- //
- // Private initializer function that does the bulk of the work
- //
- void
- TWindow::Init(TWindow* parent, TModule* module)
- {
- ZOrder = 0;
- ChildList = 0;
- Flags = 0;
- TransferBuffer = 0;
- Parent = parent;
- Attr.Param = 0;
- Attr.Menu = 0;
- Attr.AccelTable = 0;
- hAccel = 0;
- Thunk = CreateInstanceThunk(this);
- Application = GetApplicationObject();
- Scroller = 0;
-
- CursorModule = 0;
- CursorResId = 0;
- HCursor = 0;
- BkgndColor = NoColor;
-
- if (Parent)
- Parent->AddChild(this);
-
- else
- SiblingList = 0;
-
- //
- // Use passed module if one, else get parent's. If no parent, get app's
- //
- Module = module ? module : (Parent ? Parent->GetModule() : Application);
- SetUniqueId();
-
- TRACEX(OwlWin, 1, "TWindow constructed @" << (void*)this);
- }
-
- //
- // installs the thunk as the window function and saves the old window function
- // in "DefaultProc"
- //
- void
- TWindow::SubclassWindowFunction()
- {
- CHECK(HWindow != 0);
- DefaultProc = (WNDPROC)SetWindowLong(GWL_WNDPROC, DWORD(GetThunk()));
- CHECK(DefaultProc != GetThunk()); // can only be called once!
- }
-
- //
- // destructor for a TWindow: disposes of each window in its ChildList
- // and removes itself from a non-0 parent's list of children
- //
- // destroys a still-associated MS-Windows interface element and frees
- // the instance thunk used for association of an MS-Windows element
- // to the TWindow
- //
- // disposes of its Scroller if the TScroller object was constructed
- //
- static void shutDown(TWindow* win, void*) {
- win->Destroy();
- delete win;
- }
-
- TWindow::~TWindow()
- {
- //
- // Flush the cache so that messages dont get dispatched to a
- // already-destructed derived class
- //
- void CacheFlush(uint32 id);
- CacheFlush(UniqueId);
-
- //
- // ShutDown children first, so the Owl objects get a chance to clean up
- //
- ForEach(shutDown);
-
- //
- // If the HWindow is still around, then destroy it or unlink from it as
- // appropriate.
- //
- if (HWindow) {
- //
- // for aliases:
- // - we are destructing the C++ object but not destroying the MS window
- // - restore the original window function
- //
- if (IsFlagSet(wfAlias)) {
- //
- // May want to check WNDPROC against Thunk to see if its still us
- // and not restore if it's not us...
- //
- WARNX(OwlWin, GetWindowLong(GWL_WNDPROC) != (uint32)GetThunk(), 0,
- "Restoring old WndProc after foreign subclass of:" << *this);
- SetWindowLong(GWL_WNDPROC, DWORD(DefaultProc));
-
- //
- // for non-aliases:
- // - destroy the windows element
- // this is not a normal condition and is a safety net only
- //
- } else {
- WARNX(OwlWin, HWindow, 0, "Destroying from TWindow::~TWindow: " << *this);
- Destroy();
- }
- }
-
- if (Parent)
- Parent->RemoveChild(this);
-
- if (IsFlagSet(wfMainWindow))
- GetApplication()->MainWindow = 0;
-
- //
- // Delete menu id string, scroller, title, cursor & thunk
- //
- if (Attr.Menu.IsString())
- delete (char far*)Attr.Menu;
-
- //
- // delete scroller if there is one, by casting up to base and relying on
- // virtual dtor to avoid pulling in TScroller object code.
- //
- if (Scroller) {
- delete (TStreamableBase*)Scroller;
- Scroller = 0;
- }
-
- if (HIWORD(Title))
- delete Title;
-
- if (HCursor && CursorModule)
- SetCursor(0, 0);
-
- FreeInstanceThunk(Thunk);
- TRACEX(OwlWin, 1, "TWindow destructed @" << (void*)this);
- }
-
- #if defined(__WIN32__)
- //
- // overrides TEventHandler::Dispatch() to handle multi-thread synchonization
- //
- LRESULT TWindow::Dispatch(TEventInfo& info, WPARAM wp, LPARAM lp)
- {
- TApplication::TAppLock Lock(*GetApplication());
- return TEventHandler::Dispatch(info, wp, lp);
- }
-
- #endif
-
- //
- //
- BOOL
- TWindow::PreProcessMsg(MSG& msg)
- {
- return hAccel ? ::TranslateAccelerator(HWindow, hAccel, &msg) : FALSE;
- }
-
- BOOL
- TWindow::IdleAction(long /*idleCount*/)
- {
- return FALSE; // we don't need any more time for now
- }
-
- //
- // respond to this message by broadcasting it to all children
- //
- void
- TWindow::EvSysColorChange()
- {
- ChildBroadcastMessage(WM_SYSCOLORCHANGE);
- }
-
- //
- // removes the passed pointer to a child window from the linked list of
- // sibling windows which the TWindow's ChildList points to
- //
- void
- TWindow::RemoveChild(TWindow* child)
- {
- if (child && ChildList) {
- TWindow* lastChild = ChildList;
- TWindow* nextChild = lastChild;
-
- while (nextChild->SiblingList != lastChild &&
- nextChild->SiblingList != child) {
- nextChild = nextChild->SiblingList;
- }
-
- if (nextChild->SiblingList == child) {
- if (nextChild->SiblingList == nextChild)
- ChildList = 0;
-
- else {
- if (nextChild->SiblingList == ChildList)
- ChildList = nextChild;
-
- nextChild->SiblingList = nextChild->SiblingList->SiblingList;
- }
- }
- }
- }
-
- //
- // reparents "this" to a new parent
- //
- void
- TWindow::SetParent(TWindow* newParent)
- {
- if (Parent != newParent) {
- if (Parent)
- Parent->RemoveChild(this);
-
- SiblingList = 0;
-
- if (HWindow) {
- //
- // tell Windows about the change
- //
- if (newParent) {
- CHECK(newParent->HWindow);
- ::SetParent(HWindow, newParent->HWindow);
- } else
- ::SetParent(HWindow, 0);
- }
-
- Parent = newParent;
-
- if (Parent)
- Parent->AddChild(this);
- }
- }
-
- //
- // default behavior for updating document title is to pass it to parent frame
- //
- BOOL
- TWindow::SetDocTitle(LPCSTR docname, int index)
- {
- return Parent ? Parent->SetDocTitle(docname, index) : FALSE;
- }
-
- //
- // wildcard check used for child id notifications
- //
- static BOOL wildcardCheck(TGenericTableEntry __RTFAR& entry,
- TEventHandler::TEventInfo& info) {
- return entry.Id == info.Id && (entry.Msg == UINT_MAX || entry.Msg == info.Msg);
- }
-
- //
- // handles default processing of events
- //
- // this includes continued processing of menu/accelerators and child Id
- // notifications
- //
- LRESULT
- TWindow::DefaultProcessing()
- {
- if (CurrentEvent.message == WM_COMMAND_ENABLE) {
- if (CurrentEvent.win != this) {
- TWindow* receiver = Parent ? Parent : CurrentEvent.win;
- TCommandEnabler& commandEnabler = *(TCommandEnabler*)CurrentEvent.lParam;
- TEventInfo eventInfo(WM_COMMAND_ENABLE, commandEnabler.Id);
-
- if (receiver->Find(eventInfo))
- return receiver->Dispatch(eventInfo, 0, CurrentEvent.lParam);
- }
-
- return 0;
- }
-
- if (CurrentEvent.message != WM_COMMAND)
- return DefWindowProc(CurrentEvent.message, CurrentEvent.wParam, CurrentEvent.lParam);
-
- //
- // CurrentEvent.message == WM_COMMAND
- //
- #if defined(__WIN32__)
- UINT notifyCode = HIWORD(CurrentEvent.wParam);
- #else
- UINT notifyCode = HIWORD(CurrentEvent.lParam);
- #endif
- UINT id = LOWORD(CurrentEvent.wParam);
- HWND hWndCtl = (HWND)(UINT)CurrentEvent.lParam;
-
- if (CurrentEvent.win == this) {
- //
- // menu command originally destined for the receiver. defer to the app
- //
- if (hWndCtl == 0) {
- TEventInfo eventInfo(0, id);
- TApplication* app = GetApplication();
-
- if (app->Find(eventInfo)) {
- app->Dispatch(eventInfo, eventInfo.Id);
- return 0;
- }
- WARNX(OwlMsg, notifyCode<=1, 0, "Unprocessed WM_COMMAND(id=" << id << ")");
- }
- //
- // originally destined for the receiver and the receiver has called us so
- // default processing can occur
- //
- // unpack the original parameters and call DefWindowProc()
- //
- return DefWindowProc(CurrentEvent.message, CurrentEvent.wParam, CurrentEvent.lParam);
-
- } else {
- TWindow* receiver;
- UINT wParam;
- TEqualOperator equal = 0;
-
- if (hWndCtl == 0) {
- //
- // menu/accelerator/push button
- //
- // either give the message to the receiver's parent or the original
- // receiver of the message
- //
- receiver = Parent ? Parent : CurrentEvent.win;
-
- //
- // "notifyCode" is either 0 or 1 depending on whether this is from an
- // accelerator; however, we want to explicitly look for a 0...
- //
- notifyCode = 0;
-
- wParam = id; // pass along "id" in case the receiver wants it
-
- } else {
- //
- // child id notification sent to the child and the child has called us
- //
- // offer the parent an opportunity to handle the notification
- //
- // NOTE: use equal function that will do a wildcard search
- //
- equal = wildcardCheck;
- receiver = CurrentEvent.win;
-
- //
- // the child window identifier shouldn't be 0, but if it is then it will
- // look like we are searching for a WM_ message with value "notifyCode"
- //
- if (receiver->IsFlagSet(wfAlias) || id == 0)
- return receiver->DefWindowProc(CurrentEvent.message, CurrentEvent.wParam, CurrentEvent.lParam);
-
- wParam = notifyCode; // pass notification code in case receiver wants it
- }
-
- TEventInfo eventInfo(notifyCode, id);
-
- if (receiver->Find(eventInfo, equal))
- return receiver->Dispatch(eventInfo, wParam);
-
- else
- return receiver->DefaultProcessing();
- }
- }
-
- //
- // processing for WM_COMMAND
- //
- LRESULT
- TWindow::EvCommand(UINT id, HWND hWndCtl, UINT notifyCode)
- {
- TWindow* receiver = this;
- UINT wParam;
- TEqualOperator equal = 0;
-
- if (hWndCtl == 0) {
- //
- // menu/accelerator
- //
- // "notifyCode" is either 0 or 1 depending on whether this is from an
- // accelerator; however, we want to explicitly look for a 0...
- //
- notifyCode = 0;
-
- //
- // pass the "id" along in case the user wants it...
- //
- wParam = id;
-
- } else {
- //
- // child id notification
- //
- TWindow* child = GetWindowPtr(hWndCtl);
-
- //
- // pass the "notifyCode" along in case the user wants it...
- //
- wParam = notifyCode;
-
- if (child) {
- //
- // give the child first crack at the event
- //
- receiver = child;
- id = UINT_MAX; // special designator for child Id notifications that are
- // handled at the child
-
- } else {
- //
- // offer the parent an opportunity to handle the notification
- //
- // NOTE: use equal function that will do a wildcard search
- //
- equal = wildcardCheck;
-
- //
- // the child window identifier shouldn't be 0, but if it is then it will
- // look like we are searching for a WM_ message with value "notifyCode"
- //
- if (id == 0)
- return DefaultProcessing();
- }
- }
-
- TEventInfo eventInfo(notifyCode, id);
-
- if (receiver->Find(eventInfo, equal))
- return receiver->Dispatch(eventInfo, wParam);
-
- else
- return receiver->DefaultProcessing();
- }
-
- //
- void
- TWindow::EvCommandEnable(TCommandEnabler& commandEnabler)
- {
- TEventInfo eventInfo(WM_COMMAND_ENABLE, commandEnabler.Id);
-
- if (Find(eventInfo))
- Dispatch(eventInfo, 0, (LPARAM)&commandEnabler);
- }
-
- //
- // specifies default processing for an incoming message
- //
- // calls original window proc that we subclassed, using ::CallWindowProc to
- // make sure that registers get setup correctly.
- //
- LRESULT
- TWindow::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- LRESULT result;
- CHECK(DefaultProc);
- result = ::CallWindowProc(DefaultProc, HWindow, message, wParam, lParam);
- GetApplication()->ResumeThrow();
- return result;
- }
-
-
- static const int msgCacheSize = 31;
- struct TCacheEntry {
- DWORD UniqueId;
- TGenericTableEntry __RTFAR* Entry;
- UINT Msg;
- int Delta; // adjustment to "this" pointer
-
- BOOL Hit(UINT msg, DWORD uniqueId) {return msg == Msg && uniqueId == UniqueId;}
- static UINT Key(uint32 id, UINT msg) {return (UINT(id) ^ msg) % msgCacheSize;}
- };
-
- DWORD TWindow::LastUniqueId = 0;
-
- static TCacheEntry msgCache[msgCacheSize];
- static BOOL cacheEnabled = TRUE;
-
- void CacheFlush(uint32 id) {
- for (int i = 0; i < msgCacheSize; i++)
- if (msgCache[i].UniqueId == id)
- msgCache[i].Msg = 0;
- }
-
- void
- TWindow::SetUniqueId()
- {
- if (++LastUniqueId == 0) {
- //
- // numbers wrapped around. disable the cache to be safe...
- //
- LastUniqueId = 1;
- cacheEnabled = FALSE;
- }
-
- UniqueId = LastUniqueId;
- }
-
- //
- // if the message is WM_COMMAND calls EvCommand(); otherwise looks for a handler
- // in the message response table
- //
- LRESULT
- TWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
- {
- if (msg == WM_COMMAND_ENABLE) {
- EvCommandEnable(*(TCommandEnabler*)lParam);
- return 0;
-
- } else if (msg == WM_COMMAND) {
- #if defined(__WIN32__)
- return EvCommand(LOWORD(wParam), (HWND)(UINT)lParam, HIWORD(wParam));
- #else
- return EvCommand(LOWORD(wParam), (HWND)(UINT)lParam, HIWORD(lParam));
- #endif
-
- } else {
- UINT key = TCacheEntry::Key(UniqueId, msg);
- TEventInfo eventInfo(msg);
-
- //
- // check the cache
- //
- // NOTE: because there isn't necessarily a 1-1 mapping between response
- // tables and OWL classes we can't do the lookup based on the
- // response table. when we get RTTI support then we can use the
- // pointer to the runtime class information, but until then use the
- // unique Id for the window. this means our caching is instance
- // based and not class based...
- //
- if (cacheEnabled && msgCache[key].Hit(msg, UniqueId)) {
- TRACEX(OwlMsg, 1, MsgName(msg) << "* => " << *this);
-
- eventInfo.Entry = msgCache[key].Entry;
- eventInfo.Object = (GENERIC*)(((char*)this) + msgCache[key].Delta);
- return Dispatch(eventInfo, wParam, lParam);
-
- } else if (Find(eventInfo)) {
- TRACEX(OwlMsg, 1, MsgName(msg) << " => " << *this);
- msgCache[key].UniqueId = UniqueId;
- msgCache[key].Entry = eventInfo.Entry;
- msgCache[key].Msg = msg;
- msgCache[key].Delta = int(eventInfo.Object) - int(this);
- return Dispatch(eventInfo, wParam, lParam);
-
- } else {
- if (IsFlagSet(wfMainWindow)) {
- TEventInfo cmdEventInfo(msg, wParam);
- if (GetApplication()->Find(cmdEventInfo))
- return GetApplication()->Dispatch(cmdEventInfo, wParam, lParam);
- if (GetApplication()->Find(eventInfo))
- return GetApplication()->Dispatch(eventInfo, wParam, lParam);
- }
- return DefWindowProc(msg, wParam, lParam);
- }
- }
- }
-
- //
- // Save current event and call this window's WindowProc. Handles exceptions,
- // error checking, & GetWindowPtr messages.
- //
-
- LRESULT
- TWindow::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
- {
- //
- // if it's a "GetWindowPtr" message, then return pointer to this window
- //
- if (msg == GetWindowPtrMsgId)
- return (LRESULT)this;
-
- PRECONDITION(HWindow);
-
- //
- // save event away in "CurrentEvent"
- //
- TCurrentEvent saveEvent = CurrentEvent; // for nested calls
- CurrentEvent.win = this;
- CurrentEvent.message = msg;
- CurrentEvent.wParam = wParam;
- CurrentEvent.lParam = lParam;
-
- //
- // call window object's WindowProc virtual function
- //
- LRESULT result;
- result = WindowProc(msg, wParam, lParam);
- CurrentEvent = saveEvent; // restore previous event to current event
- return result;
- }
-
- //
- // Window function called for normal, initialized, OWL windows via a
- // per-window thunk. 'this' ptr is setup in register(s) by the thunk before
- // StdWndProc is called.
- //
- #if defined(__WIN32__)
- LRESULT
- FAR PASCAL _stdcall
- StdWndProc(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- return ((TWindow*)_EAX)->ReceiveMessage(msg, wParam, lParam);
- }
- #else
- LRESULT
- FAR PASCAL __export
- StdWndProc(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- return ((TWindow*)MK_FP(_ES,_BX))->ReceiveMessage(msg, wParam, lParam);
- }
- #endif
-
- //
- // First member function that receives messages from windows thru the
- // thunk & then StdWndProc. Deals with exception suspension for non-NT
- // environments.
- //
- LRESULT
- TWindow::ReceiveMessage(UINT msg, WPARAM wParam, LPARAM lParam)
- {
- #if defined(__WIN32__)
- static BOOL IsNT = ((HIWORD(::GetVersion()) & 0x8000) == 0);
- if (IsNT)
- return HandleMessage(msg, wParam, lParam);
- #endif
- TRY {
- return HandleMessage(msg, wParam, lParam);
- }
- CATCH( (TXOwl& x) {
- GetApplication()->SuspendThrow(x);
- })
- CATCH( (xalloc& x) {
- GetApplication()->SuspendThrow(x);
- })
- CATCH( (xmsg& x) {
- GetApplication()->SuspendThrow(x);
- })
- CATCH( (Bad_cast) {
- GetApplication()->SuspendThrow(TApplication::xsBadCast);
- })
- CATCH( (Bad_typeid) {
- GetApplication()->SuspendThrow(TApplication::xsBadTypeid);
- })
- CATCH( (...) {
- GetApplication()->SuspendThrow(TApplication::xsUnknown);
- })
-
- // When we're building small model, exceptions are disabled
- // CATCH is defined as empty, so the only code is the TRY block,
- // making this return unreachable
- #pragma warn -rch
- return msg == WM_CREATE ? -1 : 0; // default value returned when exception caught
- #pragma warn .rch
- }
-
- //
- // response method for an incoming WM_SIZE message
- //
- // Call virtual SetupWindow to give derived classes a chance to set things up
- // now that we have an HWindow
- //
- int
- TWindow::EvCreate(CREATESTRUCT far&)
- {
- SetupWindow();
- return (int)DefaultProcessing();
- }
-
- //
- // regular windows never hold focus child handles
- //
- BOOL
- TWindow::HoldFocusHWnd(HWND /*hWndLose*/, HWND /*hWndGain*/)
- {
- return FALSE;
- }
-
- //
- //
- void
- TWindow::EvKillFocus(HWND getFocus)
- {
- //
- // Follow the parent chain back until a window volunteers to hold our handle
- //
- TWindow* holdWin = Parent;
- while (holdWin && !holdWin->HoldFocusHWnd(HWindow, getFocus))
- holdWin = holdWin->Parent;
-
- DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_SIZE message
- //
- // saves the normal size of the window in Attr
- //
- // also calls the SetPageSize() and SetBarRange() methods of the TWindow's
- // scroller, if it has been constructed
- //
- void
- TWindow::EvSize(UINT sizeType, TSize&)
- {
- if (Scroller && sizeType != SIZE_MINIMIZED) {
- Scroller->SetPageSize();
- Scroller->SetSBarRange();
- }
-
- if (sizeType == SIZE_RESTORED) {
- TRect wndRect;
-
- GetWindowRect(wndRect);
- Attr.W = wndRect.Width();
- Attr.H = wndRect.Height();
- }
-
- // Added owl functionality: notify parent of a resize in case it wants to
- // adust accordingly
- //
- if (Parent && !(GetWindowLong(GWL_EXSTYLE)&WS_EX_NOPARENTNOTIFY))
- Parent->SendMessage(WM_PARENTNOTIFY, WM_SIZE, (UINT)HWindow);
-
- DefaultProcessing();
- }
-
- //
- // save the normal position of the window
- //
- // if IsIconic() or IsZoomed() ignore the position since it does not reflect the
- // normal state
- //
- void
- TWindow::EvMove(TPoint&)
- {
- if (!IsIconic() && !IsZoomed()) {
- TRect wndRect;
-
- GetWindowRect(wndRect);
-
- if ((GetWindowLong(GWL_STYLE) & WS_CHILD) == WS_CHILD && Parent &&
- Parent->HWindow)
- Parent->ScreenToClient(wndRect.TopLeft());
-
- Attr.X = wndRect.left;
- Attr.Y = wndRect.top;
- }
-
- DefaultProcessing();
- }
-
- //
- // handles WM_COMPAREITEM message (for owner draw controls) by forwarding
- // message to control itself
- //
- LRESULT
- TWindow::EvCompareItem(UINT /*ctrlId*/, COMPAREITEMSTRUCT far& compareInfo)
- {
- TWindow* win = GetWindowPtr(compareInfo.hwndItem);
- if (win)
- return win->ForwardMessage();
- return DefaultProcessing();
- }
-
- //
- // handles WM_DELETEITEM message (for owner draw controls) by forwarding
- // message to control itself
- //
- void
- TWindow::EvDeleteItem(UINT /*ctrlId*/, DELETEITEMSTRUCT far& deleteInfo)
- {
- TWindow* win = GetWindowPtr(deleteInfo.hwndItem);
- if (deleteInfo.hwndItem != HWindow && win)
- win->ForwardMessage();
- else
- DefaultProcessing();
- }
-
- //
- // handles WM_DRAWITEM message (for owner draw controls & menus) by forwarding
- // message to control itself
- //
- void
- TWindow::EvDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT far& drawInfo)
- {
- if (drawInfo.CtlType == ODT_MENU) {
- // dispatch to menu...
- // TMenu* menu = ...
- // menu->DrawItem(drawInfo);
-
- } else {
- TWindow* win = GetWindowPtr(drawInfo.hwndItem);
- if (drawInfo.hwndItem != HWindow && win) {
- win->ForwardMessage();
- return;
- }
- }
- DefaultProcessing();
- }
-
- //
- // handles WM_MEASUREITEM message (for owner draw controls & menus) by
- // forwarding message to control itself
- //
- void
- TWindow::EvMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT far& measureInfo)
- {
- if (measureInfo.CtlType == ODT_MENU) {
- // dispatch to menu...
- // TMenu* menu = ...
- // menu->MeasureItem(measureInfo);
-
- } else {
- HWND hwndCtl = GetDlgItem(measureInfo.CtlID); // hWnd not in struct, get
- TWindow* win = GetWindowPtr(hwndCtl);
- //
- // If the GetWindowPtr failed, & CreationWindow is non-zero, then this
- // WM_MEASUREITEM is probably for the ctrl which is not yet thunked.
- // route the message directly to creation window.
- //
- extern TWindow* _OWLDATA CreationWindow;
- if (!win && CreationWindow)
- win = CreationWindow; // sometimes this is send before Owl thunks ctl
- if (win) {
- win->ForwardMessage();
- return;
- }
- }
- DefaultProcessing();
- }
-
- //
- //
- #if defined(__WIN32__)
- LRESULT
- TWindow::EvWin32CtlColor(WPARAM wParam, LPARAM lParam)
- {
- int ctlType = CurrentEvent.message - WM_CTLCOLORMSGBOX;
-
- CHECK(ctlType >= CTLCOLOR_MSGBOX && ctlType <= CTLCOLOR_STATIC);
-
- TEventInfo eventInfo(WM_CTLCOLOR);
-
- if (!Find(eventInfo))
- return DefWindowProc(CurrentEvent.message, wParam, lParam);
-
- else {
- typedef HBRUSH(GENERIC::*CTL_COLOR_PMF)(HDC, HWND, UINT);
-
- CTL_COLOR_PMF& pmf = (CTL_COLOR_PMF&)(eventInfo.Entry->Pmf);
-
- return (LRESULT)(eventInfo.Object->*pmf)((HDC)wParam, (HWND)lParam, ctlType);
- }
- }
- #endif
-
- //
- // dispatches scroll messages as if they were Command messages.
- //
- void
- TWindow::DispatchScroll(UINT scrollCode, UINT /*thumbPos*/, HWND hWndCtrl)
- {
- if (hWndCtrl) {
- TWindow* win = GetWindowPtr(hWndCtrl);
- if (win)
- win->ForwardMessage();
-
- //
- // Adjust CurrentEvent to allow DefaultProcessing to work
- //
- WORD id = (WORD)::GetDlgCtrlID(hWndCtrl);
- CurrentEvent.message = WM_COMMAND;
- #if defined(__WIN32__)
- CurrentEvent.wParam = MAKEWPARAM(id, scrollCode);
- CurrentEvent.lParam = LPARAM(hWndCtrl);
- #else
- CurrentEvent.wParam = id;
- CurrentEvent.lParam = MAKELPARAM(hWndCtrl, scrollCode);
- #endif
-
- EvCommand(id, hWndCtrl, scrollCode);
- return;
- }
- DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_HSCROLL message
- //
- // if the message is from a scrollbar control, calls DispatchScroll()
- // otherwise passes the message to the TWindow's scroller if it has been
- // constructed, else calls DefaultProcessing()
- //
- // assumes, because of a Windows bug, that if the window has the scrollbar
- // style, it will not have scrollbar controls
- //
- void
- TWindow::EvHScroll(UINT scrollCode, UINT thumbPos, HWND hWndCtl)
- {
- if (!(GetWindowLong(GWL_STYLE) & WS_HSCROLL))
- DispatchScroll(scrollCode, thumbPos, hWndCtl); // from scrollbar control
-
- else if (Scroller)
- Scroller->HScroll(scrollCode, thumbPos);
-
- else
- DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_VSCROLL message
- //
- // if the message is from a scrollbar control, calls DispatchScroll()
- // otherwise passes the message to the TWindow's scroller if it has been
- // constructed, else calls DefaultProcessing()
- //
- // assumes, because of a Windows bug, that if the window has the scrollbar
- // style, it will not have scrollbar controls
- //
- void
- TWindow::EvVScroll(UINT scrollCode, UINT thumbPos, HWND hWndCtl)
- {
- if (!(GetWindowLong(GWL_STYLE) & WS_VSCROLL))
- DispatchScroll(scrollCode, thumbPos, hWndCtl);
-
- else if (Scroller)
- Scroller->VScroll(scrollCode, thumbPos);
-
- else
- DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_ERASEBKGND message
- //
- BOOL
- TWindow::EvEraseBkgnd(HDC hDC)
- {
- //
- // color set, we'll handle erasing (or doing nothing) here
- //
- if (BkgndColor != NoColor) {
-
- //
- // if a color is set, blt out a rectangle of it, else don't erase & let
- // paint handle background
- //
- if (BkgndColor != NoErase) {
- SetBkColor(hDC, BkgndColor);
- ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &GetClientRect(), 0, 0, 0);
- }
- return TRUE;
- }
-
- //
- // no color set, use default class brush
- //
- return (BOOL)DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_PAINT message
- //
- // calls Paint(), performing Windows-required paint setup and cleanup before
- // and after. if the TWindow has a TScroller, also calls its BeginView() and
- // EndView() methods before and after call to Paint()
- //
- void
- TWindow::EvPaint()
- {
- if (IsFlagSet(wfAlias))
- DefaultProcessing(); // use application-defined wndproc
-
- else {
- TPaintDC dc(*this);
- TRect& rect = *(TRect*)&dc.Ps.rcPaint;
-
- if (Scroller)
- Scroller->BeginView(dc, rect);
-
- Paint(dc, dc.Ps.fErase, rect);
-
- if (Scroller)
- Scroller->EndView();
- }
- }
-
- //
- // redraws the contents of the TWindow after a WM_PAINT message
- // is received
- //
- // placeholder for descendant object types to redefine
- //
- void
- TWindow::Paint(TDC&, BOOL /*erase*/, TRect&)
- {
- }
-
- //
- // response method for an incoming WM_SETCURSOR message
- //
- // if a cursor has been set for this window, & the mouse is over the
- // client area, set the cursor
- //
- BOOL
- TWindow::EvSetCursor(HWND hWndCursor, UINT hitTest, UINT /*mouseMsg*/)
- {
- if (hWndCursor == HWindow && hitTest == HTCLIENT && HCursor) {
- ::SetCursor(HCursor);
- return TRUE;
- }
- return (BOOL)DefaultProcessing();
- }
-
- //
- // response method for an incoming WM_LBUTTONDOWN message
- //
- // if the TWindow's Scroller has been constructed and if auto-scrolling
- // has been requested, captures mouse input, loops until a WM_LBUTTONUP
- // message comes in calling the Scroller's AutoScroll method, and then
- // releases capture on mouse input
- // will also break if a WM_MOUSEMOVE comes in without the left button down
- // indicating a lost WM_LBUTTONUP
- //
- void
- TWindow::EvLButtonDown(UINT /*modKeys*/, TPoint& /*pt*/)
- {
- if (Scroller && Scroller->IsAutoMode()) {
- MSG loopMsg;
-
- loopMsg.message = 0;
- SetCapture();
-
- while (loopMsg.message != WM_LBUTTONUP &&
- (loopMsg.message != WM_MOUSEMOVE || (loopMsg.wParam&MK_LBUTTON))) {
- if (::PeekMessage(&loopMsg, 0, 0, 0, PM_REMOVE)) {
- ::TranslateMessage(&loopMsg);
- ::DispatchMessage(&loopMsg);
- }
-
- Scroller->AutoScroll();
- }
-
- ReleaseCapture();
- GetApplication()->ResumeThrow();
- }
-
- DefaultProcessing();
- }
-
- //
- void
- DoEnableAutoCreate(TWindow* win, void* /*retVal*/)
- {
- if (win->HWindow)
- win->EnableAutoCreate();
- }
-
- //
- // destroys an MS-Windows element associated with the TWindow
- // after setting the wfAutoCreate flag to ON for each of the windows
- // in the TWindow's ChildList
- //
- void
- TWindow::Destroy(int retVal)
- {
- if (HWindow) {
- ForEach(DoEnableAutoCreate, &retVal);
-
- if (::DestroyWindow(HWindow))
- HWindow = 0;
- GetApplication()->ResumeThrow();
- WARNX(OwlWin, HWindow, 0, "::DestroyWindow(" << (UINT)HWindow << ") failed");
- }
- }
-
- //
- // specifies registration attributes for the MS-Windows window class
- // of the TWindow, allowing instances of TWindow to be registered
- //
- // sets the fields of the passed WNDCLASS parameter to the default
- // attributes appropriate for a TWindow
- //
- void
- TWindow::GetWindowClass(WNDCLASS& wndClass)
- {
- wndClass.cbClsExtra = 0;
- wndClass.cbWndExtra = 0;
- wndClass.hInstance = *GetModule();
- wndClass.hIcon = 0;
- wndClass.hCursor = ::LoadCursor(0, IDC_ARROW);
- wndClass.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
- wndClass.lpszMenuName = 0;
- wndClass.lpszClassName = GetClassName();
- wndClass.style = CS_DBLCLKS;
- wndClass.lpfnWndProc = InitWndProc;
- }
-
- //
- // Returns a classname for a generic owl window. Builds the name based on the
- // name part of the current module's filename with "Window" appended.
- //
- char far*
- TWindow::GetClassName()
- {
- #if defined(BUILDUP_CLASSNAME)
- static char classSuffix[] = "Window";
- static char className[_MAX_FNAME+sizeof(classSuffix)];
-
- if (!*className) {
- char filePath[_MAX_PATH];
- #if (__WIN32__)
- int len = ::GetModuleFileName(0, filePath, sizeof(filePath));
- #else
- int len = GetModule()->GetModuleFileName(filePath, sizeof(filePath));
- #endif
- CHECK(len > 0);
- _splitpath(filePath, 0, 0, className, 0);
- strcat(className, classSuffix);
- }
- return className;
- #else
- return "OwlWindow"; // assume application private class
- #endif
- }
-
- //
- void
- TWindow::LoadAcceleratorTable()
- {
- if (Attr.AccelTable) {
- hAccel = GetModule()->LoadAccelerators(Attr.AccelTable);
- WARNX(OwlWin, !hAccel, 0,
- "Unable to load accelerators " << Attr.AccelTable
- << " from " << *GetModule());
- }
- }
-
- //
- // Perform MS Windows window creation
- //
- void
- TWindow::PerformCreate(int menuOrId)
- {
- HWindow = ::CreateWindowEx(Attr.ExStyle,
- GetClassName(),
- Title,
- Attr.Style,
- Attr.X, Attr.Y, Attr.W, Attr.H,
- Parent ? Parent->HWindow : 0,
- (HMENU)menuOrId,
- *GetModule(),
- Attr.Param);
- }
-
- //
- // associates an MS-Windows interface element with the TWindow object,
- // after creating the interface element if not already created
- //
- // when creating an element, uses the creation attributes previously set in
- // the Attr data field(simply associates the TWindow with an already
- // created interface element if the "FromResource" flag is set)
- //
- // Since this member function now throw an exception on error, it always
- // returns TRUE.
- //
- BOOL
- TWindow::Create()
- {
- PRECONDITION(HWindow == 0);
-
- int menuOrId = 0;
-
- DisableAutoCreate();
-
- if (IsFlagSet(wfFromResource))
- HWindow = Parent ? Parent->GetDlgItem(Attr.Id) : 0; // windows already created it
-
- else if (Register()) {
- SetCreationWindow(this);
-
- LoadAcceleratorTable();
-
- if (Attr.Menu) {
- menuOrId = (int)GetModule()->LoadMenu(Attr.Menu);
- WARNX(OwlWin, !menuOrId, 0, "Unable to load menu: " << Attr.Menu <<
- " from " << *GetModule());
-
- } else
- menuOrId = Attr.Id;
-
- PerformCreate(menuOrId);
- GetApplication()->ResumeThrow();
-
- } else
- THROW( TXWindow(this, IDS_CLASSREGISTERFAIL) );
-
- if (!HWindow) {
- if (Attr.Menu) // && !IsFlagSet(wfFromResource) ?
- DestroyMenu(HMENU(menuOrId));
-
- THROW( TWindow::TXWindow(this, IDS_WINDOWCREATEFAIL) );
- }
-
- //
- // predefined (non-owl) class--grab the state info that the class setup,
- // install the thunk & zero the creation window since InitWndProc never got
- // called, and set a flag
- //
- if (!GetWindowPtr(HWindow)) {
- GetWindowTextTitle();
- GetHWndState();
-
- SubclassWindowFunction();
- SetCreationWindow(0);
- SetFlag(wfPredefinedClass);
-
- SetupWindow();
- }
-
- return TRUE;
- }
-
- //
- // performs setup following creation of an associated MS-Windows window.
- // Iterates through the TWindow's ChildList, attempting to create
- // an associated MS-Windows interface element for each child window
- // object in the list (a child's Create method is not called if its
- // wfAutoCreate flag is not set)
- //
- // calls TransferData to transfer data for its children for whom data transfer
- // is enabled
- //
- // if the receiver has a TScroller object, calls the scroller's SetBarRange()
- // method
- //
- // can be redefined in derived classes to perform additional special
- // initialization that requires an HWND
- //
- void
- TWindow::SetupWindow()
- {
- if (Scroller)
- Scroller->SetSBarRange();
-
- if (!CreateChildren())
- THROW( TXWindow(0, IDS_CHILDCREATEFAIL) ); // not us, an unspecified child
-
- else
- TransferData(tdSetData);
- }
-
- //
- // always called just before HWindow goes away to give derived classes a
- // chance to cleanup HWND related resources.
- //
- void
- TWindow::CleanupWindow()
- {
- }
-
- //
- // transfer window 'data' to/from the passed data buffer. Used to initialize
- // windows and get data in or out of them.
- //
- // the direction passed specifies whether data is to be read from or
- // written to the passed buffer, or whether the data element size is simply
- // to be returned
- //
- // the return value is the size (in bytes) of the transfer data. this method
- // recursively calls transfer on all its children that have wfTransfer set.
- //
-
- struct TTransferIterInfo {
- void* Data;
- TTransferDirection Direction;
- };
-
- static void transferDatchild(TWindow* child, TTransferIterInfo* info) {
- if (child->IsFlagSet(wfTransfer))
- (char*)info->Data += child->Transfer(info->Data, info->Direction);
- }
-
- UINT
- TWindow::Transfer(void* buffer, TTransferDirection direction)
- {
- if (buffer) {
- TTransferIterInfo info = { buffer, direction };
- ForEach((TActionFunc)transferDatchild, &info);
- return (char near*)info.Data - (char near*)buffer;
- }
- return 0;
- }
-
- //$---------------------------------------------------------------------------
- //
- // transfers data between the TWindow's data buffer and the child
- // windows in its ChildList (data is not transfered between any child
- // windows whose wfTransfer flag is not set)
- //
- void
- TWindow::TransferData(TTransferDirection direction)
- {
- if (TransferBuffer)
- Transfer(TransferBuffer, direction);
- }
-
- //
- // registers the TWindow's MS-Windows, if not already registered
- //
- BOOL
- TWindow::Register()
- {
- WNDCLASS windowClass;
- BOOL gc;
-
- //
- // Only check for globally registered classes if not in an NT WoW box,
- // since WoW plays nasty games with class registration.
- //
- #if defined(__WIN32__)
- gc = ::GetClassInfo(0, GetClassName(), &windowClass);
- #else
- static BOOL isWoW = BOOL(::GetWinFlags()&0x4000);
- if (!isWoW)
- gc = ::GetClassInfo(0, GetClassName(), &windowClass);
- else
- gc = 0;
- #endif
-
- if (!gc && !GetModule()->GetClassInfo(GetClassName(), &windowClass)) {
- GetWindowClass(windowClass);
- return ::RegisterClass(&windowClass);
- }
-
- return TRUE;
- }
-
- //
- // returns a BOOL indicating whether or not it is Ok to close the TWindow
- //
- // iterates through the TWindow's ChildList, calling the CanClose()
- // method of each
- //
- // returns FALSE if any of the child windows returns FALSE
- //
-
- static BOOL cannotClose(TWindow* win, void*) {
- return win->HWindow && !win->CanClose();
- }
-
- BOOL
- TWindow::CanClose()
- {
- return !FirstThat(cannotClose);
- }
-
- //
- // destroys the associated MS-Windows interface element and frees "this"
- // after determining that it is Ok to do so
- //
- // if the TWindow is the main window of the application, calls the CanClose()
- // method of the application, else calls this->CanClose(), before calling
- // Destroy()
- //
- void
- TWindow::CloseWindow(int retVal)
- {
- BOOL willClose;
-
- if (IsFlagSet(wfMainWindow))
- willClose = GetApplication()->CanClose();
-
- else
- willClose = CanClose();
-
- if (willClose)
- Destroy(retVal);
- }
-
- //
- // the default response to a WM_CLOSE message is to call CloseWindow()
- // and then have the window deleted if CloseWindow() did the Destroy().
- //
- void
- TWindow::EvClose()
- {
- if (IsFlagSet(wfAlias))
- DefaultProcessing();
-
- else {
- CloseWindow();
- if (!HWindow)
- GetApplication()->Condemn(this); // Assumes delete
- }
- }
-
- //
- // responds to an incoming WM_DESTROY message
- //
- // Calls CleanupWindow() to let derived classes cleanup
- //
- // if the TWindow is the application's main window posts a 'quit' message to
- // end the application, unless already in ~TApplication() (MainWindow == 0)
- //
- void
- TWindow::EvDestroy()
- {
- CleanupWindow();
-
- if (!IsFlagSet(wfAlias)) {
- if (IsFlagSet(wfMainWindow))
- ::PostQuitMessage(GetApplication()->Status);
- }
-
- DefaultProcessing();
- }
-
- //
- // responds to an incoming WM_NCDESTROY message, the last message
- // sent to an MS-Windows interface element
- //
- // sets the HWindow data member of the TWindow to zero to indicate that an
- // interface element is no longer associated with the object
- //
- void
- TWindow::EvNCDestroy()
- {
- DefaultProcessing();
- HWindow = 0;
- }
-
- //
- // respond to Windows attempt to close close down
- //
- BOOL
- TWindow::EvQueryEndSession()
- {
- if (IsFlagSet(wfAlias))
- return (BOOL)DefaultProcessing();
-
- else if (IsFlagSet(wfMainWindow))
- return GetApplication()->CanClose();
-
- else
- return CanClose();
- }
-
- //
- // if the window receives an Exit menu choice, it will attempt
- // to close down the window
- //
- void
- TWindow::CmExit()
- {
- if (IsFlagSet(wfMainWindow))
- CloseWindow();
-
- else
- DefaultProcessing();
- }
-
- //
- // Handle message posted to us by a control needing assistance in dealing with
- // invalid inputs
- //
- void
- TWindow::EvChildInvalid(HWND hWnd)
- {
- ::SendMessage(hWnd, WM_CHILDINVALID, 0, 0);
- }
-
- //----------------------------------------------------------------------------
- // Non-virtuals
- //----------------------------------------------------------------------------
-
- //$---------------------------------------------------------------------------
- unsigned
- TWindow::NumChildren()
- {
- return IndexOf(ChildList) + 1;
- }
-
- //$---------------------------------------------------------------------------
- //
- //
- void
- TWindow::AssignZOrder()
- {
- TWindow* wnd;
- HWND curWindow = HWindow;
-
- if (curWindow) {
- curWindow = ::GetWindow(curWindow, GW_CHILD);
-
- if (curWindow) {
- int i = 1;
-
- for (curWindow = ::GetWindow(curWindow, GW_HWNDLAST);
- curWindow;
- curWindow = ::GetWindow(curWindow, GW_HWNDPREV))
- {
- wnd = GetWindowPtr(curWindow);
-
- if (wnd)
- wnd->ZOrder = (WORD)i++;
- }
- }
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // The private field ZOrder is used to ensure the Z-order is
- // consistent through read and write of the object.
- //
- // When the object is written, parent->AssignZOrder will fill in this value
- //
- // ZOrder ranges from 1 to N where N is the number of objects and the top one.
- // A ZOrder value of 0 means that the Z-ordering has not be recoreded.
- //
- BOOL
- TWindow::OrderIsI(TWindow* win, void* position)
- {
- return win->ZOrder == *(int*)position;
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns TRUE if the child was supposed to be created but couldn't be
- //
- static BOOL
- cantCreate(TWindow* win, void*)
- {
- if (win->HWindow)
- return FALSE;
-
- BOOL autoCreate = win->IsFlagSet(wfAutoCreate);
-
- WARNX(OwlWin, !autoCreate, 0,
- "Child window(Id=" << win->GetId() << ") not autocreated");
- if (!autoCreate)
- return FALSE;
-
- //
- // this call will only fail if a user-defined Create() returns FALSE. Owl's
- // Creates always throw exceptions.
- //
- if (!win->Create())
- return TRUE;
-
- if (win->IsIconic()) {
- int textLen = ::GetWindowTextLength(win->HWindow);
- char* text = new char[textLen + 1];
-
- ::GetWindowText(win->HWindow, text, textLen + 1);
- ::SetWindowText(win->HWindow, text);
- delete text;
- }
- return FALSE;
- }
-
- //
- // create the children of the object. returns true if all the windows
- // were successfully created
- //
- BOOL
- TWindow::CreateChildren()
- {
- if (FirstThat(cantCreate)) // create children first to restore created order
- return FALSE;
- //
- // restore Z-ordering for children that have Z-ordering recorded
- //
- HWND above = HWND_TOP;
- for (int top = NumChildren(); top; top--) {
- TWindow* wnd = FirstThat(&TWindow::OrderIsI, &top);
- if (wnd) {
- wnd->SetWindowPos(above, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
- above = wnd->HWindow;
- }
- }
- return TRUE;
- }
-
- //$---------------------------------------------------------------------------
- //
- // adds the passed pointer to a child window to the linked list
- // of sibling windows which ChildList points to
- //
- void
- TWindow::AddChild(TWindow* child)
- {
- if (child)
- if (ChildList) {
- child->SiblingList = ChildList->SiblingList;
- ChildList->SiblingList = child;
- ChildList = child;
-
- } else {
- ChildList = child;
- child->SiblingList = child;
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns a pointer to the TWindow's previous sibling (the
- // window previous to the TWindow in its parent's child window
- // list)
- //
- // returns the sibling which points to the TWindow
- //
- // if the TWindow was the first child added to the list, returns
- // a pointer to the last child added
- //
- TWindow*
- TWindow::Previous()
- {
- if (!SiblingList)
- return 0;
-
- else {
- TWindow* CurrentIndex = this;
-
- while (CurrentIndex->Next() != this)
- CurrentIndex = CurrentIndex->Next();
-
- return CurrentIndex;
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns a pointer to the first TWindow in the ChildList that meets some
- // specified criteria
- //
- // if no child in the list meets the criteria, 0 is returned
- //
- // the Test parameter which defines the criteria, is a pointer to a
- // function that takes a TWindow pointer & a pointer to void
- //
- // the TWindow* will be used as the pointer to the child window and
- // the void* as a pointer to the Test function's additional parameters
- //
- // the Test function must return a Boolean value indicating whether the
- // child passed meets the criteria
- //
- TWindow*
- TWindow::FirstThat(TCondFunc test, void* paramList)
- {
- if (ChildList) {
- TWindow* nextChild = ChildList->Next();
- TWindow* curChild;
-
- do {
- curChild = nextChild;
- nextChild = nextChild->Next();
-
- //
- // Test curChild for okay
- //
- if (test(curChild, paramList))
- return curChild;
- } while (curChild != ChildList && ChildList);
- }
- return 0;
- }
-
- //$---------------------------------------------------------------------------
- //
- // iterates over each child window in the TWindow's ChildList,
- // calling the procedure whose pointer is passed as the Action to be
- // performed for each child
- //
- // a pointer to a child is passed as the first parameter to the iteration
- // procedure
- //
- void
- TWindow::ForEach(TActionFunc action, void* paramList)
- {
- if (ChildList) {
- TWindow* curChild;
- TWindow* nextChild = ChildList->Next(); // allows ForEach to delete children
-
- do {
- curChild = nextChild;
- nextChild = nextChild->Next();
- action(curChild, paramList);
- } while (curChild != ChildList && ChildList);
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns a pointer to the first TWindow in the ChildList that
- // meets some specified criteria
- //
- // if no child in the list meets the criteria, 0 is returned
- //
- // the Test parameter which defines the criteria, is a pointer to a member
- // function (this is how it's different from FirstThat above) that takes a
- // pointer to a TWindow & a pointer to void
- //
- // the TWindow pointer will be used as the pointer to the child window and the
- // void pointer as a pointer to the Test function's additional parameters
- //
- // the Test function must return a Boolean value indicating whether the child
- // passed meets the criteria
- //
- TWindow*
- TWindow::FirstThat(TCondMemFunc test, void* paramList)
- {
- if (ChildList) {
- TWindow* nextChild = ChildList->Next();
- TWindow* curChild;
-
- do {
- curChild = nextChild;
- nextChild = nextChild->Next();
-
- if ((this->*test)(curChild, paramList))
- return curChild;
- } while (curChild != ChildList && ChildList);
- }
- return 0;
- }
-
- //$---------------------------------------------------------------------------
- //
- // iterates over each child window in the TWindow's ChildList,
- // calling the member function (unlike ForEach above which takes pointer
- // to non-member function) whose pointer is passed as the Action to
- // be performed for each child
- //
- // a pointer to a child is passed as the first parameter to the iteration
- // procedure
- //
- void
- TWindow::ForEach(TActionMemFunc action, void* paramList)
- {
- if (ChildList) {
- TWindow* nextChild = ChildList->Next();
- TWindow* curChild;
-
- do {
- curChild = nextChild;
- nextChild = nextChild->Next();
- (this->*action)(curChild, paramList);
- } while (curChild != ChildList && ChildList);
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns the position at which the passed child window appears
- // in the TWindow's ChildList
- //
- // if the child does not appear in the list, -1 is returned
- //
- // zero'th position is ChildList->Next
- //
- static int position;
- static BOOL isItThisChild1(TWindow* win, void* child) {
- ++position;
- return win == (TWindow*)child;
- }
-
- int
- TWindow::IndexOf(TWindow* child)
- {
- position = -1;
- return FirstThat(isItThisChild1, child) ? position : -1;
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns the child at the passed position in the TWindow's
- // ChildList
- //
- // the ChildList is circularly-referent so that passing a position
- // larger than the number of children will cause the traversal of the
- // list to wrap
- //
- // zero'th position is ChildList->Next
- //
- TWindow*
- TWindow::At(int position)
- {
- if (position == -1)
- return 0;
-
- else {
- TWindow* currentChild = ChildList;
-
- if (currentChild) {
- currentChild = ChildList->Next();
-
- while (position > 0) {
- currentChild = currentChild->Next();
- position--;
- }
- }
- return currentChild;
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // returns a pointer to the window in the ChildList with the passed Id
- //
- // if no child in the list has the passed Id, 0 is returned
- //
- static BOOL isItThisChild2(TWindow* win, void* id) {
- return win->GetId() == *(int*)id;
- }
-
- TWindow*
- TWindow::ChildWithId(int id) const
- {
- return ((TWindow*)this)->FirstThat(isItThisChild2, &id);
- }
-
- //$---------------------------------------------------------------------------
- //
- LRESULT
- TWindow::SendMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
- LRESULT result = ::SendMessage(HWindow, msg, wParam, lParam);
- GetApplication()->ResumeThrow();
- return result;
- }
-
- //$---------------------------------------------------------------------------
- //
- LRESULT
- TWindow::ForwardMessage(HWND hWnd, BOOL send)
- {
- if (!hWnd)
- return 0;
- if (send) {
- LRESULT result = ::SendMessage(hWnd, CurrentEvent.message,
- CurrentEvent.wParam, CurrentEvent.lParam);
- GetApplication()->ResumeThrow();
- return result;
- }
- else
- return ::PostMessage(hWnd, CurrentEvent.message,
- CurrentEvent.wParam, CurrentEvent.lParam);
- }
-
- //$---------------------------------------------------------------------------
- //
- // Forward a message to an Owl window. If send, then bypass windows directly
- // and call the owl window's window proc.
- //
- LRESULT
- TWindow::ForwardMessage(BOOL send)
- {
- if (send)
- return HandleMessage(CurrentEvent.message, CurrentEvent.wParam,
- CurrentEvent.lParam);
- return ForwardMessage(HWindow, send);
- }
-
- //$---------------------------------------------------------------------------
- //
- void
- TWindow::ChildBroadcastMessage(UINT msg, WPARAM wParam, LPARAM lParam)
- {
- for (HWND hWndChild = GetWindow(GW_CHILD); hWndChild; ) {
- HWND hWndNext = ::GetWindow(hWndChild, GW_HWNDNEXT);
- ::SendMessage(hWndChild, msg, wParam, lParam);
- GetApplication()->ResumeThrow();
- hWndChild = hWndNext;
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // destroys the associated MS-Windows interface element and frees "this"
- // without calling CanClose()
- //
- // This function is obsolete. Destroy() should be called directly, & then the
- // window destructed (using delete, etc).
- //
- void
- TWindow::ShutDownWindow(int retVal)
- {
- Destroy(retVal);
- GetApplication()->Condemn(this); // Assumes delete
- }
-
- //$---------------------------------------------------------------------------
- //
- // displays the TWindow, after checking that it has a valid handle
- //
- void
- TWindow::Show(int cmdShow)
- {
- //
- // if the window is being minimzed send a WM_SYSCOMMAND; this way the
- // frame window focus saving works properly
- //
- if (HWindow)
- if (cmdShow == SW_MINIMIZE)
- HandleMessage(WM_SYSCOMMAND, SC_MINIMIZE);
-
- else
- ::ShowWindow(HWindow, cmdShow);
- }
-
- //$---------------------------------------------------------------------------
- //
- // sets the Title and caption of the TWindow
- //
- void
- TWindow::SetCaption(const char far* title)
- {
- if (Title != title) {
- if (HIWORD(Title))
- delete Title;
-
- Title = strnewdup(title);
- }
-
- if (HWindow)
- ::SetWindowText(HWindow, Title);
- }
-
- //$---------------------------------------------------------------------------
- //
- // gets the Title member var from the current window caption or text
- //
- void
- TWindow::GetWindowTextTitle()
- {
- if (LOWORD(Title) == 0xFFFF) // ignore "don't-change" titles
- return;
-
- if (HIWORD(Title))
- delete Title;
-
- int titleLength = GetWindowTextLength();
- if (titleLength < 0)
- Title = strnewdup((const char far*)"");
-
- else {
- Title = new far char[titleLength + 1];
- Title[0] = 0;
- Title[titleLength] = 0;
- GetWindowText(Title, titleLength + 1);
- }
- }
-
- //$---------------------------------------------------------------------------
- //
- // copy over the styles, the coordinates & the id from the existing HWnd into
- // the owl TWindow members.
- // Note: the title is not copied here
- //
- void
- TWindow::GetHWndState()
- {
- //
- // retrieve Attr.Style and Attr.ExStyle
- //
- // NOTE: some windows controls (e.g. EDIT) change the style bits
- // (e.g. WS_BORDER) from their original values. if we always reset
- // Attr.Style and Attr.ExStyle by extracting their values from
- // Windows, we will lose some of the style bits we supplied
- // in the CreateWindowEx call. in the case of the ResourceId
- // constructors, of course, we must retrieve these values.
- //
- if (IsFlagSet(wfFromResource)) {
- Attr.Style = GetWindowLong(GWL_STYLE);
- Attr.ExStyle = GetWindowLong(GWL_EXSTYLE);
- }
-
- //
- // retrieve Attr.X, Attr.Y, Attr.W and Attr.H
- //
- TRect wndRect;
-
- GetWindowRect(wndRect);
- Attr.H = wndRect.Height();
- Attr.W = wndRect.Width();
-
- HWND hParent = GetParent();
- if ((Attr.Style & WS_CHILD) && hParent)
- ::ScreenToClient(hParent, &wndRect.TopLeft());
-
- Attr.X = wndRect.left;
- Attr.Y = wndRect.top;
-
- #if defined(__WIN32__)
- Attr.Id = GetWindowLong(GWL_ID);
- #else
- Attr.Id = GetWindowWord(GWW_ID);
- #endif
- }
-
- //$---------------------------------------------------------------------------
- //
- // Set the cursor for this window given a TModule and a resId
- // Updates the current cursor if it is over this window.
- //
- BOOL
- TWindow::SetCursor(TModule* module, TResId resId)
- {
- if (module == CursorModule && resId == CursorResId)
- return FALSE;
-
- HCURSOR hOldCursor = (HCursor && CursorModule) ? HCursor : 0;
-
- CursorModule = module;
- CursorResId = resId;
- if (CursorResId)
- if (CursorModule)
- HCursor = CursorModule->LoadCursor(CursorResId);
- else
- HCursor = ::LoadCursor(0, CursorResId);
- else
- HCursor = 0;
-
- //
- // If the cursor is in our client window then set it now
- //
- if (HWindow) {
- TPoint p;
- GetCursorPos(p);
- ScreenToClient(p);
- if (GetClientRect().Contains(p))
- ::SetCursor(HCursor);
- }
-
- //
- // Destroy old cursor if there was one & it was not loaded from USER
- //
- if (hOldCursor)
- ::DestroyCursor(hOldCursor);
- return TRUE;
- }
-
- //$---------------------------------------------------------------------------
- //
- // not inline to avoid requiring gdiobjec.h by window.h
- //
- BOOL
- TWindow::GetUpdateRgn(TRegion& region, BOOL erase) const
- {
- return ::GetUpdateRgn(HWindow, region, erase);
- }
-
- //$---------------------------------------------------------------------------
- //
- //
- int
- TWindow::MessageBox(const char far* text,
- const char far* caption,
- UINT type)
- {
- Application->EnableCtl3dAutosubclass(TRUE);
- int retValue = ::MessageBox(HWindow, text, caption, type);
- Application->EnableCtl3dAutosubclass(FALSE);
- return retValue;
- }
-
- #if defined(__TRACE) || defined(__WARN)
- ostream& operator <<(ostream& os, const TWindow& w)
- {
- os << '(';
- #if !defined(BI_NO_RTTI)
- os << typeid(w).name() << ',';
- #endif
- os << "0x" << hex << (unsigned)w.HWindow << ',';
- if (!w.Parent)
- os << '\'' << TResId(w.Title) << '\'';
- else
- os << "id=" << w.GetId();
- os << ')';
- return os;
- }
- #endif
-
- //$---------------------------------------------------------------------------
- //
- // static member function to construct base TXOwl object
- //
- string
- TWindow::TXWindow::Msg(TWindow* win, UINT resId)
- {
- BOOL found; // did we locate the string
- string rscMsg = ResourceIdToString(&found, resId);
-
- if (found) {
- char buf[255];
-
- //
- // supply title of window if we have a valid window
- //
- wsprintf(buf, rscMsg.c_str(), win ? win->Title : "");
- return string(buf);
-
- } else
- return rscMsg;
- }
-
- //$---------------------------------------------------------------------------
- //
- // InvalidWindow exception constructor
- //
- TWindow::TXWindow::TXWindow(TWindow* win, UINT resId)
- : TXOwl(Msg(win, resId))
- {
- Window = win;
- }
-
- TWindow::TXWindow::TXWindow(const TXWindow& src) : TXOwl(src),Window(src.Window)
- {
- }
-
- int
- TWindow::TXWindow::Unhandled(TModule* app, unsigned promptResId)
- {
- delete Window;
- Window = 0;
- return TXOwl::Unhandled(app, promptResId);
- }
-
- TXOwl*
- TWindow::TXWindow::Clone()
- {
- return new TXWindow(*this);
- }
-
-