home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / DIALOG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  15.3 KB  |  590 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Defines type TDialog.  This defines the basic behavior of all dialogs.
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/dialog.h>
  10. #include <owl/applicat.h>
  11. #include <string.h>
  12. #include <bwcc.h>
  13.  
  14. DIAG_DECLARE_GROUP(OwlMsg);  // diagnostic group for message tracing
  15. DIAG_DECLARE_GROUP(OwlWin);  // diagnostic group for windows
  16.  
  17. #if !defined(SECTION) || SECTION == 1
  18.  
  19. #if !defined(RT_DLGINIT)
  20. # define RT_DLGINIT       MAKEINTRESOURCE(240)
  21. #endif
  22.  
  23. extern uint _OWLDATA GetWindowPtrMsgId; // in applicat.cpp
  24.  
  25. //
  26. // Our exported dialog proc & its proc instance
  27. //
  28. bool CALLBACK __export StdDlgProc(HWND, uint, WPARAM, LPARAM);
  29. TProcInstance StdDlgProcInstance((FARPROC)StdDlgProc);
  30.  
  31. TDialog* _OWLDATA DlgCreationWindow = 0;  // public so derived classes can create
  32.  
  33. DEFINE_RESPONSE_TABLE1(TDialog, TWindow)
  34.   EV_WM_CLOSE,
  35.   EV_WM_PAINT,
  36.   EV_WM_CTLCOLOR,
  37.   EV_WM_SETFONT,
  38.   EV_COMMAND(IDOK, CmOk),
  39.   EV_COMMAND(IDCANCEL, CmCancel),
  40. END_RESPONSE_TABLE;
  41.  
  42. //
  43. // constructor for a TDialog object
  44. //
  45. // takes an TResId for its template name or numeric Id
  46. //
  47. TDialog::TDialog(TWindow* parent, TResId resId, TModule* module)
  48. {
  49.   //
  50.   // Initialize virtual base, in case the derived-most used default ctor
  51.   //
  52.   TWindow::Init(parent, 0, module);
  53.  
  54.   DisableAutoCreate();
  55.   if (HIWORD(Title))
  56.     delete [] Title;
  57.   Title = (LPSTR)MAKEINTRESOURCE(0xFFFF); // Title setting--"don't-change"
  58.  
  59.   SetFlag(wfFromResource);
  60.   ClearFlag(wfDeleteOnClose);
  61.  
  62.   Attr.Param = 0;
  63.   IsModal = false;
  64.   Attr.Name = resId.IsString() ? strnewdup(resId) : (char far*)resId;
  65. }
  66.  
  67. //
  68. // destructor for a TDialog
  69. //
  70. // ~TWindow frees the instance thunk
  71. //
  72. TDialog::~TDialog()
  73. {
  74.   if (HIWORD(Attr.Name))
  75.     delete [] Attr.Name;
  76. }
  77.  
  78. //
  79. // Preprocess posted messages to provide various accelerator translations.
  80. // Handles normal window accelerators, MDI accelerators & dialog accelerators
  81. //
  82. bool
  83. TDialog::PreProcessMsg(MSG& msg)
  84. {
  85.   // processed any accelerators associated with this window
  86.   //
  87.   if (TWindow::PreProcessMsg(msg))
  88.     return true;
  89.  
  90.   // See if we are in an mdi child, & try mdi accelerator translation if so
  91.   //
  92.   HWND child;
  93.   HWND client;
  94.   if ((child = GetParent()) != 0 &&
  95.       (client = ::GetParent(child)) != 0 &&
  96.       child == (HWND)::SendMessage(client, WM_MDIGETACTIVE, 0, 0) &&
  97.       ::TranslateMDISysAccel(client, &msg))
  98.     return true;
  99.  
  100.   // Do dialog accelerator translation last, since it tends to eat other
  101.   // accelerators
  102.   //
  103.   return ::IsDialogMessage(HWindow, &msg);
  104. }
  105.  
  106. char far*
  107. TDialog::GetClassName()
  108. {
  109.   if (GetApplication()->BWCCEnabled())
  110.     return BORDLGCLASS;
  111.   else
  112.     return (char far*)WC_DIALOG;
  113. }
  114.  
  115. void
  116. TDialog::GetWindowClass(WNDCLASS& wndClass)
  117. {
  118.   TResId dlgClass;
  119.  
  120.   if (GetApplication()->BWCCEnabled()) {
  121.     bool FAR PASCAL(*bwccRegister)(HINSTANCE);
  122.     (FARPROC)bwccRegister = GetApplication()->GetBWCCModule()->GetProcAddress("BWCCRegister");
  123.     if (bwccRegister)
  124.       (*bwccRegister)(*GetModule());
  125.  
  126.     dlgClass = BORDLGCLASS;
  127.   }
  128.   else
  129.     dlgClass = WC_DIALOG;
  130.  
  131.   if (!::GetClassInfo(0, dlgClass, &wndClass))
  132.     GetModule()->GetClassInfo(dlgClass, &wndClass);
  133.  
  134.   wndClass.lpszClassName = GetClassName();
  135. }
  136.  
  137. void
  138. TDialog::EvSetFont(HFONT /*hFont*/, bool /*redraw*/)
  139. {
  140.   if (IsFlagSet(wfFullyCreated))
  141.     DefaultProcessing();
  142. }
  143.  
  144. void
  145. TDialog::EvPaint()
  146. {
  147.   DefaultProcessing();  // don't call TWindow::EvPaint()
  148. }
  149.  
  150. //
  151. // If this app is using Ctl3d, forward the WM_CTLCOLOR message to the
  152. // ctl3d.dll since it needs to handle that & we don't let it autosubclass
  153. //
  154. HBRUSH
  155. TDialog::EvCtlColor(HDC hDC, HWND hWndChild, uint ctlType)
  156. {
  157.   if (GetApplication()->Ctl3dEnabled()) {
  158.     HBRUSH FAR PASCAL(*ctl3dCtlColorEx)(uint, WPARAM, LPARAM) = 0;
  159.     if (!ctl3dCtlColorEx)
  160.       (FARPROC)ctl3dCtlColorEx = GetApplication()->GetCtl3dModule()->
  161.                                    GetProcAddress("Ctl3dCtlColorEx");
  162.  
  163.     HBRUSH hBr = 0;
  164.     if (ctl3dCtlColorEx)
  165.       #if defined(BI_PLAT_WIN32)
  166.         hBr = ctl3dCtlColorEx(WM_CTLCOLORMSGBOX+ctlType, WPARAM(hDC), LPARAM(hWndChild));
  167.       #else
  168.         hBr = ctl3dCtlColorEx(WM_CTLCOLOR, WPARAM(hDC), MAKELPARAM(hWndChild, ctlType));
  169.       #endif
  170.  
  171.     if (hBr)
  172.       return hBr;
  173.   }
  174.   return TWindow::EvCtlColor(hDC, hWndChild, ctlType);
  175. }
  176.  
  177. //
  178. // The default dialog function. Handles the two mesages, WM_INITDIALOG and
  179. // WM_SETFONT that may be passed to us without sending, or sent before we get
  180. // a chance to thunk DIALOG's window proc.
  181. //
  182. // EvInitDialog is called as a virtual function, while EvSetFont is dispatched
  183. // to.
  184. //
  185. bool
  186. TDialog::DialogFunction(uint msg, WPARAM wParam, LPARAM lParam)
  187. {
  188.   TRACEX(OwlMsg, 2, MsgName(msg) << "(DlgFcn)=> " << *this);
  189.  
  190.   switch (msg) {
  191.  
  192.     // 'Dispatch' WM_INITDIALOG by making a virtual call--no response table
  193.     // used. This is not generally overriden, and only arrives once.
  194.     //
  195.     case WM_INITDIALOG:
  196.       return EvInitDialog((HWND)wParam);
  197.  
  198.     // Dispatch WM_SETFONT only for the first, non-sent occurance. Subsequent
  199.     // WM_SETFONTs will be dispatched normally in TWindow.
  200.     //
  201.     case WM_SETFONT:
  202.       if (!IsFlagSet(wfFullyCreated)) {
  203.         TEventInfo  eventInfo(msg);
  204.         if (Find(eventInfo))
  205.           return (bool)Dispatch(eventInfo, wParam, lParam);
  206.       }
  207.       return true;
  208.  
  209.     // Catch these few messages here & forward to the ctrl3d dll if it is
  210.     // loaded and enabled.
  211.     //
  212.     case WM_SETTEXT:
  213.     case WM_NCPAINT:
  214.     case WM_NCACTIVATE:
  215.       if (GetApplication()->Ctl3dEnabled()) {
  216.         bool FAR PASCAL(*ctl3dDlgFramePaint)(HWND, uint, WPARAM, LPARAM) = 0;
  217.         if (!ctl3dDlgFramePaint)
  218.           (FARPROC)ctl3dDlgFramePaint = GetApplication()->GetCtl3dModule()->
  219.                                           GetProcAddress("Ctl3dDlgFramePaint");
  220.         if (ctl3dDlgFramePaint) {
  221.           SetWindowLong(DWL_MSGRESULT, (*ctl3dDlgFramePaint)(HWindow, msg, wParam, lParam));
  222.           return true;
  223.         }
  224.       }
  225.       break;
  226.   }
  227.   return false;  // not handled
  228. }
  229.  
  230. //
  231. // Handles messages that comes from WC_DIALOG's wndProc
  232. // If DlgCreationWindow is not 0, then msg is destined for DlgCreationWindow.
  233. // Setup DlgCreationWindow's HWindow, subclass the WC_DIALOG class's window
  234. // function. Calls the virtual DialogFunction() to handle specific messages,
  235. // mostly for startup sequence.
  236. //
  237. bool CALLBACK __export
  238. StdDlgProc(HWND hDlg, uint msg, WPARAM wParam, LPARAM lParam)
  239. {
  240.   // Thunk on first message to a non-thunked window & thats not one sent to
  241.   // parent dialogs.
  242.   //
  243.   if (msg == GetWindowPtrMsgId) // if it gets here, we wont know how to get it
  244.     return false;
  245.  
  246.   // Get the window ptr using the global version since there is no other
  247.   // context.
  248.   // 
  249.   TWindow*  w = ::GetWindowPtr(hDlg);
  250.   TDialog*  dialog = TYPESAFE_DOWNCAST(w, TDialog);
  251.  
  252.   if (DlgCreationWindow && !dialog && msg != WM_CANCELMODE && msg != WM_ENABLE) {
  253.     DlgCreationWindow->HWindow = hDlg;
  254.  
  255.     DlgCreationWindow->SubclassWindowFunction();
  256.     dialog = DlgCreationWindow;
  257.     DlgCreationWindow = 0;
  258.   }
  259.   if (!dialog)
  260.     return false;
  261.  
  262.   // Handle all messages once thunked.
  263.   // Call the virtual DialogFunction() to handle specific messages
  264.   //
  265. #if defined(BI_PLAT_WIN32)
  266.   static bool exceptionOK =
  267.                 !(::GetVersion()&0x80000000) || (::GetVersion()&0xFF) >= 4;
  268.   if (exceptionOK)
  269.     return dialog->DialogFunction(msg, wParam, lParam);
  270. #endif
  271.   TRY {
  272.     return dialog->DialogFunction(msg, wParam, lParam);
  273.   }
  274.   CATCH( (TXOwl& x) {
  275.     w->GetApplication()->SuspendThrow(x);
  276.   })
  277.   CATCH( (xalloc& x) {
  278.     w->GetApplication()->SuspendThrow(x);
  279.   })
  280.   CATCH( (xmsg& x) {
  281.     w->GetApplication()->SuspendThrow(x);
  282.   })
  283.   CATCH( (Bad_cast) {
  284.     w->GetApplication()->SuspendThrow(TApplication::xsBadCast);
  285.   })
  286.   CATCH( (Bad_typeid) {
  287.     w->GetApplication()->SuspendThrow(TApplication::xsBadTypeid);
  288.   })
  289.   CATCH( (...) {
  290.     w->GetApplication()->SuspendThrow(TApplication::xsUnknown);
  291.   })
  292.  
  293.   // When exceptions are disabled CATCH is defined as empty, so the only code
  294.   // is the TRY block, making this return unreachable
  295.   //
  296.   #pragma warn -rch
  297.   return true;  // default value returned when exception caught
  298.   #pragma warn .rch
  299. }
  300.  
  301. static bool
  302. RegisterFails(TWindow* win, void*)
  303. {
  304.   return !win->Register();
  305. }
  306.  
  307. //
  308. // creates an MS-Windows modeless dialog and associates the modeless
  309. // dialog interface element with the TDialog
  310. //
  311. bool
  312. TDialog::Create()
  313. {
  314.   PRECONDITION(HWindow == 0);
  315.  
  316.   IsModal = false;
  317.  
  318.   if (!Register())
  319.     THROW( TXWindow(this, IDS_CLASSREGISTERFAIL) );
  320.  
  321.   DlgCreationWindow = this;
  322.  
  323.   LoadAcceleratorTable();
  324.  
  325.   //
  326.   // register all the dialog's child objects (for custom control support)
  327.   //
  328.   if (FirstThat(RegisterFails))
  329.     THROW( TWindow::TXWindow(this, IDS_CHILDREGISTERFAIL) );
  330.  
  331.   HWindow = DoCreate();
  332.   GetApplication()->ResumeThrow();
  333.   if (!HWindow)
  334.     THROW( TWindow::TXWindow(this, IDS_WINDOWCREATEFAIL) );
  335.  
  336.   GetHWndState();
  337.   return true;
  338. }
  339.  
  340. HWND
  341. TDialog::DoCreate()
  342. {
  343.   return CreateDialogParam(*GetModule(), Attr.Name, Parent? Parent->HWindow : 0,
  344.                            (DLGPROC)(FARPROC)StdDlgProcInstance, Attr.Param);
  345. }
  346.  
  347. //
  348. // creates an modal dialog and associates the modal dialog interface
  349. // element with the TDialog.  Registers all the dialog's child objects
  350. // (for custom control support).  If this registering fails, throws TXWindow
  351. // exception.  If the dialog fails to execute, throw a TXWindow exception.
  352. // Returns the return value from the dialog manager.
  353. //
  354. int
  355. TDialog::Execute()
  356. {
  357.   PRECONDITION(HWindow == 0);
  358.  
  359.   IsModal = true;
  360.  
  361.   if (!Register())
  362.     THROW( TXWindow(this, IDS_CLASSREGISTERFAIL) );
  363.  
  364.   DlgCreationWindow = this;
  365.  
  366.   //
  367.   // register all the dialog's child objects (for custom control support)
  368.   //
  369.   if (FirstThat(RegisterFails))
  370.     THROW( TXWindow(0, IDS_CHILDREGISTERFAIL) );   // unspecified child window
  371.  
  372.   int retValue = DoExecute();
  373.   GetApplication()->ResumeThrow();
  374.  
  375.   //
  376.   // -1 if the function cannot create the dialog box
  377.   //
  378.   if (retValue == -1)
  379.     THROW( TXWindow(this, IDS_WINDOWEXECUTEFAIL) );
  380.  
  381.   return retValue;
  382. }
  383.  
  384. int
  385. TDialog::DoExecute()
  386. {
  387.   return DialogBoxParam(*GetModule(), Attr.Name, Parent ? Parent->HWindow : 0,
  388.                         (DLGPROC)(FARPROC)StdDlgProcInstance, Attr.Param);
  389. }
  390.  
  391. bool
  392. TDialog::PerformDlgInit()
  393. {
  394.   int rslt = (int)SendMessage(WM_VBXINITFORM, WPARAM(HWindow), LPARAM(Attr.Name));
  395.   if (rslt)
  396.     return rslt > 0;
  397.  
  398.   bool ok = true;
  399.   if (Attr.Name) {
  400.     HRSRC hRes = GetModule()->FindResource(Attr.Name, RT_DLGINIT);
  401.     if (hRes) {
  402.       HGLOBAL hDat = GetModule()->LoadResource(hRes);
  403.       if (hDat) {
  404.         char HUGE* res = (char HUGE*)::LockResource(hDat);
  405.         if (res) {
  406.           while (ok && *res) {
  407.             uint16 idCtl = *((uint16 far*)res)++;
  408.             uint16 msg = *((uint16 far*)res)++;
  409.             uint32 len = *((uint32 far*)res)++;
  410.  
  411.             if (SendDlgItemMessage(idCtl, msg, 0, LPARAM(res)) == -1)
  412.               ok = false;
  413.             res += len;
  414.           }
  415.           #if !defined(BI_PLAT_WIN32)
  416.             ::UnlockResource(hDat);
  417.           #endif
  418.         }
  419.         #if !defined(BI_PLAT_WIN32)
  420.           ::FreeResource(hDat);
  421.         #endif
  422.         GetApplication()->ResumeThrow();
  423.       }
  424.     }
  425.   }
  426.   return ok;
  427. }
  428.  
  429. //
  430. // responds to an incoming WM_INITDIALOG message
  431. //
  432. // this message is sent after an MS-Windows dialog is created and before
  433. // the dialog is displayed
  434. //
  435. // calls SetupWindow() to perform setup for the dialog
  436. //
  437. bool
  438. TDialog::EvInitDialog(HWND /*hWndFocus*/)
  439. {
  440.   GetHWndState();
  441.   PerformDlgInit();
  442.   SetupWindow();
  443.   SetFlag(wfFullyCreated);
  444.   return true;  // have Windows set focus to "hWndFocus"
  445. }
  446.  
  447. //
  448. // sets up the dialog box by calling setting up ctl3d if enabled, then
  449. // calling SetCaption() and then TWindow::SetupWindow()
  450. //
  451. // calling SetCaption() here allows us to override the dialog caption
  452. // (specified in the dialog resource) by setting Title prior to this point
  453. //
  454. void
  455. TDialog::SetupWindow()
  456. {
  457.   //
  458.   // If this app is using Ctl3d, tell it to explicitly subclass this dialog's
  459.   // controls (CTL3D_ALL). Its better to do this here than enable
  460.   // autosubclassing since that requires a CBT hook set all the time which
  461.   // slows the app considerably.
  462.   //
  463.   if (GetApplication()->Ctl3dEnabled()) {
  464.     bool FAR PASCAL(*ctl3dSubclassDlg)(HWND, uint16) = 0;
  465.     if (!ctl3dSubclassDlg)
  466.      (FARPROC)ctl3dSubclassDlg = GetApplication()->GetCtl3dModule()->
  467.                                    GetProcAddress("Ctl3dSubclassDlg");
  468.     if (ctl3dSubclassDlg)
  469.       ctl3dSubclassDlg(*this, 0xFFFF);
  470.   }
  471.  
  472.   SetCaption(Title);
  473.   TWindow::SetupWindow();
  474. }
  475.  
  476. //
  477. // conditionally shuts down the dialog box
  478. //
  479. // if this is a modal dialog calls CanClose() and, if CanClose() returns true,
  480. // transfers its data and shuts down, passing retValue (default IDCANCEL)
  481. //
  482. // calls TWindow::CloseWindow(retValue) if this is a modeless dialog
  483. //
  484. void
  485. TDialog::CloseWindow(int retValue)
  486. {
  487.   if (IsModal) {
  488.     if (CanClose()) {
  489.       TransferData(tdGetData);
  490.       Destroy(retValue);
  491.     }
  492.   }
  493.   else {
  494.     TWindow::CloseWindow(retValue);
  495.   }
  496. }
  497.  
  498. //
  499. // destroys the MS-Windows dialog associated with the TDialog
  500. //
  501. void
  502. TDialog::Destroy(int retValue)
  503. {
  504.   if (IsModal && HWindow) {
  505.     ForEach(DoEnableAutoCreate);
  506.     ::EndDialog(HWindow, retValue);
  507.   }
  508.   else {
  509.     TWindow::Destroy(retValue);
  510.   }
  511. }
  512.  
  513. //
  514. // set Dialog's Title data member and Caption. This is non-virtual, but is
  515. // always called with a TDialog or more specific pointer.
  516. //
  517. void
  518. TDialog::SetCaption(const char far* title)
  519. {
  520.   if (HIWORD(title) && LOWORD(title) != 0xFFFF)
  521.     TWindow::SetCaption(title);
  522. }
  523.  
  524. //
  525. // responds to an incoming notification message from a button with
  526. // an Id equal to IDOK
  527. //
  528. void
  529. TDialog::CmOk()
  530. {
  531.   CloseWindow(IDOK);
  532.  
  533.   if (!IsModal  && !HWindow && IsFlagSet(wfDeleteOnClose))
  534.     GetApplication()->Condemn(this);  
  535. }
  536.  
  537. //
  538. // responds to an incoming notification message from a button with
  539. // an Id equal to IDCANCEL. Unconditionally destroy the window.
  540. //
  541. void
  542. TDialog::CmCancel()
  543. {
  544.   EvClose();
  545. }
  546.  
  547. //
  548. // message response function for WM_CLOSE by unconditionally closing
  549. // the window.
  550. //
  551. void
  552. TDialog::EvClose()
  553. {
  554.   Destroy(IDCANCEL);
  555.  
  556.   if (!IsModal  && !HWindow && IsFlagSet(wfDeleteOnClose)) 
  557.     GetApplication()->Condemn(this);  
  558. }
  559.  
  560. #endif
  561. #if !defined(SECTION) || SECTION == 2
  562.  
  563. IMPLEMENT_STREAMABLE1(TDialog, TWindow);
  564.  
  565. //
  566. // reads an instance of TDialog from the passed ipstream
  567. //
  568. void*
  569. TDialog::Streamer::Read(ipstream& is, uint32 /*version*/) const
  570. {
  571.   ReadBaseObject((TWindow*)GetObject(), is);
  572.  
  573.   is >> (TResId&)GetObject()->Attr.Name;
  574.   is >> GetObject()->IsModal;
  575.   return GetObject();
  576. }
  577.  
  578. //
  579. // writes the TDialog to the passed opstream
  580. //
  581. void
  582. TDialog::Streamer::Write(opstream& os) const
  583. {
  584.   WriteBaseObject((TWindow*)GetObject(), os);
  585.  
  586.   os << TResId(GetObject()->Attr.Name);
  587.   os << GetObject()->IsModal;
  588. }
  589. #endif
  590.