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
dialog.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 class TDialog. TDialogs are the base for any type of
7/// modal or modeless window that loads itself from resource.
8//----------------------------------------------------------------------------
9#include <owl/pch.h>
10#include <owl/dialog.h>
11#include <owl/applicat.h>
12#include <owl/commctrl.h>
13#include <owl/appdict.h>
14#include <string.h>
15
16#if defined(OWL_SUPPORT_BWCC)
17# include <owl/private/bwcc.h>
18#endif
19
20#include <owl/winres.rh> // Defines RT_DLGINIT etc.
21
22namespace owl {
23
24/// \class TDialog
25/// Typically used to obtain information from a user, a dialog box is a window
26/// inside of which other controls such as buttons and scroll bars can appear.
27/// Unlike actual child windows which can only be displayed in the parent window's
28/// client area, dialog boxes can be moved anywhere on the screen. TDialog objects
29/// represent both modal and modeless dialog box interface elements. (A modal dialog
30/// box disables operations in its parent window while it is open, and, thus, lets
31/// you function in only one window "mode.")
32///
33/// A TDialog object has a corresponding resource definition that describes the
34/// placement and appearance of its controls. The identifier of this resource
35/// definition is supplied to the constructor of the TDialog object. A TDialog
36/// object is associated with a modal interface element by calling its Execute
37/// member function and with a modeless interface element by calling its Create
38/// member function.
39///
40/// You can use TDialog to build an application that uses a dialog as its main
41/// window by constructing your dialog as a TDialog and passing it as the client of
42/// a TFrameWindow. Your code might look something like this:
43/// \code
44/// SetMainWindow(new TFrameWindow(0, "title" new TDialog(0, IDD_MYDIALOG)));
45/// \endcode
46/// TDialog is a streamable class.
47///
48/// ObjectWindows also encapsulates common dialog boxes that let the user select
49/// font, file name, color, print options, and so on. TCommonDialog is the parent
50/// class for this group of common dialog box classes.
51
52
54DIAG_DECLARE_GROUP(OwlMsg); // diagnostic group for message tracing
55DIAG_DECLARE_GROUP(OwlWin); // diagnostic group for windows
56
57#define dfTmplMask 0x0f0000 // template mask
58#define dfTmplDelMask 0x0a0000 // delete mask
59
60//
61// Global message id for GetWindowPtr call defined in owl.cpp
62//
64
65//----------------------------------------------------------------------------
66
67//
68// Public so derived classes can create // !CQ make a static, protected member?
69//
70
71//JJH
72#if defined(WINELIB)
73static
74#endif
76
84 EV_COMMAND(IDCANCEL, CmCancel),
86
87
88//
89/// Constructor for a TDialog object
90//
91/// Takes an TResId for its template name or numeric Id
92//
93/// Invokes a TWindow constructor, passing parent and module, and calls
94/// DisableAutoCreate to prevent TDialog from being automatically created and
95/// displayed along with its parent. TDialog then initializes the caption to 0 and sets
96/// TDialogAttr.Name using the dialog box's integer or string resource
97/// identifier which must correspond to a dialog resource definition in the resource
98/// file. Note that resId may be 0, e.g. when TDialog encapsulates a common dialog.
99///
100/// Finally, it initializes TDialogAttr.Param to 0 and clear the flag dfIsModal, and
101/// if OWL5_COMPAT is defined IsModal is set to false.
102//
104{
105 // Initialize virtual base, in case the derived-most used default ctor
106 //
107 Init(parent, nullptr, module);
108
109 DialogAttr.Name = resId.IsString() ? strnewdup(resId) : const_cast<LPTSTR>(static_cast<LPCTSTR>(resId));
110}
111
112
113//
114/// Takes an pointer to dialog template
115//
116/// Invokes a TWindow constructor, passing parent and module, and calls
117/// DisableAutoCreate to prevent TDialog from being automatically created and
118/// displayed along with its parent. TDialog then initializes the caption to 0 and sets
119/// TDialogAttr.Name using DLGTEMPLATE*.
120///
121/// Finally, it initializes TDialogAttr.Param to 0 and clear the flag dfIsModal, and
122/// if OWL5_COMPAT is defined IsModal is set to false.
123//
125{
126 Init(parent, nullptr, module);
127
128 DialogAttr.Name = reinterpret_cast<LPTSTR>(const_cast<DLGTEMPLATE*>(&dlgTemplate));
129 SetFlag(del == AutoDelete ? dfDeleteTemplate : dfNoDeleteTemplate);
130}
131
132//
133/// Invokes a TWindow constructor, passing parent and module, and calls
134/// DisableAutoCreate to prevent TDialog from being automatically created and
135/// displayed along with its parent. TDialog then initializes the caption to 0 and sets
136/// TDialogAttr.Name using DLGTEMPLATE*.
137///
138/// Finally, it initializes TDialogAttr.Param to 0 and clear the flag dfIsModal, and
139/// if OWL5_COMPAT is defined IsModal is set to false.
140//
142{
144
145 Init(parent, nullptr, module);
146
147 DialogAttr.Name = reinterpret_cast<LPTSTR>(GlobalLock(hTemplate));
148 SetFlag(del == AutoDelete ? dfDeleteHandle : dfNoDeleteHandle);
149}
150
151
152//
153/// Common initialization in constructoe
154//
155void
156TDialog::Init(TWindow* parent, LPCTSTR /*title*/, TModule* module)
157{
158#if defined(OWL5_COMPAT)
159 IsModal = false;
160#endif
161 // Initialize virtual base, in case the derived-most used default ctor
162 //
163 TWindow::Init(parent, nullptr, module);
164
166
167 // NB! Previously (<= 6.30) TWindow::Title was here set to 0x0000FFFF as a flag.
168 // This "don't-change" flag was then detected in SetCaption to disable title updates.
169 // It seems the only reason for this was to avoid that the SetCaption call in SetupWindow
170 // overwrote the title of the window loaded from the resource.
171 //
172 // Now, the caption is simply set to 0 here. We use the flag wfFromResource to detect that
173 // we need to sync the caption from the loaded resource later (see SetupWindow).
174
177 DialogAttr.Param = 0;
178 DialogAttr.Name = nullptr;
179}
180
181//
182/// Destructor for a TDialog
183//
184/// If DialogAttr.Name is a string and not an integer resource identifier, this destructor
185/// frees memory allocated to DialogAttr.Name, which holds the name of the dialog box.
186//
188{
189 if(!IsFlagSet(dfTmplMask)){
191 delete[] DialogAttr.Name;
192 }
193 else if(IsFlagSet(dfTmplDelMask))
194 {
195 if(IsFlagSet(dfDeleteHandle)) // Is DialogAttr.Name a handle to memory that should be deleted?
197 else if(IsFlagSet(dfNoDeleteHandle)) // Is DialogAttr.Name a handle to memory that should not be deleted?
198 ::GlobalUnlock(::GlobalHandle(DialogAttr.Name)); // Just unlock it then.
199 }
200
201 // If DlgCreationWindow still points to this object, zero it, as the object is no longer valid
202 if (DlgCreationWindow == this)
203 {
204 DlgCreationWindow = nullptr;
205 }
206}
207
208//
209/// Preprocess posted messages to provide various accelerator translations.
210//
211/// Overrides the virtual function defined by TWindow in order to perform
212/// preprocessing of window messages. If the child window has requested keyboard
213/// navigation, PreProcessMsg handles any accelerator key messages and then
214/// processes any other keyboard messages.
215//
216bool
218{
219 // Processed any accelerators associated with this window
220 //
222 return true;
223
224 // See if we are in an mdi child, & try mdi accelerator translation if so
225 //
228 if ((child = GetParentH()) != nullptr &&
229 (client = ::GetParent(child)) != nullptr &&
230 child == reinterpret_cast<THandle>(::SendMessage(client, WM_MDIGETACTIVE, 0, 0)) &&
232 return true;
233
234 // Do dialog accelerator translation last, since it tends to eat other
235 // accelerators
236 //
237 return ::IsDialogMessage(GetHandle(), &msg);
238}
239
240//
241/// Overrides the virtual function defined in TWindow and returns the name of the
242/// dialog box's default Windows class, which must be used for a modal dialog box.
243/// For a modeless dialog box, GetWindowClassName returns the name of the default TWindow.
244//
246{
247#if defined(OWL_SUPPORT_BWCC)
248 if (GetApplication()->BWCCEnabled())
250 else
251#endif
253}
254
255//
256/// Overrides the virtual function defined in TWindow. Fills WndClass with TDialog
257/// registration attributes obtained from an existing TDialog window
258///
259/// If the class style is registered with CS_GLOBALCLASS, you must unregister the
260/// class style. You can do this by turning off the style bit. For example:
261/// \code
262/// {
263/// baseclass::GetWindowClass(wndClass);
264/// ....
265/// WndClass.style &= ~CS_GLOBALCLASS:
266/// ...
267/// }
268/// \endcode
269//
270void
272{
273
274#if defined(OWL_SUPPORT_BWCC)
275
276 const auto a = GetApplication(); CHECK(a);
277 const auto b = a->BWCCEnabled();
278 if (b)
279 a->GetBWCCModule()->Register(*GetModule());
281
282#else
283
284 const auto dlgClass = TWindowClassName{WC_DIALOG};
285
286#endif
287
288 if (!TUser::GetClassInfo(nullptr, dlgClass.GetPointerRepresentation(), &wndClass))
290
291 wndClass.lpszClassName = GetWindowClassName().GetPointerRepresentation();
292 wndClass.hInstance = *GetModule(); // !CQ Win32 only? (B50.26561)
293}
294
295//
296/// Handler for WM_PAINT. Rerout this message back to the underlying dialog to
297/// keep TWindow::EvPaint from eating it.
298//
299/// EvPaint calls TWindow's general-purpose default processing function,
300/// DefaultProcessing, for Windows-supplied painting.
301//
302void
307
308//
309/// Return the default Id.
310/// High word must be DC_HASDEFID.
311//
312/// Calls the DefaultProcessing() function. Returns the result.
313//
314uint
316{
317 return static_cast<uint>(DefaultProcessing());
318}
319
320//
321/// Set the pushbutton with identifier id the default button for the dialog.
322///
323/// Calls the DefaultProcessing function. Returns the result (type cast to boolean).
324//
325bool
327{
328 return static_cast<bool>(DefaultProcessing());
329}
330
331//
332/// Reposition the dialog so that it fits within the desktop area
333//
334void
339
340//
341/// The default dialog function. Handles the two mesages, WM_INITDIALOG and
342/// WM_SETFONT that may be passed to us without sending, or sent before we get
343/// a chance to thunk DIALOG's window proc.
344//
345/// EvInitDialog() is called as a virtual function, while EvSetFont() is dispatched
346/// to.
347//
348/// To process messages within the dialog function, your application must override
349/// this function. DialogFunction returns true if the message is handled and false
350/// if the message is not handled.
351//
354{
355 TRACEX(OwlMsg, 2, TMsgName(msg) << _T("(DlgFcn)=> ") << *this);
356
357 switch (msg) {
358
359 // 'Dispatch' WM_INITDIALOG by making a virtual call--no response table
360 // used. This is not generally overriden, and only arrives once.
361 //
362 case WM_INITDIALOG:
363 return EvInitDialog(reinterpret_cast<THandle>(param1));
364
365 // Dispatch WM_SETFONT only for the first, non-sent occurance. Subsequent
366 // WM_SETFONTs will be dispatched normally in TWindow.
367 //
368 case WM_SETFONT:
369 {
370 struct TEventGuard
371 {
372 TCurrentEvent& Current;
373 TCurrentEvent Previous;
374
376 : Current{ce}, Previous{ce}
377 {
378 Current.Win = win;
379 Current.Message = msg;
380 Current.Param1 = param1;
381 Current.Param2 = param2;
382 }
383
384 ~TEventGuard() { Current = Previous; }
385
386 auto IsRecursive()
387 {
388 // Event handlers may call TWindow::DefaultProcessing, which may cause a recursive call.
389 // We assume this is the case if the current event matches the previous.
390 //
391 return Current.Win == Previous.Win &&
392 Current.Message == Previous.Message &&
393 Current.Param1 == Previous.Param1 &&
394 Current.Param2 == Previous.Param2;
395 }
396 }
397 event{GetCurrentEvent(), this, msg, param1, param2};
398
399 auto wasHandled = TResult{FALSE};
400 if (!IsFlagSet(wfFullyCreated) && !event.IsRecursive())
401 {
402 auto eventInfo = TEventInfo{msg};
403 if (Find(eventInfo))
404 {
407 }
408 }
409 return wasHandled;
410 }
411
412#if defined(OWL_SUPPORT_CTL3D)
413 // Catch these few messages here & forward to the ctrl3d dll if it is
414 // loaded and enabled.
415 //
416 case WM_SETTEXT:
417 case WM_NCPAINT:
418 case WM_NCACTIVATE:
419 if (GetApplication()->Ctl3dEnabled()) {
422 }
423 break;
424#endif
425 }
426 return false; // Not handled
427}
428
429//
430/// Handles messages that come from the window procedure of dialogs (WC_DIALOG's
431/// wndProc). If DlgCreationWindow is not 0, then msg is destined for
432/// DlgCreationWindow. When StdDlgProc first receives a message, it checks to see if
433/// it needs to associate the global C++ variable DlgCreationWindow with the one
434/// passed in HWND. If it needs to do that, it will then subclass the window
435/// procedure. It calls the virtual DialogFunction() to handle specific messages,
436/// mostly for the startup sequence.
437/// Any exception within this function is suspended by TApplication::SuspendThrow.
438//
441{
442 try
443 {
444 // Retrieve the TDialog pointer.
445 //
446 if (msg == GetWindowPtrMsgId) return false;
447 TDialog* dlg = dynamic_cast<TDialog*>(owl::GetWindowPtr(hDlg));
448 if (DlgCreationWindow && !dlg && msg != WM_CANCELMODE && msg != WM_ENABLE)
449 {
450 dlg = DlgCreationWindow;
451 dlg->SetHandle(hDlg);
453 DlgCreationWindow = nullptr;
454 }
455 if (!dlg) return false;
456
457 // Dispatch the message to the DialogFunction virtual function.
458 //
459 return dlg->DialogFunction(msg, param1, param2);
460 }
461 catch (...)
462 {
463 TRACEX(OwlWin, 0, _T("TDialog::StdDlgProc: Suspending unhandled exception for message: ") << msg);
464
465 OWLGetAppDictionary().GetApplication()->SuspendThrow(std::current_exception());
466 }
467
468 return false; // If we get here, an error occurred.
469}
470
471//
472/// Register all the dialog's child objects (for custom control support)
473//
474void
476{
477 for (auto& w : GetChildren())
478 if (!w.Register())
479 throw TXWindow(this, IDS_CLASSREGISTERFAIL);
480}
481
482//
483/// Creates a modeless dialog box interface element associated with the TDialog
484/// object. Registers all the dialog's child windows for custom control support.
485/// Calls PerformCreate to perform the actual creation of the dialog box. Create
486/// returns true if successful. If unsuccessful, Create throws a TXInvalidWindow
487/// exception.
488//
489bool
491{
492 PRECONDITION(GetHandle() == 0);
493
494#if defined(OWL5_COMPAT)
495 IsModal = false;
496#endif
497 ClearFlag(dfIsModal);
498
499 if (!Register())
501
502 DlgCreationWindow = this;
504
505 // Register all the dialog's child objects (for custom control support)
506 //
508
509 CHECK(!GetHandle()); // Ensure handle is NULL in case of exceptions.
510
511 // In the new API, PerformCreate takes no arguments.
512 // Also PerformCreate now returns the handle instead of calling SetHandle.
513 //
516 WARNX(OwlWin, !GetHandle(), 0, _T("TDialog::Create failed"));
517 if (!GetHandle())
519
520 GetHWndState();
521 return true;
522}
523
524//
525/// Called from Create to perform the final step in creating an Windows interface
526/// element to be associated with a TWindow. Creates the dialgo using either a
527/// resource id or dialog template.
528//
529// TODO: Store the DLGTEMPLATE in a separate parameter instead of multiplexing it
530// into DialogAttr.Name and make DialogAttr.Name a TResId.
531//
534{
536 typedef const DLGTEMPLATE* TTemplate;
539 *GetModule(),
541 GetParentO() ? GetParentO()->GetHandle() : nullptr,
542 reinterpret_cast<DLGPROC>(StdDlgProc),
544 ) :
546 *GetModule(),
547 reinterpret_cast<TTemplate>(DialogAttr.Name),
548 GetParentO() ? GetParentO()->GetHandle() : nullptr,
549 reinterpret_cast<DLGPROC>(StdDlgProc),
551 );
552 return h;
553}
554
555
556//
557/// Creates and executes a modal dialog box interface element associated with the TDialog object.
558/// If the element is successfully associated, Execute does not return until the TDialog is closed.
559///
560/// Execute performs the following tasks:
561///
562/// -# Registers this dialog's window class and all of the dialog's child windows.
563/// -# Calls TDialog::DoExecute to execute the dialog box.
564///
565/// Execute returns an integer value that indicates how the user closed the modal dialog box. This
566/// will normally be IDOK or IDCANCEL, but the value may be customized by derived dialog classes.
567///
568/// If the dialog class cannot be registered (TWindow::Register returns false), or the execution of
569/// the dialog fails (TDialog::DoExecute returns -1), then Execute throws the TXWindow exception.
570///
571/// \note Derived dialog classes may need to communicate errors apart from window creation failure.
572/// The derived class may throw other exceptions, return other error codes, or set custom error
573/// states. For example, the classes TFileOpenDialog and TFileSaveDialog will set the associated
574/// TOpenSaveDialog::TData::Error state to indicate any errors, such as buffer overflow. In
575/// general, client code should be aware of any error handling defined by the derived class. Do not
576/// assume that a return value of IDOK means success.
577///
578/// For example:
579///
580/// \code
581/// TOpenSaveDialog::TData data{...};
582/// TFileOpenDialog dlg{this, data};
583/// const auto r = dlg.Execute();
584/// if (data.Error != 0)
585/// {
586/// // ...Handle error...
587/// }
588/// else if (r == IDOK)
589/// {
590/// // ...Open file...
591/// }
592/// \endcode
593//
594int
596{
597 PRECONDITION(GetHandle() == 0);
598
599#if defined(OWL5_COMPAT)
600 IsModal = true;
601#endif
602 SetFlag(dfIsModal);
603
604 if (!Register())
606
607 DlgCreationWindow = this;
608
609 // Register all the dialog's child objects (for custom control support)
610 //
612
613 int retValue = DoExecute();
615
616 // DoExecute returns -1 if it could not create the dialog box
617 //
618 if (retValue == -1)
620
621 return retValue;
622}
623
624//
625//
626/// Overriden TWindow virtual to modaly execute this dialog & return the result.
627///
628/// DoExecute is called by Execute() to perform the actual execution of a modal dialog
629/// box. If enabled Emulation of ModalDialog it calls TWindow::DoExecute().
630//
631int
633{
634 if (IsFlagSet(dfModalWindow))
635 return TWindow::DoExecute();
636
638 TWindow::THandle p = GetParent() ? GetParent()->GetHandle() : nullptr;
639 LPCDLGTEMPLATE t = reinterpret_cast<LPCDLGTEMPLATE>(DialogAttr.Name);
643 WARN(r > INT_MAX, _T("TDialog::DoExecute: EndDialog 64-bit result truncated to 32 bits."));
644 return static_cast<int>(r);
645}
646
647
648//
649/// Performs resource-directed initialization of controls. Uses the DLGINIT
650/// resource with an id matching this dialog's as structured message packets
651/// to send to controls.
652//
653/// Initializes the dialog box controls with the contents of DLGINIT, the dialog
654/// box resource identifier, which describes the appearance and location of the
655/// controls (buttons, group boxes, and so on). Returns true if successful,
656/// or no DLGINIT resource was found; otherwise returns false.
657//
658bool
660{
661 if (!DialogAttr.Name) return true; // Move along; nothing to see here.
662
663 // Try to retrieve a pointer to RT_DLGINIT resource data.
664 //
665 char* res = 0;
667 res = reinterpret_cast<char*>(DialogAttr.Name); // Should point to DLGINIT resource data.
668 else
669 {
672 if (hRes)
673 {
675 if (!hDat) return false;
676 res = static_cast<char*>(::LockResource(hDat));
677 if (!res) return false;
678 }
679 }
680 if (!res) return true; // No DLGINIT, but that's fine.
681
682 // Now pick up message packets from the DLGINIT resource and send them.
683 // A null-terminator indicates the end.
684 //
685 while (*res)
686 {
687 // Decode the message packet header (idc, msg, len).
688 //
689 WORD idc = *reinterpret_cast<WORD*>(res); res += sizeof(idc);
690 WORD msg = *reinterpret_cast<WORD*>(res); res += sizeof(msg);
691 DWORD len = *reinterpret_cast<DWORD*>(res); res += sizeof(len);
692 void* data = res;
693
694 // Send the message.
695 // Handle old MFC custom messages and the OWL DLGINIT messages specially.
696 // These messages carry ANSI strings, so we convert to wide string as needed.
697 // We check for the null-terminator to catch mal-formed strings.
698 //
699 switch (msg)
700 {
701 case 0x0401: // LB_ADDSTRING alias (data is ANSI text)
702 {
704 if (res[len - 1] != '\0') return false;
705 LPCTSTR text = _A2W(static_cast<LPCSTR>(data));
707 if (r == LB_ERR || r == LB_ERRSPACE) return false;
708 break;
709 }
710 case 0x0403: // CB_ADDSTRING alias (data is ANSI text)
711 {
713 if (res[len - 1] != '\0') return false;
714 LPCTSTR text = _A2W(static_cast<LPCSTR>(data));
716 if (r == CB_ERR || r == CB_ERRSPACE) return false;
717 break;
718 }
719 case 0x1234: // CBEM_INSERTSTRING alias (data is ANSI text)
720 {
722 if (res[len - 1] != '\0') return false;
723 COMBOBOXEXITEM item;
724 item.mask = CBEIF_TEXT;
725 item.iItem = -1;
726 item.pszText = _A2W(static_cast<LPSTR>(data));
728 if (r == -1) return false;
729 break;
730 }
731 case OWL_DLGINIT_COMMAND: // TODO: Move the code in this block to its own function.
732 {
733 // There should be no data with this message.
734 //
735 if (len != 0)
736 {
737 TRACE(_T("Corrupt OWL_DLGINIT_COMMAND in DLGINIT. Expected data size 0, but size was ") << len << _T(".\n"));
738 return false;
739 }
740
741 // There should be an initialisation command in the static text of the given control.
742 // We load the static text of the given control, which should be in the format "{<command>}".
743 // We then execute "<command>". Currently, the only command supported is "LoadString <id>",
744 // which specifies that we should load the title of the control from resource string <id>.
745 //
746 using namespace std;
747 IFDIAG(static const tchar error[] = _T("Either correct the command in the control title, or remove the OWL_DLGINIT_COMMAND message in DLGINIT.");)
750 in.setf(ios::skipws);
752 tstring cmd;
753 in >> openingBrace >> cmd;
754 if (!in.good() || openingBrace != _T('{'))
755 {
756 TRACE(_T("PerformDlgInit expected {<command>} in the title of control #") << idc
757 << _T(", but found \"") << title << _T("\".\n") << error);
758 return false;
759 }
760 if (cmd == _T("LoadString"))
761 {
762 int id;
764 in >> id >> closingBrace;
765 if (!in.good() || closingBrace != _T('}'))
766 {
767 TRACE(_T("PerformDlgInit found a syntax error in the title of control #") << idc
768 << _T(": \"") << title << _T("\".\n") << error);
769 return false;
770 }
771 SetDlgItemText(idc, id);
772 }
773 else
774 {
775 TRACE(_T("PerformDlgInit didn't recognize the command in the title of control #") << idc
776 << _T(": \"") << cmd << _T("\".\n") << error);
777 return false;
778 }
779 break;
780 }
781 default: // Send any other message type and hope it goes well (there is no consistent way to detect failure).
782 {
783 WARNX(OwlMsg, true, 1, _T("Default DLGINIT item handler sent message #") << msg << _T(" to control #") << idc << _T(" with no error handling."));
785 break;
786 }
787 }
788
789 // Move the pointer to the next packet.
790 //
791 res = static_cast<char*>(data) + len;
792 }
794 return true;
795}
796
797//
798/// Virtual handler for WM_INITDIALOG message, called from DialogFunction() just
799/// before the dialog box is displayed. Performs any setup
800/// required for the dialog box or its controls.
801//
802bool
804{
805 GetHWndState();
806 if (DialogAttr.Name) // Resource to initialize?
807 {
808 bool r = PerformDlgInit();
809 if (!r) TXWindow::Raise(this, IDS_DLGINITFAIL);
810 }
812 return true; // have Windows set focus to "hFocus"
813}
814
815//
816/// Overrides the virtual function defined in TWindow. Sets up the dialog box by
817/// calling SetCaption and TWindow::SetupWindow.
818///
819/// Calling SetCaption here allows us to override the dialog caption
820/// (specified in the dialog resource) by calling SetCaption prior to this point.
821/// If the caption is not yet initialised, and the dialog is created from a
822/// resource, we sync the caption with the window text title.
823//
824void
826{
827#if defined(OWL_SUPPORT_CTL3D)
828 // If this app is using Ctl3d, tell it to explicitly subclass this dialog's
829 // controls (CTL3D_ALL). Its better to do this here than enable
830 // autosubclassing since that requires a CBT hook set all the time which
831 // slows the app considerably.
832 //
834 GetApplication()->GetCtl3dModule()->SubclassDlg(*this, 0xFFFF);
835#endif
836
840 else
842}
843
844//
845/// Overrides the virtual function defined by TWindow and conditionally shuts down
846/// the dialog box. If the dialog box is modeless, it calls TWindow::CloseWindow(), passing retValue.
847///
848/// If the dialog box is modal, it calls CanClose(). If CanClose() returns true,
849/// CloseWindow() calls TransferData() to transfer dialog box data, and shuts down, passing retValue.
850/// \note The default value of retValue is IDCANCEL.
851//
852void
854{
855 if (IsFlagSet(dfIsModal))
856 {
857 try
858 {
859 if (CanClose())
860 {
863 }
864 }
865 catch (...)
866 {
867 // Jogy - an exception throw in either CacClose() or TransferData() can leave the dialog and it's message loop
868 // hanging around, leaving the application in an unusable state. To avoid this, call unconditionally Destroy,
869 // and then rethrow the exception to a higher-level handler
871 throw;
872 }
873 }
874 else
876}
877
878//
879/// Destroys the interface element associated with the TDialog object. If the
880/// element is a modeless dialog box or enabled Emulation of ModlaDialog , Destroy
881/// calls TWindow::Destroy. If the element is a modal dialog box, Destroy calls
882/// EnableAutoCreate on all child windows. Then Destroy calls the Windows function
883/// ::EndDialog, passing retValue as the value returned to indicate the result of
884/// the dialog's execution. The default retValue is IDCANCEL.
885//
886void
888{
889 if (!IsFlagSet(dfModalWindow) && IsFlagSet(dfIsModal) && GetHandle())
890 {
891 for (auto& w : GetChildren())
892 if (w.GetHandle())
893 w.EnableAutoCreate();
895 }
896 else
898}
899
900
901// Section is empty. It used to be occupied by a SetCaption override, that is no
902// longer needed.
903
904
905//
906/// Responds to a click on the dialog box's OK button with the identifier IDOK.
907/// Calls CloseWindow, passing IDOK.
908//
909void
911{
913
914 if (!IsFlagSet(dfIsModal) && !GetHandle() && IsFlagSet(wfDeleteOnClose))
915 GetApplication()->Condemn(this);
916}
917
918//
919/// Responds to an incoming notification message from a button with
920/// an Id equal to IDCANCEL. Unconditionally destroys the window.
921//
922void
924{
925 EvClose();
926}
927
928//
929/// Message response function for WM_CLOSE by unconditionally closing
930/// the window.
931//
932void
934{
935 if (IsFlagSet(wfAlias))
936 DefaultProcessing();//if this line is missing, when subclassing dialogs, (e.g. messagebox), they do not close
937 else
938 {
940
941 if (!IsFlagSet(dfIsModal) && !GetHandle() && IsFlagSet(wfDeleteOnClose))
942 GetApplication()->Condemn(this);
943 }
944}
945
946
947//
948/// Constructor. Initializes the base class.
949//
955
956//
957/// Enables/disables the control.
958//
959void
961{
962 if(ToBool(::IsWindowEnabled(GetReceiver())) != enable)
963 ::EnableWindow(GetReceiver(), enable);
965}
966
967//
968/// Set the text of the control
969//
970void
972{
974 ::GetWindowText(GetReceiver(),buffer,MAX_PATH);
975 if(_tcscmp(buffer, text) != 0)
976 ::SetWindowText(GetReceiver(), text);
977}
978
979//
980/// Use with only buttons!
981//
982void
984{
985 if(::SendMessage(GetReceiver(), BM_GETCHECK,0,0) != check)
986 ::SendMessage(GetReceiver(), BM_SETCHECK, check, 0);
987}
988
989
990//
991/// If idleCount is 0, iterates over each child control and routes the command
992/// enabler. Does not rely on an OWL interface object to work. Returns false.
993//
994bool
996{
998
999 if (idleCount == 0) {
1001 while (::IsWindow(child)) {
1002 int id = ::GetWindowLong(child, GWL_ID);
1004 RouteCommandEnable(*this, ce);
1006 }
1007 }
1008 return false;
1009}
1010
1011//
1012/// Returns the rect, specified in screen coordinates, corresponding to the given rect, specified
1013/// in dialog coordinates.
1014/// Throws TXOWl on failure.
1015//
1017{
1018 auto rScreen = rDialog;
1019 auto r = MapDialogRect(rScreen);
1020 if (!r) throw TXOwl{_T("TDialog::MapDialogRectToScreen failed")};
1021 return rScreen;
1022}
1023
1024//
1025/// Sets focus within a dialog to a specific control.
1026//
1027void
1033
1034
1035//
1036/// Sets the focus to either the previous control with WS_TABSTOP, or the next
1037/// control with WS_TABSTOP.
1038//
1039void
1044
1045
1046
1048
1049#if OWL_PERSISTENT_STREAMS
1050
1051//
1052// Reads an instance of TDialog from the passed ipstream
1053//
1054void*
1055TDialog::Streamer::Read(ipstream& is, uint32 /*version*/) const
1056{
1057 ReadBaseObject((TWindow*)GetObject(), is);
1058
1059 is >> (TResId&)GetObject()->DialogAttr.Name;
1060
1061 bool isModal;
1062 is >> isModal;
1063 isModal ? GetObject()->SetFlag(dfIsModal) : GetObject()->ClearFlag(dfIsModal);
1064
1065 return GetObject();
1066}
1067
1068//
1069// Writes the TDialog to the passed opstream
1070//
1071void
1072TDialog::Streamer::Write(opstream& os) const
1073{
1074 WriteBaseObject((TWindow*)GetObject(), os);
1075
1076 os << TResId(GetObject()->DialogAttr.Name);
1077 os << (bool)GetObject()->IsFlagSet(dfIsModal);
1078}
1079#endif
1080
1081} // OWL namespace
Definition of class TAppDictionary.
Definition of class TApplication.
Legacy support for Borland Windows Custom Controls (BWCC)
#define CHECK(condition)
Definition checks.h:239
#define WARNX(group, condition, level, message)
Definition checks.h:277
#define TRACE(message)
Definition checks.h:255
#define WARN(condition, message)
Definition checks.h:273
#define PRECONDITION(condition)
Definition checks.h:227
#define DIAG_DECLARE_GROUP(group)
Definition checks.h:404
#define IFDIAG(a)
Definition checks.h:418
#define TRACEX(group, level, message)
Definition checks.h:263
TApplication * GetApplication(uint pid=0)
Looks up and returns the application associated with a given process ID.
Definition appdict.cpp:192
void ResumeThrow()
Rethrows the suspended exception stored by a previous call to SuspendThrow.
void SuspendThrow(std::exception_ptr)
Stores the given exception so that it can be rethrown later by a call to ResumeThrow.
void Condemn(TWindow *win)
Condemns the given window to be deleted the at the next available safe time.
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
HWND GetReceiver() const
Returns the handle of the window that this enabler was destined for.
Definition window.h:1728
A TCommandEnabler for child controls in a dialog.
Definition dialog.h:60
void SetCheck(int check)
Use with only buttons!
Definition dialog.cpp:983
void Enable(bool enable=true)
Enables/disables the control.
Definition dialog.cpp:960
void SetText(LPCTSTR text)
Set the text of the control.
Definition dialog.cpp:971
TControlEnabler(uint id, HWND hWndReceiver=0)
Constructor. Initializes the base class.
Definition dialog.cpp:950
Typically used to obtain information from a user, a dialog box is a window inside of which other cont...
Definition dialog.h:85
void Init(TWindow *parent, LPCTSTR title, TModule *module)
Common initialization in constructor.
Definition dialog.cpp:156
void SetControlFocus(HWND hwnd)
Sets focus within a dialog to a specific control.
Definition dialog.cpp:1028
void CloseWindow(int retValue=IDCANCEL) override
Overrides the virtual function defined by TWindow and conditionally shuts down the dialog box.
Definition dialog.cpp:853
virtual bool EvInitDialog(HWND hWndFocus)
Virtual handler for WM_INITDIALOG message, called from DialogFunction()
Definition dialog.cpp:803
void GetWindowClass(WNDCLASS &) override
Overrides the virtual function defined in TWindow.
Definition dialog.cpp:271
auto Create() -> bool override
Creates a modeless dialog box interface element associated with the TDialog object.
Definition dialog.cpp:490
auto PreProcessMsg(MSG &) -> bool override
Preprocess posted messages to provide various accelerator translations.
Definition dialog.cpp:217
THow
Enumeration to be used when invoking the 'SetControlFocus' method.
Definition dialog.h:149
@ Next
Set focus to the next sibling.
Definition dialog.h:150
bool PerformDlgInit()
Initialize dialog controls with contents of DLGINIT resources, if any.
Definition dialog.cpp:659
bool SetMsgResult(TResult result)
Sets the dialog procedure message result (DWLP_MSGRESULT) and returns true.
Definition dialog.h:282
auto Execute() -> int override
Creates and executes a modal dialog box interface element associated with the TDialog object.
Definition dialog.cpp:595
void EvClose()
Message response function for WM_CLOSE by unconditionally closing the window.
Definition dialog.cpp:933
void EvReposition()
Reposition the dialog so that it fits within the desktop area.
Definition dialog.cpp:335
auto PerformCreate() -> THandle override
Called from Create to perform the final step in creating an Windows interface element to be associate...
Definition dialog.cpp:533
void CmOk()
Responds to a click on the dialog box's OK button with the identifier IDOK.
Definition dialog.cpp:910
void SetupWindow() override
Overrides the virtual function defined in TWindow.
Definition dialog.cpp:825
TDialogAttr DialogAttr
New name.
Definition dialog.h:211
uint EvGetDefId()
Return the default Id.
Definition dialog.cpp:315
~TDialog() override
Destructor for a TDialog.
Definition dialog.cpp:187
void Destroy(int retValue=IDCANCEL) override
Destroys the interface element associated with the TDialog object.
Definition dialog.cpp:887
virtual INT_PTR DialogFunction(TMsgId, TParam1, TParam2)
Override this to process messages within the dialog function.
Definition dialog.cpp:353
bool EvSetDefId(int id)
Set the pushbutton with identifier id the default button for the dialog.
Definition dialog.cpp:326
void RegisterChildObjects()
Registers WINDOW class(es) of Children.
Definition dialog.cpp:475
auto GetWindowClassName() -> TWindowClassName override
Overrides the virtual function defined in TWindow and returns the name of the dialog box's default Wi...
Definition dialog.cpp:245
void EvPaint()
Handler for WM_PAINT.
Definition dialog.cpp:303
void CmCancel()
Responds to an incoming notification message from a button with an Id equal to IDCANCEL.
Definition dialog.cpp:923
static INT_PTR CALLBACK StdDlgProc(HWND, UINT, WPARAM, LPARAM) noexcept
Callback procs for hooking TDialog to native window.
Definition dialog.cpp:440
auto DoExecute() -> int override
Overriden TWindow virtual to modaly execute this dialog & return the result.
Definition dialog.cpp:632
auto MapDialogRectToScreen(const TRect &) const -> TRect
Returns the rect, specified in screen coordinates, corresponding to the given rect,...
Definition dialog.cpp:1016
TDialog(TWindow *parent, TResId resId, TModule *module=nullptr)
Constructor for a TDialog object.
Definition dialog.cpp:103
auto IdleAction(long idleCount) -> bool override
Handle enabling and disabling of child controls.
Definition dialog.cpp:995
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
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
TRect is a mathematical class derived from tagRect.
Definition geometry.h:308
bool IsString() const
Returns true if this resource identifier encodes a string pointer.
Definition wsyscls.h:86
static BOOL GetClassInfo(HINSTANCE, LPCTSTR, LPWNDCLASS)
Definition module.cpp:1088
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
TCurrentEvent & GetCurrentEvent()
Returns the current event to be processed in the message queue.
Definition window.h:2047
void SetDlgItemText(int childId, LPCTSTR text) const
Sets the title or text of a control in a dialog box.
Definition window.h:3146
TApplication * GetApplication() const
Gets a pointer to the TApplication object associated with this.
Definition window.h:1855
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
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
virtual void Destroy(int retVal=0)
Destroys an MS-Windows element associated with the TWindow.
Definition window.cpp:2160
TWindow * GetParent() const
Retrieves the OWL object of the parent window. If none exists, returns 0.
Definition window.h:2013
virtual int DoExecute()
Do actual modal execution using the Begin/End Modal support of TApplication.
Definition window.cpp:2508
void GetWindowTextTitle()
Updates the TWindow internal caption (Title) from the current window's caption.
Definition window.cpp:3437
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
long GetWindowLong(int index) const
Retrieves information about the window depending on the value stored in index.
Definition window.h:2388
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
TWindow * GetParentO() const
Return the OWL's parent for this window.
Definition window.h:2006
TModule * GetModule() const
Returns a pointer to the module object.
Definition window.h:1841
void LoadAcceleratorTable()
Loads a handle to the window's accelerator table specified in the TWindowAttr structure (Attr....
Definition window.cpp:2307
void RouteCommandEnable(HWND hInitCmdTarget, TCommandEnabler &ce)
Walks the chain of windows from the initial target window to this window.
Definition window.cpp:1161
bool IsWindow() const
Returns true if an HWND is being used.
Definition window.h:2040
void SetCaption(LPCTSTR title)
Copies title to an allocated string pointed to by title.
Definition window.cpp:3410
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
TResult SendDlgItemMessage(int childId, TMsgId, TParam1=0, TParam2=0)
Sends a message (msg) to the control specified in childId.
Definition window.h:2092
void SubclassWindowFunction()
Installs the instance thunk as the WindowProc and saves the old window function in DefaultProc.
Definition window.cpp:2720
LPCTSTR GetCaption() const
Returns the Title member of TWindow.
Definition window.h:1900
TResult DefaultProcessing()
Handles default processing of events, which includes continued processing of menu/accelerators comman...
Definition window.cpp:852
virtual bool CanClose()
Use this function to determine if it is okay to close a window.
Definition window.cpp:2795
void ClearFlag(uint mask)
Clears the specified TWindow wfXxxx constant flags (for example wfAlias, wfTransfer,...
Definition window.h:1790
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
virtual bool Register()
Registers the Windows registration class of this window, if this window is not already registered.
Definition window.cpp:2749
int GetDlgItemText(int childId, TCHAR *text, int maxValue) const
Retrieves the text of a control specified by childId.
Definition window.h:3133
TResult SendMessage(TMsgId, TParam1=0, TParam2=0) const
Sends a message (msg) to a specified window or windows.
Definition window.cpp:3288
virtual void SetupWindow()
Performs setup following creation of an associated MS-Windows window.
Definition window.cpp:2575
bool IsFlagSet(uint mask)
Returns the state of the bit flag in Attr.Flags whose mask is supplied.
Definition window.h:1797
HWND THandle
TWindow encapsulates an HWND.
Definition window.h:418
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
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
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
Definition of classes for CommonControl encapsulation.
#define _tcscmp
Definition cygwin.h:75
#define MAX_PATH
Definition cygwin.h:98
#define _T(x)
Definition cygwin.h:51
#define dfTmplMask
Definition dialog.cpp:57
#define dfTmplDelMask
Definition dialog.cpp:58
Definition of TDialog class and TDialogAttr struct.
#define DEFINE_RESPONSE_TABLE1(cls, base)
Macro to define a response table for a class with one base.
Definition eventhan.h:492
TAutoDelete
Flag for Handle ctors to control Handle deletion in dtor.
Definition gdibase.h:70
void ReadBaseObject(Base *base, ipstream &in)
Definition objstrm.h:1159
#define IMPLEMENT_STREAMABLE1(cls, base1)
Definition objstrm.h:1725
void WriteBaseObject(Base *base, opstream &out)
Definition objstrm.h:1150
@ AutoDelete
Definition gdibase.h:70
THandle GetHandle() const
Return the instance handle of the library module represented by the TModule obect.
Definition module.h:1233
auto GetClassInfo(TWindowClassName, WNDCLASS *wndclass) const -> bool
Retrieves information about the given window class.
Definition module.h:1394
HGLOBAL LoadResource(HRSRC hRsrc) const
Wrapper for the Windows API.
Definition module.h:1352
HRSRC FindResource(TResId id, TResId type) const
Wrapper for the Windows API to find a particular resource.
Definition module.h:1308
HRSRC FindResourceEx(TResId id, TResId type, TLangId langId=LangNeutral) const
Wrapper for the Windows API to find a particular resource.
Definition module.h:1334
@ wfDeleteOnClose
Window is condemned on EvClose.
Definition window.h:70
@ wfAlias
TWindow is an alias to a preexisting HWND.
Definition window.h:59
@ wfFromResource
Handle comes from HWND created from resource.
Definition window.h:61
@ wfFullyCreated
Window is fully created & not being destroyed.
Definition window.h:64
@ tdGetData
Get data from the window into the buffer.
Definition window.h:93
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
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
EV_DM_GETDEFID
Definition dialog.cpp:80
UINT TMsgId
Message ID type.
Definition dispatch.h:53
EV_WM_PAINT
Definition control.cpp:28
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
LPARAM TParam2
Second parameter type.
Definition dispatch.h:55
bool ToBool(const T &t)
Definition defs.h:291
WPARAM TParam1
First parameter type.
Definition dispatch.h:54
EV_DM_REPOSITION
Definition dialog.cpp:82
std::istringstream tistringstream
Definition strmdefs.h:37
TAppDictionary & OWLGetAppDictionary()
Global exported TAppDictionary in Owl.
Definition appdict.cpp:35
EV_DM_SETDEFID
Definition dialog.cpp:81
OWL_DIAGINFO
Definition animctrl.cpp:14
END_RESPONSE_TABLE
Definition button.cpp:26
LRESULT TResult
Result type.
Definition dispatch.h:52
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
EV_WM_CLOSE
Definition commdial.cpp:23
#define _OWLDATA(p)
Definition defs.h:340
Definition of class TString, a flexible universal string envelope class.
Current event structure for windows events.
Definition applicat.h:113
TMsgId Message
Message ID.
Definition applicat.h:115
TWindow * Win
Window that message was sent/dispatched to.
Definition applicat.h:114
TParam1 Param1
First parameter (WPARAM)
Definition applicat.h:116
TParam2 Param2
Second parameter (LPARAM)
Definition applicat.h:117
LPARAM Param
Param is used to pass initialization data to the dialog box when it is constructed.
Definition dialog.h:49
TCHAR * Name
Name holds the identifier, which can be either a string or an integer resource identifier,...
Definition dialog.h:39
#define EV_COMMAND(id, method)
Response table entry for a menu/accelerator/push button message.
Definition windowev.h:171