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