OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
window.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1991, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of TWindow. This defines the basic behavior of all Windows.
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/defs.h>
10#include <owl/window.h>
11#include <owl/applicat.h>
12#include <owl/appdict.h>
13#include <owl/scroller.h>
14#include <owl/gdiobjec.h>
15#include <owl/menu.h>
16#include <owl/framewin.h>
17#include <owl/commctrl.h>
18#include <owl/shellitm.h>
19#include <owl/tooltip.h>
20
21#if defined(BI_MULTI_THREAD_RTL)
22#include <owl/thread.h>
23#endif
24
25#include <stdlib.h>
26#include <stdio.h>
27
28#include <owl/registry.h>
29
30#include <owl/hlpmanag.h> //THelpHitInfo
31#include <array>
32#include <vector>
33#include <algorithm>
34
35#if defined(__BORLANDC__)
36# pragma option -w-ccc // Disable "Condition is always true/false"
37#endif
38
39using namespace std;
40
41namespace owl {
42
44DIAG_DECLARE_GROUP(OwlMsg); // diagnostic group for message tracing
45DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlWin, 1, 0); // diag. group for windows
46DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlCmd, 1, 0); // diag. group for commands
47
48namespace {
49
50 //
51 // Attempts to retrieve the system setting for mouse wheel scrolling granularity.
52 // If retrieval fails, the failure is logged (in debug mode) and the system default is returned.
53 //
55 {
56 auto n = 3u; // System default.
58 WARN(!r, _T("SystemParametersInfo(SPI_GETWHEELSCROLLLINES) failed. LastError: ") << GetLastError()); InUse(r);
59 return n;
60 };
61
62} // namespace
63
64} // OWL namespace
65
66//
67// Define to use rtti to create unique window ids for the message cache
68//
69#define OWL_RTTI_MSGCACHE
70#define TYPE_UNIQUE_ID(t) reinterpret_cast<UINT_PTR>(typeid(t).name())
71
72bool gBatchMode = false; // true if we were invoked to do batch processing
73 // which means windows should be invisible and whatnot
74 // currently this is only set if we have an output parameter
75
76namespace owl {
77
78//
79// Externs defined in owl.cpp
80//
84
97 EV_WM_CTLCOLORBTN(EvCtlColor),
98 EV_WM_CTLCOLORDLG(EvCtlColor),
99 EV_WM_CTLCOLOREDIT(EvCtlColor),
101
102#if defined(OWL5_COMPAT)
103
104 EV_WM_CTLCOLORMSGBOX(EvCtlColor), // This entry is deprecated. See TDispatch<WM_CTLCOLORMSGBOX>.
105
106#endif
107
127
128
129
130/// \class TCommandEnabler
131///
132/// An abstract base class used for automatic enabling and disabling of commands,
133/// TCommandEnabler is a class from which you can derive other classes, each one
134/// having its own command enabler. For example, TButtonGadgetEnabler is a derived
135/// class that's a command enabler for button gadgets, and TMenuItemEnabler is a
136/// derived class that's a command enabler for menu items. Although your derived
137/// classes are likely to use only the functions Enable, SetCheck, and GetHandled,
138/// all of TCommandEnabler's functions are described so that you can better
139/// understand how ObjectWindows uses command processing. The following paragraphs
140/// explain the dynamics of command processing.
141///
142///
143/// <b>Handling command messages</b>
144///
145/// Commands are messages of the windows WM_COMMAND type that have associated
146/// command identifiers (for example, CM_FILEMENU). When the user selects an item
147/// from a menu or a toolbar, when a control sends a notification message to its
148/// parent window, or when an accelerator keystroke is translated, a WM_COMMAND
149/// message is sent to a window.
150///
151///
152/// <b>Responding to command messages</b>
153///
154/// A command is handled differently depending on which type of command a window
155/// receives. Menu items and accelerator commands are handled by adding a command
156/// entry to a message response table using the EV_COMMAND macro. The entry requires
157/// two arguments:
158/// - A command identifier (for example, CM_LISTUNDO)
159/// - A member function (for example, CMEditUndo)
160///
161/// Child ID notifications, messages that a child window sends to its parent window,
162/// are handling by using one of the notification macros defined in the header file
163/// windowev.h.
164/// It is also possible to handle a child ID notification at the child window by
165/// adding an entry to the child's message response table using the
166/// EV_NOTIFY_AT_CHILD macro. This entry requires the following arguments:
167/// - A notification message (for example, LBN_DBLCLK)
168/// - A member function (for example, CmEditItem)
169///
170/// <b>TWindow command processing</b>
171///
172/// One of the classes designed to handle command processing, TWindow performs basic
173/// command processing according to these steps:
174/// - 1. The member function WindowProc calls the virtual member function EvCommand.
175/// - 2. EvCommand checks to see if the window has requested handling the command by
176/// looking up the command in the message response table.
177/// - 3. If the window has requested handling the command identifier by using the
178/// EV_COMMAND macro, the command is dispatched.
179///
180/// TWindow also handles Child ID notifications at the child window level.
181///
182///
183/// <b>TFrameWindow command processing</b>
184///
185/// TFrameWindow provides specialized command processing by overriding its member
186/// function EvCommand and sending the command down the command chain (that is, the
187/// chain of windows from the focus window back up to the frame itself, the original
188/// receiver of the command message).
189///
190/// If no window in the command chain handles the command, TFrameWindow delegates
191/// the command to the application object. Although this last step is theoretically
192/// performed by the frame window, it is actually done by TWindow's member function,
193/// DefaultProcessing().
194///
195///
196/// <b>Invoking EvCommand</b>
197///
198/// When TFrameWindow sends a command down the command chain, it does not directly
199/// dispatch the command; instead, it invokes the window's EvCommand member
200/// function. This procedure gives the windows in the command chain the flexibility
201/// to handle a command by overriding the member function EvCommand instead of being
202/// limited to handling only the commands requested by the EV_COMMAND macro.
203///
204///
205/// <b>Handling command enable messages</b>
206///
207/// Most applications expend considerable energy updating menu items and tool bar
208/// buttons to provide the necessary feedback indicating that a command has been
209/// enabled. In order to simplify this procedure, ObjectWindows lets the event
210/// handler that is going to handle the command make the decision about whether or
211/// not to enable or disable a command.
212///
213/// Although the WM_COMMAND_ENABLE message is sent down the same command chain as
214/// the WM_COMMAND event; exactly when the WM_COMMAND_ENABLE message is sent depends
215/// on the type of command enabling that needs to be processed.
216///
217///
218/// <b>Command enabling for menu items</b>
219///
220/// TFrameWindow performs this type of command enabling when it receives a
221/// WM_INITMENUPOPUP message. It sends this message before a menu list appears.
222/// ObjectWindows then identifies the menu commands using the command IDs and sends
223/// requests for the commands to be enabled.
224///
225/// Note that because Object Windows actively maintains toolbars and menu items, any
226/// changes made to the variables involved in the command enabling functions are
227/// implemented dynamically and not just when a window is activated.
228///
229///
230/// <b>Command enabling for toolbar buttons</b>
231///
232/// This type of command enabling is performed during idle processing (in the
233/// IdleAction function). The Default Message-Processing Flowchart that accompanies
234/// TWindow::DefaultProcessing is a graphical illustration of this process.
235///
236///
237/// <b>Creating specialized command enablers</b>
238///
239/// Associated with the WM_COMMAND_ENABLE message is an object of the
240/// TCommandEnabler type. This family of command enablers includes specialized
241/// command enablers for menu items and toolbar buttons.
242///
243/// As you can see from TCommandEnabler's class declaration, you can do
244/// considerably more than simply enable or disable a command using the command
245/// enabler. For example, you have the ability to change the text associated with
246/// the command as well as the state of the command.
247///
248///
249/// <b>Using the EV_COMMAND_ENABLE macro</b>
250///
251/// You can use the EV_COMMAND_ENABLE macro to handle WM_COMMAND_ENABLE messages.
252/// Just as you do with the EV_COMMAND macro, you specify the command identifier
253/// that you want to handle and the member function you want to invoke to handle the
254/// message.
255///
256///
257/// <b>Automatically enabling and disabling commands</b>
258///
259/// ObjectWindows simplifies enabling and disabling of commands by automatically
260/// disabling commands for which there are no associated handlers. TFrameWindow's
261/// member function EvCommandEnable performs this operation, which involves
262/// completing a two-pass algorithm:
263/// - 1. The first pass sends a WM_COMMAND_ENABLE message down the command chain
264/// giving each window an explicit opportunity to do the command enabling.
265/// - 2. If no window handles the command enabling request, then ObjectWindows checks
266/// to see whether any windows in the command chain are going to handle the command
267/// through any associated EV_COMMAND entries in their response tables. If there is
268/// a command handler in one of the response tables, then the command is enabled;
269/// otherwise it is disabled.
270///
271/// Because of this implicit command enabling or disabling, you do not need to (and
272/// actually should not) do explicit command enabling unless you want to change the
273/// command text, change the command state, or conditionally enable or disable the
274/// command.
275///
276/// If you handle commands indirectly by overriding the member function EvCommand
277/// instead of using the EV_COMMAND macro to add a response table entry, then
278/// ObjectWindows will not be aware that you are handling the command. Consequently,
279/// the command may be automatically disabled. Should this occur, the appropriate
280/// action to take is to also override the member function EvCommandEnable and
281/// explicitly enable the command.
282
283
284//
285/// Constructs the TCommandEnabler object with the specified command ID. Sets the
286/// message responder (hWndReceiver) to zero.
287//
289:
290 Id(id),
291 HWndReceiver(hReceiver)
292{
293 Flags = 0;
294}
295
296//
297/// Enables or disables the command sender. When Enable is called, it sets the
298/// Handled flag.
299//
300void
305
307{
308 auto wp = GetWindowPlacement();
309 TRACEX(OwlWin, 1,
310 "PLACEMENT=" << TRect{wp.rcNormalPosition} <<
311 " handle=" << GetHandle() <<
312 " min=" << TPoint{wp.ptMinPosition} <<
313 " max=" << TPoint{wp.ptMaxPosition} <<
314 " showCmd=" << wp.showCmd <<
315 " flags=" << wp.flags);
316}
317
318//
319/// Adds this to the child list of parent if nonzero, and calls EnableAutoCreate so
320/// that this will be created and displayed along with parent. Also sets the title
321/// of the window and initializes the window's creation attributes.
322///
323/// The following paragraphs describe procedures common to both constructor
324/// syntaxes. module specifies the application or DLL that owns the TWindow
325/// instance. ObjectWindows needs the correct value of module to find needed
326/// resources. If module is 0, TWindow sets its module according to the following
327/// rules:
328/// - If the window has a parent, the parent's module is used.
329/// - If the TWindow constructor is invoked from an application, the
330/// module is set to the application.
331/// - If the TWindow constructor is invoked from a DLL that is
332/// dynamically linked with the ObjectWindows DLL and the currently running
333/// application is linked the same way, the module is set to the currently running
334/// application.
335/// - If the TWindow constructor is invoked from a DLL that is
336/// statically linked with the ObjectWindows library or the invoking DLL is
337/// dynamically linked with ObjectWindows DLL but the currently running application
338/// is not, no default is used for setting the module. Instead, a TXInvalidModule
339/// exception is thrown and the object is not created.
340//
342 : Handle{nullptr}, Title{nullptr}, DefaultProc{nullptr}, InstanceProc{nullptr}, Module{nullptr}
343{
344 Init(parent, title, module);
345}
346
347//
348/// String-aware overload
349//
351 : Handle{nullptr}, Title{nullptr}, DefaultProc{nullptr}, InstanceProc{nullptr}, Module{nullptr}
352{
353 Init(parent, title, module);
354}
355
356//
357/// Constructs a TWindow that is used as an alias for a non-ObjectWindows window,
358/// and sets wfAlias. Because the HWND is already available, this constructor,
359/// unlike the other TWindow constructor, performs the "thunking" and extraction of
360/// HWND information instead of waiting until the function Create creates the
361/// interface element.
362///
363/// The following paragraphs describe procedures common to both constructor
364/// syntaxes. module specifies the application or DLL that owns the TWindow
365/// instance. ObjectWindows needs the correct value of module to find needed
366/// resources. If module is 0, TWindow sets its module according to the following
367/// rules:
368/// - If the window has a parent, the parent's module is used.
369/// - If the TWindow constructor is invoked from an application, the
370/// module is set to the application.
371/// - If the TWindow constructor is invoked from a DLL that is
372/// dynamically linked with the ObjectWindows DLL and the currently running
373/// application is linked the same way, the module is set to the currently running
374/// application.
375/// - If the TWindow constructor is invoked from a DLL that is
376/// statically linked with the ObjectWindows library or the invoking DLL is
377/// dynamically linked with ObjectWindows DLL but the currently running application
378/// is not, no default is used for setting the module. Instead, a TXInvalidModule
379/// exception is thrown and the object is not created.
380
382 : Handle{nullptr}, Title{nullptr}, DefaultProc{nullptr}, InstanceProc{nullptr}, Module{nullptr}
383{
385 Init(handle, module);
386}
387
388//
389/// Protected constructor for use by immediate virtually derived classes.
390/// Immediate derivitives must call an Init() before constructions are done.
391//
393 : Handle{nullptr}, Title{nullptr}, DefaultProc{nullptr}, InstanceProc{nullptr}, Module{nullptr}
394{}
395
396//
397/// Normal initialization of a default constructed TWindow. Is ignored if
398/// called more than once.
399//
400void
402{
403 if (!InstanceProc) {
405 PerformInit(parent, module);
407
408 // Initialize creation attributes
409 //
410 Attr.Style = WS_CHILD | WS_VISIBLE;
411 Attr.X = Attr.Y = Attr.W = Attr.H = 0;
412 Attr.ExStyle = 0;
413 Attr.Id = 0;
414 }
415}
416
417//
418/// Wrapper initialization of a default constructed TWindow. Is ignored if
419/// called more than once.
420//
421void
423{
425
426 if (!InstanceProc) {
427 // Perform preliminary initialization
428 //
430 SetCaption(LPCTSTR(nullptr));
431
432 // If we've been given a module, then setup that and the app now if
433 // possible so that GetWindowPtr below has some context. Otherwise at least
434 // set it to 0.
435 //
436 Application = TYPESAFE_DOWNCAST(module,TApplication);
437
438 // If the receiver's parent is an OWL window then pass the window to
439 // PerformInit so the receiver can be added to the parent's list of children.
440 //
442 TWindow* parent = hParent ? GetWindowPtr(hParent) : nullptr;
443 PerformInit(parent, module);
444
445 // Install the instance window proc.
446 //
448
449 // Copy over the title, styles, the coordinates & the id
450 //
452 GetHWndState(true); //DLN now we force resysnc of style settings for non-owl windows.
453
454 // Keep track that this is an alias object & that it is already created
455 //
457
458 // Unique id may have been set inadvertantly to TWindow by the above
459 // GetWindowTextTitle, et. al. Reset it just in case
460 //
461 SetUniqueId();
462 }
463}
464
465//
466// Private initializer function that does the bulk of the work for the
467// protected Init()s
468//
469void
470TWindow::PerformInit(TWindow* parent, TModule* module)
471{
472 // Initialize members.
473 //
474 ZOrder = 0;
475 ChildList = nullptr;
476 Flags = wfDeleteOnClose;
477 TransferBuffer = nullptr;
478 TransferBufferSize = 0;
479 Parent = parent;
480 Attr.Param = nullptr;
481 Attr.Menu = 0;
482 Attr.AccelTable = 0;
483 HAccel = nullptr;
484 Scroller = 0;
485 ContextPopupMenu = nullptr;
486 Tooltip = nullptr;
487 CursorModule = nullptr;
488 CursorResId = 0;
489 HCursor = nullptr;
490 BkgndColor = TColor::None;
491 TextColor = TColor::None;
492 Font.reset();
493
494 // Set the window proc for this window instance.
495 //
496 InstanceProc = CreateInstanceProc();
497
498 // Link to parent.
499 //
500 if (Parent)
501 Parent->AddChild(this);
502 else
503 SiblingList = nullptr;
504
505 // Use passed module if one, else get parent's. If no parent, use app
506 //
507 if (Parent) {
508 Application = Parent->GetApplication();
509 Module = module ? module : Parent->GetModule();
510 }
511 else {
512 Module = module ? module : nullptr;
513 Application = TYPESAFE_DOWNCAST(Module,TApplication);
514 if (!Application)
515 {
516 //Application = OWLGetAppDictionary().GetApplication(0);
517 Application = GetApplicationObject();
518 if (!Module)
519 Module = Application;
520 }
521 CHECK(Application);
522 }
523 SetUniqueId();
524
525 TRACEX(OwlWin, 1, _T("TWindow constructed @") << (void*)this << *this);
526}
527
528namespace
529{
530
531//
532// Function prototype
533//
534void CacheFlush(UINT_PTR id);
535
536}
537
538//
539/// Destroys this window (unless this is an alias) and the children.
540/// First, restores the underlying window's WindowProc (i.e. reverts the subclassing).
541/// Then, destroys the children and, in turn, the underlying window (unless aliased).
542/// Finally, dissociates this from the parent and application, and deallocates acquired resources.
543//
545{
546 // Clean up the instance WindowProc early; we're in the destructor, so we don't want to handle
547 // any more messages.
548 //
549 if (GetHandle())
550 {
551 WARNX(OwlWin, GetWindowProc() != GetInstanceProc(), 0,
552 _T("Restoring old WndProc after foreign subclass of:") << *this);
553 SetWindowProc(DefaultProc ? DefaultProc : &::DefWindowProc);
554 }
555 FreeInstanceProc();
556 InstanceProc = nullptr;
557
558 // Flush the cache, so that messages will not be dispatched to a destructed derived class.
559 //
560 owl::CacheFlush(UniqueId);
561
562 // Destroy the children first, so that they get a chance to clean up.
563 //
564 // Note that the old implementation deleted the child while traversing the linked list of
565 // children. However, while the implementation of the iteration may be written to allow this, it
566 // is poor programming style to assume that iterators remain valid while mutating the underlying
567 // structure. So, to make the code less brittle, we now collect the children into a vector before
568 // deleting them.
569 //
570 // Also note that the code here assumes that the child was dynamically allocated. If not, the
571 // child must be taken out of the children list before the parent is destructed.
572 //
573 auto c = vector<TWindow*>{};
574 for (auto& w : GetChildren())
575 c.push_back(&w);
576 for (auto w : c)
577 try
578 {
579 w->Destroy();
580 delete w;
581 }
582 catch (...)
583 {
584 TRACEX(OwlWin, 0, _T("~TWindow: Swallowed exception while destroying child: ") << *w);
585 }
586
587 // If the handle is still around, and this is not an alias, then destroy the window.
588 //
589 if (GetHandle() && !IsFlagSet(wfAlias))
590 {
591 WARNX(OwlWin, GetHandle(), 0, _T("Destroying from TWindow::~TWindow: ") << *this);
592 try { Destroy(); }
593 catch (...)
594 {
595 TRACEX(OwlWin, 0, _T("~TWindow: Swallowed exception while destroying this: ") << *this);
596 }
597 }
598
599 // Remove external references to this.
600 //
601 if (Parent)
602 Parent->RemoveChild(this);
603 if (Application)
604 Application->Uncondemn(this);
605
606 // Deallocate resources.
607 //
608 SetCaption(nullptr);
609 SetCursor(nullptr, TResId{0});
610 SetScroller(nullptr);
611 delete ContextPopupMenu;
612 if (Attr.Menu.IsString())
613 delete[] Attr.Menu.GetString();
614
615 TRACEX(OwlWin, 1, _T("TWindow destructed @") << (void*)this << *this);
616}
617
618#if defined(BI_MULTI_THREAD_RTL)
619//
620/// Cracks and dispatches a TWindow message. The info parameter is the
621/// event-handling function. The wp and lp parameters are the message parameters the
622/// dispatcher cracks.
623/// \note Overrides TEventHandler::Dispatch() to handle multi-thread synchronization
624//
626{
627 TApplication::TQueueLock lock(*GetApplication());
629}
630
631#endif
632
633//
634/// Called from TApplication::ProcessAppMsg() to give the window an
635/// opportunity to perform preprocessing of the Windows message
636///
637/// If you return true, further processing of the message is halted
638///
639/// Allows preprocessing of queued messages prior to dispatching. If you override
640/// this method in a derived class, be sure to call the base class's PreProcessMsg
641/// because it handles the translation of accelerator keys.
642//
643bool
645{
647
648 // Check if this message might be worth relaying to the tooltip window
649 //
651 if (tooltip && tooltip->IsWindow()) {
652 if (msg.hwnd == *this || IsChild(msg.hwnd)) {
653 if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) {
654 tooltip->RelayEvent(msg);
655 }
656 }
657 }
658
659 return HAccel ? ::TranslateAccelerator(GetHandle(), HAccel, &msg) : false;
660}
661
662//
663/// Called when no messages are waiting to be processed, IdleAction performs idle
664/// processing as long as true is returned. idleCount specifies the number of times
665/// idleAction has been called between messages.
666///
667/// Propagate idle action to all children if count==0, and to any children that
668/// previously said they wanted more time.
669//
670bool
672{
673 bool wantMore = false;
674 TWindow* win = GetFirstChild();
675 if (win) {
676 do {
677 if (idleCount == 0 || win->IsFlagSet(wfPropagateIdle)) {
678 if (win->IdleAction(idleCount)) {
680 wantMore = true;
681 }
682 else {
684 }
685 }
686 win = win->Next();
687 } while (win && win != GetFirstChild());
688 }
689 return wantMore;
690}
691
693/// Respond to WM_SYSCOLORCHANGE by broadcasting it to all children
694//
695void
701
702//
703/// Removes a child window. Uses the ObjectWindows list of objects rather the
704/// Window's HWND list.
705//
706void
708{
709 if (child && ChildList) {
710 TWindow* lastChild = ChildList;
712
713 while (nextChild->SiblingList != lastChild &&
714 nextChild->SiblingList != child) {
715 nextChild = nextChild->SiblingList;
716 }
717
718 if (nextChild->SiblingList == child) {
719 if (nextChild->SiblingList == nextChild)
720 ChildList = nullptr;
721
722 else {
723 if (nextChild->SiblingList == ChildList)
724 ChildList = nextChild;
725
726 nextChild->SiblingList = nextChild->SiblingList->SiblingList;
727 }
728 }
729 }
730}
731
732//
733/// Sets the parent for the specified window by setting Parent to the specified new
734/// Parent window object. Removes this window from the child list of the previous
735/// parent window, if any, and adds this window to the new parent's child list.
736//
737void
739{
740 if (Parent != newParent) {
741 if (Parent)
742 Parent->RemoveChild(this);
743
744 SiblingList = nullptr;
745
746 Parent = newParent;
747
748 if (Parent)
749 Parent->AddChild(this);
750 }
751 // Tell Windows about the change too, if appropriate
752 //
753 if (GetHandle() && Parent && GetParentH() != Parent->GetHandle()) {
754 if (newParent) {
755 if (newParent->GetHandle())
756 ::SetParent(GetHandle(), newParent->GetHandle());
757 }
758 else
759 ::SetParent(GetHandle(), nullptr);
760 }
761}
762
763//
764/// Default behavior for updating document title is to pass it to parent frame
765///
766/// Stores the title of the document (docname). index is the number of the view
767/// displayed in the document's caption bar. In order to determine what the view
768/// number should be, SetDocTitle makes two passes: the first pass checks to see if
769/// there's more than one view, and the second pass, if there is more than one view,
770/// assigns the next number to the view. If there is only one view, index is 0;
771/// therefore, the document does not display a view number. When TDocument is
772/// checking to see if more than one view exists, index is -1. In such cases, only
773/// the document's title is displayed in the caption bar.
774/// SetDocTitle returns true if there is more than one view and TDocument displays
775/// the number of the view passed in index.
776//
777bool
779{
780 return Parent ? Parent->SetDocTitle(docname, index) : false;
781}
782
783//
784/// Sets the scroller object for this window. This window assumes ownership of the
785/// scroller object, and will delete it when done and on subsequent sets.
786//
787void
789{
790 // This temporary variable is needed, because TScroller::~TScroller() calls TWindow::SetScroller(0)
791 TScroller* temp = Scroller;
792 Scroller = scroller;
793 delete temp;
794}
795
796//
797// Wildcard check used for child id notifications
798//
799static bool wildcardCheck(const TGenericTableEntry & entry, const TEventHandler::TEventInfo& info)
800{
801 return entry.Id == info.Id && (entry.Msg == UINT_MAX || entry.Msg == info.Msg);
802}
803
804//
805/// Handles default processing of events, which includes continued processing
806/// of menu/accelerators commands and enablers, as well as notifications
807//
808/// Serves as a general-purpose default processing function that handles a variety
809/// of messages. After being created and before calling DefaultProcessing, however,
810/// a window completes the following sequence of events (illustrated in the Default
811/// Message-Processing Flowchart).
812/// - If the window is already created, SubclassWindowFunction is used to
813/// install a thunk in place of the window's current procedure. The previous
814/// window procedure is saved in DefaultProc.
815/// - If the window has not been created, InitWndProc is set up as the
816/// window proc in the class. Then, when the window first receives a message,
817/// InitWndProc calls GetWindowProc to get the window's thunk (created by the
818/// constructor by calling CreateInstanceProc). InitWndProc then switches the
819/// the window procedure to the thunk.
820/// - After this point, the thunk responds to incoming messages by calling ReceiveMessage
821/// which calls the virtual function WindowProc to process the message. ObjectWindows uses
822/// the special registered message GetWindowPtrMsgId to get the this-pointer of an HWND.
823/// ReceiveMessage responds to this message by returning the this pointer obtained
824/// from the thunk.
825///
826/// If the incoming message is not a command or command enable message, WindowProc
827/// immediately searches the window's response table for a matching entry. If the
828/// incoming message is a command or command enable message, WindowProc calls
829/// EvCommand or EvCommandEnable. EvCommand and EvCommandEnable begin searching for
830/// a matching entry in the focus window's response table. If an entry is found, the
831/// corresponding function is dispatched; otherwise ObjectWindows calls
832/// DefaultProcessing to finish the recursive walk back up the parent chain,
833/// searching for a match until the receiving window (the window that initially
834/// received the message) is reached. At this point, one of the following actions
835/// occurs:
836/// - If there is still no match and this is the MainWindow of the
837/// application, the window searches the application's response table.
838/// - If there are no matches and this is a command, DefWindowProc is
839/// called.
840/// - If this is a CommandEnable message, no further action is taken.
841/// - If this is not a command, and if a response table entry exists for
842/// the window, WindowProc dispatches the corresponding EvXxxx function to handle
843/// the message.
844/// - If this is the application's MainWindow, and the message is
845/// designed for the application, the message is forwarded to the application.
846/// - For any other cases, the window calls DefWindowProc.
847///
848/// The following diagram illustrates this sequence of message-processing events:
849/// \image html bm282.BMP
850//
853{
855
856 if (currentEvent.Message == WM_COMMAND_ENABLE) {
857 if (currentEvent.Win != this) {
858 TWindow* receiver = Parent ? Parent : currentEvent.Win;
859 TCommandEnabler& commandEnabler = *reinterpret_cast<TCommandEnabler*>(currentEvent.Param2);
861
862 if (receiver->Find(eventInfo))
863 return receiver->Dispatch(eventInfo, 0, currentEvent.Param2);
864 }
865
866 return 0;
867 }
868
869 // Handle normal message default processing by routing directly to the
870 // virtual DefWindowProc() for the window.
871 //
872 if (currentEvent.Message != WM_COMMAND && currentEvent.Message != WM_NOTIFY)
873 return DefWindowProc(currentEvent.Message,
874 currentEvent.Param1,
875 currentEvent.Param2);
876
877 // currentEvent.Message == WM_COMMAND or WM_NOTIFY
878 //
880 uint id;
882
883 // Get notify code, control id and control handle from packed params.
884 // Unpacking based on message & platform.
885 //
886 if (currentEvent.Message == WM_COMMAND) {
888 id = LoUint16(currentEvent.Param1);
889 hWndCtl = reinterpret_cast<HWND>(currentEvent.Param2);
890 }
891 else {
892 TNotify& _not = *reinterpret_cast<TNotify*>(currentEvent.Param2);
893 notifyCode = _not.code;
894 id = static_cast<uint>(_not.idFrom); //currentEvent.Param1; // Y.B. In help written -> use not.idFrom.
895 if (_not.code == static_cast<uint>(TTN_NEEDTEXT) &&
896 (reinterpret_cast<TTooltipText*>(&_not))->uFlags&TTF_IDISHWND){
897 id = ::GetDlgCtrlID(reinterpret_cast<HWND>(_not.idFrom));
898 }
899 hWndCtl = _not.hwndFrom;
900 }
901
902 // If all special routing is done, then process the command/notify for this
903 // window
904 //
905 if (currentEvent.Win == this) {
906 // Menu command originally destined for the receiver, defer to the app.
907 //
908 if (hWndCtl == nullptr) {
909 TEventInfo eventInfo(0, id);
911
912 if (app->Find(eventInfo)) {
913 app->Dispatch(eventInfo, eventInfo.Id);
914 return 0;
915 }
916 WARNX(OwlMsg, notifyCode<=1, 0, _T("Unprocessed WM_COMMAND(id=") << id << _T(")"));
917 }
918 // Originally destined for the receiver and the receiver has called us so
919 // default processing can occur.
920 // Unpack the original parameters and call DefWindowProc()
921 //
922 return DefWindowProc(currentEvent.Message, currentEvent.Param1, currentEvent.Param2);
923 }
924
925 // Perform special routing for commands and notifications
926 //
927 else {
930
931 if (hWndCtl == nullptr) {
932 // Menu/accelerator/push button
933 // Either give the message to the receiver's parent or the original
934 // receiver of the message
935 //
936 receiver = Parent ? Parent : currentEvent.Win;
937
938 // "notifyCode" is either 0 or 1 depending on whether this is from an
939 // accelerator; however, we want to explicitly look for a 0...
940 //
941 notifyCode = 0;
942 }
943 else {
944 // Child id notification (either WM_COMMAND or WM_NOTIFY) sent to the
945 // child and the child has called us.
946 // Offer the parent an opportunity to handle the notification
947 // NOTE: use equal function that will do a wildcard search
948 //
949 equal = wildcardCheck;
951
952 // The child window identifier shouldn't be 0, but if it is then it will
953 // look like we are searching for a WM_ message with value "notifyCode",
954 // in that case just give up and call DefWindowProc() for the window.
955 //
956 if (receiver->IsFlagSet(wfAlias) || id == 0)
957 return receiver->DefWindowProc(currentEvent.Message,
958 currentEvent.Param1,
959 currentEvent.Param2);
960 }
961
962 // Now dispatch the command or notification to the receiver window
963 //
965
966 // NOTE: The ResponseTableEntry of handlers which expect an id (e.g.
967 // EV_COMMAND_AND_ID) have a zero in their first field. The
968 // ResponseTableEntry of handlers which expect a notification code
969 // (e.g. EV_CHILD_NOTIFY_AND_CODE and EV_NOTIFY_ALL_CODES) contain
970 // either the notifyCode or UINT_MAX in that field. Hence, we can
971 // dispatch the expected information based on the contents of that
972 // field.
973 //
974 // However, this logic will fail to disambiguate cases where a
975 // notification code is 0. The only standard control with such a
976 // notification is BUTTON /w BN_CLICKED. So for button handlers
977 // expecting the id, you can use EV_COMMAND_AND_ID. For handlers
978 // expecting the notification code, you can use EV_NOTIFY_ALL_CODES,
979 // (*NOT* EV_CHILD_NOTIFY_AND_CODE(Id, BN_CLICKED, xxxx,...))
980 //
981 if (receiver->Find(eventInfo, equal)) {
982 TParam1 param1 = eventInfo.Entry->NotifyCode ? notifyCode : id;
983 return receiver->Dispatch(eventInfo, param1, currentEvent.Param2);
984 }
985 else
986 return receiver->DefaultProcessing();
987 }
988}
989
990//
991/// WindowProc calls EvCommand to handle WM_COMMAND messages. id is the identifier
992/// of the menu item or control. hWndCtl holds a value that represents the control
993/// sending the message. If the message is not from a control, it is 0. notifyCode
994/// holds a value that represents the control's notification message. If the message
995/// is from an accelerator, notifyCode is 1; if the message is from a menu,
996/// notifyCode is 0.
997//
1000{
1001 TRACEX(OwlCmd, 1, _T("TWindow::EvCommand - id(") << id << _T("), ctl(") <<\
1002 hex << reinterpret_cast<void*>(hWndCtl) << _T("), code(") << notifyCode << _T(")"));
1003
1004 TWindow* receiver = this;
1006
1007 // Menu/accelerator
1008 //
1009 if (hWndCtl == nullptr) {
1010 // "notifyCode" is either 0 or 1 depending on whether this is from an
1011 // accelerator; however, we want to explicitly look for a 0 in the tables
1012 //
1013 notifyCode = 0;
1014 }
1015
1016 // Child id notification
1017 //
1018 else {
1020
1021 if (child) {
1022 // Give the child first crack at the event
1023 //
1024 receiver = child;
1025 id = UINT_MAX; // special designator for child Id notifications that are
1026 // handled at the child
1027 }
1028 else {
1029 // Offer the parent an opportunity to handle the notification
1030 //
1031 // NOTE: use equal function that will do a wildcard search
1032 //
1033 equal = wildcardCheck;
1034
1035 // The child window identifier shouldn't be 0, but if it is then it will
1036 // look like we are searching for a WM_ message with value "notifyCode"
1037 //
1038 if (id == 0)
1039 return DefaultProcessing();
1040 }
1041 }
1042
1044
1045 // NOTE: The ResponseTableEntry of handlers which expect an id
1046 // (e.g. EV_COMMAND_AND_ID) have a zero in their first field.
1047 // The ResponseTableEntry of handlers which expect a notification
1048 // code (e.g. EV_CHILD_NOTIFY_AND_CODE and EV_NOTIFY_ALL_CODES)
1049 // contain either the notifyCode or UINT_MAX in that field.
1050 // Hence, we can dispatch the expected information based on the
1051 // contents of that field.
1052 //
1053 // However, this logic will fail to disambiguate cases where
1054 // a notification code is 0. The only standard control with
1055 // such a notification is BUTTON /w BN_CLICKED. So for button
1056 // handlers expecting the id, you can use EV_COMMAND_AND_ID.
1057 // For handlers expecting the notification code, you can use
1058 // EV_NOTIFY_ALL_CODES.
1059 //
1060 // Do *NOT* use "EV_CHILD_NOTIFY_AND_CODE(Id, BN_CLICKED, xxxx,...)"
1061 //
1062 if (receiver->Find(eventInfo, equal))
1063 return receiver->Dispatch(eventInfo,
1064 eventInfo.Entry->NotifyCode ? notifyCode : id);
1065 else
1066 return receiver->DefaultProcessing();
1067}
1068
1069//
1070/// Handles WM_NOTIFY and subdispatch messages from child controls. This is the
1071/// default message handler for WM_NOTIFY.
1072// !CQ NOTE: similarity between EvCommand child notifies--merge?
1073//
1074TResult
1076{
1077 // Intercept requests for tooltip texts and turn the request into
1078 // a command enabler. This mechanism allows us to route the request
1079 // the same way commands are routed in OWL. Therefore, the object that
1080 // handles a command is the object that gets first crack at providing
1081 // the tip text for that command.
1082 //
1083 if (notifyInfo.code == TTN_NEEDTEXT)
1084 {
1085 auto& ttText = reinterpret_cast<TTooltipText&>(notifyInfo);
1086 auto enabler = TTooltipEnabler{ttText, GetHandle()};
1087 const auto cmdTarget = GetParent() ? GetParent() : this;
1088 RouteCommandEnable(cmdTarget->GetHandle(), enabler);
1089 const auto handled = enabler.GetHandled();
1090 WARNX(OwlWin, !handled, 1, _T("No command enabler found for TTN_NEEDTEXT (Id: ") << enabler.GetId() << _T(")."));
1091 if (handled)
1092 return 0;
1093 }
1094
1095 TWindow* receiver = this;
1097 TWindow* child = GetWindowPtr(notifyInfo.hwndFrom);
1098
1099 if (child) {
1100 // Give the Owl child first crack at the event
1101 //
1102 receiver = child;
1103 ctlId = UINT_MAX;// special designator for child Id notifications that are
1104 // handled at the child // !CQ may need a different value
1105 }
1106 else {
1107 // Offer the parent an opportunity to handle the notification
1108 // NOTE: use equal function that will do a wildcard search
1109 //
1110 equal = wildcardCheck;
1111
1112 // The child window identifier shouldn't be 0, but if it is then it will
1113 // look like we are searching for a WM_ message with value "notifyCode"
1114 //
1115 if (ctlId == 0)
1116 return DefaultProcessing();
1117 }
1118
1120
1121 // Pass the "notifyCode" along in case the user wants it...
1122 //
1123 if (receiver->Find(eventInfo, equal))
1124 return receiver->Dispatch(eventInfo, notifyInfo.code, TParam2(&notifyInfo));
1125 else
1126 return receiver->DefaultProcessing();
1127}
1128
1129//
1130/// Called by WindowProc to handle WM_COMMAND_ENABLE messages, EvCommandEnable calls
1131/// the CmXxxx command-handling function or calls DefaultProcessing to handle the
1132/// incoming message.
1133//
1134void
1136{
1137
1138// code copied from old unix owl (JAM 04-16-01)
1139//DLN test replace of DispatchMsg for CC 5.1
1141 if (Find(eventInfo))
1143
1144// DispatchMsg(WM_COMMAND_ENABLE, commandEnabler.Id, 0, TParam2(&commandEnabler));
1145}
1146
1147//
1148/// Walks the chain of windows from the initial target window to this window. If it
1149/// finds a window to receive the message, RouteCommandEnable dispatches the command
1150/// enabler to that window. hInitCmdTarget is the handle to the initial command
1151/// target window, which can be focus window but does not need to be. ce is a
1152/// reference to the command enabler.
1153/// Other classes use this function to perform particular command enabling tasks:
1154/// For example, TFrameWindow calls RouteCommandEnable to perform the majority of
1155/// its menu command enabling tasks. When it is an embedded window, TOleWindow also
1156/// uses RouteCommandEnable to perform command enabling.
1157///
1158/// Don't process for windows out of our window tree (esp. other apps)
1159//
1160void
1162{
1163 // Extra processing for commands & commandEnablers: send the command down the
1164 // command chain if we are the original receiver
1165 //
1166 if (commandEnabler.IsReceiver(*this)) {
1168 while (hCmdTarget && hCmdTarget != *this) {
1170
1171 if (cmdTarget) {
1172 cmdTarget->EvCommandEnable(commandEnabler);
1173
1174 if (commandEnabler.GetHandled())
1175 return;
1176 }
1178 }
1179 }
1180
1181 // Always call base handler
1182 //
1184
1185 // No one explicitly enabled/disabled the command via the enabler, so run up
1186 // the command chain checking for any one who is going to handle the command
1187 // itself; if not then disable it...
1188 // Don't do this for command senders that don't actually generate commands,
1189 // like popup menu items.
1190 //
1191 if (commandEnabler.IsReceiver(*this) && !commandEnabler.GetHandled()
1192 && commandEnabler.SendsCommand()) {
1193 bool enable = false;
1195
1197 while (true) {
1199
1200 if (cmdTarget && cmdTarget->Find(eventInfo)) {
1201 enable = true; // command will be handled, leave sender alone
1202 break;
1203 }
1204 if (!hCmdTarget || hCmdTarget == *this)
1205 break;
1206
1208 }
1209
1210 if (!enable) {
1211 // Check if the app wants to handle it
1212 //
1215 if (app->Find(enableInfo)) {
1216 app->Dispatch(enableInfo, 0, TParam2(&commandEnabler));
1217 if (commandEnabler.GetHandled())
1218 return;
1219 }
1220 enable = app->Find(eventInfo);
1221 }
1222
1223 commandEnabler.Enable(enable);
1224 }
1225}
1226
1227//
1228/// Virtual function provides final default processing for an incoming message
1229/// Calls original window proc that was subclassed, using ::CallWindowProc to
1230/// make sure that registers get setup correctly.
1231//
1232/// Performs default Windows processing and passes the incoming Windows message. You
1233/// usually do not need to call this function directly. Classes such as TMDIFrame
1234/// and TMDIChild override this function to perform specialized default processing.
1235
1236TResult
1238{
1239 PRECONDITION(DefaultProc);
1240
1241 bool priorException = Application && Application->HasSuspendedException();
1242 TResult result = ::CallWindowProc(DefaultProc, GetHandle(), message, param1, param2);
1243 if (!priorException) // Don't rethrow exceptions if we are in a clean-up phase.
1245 return result;
1246}
1247
1248//namespace owl {
1249
1250/// \addtogroup internal
1251/// @{
1252
1253
1254//
1255// Message cache
1256//
1257static const int msgCacheSize = 31;
1258struct TCacheEntry{
1259 typedef UINT_PTR TId;
1260 TId UniqueId;
1261 const TGenericTableEntry* Entry;
1262 TMsgId Msg;
1263 int Delta; // adjustment to "this" pointer
1264
1265 //30.05.2007 - Submitted by Frank Rast: Initialization of TCacheEntry data members was missing.
1266 TCacheEntry() : UniqueId(0), Entry(nullptr), Msg(0), Delta(0) {}
1267
1268 void Set(TId uniqueId, TMsgId msg, const TGenericTableEntry* entry, int delta = 0) {
1269 UniqueId = uniqueId;
1270 Entry = entry;
1271 Msg = msg;
1272 Delta = delta;
1273 }
1274 bool Hit(TMsgId msg, TId uniqueId) {return msg == Msg && uniqueId == UniqueId;}
1275
1276 static int Key(TId id, TMsgId msg) {return (id ^ static_cast<TId>(msg)) % msgCacheSize;}
1277};
1278
1279
1280struct TCacheEntryStr
1282: public TLocalObject
1283#endif
1284{
1285 TCacheEntryStr():Enabled(true)
1286 {
1287 }
1288 ~TCacheEntryStr()
1289 {
1290 }
1291
1292 TCacheEntry Cache[msgCacheSize];
1293 bool Enabled;
1294
1295 void CacheFlush(TCacheEntry::TId id);
1296 void Set(int index, TCacheEntry::TId uniqueId, TMsgId, const TGenericTableEntry* entry, int delta = 0);
1297 bool Check(int index, TMsgId, TCacheEntry::TId id);
1298
1299#if defined(BI_MULTI_THREAD_RTL)
1300// TMRSWSection Lock;
1301#endif
1302};
1303
1304TCacheEntry::TId TWindow::LastUniqueId = 0;
1305
1306static TCacheEntryStr& GetCache()
1307{
1308#if defined(BI_MULTI_THREAD_RTL)
1310 return cacheEntry.Get();
1311#else
1312 static TCacheEntryStr cacheEntry;
1313 return cacheEntry;
1314#endif
1315};
1316
1317namespace
1318{
1319 //
1320 // Ensure singleton initialization at start-up (single-threaded, safe).
1321 //
1322 TCacheEntryStr& InitCacheEntryStr = GetCache();
1323}
1324
1325#if defined(BI_MULTI_THREAD_RTL)
1326#define LOCKCACHE //TMRSWSection::TLock Lock(GetCache().Lock);
1327#else
1328#define LOCKCACHE
1329#endif
1330//
1332{
1333 LOCKCACHE
1334 for (int i = 0; i < msgCacheSize; i++)
1335 if (Cache[i].UniqueId == id)
1336 Cache[i].Msg = 0;
1337}
1338//
1340{
1341 LOCKCACHE
1342 Cache[index].Set(uniqueId, msg, entry, delta);
1343}
1344//
1346{
1347 LOCKCACHE
1348 return Enabled && Cache[index].Hit(msg, id);
1349}
1350
1351namespace
1352{
1353
1354//
1355void CacheFlush(UINT_PTR id)
1356{
1357 GetCache().CacheFlush(id);
1358}
1359
1360}
1361
1362/// @}
1363
1364//
1365// If rtti is available, then use it get an id for this window that is unique
1366// on a per-class basis.
1367//
1368// Without rtti, use a per-instance unique id. Less efficient, but safe.
1369//
1370void
1371TWindow::SetUniqueId()
1372{
1373#if defined(OWL_RTTI_MSGCACHE)
1374 UniqueId = 0;
1375#else
1376 if (++LastUniqueId == 0) {
1377 //
1378 // numbers wrapped around. disable the cache to be safe...
1379 //
1380 LastUniqueId = 1;
1381 GetCache().Enabled = false;
1382 }
1383 UniqueId = LastUniqueId;
1384#endif
1385}
1386
1387//
1388/// Dispatches the given message using the response table. Similar to SendMessage
1389/// but goes directly to the OWL window, bypassing the Windows message queue.
1390//
1391TResult
1393{
1394 // ReceiveMessage suspends any exception, so we need to rethrow it after the call.
1395 //
1396 TResult r = ReceiveMessage(Handle, msg, p1, p2);
1398 return r;
1399}
1400
1401//
1402/// First virtual function called to handling incoming messages to a TWindow
1403//
1404/// Processes incoming messages by calling EvCommand to handle WM_COMMAND messages,
1405/// EvCommandEnable to handle WM_COMMAND_ENABLE messages, and dispatching for all
1406/// other messages.
1407//
1408TResult
1410{
1411 PRECONDITION(GetHandle()); // Should never get here without a handle
1412
1413 // Handle WM_COMMAND_ENABLE command enable msgs by directly calling the
1414 // virtual EvCommandEnable
1415 //
1416 if (msg == WM_COMMAND_ENABLE) {
1417 TRACEX(OwlMsg, 1, _T("WM_COMMAND_ENABLE") << _T("! => ") << *this);
1418 EvCommandEnable(*reinterpret_cast<TCommandEnabler*>(param2));
1419 return 0;
1420 }
1421 // Handle WM_COMMAND command msgs by directly calling the
1422 // virtual EvCommand
1423 //
1424 else if (msg == WM_COMMAND) {
1425 TRACEX(OwlMsg, 1, _T("WM_COMMAND, ") << LoUint16(param1) << _T(" ! => ") << *this);
1426 return EvCommand(LoUint16(param1), reinterpret_cast<HWND>(param2), HiUint16(param1));
1427 }
1428 // Handle WM_NOTIFY msgs by directly calling the virtual EvNotify
1429 // !CQ why not use response table dispatch? For above too?
1430 //
1431 else if (msg == WM_NOTIFY) {
1432
1433 // We've received reports of some controls (out there) sending
1434 // WM_NOTIFY with a NULL LPARAM !!
1435 //
1437 //DLN SET ID to 0 for these NULL LPARAM to avoid bad resource access
1438 dumbNMHDR.idFrom = static_cast<UINT>(-1);
1439 TNotify* notify = param2 ? reinterpret_cast<TNotify*>(param2) : &dumbNMHDR;
1440
1441 TRACEX(OwlMsg, 1, _T("WM_NOTIFY, ") << notify->idFrom << _T(", ")\
1442 << notify->code << _T(", ")\
1443 << hex << reinterpret_cast<void*>(notify->hwndFrom) << _T(", ")\
1444 << _T(" ! => ") << *this);
1445 return EvNotify(static_cast<uint>(param1), *notify);
1446 }
1447
1448 // Handle all other messages by looking up and dispatching using the
1449 // response tables
1450 //
1451 else {
1452#if defined(OWL_RTTI_MSGCACHE)
1453 if (!UniqueId)
1454 UniqueId = TYPE_UNIQUE_ID(*this);
1455#endif
1456 int key = TCacheEntry::Key(UniqueId, msg);
1458
1459 // Check the cache. A cache hit may be an RT handler, or an RT miss.
1460 //
1461 TCacheEntryStr& cache = GetCache();
1462 if(cache.Check(key, msg, UniqueId)) {
1463 eventInfo.Entry = cache.Cache[key].Entry;
1464 if (eventInfo.Entry) {
1465 TRACEX(OwlMsg, 1, TMsgName(msg) << _T("* => ") << *this);
1466 eventInfo.Object = reinterpret_cast<TGeneric*>(((reinterpret_cast<char*>(this)) + cache.Cache[key].Delta));
1467 return Dispatch(eventInfo, param1, param2);
1468
1469 } // else fall out & do default below
1470 }
1471 // Perform the lookup on this window.
1472 //
1473 else if (this->Find(eventInfo)) {
1474 TRACEX(OwlMsg, 1, TMsgName(msg) << _T(" => ") << *this);
1475 const int delta = static_cast<int>(reinterpret_cast<INT_PTR>(eventInfo.Object) - reinterpret_cast<INT_PTR>(this));
1476 cache.Set(key,UniqueId, msg, eventInfo.Entry, delta);
1477 return Dispatch(eventInfo, param1, param2);
1478 }
1479 else // not found
1480 cache.Set(key,UniqueId, msg, nullptr); // Cache no-handler entries too
1481
1482 // Behavior for messages that have no handler. If this is the main window,
1483 // then give the app a chance to handle the message. If not the main
1484 // window, or if the app had no handler, just call DefWindowProc() to
1485 // pass the message back to whomever we subclassed
1486 //
1487 if (IsFlagSet(wfMainWindow)) {
1488 TEventInfo cmdEventInfo(msg, static_cast<uint>(param1));
1493 }
1494 return DefWindowProc(msg, param1, param2);
1495 }
1496}
1497
1498#if !defined(BI_COMP_GNUC)
1499#pragma warn -par
1500#endif
1501
1502//
1503/// Handles messages sent to the window.
1504/// May be called directly by the windows message dispatch mechanism,
1505/// or manually via HandleMessage.
1506/// If the message is a GetWindowPtr message, it is handled immediately,
1507/// otherwise the current event is saved and the call forwarded to WindowProc.
1508/// Any unhandled exception in WindowProc is suspended (see TApplication::SuspendThrow).
1509//
1510TResult
1511TWindow::ReceiveMessage(HWND hwnd, TMsgId msg, TParam1 param1, TParam2 param2) noexcept
1512{
1513 WARNX(OwlWin, hwnd != Handle, 0, "ReceiveMessage: The passed handle does not match this window.");
1514 InUse(hwnd);
1515
1516 // If it's a "GetWindowPtr" message, then return pointer to this window
1517 //
1518 if (msg == GetWindowPtrMsgId && (!param2 || param2 == TParam2(Application)))
1519 return TResult(this);
1520
1521 // Save event away in "CurrentEvent"
1522 //
1523 TCurrentEvent& currentEvent = GetCurrentEvent();
1524 TCurrentEvent saveEvent = currentEvent; // for nested calls
1525 currentEvent.Win = this;
1526 currentEvent.Message = msg;
1527 currentEvent.Param1 = param1;
1528 currentEvent.Param2 = param2;
1529
1530 // Call window object's WindowProc virtual function
1531 //
1532 TResult result = 0;
1533 try
1534 {
1535 result = WindowProc(msg, param1, param2);
1536 }
1537 catch (...)
1538 {
1539 TRACEX(OwlWin, 0, _T("TWindow::ReceiveMessage: Suspending unhandled exception for message: ") << msg);
1540
1541 GetApplication()->SuspendThrow(std::current_exception());
1542 }
1543 currentEvent = saveEvent; // restore previous event to current event
1544 return result;
1545}
1546
1547#if !defined(BI_COMP_GNUC)
1548#pragma warn .par
1549#endif
1550
1551//
1552/// Determine the object pointer by sending a GetWindowPtrMsgId message to the window.
1553/// When TWindow::ReceiveMessage receives this message it returns a pointer to the object.
1554/// If app is non-zero, then the process makes sure that the corresponding
1555/// TWindow is returned.
1556//
1558{
1559 if (!hWnd /* && ::IsWindow(hWnd) */) // Could also check handle validity
1560 return nullptr;
1561
1563
1564 // Avoid SendMessage to cutdown the overhead & message spy tool flooding
1565 //
1566 // Under Win32 don't even try if it is not our process. Some Win32's will
1567 // return a wndProc that crashes.
1568 //
1572 return nullptr;
1573
1574 WNDPROC wndProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC));
1575 if (!wndProc)
1576 return nullptr;
1577 return reinterpret_cast<TWindow*>(::CallWindowProc(wndProc, hWnd, GetWindowPtrMsgId, 0, param2));
1578}
1579
1580//
1581/// Response method for an incoming WM_CREATE message
1582///
1583/// Performs setup and data transfer now that we are created & have a Handle.
1584/// Should return true if the
1585//
1586bool
1588{
1589 PerformSetupAndTransfer(); // TODO: Add exception handling and return false on exceptions.
1591 return r == 0;
1592}
1593
1594//
1595/// Responds to a request by a child window to hold its HWND when it is losing
1596/// focus. Stores the child's HWND in HoldFocusHwnd.
1597//
1598/// \note Regular windows never hold focus child handles--just say no.
1599//
1600bool
1601TWindow::HoldFocusHWnd(HWND /*hWndLose*/, HWND /*hWndGain*/)
1602{
1603 return false;
1604}
1605
1606//
1607/// Handle WM_KILLFOCUS so that we can have a parent window hold onto our
1608/// Handle and possibly restore focus later.
1609//
1610void
1612{
1613 // Follow the parent chain back until a window volunteers to hold our handle
1614 //
1616 TWindow* holdWin = Parent;
1617 while (holdWin && !holdWin->HoldFocusHWnd(GetHandle(), getFocus))
1618 holdWin = holdWin->Parent;
1619 }
1620
1622}
1623
1624//
1625/// Response method for an incoming WM_SIZE message
1626///
1627/// Saves the normal size of the window in Attr.
1628/// Also calls the SetPageSize() and SetBarRange() methods of the TWindow's
1629/// scroller, if it has been constructed.
1630//
1631void
1633{
1635 static bool inScroller = false;
1636 if (!inScroller && Scroller && sizeType != SIZE_MINIMIZED) {
1637 inScroller = true;
1638 Scroller->SetPageSize();
1639 Scroller->SetSBarRange();
1640 inScroller = false;
1641 }
1642
1643 if (sizeType == SIZE_RESTORED) {
1644 TRect wndRect;
1646
1647 Attr.W = wndRect.Width();
1648 Attr.H = wndRect.Height();
1649 }
1650
1651 // Added Owl functionality: notify parent of a resize in case it wants to
1652 // adjust accordingly
1653 //
1654 if (Parent && !(GetExStyle() & WS_EX_NOPARENTNOTIFY))
1656
1658}
1659
1660//
1661/// Save the normal position of the window.
1662/// If IsIconic() or IsZoomed() ignore the position since it does not reflect
1663/// the normal state
1664//
1665void
1667{
1668 if (!IsIconic() && !IsZoomed()) {
1669 TRect wndRect;
1670
1672
1673 if ((GetWindowLong(GWL_STYLE) & WS_CHILD) == WS_CHILD && Parent &&
1674 Parent->GetHandle())
1675 Parent->ScreenToClient(wndRect.TopLeft());
1676
1677 Attr.X = wndRect.left;
1678 Attr.Y = wndRect.top;
1679 }
1680
1682}
1683
1684//
1685/// Handles WM_COMPAREITEM message (for owner draw controls) by forwarding
1686/// message to control itself
1687//
1688int
1690{
1691 TWindow* w = GetWindowPtr(compareInfo.hwndItem);
1692 TResult r = w ? w->ForwardMessage() : DefaultProcessing();
1693 return static_cast<int>(r);
1694}
1695
1696//
1697/// Handles WM_DELETEITEM message (for owner draw controls) by forwarding
1698/// message to control itself
1699//
1700void
1702{
1703 TWindow* win = GetWindowPtr(deleteInfo.hwndItem);
1704 if (deleteInfo.hwndItem != GetHandle() && win)
1705 win->ForwardMessage();
1706 else
1708}
1709//
1710/// Handles WM_DRAWITEM message (for owner draw controls & menus) by forwarding
1711/// message to control itself
1712//
1714void
1716{
1717 if (drawInfo.CtlType == ODT_MENU) {
1718 TDrawItem* item = ItemData2DrawItem(drawInfo.itemData);
1719 if(item){
1720 DRAWITEMSTRUCT i(drawInfo); // Create copy to support legacy non-const virtual TDrawItem::Draw.
1721 item->Draw(i);
1722 return;
1723 }
1724 }
1725 else {
1726 TWindow* win = GetWindowPtr(drawInfo.hwndItem);
1727 if (drawInfo.hwndItem != GetHandle() && win) {
1728 win->ForwardMessage();
1729 return;
1730 }
1731 }
1733}
1734
1735//
1736/// Handles WM_MEASUREITEM message (for owner draw controls & menus) by
1737/// forwarding message to control itself
1738//
1739void
1741{
1742 if (measureInfo.CtlType == ODT_MENU) {
1743 TDrawItem* item = ItemData2DrawItem(measureInfo.itemData);
1744 if(item){
1745 item->Measure(measureInfo);
1746 return;
1747 }
1748 }
1749 else {
1750 HWND hCtl = GetDlgItem(measureInfo.CtlID); // hWnd not in struct, get
1751 TWindow* win = GetWindowPtr(hCtl);
1752
1753 // If the GetWindowPtr failed, & CreationWindow is non-zero, then this
1754 // WM_MEASUREITEM is probably for the ctrl which is not yet subclassed.
1755 // Route the message directly to creation window.
1756 // NOTE: Msg. may be sent before OWL has had a chance to subclass the ctrl.
1757 //
1758 if (!win) {
1760 if (creationWindow) {
1761 if (creationWindow != this) // Don't cause a recursion loop
1762 win = creationWindow;
1763 }
1764 else
1765 win = ChildWithId(ctrlId);
1766 }
1767 if(win){
1768 // 970921 MILI 11 The first WM_MEASUREITEM message for a control may
1769 // be is sent before OWL has had any chance to grab the handle for that
1770 // control. In that case we use Find+Dispatch instead of SendMessage to
1771 // forward the message to the control.
1772 if(win->GetHandle()){
1773// !CQ Handle causes bad behavior on DefWindowProc of control in some cases
1774/// win->HandleMessage(WM_MEASUREITEM, ctrlId, TParam2(&measureInfo));
1775/// win->ForewardMessage();
1777 return;
1778 }
1779 else{
1781 if (win->Find(eventInfo)){
1783 return;
1784 }
1785 }
1786 }
1787 }
1789}
1790
1791//
1792/// Called by EvHScroll and EvVScroll to dispatch messages from scroll bars.
1793//
1794void
1796{
1797 if (hWndCtrl) {
1799 if (win)
1800 win->ForwardMessage();
1801
1802 // Adjust "CurrentEvent" to allow DefaultProcessing to work
1803 //
1804 uint16 id = static_cast<uint16>(::GetDlgCtrlID(hWndCtrl));
1806 currentEvent.Message = WM_COMMAND;
1807 currentEvent.Param1 = MkParam1(id, scrollCode);
1808 currentEvent.Param2 = TParam2(hWndCtrl);
1809
1811 return;
1812 }
1814}
1815
1816//
1817/// Event handler for WM_MOUSEHWHEEL.
1818/// Responds to horizontal mouse wheel event if Scroller exists.
1819//
1820void
1822{
1823 if (Scroller && !(modKeys & (MK_SHIFT | MK_CONTROL)))
1824 {
1825 const auto n = GetWheelScrollLines_();
1826 const auto dx = (n == WHEEL_PAGESCROLL) ?
1827 ((zDelta > 0) ? -Scroller->XPage : Scroller->XPage) :
1828 ::MulDiv(-zDelta, n, WHEEL_DELTA) * Scroller->XLine;
1829 Scroller->ScrollBy(dx, 0);
1830 }
1831 else
1833}
1834
1835//
1836/// Event handler for WM_MOUSEWHEEL.
1837/// Responds to vertical mouse wheel event if Scroller exists.
1838//
1839void
1841{
1842 if (Scroller && !(modKeys & (MK_SHIFT | MK_CONTROL)))
1843 {
1844 const auto n = GetWheelScrollLines_();
1845 const auto dy = (n == WHEEL_PAGESCROLL) ?
1846 ((zDelta > 0) ? -Scroller->YPage : Scroller->YPage) :
1847 ::MulDiv(-zDelta, n, WHEEL_DELTA) * Scroller->YLine;
1848 Scroller->ScrollBy(0, dy);
1849 }
1850 else
1852}
1853
1854//
1855/// Response method for an incoming WM_HSCROLL message
1856///
1857/// If the message is from a scrollbar control, calls DispatchScroll()
1858/// otherwise passes the message to the TWindow's scroller if it has been
1859/// constructed, else calls DefaultProcessing()
1860///
1861/// Assumes, because of a Windows bug, that if the window has the scrollbar
1862/// style, it will not have scrollbar controls
1863//
1864void
1866{
1867 if (!(GetWindowLong(GWL_STYLE) & WS_HSCROLL) && !Scroller)
1868 {
1869 DispatchScroll(scrollCode, thumbPos, hWndCtl); // from scrollbar control
1870 }
1871 else if (Scroller)
1872 {
1873 Scroller->HScroll(scrollCode, thumbPos);
1874 }
1875 else
1876 {
1878 }
1879}
1880
1881//
1882/// Response method for an incoming WM_VSCROLL message
1883///
1884/// If the message is from a scrollbar control, calls DispatchScroll()
1885/// otherwise passes the message to the TWindow's scroller if it has been
1886/// constructed, else calls DefaultProcessing()
1887///
1888/// Assumes, because of a Windows bug, that if the window has the scrollbar
1889/// style, it will not have scrollbar controls
1890//
1891void
1893{
1894 if (!(GetWindowLong(GWL_STYLE) & WS_VSCROLL) && !Scroller)
1896
1897 else if (Scroller)
1898 Scroller->VScroll(scrollCode, thumbPos);
1899
1900 else
1902}
1903
1904//
1905/// Handler for WM_ERASEBKGND.
1906///
1907/// If the background color (see TWindow::SetBkgndColor) is not set, or
1908/// it has been set to TColor::None, then this function simply forwards the
1909/// message to DefaultProcessing. The default processing uses the brush
1910/// specified in the window class (WNDCLASS:hbrBackground) to clear the client
1911/// area. If the background color is set to TColor::Transparent, no clearing is
1912/// done, and the function simply returns `true`. Otherwise, the current
1913/// background color is used to clear the client area, and `true` is returned,
1914/// indicating no further erasing is required.
1915///
1916/// If you want to handle erasure in your Paint override, then override this
1917/// handler and return false. Paint will then receive `true` in its `erase`
1918/// parameter, and you must ensure that all of the background is painted within
1919/// the invalidated region.
1920///
1921/// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648055.aspx
1922//
1923bool
1925{
1926 if (BkgndColor == TColor::None)
1927 return static_cast<bool>(DefaultProcessing()); // Use WNDCLASS::hbrBackground.
1928
1929 if (BkgndColor == TColor::Transparent)
1930 return true; // We want no erasing, please.
1931
1932 TDC(hDC).FillSolidRect(GetClientRect(), BkgndColor);
1933 return true;
1934}
1935
1936//
1937/// Handler for control color messages (WM_CTLCOLOR family).
1938///
1939/// If the passed control `ctl` is a child encapsulated by OWL, then the text and background color
1940/// of the control is used. If the control is not encapsulated by OWL, or the control does not
1941/// specify a color (TColor::None), then colors are assigned by the parent (dialog). If the parent
1942/// has no colors set, default colors will be used.
1943///
1944/// If the background color is set to TColor::Transparent, then the background mode of the device
1945/// context `hDC` is set to TRANSPARENT and NULL_BRUSH is returned. Otherwise a solid brush of the
1946/// background color is returned.
1947///
1948/// \note Parent colors will not override defaults for Edit and List Box controls. For these
1949/// control types, the colors can only be set by the controls themselves. To set the colors for an
1950/// Edit or List Box control, encapsulate the control using the corresponding OWL class, and call
1951/// SetTextColor and SetBkgndColor on the object. For other controls, such as the Static control,
1952/// the parent will set the control's colors to match the parent's colors, unless explicitly set by
1953/// the control itself. This ensures that a dialog box is drawn properly. For example, a dialog
1954/// with labels and fields is drawn with the parent's colors for the labels, but with the system
1955/// default colors for the fields, unless colors are explicitly set by the controls.
1956/// Also, setting colors for a Combo Box control has no effect, since this control uses subcontrols
1957/// for the Edit field and List Box components. Hence, combo boxes need to be treated specially by
1958/// the parent by handling WM_CTLCOLOREDIT and WM_CTLCOLORLISTBOX, and testing the passed `ctl`
1959/// window handle for a match against the subcontrols. To determine the handles of the subcontrols,
1960/// use TComboBox::GetEditHandle and TComboBox::GetListHandle (or TComboBox::GetInfo to get both).
1961/// These functions are encapsulations of the Windows API function GetComboBoxInfo.
1962///
1963/// \code{.cpp}
1964/// // TComboBox ComboBox;
1965///
1966/// DEFINE_RESPONSE_TABLE1(TMyDlg, TDialog)
1967/// //...
1968/// EV_WM_CTLCOLOREDIT(EvCtlColor),
1969/// EV_WM_CTLCOLORLISTBOX(EvCtlColor),
1970/// END_RESPONSE_TABLE;
1971///
1972/// auto TMyDlg::EvCtlColor(HDC hdc, HWND ctl, uint ctlType) -> HBRUSH
1973/// {
1974/// const auto i = ComboBox.GetInfo();
1975/// const auto w = (ctl == i.hwndItem || ctl == i.hwndList) ? ComboBox.GetHandle() : ctl;
1976/// return TWindow::EvCtlColor(hdc, w, ctlType);
1977/// }
1978/// \endcode
1979///
1980/// \sa SetBkgndColor, SetTextColor
1981//
1982HBRUSH
1984{
1985 // Start by letting the default processing handle the message. This ensures that we get the
1986 // system defaults for the attributes we do not override.
1987 //
1988 const auto defaultErasureBrush = reinterpret_cast<HBRUSH>(DefaultProcessing());
1989
1990 // Now we need to determine which colors to use. If we are handling colors for a child, i.e. the
1991 // ctlType is not CTLCOLOR_DLG, then we let the child specify the color. If the child is not
1992 // encapsulated by OWL, or does not specify a color, then we use our own color. If we do not have
1993 // a color, we use the system default (as provided by the default processing).
1994 //
1995 // Note: We leave the colors of Edit and Listbox controls alone, unless the control is
1996 // encapsulated by an OWL class and explicitly specifies a color (i.e. other than TColor::None).
1997 //
1998 const auto owlChild = (ctlType != CTLCOLOR_DLG) ? GetWindowPtr(ctl) : nullptr;
2000 const auto textColor = (owlChild && owlChild->GetTextColor() != TColor::None) ? owlChild->GetTextColor() :
2002 TextColor;
2003 const auto bkgndColor = (owlChild && owlChild->GetBkgndColor() != TColor::None) ? owlChild->GetBkgndColor() :
2005 BkgndColor;
2006
2007 // Override the control text color, if set.
2008 //
2009 if (textColor != TColor::None)
2010 {
2013 }
2014
2015 // Override the background color, if set, and return a corresponding erasure brush.
2016 //
2017 if (bkgndColor == TColor::None)
2018 {
2019 return defaultErasureBrush;
2020 }
2021 else if (bkgndColor == TColor::Transparent)
2022 {
2023 ::SetBkMode(hDC, TRANSPARENT);
2024 return reinterpret_cast<HBRUSH>(::GetStockObject(NULL_BRUSH));
2025 }
2026 else
2027 {
2028 ::SetBkColor(hDC, bkgndColor);
2029 return TBrush{bkgndColor}; // HBRUSH will stay in cache.
2030 }
2031}
2032
2033//
2034/// Response method for an incoming WM_PAINT message
2035///
2036/// Calls Paint(), performing Windows-required paint setup and cleanup before
2037/// and after. if the TWindow has a TScroller, also calls its BeginView() and
2038/// EndView() methods before and after call to Paint()
2039//
2040void
2042{
2043 if (IsFlagSet(wfAlias))
2044 DefaultProcessing(); // use application-defined wndproc
2045
2046 else {
2047 TPaintDC dc(*this);
2048 TRect& rect = *static_cast<TRect*>(&dc.Ps.rcPaint);
2049
2050 if (Scroller)
2051 Scroller->BeginView(dc, rect);
2052
2053 Paint(dc, dc.Ps.fErase, rect);
2054
2055 if (Scroller)
2056 Scroller->EndView();
2057 }
2058}
2059
2060//
2061/// Repaints the client area (the area you can use for drawing) of a window. Called
2062/// by base classes when responding to a WM_PAINT message, Paint serves as a
2063/// placeholder for derived types that define Paint member functions. Paint is
2064/// called by EvPaint and requested automatically by Windows to redisplay the
2065/// window's contents. dc is the paint display context supplied to text and graphics
2066/// output functions. The supplied reference to the rect structure is the bounding
2067/// rectangle of the area that requires painting. erase indicates whether the
2068/// background needs erasing.
2069//
2070void
2071TWindow::Paint(TDC&, bool /*erase*/, TRect&)
2072{
2073}
2074
2075//
2076/// Response method for an incoming WM_SETCURSOR message.
2077/// If a cursor has been set for this window using TWindow::SetCursor, and the mouse is over the
2078/// client area, the cursor is used. Otherwise, the cursor for the window class is used (default).
2079//
2080bool
2082{
2083 if (hWndCursor == GetHandle() && codeHitTest == HTCLIENT && HCursor) {
2084 ::SetCursor(HCursor);
2085 return true;
2086 }
2087 return static_cast<bool>(DefaultProcessing());
2088}
2089
2090//
2091/// Response method for an incoming WM_LBUTTONDOWN message
2092///
2093/// If the TWindow's Scroller has been constructed and if auto-scrolling
2094/// has been requested, captures mouse input, loops until a WM_LBUTTONUP
2095/// message comes in calling the Scroller's AutoScroll method, and then
2096/// releases capture on mouse input.
2097/// Will also break if a WM_MOUSEMOVE comes in without the left button down
2098/// indicating a lost WM_LBUTTONUP
2099//
2100void
2101TWindow::EvLButtonDown(uint /*modKeys*/, const TPoint& /*pt*/)
2102{
2103 if (Scroller && Scroller->IsAutoMode()) {
2104 MSG loopMsg;
2105
2106 loopMsg.message = 0;
2107 SetCapture();
2108
2109 while (loopMsg.message != WM_LBUTTONUP && Scroller->IsAutoMode() &&
2110 (loopMsg.message != WM_MOUSEMOVE || (loopMsg.wParam&MK_LBUTTON))) {
2111 if (::PeekMessage(&loopMsg, nullptr, 0, 0, PM_REMOVE)) {
2114
2115 // Rethrow any exception suspended in the handler, in which case we need to release
2116 // the mouse capture.
2117 //
2118 try
2119 {
2121 }
2122 catch (...)
2123 {
2125 throw;
2126 }
2127 }
2128 Scroller->AutoScroll();
2129 }
2131 }
2132
2134}
2135
2136//namespace owl {
2137//
2138//
2139//
2140void
2141DoEnableAutoCreate(TWindow* win, void* /*retVal*/)
2142{
2143 if (win->GetHandle())
2144 win->EnableAutoCreate();
2145}
2146
2147//} // OWL namespace
2148
2149//
2150/// Destroys an MS-Windows element associated with the TWindow.
2151//
2152/// First, Destroy calls EnableAutoCreate for each window in the child list to
2153/// ensure that windows in the child list will be re-created if this is re-created.
2154/// Then, it destroys the associated interface element.
2155/// If a derived window class expects to be destructed directly, it should call
2156/// Destroy as the first step in its destruction so that any virtual functions and
2157/// event handlers can be called during the destroy sequence.
2158//
2159void
2161{
2162 if (GetHandle())
2163 {
2164 for (auto& w : GetChildren())
2165 {
2166 if (w.GetHandle())
2167 w.EnableAutoCreate();
2168 }
2169
2170 if (IsFlagSet(wfModalWindow)) {
2173 if (Parent && Parent->GetHandle())
2174 Parent->SetFocus();
2175 }
2176
2177 if (!IsFlagSet(wfAlias)) {
2179 SetHandle(nullptr);
2180 }
2181
2183 WARNX(OwlWin, GetHandle(), 0, _T("::DestroyWindow(") << static_cast<void*>(GetHandle()) << _T(") failed"));
2184 }
2185}
2186
2187//
2188/// Redefined by derived classes, GetWindowClass fills the supplied MS-Windows
2189/// registration class structure with registration attributes, thus, allowing
2190/// instances of TWindow to be registered. This function, along with GetWindowClassName,
2191/// allows Windows classes to be used for the specified ObjectWindows class and its
2192/// derivatives. It sets the fields of the passed WNDCLASS parameter to the default
2193/// attributes appropriate for a TWindow. The fields and their default attributes
2194/// for the class are the following:
2195/// - \c \b cbClsExtra 0 (the number of extra bytes to reserve after the Window class
2196/// structure). This value is not used by ObjectWindows.
2197/// - \c \b cbWndExtra 0 (the number of extra bytes to reserve after the Window instance).
2198/// This value is not used by ObjectWindows.
2199/// - \c \b hInstance The instance of the class in which the window procedure exists
2200/// - \c \b hIcon 0 (Provides a handle to the class resource.) By default, the application
2201/// must create an icon if the application's window is minimized.
2202/// - \c \b hCursor IDC_ARROW (provides a handle to a cursor resource)
2203/// - \c \b hbrBackground COLOR_WINDOW + 1 (the system background color)
2204/// - \c \b lpszMenuName 0 (Points to a string that contains the name of the class's menu.)
2205/// By default, the windows in this class have no assigned menus.
2206/// - \c \b lpszClassName Points to a string that contains the name of the window class.
2207/// - \c \b lpfnWndProc The address of the window procedure. This value is not used by
2208/// ObjectWindows.
2209/// - \c \b style Style field.
2210///
2211/// The style field can contain one or more of the following values:
2212/// - \c \b CS_BYTEALIGNCLIENT Aligns the window's client on a byte boundary in the x
2213/// direction. This alignment, designed to improve performance, determines the width
2214/// and horizontal position of the window.
2215/// - \c \b CS_BYTEALIGNWINDOW Aligns a window on a byte boundary in the x direction. This
2216/// alignment, designed to improve performance, determines the width and horizontal
2217/// position of the window.
2218/// - \c \b CS_CLASSDC Allocates a single device context (DC) that's going to be shared by
2219/// all of the window in the class. This style controls how multi-threaded
2220/// applications that have windows belonging to the same class share the same DC.
2221/// - \c \b CS_DBLCLKS Sends a double-click mouse message to the window procedure when the
2222/// mouse is double-clicked on a window belonging to this class.
2223/// - \c \b CS_GLOBALCLASS Allows an application to create a window class regardless of the
2224/// instance parameter. You can also create a global class by writing a DLL that
2225/// contains the window class.
2226/// - \c \b CS_HREDRAW If the size of the window changes as a result of some movement or
2227/// resizing, redraws the entire window.
2228/// - \c \b CS_NOCLOSE Disables the Close option on this window's system menu.
2229/// - \c \b CS_OWNDC Enables each window in the class to have a different DC.
2230/// - \c \b CS_PARENTDC Passes the parent window's DC to the child windows.
2231/// - \c \b CS_SAVEBITS Saves the section of the screen as a bitmap if the screen is covered
2232/// by another window. This bitmap is later used to recreate the window when it is
2233/// no longer obscured by another window.
2234/// - \c \b CS_VREDRAW If the height of the client area is changed, redraws the entire
2235/// window.
2236///
2237/// After the Windows class structure has been filled with default values by the
2238/// base class, you can override this function to change the values of the Windows
2239/// class structure. For example, you might want to change the window's colors or
2240/// the cursor displayed.
2241///
2242/// Register unique classes for windows that want system background colors so
2243/// that full-drag erasing uses the right color (NT fails to let window erase
2244/// itself)
2245///
2246void
2248{
2249 wndClass.cbClsExtra = 0;
2250 wndClass.cbWndExtra = 0;
2251 wndClass.hInstance = *GetModule();
2252 wndClass.hIcon = nullptr;
2253 wndClass.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
2254
2255 if (BkgndColor.IsSysColor() &&
2256 BkgndColor != TColor::None && BkgndColor != TColor::Transparent)
2257 wndClass.hbrBackground = reinterpret_cast<HBRUSH>(static_cast<INT_PTR>(BkgndColor.Index() + 1));
2258 else
2259 wndClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
2260
2261 wndClass.lpszMenuName = nullptr;
2262 wndClass.lpszClassName = GetWindowClassName().GetPointerRepresentation();
2263 wndClass.style = CS_DBLCLKS;
2264 wndClass.lpfnWndProc = InitWndProc;
2265}
2266
2267//
2268// Return the classname for a generic owl window. Assume instance private class
2269// registration so that no instance mangling is needed.
2270//
2271// Register unique classnames for windows that want system background colors
2272//
2274 static const tchar baseClassName[] = _T("OWL_Window");
2275
2276 if (BkgndColor.IsSysColor() &&
2277 BkgndColor != TColor::None && BkgndColor != TColor::Transparent) {
2278 static tchar namebuff[COUNTOF(baseClassName) + 1 + 10 + 1 + 4]; // ?? How was this formula calculated
2279 _stprintf(namebuff, _T("%s:%X"), baseClassName, BkgndColor.Index());
2280 // !CQ could hash in classStyle too.
2281 return TWindowClassName{namebuff};
2282 }
2284}
2285
2286//
2287// Set this window's accelerator table, performing the load also if this window
2288// is already created
2289//
2290void
2292{
2293 Attr.AccelTable = resId;
2294 if (GetHandle())
2296 else
2297 HAccel = nullptr;
2298}
2299
2300//
2301/// Loads a handle to the window's accelerator table specified in the TWindowAttr
2302/// structure (Attr.AccelTable). If the accelerator does not exist,
2303/// LoadAcceleratorTable produces an "Unable to load accelerator table" diagnostic
2304/// message.
2305//
2306void
2308{
2309 if (Attr.AccelTable) {
2310 HAccel = LoadAccelerators(Attr.AccelTable);
2311 WARNX(OwlWin, !HAccel, 0,
2312 _T("Unable to load accelerators ") << Attr.AccelTable
2313 << _T(" from ") << *GetModule());
2314 }
2315}
2316
2317//
2318// Helper used by Create and PerformCreate to make a menu-or-id union parameter
2319// for CreateWindowEx; see Windows SDK documentation.
2320//
2321HMENU
2322TWindow::MakeMenuOrId()
2323{
2325
2326 HMENU m = Attr.Menu ? LoadMenu(Attr.Menu) : reinterpret_cast<HMENU>(static_cast<INT_PTR>(Attr.Id));
2327 WARNX(OwlWin, Attr.Menu && !m, 0,
2328 _T("Unable to load menu: ") << Attr.Menu << _T(" from ") << *GetModule());
2329 return m;
2330}
2331
2332
2333//
2334/// Called from Create to perform the final step in creating an Windows interface
2335/// element to be associated with a TWindow. PerformCreate can be overridden to
2336/// provide alternate implementations.
2337///
2338/// In strict mode we ignore the argument passed, and we build the menu-or-id
2339/// parameter to CreateWindowEx purely based on TWindow data members. In old
2340/// mode we treat the argument like before and assume that it is already a
2341/// composed menu-or-id union. In case it represents a menu, we take ownership
2342/// of the allocated menu (which should have been created by the caller).
2343//
2346{
2348 //
2349 // Use RAII to ensure the menu is released in case of failure.
2350 //
2351 struct TMenuGuard
2352 {
2353 HMENU m;
2354 bool is_mine;
2355
2357 ~TMenuGuard() {if (is_mine) DestroyMenu(m);}
2358 operator HMENU() {return m;}
2359 HMENU RelinquishOwnership() {is_mine = false; return m;}
2360 }
2361 menuOrId(MakeMenuOrId(), Attr.Menu != 0);
2363 Attr.ExStyle,
2364 GetWindowClassName().GetPointerRepresentation(),
2365 Title,
2366 Attr.Style,
2367 Attr.X, Attr.Y, Attr.W, Attr.H,
2368 Parent ? Parent->GetHandle() : nullptr,
2369 menuOrId,
2370 *GetModule(),
2371 Attr.Param
2372 );
2373 if (h) menuOrId.RelinquishOwnership(); // The menu belongs to the window now.
2374 return h;
2375}
2376
2377//
2378/// Creates the window interface element to be associated with this ObjectWindows
2379/// interface element. Specifically, Create performs the following window creation
2380/// tasks:
2381/// - 1. If the HWND already exists, Create returns true. (It is perfectly valid to
2382/// call Create even if the window currently exists.)
2383/// - 2. If the wfFromResource flag is set, then Create grabs the HWND based on the
2384/// window ID. Otherwise, Create registers the window, sets up the window thunk,
2385/// loads accelerators and menus, and calls PerformCreate in the derived class to
2386/// create the HWND.
2387/// - 3. If class registration fails for the window, Create calls TXWindow with
2388/// IDS_CLASSREGISTERFAIL. If the window creation fails, Create calls TXWindow with
2389/// IDS_WINDOWCREATEFAIL.
2390/// - 4. If the window is created for a predefined Window class (for example, a
2391/// button or dialog class) registered outside of ObjectWindows, then ObjectWindows
2392/// thunks the window so that it can intercept messages and obtains the state of the
2393/// window (the window's attributes) from the HWND.
2394///
2395/// \note Since this member function now throws an exception on error, it always
2396/// returns true.
2397//
2398bool
2400{
2401 if (GetHandle())
2402 return true;
2403
2405
2406 // If this is the main window, make sure it is treated as one by the shell.
2407 //
2410
2412 SetHandle(Parent ? Parent->GetDlgItem(Attr.Id) : nullptr); // Windows already created it.
2413 else
2414 {
2415 // Make sure the window class is registered.
2416 //
2417 if (!Register())
2419
2420 // Perform necessary steps to create the window and attach the window procedure.
2421 //
2422 SetCreationWindow(this);
2424 CHECK(!GetHandle()); // Ensure handle is NULL in case of exceptions.
2425
2426 // In the new API, PerformCreate takes no arguments.
2427 // Also PerformCreate now returns the handle instead of calling SetHandle.
2428 //
2431 }
2432 WARNX(OwlWin, !GetHandle(), 0, _T("TWindow::Create failed: ") << *this);
2433 if (!GetHandle())
2435
2436 // Here we deal with non-subclassed handles. This may be caused by two scenarios:
2437 //
2438 // 1. Predefined window class (non-owl) windows.
2439 // 2. OWL controls which were created from resource [Although these
2440 // are registered with InitWndProc, they did not get subclassed since
2441 // 'CreationWindow' was not set when they received their first messages].
2442 //
2443 if (!GetWindowPtr(GetHandle()))
2444 {
2445
2446 // If we have a title, then overwrite the current window text, if any.
2447 // Otherwise sync the title with the current window text.
2448 //
2449 if (Title)
2450 SetCaption(Title);
2451 else
2453
2454 // Grab the state info.
2455 //
2456 GetHWndState();
2457
2458 // If it's a 'predefinedClass' window, subclass it.
2459 //
2460 if (GetWindowProc() != InitWndProc)
2461 {
2463
2464 // Reset the 'CreationWindow' pointer [if necessary].
2465 //
2466 if (GetCreationWindow() == this)
2467 SetCreationWindow(nullptr);
2468
2469 // Set status flag [since we missed EvCreate].
2470 //
2472 }
2473 else
2474 {
2475 // This window's WNDPROC is 'InitWndProc' - However, it has not
2476 // been subclassed since 'CreationWindow' was not set when it received
2477 // its first messages [it was probably created from a resource but
2478 // registered by OWL]. We'll set 'CreationWindow' and send a dummy
2479 // message to allow subclassing to take place.
2480 //
2481 if (!GetCreationWindow())
2482 SetCreationWindow(this);
2483 SendMessage(WM_USER+0x4000, 0, 0);
2484 }
2485
2486 // Perform setup and transfer now, since 'EvCreate' was missed earlier.
2487 //
2489 }
2490 return true;
2491}
2492
2493//
2494/// Creates the underlying HWND and makes it modal with the help of TApplication's
2495/// BeginModal support.
2496//
2497int
2499{
2500 return DoExecute();
2501}
2502
2503//
2504/// Do actual modal execution using the Begin/End Modal support of TApplication.
2505/// \note Defaults to 'TASKMODAL'.
2506//
2507int
2509{
2510 // Attempting to go modal when one's a child is indicative of
2511 // suicidal tendencies!!
2512 //
2513 PRECONDITION((GetStyle() & WS_CHILD) == 0);
2514
2515 if (GetApplication()) {
2516 if (Create()) {
2518 return GetApplication()->BeginModal(this, MB_TASKMODAL);
2519 }
2520 }
2521 return -1;
2522}
2523
2524//
2525/// Ensures that the window is fully set up; then transfers data into the window.
2526//
2527void
2529{
2530 SetupWindow();
2532
2533 // Note that transfer has already happened in SetupWindow if the library is
2534 // built in backwards compatibility mode. See SetupWindow for details.
2535 //
2536#if !defined(OWL5_COMPAT)
2538#endif
2539}
2540
2541//
2542/// Performs setup following creation of an associated MS-Windows window.
2543///
2544/// The first virtual function called when the HWindow becomes valid. TWindow's
2545/// implementation performs window setup by iterating through the child list,
2546/// attempting to create an associated interface element for each child window
2547/// object for which autocreation is enabled. (By default, autocreation is enabled
2548/// for windows and controls, and disabled for dialog boxes.)
2549/// If a child window cannot be created, SetupWindow calls TXWindow
2550/// with an IDS_CHILDCREATEFAIL message.
2551///
2552/// If the receiver has a TScroller object, calls the scroller's SetBarRange()
2553/// method.
2554///
2555/// SetupWindow can be redefined in derived classes to perform additional special
2556/// initialization. Note that the HWindow is valid when the overridden SetupWindow
2557/// is called, and that the children's HWindows are valid after calling the base
2558/// classes' SetupWindow function.
2559///
2560/// The following example from the sample program, APPWIN.CPP, illustrates the use
2561/// of an overridden SetupWindow to setup a window, initialize .INI entries, and
2562/// tell Windows that we want to accept drag and drop transactions:
2563/// \code
2564/// void TAppWindow::SetupWindow()
2565/// {
2566/// TFloatingFrame::SetupWindow();
2567/// InitEntries(); // Initialize .INI entries.
2568/// RestoreFromINIFile(); // from APPLAUNC.INI in the startup directory
2569/// UpdateAppButtons();
2570/// DragAcceptFiles(true);
2571/// }
2572/// \endcode
2573//
2574void
2576{
2577 TRACEX(OwlWin, 1, _T("TWindow::SetupWindow() @") << (void*)this << *this);
2578
2579 // Update scrollbar - if a scroller was attached to the window
2580 //
2581 if (Scroller){
2582 Scroller->SetWindow(this);
2583 Scroller->SetSBarRange();
2584 }
2585
2586 // If this is main Window and GetAplication()->GetTooltip() != 0; create it.
2587 if (IsFlagSet(wfMainWindow)){
2589 if(tooltip){
2590 if(!tooltip->GetParentO())
2591 tooltip->SetParent(this);
2592 if(!tooltip->GetHandle()){
2593 // Make sure tooltip is disabled so it does not take input focus
2594 tooltip->ModifyStyle(0,WS_DISABLED);
2595 tooltip->Create();
2596 }
2597 }
2598 }
2599
2600 // NOTE: CreateChildren will throw a TXWindow exception if one of the
2601 // child objects could not be created.
2602 //
2604
2605 // Transfer data here for legacy compatibility.
2606 // Note that this may be before any setup in a derived class has completed,
2607 // if that class overrides SetupWindow by calling this base version first,
2608 // as is the usual idiom. This problem has now been fixed, and TransferData
2609 // is now normally called from PerformSetupAndTransfer, thus ensuring that setup
2610 // has been fully completed before transfer. But we retain the old behaviour
2611 // here for compatibility modes to support legacy applications.
2612 //
2613#if defined(OWL5_COMPAT)
2615#endif
2616}
2617
2618//
2619/// Always called immediately before the HWindow becomes invalid, CleanupWindow
2620/// gives derived classes an opportunity to clean up HWND related resources. This
2621/// function is the complement to SetupWindow.
2622///
2623/// Override this function in your derived class to handle window cleanup. Derived
2624/// classes should call the base class's version of CleanupWindow as the last step
2625/// before returning. The following example from the sample program, APPWIN.CPP,
2626/// illustrates this process:
2627/// \code
2628/// //Tell windows that we are not accepting drag and drop transactions any more and
2629/// //perform other window cleanup.
2630/// void
2631/// TAppWindow::CleanupWindow()
2632/// {
2633/// AppLauncherCleanup();
2634/// DragAcceptFiles(false);
2635/// TWindow::CleanupWindow();
2636/// }
2637/// \endcode
2638//
2639void
2641{
2642 TRACEX(OwlWin, 1, _T("TWindow::CleanupWindow() @") << (void*)this << *this);
2643}
2644
2645//
2646/// Transfers data to or from any window with or without children and returns the
2647/// total size of the data transferred. Transfer is a general mechanism for data
2648/// transfer that can be used with or without using TransferData. The direction
2649/// supplied specifies whether data is to be read from or written to the supplied
2650/// buffer, or whether the size of the transfer data is simply to be returned. Data
2651/// is not transferred to or from any child windows whose wfTransfer flag is not
2652/// set. The return value is the size (in bytes) of the transfer data.
2653//
2654uint
2656{
2657 if (!buffer && direction != tdSizeData) return 0;
2658
2659 //
2660 // Transfer window 'data' to/from the passed data buffer. Used to initialize
2661 // windows and get data in or out of them.
2662 //
2663 // The direction passed specifies whether data is to be read from or written
2664 // to the passed buffer, or whether the data element size is simply to be
2665 // returned
2666 //
2667 // The return value is the size (in bytes) of the transfer data. this method
2668 // recursively calls transfer on all its children that have wfTransfer set.
2669 //
2670 auto p = buffer;
2671 for (auto& w : GetChildren())
2672 {
2673 if (w.IsFlagSet(wfTransfer))
2674 p = static_cast<char*>(p) + w.Transfer(p, direction);
2675 }
2676 return static_cast<uint>(reinterpret_cast<char*>(p) - reinterpret_cast<char*>(buffer));
2677}
2678
2679//
2680/// Transfers data between the TWindow's data buffer and the child
2681/// windows in its ChildList (data is not transfered between any child
2682/// windows whose wfTransfer flag is not set)
2683///
2684/// A window usually calls TransferData during setup and closing of windows and
2685/// relies on the constructor to set TransferBuffer to something meaningful.
2686/// TransferData calls the Transfer member function of each participating child
2687/// window, passing a pointer to TransferBuffer as well as the direction specified
2688/// in direction (tdSetData, tdGetData, or tdSizeData).
2689//
2690void
2692{
2693 if (!TransferBuffer) return; // nothing to do
2694 uint size = Transfer(TransferBuffer, tdSizeData);
2695 if (direction == tdSizeData) return; // done
2696 if (TransferBufferSize > 0 && size != TransferBufferSize)
2698 WARN(TransferBufferSize == 0,
2699 _T("TWindow::TransferData: Unsafe transfer is performed! ")
2700 _T("Use one of the safe overloads of SetTransferBuffer to enable buffer checks."));
2701 Transfer(TransferBuffer, direction);
2702}
2703
2704//
2705// Checks whether the given HWND belongs to this process.
2706// Internal function.
2707//
2708inline static bool BelongsToCurrentProcess (HWND h)
2709{
2710 DWORD processId = 0;
2712 return processId == ::GetCurrentProcessId();
2713}
2714
2715//
2716/// Installs the instance thunk as the WindowProc and saves the old window function
2717/// in DefaultProc.
2718//
2719void
2721{
2723 PRECONDITION(GetInstanceProc());
2724
2725 if (!BelongsToCurrentProcess(GetHandle())) return;
2726
2727 // If the window already has the window proc we want,
2728 // then just ensure that it has a default proc and return.
2729 //
2730 if (GetInstanceProc() == GetWindowProc())
2731 {
2732 if (!DefaultProc) DefaultProc = ::DefWindowProc;
2733 return;
2734 }
2735
2736 // Initialize the instance proc and install it.
2737 //
2738 InitInstanceProc();
2739 DefaultProc = SetWindowProc(GetInstanceProc());
2740}
2741
2742//
2743/// Registers the Windows registration class of this window, if this window is not
2744/// already registered. Calls GetWindowClassName and GetWindowClass to retrieve the
2745/// Windows registration class name and attributes of this window. Register returns
2746/// true if this window is registered.
2747//
2748bool
2750{
2751 auto& m = *GetModule();
2752 const auto c = GetWindowClassName();
2753 if (m.IsRegisteredClass(c)) return true;
2754 auto w = WNDCLASS{};
2756 CHECK(c.GetPointerRepresentation() == w.lpszClassName);
2757 return m.IsRegisteredClass(c) ? true : ::RegisterClass(&w);
2758}
2759
2760//
2761/// Use this function to determine if it is okay to close a window. Returns true if
2762/// the associated interface element can be closed. Calls the CanClose member
2763/// function of each of its child windows. Returns false if any of the CanClose
2764/// calls returns false.
2765/// In your application's main window, you can override TWindow's CanClose and call
2766/// TWindow::MessageBox to display a YESNOCANCEL message prompting the user as
2767/// follows:
2768/// - \c \b YES Save the data
2769/// - \c \b NO Do not save the data, but close the window
2770/// - \c \b CANCEL Cancel the close operation and return to the edit window
2771///
2772/// The following example shows how to write a CanClose function that displays a
2773/// message box asking if the user wants to save a drawing that has changed. To save
2774/// time, CanClose uses the IsDirty flag to see if the drawing has changed. If so,
2775/// CanClose queries the user before closing the window.
2776/// \code
2777/// bool TMyWindow::CanClose()
2778/// {
2779/// if (IsDirty)
2780/// switch(MessageBox("Do you want to save?", "Drawing has changed.",
2781/// MB_YESNOCANCEL | MB_ICONQUESTION)) {
2782/// case IDCANCEL:
2783/// // Choosing Cancel means to abort the close -- return false.
2784/// return false;
2785///
2786/// case IDYES:
2787/// // Choosing Yes means to save the drawing.
2788/// CmFileSave();
2789/// }
2790/// return true;
2791/// }
2792/// \endcode
2793//
2794bool
2796{
2797 auto c = GetChildren();
2798 return all_of(c.begin(), c.end(), [](TWindow& w) { return !w.GetHandle() || w.CanClose(); });
2799}
2800
2801//
2802/// Determines if it is okay to close a window before actually closing the window.
2803/// If this is the main window of the application, calls GetApplication->CanClose.
2804/// Otherwise, calls this->CanClose to determine whether the window can be closed.
2805/// After determining that it is okay to close the window, CloseWindow calls Destroy
2806/// to destroy the HWND.
2807//
2808void
2810{
2811 bool willClose;
2812
2815
2816 else
2817 willClose = CanClose();
2818
2819 if (willClose)
2820 Destroy(retVal);
2821}
2822
2823//
2824/// The default response to a WM_CLOSE message is to call CloseWindow()
2825/// and then have the window deleted if the Handle was really destroyed.
2826//
2827void
2829{
2830 if (IsFlagSet(wfAlias))
2832
2833 else {
2834 CloseWindow();
2836 GetApplication()->Condemn(this); // Assumes delete
2837 }
2838}
2839
2840//
2841/// Responds to an incoming WM_DESTROY message
2842///
2843/// Calls CleanupWindow() to let derived classes cleanup
2844/// Clears the wfFullyCreated flag since this window is no longer fully created
2845///
2846/// If the TWindow is the application's main window posts a 'quit' message to
2847/// end the application, unless already in ~TApplication() (MainWindow == 0)
2848//
2849void
2851{
2853 CleanupWindow();
2854
2855 if (!IsFlagSet(wfAlias)) {
2856 if (IsFlagSet(wfMainWindow) && GetApplication()->IsRunning())
2858 }
2859
2861}
2862
2863//
2864/// Responds to an incoming WM_NCDESTROY message, the last message
2865/// sent to an MS-Windows interface element
2866///
2867/// Sets the Handle data member of the TWindow to zero to indicate that an
2868/// interface element is no longer associated with the object
2869//
2870void
2872{
2874 SetHandle(nullptr);
2875}
2876
2877//
2878/// Respond to Windows attempt to close down. Determines if this app or window
2879/// is ready to close.
2880//
2881bool
2883{
2884 if (IsFlagSet(wfAlias))
2885 return static_cast<bool>(DefaultProcessing());
2886
2887 else if (IsFlagSet(wfMainWindow))
2888 return GetApplication()->CanClose();
2889
2890 else
2891 return CanClose();
2892}
2893
2894//
2895/// Provides default handling for WM_ENDSESSION.
2896/// If the session is ending, throws the exception TXEndSession, thus shutting down the
2897/// entire applicaton.
2898//
2899void
2901{
2902 if (endSession)
2903 throw TXEndSession();
2904 else
2906}
2907
2908
2909//
2910/// Handle message posted to us by a control needing assistance in dealing with
2911/// invalid inputs
2912///
2913/// Responds to a WM_CHILDINVALID message posted by a child edit control. Indicates
2914/// that the contents of the child window are invalid.
2915//
2916void
2923
2924//----------------------------------------------------------------------------
2925// Non-virtuals
2926//
2927
2928void
2930{
2932 FreeInstanceProc();
2933 InstanceProc = nullptr;
2934 Init(handle, GetModule());
2935}
2936
2937
2938void
2940{
2941 // NOTE: This is by no means a complete way of detaching the window...
2942 // The following is logic allows Delphi/OWL interaction..
2943 //
2945 SetHandle(nullptr);
2947}
2948
2949
2950//
2951/// Returns the number of child windows of the window.
2952//
2953unsigned
2955{
2956 return IndexOf(ChildList) + 1;
2957}
2958
2959//
2960// Walks over children and assigns a z-order index to the ZOrder member
2961//
2962void
2963TWindow::AssignZOrder()
2964{
2965 TWindow* wnd;
2967
2968 if (curWindow) {
2970
2971 if (curWindow) {
2972 int i = 1;
2973
2975 curWindow;
2977 {
2979
2980 if (wnd)
2981 wnd->ZOrder = static_cast<uint16>(i++);
2982 }
2983 }
2984 }
2985}
2986
2987//
2988/// Creates the child windows in the child list whose auto-create flags (with
2989/// wfAutoCreate mask) are set. If all of the child windows are created
2990/// successfully, CreateChildren returns true.
2991/// \note Throws an exception (TXWindow) if a child object could not be
2992/// created.
2993//
2994bool
2996{
2997 // Create children first to restore creation order.
2998 //
2999 for (auto& child : GetChildren())
3000 {
3001 //
3002 if (child.GetHandle())
3003 continue;
3004
3005 bool autoCreate = child.IsFlagSet(wfAutoCreate);
3006 WARNX(OwlWin, !autoCreate, 0, _T("Child window(Id=") << child.GetId() << _T(") not autocreated"));
3007 if (!autoCreate)
3008 continue;
3009
3010 // This call will only fail if a user-defined Create() returns false.
3011 // OwlNext's Create-implementations always throw exceptions.
3012 //
3013 if (!child.Create())
3015
3016 // Get & set the window text for the child if it is iconic.
3017 // TODO: Review if this hack is still necessary.
3018 //
3019 if (child.IsIconic())
3020 child.SetWindowText(child.GetWindowText());
3021 }
3022
3023 // Restore Z-ordering for children that have Z-ordering recorded.
3024 //
3026 for (int top = NumChildren(); top; top--)
3027 {
3028 auto c = GetChildren();
3029 const auto i = find_if(c.begin(), c.end(), [&top](TWindow& w) { return w.ZOrder == top; });
3030 if (i != c.end())
3031 {
3032 TWindow& child = *i;
3033 child.SetWindowPos(above, TRect{}, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
3034 above = child.GetHandle();
3035 }
3036 }
3037 return true;
3038}
3039
3040//
3041// adds the passed pointer to a child window to the linked list
3042// of sibling windows which ChildList points to
3043//
3044void
3045TWindow::AddChild(TWindow* child)
3046{
3047 if (!child) return;
3048 if (ChildList)
3049 {
3050 child->SiblingList = ChildList->SiblingList;
3051 ChildList->SiblingList = child;
3052 ChildList = child;
3053 }
3054 else
3055 {
3056 ChildList = child;
3057 child->SiblingList = child;
3058 }
3059}
3060
3061//
3062/// Returns a pointer to the TWindow's previous sibling (the window previous to
3063/// the TWindow in its parent's child window list)
3064///
3065/// If the TWindow was the first child added to the list, returns a pointer to
3066/// the last child added
3067//
3068TWindow*
3070{
3071 if (!SiblingList) {
3072 return nullptr;
3073 }
3074 else {
3075 TWindow* CurrentIndex = this;
3076
3077 while (CurrentIndex->Next() != this)
3078 CurrentIndex = CurrentIndex->Next();
3079
3080 return CurrentIndex;
3081 }
3082}
3083
3084#if defined(OWL5_COMPAT)
3085
3086//
3087/// Returns a pointer to the first TWindow in the ChildList that meets some
3088/// specified criteria
3089///
3090/// If no child in the list meets the criteria, 0 is returned
3091///
3092/// The Test parameter which defines the criteria, is a pointer to a
3093/// function that takes a TWindow pointer & a pointer to void
3094///
3095/// The TWindow* will be used as the pointer to the child window and
3096/// the void* as a pointer to the Test function's additional parameters
3097///
3098/// The Test function must return a Boolean value indicating whether the
3099/// child passed meets the criteria
3100///
3101/// In the following example, GetFirstChecked calls FirstThat to obtain a pointer
3102/// (p) to the first check box in the child list that is checked:
3103/// \code
3104/// bool IsThisBoxChecked(TWindow* p, void*) {
3105/// return ((TCheckBox*)p)->GetCheck() == BF_CHECKED;
3106/// }
3107/// TCheckBox* TMyWindow::GetFirstChecked() {
3108/// return FirstThat(IsThisBoxChecked);
3109/// }
3110/// \endcode
3111//
3112TWindow*
3113TWindow::FirstThat(TCondFunc test, void* paramList) const
3114{
3115 if (ChildList) {
3116 TWindow* nextChild = ChildList->Next();
3118
3119 do {
3121 nextChild = nextChild->Next();
3122
3123 //
3124 // Test curChild for okay
3125 //
3126 if (test(curChild, paramList))
3127 return curChild;
3128 } while (curChild != ChildList && ChildList);
3129 }
3130 return 0;
3131}
3132
3133//
3134/// Iterates over each child window in the TWindow's ChildList,
3135/// calling the procedure whose pointer is passed as the Action to be
3136/// performed for each child
3137///
3138/// A pointer to a child is passed as the first parameter to the iteration
3139/// procedure
3140///
3141/// In the following example, CheckAllBoxes calls ForEach, checking all the check
3142/// boxes in the child list:
3143/// \code
3144/// void CheckTheBox(TWindow* p, void*) {
3145/// ((TCheckBox*)p)->Check();
3146/// }
3147/// void CheckAllBoxes() {
3148/// ForEach(CheckTheBox);
3149/// }
3150/// \endcode
3151//
3152void
3153TWindow::ForEach(TActionFunc action, void* paramList)
3154{
3155 if (ChildList) {
3157 TWindow* nextChild = ChildList->Next(); // Allows ForEach to delete children
3158
3159 do {
3161 nextChild = nextChild->Next();
3163 } while (curChild != ChildList && ChildList);
3164 }
3165}
3166
3167//
3168/// Returns a pointer to the first TWindow in the ChildList that
3169/// meets some specified criteria
3170///
3171/// If no child in the list meets the criteria, 0 is returned
3172///
3173/// The Test parameter which defines the criteria, is a pointer to a member
3174/// function (this is how it's different from FirstThat above) that takes a
3175/// pointer to a TWindow & a pointer to void
3176///
3177/// The TWindow pointer will be used as the pointer to the child window and the
3178/// void pointer as a pointer to the Test function's additional parameters
3179///
3180/// The Test function must return a Boolean value indicating whether the child
3181/// passed meets the criteria
3182TWindow*
3183TWindow::FirstThat(TCondMemFunc test, void* paramList)
3184{
3185 if (ChildList) {
3186 TWindow* nextChild = ChildList->Next();
3188
3189 do {
3190 CHECKX(nextChild, _T("The child list was corrupted/modified while traversing it"));
3192 nextChild = nextChild->Next();
3193
3194 if ((this->*test)(curChild, paramList))
3195 return curChild;
3196 } while (curChild != ChildList && ChildList);
3197 }
3198 return 0;
3199}
3200
3201//
3202/// Iterates over each child window in the TWindow's ChildList,
3203/// calling the member function (unlike ForEach above which takes pointer
3204/// to non-member function) whose pointer is passed as the Action to
3205/// be performed for each child
3206///
3207/// A pointer to a child is passed as the first parameter to the iteration
3208/// procedure
3209//
3210void
3211TWindow::ForEach(TActionMemFunc action, void* paramList)
3212{
3213 if (ChildList) {
3214 TWindow* nextChild = ChildList->Next();
3216
3217 do {
3218 CHECKX(nextChild, _T("The child list was corrupted/modified while traversing it"));
3220 nextChild = nextChild->Next();
3221 (this->*action)(curChild, paramList);
3222 } while (curChild != ChildList && ChildList);
3223 }
3224}
3225
3226#endif
3227
3228//
3229/// Returns the position at which the passed child window appears in the TWindow's ChildList.
3230/// Position 0 references the first child, as returned by TWindow::GetFirstChild.
3231///
3232/// \returns -1 is returned, if the child does not appear in the list.
3233//
3234int TWindow::IndexOf(const TWindow* child) const
3235{
3236 auto i = 0;
3237 for (auto& c : GetChildren())
3238 if (&c == child)
3239 return i;
3240 else
3241 ++i;
3242 return -1;
3243}
3244
3245//
3246/// Returns the child at the passed position in the TWindow's ChildList
3247/// Position 0 references the first child, as returned by TWindow::GetFirstChild.
3248///
3249/// \returns `nullptr` is returned, if the position is negative.
3250///
3251/// \note Passing a position larger or equal to the number of children, i.e. `At(i)` for *i* larger
3252/// or equal to *n*, where *n* equals the value returned by TWindow::NumChildren, will be
3253/// equivalent to `At(i % n)`. This behaviour is for backwards compatibility reasons, for legacy
3254/// code that depends on the original implementation, which did circular traversal. However, the
3255/// list is never traversed circularly in the current implementation. Instead, `i % n` is
3256/// calculated as the number of links to traverse.
3257//
3258TWindow* TWindow::At(int position)
3259{
3260 if (position < 0) return nullptr;
3261 position %= NumChildren();
3262 auto i = 0;
3263 for (auto& w : GetChildren())
3264 if (i == position)
3265 return &w;
3266 else
3267 ++i;
3268 return nullptr; // Should never get here, though.
3269}
3270
3271//
3272/// Returns a pointer to the window in the child window list that has the supplied
3273/// id. Returns 0 if no child window has the indicated id.
3274//
3276{
3277 auto c = GetChildren();
3278 const auto i = find_if(c.begin(), c.end(), [id](TWindow& w) { return w.GetId() == id; });
3279 return (i != c.end()) ? &(*i) : nullptr;
3280}
3281
3282//
3283/// Sends a message (msg) to a specified window or windows. After it calls the
3284/// window procedure, it waits until the window procedure has processed the message
3285/// before returning.
3286//
3287TResult
3289{
3291
3294 return result;
3295}
3296
3297//
3298/// Forwards the window's current message. Calls SendMessage if send is true;
3299/// otherwise calls PostMessage.
3300//
3301TResult
3303{
3304 if (!handle)
3305 return 0;
3306
3308 if (send) {
3309 TResult result = ::SendMessage(handle, currentEvent.Message,
3310 currentEvent.Param1,
3311 currentEvent.Param2);
3313 return result;
3314 }
3315 else
3316 return ::PostMessage(handle, currentEvent.Message,
3317 currentEvent.Param1,
3318 currentEvent.Param2);
3319}
3320
3321//
3322/// Forwards the window's current message. Calls SendMessage if send is true;
3323/// otherwise calls PostMessage.
3324//
3325TResult
3327{
3329 if (send)
3330 return HandleMessage(currentEvent.Message, currentEvent.Param1,
3331 currentEvent.Param2);
3332 return ForwardMessage(GetHandle(), send);
3333}
3334
3335//
3336/// Sends the specified message to all immediate children using SendMessage.
3337/// \note Includes non-object windows
3338//
3339void
3349
3350//
3351/// Posts messages when the mouse pointer leaves a window or hovers over a
3352/// window for a specified amount of time.
3353/// Encapsulates the eponymous Windows API function.
3354/// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms646265.aspx
3355//
3356bool
3358{
3359 TRACKMOUSEEVENT a = {sizeof(TRACKMOUSEEVENT), flags, GetHandle(), static_cast<DWORD>(hoverTime)};
3360 return ::TrackMouseEvent(&a) != FALSE;
3361}
3362
3363//
3364/// Encapsulates a call to TrackMouseEvent, passing the TME_CANCEL flag.
3365/// See TrackMouseEvent.
3366//
3367bool
3369{
3370 return TrackMouseEvent(flags | TME_CANCEL);
3371}
3372
3373//
3374/// Returns the current state of mouse event tracking initiated by TrackMouseEvent.
3375/// Encapsulates a call to ::TrackMouseEvent, passing the TME_QUERY flag.
3376/// See TrackMouseEvent and Windows API structure TRACKMOUSEEVENT.
3377/// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms645604.aspx
3378//
3381{
3384 CHECK(r); InUse(r);
3385 return a;
3386}
3387
3388//
3389/// This version of ShutDownWindow unconditionally shuts down a given window, calls
3390/// Destroy on the interface element, and then deletes the interface object. Instead
3391/// of using ShutDownWindow, you can call Destroy directly and then delete the
3392/// interface object.
3393///
3394/// \note This function is static to avoid side effects of deleting 'this'.
3395//
3396void
3398{
3399 win->Destroy(retVal);
3400 delete win;
3401}
3402
3403//
3404/// Copies title to an allocated string pointed to by title. Sets the caption of the
3405/// interface element to title. Deletes any previous title.
3406/// If the given title is 0, then the internal caption is initialized to 0, and no update
3407/// of the interface element is done.
3408//
3409void
3411{
3412 if (Title != title) {
3413 if (Title)
3414 delete[] Title;
3415 Title = title ? strnewdup(title) : nullptr;
3416 }
3417
3418 if (Title && GetHandle())
3419 ::SetWindowText(GetHandle(), Title);
3420}
3421
3422//
3423/// Sets the window title to the resource string identified by the given id.
3424//
3425void
3430
3431//
3432/// Updates the TWindow internal caption (Title) from the current window's caption.
3433/// GetWindowTextTitle is used to keep Title synchronized with the actual window
3434/// state when there is a possibility that the state might have changed.
3435//
3436void
3438{
3439 // NB! Previously (<= 6.30) Title was here checked against 0xXXXXFFFF; a flag for "don't-change".
3440 // See comment in TDialog::Init for more details.
3441
3442 if (Title)
3443 delete[] Title;
3444
3446 if (titleLength < 0) {
3447 Title = strnewdup(_T(""));
3448 }
3449 else {
3450 Title = new tchar[titleLength + 1];
3451 Title[0] = 0;
3452 Title[titleLength] = 0;
3453 GetWindowText(Title, titleLength + 1);
3454 }
3455}
3456
3457//
3458/// Copies the style, coordinate, and the resource id (but not the title) from the
3459/// existing HWnd into the TWindow members.
3460/// \note The title is not copied here, but in GetWindowTextTitle()
3461//
3462void
3464{
3465 // Retrieve Attr.Style and Attr.ExStyle
3466 //
3467 // NOTE: some windows controls (e.g. EDIT) change the style bits
3468 // (e.g. WS_BORDER) from their original values. if we always reset
3469 // Attr.Style and Attr.ExStyle by extracting their values from
3470 // Windows, we will lose some of the style bits we supplied
3471 // in the CreateWindowEx call. in the case of the ResourceId
3472 // constructors, of course, we must retrieve these values.
3473 //
3477 }
3478
3479 // Retrieve Attr.X, Attr.Y, Attr.W and Attr.H
3480 //
3481 TRect wndRect;
3482
3484 Attr.H = wndRect.Height();
3485 Attr.W = wndRect.Width();
3486
3488 if ((Attr.Style & WS_CHILD) && hParent)
3489 ::ScreenToClient(hParent, &wndRect.TopLeft());
3490
3491 Attr.X = wndRect.left;
3492 Attr.Y = wndRect.top;
3493
3494 Attr.Id = GetWindowLong(GWL_ID);
3495}
3496
3497//
3498/// Translates the text of a specified control into an integer value and returns it.
3499/// The parameter 'translated' points to a variable that is set to 'true' on success, 'false' otherwise.
3500/// The parameter 'isSigned' indicates that the retrieved value is signed (the default).
3501/// \note Wraps the corresponding function in the Windows API.
3502//
3503uint
3513
3514//
3515// Implementation functions for style getters and mutators.
3516//
3517namespace {
3518
3519template <int GwlStyle, uint32 TWindowAttr::*StyleMem>
3520auto GetStyle_(const TWindow* w) -> uint32
3521{
3522 return w->GetHandle() ? w->GetWindowLong(GwlStyle) : (w->Attr.*StyleMem);
3523}
3524
3525template <int GwlStyle, uint32 TWindowAttr::*StyleMem>
3526auto SetStyle_(TWindow* w, uint32 style) -> uint32
3527{
3528 const auto setStyleMem = [](TWindow* w, uint32 style)
3529 {
3530 const auto oldstyle = w->Attr.*StyleMem;
3531 w->Attr.*StyleMem = style;
3532 return oldstyle;
3533 };
3534 return w->GetHandle() ? w->SetWindowLong(GwlStyle, style) : setStyleMem(w, style);
3535}
3536
3537template <uint32 (TWindow::*GetStyleMemFun)() const, uint32 (TWindow::*SetStyleMemFun)(uint32)>
3538auto ModifyStyle_(TWindow* w, uint32 offBits, uint32 onBits, uint swpFlags) -> bool
3539{
3540 const auto style = (w->*GetStyleMemFun)();
3541 const auto newStyle = (style & ~offBits) | onBits;
3542 const auto isDifferent = style != newStyle;
3543 if (isDifferent)
3544 {
3546 if (swpFlags != 0)
3547 w->SetWindowPos(nullptr, {}, swpFlags | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
3548 }
3549 return isDifferent;
3550}
3551
3552} // anonymous namespace
3553
3554//
3555/// Gets the style bits of the underlying window or the 'Style' member of the
3556/// attribute structure associated with this TWindow object.
3557//
3559{
3561}
3562
3563//
3564/// Sets the style bits of the underlying window or the 'Style' member of the
3565/// attribute structure associated with this TWindow object.
3566//
3568{
3570}
3571
3572//
3573/// Gets the extra style bits of the window.
3574//
3576{
3578}
3579
3580//
3581/// Sets the extra style bits of the window.
3582//
3584{
3586}
3587
3588//
3589/// Modifies the style bits of the window.
3590//
3595
3596//
3597/// Modifies the style bits of the window.
3598//
3603
3604//
3605/// Gets the screen coordinates of the window's rectangle and copies them into rect.
3606/// \note Gets the window rectangle whether it has been created or not
3607//
3608void
3610 if (GetHandle()) {
3612 }
3613 else {
3614 rect.SetWH(Attr.X, Attr.Y, Attr.W, Attr.H);
3615 }
3616}
3617
3618//
3619/// Gets the coordinates of the window's client area and then copies them into the
3620/// object referred to by TRect.
3621/// \note Gets the window's client rectangle whether it has been created or not
3622//
3623void
3625 if (GetHandle()) {
3627 }
3628 else {
3629 rect.Set(0, 0, Attr.W, Attr.H);
3630 }
3631}
3632
3633//
3634/// Set the new window position.
3635//
3636/// Changes the size of the window pointed to by x, y, w, and h. flags contains one
3637/// of the SWP_Xxxx Set Window Position constants that specify the size and
3638/// position of the window. If flags is set to SWP_NOZORDER, SetWindowPos ignores
3639/// the hWndInsertAfter parameter and retains the current ordering of the child,
3640/// pop-up, or top-level windows.
3641///
3642/// SWP_Xxxx Set Window Position Constants
3643///
3644/// - \c \b SWP_DRAWFRAME Draws a frame around the window.
3645/// - \c \b SWP_FRAMECHANGED Sends a message to the window to recalculate the window's
3646/// size. If this flag is not set, a recalculate size message is sent only at the
3647/// time the window's size is being changed.
3648/// - \c \b SWP_HIDEWINDOW Hides the window.
3649/// - \c \b SWP_NOACTIVATE Does not activate the window. If this flag is not set, the
3650/// window is activated and moved to the top of the stack of windows.
3651/// - \c \b SWP_NOCOPYBITS Discards the entire content area of the client area of the
3652/// window. If this flag is not set, the valid contents are saved and copied into
3653/// the window after the window is resized or positioned.
3654/// - \c \b SWP_NOMOVE Remembers the window's current position.
3655/// - \c \b SWP_NOSIZE Remembers the window's current size.
3656/// - \c \b SWP_NOREDRAW Does not redraw any changes to the window. If this flag is set, no
3657/// repainting of any window area (including client, nonclient, and any window part
3658/// uncovered as a result of a move) occurs. When this flag is set, the application
3659/// must explicitly indicate if any area of the window is invalid and needs to be
3660/// redrawn.
3661/// - \c \b SWP_NOZORDER Remembers the current Z-order (window stacking order).
3662/// - \c \b SWP_SHOWWINDOW Displays the window.
3663//
3664bool
3666 int x, int y, int w, int h,
3667 uint flags)
3668{
3669 if (GetHandle())
3670 return ::SetWindowPos(GetHandle(), hWndInsertAfter, x, y, w, h, flags);
3671
3672 if (!(flags & SWP_NOMOVE)) {
3673 Attr.X = x;
3674 Attr.Y = y;
3675 }
3676 if (!(flags & SWP_NOSIZE)) {
3677 Attr.W = w;
3678 Attr.H = h;
3679 }
3680
3681 // !CQ Can't do much with Z-Order or owner Z-Order
3682
3683 if (flags & SWP_SHOWWINDOW)
3684 Attr.Style |= WS_VISIBLE;
3685 else if (flags & SWP_HIDEWINDOW)
3686 Attr.Style &= ~WS_VISIBLE;
3687
3688 return true;
3689}
3690
3691//
3692/// Displays this TWindow in a given state. Can be called either before or after
3693/// the Window is created. If before, the show state is placed into Attr for use
3694/// at creation
3695///
3696/// After ensuring that the TWindow interface element has a valid handle, ShowWindow
3697/// displays the TWindow on the screen in a manner specified by cmdShow, which can
3698/// be one of the following SW_Xxxx Show Window constants:
3699/// - \c \b SW_SHOWDEFAULT Show the window in its default configuration. Should be used at
3700/// startup.
3701/// - \c \b SW_HIDE Hide the window and activate another window.
3702/// - \c \b SW_MINIMIZE Minimize the window and activate the top-level window in the list.
3703/// - \c \b SW_RESTORE Same as SW_SHOWNORMAL.
3704/// - \c \b SW_SHOW Show the window in the window's current size and position.
3705/// - \c \b SW_SHOWMAXIMIZED Activate and maximize the window.
3706/// - \c \b SW_SHOWMINIMIZED Activate window as an icon.
3707/// - \c \b SW_SHOWNA Display the window as it is currently.
3708/// - \c \b SW_SHOWMINNOACTIVE Display the window as an icon.
3709/// - \c \b SW_SHOWNORMAL Activate and display the window in its original size and position.
3710/// - \c \b SW_SHOWSMOOTH Show the window after updating it in a bitmap.
3711//
3712bool
3714{
3715 // If the window is being minimzed send a WM_SYSCOMMAND; this way the
3716 // frame window focus saving works properly
3717 // !CQ do we still need this with final owl2 focus saving?
3718 //
3719 if (gBatchMode)
3720 return true;
3721 if (GetHandle()) {
3722 if (cmdShow == SW_MINIMIZE)
3724
3725 else
3726 return ::ShowWindow(GetHandle(), cmdShow);
3727 }
3728
3729 switch (cmdShow) {
3730 case SW_HIDE:
3731 Attr.Style &= ~WS_VISIBLE;
3732 break;
3733 case SW_SHOWNORMAL:
3734 case SW_RESTORE:
3735 Attr.Style |= WS_VISIBLE;
3736 Attr.Style &= ~(WS_MINIMIZE | WS_MAXIMIZE);
3737 break;
3738 case SW_SHOWMINIMIZED:
3739 case SW_MINIMIZE:
3740 case SW_SHOWMINNOACTIVE:
3741 Attr.Style |= WS_VISIBLE;
3742 Attr.Style |= WS_MINIMIZE;
3743 break;
3744 case SW_SHOWMAXIMIZED:
3745 Attr.Style |= WS_VISIBLE;
3746 Attr.Style |= WS_MAXIMIZE;
3747 break;
3748 case SW_SHOWNOACTIVATE:
3749 case SW_SHOW:
3750 case SW_SHOWNA:
3751 Attr.Style |= WS_VISIBLE;
3752 break;
3753 }
3754 return true;
3755}
3756
3757//
3758/// Sets the mouse cursor for the window, loading the given `resId` from the given `module`.
3759/// If `module` is `nullptr`, then `resId` can be one of the IDC_xxxx constants that represent
3760/// different kinds of cursors. See the Windows documentation for a list of valid values.
3761/// If the mouse is over the client area, the function immediately updates the cursor.
3762/// If `resId` is 0, then the cursor for the window class is used, according to the default
3763/// processing for the WM_SETCURSOR message (see EvSetCursor).
3764//
3765bool
3767{
3768 if (module == CursorModule && resId == CursorResId)
3769 return false;
3770
3771 HCURSOR hOldCursor = (HCursor && CursorModule) ? HCursor : nullptr;
3772
3773 CursorModule = module;
3774 CursorResId = resId;
3775 if (CursorResId)
3776 if (CursorModule)
3777 HCursor = CursorModule->LoadCursor(CursorResId);
3778 else
3779 HCursor = ::LoadCursor(nullptr, CursorResId.GetPointerRepresentation());
3780 else
3781 HCursor = nullptr;
3782
3783 // If the cursor is in our client window then set it now
3784 //
3785 if (GetHandle()) {
3786 TPoint p;
3787 GetCursorPos(p);
3788 ScreenToClient(p);
3789 if (GetClientRect().Contains(p))
3790 {
3791 auto getClassCursor = [&] { return reinterpret_cast<HCURSOR>(::GetClassLongPtr(GetHandle(), GCLP_HCURSOR)); };
3792 ::SetCursor(HCursor ? HCursor : getClassCursor());
3793 }
3794 }
3795
3796 // Destroy old cursor if there was one & it was not loaded from USER
3797 //
3798 if (hOldCursor)
3800 return true;
3801}
3802
3803//
3804/// Handle WM_INITMENUPOPUP while embeded to generate command enable messages
3805/// for our server menu items. Very similar to TFrameWindow::EvInitMenuPopup;
3806/// could rearrange code to share better.
3807//
3808void
3810{
3811 if (IsFlagSet(wfAlias))
3813
3814 else if (!isSysMenu && hPopupMenu) {
3815 const int count = ::GetMenuItemCount(hPopupMenu);
3816
3817 for (int pos = 0; pos < count; pos++) {
3818 uint id;
3819
3820 if (hPopupMenu == GetMenu()) // top level menu
3821 id = ::GetMenuItemID(hPopupMenu, pos);
3822
3823 else {
3824 // For second level and below menus, return the implied id for popup
3825 // sub-menus. The implied id for a sub-menu is the id of the first item
3826 // in the popup sub-menu less 1. If there are more than one level of
3827 // popup menus, it will recursively look into those sub-menus as well.
3828 //
3830 id = popupMenu.GetMenuItemID(pos);
3831 }
3832
3833 // Ignore separators
3834 //
3835 if (id == 0 || uint16(id) == uint16(-1))
3836 continue;
3837
3838 // Skip the rest if it is the mdi child list, or system commands
3839 //
3840 if (id == static_cast<uint>(IDW_FIRSTMDICHILD) || id > 0xF000)
3841 break;
3842
3845 }
3846 }
3847}
3848
3849//
3850/// Sets the font that a control uses to draw text.
3851/// If the given font owns the underlying font handle (HFONT), the window will share ownership. If
3852/// the given font does not own the handle, neither will the window. In any case, the given TFont
3853/// object does not need to outlive the window. However, if the underlying font handle is not
3854/// owned, the caller must make sure that the font handle outlives the window. In this last case,
3855/// the call is equivalent to `SetWindowFont (font.GetHandle(), redraw)`.
3856/// \note Wrapper for Windows API.
3857//
3858void
3860{
3861 WARN(!font.IsHandleOwner(), _T("The given font has (a font handle with) unmanaged lifetime."));
3862 if (!font.IsHandleOwner())
3863 return SetWindowFont(font.GetHandle(), redraw);
3864
3865 // Note: The TFont copy constructor shares the font handle. It does not create a new font.
3866 //
3867 Font = make_unique<TFont>(font);
3868 SetWindowFont(Font->GetHandle(), redraw);
3869}
3870
3871//
3872/// Associates a pop-up menu with the window so that it can automatically handle a
3873/// WM_CONTEXTMENU message.
3874//
3875// !CQ Is this unusual/confusing to take the pointer & own it, & not a ref
3876// !CQ & copy it???
3877//
3878void
3880{
3881 delete ContextPopupMenu;
3882 ContextPopupMenu = popupMenu;
3883}
3884
3885//
3886/// The default message handler for WM_CONTEXTMENU.
3887/// Respond to a right button click or VK_APPS key press in the window.
3888/// If a context menu is set, display it.
3889//
3890void
3892{
3894 if (!m)
3895 {
3897 return;
3898 }
3899
3900 TPoint p(x, y);
3901 bool invalidPos = (x < 0 && y < 0);
3902 if (invalidPos)
3903 {
3904 // The message was probably generated by the VK_APPS key (sets x = y = -1).
3905 // See the Windows API documentation for WM_CONTEXTMENU.
3906 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms647592.aspx
3907 // In this case, we open the menu in the upper left corner of the given window.
3908 //
3909 p = TPoint(0, 0);
3911 }
3912 else
3913 {
3914 // Provide additional help support by reporting the click position to the main window.
3915 //
3916 THelpHitInfo hit(p, this);
3917 GetApplication()->GetMainWindow()->HandleMessage(WM_OWLHELPHIT, 0, reinterpret_cast<TParam2>(&hit));
3918 }
3919 m->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, p, 0, GetHandle());
3920}
3921
3922//
3923/// The default message handler for WM_ENTERIDLE.
3924//
3925void
3927{
3928 // If we're the main window, let it rip from the receiver
3929 //
3930 if (source == MSGF_DIALOGBOX) {
3932 IdleAction(0);
3933 else {
3935 if (win)
3936 win->IdleAction(0);
3937 }
3938 }
3939
3940 // Let original proc. have a crack at msg.
3941 //
3943}
3944
3945//
3946/// Wrapper for Windows API.
3947/// Returns display and placement information (normal, minimized, and maximized) about the window.
3948/// Throws TXOwl on failure. To get extended error information, call GetLastError.
3949//
3951{
3953 auto wp = WINDOWPLACEMENT{sizeof(WINDOWPLACEMENT)};
3954 const auto r = ::GetWindowPlacement(GetHandle(), &wp);
3955 if (!r) throw TXOwl{_T("TWindow::GetWindowPlacement failed")};
3956 return wp;
3957}
3958
3959//
3960/// Wrapper for Windows API.
3961/// Sets the window to a display mode and screen position. `place` points to a window
3962/// placement structure that specifies whether the window is to be hidden, minimized
3963/// or displayed as an icon, maximized, restored to a previous position, activated
3964/// in its current form, or activated and displayed in its normal position.
3965/// Throws TXOwl on failure. To get extended error information, call GetLastError.
3966//
3968{
3970 auto wp = place;
3971 wp.length = sizeof(WINDOWPLACEMENT);
3972 const auto r = ::SetWindowPlacement(GetHandle(), &wp);
3973 if (!r) throw TXOwl{_T("TWindow::SetWindowPlacement failed")};
3974}
3975
3976#if defined(OWL5_COMPAT)
3977
3978//
3979/// Overload for backwards compatibility.
3980/// Returns `true` if successful and `false` on failure.
3981/// To get extended error information, call GetLastError.
3982//
3984{
3986 try
3987 {
3989 return true;
3990 }
3991 catch (const TXOwl&)
3992 {
3993 return false;
3994 }
3995}
3996
3997//
3998/// Overload for backwards compatibility.
3999/// Returns `true` if successful and `false` on failure.
4000/// To get extended error information, call GetLastError.
4001//
4003{
4005 try
4006 {
4008 return true;
4009 }
4010 catch (const TXOwl&)
4011 {
4012 return false;
4013 }
4014}
4015
4016#endif
4017
4018//
4019/// Overload for TRegion.
4020/// \note The system takes ownership of the region handle, hence you must pass a moveable argument.
4021/// For example, `SetWindowRgn(TRegion{...})` or `SetWindowRegion(std::move(rgn))`.
4022/// \sa TWindow::SetWindowRgn(HRGN, bool)
4023//
4025{
4026 PRECONDITION(GetHandle());
4027 return ::SetWindowRgn(GetHandle(), r.Release(), repaint) != 0;
4028}
4029
4030//
4031/// Retrieves the properties of the given scroll bar.
4032/// The 'scrollInfo' parameter must be properly initialized according
4033/// to the Windows API documentation for SCROLLINFO.
4034/// Returns true on success.
4035/// \note Wrapper for Windows API.
4036//
4037bool
4039{
4041 return ::GetScrollInfo(GetHandle(), bar, scrollInfo);
4042}
4043
4044//
4045/// Function-style overload
4046/// Returns selected properties of the given scroll bar.
4047/// Valid values for the 'mask' parameter are the same as for the
4048/// SCROLLINFO::fMask member documented by the Windows API.
4049/// \note On failure, SCROLLINFO::nMin, nMax, nPage, nPos and nTrackPos
4050/// are all left value-initialized (0).
4051//
4054{
4055 SCROLLINFO i = {sizeof(SCROLLINFO), mask};
4056 bool r = GetScrollInfo(bar, &i);
4057 WARNX(OwlWin, !r, 0, _T("GetScrollInfo failed.")); InUse(r);
4058 return i;
4059}
4060
4061//
4062/// Sets the properties of the given scroll bar.
4063/// Returns the current position of the scroll bar thumb.
4064/// \note Wrapper for Windows API.
4065//
4066int
4068{
4070 return ::SetScrollInfo(GetHandle(), bar, scrollInfo, redraw);
4071}
4072
4073//
4074/// Returns the thumb position in the scroll bar. The position returned is relative
4075/// to the scrolling range. If bar is SB_CTL, it returns the position of a control
4076/// in the scroll bar. If bar is SB_HORZ, it returns the position of a horizontal
4077/// scroll bar. If bar is SB_VERT, it returns the position of a vertical scroll bar.
4078//
4079int
4081{
4082 return GetScrollInfo(bar, SIF_POS).nPos;
4083}
4084
4085//
4086/// Sets the thumb position in the scroll bar. Parameter 'bar' identifies the position
4087/// (horizontal, vertical, or scroll bar control) to return and can be one of the
4088/// SB_Xxxx scroll bar constants.
4089/// Returns the current position of the scroll bar thumb.
4090//
4091int
4093{
4094 SCROLLINFO i = {sizeof(SCROLLINFO), SIF_POS, 0, 0, 0, pos};
4095 return SetScrollInfo(bar, &i, redraw);
4096}
4097
4098//
4099/// Returns the thumb track position in the scroll bar. Call this function only during
4100/// the processing of a scroll message with the SB_THUMBTRACK or SB_THUMBPOSITION code.
4101/// See GetScrollPos for valid values for the 'bar' parameter.
4102//
4103int
4105{
4106 return GetScrollInfo(bar, SIF_TRACKPOS).nTrackPos;
4107}
4108
4109//
4110/// Returns the minimum and maximum positions in the scroll bar. If bar is SB_CTL,
4111/// it returns the position of a control in the scroll bar. If bar is SB_HORZ, it
4112/// returns the position of a horizontal scroll bar. If bar is SB_VERT, it returns
4113/// the position of a vertical scroll bar. minPos and maxPos hold the lower and
4114/// upper range, respectively, of the scroll bar positions. If there are no scroll
4115/// bar controls, or if the scrolls are non-standard, minPos and maxPos are zero.
4116//
4117void
4119{
4121 minPos = i.nMin;
4122 maxPos = i.nMax;
4123}
4124
4125//
4126/// Function-style overload
4127//
4130{
4132 return TScrollRange(i.nMin, i.nMax);
4133}
4134
4135//
4136/// Sets the thumb position in the scroll bar. bar identifies the position
4137/// (horizontal, vertical, or scroll bar control) to set and can be one of the
4138/// SB_Xxxx scroll bar constants. minPos and maxPos specify the lower and upper
4139/// range, respectively, of the scroll bar positions.
4140//
4141void
4143{
4146}
4147
4148//
4149/// Overload taking the range as a pair
4150//
4151void
4153{
4154 SetScrollRange(bar, r.first, r.second, redraw);
4155}
4156
4157//
4158/// Returns the page property (SCROLLINFO::nPage) of the given scroll bar.
4159//
4160int
4162{
4163 return GetScrollInfo(bar, SIF_PAGE).nPage;
4164}
4165
4166//
4167/// Sets the page property (SCROLLINFO::nPage) of the given scroll bar.
4168//
4169void
4171{
4172 SCROLLINFO i = {sizeof(SCROLLINFO), SIF_PAGE, 0, 0, static_cast<UINT>(page)};
4174}
4175
4176//
4177//
4178//
4179void
4181{
4182 if (!Tooltip) {
4183
4184 // To circumvent this scenario, we'll look for a window which is fairly
4185 // stable/rooted as owner of the tooltip. Ideally, we'll get the
4186 // application's main window.
4187 //
4188 TWindow* tipParent = this;
4189
4190/* // check it what if window -> is closed but tooltip live?????????
4191 // it is for gastget only ????????????????????
4192 while (tipParent->GetParentO()){
4193 tipParent = tipParent->GetParentO();
4194 if (tipParent->IsFlagSet(wfMainWindow))
4195 break;
4196 }
4197*/
4198 // Create and initialize tooltip
4199 //
4201 }
4202 else {
4203 if (Tooltip->GetHandle())
4204 Tooltip->Activate(enable);
4205 }
4206}
4207
4208//
4209// Set a specific tooltip for this window. Assume we now own the ToolTip
4210//
4211void
4213{
4214 // Cleanup; via Condemned list if tooltip was created
4215 //
4216 if (Tooltip) {
4217 if (Tooltip->GetHandle())
4218 Tooltip->SendMessage(WM_CLOSE);
4219 else
4220 delete Tooltip;
4221 }
4222
4223 // Store new tooltip and create if necessary
4224 //
4225 Tooltip = tooltip;
4226 if (Tooltip) {
4227 if (!Tooltip->GetHandle()) {
4228
4229 // Make sure tooltip is disabled so it does not take input focus
4230 Tooltip->Attr.Style |= WS_DISABLED;
4231 Tooltip->Create();
4232 }
4233 }
4234}
4235
4236//
4237/// Copies a window's update region into a region specified by region. If erase is
4238/// true, GetUpdateRgn erases the background of the updated region and redraws
4239/// nonclient regions of any child windows. If erase is false, no redrawing occurs.
4240/// If the call is successful, GetUpdateRgn returns a value indicating the kind of
4241/// region that was updated. If the region has no overlapping borders, it returns
4242/// SIMPLEREGION; if the region has overlapping borders, it returns COMPLEXREGION;
4243/// if the region is empty, it returns NULLREGION; if an error occurs, it returns
4244/// ERROR.
4245///
4246/// \note Not inline to avoid requiring gdiobjec.h by window.h just to get TRegion's
4247/// conversion operator
4248//
4249int
4251{
4253
4254 return ::GetUpdateRgn(GetHandle(), region, erase);
4255}
4256
4257
4258//
4259/// If a window can process dropped files, DragAcceptFiles sets accept to true.
4260/// \note Wrapper for Windows API.
4261//
4262void
4264{
4267}
4268
4269//
4270/// Creates and displays a message box that contains a message (text), a title
4271/// (caption), and icons or push buttons (type). If caption is 0, the default title
4272/// is displayed. Although flags is set to one push button by default, it can contain
4273/// a combination of the MB_Xxxx message constants. This function returns one of
4274/// the following constants:
4275/// - \c \b IDABORT User selected the abort button.
4276/// - \c \b IDCANCEL User selected the cancel button.
4277/// - \c \b IDIGNORE User selected the ignore button.
4278/// - \c \b IDNO User selected the no button.
4279/// - \c \b IDOK User selected the OK button
4280/// - \c \b IDRETRY User selected the retry button.
4281/// - \c \b IDYES User selected the yes button.
4282//
4283int
4285{
4288 return GetApplication()->MessageBox(*this, text, caption, flags);
4289}
4290
4291int
4293{
4297
4299 return MessageBox(text.c_str(), caption, flags);
4300}
4301
4302int
4304{
4308
4310 return MessageBox(text.c_str(), caption.c_str(), flags);
4311}
4312
4313//
4314/// Displays a standard message box.
4315/// Wrapper for Windows API.
4316/// \sa http://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxindirecta
4317//
4319{
4320 auto p = MSGBOXPARAMS
4321 {
4322 sizeof(MSGBOXPARAMS),
4323 GetHandle(),
4325 text,
4326 caption,
4327 styleFlags,
4328 icon,
4330 callback,
4332 };
4333 return ::MessageBoxIndirect(&p);
4334}
4335
4336//
4337/// Displays a standard message box using the given icon.
4338/// The flag MB_USERICON is automatically combined with the given flags, so there is no need to specify it.
4339/// Wrapper for Windows API.
4340///
4341/// \note The specified icon resource is assumed to reside in the same module as the window, i.e. the
4342/// HINSTANCE handle passed to ::MessageBoxIndirect is the value returned by `this->GetModule()->GetHandle()`.
4343///
4344/// \sa http://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxindirecta
4345//
4346auto TWindow::MessageBoxIndirect(TResId icon, const tstring& text, const tstring& caption, uint flags) const -> int
4347{
4348 PRECONDITION(GetModule() && GetModule()->GetHandle());
4349 return MessageBoxIndirect(
4350 GetModule()->GetHandle(),
4351 TResId{text.c_str()},
4352 TResId{caption.c_str()},
4353 flags | MB_USERICON,
4354 icon,
4355 0,
4356 nullptr,
4357 0
4358 );
4359}
4360
4361auto TWindow::FormatMessageBox(const tstring& formatString, const tstring& caption, uint flags, ...) const -> int
4362{
4363 va_list argp;
4364 va_start(argp, flags);
4365 try
4366 {
4367 auto format = [](const tstring& fmt, va_list argp) -> tstring
4368 {
4369 auto buffer = array<tchar, 1024>{};
4370 const auto r = _vsntprintf(buffer.data(), buffer.size(), fmt.c_str(), argp);
4371 if (r == -1)
4372 {
4373 buffer.back() = _T('\0');
4374 WARNX(OwlWin, r == -1, 0, _T("TWindow::FormatMessageBox: Message was truncated."));
4375 }
4376 return buffer.data();
4377 };
4378 const auto s = format(formatString, argp);
4379 const auto r = MessageBox(s, caption, flags);
4380 va_end(argp);
4381 return r;
4382 }
4383 catch (...)
4384 {
4385 WARNX(OwlWin, true, 0, _T("TWindow::FormatMessageBox failed."));
4386 va_end(argp);
4387 throw;
4388 }
4389}
4390
4391//
4392//
4393//
4395{
4396 HAccel = _hAccel;
4397}
4398
4399//
4400/// For use with CopyText.
4401//
4402struct TWindowGetWindowText
4403{
4404 const TWindow& win;
4405 TWindowGetWindowText(const TWindow& w) : win(w) {}
4406
4407 int operator()(LPTSTR buf, int buf_size)
4408 {return win.GetWindowText(buf, buf_size);}
4409};
4410
4411//
4412/// String-aware overload
4413//
4414tstring
4416{
4417 return CopyText(GetWindowTextLength(), TWindowGetWindowText(*this));
4418}
4419
4420//
4421/// For use with CopyText.
4422//
4423struct TWindowGetDlgItemText
4424{
4425 const TWindow& win;
4426 int id;
4427 TWindowGetDlgItemText(const TWindow& w, int id_) : win(w), id(id_) {}
4428
4429 int operator()(LPTSTR buf, int buf_size)
4430 {return win.GetDlgItemText(id, buf, buf_size);}
4431};
4432
4433//
4434/// String-aware overload
4435//
4436tstring
4438{
4439 return CopyText(::GetWindowTextLength(GetDlgItem(childId)), TWindowGetDlgItemText(*this, childId));
4440}
4441
4442//
4443//
4444//
4445#if defined(__TRACE) || defined(__WARN)
4446//namespace owl {
4447 ostream& operator <<(ostream& os, const TWindow& w)
4448 {
4449 os << '(';
4450 os << _OBJ_FULLTYPENAME(&w) << ',';
4451 os << static_cast<void*>(w.GetHandle()) << ',';
4452 if (w.GetCaption())
4453 os << '\'' << w.GetCaption() << '\'' << ',';
4454 if (w.GetParentO())
4455 os << "id=" << w.GetId();
4456 os << ')';
4457 return os;
4458 }
4459//} // OWL namespace
4460#endif
4461
4462///////////////////////////////////////////////////////////////////////////////////////
4463//
4465{
4466 // 0. If 0
4467 if(data==0)
4468 return 0;
4469 // 1. check to make sure the pointer is valid
4470 if(IsBadReadPtr((void*)data, sizeof(TDrawItem)))
4471 return 0; // quick escape
4472
4473 // 2. check signature -> starting from 5's byte
4474#if defined(_WIN64)
4475 uint32* itemId = (uint32*)((uint8*)data+8);
4476#else
4477 uint32* itemId = (uint32*)((uint8*)data+4);
4478#endif
4480 return 0;
4481
4482 // 3. check to make sure the VTable pointer is valid
4483 if(IsBadReadPtr(*(void**)data, sizeof(void*)))
4484 return 0; // quick escape
4485
4486#if 0 //?? maby simple casting enauph after checking itemId??
4487 TDrawItem* item;
4488 try{
4489 item = localTryCatchBlock(data);
4490 }
4491 catch(...){
4492 return 0;
4493 }
4494 return item;
4495#else
4496 return (TDrawItem*)(void*)data;
4497#endif
4498}
4499///////////////////////////////////////////////////////////////////////////////////////
4500
4501
4502//
4503// Converts the given integer to a string.
4504// TODO: Relocate somewhere else more convenient for reuse.
4505//
4506static tstring
4507ToString(int v)
4508{
4509 tchar buf[64];
4510 _stprintf(buf, _T("%d"), v);
4511 return tstring(buf);
4512}
4513
4514//
4515// Returns a string which kind-of identifies the window (used during autopsy
4516// and vivisection of dead/dying window).
4517//
4518static tstring
4519GetSuspectDescription(TWindow* w)
4520{
4522 if (!w) return _T("");
4523
4524 tstring caption = w->GetCaption() ? w->GetCaption() : _T("");
4525 tstring id = ToString(w->GetWindowAttr().Id);
4527
4528 tstring s;
4529 s += _T("\"") + caption + _T("\"");
4530 s += _T(", ID: ") + id;
4531 s += _T(", window ") + type;
4532 s += _T(".");
4533 return s;
4534}
4535
4536//
4537// Formats an error message defined by the given resource id.
4538// Appends the last system error message if any.
4539//
4540// NB! Note that the TSystemMessage probably is too far from the problem site to give a
4541// meaningful error message; intermediate system calls have probably happened since
4542// the exception was thrown.
4543//
4544static tstring
4545MakeTXWindowMessage(TWindow* win, uint resId)
4546{
4547 TSystemMessage m;
4548 tstring s = TXOwl::MakeMessage(resId, GetSuspectDescription(win).c_str());
4549 if (m.SysError() != ERROR_SUCCESS)
4550 s += _T("\n\nSystem error: ") + m.SysMessage();
4551 return s;
4552}
4553
4554//
4555/// Constructs a TXWindow object with a default resource ID of IDS_INVALIDWINDOW.
4556//
4558:
4559 TXOwl(MakeTXWindowMessage(win, resId), resId),
4560 Window(win)
4561{
4562}
4563
4564//
4565/// Copy the exception object.
4566//
4568:
4569 TXOwl(src),
4570 Window(src.Window)
4571{
4572}
4573
4574//
4575/// Unhandled exception.
4576///
4577/// Called if an exception caught in the window's message loop has not been handled.
4578/// Unhandled() deletes the window. This type of exception can occur if a window
4579/// cannot be created.
4580//
4581int
4583{
4584 Window = 0;
4586}
4587
4588//
4589/// Clone the exception object for safe-throwing.
4590//
4591TXWindow*
4593{
4594 return new TXWindow(*this);
4595}
4596
4597
4598//
4599/// Throws the exception object. Throw() must be implemented in any class derived
4600/// from TXOwl.
4601//
4602void
4604{
4605 throw *this;
4606}
4607
4608//
4609/// Creates the TXWindow exception and throws it.
4610//
4611void
4613{
4614 TXWindow(win, resourceId).Throw();
4615}
4616
4617//
4618// Returns the window causing the exception.
4619//
4620TWindow*
4622{
4623 return Window;
4624}
4625
4626} // OWL namespace
4627
4628/* ========================================================================== */
Definition of class TAppDictionary.
Definition of class TApplication.
#define LOCKCACHE(l, s)
Definition brush.cpp:92
#define CHECK(condition)
Definition checks.h:239
#define WARNX(group, condition, level, message)
Definition checks.h:277
#define WARN(condition, message)
Definition checks.h:273
#define PRECONDITION(condition)
Definition checks.h:227
#define CHECKX(condition, message)
Definition checks.h:245
#define DIAG_DECLARE_GROUP(group)
Definition checks.h:404
#define TRACEX(group, level, message)
Definition checks.h:263
#define DIAG_DEFINE_GROUP_INIT(f, g, e, l)
Definition checks.h:429
Derived from TModule and TMsgThread and virtually derived from TEventHandler, TApplication acts as an...
Definition applicat.h:141
void ResumeThrow()
Rethrows the suspended exception stored by a previous call to SuspendThrow.
int MessageBox(HWND wnd, const tstring &text, const tstring &caption=tstring(), uint type=MB_OK) const
Definition applicat.h:774
int BeginModal(TWindow *window, int flags=MB_APPLMODAL)
Called to begin a modal window's modal message loop.
void Condemn(TWindow *win)
Condemns the given window to be deleted the at the next available safe time.
virtual bool CanClose()
Determine whether the application can be closed.
bool HasSuspendedException() const
Definition applicat.h:242
TFrameWindow * GetMainWindow()
Return the current main window.
Definition applicat.h:592
virtual TTooltip * GetTooltip() const
Get Tooltip.
Definition applicat.h:762
void EndModal(int result)
Cause the current modal message loop to break and have it return a result Re-enable the disabled wind...
void Uncondemn(TWindow *win)
Removes the given window from the list of condemned windows.
The GDI Brush class is derived from TGdiObject.
Definition gdiobjec.h:180
static const TColor Transparent
a non-painting color
Definition color.h:319
static const TColor None
not-a-color
Definition color.h:318
int Index() const
Return the index of the palette entry.
Definition color.h:690
bool IsSysColor() const
Return true if the color is a system color.
Definition color.h:738
Base class for an extensible interface for auto enabling/disabling of commands (menu items,...
Definition window.h:209
virtual void Enable(bool enable=true)
Enables or disables the command sender.
Definition window.cpp:301
uint Flags
TCommandStatus flags Is TCommandStatus::WasHandled if the command enabler has been handled.
Definition window.h:275
TCommandEnabler(uint id, HWND hWndReceiver=0)
Constructs the TCommandEnabler object with the specified command ID.
Definition window.cpp:288
@ WasHandled
Command was enabled or disabled.
Definition window.h:268
TDC is the root class for GDI DC wrappers.
Definition dc.h:64
bool FillSolidRect(const TRect &r, const TColor &color)
Definition dc.h:318
virtual void Measure(MEASUREITEMSTRUCT &)
Definition window.h:195
virtual void Draw(DRAWITEMSTRUCT &)
Definition window.h:194
A nested class, TEventInfo provides specific information about the type of message sent,...
Definition eventhan.h:170
virtual bool Find(TEventInfo &info, TEqualOperator op=0)
Searches the list of response table entries looking for a match.
Definition eventhan.cpp:371
TResult Dispatch(TEventInfo &info, TParam1, TParam2=0)
Takes the message data from TEventInfo's Msg data member and dispatches it to the correct event-handl...
Definition eventhan.cpp:396
bool(* TEqualOperator)(const TGenericTableEntry &, const TEventInfo &)
Definition eventhan.h:193
TFont derived from TGdiObject provides constructors for creating font objects from explicit informati...
Definition gdiobjec.h:296
The TMenu class encapsulates window menus.
Definition menu.h:77
Derived from TCommandEnabler, TMenuItemEnabler is a command enabler for menu items.
Definition framewin.h:39
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
TNotify is a thin wrapper around the NMHDR structure.
Definition commctrl.h:91
A DC class that wraps begin and end paint calls for use in an WM_PAINT response function.
Definition dc.h:671
PAINTSTRUCT Ps
The paint structure associated with this TPaintDC object.
Definition dc.h:677
TPoint is a support class, derived from tagPOINT.
Definition geometry.h:87
TPopupMenu creates an empty pop-up menu to add to an existing window or pop-up menu.
Definition menu.h:189
TRect is a mathematical class derived from tagRect.
Definition geometry.h:308
TRegion, derived from TGdiObject, represents GDI abstract shapes or regions.
Definition gdiobjec.h:581
TPointer GetString() const
Returns the encapsulated string pointer, provided this resource identifier encodes a string pointer.
Definition wsyscls.h:101
bool IsString() const
Returns true if this resource identifier encodes a string pointer.
Definition wsyscls.h:86
TPointer GetPointerRepresentation() const
Returns the encapsulated pointer.
Definition wsyscls.h:76
A template class, TResponseTableEntry lets you define a pattern for entries into a response table.
Definition eventhan.h:217
Class TScroller implements the actual scroller object.
Definition scroller.h:46
virtual void SetWindow(TWindow *win)
Sets the owning window to win.
Definition scroller.h:126
int YPage
Specifies the number of logical device units per page to scroll the rectangle in the vertical (Y) dir...
Definition scroller.h:105
virtual void BeginView(TDC &dc, TRect &rect)
If TScroller_AutoOrg is true (default condition), BeginView automatically offsets the origin of the l...
Definition scroller.cpp:169
virtual bool IsAutoMode()
IsAutoMode is true if automatic scrolling is activated.
Definition scroller.cpp:348
int XLine
Specifies the number of logical device units per line to scroll the rectangle in the horizontal (X) d...
Definition scroller.h:102
virtual void VScroll(uint scrollEvent, int thumbPos)
Responds to the specified vertical scrollEvent by calling ScrollBy or ScrollTo.
Definition scroller.cpp:210
virtual void HScroll(uint scrollEvent, int thumbPos)
Responds to the specified horizontal scrollEvent by calling ScrollBy or ScrollTo.
Definition scroller.cpp:260
void ScrollBy(long dx, long dy)
Scrolls to a position calculated using the passed delta values.
Definition scroller.h:134
virtual void SetSBarRange()
Sets the range of the owner window's scroll bars to match the range of the TScroller and repaints as ...
Definition scroller.cpp:138
virtual void EndView()
Updates the position of the owner window's scroll bars to be coordinated with the position of the TSc...
Definition scroller.cpp:186
int YLine
Specifies the number of logical device units per line to scroll the rectangle in the vertical (Y) dir...
Definition scroller.h:103
virtual void AutoScroll()
Performs "auto-scrolling" (dragging the mouse from within the client client area of the Window to wit...
Definition scroller.cpp:363
int XPage
Specifies the number of logical device units per page to scroll the rectangle in the horizontal (X) d...
Definition scroller.h:104
virtual void SetPageSize()
Sets the XPage and YPage data members (amount by which to scroll on a page scroll request) to the wid...
Definition scroller.cpp:65
static void DragAcceptFiles(HWND, BOOL)
Invokes 'DragAcceptFiles' indirectly.
Definition shellitm.cpp:74
The tagSIZE struct is defined as.
Definition geometry.h:234
TTooltipEnabler is the object forwarded along the command-chain to retrieve the tip text of a tool.
Definition tooltip.h:149
TTooltip encapsulates a tooltip window - i.e.
Definition tooltip.h:175
void Activate(bool activate=true)
Set state of tooltip.
Definition tooltip.h:394
TTooltipText identifies a tool for which text is to be displayed.
Definition commctrl.h:153
Type-safe encapsulation of a Windows class name, a union between ATOM and LPCTSTR.
Definition module.h:47
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
HWND GetParentH() const
Return the handle of the parent.
Definition window.h:1999
HWND SetFocus()
Sets the keyboard focus to current window and activates the window that receives the focus by sending...
Definition window.h:2151
bool EvEraseBkgnd(HDC)
Handler for WM_ERASEBKGND.
Definition window.cpp:1924
static LRESULT CALLBACK InitWndProc(HWND, UINT msg, WPARAM, LPARAM)
Callback process for hooking TWindow to native window.
Definition owl.cpp:189
static TPoint GetCursorPos()
Definition window.h:1212
bool SetCursor(TModule *module, TResId resId)
Sets the mouse cursor for the window, loading the given resId from the given module.
Definition window.cpp:3766
HMENU LoadMenu(TResId id) const
Definition window.h:611
HWND SetCapture()
Sets the mouse capture to the current window.
Definition window.h:2121
int GetScrollTrackPos(int bar) const
Returns the thumb track position in the scroll bar.
Definition window.cpp:4104
virtual THandle PerformCreate()
Called from Create to perform the final step in creating an Windows interface element to be associate...
Definition window.cpp:2345
tstring LoadString(uint id) const
Definition window.h:608
void EvMove(const TPoint &clientOrigin)
Save the normal position of the window.
Definition window.cpp:1666
TCurrentEvent & GetCurrentEvent()
Returns the current event to be processed in the message queue.
Definition window.h:2047
void EvEnterIdle(uint source, HWND hWndDlg)
The default message handler for WM_ENTERIDLE.
Definition window.cpp:3926
virtual void SetParent(TWindow *newParent)
Sets the parent for the specified window by setting Parent to the specified new Parent window object.
Definition window.cpp:738
TApplication * GetApplication() const
Gets a pointer to the TApplication object associated with this.
Definition window.h:1855
void ChildBroadcastMessage(TMsgId, TParam1=0, TParam2=0)
Sends the specified message to all immediate children using SendMessage.
Definition window.cpp:3340
HACCEL LoadAccelerators(TResId id) const
Definition window.h:610
void AttachHandle(HWND handle)
Definition window.cpp:2929
int EvCompareItem(uint ctrlId, const COMPAREITEMSTRUCT &compareInfo)
Handles WM_COMPAREITEM message (for owner draw controls) by forwarding message to control itself.
Definition window.cpp:1689
virtual ~TWindow() override
Destroys this window (unless this is an alias) and the children.
Definition window.cpp:544
TWindow()
Protected constructor for use by immediate virtually derived classes.
Definition window.cpp:392
virtual void EnableTooltip(bool enable=true)
Definition window.cpp:4180
tstring GetWindowText() const
String-aware overload.
Definition window.cpp:4415
void EvPaint()
Response method for an incoming WM_PAINT message.
Definition window.cpp:2041
void TraceWindowPlacement()
Definition window.cpp:306
void DispatchScroll(uint scrollCode, uint thumbPos, HWND hWndCtrl)
Called by EvHScroll and EvVScroll to dispatch messages from scroll bars.
Definition window.cpp:1795
void GetHWndState(bool forceStyleSync=false)
Copies the style, coordinate, and the resource id (but not the title) from the existing HWnd into the...
Definition window.cpp:3463
void EvClose()
The default response to a WM_CLOSE message is to call CloseWindow() and then have the window deleted ...
Definition window.cpp:2828
void EvContextMenu(HWND childHwnd, int x, int y)
The default message handler for WM_CONTEXTMENU.
Definition window.cpp:3891
virtual void GetWindowClass(WNDCLASS &wndClass)
Redefined by derived classes, GetWindowClass fills the supplied MS-Windows registration class structu...
Definition window.cpp:2247
bool SetWindowPos(HWND hWndInsertAfter, const TRect &rect, uint flags)
Changes the size of the window pointed to by rect.
Definition window.h:2809
virtual void EvCommandEnable(TCommandEnabler &ce)
Called by WindowProc to handle WM_COMMAND_ENABLE messages, EvCommandEnable calls the CmXxxx command-h...
Definition window.cpp:1135
virtual int Execute()
Creates the underlying HWND and makes it modal with the help of TApplication's BeginModal support.
Definition window.cpp:2498
virtual bool PreProcessMsg(MSG &msg)
Called from TApplication::ProcessAppMsg() to give the window an opportunity to perform preprocessing ...
Definition window.cpp:644
HWND GetWindow(uint cmd) const
Returns the handle of the window that has the indicated relationship to this window.
Definition window.h:2784
auto GetChildren()
Returns a TWindow::TChildrenRange that can be iterated by standard means.
Definition window.h:550
void AssignContextMenu(TPopupMenu *menu)
Associates a pop-up menu with the window so that it can automatically handle a WM_CONTEXTMENU message...
Definition window.cpp:3879
TWindow * Previous()
Returns a pointer to the TWindow's previous sibling (the window previous to the TWindow in its parent...
Definition window.cpp:3069
HWND GetDlgItem(int childId) const
Retrieves the handle of a control specified by childId.
Definition window.h:3108
void EvMouseWheel(uint modKeys, int zDelta, const TPoint &point)
Event handler for WM_MOUSEWHEEL.
Definition window.cpp:1840
virtual void Destroy(int retVal=0)
Destroys an MS-Windows element associated with the TWindow.
Definition window.cpp:2160
void EvDestroy()
Responds to an incoming WM_DESTROY message.
Definition window.cpp:2850
virtual bool Create()
Creates the window interface element to be associated with this ObjectWindows interface element.
Definition window.cpp:2399
void SetAcceleratorTable(TResId resId)
Definition window.cpp:2291
void EvDeleteItem(uint ctrlId, const DELETEITEMSTRUCT &deleteInfo)
Handles WM_DELETEITEM message (for owner draw controls) by forwarding message to control itself.
Definition window.cpp:1701
TWindow * GetParent() const
Retrieves the OWL object of the parent window. If none exists, returns 0.
Definition window.h:2013
auto MessageBoxIndirect(HINSTANCE resourceModule, TResId text, TResId caption, uint flags, TResId icon, DWORD_PTR contextHelpId, MSGBOXCALLBACK, DWORD languageId) const -> int
Displays a standard message box.
Definition window.cpp:4318
TWindow * GetWindowPtr(HWND hWnd) const
Calls TApplication:GetWindowPtr on the application associated with this window.
Definition window.h:3567
virtual int DoExecute()
Do actual modal execution using the Begin/End Modal support of TApplication.
Definition window.cpp:2508
virtual void RemoveChild(TWindow *child)
Removes a child window.
Definition window.cpp:707
void SetWindowFont(HFONT font, bool redraw=true)
Sets the font that a control uses to draw text.
Definition window.h:3476
void SetTooltip(TTooltip *tooltip)
Definition window.cpp:4212
TRACKMOUSEEVENT QueryMouseEventTracking() const
Returns the current state of mouse event tracking initiated by TrackMouseEvent.
Definition window.cpp:3380
void GetWindowTextTitle()
Updates the TWindow internal caption (Title) from the current window's caption.
Definition window.cpp:3437
void GetScrollRange(int bar, int &minPos, int &maxPos) const
Returns the minimum and maximum positions in the scroll bar.
Definition window.cpp:4118
auto FormatMessageBox(const tstring &formatStr, const tstring &caption, uint flags,...) const -> int
Definition window.cpp:4361
TRect GetWindowRect() const
Gets the screen coordinates of the window's rectangle.
Definition window.h:2257
virtual TTooltip * GetTooltip() const
Definition window.h:1821
void EvHScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
Response method for an incoming WM_HSCROLL message.
Definition window.cpp:1865
void DisableAutoCreate()
Disables the feature that allows an associated child window interface element to be created and displ...
Definition window.h:1814
void PerformSetupAndTransfer()
Ensures that the window is fully set up; then transfers data into the window.
Definition window.cpp:2528
void SetHandle(THandle)
Sets the window handle in a derived class.
Definition window.h:2034
void SetWindowPlacement(const WINDOWPLACEMENT &place)
Wrapper for Windows API.
Definition window.cpp:3967
virtual TResult WindowProc(TMsgId, TParam1, TParam2)
First virtual function called to handling incoming messages to a TWindow.
Definition window.cpp:1409
static void ShutDownWindow(TWindow *win, int retVal=0)
This version of ShutDownWindow unconditionally shuts down a given window, calls Destroy on the interf...
Definition window.cpp:3397
void EvVScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
Response method for an incoming WM_VSCROLL message.
Definition window.cpp:1892
virtual auto GetWindowClassName() -> TWindowClassName
Definition window.cpp:2273
virtual TResult DefWindowProc(TMsgId, TParam1, TParam2)
Virtual function provides final default processing for an incoming message Calls original window proc...
Definition window.cpp:1237
long GetWindowLong(int index) const
Retrieves information about the window depending on the value stored in index.
Definition window.h:2388
virtual uint Transfer(void *buffer, TTransferDirection direction)
Transfers data to or from any window with or without children and returns the total size of the data ...
Definition window.cpp:2655
void Init(TWindow *parent, LPCTSTR title, TModule *module)
Normal initialization of a default constructed TWindow.
Definition window.cpp:401
void SetFlag(uint mask)
Sets the specified TWindow wfXxxx constant flags (for example wfAlias, wfTransfer,...
Definition window.h:1783
bool EvCreate(CREATESTRUCT &)
Response method for an incoming WM_CREATE message.
Definition window.cpp:1587
auto SetWindowRgn(HRGN, bool repaint=false) -> bool
Sets the area within the window where the system permits drawing.
Definition window.h:3011
void SetTextColor(TColor color, bool shouldUpdate=true)
Sets the text color for the window.
Definition window.h:1951
WINDOWPLACEMENT GetWindowPlacement() const
Wrapper for Windows API.
Definition window.cpp:3950
static void ReleaseCapture()
Releases the mouse capture from this window.
Definition window.h:2130
TModule * GetModule() const
Returns a pointer to the module object.
Definition window.h:1841
uint32 SetExStyle(uint32 style)
Sets the extra style bits of the window.
Definition window.cpp:3583
void LoadAcceleratorTable()
Loads a handle to the window's accelerator table specified in the TWindowAttr structure (Attr....
Definition window.cpp:2307
WNDPROC GetWindowProc() const
Definition window.h:2459
void RouteCommandEnable(HWND hInitCmdTarget, TCommandEnabler &ce)
Walks the chain of windows from the initial target window to this window.
Definition window.cpp:1161
bool IsIconic() const
Returns true if window is iconic or minimized.
Definition window.h:2628
TPopupMenu * GetContextMenu() const
Returns the associated popup menu used by the window.
Definition window.h:3266
void ClientToScreen(TPoint &point) const
Converts the client coordinates specified in point to screen coordinates for the new window.
Definition window.h:2248
virtual bool SetDocTitle(LPCTSTR docname, int index)
Default behavior for updating document title is to pass it to parent frame.
Definition window.cpp:778
void EvKillFocus(HWND hWndGetFocus)
Handle WM_KILLFOCUS so that we can have a parent window hold onto our Handle and possibly restore foc...
Definition window.cpp:1611
void SetCaption(LPCTSTR title)
Copies title to an allocated string pointed to by title.
Definition window.cpp:3410
int SetScrollInfo(int bar, SCROLLINFO *scrollInfo, bool redraw=true)
Sets the properties of the given scroll bar.
Definition window.cpp:4067
int GetWindowText(TCHAR *str, int maxCount) const
Copies the window's title into a buffer pointed to by string.
Definition window.h:2655
bool IsChild(HWND hWnd) const
Returns true if the window is a child window or a descendant window of this window.
Definition window.h:3176
uint32 GetExStyle() const
Gets the extra style bits of the window.
Definition window.cpp:3575
virtual void CleanupWindow()
Always called immediately before the HWindow becomes invalid, CleanupWindow gives derived classes an ...
Definition window.cpp:2640
void EvDrawItem(uint ctrlId, const DRAWITEMSTRUCT &drawInfo)
Definition window.cpp:1715
HMENU GetMenu() const
Returns the handle to the menu of the indicated window.
Definition window.h:3244
TResult HandleMessage(TMsgId, TParam1=0, TParam2=0)
Dispatches the given message using the response table.
Definition window.cpp:1392
bool TrackMouseEvent(uint flags=TME_HOVER|TME_LEAVE, int hoverTime=HOVER_DEFAULT)
Posts messages when the mouse pointer leaves a window or hovers over a window for a specified amount ...
Definition window.cpp:3357
void SetScrollRange(int bar, int minPos, int maxPos, bool redraw=true)
Sets the thumb position in the scroll bar.
Definition window.cpp:4142
void EvLButtonDown(uint modKeys, const TPoint &point)
Response method for an incoming WM_LBUTTONDOWN message.
Definition window.cpp:2101
bool ModifyStyle(uint32 offBits, uint32 onBits, uint swpFlags=0)
Modifies the style bits of the window.
Definition window.cpp:3591
virtual bool IdleAction(long idleCount)
Called when no messages are waiting to be processed, IdleAction performs idle processing as long as t...
Definition window.cpp:671
int GetUpdateRgn(TRegion &rgn, bool erase=true) const
Copies a window's update region into a region specified by region.
Definition window.cpp:4250
void SethAccel(HACCEL)
Definition window.cpp:4394
void SetScrollPage(int bar, int page, bool redraw=true)
Sets the page property (SCROLLINFO::nPage) of the given scroll bar.
Definition window.cpp:4170
void SetScroller(TScroller *scroller)
Sets the scroller object for this window.
Definition window.cpp:788
void SubclassWindowFunction()
Installs the instance thunk as the WindowProc and saves the old window function in DefaultProc.
Definition window.cpp:2720
HCURSOR LoadCursor(TResId id) const
Definition window.h:612
uint32 GetStyle() const
Gets the style bits of the underlying window or the 'Style' member of the attribute structure associa...
Definition window.cpp:3558
TResult ForwardMessage(HWND handle, bool send=true)
Forwards the window's current message.
Definition window.cpp:3302
TResult DefaultProcessing()
Handles default processing of events, which includes continued processing of menu/accelerators comman...
Definition window.cpp:852
uint GetDlgItemInt(int childId, bool *translated=0, bool isSigned=true) const
Translates the text of a specified control into an integer value and returns it.
Definition window.cpp:3504
TRect GetClientRect() const
Gets the coordinates of the window's client area (the area in a window you can use for drawing).
Definition window.h:2217
int GetDlgCtrlID() const
Returns the ID of the control.
Definition window.h:3097
void EvMouseHWheel(uint modKeys, int zDelta, const TPoint &point)
Event handler for WM_MOUSEHWHEEL.
Definition window.cpp:1821
void SetWindowText(LPCTSTR str)
Sets the window's text to the given string (by copying).
Definition window.h:2669
bool CreateChildren()
Creates the child windows in the child list whose auto-create flags (with wfAutoCreate mask) are set.
Definition window.cpp:2995
void EvNCDestroy()
Responds to an incoming WM_NCDESTROY message, the last message sent to an MS-Windows interface elemen...
Definition window.cpp:2871
bool GetScrollInfo(int bar, SCROLLINFO *scrollInfo) const
Retrieves the properties of the given scroll bar.
Definition window.cpp:4038
virtual TResult EvCommand(uint id, HWND hWndCtl, uint notifyCode)
WindowProc calls EvCommand to handle WM_COMMAND messages.
Definition window.cpp:999
virtual bool CanClose()
Use this function to determine if it is okay to close a window.
Definition window.cpp:2795
uint32 SetStyle(uint32 style)
Sets the style bits of the underlying window or the 'Style' member of the attribute structure associa...
Definition window.cpp:3567
void ClearFlag(uint mask)
Clears the specified TWindow wfXxxx constant flags (for example wfAlias, wfTransfer,...
Definition window.h:1790
void DetachHandle()
Definition window.cpp:2939
virtual void TransferData(TTransferDirection direction)
Transfers data between the TWindow's data buffer and the child windows in its ChildList (data is not ...
Definition window.cpp:2691
bool IsZoomed() const
Returns true if window is zoomed or maximized.
Definition window.h:2617
virtual bool Register()
Registers the Windows registration class of this window, if this window is not already registered.
Definition window.cpp:2749
virtual TResult EvNotify(uint id, TNotify &notifyInfo)
Handles WM_NOTIFY and subdispatch messages from child controls.
Definition window.cpp:1075
virtual bool HoldFocusHWnd(HWND hLose, HWND hGain)
Responds to a request by a child window to hold its HWND when it is losing focus.
Definition window.cpp:1601
void EvChildInvalid(HWND hWnd)
Handle message posted to us by a control needing assistance in dealing with invalid inputs.
Definition window.cpp:2917
void ScreenToClient(TPoint &point) const
Uses the screen coordinates specified in point to calculate the client window's coordinates and then ...
Definition window.h:2192
TWindow * Next()
Returns a pointer to the next sibling window in the window's sibling list.
Definition window.h:1755
int GetDlgItemText(int childId, TCHAR *text, int maxValue) const
Retrieves the text of a control specified by childId.
Definition window.h:3133
bool CancelMouseEvent(uint flags=TME_HOVER|TME_LEAVE)
Encapsulates a call to TrackMouseEvent, passing the TME_CANCEL flag.
Definition window.cpp:3368
void EvSysColorChange()
Respond to WM_SYSCOLORCHANGE by broadcasting it to all children.
Definition window.cpp:696
virtual bool ShowWindow(int cmdShow)
Displays this TWindow in a given state.
Definition window.cpp:3713
int MessageBox(LPCTSTR text, LPCTSTR caption=0, uint flags=MB_OK) const
Creates and displays a message box that contains a message (text), a title (caption),...
Definition window.cpp:4284
int GetScrollPos(int bar) const
Returns the thumb position in the scroll bar.
Definition window.cpp:4080
TResult SendMessage(TMsgId, TParam1=0, TParam2=0) const
Sends a message (msg) to a specified window or windows.
Definition window.cpp:3288
int SetScrollPos(int bar, int pos, bool redraw=true)
Sets the thumb position in the scroll bar.
Definition window.cpp:4092
virtual void SetupWindow()
Performs setup following creation of an associated MS-Windows window.
Definition window.cpp:2575
virtual void Paint(TDC &dc, bool erase, TRect &rect)
Repaints the client area (the area you can use for drawing) of a window.
Definition window.cpp:2071
WNDPROC SetWindowProc(WNDPROC wndProc)
Definition window.h:2467
void EvEndSession(bool endSession, uint flags)
Provides default handling for WM_ENDSESSION.
Definition window.cpp:2900
HBRUSH EvCtlColor(HDC hDC, HWND hWndChild, uint ctlType)
Handler for control color messages (WM_CTLCOLOR family).
Definition window.cpp:1983
bool ModifyExStyle(uint32 offBits, uint32 onBits, uint swpFlags=0)
Modifies the style bits of the window.
Definition window.cpp:3599
bool IsFlagSet(uint mask)
Returns the state of the bit flag in Attr.Flags whose mask is supplied.
Definition window.h:1797
bool EvQueryEndSession(uint flags)
Respond to Windows attempt to close down.
Definition window.cpp:2882
void DragAcceptFiles(bool accept)
If a window can process dropped files, DragAcceptFiles sets accept to true.
Definition window.cpp:4263
void EvSize(uint sizeType, const TSize &size)
Response method for an incoming WM_SIZE message.
Definition window.cpp:1632
uint NumChildren() const
Returns the number of child windows of the window.
Definition window.cpp:2954
void EvMeasureItem(uint ctrlId, MEASUREITEMSTRUCT &measureInfo)
Handles WM_MEASUREITEM message (for owner draw controls & menus) by forwarding message to control its...
Definition window.cpp:1740
void EnableAutoCreate()
Ensures that an associated child window interface element is created and displayed along with its par...
Definition window.h:1805
bool EvSetCursor(HWND hWndCursor, uint codeHitTest, TMsgId mouseMsg)
Response method for an incoming WM_SETCURSOR message.
Definition window.cpp:2081
TWindow * GetFirstChild()
Returns a pointer to the first child window, which is the first window created in the interface objec...
Definition window.h:1770
std::pair< int, int > TScrollRange
Definition window.h:1123
HWND THandle
TWindow encapsulates an HWND.
Definition window.h:418
void EvInitMenuPopup(HMENU hPopupMenu, uint index, bool isSysMenu)
Handle WM_INITMENUPOPUP while embeded to generate command enable messages for our server menu items.
Definition window.cpp:3809
HWND GetHandle() const
Returns the handle of the window.
Definition window.h:2020
virtual void CloseWindow(int retVal=0)
Determines if it is okay to close a window before actually closing the window.
Definition window.cpp:2809
auto ChildWithId(int id) const -> const TWindow *
Definition window.h:681
int GetWindowTextLength() const
Returns the length, in characters, of the specified window's title.
Definition window.h:2641
int GetScrollPage(int bar) const
Returns the page property (SCROLLINFO::nPage) of the given scroll bar.
Definition window.cpp:4161
TXEndSession is thrown from TWindow's handler for WM_ENDSESSION.
Definition except.h:111
TXOwl is root class of the ObjectWindows exception hierarchy.
Definition except.h:38
A nested class, TXWindow describes an exception that results from trying to create an invalid window.
Definition window.h:1647
static void Raise(TWindow *win=nullptr, uint resourceId=IDS_INVALIDWINDOW)
Creates the TXWindow exception and throws it.
Definition window.cpp:4612
int Unhandled(TModule *app, uint promptResId)
Unhandled exception.
Definition window.cpp:4582
TXWindow(TWindow *win=nullptr, uint resourceId=IDS_INVALIDWINDOW)
Constructs a TXWindow object with a default resource ID of IDS_INVALIDWINDOW.
Definition window.cpp:4557
TWindow * GetWindow() const
Definition window.cpp:4621
TXWindow * Clone()
Clone the exception object for safe-throwing.
Definition window.cpp:4592
void Throw()
Throws the exception object.
Definition window.cpp:4603
Definition of classes for CommonControl encapsulation.
#define _stprintf
Definition cygwin.h:88
#define _T(x)
Definition cygwin.h:51
#define WM_COMMAND_ENABLE
Definition dispatch.h:4103
#define WM_OWLHELPHIT
Notify Help manager with hit point.
Definition dispatch.h:4118
#define WM_CHILDINVALID
Definition dispatch.h:4104
#define DEFINE_RESPONSE_TABLE(cls)
Macro to define a response table for a class with no base response tables.
Definition eventhan.h:479
Definition of class TFrameWindow.
Definition of abstract GDI object class and derived classes.
#define _OBJ_FULLTYPENAME(obj)
Definition objstrm.h:78
TResponseTableEntry< TGeneric > TGenericTableEntry
Definition eventhan.h:144
static tstring MakeMessage(uint resId, const tstring &infoStr, TModule *module=&GetGlobalModule())
Definition except.cpp:242
virtual int Unhandled(TModule *appModule, uint promptResId)
Per-exception class unhandled-handler, will default to the per-module unhandled-handler.
Definition except.cpp:160
void CacheFlush(TCacheEntry::TId id)
Definition window.cpp:1331
void Set(int index, TCacheEntry::TId uniqueId, TMsgId, const TGenericTableEntry *entry, int delta=0)
Definition window.cpp:1339
bool Check(int index, TMsgId, TCacheEntry::TId id)
Definition window.cpp:1345
HCURSOR LoadCursor(TResId id) const
Wrapper for the Windows API.
Definition module.cpp:892
TTransferDirection
The TTransferDirection enum describes the constants that the transfer function uses to determine how ...
Definition window.h:92
@ wfDeleteOnClose
Window is condemned on EvClose.
Definition window.h:70
@ wfAlias
TWindow is an alias to a preexisting HWND.
Definition window.h:59
@ wfModalWindow
Was created via TWindow::Execute.
Definition window.h:81
@ wfPredefinedClass
Window class used belongs to a predefined Windows class and was not defined by OWL.
Definition window.h:66
@ wfFromResource
Handle comes from HWND created from resource.
Definition window.h:61
@ wfMainWindow
This frame window is the main window.
Definition window.h:63
@ wfFullyCreated
Window is fully created & not being destroyed.
Definition window.h:64
@ wfDetached
Window handle has been detached.
Definition window.h:82
@ wfPropagateIdle
Pass down IdleAction.
Definition window.h:80
@ wfTransfer
Participates in the Transfer mechanism.
Definition window.h:67
@ wfAutoCreate
Create the HWND when our parent is created.
Definition window.h:60
@ tdSizeData
Return the size of data transferred by the class.
Definition window.h:95
@ tdSetData
Set data from the buffer into the window.
Definition window.h:94
Declares THelpContext and THelpFileManager.
char * strnewdup(const char *s, size_t minAllocSize=0)
Definition memory.cpp:25
#define _A2W(lpw)
Definition memory.h:220
#define _USES_CONVERSION
Definition memory.h:217
Definition of Window Menu encapsulation class.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
EV_WM_QUERYENDSESSION
Definition window.cpp:117
EV_WM_INITMENUPOPUP
Definition framewin.cpp:35
EV_WM_SETCURSOR
Definition docking.cpp:99
EV_WM_DELETEITEM
Definition combobex.cpp:26
UINT TMsgId
Message ID type.
Definition dispatch.h:53
EV_WM_CHILDINVALID
Definition edit.cpp:86
EV_WM_NCDESTROY
Definition editview.cpp:31
owl::opstream & operator<<(owl::opstream &os, const TColor &c)
Insert the color value into a persistent output stream.
Definition color.h:498
EV_WM_HSCROLL
Definition notetab.cpp:55
TApplication * GetApplicationObject(uint pid=0)
Global function that calls GetApplication() on owl's app-dictionary.
Definition appdict.cpp:298
EV_WM_MOUSEHWHEEL
Definition window.cpp:124
EV_WM_PAINT
Definition control.cpp:28
EV_WM_KILLFOCUS
Definition edit.cpp:85
uint16 HiUint16(LRESULT r)
Definition defs.h:270
EV_WM_MOUSEWHEEL
Definition window.cpp:123
void SetCreationWindow(TWindow *w)
Definition owl.cpp:138
EV_WM_CREATE
Definition window.cpp:113
unsigned long uint32
Definition number.h:34
TWindow * GetWindowPtr(HWND, const TApplication *)
Raw function to retrieve a TWindow pointer given an HWND from the a given app, or any app (app==0).
Definition window.cpp:1557
EV_WM_CONTEXTMENU
Definition window.cpp:121
char tchar
Definition defs.h:77
void InUse(const T &arg)
Handy utility to avoid compiler warnings about unused parameters.
Definition defs.h:299
LPARAM TParam2
Second parameter type.
Definition dispatch.h:55
EV_WM_SETFONT
Definition glyphbtn.cpp:309
tstring CopyText(int size, TGetText get_text)
Copies text from a C-string (null-terminated character array) into a string object,...
Definition defs.h:317
EV_WM_MOVE
Definition window.cpp:88
uint16 LoUint16(LRESULT r)
Definition defs.h:264
TModule * Module
Definition global.cpp:34
OWL_DIAGINFO
Definition animctrl.cpp:14
TParam1 MkParam1(uint lo, uint hi)
Definition dispatch.h:68
END_RESPONSE_TABLE
Definition button.cpp:26
LRESULT TResult
Result type.
Definition dispatch.h:52
unsigned short uint16
Definition number.h:33
EV_WM_COMPAREITEM
Definition combobex.cpp:25
std::string tstring
Definition defs.h:79
EV_WM_DESTROY
Definition clipview.cpp:22
EV_WM_VSCROLL
Definition scrollba.cpp:18
unsigned int uint
Definition number.h:25
const unsigned int IDW_FIRSTMDICHILD
child window IDs, 32 max to 32032
Definition framewin.h:29
EV_WM_ENDSESSION
Definition window.cpp:118
EV_WM_DRAWITEM
Definition combobex.cpp:27
EV_WM_ENTERIDLE
Definition decframe.cpp:32
EV_WM_LBUTTONDOWN
Definition checklst.cpp:195
EV_WM_SYSCOLORCHANGE
Definition gadgetwi.cpp:53
EV_WM_ERASEBKGND
Definition docking.cpp:965
TDrawItem * ItemData2DrawItem(ULONG_PTR data)
Handles WM_DRAWITEM message (for owner draw controls & menus) by forwarding message to control itself...
Definition window.cpp:4464
EV_WM_SIZE
Definition decframe.cpp:34
EV_WM_MEASUREITEM
Definition combobex.cpp:28
action
Definition regexp.cpp:133
TWindow * GetCreationWindow()
Definition owl.cpp:128
void DoEnableAutoCreate(TWindow *win, void *)
A TActionFunc defined in window.cpp.
Definition window.cpp:2141
EV_WM_CLOSE
Definition commdial.cpp:23
General definitions used by all ObjectWindows programs.
#define OWL_INI
Definition defs.h:170
#define _OWLFUNC(p)
Definition defs.h:341
#define _OWLDATA(p)
Definition defs.h:340
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
General Registry access & registration implementation TRegKey, TRegValue, TRegKeyIterator,...
Definition of class TScroller.
Definitions of Win95 Shell Clases: TShellItem, TShellItemIterator, TPidl, TShellMalloc.
Current event structure for windows events.
Definition applicat.h:113
TResId Menu
Contains the resource ID for the menu associated with this window.
Definition window.h:346
LPVOID Param
Contains a value that is passed to Windows when the window is created.
Definition window.h:357
int X
horizontal position of top left corenr of the window
Definition window.h:339
int W
width of the window
Definition window.h:341
int H
height of the window
Definition window.h:342
int Y
vertical position of top left corenr of the window
Definition window.h:340
int Id
Contains the identifier of the child window.
Definition window.h:351
uint32 Style
Contains the values that define the style, shape, and size of your window.
Definition window.h:331
uint32 ExStyle
Contains the extended style values of your window.
Definition window.h:337
TResId AccelTable
Holds the resource ID for the window's accelerator table.
Definition window.h:360
Definition of the TTooltip class and helper objects.
#define TYPE_UNIQUE_ID(t)
Definition window.cpp:70
bool gBatchMode
Definition window.cpp:72
Base window class TWindow definition, including HWND encapsulation.
#define EV_WM_CTLCOLORLISTBOX(method)
Definition windowev.h:261
#define EV_WM_CTLCOLORSCROLLBAR(method)
Definition windowev.h:273
#define EV_WM_CTLCOLORBTN(method)
Definition windowev.h:258
#define EV_WM_CTLCOLORDLG(method)
Definition windowev.h:260
#define EV_WM_CTLCOLORSTATIC(method)
Definition windowev.h:274
#define EV_WM_CTLCOLOREDIT(method)
Definition windowev.h:259
#define WS_EX_APPWINDOW
Definition wsysinc.h:63