OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
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