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) return false; // Cancel.
222
223 // NOTE: To avoid invalidating iterators while deleting the children, we first collect the
224 // children in a vector before deleting them.
225 //
226 // Also note that we need to check again whether a child can close, since this can change as we
227 // close children. In particular, multiple views connected to the same dirty document will all
228 // happily close until there is only one view left, which then may refuse.
229 //
230 auto cv = std::vector<TWindow*>{};
231 for (auto& w : c)
232 cv.push_back(&w);
233 for (const auto w : cv)
234 {
235 if (!w->CanClose()) return false; // Cancel.
236 w->Destroy();
237 delete w;
238 }
239 return true;
240}
241
242//
243/// Intercepts the WM_MDICREATE message sent when MDI child windows are created,
244/// and, if the client's style includes MDIS_ALLCHILDSTYLES, and the child window's
245/// specified style is 0, then changes the child window style attributes to
246/// WS_VISIBLE, WS_CHILD, WS_CLIPSIBLINGS, WS_CLIPCHILDREN, WS_SYSMENU, WS_CAPTION,
247/// WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX.
248//
249HWND
251{
252 // Fill in default child window styles if they request style 0 since this
253 // client by default has set allchildstyles
254 //
255 if ((Attr.Style&MDIS_ALLCHILDSTYLES) && !createStruct.style)
256 createStruct.style =
260
261 // Work around a Windows MDI bug w/ bad menus if MDI child is created
262 // maximized, by hiding child now & maximizing later
263 //
265 if (createStruct.style & WS_MAXIMIZE)
266 createStruct.style &= ~(WS_MAXIMIZE | WS_VISIBLE);
267
268 TResult result = DefaultProcessing();
269
270 // Finish up maximized MDI child workaround
271 //
272 if (THandle(result) && (origStyle & WS_MAXIMIZE)) {
275 }
276
277 return reinterpret_cast<HWND>(result);
278}
279
280//
281/// Destroys an MDI child window.
282//
283void
285{
286 // When an MDI child is destroyed while other children are hidden or disabled,
287 // the Windows MDI child management gets confused causing subsequent failure.
288 // To prevent this, we temporarily unhide and enable siblings during destroy.
289 //
290 const auto unhide = [&](TWindow& child)
291 {
292 if (child.GetHandle() == w || !child.IsWindow())
293 return;
294 if (!child.IsWindowVisible())
295 {
297 child.SetFlag(wfUnHidden);
298 }
299 if (!child.IsWindowEnabled())
300 {
301 child.EnableWindow(true);
302 child.SetFlag(wfUnDisabled);
303 }
304 };
305
306 const auto rehide = [&](TWindow& child)
307 {
308 if (child.GetHandle() == w || !child.IsWindow())
309 return;
310 if (child.IsFlagSet(wfUnHidden))
311 {
312 child.ClearFlag(wfUnHidden);
313 child.ShowWindow(SW_HIDE);
314 }
315 if (child.IsFlagSet(wfUnDisabled))
316 {
317 child.ClearFlag(wfUnDisabled);
318 child.EnableWindow(false);
319 }
320 };
321
322 for (auto& w : GetChildren()) unhide(w);
324 for (auto& w : GetChildren()) rehide(w);
326}
327
328//
329/// Forwards dropped file messages by default to the parent (MDI Frame) where they
330/// can be handled, or be allowed to forward to the application where they can be
331/// handled more easily.
332//
333void
335{
336 Parent->ForwardMessage();
337}
338
339//
340/// If there are MDI child windows, CmChildActionEnalbe enables any one of the child
341/// window action menu items.
342//
343void
348
349
350
352
353#if OWL_PERSISTENT_STREAMS
354
355//
356/// Reads an instance of TMDIClient from the passed ipstream
357//
358void*
359TMDIClient::Streamer::Read(ipstream& is, uint32 /*version*/) const
360{
361 ReadBaseObject((TWindow*)GetObject(), is);
362
363 if (GetObject()->ClientAttr == 0)
364 GetObject()->ClientAttr = new CLIENTCREATESTRUCT; //
365
366 uint idFirstChild; // Need temp for near data model since ClientAttr is
367 is >> idFirstChild;
368 GetObject()->ClientAttr->idFirstChild = idFirstChild;
369 GetObject()->ClientAttr->hWindowMenu = (HMENU) 0;
370 GetObject()->Attr.Param = reinterpret_cast<LPVOID>(GetObject()->ClientAttr);
371
372 return GetObject();
373}
374
375//
376/// Writes the TMDIClient to the passed opstream
377//
378void
379TMDIClient::Streamer::Write(opstream& os) const
380{
381 WriteBaseObject((TWindow*)GetObject(), os);
382 os << GetObject()->ClientAttr->idFirstChild;
383}
384
385#endif
386
387} // OWL namespace
388/* ========================================================================== */
389
#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:344
void EvDropFiles(TDropInfo)
Forwards dropped file messages by default to the parent (MDI Frame) where they can be handled,...
Definition mdiclien.cpp:334
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:250
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:284
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:78
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:50
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