| Current Path : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/ |
| Current File : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/OLEFRAME.CPP |
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// Implementation of class TOleFrame.
//----------------------------------------------------------------------------
#define INC_OLE2
#include <owl/owlpch.h>
#include <owl/decmdifr.h>
#include <owl/statusba.h>
#include <owl/ocfevent.h>
#include <owl/uihandle.h>
#include <owl/oleframe.h>
#include <owl/olewindo.h>
DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlOleMenu, 1, 0);
//#define DEBUG_PADS // define to make pads paint red for debugging
const int DllIdleTime = 200; // time in MS for idle action polling
// Four edge locations for inplace-server space negotiation
//
const TDecoratedFrame::TLocation SpaceLoc[] = {
TDecoratedFrame::Left,
TDecoratedFrame::Top,
TDecoratedFrame::Right,
TDecoratedFrame::Bottom
};
//----------------------------------------------------------------------------
// An empty no-erase window that inserts itself into its decorated frame
// parent
//
class TPadWindow : public TWindow {
public:
TPadWindow(TWindow* parent, int edge, TModule* module = 0)
: TWindow(parent, 0, module)
{
Attr.Id = IDW_PADDECORATION+edge;
Attr.Style = WS_CHILD | WS_VISIBLE;
Attr.W = Attr.H = 1; // takeup no space until needed
// need 1 since layout overlapps borders
#if defined(DEBUG_PADS)
SetBkgndColor(TColor(255,0,0)); // to help Debug toolbar negotiations
strstream s;
s << "Pad" << ('0' + edge);
Title = strnewdup(s.str());
#else
SetBkgndColor(NoErase); // Don't erase--to avoid flicker
#endif
}
};
//----------------------------------------------------------------------------
// A small window class to act as a holder for the unattached remote server
// view windows
//
class TRemViewBucket : public TFrameWindow {
public:
TRemViewBucket(TWindow* parent)
: TFrameWindow(parent, "RemViewBucket")
{
Attr.Style = WS_CHILD | WS_DISABLED;
Attr.Id = IDW_REMVIEWBUCKET;
}
bool SetDocTitle(const char far*, int) {return true;}
protected:
private:
};
DEFINE_RESPONSE_TABLE1(TOleFrame, TDecoratedFrame)
EV_WM_SIZE,
EV_WM_TIMER,
EV_WM_ACTIVATEAPP,
EV_MESSAGE(WM_OCEVENT, EvOcEvent),
EV_OC_APPINSMENUS,
EV_OC_APPMENUS,
EV_OC_APPPROCESSMSG,
EV_OC_APPFRAMERECT,
EV_OC_APPBORDERSPACEREQ,
EV_OC_APPBORDERSPACESET,
EV_OC_APPSTATUSTEXT,
EV_OC_APPRESTOREUI,
EV_OC_APPSHUTDOWN,
END_RESPONSE_TABLE;
TOleFrame::TOleFrame(const char far* title,
TWindow* clientWnd,
bool trackMenuSelection,
TModule* module)
:
TDecoratedFrame(0, title, clientWnd, trackMenuSelection, module),
TFrameWindow(0, title, clientWnd, false, module),
TWindow(0, title, module),
HOldMenu(0),
OcApp(0),
StashCount(0),
OcShutDown(DontCare)
{
new TRemViewBucket(this); // Construct bucket to hold hidden server windows
// Retrieve the OcApp ptr from our owning application if it is a TOcModule
//
TOcModule* ocm = TYPESAFE_DOWNCAST(GetApplication(), TOcModule);
if (ocm)
SetOcApp(ocm->OcApp);
}
//
// Let the OC app go. It will delete itself when it can
//
TOleFrame::~TOleFrame()
{
}
//
// Initial set of OcApp being passed to us to use.
//
void
TOleFrame::SetOcApp(TOcApp* ocApp)
{
PRECONDITION(ocApp);
OcApp = ocApp;
// Initialize OLE 2 clipboard format names
//
char f[] = "%s";
AddUserFormatName(f, f, ocrEmbedSource);
AddUserFormatName(f, f, ocrEmbeddedObject);
AddUserFormatName(f, f, ocrLinkSource);
}
//
// Let the OcApp know our HWND so that it can talk to us
//
void
TOleFrame::SetupWindow()
{
PRECONDITION(OcApp);
TDecoratedFrame::SetupWindow();
OcApp->SetupWindow(*this);
// Insert the four pad windows for in-place server toolbars. Inserting last
// will place them as the inner-most decorations, which is needed with the
// status bar
//
for (int edge = 0; edge < 4; edge++)
Insert(*new TPadWindow(this, edge), ::SpaceLoc[edge]);
// Create a timer to allow us to poll for idle time when we are a dll server
//
if (!OcApp->IsOptionSet(amExeMode))
SetTimer(IDT_DLLIDLE, DllIdleTime);
}
//
//
//
void
TOleFrame::CleanupWindow()
{
if (!OcApp->IsOptionSet(amExeMode))
KillTimer(IDT_DLLIDLE);
}
//
// Add user defined format and result names to the list
//
void
TOleFrame::AddUserFormatName(const char far* name, const char far* resultName,
const char far* id)
{
PRECONDITION(OcApp);
OcApp->AddUserFormatName(name, resultName, id);
}
//
//
//
void
TOleFrame::OleViewClosing(bool close)
{
if (close && OcShutDown == DontCare) {
OcShutDown = ViewInitiated;
}
else if (!close && OcShutDown == ViewInitiated) {
OcShutDown = DontCare;
}
}
// Disconnect document servers with their clients.
// Document servers can be documents with objects copied on the clipboard or
// documents brought up though linking.
//
void
sDisconnectDocServer(TWindow* win, void* /*retVal*/)
{
if (win) {
win->ForEach(sDisconnectDocServer);
TOleWindow* oleWin = TYPESAFE_DOWNCAST(win, TOleWindow);
if (oleWin)
oleWin->OleShutDown();
}
}
//
// Make sure that any embeded servers also get a chance to OK the close
// sequence. If the user closes the app, but there are still embeddings, hide
// the frame instead of destroying it
//
void
TOleFrame::Destroy(int retVal)
{
if (!HWindow || OcShutDown == UserInitiated)
return;
// Disconnect document servers with their clients if user shuts down the app
//
if (OcShutDown == DontCare) {
OcShutDown = UserInitiated;
ForEach(sDisconnectDocServer, 0);
}
if (!OcApp->CanClose()) {
OcApp->SetOption(amEmbedding, true);
OcShutDown = DontCare; // reset the shutdown flag
ShowWindow(SW_HIDE);
}
else {
bool dllServer = !OcApp->IsOptionSet(amExeMode);
TDecoratedFrame::Destroy(retVal);
// If user shuts down the DLL server (as in the case of open-editing,
// we need to set the mainwindow flag to 0 so that only the application
// will be destroyed. All windows are destroyed in previous calls.
//
if (dllServer && OcShutDown != ServerInitiated) {
// GetApplication()->SetMainWindow(0);
GetApplication()->MainWindow = 0;
delete GetApplication();
}
}
}
//
// Forward size message to OcApp to allow it to notify any embedded servers
// about size changes
//
void
TOleFrame::EvSize(uint sizeType, TSize& size)
{
TDecoratedFrame::EvSize(sizeType, size);
if (OcApp)
OcApp->EvResize();
}
//
// Forward Activate messages to OcApp to allow it to notify any embedded servers
// about being activated
//
void
TOleFrame::EvActivateApp(bool active, HTASK hTask)
{
OcApp->EvActivate(active);
TDecoratedFrame::EvActivateApp(active, hTask);
}
//
//
//
void
TOleFrame::EvTimer(uint timerId)
{
if (timerId == IDT_DLLIDLE)
GetApplication()->PostDispatchAction();
TWindow::EvTimer(timerId);
}
//
// Handle & sub-dispatch the OC event message.
//
LRESULT
TOleFrame::EvOcEvent(WPARAM wParam, LPARAM lParam)
{
TEventHandler::TEventInfo eventInfo(WM_OCEVENT, wParam);
// Give the client window the first chance at it
//
TWindow* receiver = GetClientWindow();
if (receiver->Find(eventInfo))
return receiver->Dispatch(eventInfo, wParam, lParam);
// Then try this frame
//
if (Find(eventInfo))
return Dispatch(eventInfo, wParam, lParam);
// Last, try the application in case it wants to override events
//
if (GetApplication()->Find(eventInfo))
return GetApplication()->Dispatch(eventInfo, wParam, lParam);
return 0;
}
//
// Insert our menus into a provided menu bar, possibly merging them with a
// servers.
//
bool
TOleFrame::EvOcAppInsMenus(TOcMenuDescr far& sharedMenu)
{
if (HOldMenu) {
TRACEX(OwlOleMenu, 0, "EvOcAppInsMenus called while HOldMenu is " << hex <<
(uint)HOldMenu);
return true;
}
// Recreate a temporary composite menu for frame
//
TMenuDescr compMenuDesc; // empty menudescr
if (GetMenuDescr()) {
compMenuDesc.Merge(*GetMenuDescr());
// Mask off the server menus
//
compMenuDesc.Merge(TMenuDescr(0, 0, -1, 0, -1, 0, -1));
}
// Merge into the OLE shared menubar
//
TMenuDescr shMenuDescr(sharedMenu.HMenu,
sharedMenu.Width[0],
sharedMenu.Width[1],
sharedMenu.Width[2],
sharedMenu.Width[3],
sharedMenu.Width[4],
sharedMenu.Width[5]);
shMenuDescr.Merge(compMenuDesc);
// Copy the shared menu widths back to the OC struct
//
for (int i = 0; i < 6; i++)
sharedMenu.Width[i] = shMenuDescr.GetGroupCount(i);
// Save the container popups so they can be destroyed later
//
StashContainerPopups(shMenuDescr);
TRACEX(OwlOleMenu, 0, "Merged menu " << hex << (uint)sharedMenu.HMenu);
return true;
}
//
// Now, actually set the merged menubar into our frame
//
bool
TOleFrame::EvOcAppMenus(TOcMenuDescr far& appMenus)
{
if (!appMenus.HMenu) {
if (HOldMenu) {
TRACEX(OwlOleMenu, 0, "EvOcAppMenus(0) resetting Old " << hex <<
(uint)HOldMenu);
TMenu oleMenu(*this);
SetMenu(HOldMenu); // assumes we are just restoring the old owl menu
HOldMenu = 0;
}
DestroyStashedPopups(); // destroy the popup copies we made
return true;
}
// Don't set the menu again if we are holding a merged one already
//
if (HOldMenu) {
TRACEX(OwlOleMenu, 0, "EvOcAppMenus called while HOldMenu is " << hex <<
(uint)HOldMenu);
return true;
}
HOldMenu = GetMenu();
TRACEX(OwlOleMenu, 0, "Saved Old " << hex << (uint)HOldMenu);
SetMenu(appMenus.HMenu);
TRACEX(OwlOleMenu, 0, "Set merged " << hex << (uint)appMenus.HMenu);
return true;
}
//
// Process accelerators and other queued messages from the server's queue in
// our app
//
bool
TOleFrame::EvOcAppProcessMsg(MSG far* msg)
{
#if defined(BI_DATA_NEAR)
MSG nearMsg = *msg;
bool ret = GetApplication()->ProcessAppMsg(nearMsg);
*msg = nearMsg;
return ret;
#else
return GetApplication()->ProcessAppMsg(*msg);
#endif
}
//
// Let the server know our frame's client rect, minus the status bar height,
// if there is one
//
bool
TOleFrame::EvOcAppFrameRect(TRect far* rect)
{
PRECONDITION(rect);
*rect = GetClientRect();
TWindow* sb = ChildWithId(IDW_STATUSBAR);
if (sb) {
TRect sbr = sb->GetClientRect();
rect->bottom -= sbr.bottom+1;
}
return true;
}
//
// Let the server know that we can handle border adornments on all four edges
//
bool
TOleFrame::EvOcAppBorderSpaceReq(TRect far* /*space*/)
{
return true;
}
//
// Actually create space on the requested edges for the server's adornments
//
bool
TOleFrame::EvOcAppBorderSpaceSet(TRect far* space)
{
// Resize pad decorations based on edges requested
//
int* edges = (int*)space; // treat space as array of 4 int edges
bool needLayout = false;
for (int i = 0; i < 4; i++) {
TWindow* pad = ChildWithId(IDW_PADDECORATION+i);
if (pad) {
int edge = edges && edges[i] ? edges[i]+1 : 1;
if (i%1 == 0 && pad->Attr.W != edge || // left & right edge
i%1 == 1 && pad->Attr.H != edge) { // top & bottom edge
TLayoutMetrics m;
GetChildLayoutMetrics(*pad, m);
pad->Attr.H = pad->Attr.W = edge; // set both axis, one will be stretched
SetChildLayoutMetrics(*pad, m);
needLayout = true;
}
}
}
// Turn on/off control bar as needed
//
TWindow* tb = ChildWithId(IDW_TOOLBAR);
if (tb)
if (space && tb->IsWindowVisible() || !space && !tb->IsWindowVisible()) {
SendMessage(WM_COMMAND, IDW_TOOLBAR); // toggle tool bar on/off
needLayout = false; // layout already done now by decorated frame.
}
// Now do layout once at the end to reduce repaint
//
if (needLayout)
Layout();
return true;
}
//
// Display the servers status messages on our status bar
//
void
TOleFrame::EvOcAppStatusText(const char far* text)
{
TMessageBar* mb = TYPESAFE_DOWNCAST(ChildWithId(IDW_STATUSBAR), TMessageBar);
if (mb) {
//mb->SetHintText(text); // is the text a hint, or general status??
#if defined(BI_DATA_NEAR)
mb->SetText(string(text).c_str());
#else
mb->SetText(text);
#endif
}
}
//
// Save off the popup menu handles that are copies so that we can destroy
// them later. Keep track of active object menus, to allow cleanup when
// the last one goes away.
//
void TOleFrame::StashContainerPopups(const TMenuDescr& shMenuDescr)
{
StashCount++;
int m = 0;
for (int i = 0; i < 6; i++) {
if (i%2 == 0)
for (int j = 0; j < shMenuDescr.GetGroupCount(i); j++) {
uint state = shMenuDescr.GetMenuState(m+j, MF_BYPOSITION);
if (state == uint(-1))
continue;
TRACEX(OwlOleMenu, 1, "Stashing " << hex << (uint)shMenuDescr.GetSubMenu(m+j));
StashedContainerPopups.AppendMenu(state, TMenu(shMenuDescr.GetSubMenu(m+j)), "");
}
m += shMenuDescr.GetGroupCount(i);
}
}
//
// Throw away our popup copies that are no longer needed, when the last active
// object is deactivated.
//
void TOleFrame::DestroyStashedPopups()
{
if (--StashCount)
return;
while (StashedContainerPopups.GetMenuItemCount()) {
TRACEX(OwlOleMenu, 1, "Destroying " << hex << (uint)StashedContainerPopups.GetSubMenu(0));
StashedContainerPopups.DeleteMenu(0, MF_BYPOSITION);
}
}
//
// Restore the UI back to pre-inplace server state. Remove the border space pads
// and restore the menu.
//
void
TOleFrame::EvOcAppRestoreUI()
{
// Only restore the old menu if we are holding a merged one
//
if (HOldMenu) {
TRACEX(OwlOleMenu, 0, "EvOcAppRestoreUI resetting Old " << hex <<
(uint)HOldMenu);
TMenu oleMenu(*this);
SetMenu(HOldMenu); // assumes we are just restoring the old owl menu
HOldMenu = 0;
}
// Remove pad decorations & restore our toobar if we have one
//
EvOcAppBorderSpaceSet(0);
}
//
// Called by TOcRemView::Close when last embedding is closed
// If that's the only reason the app is up we need to shut ourselves down
//
bool
TOleFrame::EvOcAppShutdown()
{
// If TOleFrame was created purely for embedded server, then
// we want to shut down the app when nobody is using the server.
// The amEmbedding flag will be set to false if user created normal
// document in this frame.
//
if (OcShutDown == DontCare && OcApp->IsOptionSet(amEmbedding)) {
// The shut down is initiated by OCF
//
OcShutDown = ServerInitiated;
// Post frame close to kill the app later
//
PostMessage(WM_CLOSE);
return true;
}
else {
// If the last view closing caused the ocapp to shutdown, then close this
// frame.
//
if (OcApp->IsOptionSet(amEmbedding) && OcShutDown == ViewInitiated)
PostMessage(WM_CLOSE);
return false; // Shut down initiated by user
}
}