Files
TeslaRel410/BORLAND/BC45/SOURCE/OWL/FRAMEWIN.CPP
T
CydandClaude Fable 5 63312e07f9 source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived
- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
  is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
  Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
  (extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
  BT game source (never mixed into CODE/). Round 1-3 state:
  * 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
    (BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
    since 1996.
  * BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
    its binary-recorded line 400 exactly.
  * BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
    (Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
    TeamScore=12 flagged [T4]).
  * MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
    (VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
    the period compiler is the drift detector).
  * Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
    (per-TU verification sweep under authentic OPT.MAK flags).
  * README: corrected roadmap - MECH.HPP is the capstone grown with the mech
    TU reconstructions; BTREG.CPP green = the header-family milestone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 07:33:26 -05:00

1020 lines
26 KiB
C++

//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
//
// Implementation of class TFrameWindow
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl/owlpch.h>
#include <owl/framewin.h>
#include <owl/applicat.h>
#include <owl/menu.h>
#if !defined(SECTION) || SECTION == 1
DEFINE_RESPONSE_TABLE1(TFrameWindow, TWindow)
EV_WM_PAINT,
EV_WM_ERASEBKGND,
EV_WM_QUERYDRAGICON,
EV_WM_INITMENUPOPUP,
EV_WM_SETFOCUS,
EV_WM_SIZE,
EV_WM_PARENTNOTIFY,
EV_WM_ENTERIDLE,
END_RESPONSE_TABLE;
//
// Enable/disable the command sender, in this case the menu item.
//
void
TMenuItemEnabler::Enable(bool enable)
{
TCommandEnabler::Enable(enable);
::EnableMenuItem(HMenu, Position,
MF_BYPOSITION | (enable ? MF_ENABLED : MF_GRAYED));
}
//
// Set the text for the command sender, in this case the menu item.
//
void
TMenuItemEnabler::SetText(const char far* str)
{
::ModifyMenu(HMenu, Position, MF_BYPOSITION | MF_STRING, Id, str);
}
//
// Set the check state of the command sender, in this case the menu item.
//
void
TMenuItemEnabler::SetCheck(int state)
{
::CheckMenuItem(HMenu, Position,
MF_BYPOSITION | (state == Checked ? MF_CHECKED : MF_UNCHECKED));
}
//----------------------------------------------------------------------------
//
// constructor for a TFrameWindow
//
TFrameWindow::TFrameWindow(TWindow* parent,
const char far* title,
TWindow* clientWnd,
bool shrinkToClient,
TModule* module)
{
//
// Initialize virtual base, in case the derived-most used default ctor
//
TWindow::Init(parent, title, module);
IconResId = 0; // remember that we still need to init
Init(clientWnd, shrinkToClient);
}
//
// constructor for a TFrameWindow. This ctor is generally not used by derived
// classes, only as generic alias to a framewindow-like HWND
//
TFrameWindow::TFrameWindow(HWND hWnd, TModule* module)
: TWindow(hWnd, module)
{
Init(0);
}
//
// Protected constructor for use by immediate virtually derived classes.
// Immediate derivitives must call Init() before constructions are done.
//
TFrameWindow::TFrameWindow()
{
IconResId = 0; // Zero this member to remember that we still need to init
}
//
// Normal initialization of a default constructed TFrameWindow. Is ignored
// if called more than once.
//
void
TFrameWindow::Init(TWindow* clientWnd, bool shrinkToClient)
{
if (!IconResId) {
Attr.Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
Attr.X = Attr.W = CW_USEDEFAULT;
if (clientWnd)
Attr.Style |= WS_CLIPCHILDREN;
if (shrinkToClient)
SetFlag(wfShrinkToClient);
Init(clientWnd);
}
}
//
// Private initializer does a bulk of the common frame window initialization
//
void
TFrameWindow::Init(TWindow* clientWnd)
{
HWndRestoreFocus = 0;
KeyboardHandling = false;
ClientWnd = clientWnd;
MenuDescr = 0;
MergeModule = 0;
IconModule = ::Module;
IconResId = IDI_OWLAPP;
MinimizedPos = TPoint(-1,-1); // Windows convention for never minimized
if (ClientWnd) {
ClientWnd->SetParent(this);
ClientWnd->EnableAutoCreate(); // in case client is a dialog
SetBkgndColor(NoErase); // no need to erase client area
}
}
TFrameWindow::~TFrameWindow()
{
delete MenuDescr;
}
static uint32
GetMenuStateBits(HMENU hmenu, int count)
{
uint32 bit = 1;
uint32 result = 0;
for (int i=0; i<count; i++) {
uint state = GetMenuState(hmenu, i, MF_BYPOSITION);
if (state != (uint)-1) {
if (!(state & (MF_DISABLED | MF_GRAYED))) {
result |= bit;
}
}
bit <<= 1;
}
return result;
}
void
TFrameWindow::EvInitMenuPopup(HMENU hPopupMenu, uint index, bool sysMenu)
{
if (!sysMenu && hPopupMenu) {
const int count = ::GetMenuItemCount(hPopupMenu);
// Save current state of visible top level menus
//
uint32 preState = 0;
if (hPopupMenu == GetMenu())
preState = GetMenuStateBits(hPopupMenu, count);
TWindow::EvInitMenuPopup(hPopupMenu, index, sysMenu);
// If the top level menu state changes, redraw the menu bar
//
if (hPopupMenu == GetMenu())
if (GetMenuStateBits(hPopupMenu, count) != preState)
DrawMenuBar();
}
}
static void
DoIdleAction(TWindow* win, void* idleCount)
{
win->IdleAction(*(long*)idleCount);
}
//
// TFrameWindow processes idle action occurs once per block of messages
//
bool
TFrameWindow::IdleAction(long idleCount)
{
if (idleCount == 0) {
// do command enabling for the menu bar if this is the active task
//
#if defined(BI_PLAT_WIN32)
if (GetFocus()) {
#else
HWND focus = GetFocus();
if (focus && ::GetWindowTask(focus) == GetCurrentTask()) {
#endif
long style = ::GetWindowLong(*this, GWL_STYLE);
if (!(style & WS_CHILD)) {
HMENU hMenu = ::GetMenu(*this);
if (IsMenu(hMenu))
HandleMessage(WM_INITMENUPOPUP, WPARAM(hMenu));
}
}
// give child windows an opportunity to do any idle processing
//
ForEach(DoIdleAction, &idleCount);
}
return false; // we don't need any more time for now
}
//
// Locate and return the child window that is the target of command and command
// enable messages.
//
HWND
TFrameWindow::GetCommandTarget()
{
// Start with the focus window
//
HWND hFocus = ::GetFocus();
// If its a child of ours, then return it.
//
if (IsChild(hFocus))
return hFocus;
// The focus is not our descendent, use our most recently active child
//
if (HWndRestoreFocus)
return HWndRestoreFocus;
// If we have a client, fall back on that
//
if (GetClientWindow())
return *GetClientWindow();
// Don't know who else to send it to, return ourselves
//
return *this;
}
//
// Handle WM_COMMAND to provide extra processing for commands: send the
// command down the command chain
//
LRESULT
TFrameWindow::EvCommand(uint id, HWND hWndCtl, uint notifyCode)
{
// walk the command chain from the focus child back up to us or until
// we hit a child that is an owl window. Delegate to owl-child or forward to
// our base if no child is found.
//
if (hWndCtl == 0) {
HWND hCmdTarget = GetCommandTarget();
// Check owl parentage too in case the hWnds were reparented
//
while (hCmdTarget && hCmdTarget != HWindow) {
TWindow* cmdTarget = GetWindowPtr(hCmdTarget);
if (cmdTarget)
return cmdTarget->EvCommand(id, hWndCtl, notifyCode);
hCmdTarget = ::GetParent(hCmdTarget);
}
}
return TWindow::EvCommand(id, hWndCtl, notifyCode);
}
//
// Handle WM_COMMAND_ENABLE to provide command enable distribution and default
// support for windows without command enable handlers.
//
void
TFrameWindow::EvCommandEnable(TCommandEnabler& commandEnabler)
{
// Don't process for windows out of our window tree (esp. other apps)
//
RouteCommandEnable(GetCommandTarget(), commandEnabler);
}
//
// Preprocess queued messages to handle translation of accelerators on a per
// window basis, and dialog-like keyboard navigation if enabled.
//
bool
TFrameWindow::PreProcessMsg(MSG& msg)
{
if (TWindow::PreProcessMsg(msg))
return true; // process accelerators
if (KeyboardHandling && msg.message >= WM_KEYFIRST &&
msg.message <= WM_KEYLAST) {
HWND parent = ::GetParent(msg.hwnd);
//
// Retrieve the COMBO handle if we're in the EDIT ctl
// parented to the combobox
//
char szClassName[0x10];
::GetClassName(parent, szClassName, sizeof(szClassName));
if (!strcmpi(szClassName, "COMBOBOX"))
parent = ::GetParent(parent);
if (parent && ::IsDialogMessage(parent, &msg));
return true;
}
return false;
}
//
// Overrides TWindow's non-virtual SetMenu to make it virtual. This allows
// derived frame classes to implement this differently
// It also calls the application's PreProcessMenu() if it is the main window
// to let it make any changes just before setting.
//
bool
TFrameWindow::SetMenu(HMENU newMenu)
{
if (IsFlagSet(wfMainWindow))
GetApplication()->PreProcessMenu(newMenu);
return TWindow::SetMenu(newMenu);
}
//
// Perform a high-level menu assignment either before or after the HWND for the
// window has been created.
//
// returns true if successful; false otherwise
//
bool
TFrameWindow::AssignMenu(TResId menuResId)
{
if (menuResId != Attr.Menu) {
if (Attr.Menu.IsString())
delete (char far*)Attr.Menu;
Attr.Menu = menuResId.IsString() ? strnewdup(menuResId) : (char far*)menuResId;
}
// if the window has been created then load and set the new menu and destroy
// the old menu
//
if (!HWindow)
return true;
HMENU curMenu = GetMenu();
HMENU newMenu = GetModule()->LoadMenu(Attr.Menu);
if (!SetMenu(newMenu))
return false;
if (curMenu)
::DestroyMenu(curMenu);
return true;
}
//
// Set the Icon for use when this frame is minimized
//
bool
TFrameWindow::SetIcon(TModule* module, TResId resId)
{
IconModule = module;
IconResId = resId;
return true;
}
//
// Return the current client window as a TWindow*
//
TWindow*
TFrameWindow::GetClientWindow()
{
return ClientWnd;
}
//
// Remove the current client (if any) and set a new one.
// Assume clientWnd was parented to us.
//
TWindow*
TFrameWindow::SetClientWindow(TWindow* clientWnd)
{
TWindow* oldClientWnd = ClientWnd;
HWND oldHWnd = oldClientWnd ? oldClientWnd->HWindow : (HWND)0;
RemoveChild(ClientWnd);
if (HWndRestoreFocus == oldHWnd)
HWndRestoreFocus = 0;
ClientWnd = clientWnd;
if (ClientWnd) {
ClientWnd->SetParent(this);
if (!ClientWnd->HWindow)
ClientWnd->Create();
ClientWnd->Show(SW_NORMAL);
SetBkgndColor(NoErase); // no need to erase client area
ResizeClientWindow();
}
else
SetBkgndColor(NoColor); // will need to erase client area
if (ClientWnd && ClientWnd->HWindow)
ClientWnd->SetFocus();
else
SetFocus();
return oldClientWnd;
}
//
// If someone removes our client with a RemoveChild() call, update our client
// and restore focus ptrs.
//
void
TFrameWindow::RemoveChild(TWindow* child)
{
TWindow::RemoveChild(child);
if (child) {
if (child == ClientWnd)
ClientWnd = 0;
if (child->HWindow == HWndRestoreFocus)
HWndRestoreFocus = 0;
}
}
//
// Set the document style title for this frame window. Uses SetWindowText to
// modify the caption directly without modifying the Title data member.
// Generates a composite title based on Title if it exists, docname, and index
// if it is > 0.
// [<Title> - ]<docname>[:<index>]
//
bool
TFrameWindow::SetDocTitle(const char far* docname, int index)
{
if (index >= 0) {
string title;
if (Title && *Title) {
title = Title;
title += " - ";
}
title += docname;
if (index > 0) {
title += ':';
char num[10];
itoa(index, num, 10);
title += num;
}
SetWindowText(title.c_str());
} // else if index negative, simply acknowledge that title will display
return true;
}
//
// Obtain the real windows application icon. The IDI_APPLICATION icon is an
// ugly black & white box, but when a class is registered with this icon it
// gets substituted with a better windows icon. Worse case we end up with the
// ugly box icon.
//
static HICON
getAppIcon()
{
static HICON hRealAppIcon = 0;
if (!hRealAppIcon) {
WNDCLASS wndClass;
static char className[] = "IconSnarfer";
memset(&wndClass, 0, sizeof wndClass);
wndClass.hInstance = *::Module;
wndClass.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wndClass.lpszClassName = className;
wndClass.lpfnWndProc = ::DefWindowProc;
::RegisterClass(&wndClass);
::GetClassInfo(*::Module, className, &wndClass);
hRealAppIcon = wndClass.hIcon;
::UnregisterClass(className, *::Module);
}
return hRealAppIcon ? hRealAppIcon : ::LoadIcon(0, IDI_APPLICATION);
}
//
// Response method for an incoming WM_PAINT message
//
// If iconic, and an icon has been defined then draw that.
// Or, if iconic & there is a client window, then call its paint function.
//
// If not iconic, forwards to TWindow for normal paint processing
//
void
TFrameWindow::EvPaint()
{
if (IsIconic() && (IconResId || ClientWnd)) {
TPaintDC dc(HWindow);
if (IconResId) {
HINSTANCE hInstance = IconModule ? HINSTANCE(*IconModule) : HINSTANCE(0);
HICON hIcon = ::LoadIcon(hInstance, IconResId);
::DrawIcon(dc, 0, 0, hIcon ? hIcon : getAppIcon());
}
else
ClientWnd->Paint(dc, dc.Ps.fErase, *(TRect*)&dc.Ps.rcPaint);
}
else
TWindow::EvPaint();
}
//
// Response method for an incoming WM_ERASEBKGND message
//
// If this frame window is iconic, and there is a client window, then give it
// a chance to erase the background since it may want to take over painting.
//
// If not iconic, forward to TWindow for normal erase background processing
//
bool
TFrameWindow::EvEraseBkgnd(HDC hDC)
{
if (IsIconic()) {
if (!IconResId && ClientWnd)
return (bool)ClientWnd->HandleMessage(WM_ERASEBKGND, WPARAM(hDC));
HandleMessage(WM_ICONERASEBKGND, WPARAM(hDC));
return true;
}
else
return TWindow::EvEraseBkgnd(hDC);
}
//
// Response method for an incoming WM_QUERYDRAGICON message
//
// If there is an icon set for this frame, then return it so that windows
// can make a nice cursor out of it when the user drags the icon
//
HANDLE
TFrameWindow::EvQueryDragIcon()
{
if (IconResId) {
HINSTANCE hInstance = IconModule ? HINSTANCE(*IconModule) : HINSTANCE(0);
HICON hIcon = ::LoadIcon(hInstance, IconResId);
return hIcon ? hIcon : getAppIcon();
}
else
return TWindow::EvQueryDragIcon();
}
static inline bool
IsEnabledVisibleChild(long style)
{
return (style & (WS_CHILD | WS_VISIBLE | WS_DISABLED)) == (WS_CHILD | WS_VISIBLE);
}
static TWindow*
SearchForChildWithTab(TWindow* win)
{
TWindow* firstChild = win->GetFirstChild();
if (firstChild) {
TWindow* child = firstChild;
do {
if (child->HWindow) {
long style = child->GetWindowLong(GWL_STYLE);
if (IsEnabledVisibleChild(style)) {
if (style & WS_TABSTOP)
return child;
else {
TWindow* result = SearchForChildWithTab(child);
if (result)
return result;
}
}
}
child = child->Next();
} while (child != firstChild);
}
return 0;
}
static bool
EnabledVisibleChild(TWindow* win, void*)
{
return win->HWindow ? IsEnabledVisibleChild(win->GetWindowLong(GWL_STYLE)) :
false;
}
//
// if the receiver doesn't have any children then returns 0. otherwise
// we search for the first child with WS_TABSTOP; if no child has WS_TABSTOP
// then we return the first enabled visible child
//
// does a depth-first search of nested child windows
//
// NOTE: we stop at the first child with WS_TABSTOP and do not search its
// children...
//
TWindow*
TFrameWindow::FirstChildWithTab()
{
TWindow* win = SearchForChildWithTab(this);
return win ? win : FirstThat(EnabledVisibleChild);
}
//
// Respond to a request to hold on to the handle of a child window that is
// losing focus, so that we can restore it again later (below).
//
// return true if caller can stop searching for a window to hold its handle.
//
bool
TFrameWindow::HoldFocusHWnd(HWND hWndLose, HWND hWndGain)
{
if (IsChild(hWndLose)) {
if (!hWndGain || !IsChild(hWndGain))
HWndRestoreFocus = hWndLose;
return true;
}
return hWndLose == HWindow;
}
//
// Handle WM_SETFOCUS to return focus back to the child that had it most
// recently, or find the best one to give it to otherwise.
//
void
TFrameWindow::EvSetFocus(HWND hWndLostFocus)
{
TWindow::EvSetFocus(hWndLostFocus);
if (HWndRestoreFocus) {
//
// Set focus to the saved HWND as long as it is still a valid window handle
//
if (::IsWindow(HWndRestoreFocus))
::SetFocus(HWndRestoreFocus);
HWndRestoreFocus = 0;
}
else {
TWindow* win = FirstChildWithTab();
if (win && win->HWindow != hWndLostFocus)
win->SetFocus();
}
}
//
// Close this window if the client is destroyed
//
// Clear the wfFullyCreated flag on any child that is destroyed
// Resize this frame if the client changes size & wfShrinkToClient is set
//
void
TFrameWindow::EvParentNotify(uint event,
uint childHandleOrX, uint /*childIDOrY*/)
{
if (event == WM_DESTROY) {
if (ClientWnd && ClientWnd->HWindow == HWND(childHandleOrX))
PostMessage(WM_CLOSE); // using ShutDownWindow() has side effects
TWindow* c = GetWindowPtr(HWND(childHandleOrX));
if (c)
c->ClearFlag(wfFullyCreated);
}
else if (event == WM_SIZE) {
if (IsFlagSet(wfShrinkToClient)
&& ClientWnd
&& ClientWnd->HWindow == HWND(childHandleOrX)
&& !IsIconic())
ResizeClientWindow();
}
}
//
// Watch for WM_ENTERIDLE messages from idling modal dialog boxes so that
// background processing can continue when they are up.
//
void
TFrameWindow::EvEnterIdle(uint source, HWND hWndDlg)
{
if (source == MSGF_DIALOGBOX && IsFlagSet(wfMainWindow))
IdleAction(0); // could call GetApplication()->IdleAction(0)...
TWindow::EvEnterIdle(source, hWndDlg);
}
//
// Resize & reposition the client window to fit in this frames client area
// or resize the frame to fit around the client's client area if
// wfShrinkToClient
// Return true if a client was actualy resized.
// Adjust clients styles & make sure they get set.
//
bool
TFrameWindow::ResizeClientWindow(bool redraw)
{
if (!ClientWnd)
return false;
// prevent recursion during resize by ignore calls from EvParentNotify and
// EvSize when we have already been called
// do this by disabling notifications while resizing using the
// wfShrinkToClient flag as a semaphore on the client
//
if (ClientWnd->IsFlagSet(wfShrinkToClient))
return true;
ClientWnd->SetFlag(wfShrinkToClient);
bool clientResized = false;
TSize frameSize = GetClientRect().Size();
TSize childSize = ClientWnd->GetWindowRect().Size();
// first time through, strip client window of thick borders
// if shrink-to-client, then must measure the client size first
// if the client has scrolls bars, we must hide them to obtain the correct
// size
// Border style is left on & dealt with by hand below
//
const uint32 badClientStyles = WS_DLGFRAME | WS_THICKFRAME | // bad borders
WS_POPUP | WS_OVERLAPPED; // bad parenting
const uint32 badClientExStyles = WS_EX_DLGMODALFRAME;
if ((ClientWnd->Attr.Style & badClientStyles) ||
(ClientWnd->Attr.ExStyle & badClientExStyles)) {
if (IsFlagSet(wfShrinkToClient)) {
TSize tstSize = ClientWnd->GetClientRect().Size();
ClientWnd->ShowScrollBar(SB_BOTH, false);
childSize = ClientWnd->GetClientRect().Size();
if (childSize != tstSize) {
int restore = SB_BOTH;
if (childSize.cx == tstSize.cx)
restore = SB_HORZ;
if (childSize.cy == tstSize.cy)
restore = SB_VERT;
ClientWnd->ShowScrollBar(restore, true);
}
}
if (ClientWnd->Attr.Style & badClientStyles) {
bool reparent = (ClientWnd->Attr.Style & (WS_POPUP|WS_OVERLAPPED)) != 0;
ClientWnd->Attr.Style &= ~badClientStyles;
ClientWnd->Attr.Style |= WS_CHILD | WS_BORDER | WS_VISIBLE;
ClientWnd->SetWindowLong(GWL_STYLE, ClientWnd->Attr.Style);
if (reparent)
::SetParent(*ClientWnd, *this);
}
if (ClientWnd->Attr.ExStyle & badClientExStyles) {
ClientWnd->Attr.ExStyle &= ~badClientExStyles;
ClientWnd->SetWindowLong(GWL_EXSTYLE, ClientWnd->Attr.ExStyle);
}
}
if (ClientWnd->Attr.Style & WS_BORDER) {
childSize = ClientWnd->GetClientRect().Size();
}
if (childSize != frameSize) {
if (IsFlagSet(wfShrinkToClient)) {
TRect outside = GetWindowRect();
TPoint outsideOrg(0, 0);
if (Parent)
Parent->ClientToScreen(outsideOrg); // adjust our rect by our parent's
TSize border = outside.Size() - frameSize;
MoveWindow(outside.left - outsideOrg.x, outside.top - outsideOrg.y,
childSize.cx + border.cx, childSize.cy + border.cy, redraw);
frameSize = childSize; // must move client, will not cause an EvSize
}
else {
clientResized = true; // client will get resized
}
}
// If frame is sizeable, turn off flag so that user can then resize
// after initial setup
//
if (Attr.Style & WS_THICKFRAME)
ClearFlag(wfShrinkToClient);
// Handle border style by shoving the client's borders under the frame
//
if (ClientWnd->Attr.Style & WS_BORDER) {
int bx = ::GetSystemMetrics(SM_CXBORDER);
int by = ::GetSystemMetrics(SM_CYBORDER);
ClientWnd->MoveWindow(-bx, -by, frameSize.cx+bx+bx, frameSize.cy+by+by, redraw);
}
else
ClientWnd->MoveWindow(0, 0, frameSize.cx, frameSize.cy, redraw);
ClientWnd->ClearFlag(wfShrinkToClient);
return clientResized;
}
//
// called following a successful association between an MS-Windows interface
// element and a TFrameWindow
//
void
TFrameWindow::SetupWindow()
{
// create windows in child list (this includes the client window)
//
TWindow::SetupWindow();
ResizeClientWindow();
if (MinimizedPos != TPoint(-1,-1)) {
WINDOWPLACEMENT windata;
windata.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(&windata);
windata.flags = WPF_SETMINPOSITION;
windata.showCmd = SW_SHOWNA;
windata.ptMinPosition = MinimizedPos;
SetWindowPlacement(&windata);
}
// if SetMenuDescr() was called before window created, update the menu now
//
if (IsFlagSet(wfMainWindow) && MenuDescr) {
HMENU curMenu = GetMenu();
TMenu newMenu(*MenuDescr, NoAutoDelete);
if (SetMenu(newMenu)) {
if (curMenu)
::DestroyMenu(curMenu);
}
else
::DestroyMenu(newMenu);
}
// if we haven't set HWndRestoreFocus then pick the first child with tabstop
//
if (!HWndRestoreFocus) {
TWindow* win = FirstChildWithTab();
HWndRestoreFocus = win ? win->HWindow : HWindow;
}
}
//
// response method for an incoming WM_SIZE message
//
// if not minimizing resizes the client window to be the same size as the
// client rectangle,
// if no WM_SIZE sent, forwards WM_SIZE message to client so it can recalc.
//
void
TFrameWindow::EvSize(uint sizeType, TSize& size)
{
TWindow::EvSize(sizeType, size);
if (ClientWnd) {
bool sizeSent = false;
if (sizeType != SIZE_MINIMIZED) {
sizeSent = ResizeClientWindow();
size = ClientWnd->GetClientRect().Size();
}
if (!sizeSent)
ClientWnd->ForwardMessage();
}
}
#endif
#if !defined(SECTION) || SECTION == 2
//
// Set the menu descriptor for this frame window
//
void
TFrameWindow::SetMenuDescr(const TMenuDescr& menuDescr)
{
delete MenuDescr;
MenuDescr = new TMenuDescr(menuDescr);
if (IsFlagSet(wfMainWindow) && HWindow) {
HMENU curMenu = GetMenu();
TMenu newMenu(*MenuDescr, NoAutoDelete);
if (SetMenu(newMenu))
::DestroyMenu(curMenu);
else
::DestroyMenu(newMenu);
}
}
//
// Merge another menu, given its menu descriptor, into our own using our menu
// descriptor.
// optionally use an existing HMENU to merge into & set
//
bool
TFrameWindow::MergeMenu(const TMenuDescr& childMenuDescr)
{
if (!MenuDescr || !HWindow)
return false;
MergeModule = childMenuDescr.GetModule();
TMenu curMenu(*this, NoAutoDelete);
TMenu newMenu(NoAutoDelete);
MenuDescr->Merge(childMenuDescr, newMenu);
if (IsFlagSet(wfMainWindow))
GetApplication()->PreProcessMenu(newMenu);
if (SetMenu(newMenu)) {
::DestroyMenu(curMenu);
return true;
}
else {
::DestroyMenu(newMenu);
return false;
}
}
//
// Restore our menu to the one described by our menu descriptor
//
bool
TFrameWindow::RestoreMenu()
{
if (!MenuDescr)
return false;
HMENU curMenu = GetMenu();
TMenu newMenu(*MenuDescr, NoAutoDelete);
if (SetMenu(newMenu)) {
MergeModule = 0;
::DestroyMenu(curMenu);
}
else
::DestroyMenu(newMenu);
return true;
}
#endif
#if !defined(SECTION) || SECTION == 3
IMPLEMENT_STREAMABLE1(TFrameWindow, TWindow);
//
// reads data of the uninitialized TFrameWindow from the passed ipstream
//
void*
TFrameWindow::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TFrameWindow* o = GetObject();
ReadVirtualBase((TWindow*)o, is);
if (o->IsFlagSet(wfMainWindow))
return o;
is >> o->ClientWnd;
is >> o->KeyboardHandling;
o->HWndRestoreFocus = 0;
bool hasMenuDescr = is.readByte();
if (hasMenuDescr) {
o->MenuDescr = new TMenuDescr;
is >> *o->MenuDescr;
}
else
o->MenuDescr = 0;
is >> o->IconModule;
is >> o->IconResId;
is >> o->MergeModule;
is >> o->MinimizedPos;
return o;
}
//
// writes data of the TFrameWindow to the passed opstream
//
void
TFrameWindow::Streamer::Write(opstream& os) const
{
TFrameWindow* o = GetObject();
WriteVirtualBase((TWindow*)o, os);
if (o->IsFlagSet(wfMainWindow))
return;
os << o->ClientWnd;
os << o->KeyboardHandling;
os.writeByte(uint8(o->MenuDescr ? 1 : 0));
if (o->MenuDescr)
os << *o->MenuDescr;
os << o->IconModule;
os << o->IconResId;
os << o->MergeModule;
WINDOWPLACEMENT windata;
windata.length = sizeof(WINDOWPLACEMENT);
o->GetWindowPlacement(&windata);
os << TPoint(windata.ptMinPosition);
}
#endif // SECTION