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
mdiclien.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 TMDIClient. This defines the basic behavior
7/// of all MDI client windows.
8//----------------------------------------------------------------------------
9#include <owl/pch.h>
10#include <owl/mdi.h>
11#include <algorithm>
12#include <vector>
13
14namespace owl {
15
17
18
19DEFINE_RESPONSE_TABLE1(TMDIClient, TWindow)
20 EV_COMMAND(CM_CREATECHILD, CmCreateChild),
21 EV_COMMAND(CM_TILECHILDREN, CmTileChildren),
22 EV_COMMAND(CM_TILECHILDRENHORIZ, CmTileChildrenHoriz),
23 EV_COMMAND(CM_CASCADECHILDREN, CmCascadeChildren),
24 EV_COMMAND(CM_ARRANGEICONS, CmArrangeIcons),
25 EV_COMMAND(CM_CLOSECHILDREN, CmCloseChildren),
26 EV_COMMAND_ENABLE(CM_TILECHILDREN, CmChildActionEnable),
29 EV_COMMAND_ENABLE(CM_ARRANGEICONS, CmChildActionEnable),
30 EV_COMMAND_ENABLE(CM_CLOSECHILDREN, CmChildActionEnable),
35
36//
37/// Constructor for a TMDIClient
38//
39/// Creates an MDI client window object by invoking the base class TWindow
40/// constructor, passing it a null parent window, a null title, and the specified
41/// library ID. Sets the default client window identifier (IDW_MDICLIENT) and sets
42/// the style to include MDIS_ALLCHILDSTYLES, WS_GROUP, WS_TABSTOP, WS_CLIPCHILDREN,
43/// WS_VSCROLL, and WS_HSCROLL. Initializes the ClientAttr data member, setting its
44/// idFirstChild member to IDW_FIRSTMDICHILD.
45//
46/// Allocates a CLIENTCREATESTRUCT on the heap and
47/// ClientAttr to point to this space
48//
50{
51 // Initialize virtual base, in case the derived-most used default ctor
52 //
53 TWindow::Init(nullptr, nullptr, module);
54
55 Attr.Id = IDW_MDICLIENT;
56
57 // Allow client area to grow scroll bars if necessary
58 //
61
62 Attr.Style &= ~WS_BORDER;
63 Attr.ExStyle |= WS_EX_CLIENTEDGE;
64
65 ClientAttr = new CLIENTCREATESTRUCT;
66 ClientAttr->hWindowMenu = nullptr;
67 ClientAttr->idFirstChild = IDW_FIRSTMDICHILD;
68
69 Attr.Param = reinterpret_cast<LPVOID>(ClientAttr);
70 SetFlag(wfStreamTop);
71}
72
73//
74/// Constructor for a TMDIClient which is being used in a DLL as an alias
75/// for a non-OWL window. This ctor is generally not used by derived
76/// classes
77//
79:
80 TWindow(handle, module)
81{
82 ClientAttr = 0;
84}
85
86//
87/// Frees the memory associated with ClientAttr
88//
90{
91 delete ClientAttr;
92}
93
94//
95/// Returns TMDIClient's registration class name, "MDICLIENT."
96//
98{
99 return TWindowClassName{_T("MDICLIENT")};
100}
101
102//
103/// Use the Windows message to get the active mdi child, and then down cast
104/// to our MDI child derived class before returning it.
105//
113
114//
115/// Arranges the MDI child window icons at the bottom of the MDI client window.
116//
117void
122
123//
124/// Sizes and arranges all of the non-iconized MDI child windows within the MDI
125/// client window. The children are overlapped, although each title bar is visible.
126//
127void
132
133//
134/// Sizes and arranges all of the non-iconized MDI child windows within the MDI
135/// client window. The children fill up the entire client area without overlapping.
136//
137void
142
143//
144/// Preprocess messages in order to translate MDI accelerator keys
145///
146/// If the specified msg is one of WM_KEYDOWN or WM_SYSKEYDOWN, then the keyboard
147/// accelerators are translated for the MDI client.
148//
149bool
151{
152 if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
154
155 else
156 return false;
157}
158
159//
160/// Creates the interface element associated with the MDI client window. Calls
161/// TWindow::Create after first setting the child window menu in ClientAttr to the
162/// parent frame window's child menu.
163//
164bool
166{
168
169 CHECK(frame);
170
171 ClientAttr->hWindowMenu = frame->FindChildMenu(frame->GetMenu());
172 return TWindow::Create();
173}
174
175//
176/// Initializes and creates a new TMDIChild by calling InitChild and Create.
177//
180{
182 CHECK(child);
183 if (child->Create())
184 return child;
185 return nullptr;
186}
187
188//
189/// Constructs an instance of a TMDIChild with this TMDIClient as parent.
190/// Override this virtual function in your derived MDI client class to construct an instance
191/// of a derived MDI child class. For example,
192/// \code
193/// TMyMDIChild* TMyMDIClient::InitChild() // override
194/// {
195/// return new TMyMDIChild(this);
196/// }
197/// \endcode
198//
201{
202 return new TMDIChild(*this);
203}
204
205//
206/// Closes the TMDIChild windows owned by this MDI client.
207/// First calls TWindow::CanClose on each of the children, then if all return true, closes them.
208///
209/// \returns `true` is returned, if the children are closed, or if this client has no children.
210/// Otherwise, `false` is returned.
211///
212/// \note The implementation of this function assumes that the children were dynamically allocated,
213/// and have delegated ownership to the MDI parent. If a child is not dynamically allocated, or it
214/// has shared ownership, it must be removed from the children list, before this function is called.
215//
216bool
218{
219 auto c = GetChildren();
220 const auto canClose = std::all_of(c.begin(), c.end(), [](TWindow& w) { return w.CanClose(); });
221 if (canClose)
222 {
223 // Note that the old implementation deleted the child while traversing the linked list of
224 // children. However, while the implementation of the iteration may be written to allow this, it
225 // is poor programming style to assume that iterators remain valid while mutating the underlying
226 // structure. So, to make the code less brittle, we now collect the children into a vector before
227 // deleting them.
228 //
229 // Also note that the code here assumes that the child was dynamically allocated. If not, the
230 // child must be taken out of the children list before this function is called.
231 //
232 auto cv = std::vector<TWindow*>{};
233 for (auto& w : c)
234 cv.push_back(&w);
235 for (auto& w : cv)
236 {
237 w->Destroy();
238 delete w;
239 }
240 }
241 return canClose;
242}
243
244//
245/// Intercepts the WM_MDICREATE message sent when MDI child windows are created,
246/// and, if the client's style includes MDIS_ALLCHILDSTYLES, and the child window's
247/// specified style is 0, then changes the child window style attributes to
248/// WS_VISIBLE, WS_CHILD, WS_CLIPSIBLINGS, WS_CLIPCHILDREN, WS_SYSMENU, WS_CAPTION,
249/// WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX.
250//
251HWND
253{
254 // Fill in default child window styles if they request style 0 since this
255 // client by default has set allchildstyles
256 //
257 if ((Attr.Style&MDIS_ALLCHILDSTYLES) && !createStruct.style)
258 createStruct.style =
262
263 // Work around a Windows MDI bug w/ bad menus if MDI child is created
264 // maximized, by hiding child now & maximizing later
265 //
267 if (createStruct.style & WS_MAXIMIZE)
268 createStruct.style &= ~(WS_MAXIMIZE | WS_VISIBLE);
269
270 TResult result = DefaultProcessing();
271
272 // Finish up maximized MDI child workaround
273 //
274 if (THandle(result) && (origStyle & WS_MAXIMIZE)) {
277 }
278
279 return reinterpret_cast<HWND>(result);
280}
281
282//
283/// Destroys an MDI child window.
284//
285void
287{
288 // When an MDI child is destroyed while other children are hidden or disabled,
289 // the Windows MDI child management gets confused causing subsequent failure.
290 // To prevent this, we temporarily unhide and enable siblings during destroy.
291 //
292 const auto unhide = [&](TWindow& child)
293 {
294 if (child.GetHandle() == w || !child.IsWindow())
295 return;
296 if (!child.IsWindowVisible())
297 {
299 child.SetFlag(wfUnHidden);
300 }
301 if (!child.IsWindowEnabled())
302 {
303 child.EnableWindow(true);
304 child.SetFlag(wfUnDisabled);
305 }
306 };
307
308 const auto rehide = [&](TWindow& child)
309 {
310 if (child.GetHandle() == w || !child.IsWindow())
311 return;
312 if (child.IsFlagSet(wfUnHidden))
313 {
314 child.ClearFlag(wfUnHidden);
315 child.ShowWindow(SW_HIDE);
316 }
317 if (child.IsFlagSet(wfUnDisabled))
318 {
319 child.ClearFlag(wfUnDisabled);
320 child.EnableWindow(false);
321 }
322 };
323
324 for (auto& w : GetChildren()) unhide(w);
326 for (auto& w : GetChildren()) rehide(w);
328}
329
330//
331/// Forwards dropped file messages by default to the parent (MDI Frame) where they
332/// can be handled, or be allowed to forward to the application where they can be
333/// handled more easily.
334//
335void
337{
338 Parent->ForwardMessage();
339}
340
341//
342/// If there are MDI child windows, CmChildActionEnalbe enables any one of the child
343/// window action menu items.
344//
345void
350
351
352
354
355#if OWL_PERSISTENT_STREAMS
356
357//
358/// Reads an instance of TMDIClient from the passed ipstream
359//
360void*
361TMDIClient::Streamer::Read(ipstream& is, uint32 /*version*/) const
362{
363 ReadBaseObject((TWindow*)GetObject(), is);
364
365 if (GetObject()->ClientAttr == 0)
366 GetObject()->ClientAttr = new CLIENTCREATESTRUCT; //
367
368 uint idFirstChild; // Need temp for near data model since ClientAttr is
369 is >> idFirstChild;
370 GetObject()->ClientAttr->idFirstChild = idFirstChild;
371 GetObject()->ClientAttr->hWindowMenu = (HMENU) 0;
372 GetObject()->Attr.Param = reinterpret_cast<LPVOID>(GetObject()->ClientAttr);
373
374 return GetObject();
375}
376
377//
378/// Writes the TMDIClient to the passed opstream
379//
380void
381TMDIClient::Streamer::Write(opstream& os) const
382{
383 WriteBaseObject((TWindow*)GetObject(), os);
384 os << GetObject()->ClientAttr->idFirstChild;
385}
386
387#endif
388
389} // OWL namespace
390/* ========================================================================== */
391
#define CHECK(condition)
Definition checks.h:239
Base class for an extensible interface for auto enabling/disabling of commands (menu items,...
Definition window.h:209
TDropInfo is a simple class that supports file-name drag-and-drop operations using the WM_DROPFILES m...
Definition wsyscls.h:257
TMDIChild defines the basic behavior of all MDI child windows.
Definition mdichild.h:42
Multiple Document Interface (MDI) client windows (represented by a TMDIClient object) manage the MDI ...
Definition mdi.h:37
virtual bool CloseChildren()
Closes the TMDIChild windows owned by this MDI client.
Definition mdiclien.cpp:217
auto GetWindowClassName() -> TWindowClassName override
Returns TMDIClient's registration class name, "MDICLIENT.".
Definition mdiclien.cpp:97
TMDIClient(TModule *module=0)
Constructor for a TMDIClient.
Definition mdiclien.cpp:49
void CmChildActionEnable(TCommandEnabler &commandEnabler)
If there are MDI child windows, CmChildActionEnalbe enables any one of the child window action menu i...
Definition mdiclien.cpp:346
void EvDropFiles(TDropInfo)
Forwards dropped file messages by default to the parent (MDI Frame) where they can be handled,...
Definition mdiclien.cpp:336
TMDIChild * GetActiveMDIChild()
Use the Windows message to get the active mdi child, and then down cast to our MDI child derived clas...
Definition mdiclien.cpp:107
virtual TMDIChild * InitChild()
Constructs an instance of a TMDIChild with this TMDIClient as parent.
Definition mdiclien.cpp:200
virtual void TileChildren(int tile=MDITILE_VERTICAL)
Sizes and arranges all of the non-iconized MDI child windows within the MDI client window.
Definition mdiclien.cpp:138
virtual void ArrangeIcons()
Arranges the MDI child window icons at the bottom of the MDI client window.
Definition mdiclien.cpp:118
~TMDIClient()
Frees the memory associated with ClientAttr.
Definition mdiclien.cpp:89
auto Create() -> bool override
Creates the interface element associated with the MDI client window.
Definition mdiclien.cpp:165
virtual TMDIChild * CreateChild()
Initializes and creates a new TMDIChild by calling InitChild and Create.
Definition mdiclien.cpp:179
HWND EvMDICreate(MDICREATESTRUCT &createStruct)
Intercepts the WM_MDICREATE message sent when MDI child windows are created, and, if the client's sty...
Definition mdiclien.cpp:252
virtual void CascadeChildren()
Sizes and arranges all of the non-iconized MDI child windows within the MDI client window.
Definition mdiclien.cpp:128
auto PreProcessMsg(MSG &) -> bool override
Preprocess messages in order to translate MDI accelerator keys.
Definition mdiclien.cpp:150
void EvMDIDestroy(HWND hWnd)
Destroys an MDI child window.
Definition mdiclien.cpp:286
Multiple Document Interface (MDI) frame windows, represented by TMDIFrame, are overlapped windows tha...
Definition mdi.h:122
static HMENU FindChildMenu(HMENU)
Find & return the child menu of an MDI frame's (or anyone's) menu bar.
Definition mdiframe.cpp:166
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
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
auto GetChildren()
Returns a TWindow::TChildrenRange that can be iterated by standard means.
Definition window.h:550
virtual bool Create()
Creates the window interface element to be associated with this ObjectWindows interface element.
Definition window.cpp:2399
TWindow * GetWindowPtr(HWND hWnd) const
Calls TApplication:GetWindowPtr on the application associated with this window.
Definition window.h:3567
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
HMENU GetMenu() const
Returns the handle to the menu of the indicated window.
Definition window.h:3244
TResult HandleMessage(TMsgId, TParam1=0, TParam2=0)
Dispatches the given message using the response table.
Definition window.cpp:1392
TResult DefaultProcessing()
Handles default processing of events, which includes continued processing of menu/accelerators comman...
Definition window.cpp:852
TWindow * GetFirstChild()
Returns a pointer to the first child window, which is the first window created in the interface objec...
Definition window.h:1770
HWND THandle
TWindow encapsulates an HWND.
Definition window.h:418
HWND GetHandle() const
Returns the handle of the window.
Definition window.h:2020
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
#define _T(x)
Definition cygwin.h:51
#define DEFINE_RESPONSE_TABLE1(cls, base)
Macro to define a response table for a class with one base.
Definition eventhan.h:492
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
@ wfUnDisabled
Used temporarily when destroying MDI child.
Definition window.h:69
@ wfUnHidden
Used temporarily when destroying MDI child.
Definition window.h:68
@ wfStreamTop
This window is the topmost one to stream.
Definition window.h:65
Definition of TMDIClient and TMDIFrame classes.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
EV_WM_MDIDESTROY
Definition mdiclien.cpp:32
EV_WM_MDICREATE
Definition mdiclien.cpp:31
EV_WM_DROPFILES
Definition mdiclien.cpp:33
const unsigned int IDW_MDICLIENT
ID of MDI client window.
Definition framewin.h:28
unsigned long uint32
Definition number.h:34
WPARAM TParam1
First parameter type.
Definition dispatch.h:54
OWL_DIAGINFO
Definition animctrl.cpp:14
END_RESPONSE_TABLE
Definition button.cpp:26
unsigned int uint
Definition number.h:25
const unsigned int IDW_FIRSTMDICHILD
child window IDs, 32 max to 32032
Definition framewin.h:29
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
#define EV_COMMAND_ENABLE(id, method)
Response table entry for enabling a command.
Definition windowev.h:193
#define EV_COMMAND(id, method)
Response table entry for a menu/accelerator/push button message.
Definition windowev.h:171
#define WS_EX_CLIENTEDGE
Definition wsysinc.h:33