OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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