home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C Programming Starter Kit 2.0
/
SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso
/
bc45
/
owlsrc.pak
/
OLEWINDO.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-23
|
38KB
|
1,672 lines
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// Implementation of TOleWindow. Window class that supports Ole2
// container & server using OCF TOcView & TOcRemView
//----------------------------------------------------------------------------
#define INC_OLE2
#include <owl/owlpch.h>
#include <owl/window.h>
#include <owl/gdiobjec.h>
#include <owl/uihandle.h>
#include <owl/scroller.h>
#include <ocf/ocdoc.h>
#include <ocf/ocview.h>
#include <owl/docview.rh>
#include <owl/oleview.rh>
#include <owl/oleframe.h>
#include <owl/olewindo.h>
#include <owl/oledlg.h>
//----------------------------------------------------------------------------
// Size of rectangle in two clks must occur to be a doubleClick
//
#if !defined(BI_PLAT_WIN32)
TSize DblClkDelta(3, 3);
#else
TSize DblClkDelta(GetSystemMetrics(SM_CXDOUBLECLK)/2,
GetSystemMetrics(SM_CYDOUBLECLK)/2);
#endif
//----------------------------------------------------------------------------
// TOleClientDC
//
TOleClientDC::TOleClientDC(TOleWindow& win, bool scale)
:
TClientDC(win)
{
win.SetupDC(*this, scale);
}
//----------------------------------------------------------------------------
// TOleWindow
//
DEFINE_RESPONSE_TABLE1(TOleWindow, TWindow)
EV_WM_PAINT,
EV_WM_LBUTTONDOWN,
EV_WM_RBUTTONDOWN,
EV_WM_LBUTTONDBLCLK,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_WM_SIZE,
EV_WM_MDIACTIVATE,
EV_WM_MOUSEACTIVATE,
EV_WM_SETFOCUS,
EV_WM_SETCURSOR,
EV_WM_DROPFILES,
EV_WM_VSCROLL,
EV_WM_HSCROLL,
EV_WM_MENUSELECT,
EV_COMMAND_ENABLE(CM_FILECLOSE, CeFileClose),
EV_COMMAND(CM_EDITDELETE, CmEditDelete),
EV_COMMAND_ENABLE(CM_EDITDELETE, CeEditDelete),
EV_COMMAND(CM_EDITCUT, CmEditCut),
EV_COMMAND_ENABLE(CM_EDITCUT, CeEditCut),
EV_COMMAND(CM_EDITCOPY, CmEditCopy),
EV_COMMAND_ENABLE(CM_EDITCOPY, CeEditCopy),
EV_COMMAND(CM_EDITPASTE, CmEditPaste),
EV_COMMAND_ENABLE(CM_EDITPASTE, CeEditPaste),
EV_COMMAND(CM_EDITPASTESPECIAL, CmEditPasteSpecial),
EV_COMMAND_ENABLE(CM_EDITPASTESPECIAL, CeEditPasteSpecial),
EV_COMMAND(CM_EDITPASTELINK, CmEditPasteLink),
EV_COMMAND_ENABLE(CM_EDITPASTELINK, CeEditPasteLink),
EV_COMMAND(CM_EDITINSERTOBJECT, CmEditInsertObject),
EV_COMMAND_ENABLE(CM_EDITINSERTOBJECT, CeEditInsertObject),
EV_COMMAND_ENABLE(CM_EDITLINKS, CeEditLinks),
EV_COMMAND(CM_EDITLINKS, CmEditLinks),
EV_COMMAND_ENABLE(CM_EDITOBJECT, CeEditObject),
EV_COMMAND_ENABLE(CM_EDITCONVERT, CeEditConvert),
EV_COMMAND(CM_EDITCONVERT, CmEditConvert),
EV_COMMAND_ENABLE(CM_EDITSHOWOBJECTS, CeEditShowObjects),
EV_COMMAND(CM_EDITSHOWOBJECTS, CmEditShowObjects),
EV_MESSAGE(WM_OCEVENT, EvOcEvent),
// EV_OC_VIEWDISCARDUNDO, //!CQ not processing this yet...
// Container specific messages
//
EV_OC_VIEWPARTINVALID,
EV_OC_VIEWTITLE,
EV_OC_VIEWSETTITLE,
EV_OC_VIEWBORDERSPACEREQ,
EV_OC_VIEWBORDERSPACESET,
EV_OC_VIEWDROP,
EV_OC_VIEWDRAG,
EV_OC_VIEWSCROLL,
EV_OC_VIEWGETSCALE,
EV_OC_VIEWGETSITERECT,
EV_OC_VIEWSETSITERECT,
EV_OC_VIEWPARTACTIVATE,
EV_OC_VIEWPASTEOBJECT,
// Server specific messages
//
EV_OC_VIEWPAINT,
EV_OC_VIEWSAVEPART,
EV_OC_VIEWLOADPART,
EV_OC_VIEWINSMENUS,
EV_OC_VIEWSHOWTOOLS,
EV_OC_VIEWGETPALETTE,
EV_OC_VIEWCLIPDATA,
EV_OC_VIEWSETDATA,
EV_OC_VIEWCLOSE,
EV_OC_VIEWPARTSIZE,
EV_OC_VIEWOPENDOC,
EV_OC_VIEWATTACHWINDOW,
EV_OC_VIEWSETSCALE,
EV_OC_VIEWGETITEMNAME,
EV_OC_VIEWSETLINK,
EV_OC_VIEWBREAKLINK,
EV_OC_VIEWDOVERB,
END_RESPONSE_TABLE;
TOleWindow::TOleWindow(TWindow* parent, TModule* module)
:
TWindow(parent, 0, module),
Pos(0, 0, 0, 0),
Remote(false),
ShowObjects(false)
{
// Derived class will need to create a OcDocument object to hold the ole
// parts that we create and a OcView to provide ole services
//
OcApp = 0;
OcDoc = 0;
OcView = 0;
Init();
}
void
TOleWindow::Init()
{
// Clip children to not paint on in-place servers, & clip siblings to not
// paint on floating tool palettes
//
Attr.Style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
Attr.AccelTable = IDA_OLEVIEW;
DragHit = TUIHandle::Outside;
DragPart = 0;
DragDC = 0;
// Minimum part size
//
HDC dc = GetDC(0);
MinWidth = GetDeviceCaps(dc, LOGPIXELSX) / 4;
MinHeight = GetDeviceCaps(dc, LOGPIXELSY) / 4;
ReleaseDC(0, dc);
// Snag the OcApp from the TOleFrame object for quick reference
//
TOleFrame* olefr = TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(), TOleFrame);
CHECK(olefr);
OcApp = olefr->GetOcApp();
OcApp->AddRef();
}
TOleWindow::~TOleWindow()
{
// Let the OC objects go. They will delete themselves when they can
// If it's a remote view, then the last release is called by the container.
//
if (OcDoc)
OcDoc->Close(); // close all the embedded parts first
if (OcView && !IsRemote()) {
OcView->ReleaseObject(); // use ReleaseObject here to tell it we are gone
OcView = 0;
}
delete OcDoc;
if (OcApp) {
OcApp->Release();
OcApp = 0;
}
}
//
// Perform normal SetupWindow, plus let the OcView object know our HWND so that
// it can talk to us.
//
void
TOleWindow::SetupWindow()
{
if (!OcView)
CreateOcView(0, false, 0); // don't have much context by this time
CHECK(OcView);
TWindow::SetupWindow();
OcView->SetupWindow(*this, IsRemote());
}
//
// Called to perform the actual setting up of the OcView member
// Derived class needs to construct the TOcView/TOcRemView here & return it
//
TOcView*
TOleWindow::CreateOcView(TRegLink* link, bool isRemote, IUnknown* outer)
{
if (!OcDoc)
OcDoc = new TOcDocument(*GetOcApp());
if (!OcView) {
TRegList* regList = link ? &link->GetRegList() : 0;
// Create a remote view on the server document if it embeded, else make a
// normal, container view
//
if (isRemote)
OcView = new TOcRemView(*GetOcDoc(), regList, outer);
else
OcView = new TOcView(*GetOcDoc(), regList, outer);
Remote = isRemote;
}
return OcView;
}
//
// Handle the command enabling for a range of command IDs for verbs
//
void
TOleWindow::EvCommandEnable(TCommandEnabler& commandEnabler)
{
if (CM_EDITFIRSTVERB <= commandEnabler.Id && commandEnabler.Id <= CM_EDITLASTVERB) {
CeEditVerbs(commandEnabler);
}
else if (IsRemote()) {
// Get the focus, in case it is a child that should receive the cmds
// fall back to this window in case the Ole menu bar stole focus!
//
HWND hCmdTarget = ::GetFocus();
if (hCmdTarget != HWindow && !IsChild(hCmdTarget))
hCmdTarget = HWindow;
RouteCommandEnable(hCmdTarget, commandEnabler);
}
else {
TWindow::EvCommandEnable(commandEnabler);
}
}
//
// processing a range of command IDs for verbs
//
LRESULT
TOleWindow::EvCommand(uint id, HWND hWndCtl, uint notifyCode)
{
if (hWndCtl == 0) {
if (CM_EDITFIRSTVERB <= id && id <= CM_EDITLASTVERB) {
EvDoVerb(id - CM_EDITFIRSTVERB);
return 0;
}
}
return TWindow::EvCommand(id, hWndCtl, notifyCode);
}
//
// Intercept CanClose() to interpose OpenEdit semantics. Ole 2 servers don't
// prompt the user on close--just save & close.
//
bool
TOleWindow::CanClose()
{
// We don't want to close the view for DLL servers
//
if (IsOpenEditing() && !OcApp->IsOptionSet(amExeMode)) {
TOleFrame* olefr = TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(), TOleFrame);
CHECK(olefr);
olefr->ShowWindow(SW_HIDE);
OleShutDown();
return false;
}
if (GetOcRemView() || TWindow::CanClose()) {
if (OcDoc)
OcDoc->Close();
return true;
}
return false;
}
//
// Notify part
//
void
TOleWindow::InvalidatePart(TOcInvalidate invalid)
{
if (GetOcRemView())
GetOcRemView()->Invalidate(invalid);
}
//
// Is the window in Open-Edit mode
//
bool
TOleWindow::IsOpenEditing() const
{
TOcRemView* ocRemView = const_cast<TOleWindow*>(this)->GetOcRemView();
return ocRemView && ocRemView->GetState() == TOcRemView::OpenEditing;
}
//
// Handles the file File>Close menu option for server app
//
void
TOleWindow::CeFileClose(TCommandEnabler& ce)
{
// if open editing server, reflect the container's name in "close" option
//
if (IsOpenEditing()) {
string optName = GetModule()->LoadString(IDS_CLOSESERVER);
TString title = GetOcRemView()->GetContainerTitle();
if (title.Length() > 0)
optName += title;
ce.SetText(optName.c_str());
}
}
//
//
//
void
TOleWindow::CeEditInsertObject(TCommandEnabler& ce)
{
ce.Enable(OcApp && OcView);
}
//
// Get the insertion point for the embedded object in device units.
// Currently we're using only the top left point for position, size is
// redundant.
//
void
TOleWindow::GetInsertPosition(TRect& rect)
{
TOleClientDC dc(*this);
// Default insertion point is at 0.5" away from current viewport origin
//
rect.left = dc.GetDeviceCaps(LOGPIXELSX) / 2; // in pixels
rect.top = dc.GetDeviceCaps(LOGPIXELSY) / 2; // in pixels
// Adjust the position of embedded object to be in pixels and reflect the
// zoom factor.
//
dc.LPtoDP((TPoint*)&rect, 1);
// No size yet.
//
rect.right = rect.left;
rect.bottom = rect.top;
}
//
// Insert an OLE object into the view
//
void
TOleWindow::CmEditInsertObject()
{
PRECONDITION(OcView);
TOcInitInfo initInfo(OcView);
if (OcApp->Browse(initInfo)) {
TRect rect;
GetInsertPosition(rect);
SetSelection(new TOcPart(*GetOcDoc(), initInfo, rect));
OcView->Rename();
InvalidatePart(invView);
}
}
void
TOleWindow::CeEditDelete(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
void
TOleWindow::CmEditDelete()
{
if (!DragPart)
return;
TOcPartChangeInfo changeInfo(DragPart, invData|invView);
EvOcViewPartInvalid(changeInfo);
DragPart->Delete();
DragPart = 0;
}
void
TOleWindow::CeEditCut(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
void
TOleWindow::CmEditCut()
{
DragPart->Detach();
OcApp->Copy(DragPart);
SetSelection(0);
}
void
TOleWindow::CeEditCopy(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
void
TOleWindow::CmEditCopy()
{
if (DragPart)
OcApp->Copy(DragPart);
}
void
TOleWindow::CeEditPasteLink(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnablePasteLink, OcView));
}
void
TOleWindow::CmEditPasteLink()
{
OcView->Paste(true);
}
void
TOleWindow::CeEditPaste(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnablePaste, OcView));
}
void
TOleWindow::CmEditPaste()
{
OcView->Paste(false);
InvalidatePart(invView);
}
void
TOleWindow::CeEditPasteSpecial(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnableBrowseClipboard, OcView));
}
void
TOleWindow::CmEditPasteSpecial()
{
TOcInitInfo initInfo(GetOcView());
if (GetOcView()->BrowseClipboard(initInfo)) {
if (!OcView->PasteNative(initInfo)) { // Not native data
EvOcViewPasteObject(initInfo);
}
InvalidatePart(invView);
}
}
//
// Append the object menu and enable it
//
void
TOleWindow::CeEditObject(TCommandEnabler& ce)
{
// Downcast to get at submenu item
//
TMenuItemEnabler* me = TYPESAFE_DOWNCAST(&ce, TMenuItemEnabler);
if (!me)
return;
int verbPos = me->GetPosition(); // remember the verb menu position
TMenu editMenu(me->GetMenu());
string optName = GetModule()->LoadString(IDS_EDITOBJECT);
if (!DragPart) {
// Remove the verb menu, if any
//
if (editMenu.GetSubMenu(verbPos)) {
editMenu.DeleteMenu(verbPos, MF_BYPOSITION);
editMenu.InsertMenu(verbPos, MF_GRAYED | MF_BYPOSITION | MF_STRING,
CM_EDITOBJECT, optName.c_str());
}
ce.Enable(false);
return;
}
// Add verb menu
//
TOcVerb ocVerb;
TMenu* verbMenu = CreateVerbPopup(ocVerb);
string newMenuName(OleStr(ocVerb.TypeName));
newMenuName += ' ';
newMenuName += optName;
editMenu.ModifyMenu(verbPos, MF_ENABLED | MF_BYPOSITION | MF_POPUP,
(uint)verbMenu->GetHandle(), newMenuName.c_str());
delete verbMenu;
ce.Enable(true);
}
//
// Command enabler for "Edit" "Convert..." option
//
void
TOleWindow::CeEditConvert(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
void
TOleWindow::CmEditConvert()
{
OcApp->Convert(DragPart, false);
}
//
// Command enabler for "Edit" "Links..." option
//
void
TOleWindow::CeEditLinks(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnableBrowseLinks, OcView));
}
void
TOleWindow::CmEditLinks()
{
PRECONDITION(OcView);
OcView->BrowseLinks();
}
void
TOleWindow::CeEditVerbs(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
void
TOleWindow::CmEditShowObjects()
{
ShowObjects = !ShowObjects;
Invalidate();
}
void
TOleWindow::CeEditShowObjects(TCommandEnabler& ce)
{
ce.SetCheck(ShowObjects ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
}
//
// Has in-place active part?
//
bool
TOleWindow::HasActivePart()
{
return OcView->GetActivePart() != 0;
}
//
// Change cursor shape if within an embedded object
//
bool
TOleWindow::EvSetCursor(HWND wnd, uint hitTest, uint mouseMsg)
{
TPoint pt;
GetCursorPos(pt);
ScreenToClient(pt);
TOcPart* p = OcView->GetActivePart();
if (hitTest == HTCLIENT) {
if (p) { // there is an activated part
TUIHandle handle(p->GetRect(), TUIHandle::Framed);
if (handle.HitTest(pt) == TUIHandle::MidCenter) {
return false; // let the inplace server set its cursor shape
}
else { // use arrow cursor
::SetCursor(::LoadCursor(0, IDC_ARROW));
return true;
}
}
}
// Set cursor for resize when cursor over inactive part
//
if (!p && DragPart) {
TRect rect(DragPart->GetRect());
TOleClientDC dc(*this);
dc.LPtoDP((TPoint*)&rect, 2);
TUIHandle handle(rect, TUIHandle::HandlesIn | TUIHandle::Grapples |
TUIHandle::Framed);
if (handle.HitTest(pt) != TUIHandle::Outside)
::SetCursor(::LoadCursor(0, TResId(handle.GetCursorId(handle.HitTest(pt)))));
else
::SetCursor(::LoadCursor(0, IDC_ARROW));
return true;
}
return ShowCursor(wnd, hitTest, mouseMsg);
}
//
// Show cursor when it's not in an embedded object
//
bool
TOleWindow::ShowCursor(HWND /*wnd*/, uint /*hitTest*/, uint /*mouseMsg*/)
{
::SetCursor(::LoadCursor(0, IDC_ARROW));
return true;
}
//
// Accept dropped file from file manager
//
void
TOleWindow::EvDropFiles(TDropInfo dropInfo)
{
int fileCount = dropInfo.DragQueryFileCount();
for (int index = 0; index < fileCount; index++) {
int fileLength = dropInfo.DragQueryFileNameLen(index)+1;
OLECHAR* filePath = new OLECHAR[fileLength];
dropInfo.DragQueryFile(index, OleStr(filePath), fileLength);
TOcInitInfo initInfo(ihEmbed, iwFile, OcView);
initInfo.Path = filePath;
TRect rect;
GetInsertPosition(rect);
SetSelection(new TOcPart(*GetOcDoc(), initInfo, rect));
OcView->Rename();
InvalidatePart(invView);
delete [] filePath;
}
dropInfo.DragFinish();
}
//
// Handle left double-click message
//
void
TOleWindow::EvLButtonDblClk(uint modKeys, TPoint& point)
{
PRECONDITION(GetOcDoc() && GetOcView());
TOleClientDC dc(*this);
dc.DPtoLP(&point);
TOcPart* p = GetOcDoc()->GetParts().Locate(point);
if (modKeys & MK_CONTROL) {
if (p)
p->Open(true); // Ctrl key forces open editing
}
else {
SetSelection(p);
if (p && p == GetOcView()->GetActivePart()) { // resync the active flag
p->Activate(false);
}
GetOcView()->ActivatePart(p); // In-place activation
}
}
//
// Set new selection, clear/set handles around objects
//
void
TOleWindow::SetSelection(TOcPart* part)
{
if (part == DragPart)
return;
// Invalidate old part
//
TOcPartChangeInfo changeInfo(DragPart, invView);
if (DragPart) {
DragPart->Select(false);
DragPart->Activate(false);
EvOcViewPartInvalid(changeInfo);
}
DragPart = part;
changeInfo.SetPart(DragPart);
if (DragPart) {
part->Select(true); // select this one
EvOcViewPartInvalid(changeInfo);
}
}
//
// Create popup menu
//
void
TOleWindow::EvRButtonDown(uint, TPoint& point)
{
PRECONDITION(GetOcDoc());
// Perform hit test on parts...
//
TPoint oldPoint = point;
TOleClientDC dc(*this);
dc.DPtoLP(&point);
TOcPart* p = GetOcDoc()->GetParts().Locate(point);
SetSelection(p);
if (DragPart) {
// Create popup menu
//
TMenu menu(GetModule()->LoadMenu(IDM_OLEPOPUP), AutoDelete);
TPopupMenu popMenu(menu.GetSubMenu(0));
if (popMenu.GetHandle()) {
TOcVerb ocVerb;
TMenu* verbMenu = CreateVerbPopup(ocVerb);
string optName = GetModule()->LoadString(IDS_EDITOBJECT);
string newMenuName(OleStr(ocVerb.TypeName));
newMenuName += ' ';
newMenuName += optName;
popMenu.ModifyMenu(CM_EDITOBJECT, MF_ENABLED | MF_BYCOMMAND | MF_POPUP,
(uint)verbMenu->GetHandle(), newMenuName.c_str());
delete verbMenu;
// Add the verb menu
//
ClientToScreen(oldPoint);
// Route commands through main window
//
popMenu.TrackPopupMenu(TPM_RIGHTBUTTON, oldPoint, 0, *this);
}
}
}
//
// Deactivate active embedded object if any
//
bool
TOleWindow::Deactivate()
{
// Deactivate active part, if any
//
if (DragPart && DragPart->IsActive()) {
SetSelection(0);
return true;
}
else
return false;
}
//
// Select embedded object, point is in logical units
//
bool
TOleWindow::Select(uint, TPoint& point)
{
PRECONDITION(GetOcDoc());
// If the point is not on the current selection, perform hit test on parts
// to find & select one
//
if (!DragPart || !DragPart->IsVisible(TRect(point, TSize(1,1))))
SetSelection(GetOcDoc()->GetParts().Locate(point));
// If a part is now selected, manipulate it.
//
if (DragPart) {
DragRect = DragPart->GetRect();
DragRect.right++;
DragRect.bottom++;
if (DragPart->IsSelected()) {
TUIHandle handle(DragRect, TUIHandle::HandlesIn | TUIHandle::Grapples |
TUIHandle::Framed);
DragHit = handle.HitTest(point);
}
else {
DragHit = TUIHandle::MidCenter;
}
if (!DragDC)
DragDC = new TOleClientDC(*this);
DragDC->DrawFocusRect(DragRect);
DragStart = DragPt = point;
SetCapture();
return true;
}
return false;
}
//
// Check if any embedded object is selected
//
void
TOleWindow::EvLButtonDown(uint modKeys, TPoint& point)
{
// Deactivating in-place active object, if any
//
if (Deactivate())
return;
// Convert the point to logical unit
//
if (!DragDC)
DragDC = new TOleClientDC(*this);
DragDC->DPtoLP(&point);
Select(modKeys, point);
}
//
// Is the logical point within the client area?
//
bool
TOleWindow::InClient(TDC& dc, TPoint& point)
{
TRect logicalRect = GetClientRect();
dc.DPtoLP((TPoint*)&logicalRect, 2);
return logicalRect.Contains(point);
}
//
//
//
void
TOleWindow::EvMouseMove(uint modKeys, TPoint& point)
{
if (!DragDC)
return;
// Convert the point to logical unit
//
DragDC->DPtoLP(&point);
// A MidCenter hit is a move
//
if (DragHit == TUIHandle::MidCenter) {
DragDC->DrawFocusRect(DragRect); // erase old rect
// Account for case when the hand is a little shaky and a double click for
// open editing generates a move msg. as a side-effect
//
bool force = ((modKeys & MK_CONTROL) || (::GetKeyState(VK_MENU)&0x8000)) &&
(abs(point.x-DragStart.x) > DblClkDelta.cx ||
abs(point.y-DragStart.y) > DblClkDelta.cy);
// Start drag & drop if point is outside client, or Ctrl or Alt is pressed
//
if (DragPart && (!InClient(*DragDC, point) || force)) {
TOcDropAction outAction;
OcApp->Drag(DragPart, daDropCopy | daDropMove | daDropLink, outAction);
TOcPartChangeInfo changeInfo(DragPart, invView | invData);
EvOcViewPartInvalid(changeInfo);
DragHit = TUIHandle::Outside;
ReleaseCapture();
// Delete the dragged part since it was dragged out
//
if (outAction == daDropMove) {
DragPart->Delete();
DragPart = 0;
}
}
else {
TPoint delta = point - DragPt;
DragRect.Offset(delta.x, delta.y);
DragDC->DrawFocusRect(DragRect); // draw new rect
}
}
// All other non-outside hits are resizes
//
else if (DragHit != TUIHandle::Outside) { // handle
DragDC->DrawFocusRect(DragRect); // erase old rect
int dl = (DragHit%3) == 0 ? point.x - DragPt.x : 0;
int dr = (DragHit%3) == 2 ? point.x - DragPt.x : 0;
int dt = (DragHit/3) == 0 ? point.y - DragPt.y : 0;
int db = (DragHit/3) == 2 ? point.y - DragPt.y : 0;
// maintain minimum part size
//
if ((DragRect.Width() + dr - dl) >= MinWidth) {
DragRect.left += dl;
DragRect.right += dr;
}
if ((DragRect.Height() + db - dt) >= MinHeight) {
DragRect.top += dt;
DragRect.bottom += db;
}
DragDC->DrawFocusRect(DragRect); // draw new rect
}
DragPt = point;
}
void
TOleWindow::EvLButtonUp(uint /*modKeys*/, TPoint& /*point*/)
{
if (DragPart) {
TOcPartChangeInfo changeInfo(DragPart, invView | invData);
// All non-outside hits are moves or resizes
//
if (DragHit != TUIHandle::Outside) {
EvOcViewPartInvalid(changeInfo);
DragPart->SetPos(DragRect.TopLeft());
if (DragHit != TUIHandle::MidCenter)
DragPart->SetSize(DragRect.Size()); // A MidCenter hit is a move only
EvOcViewPartInvalid(changeInfo);
}
InvalidatePart(invView);
DragHit = TUIHandle::Outside;
ReleaseCapture();
}
if (DragDC) {
delete DragDC;
DragDC = 0;
DragRect.SetNull();
}
}
//
// Let OcView know that the view window has changed sizes
//
void
TOleWindow::EvSize(uint sizeType, TSize& size)
{
TWindow::EvSize(sizeType, size);
OcView->EvResize();
}
//
// Handle message forwarded from our mdi child frame (if any) to let OcView
// know that the view window has changed size
//
void
TOleWindow::EvMDIActivate(HWND hWndActivated, HWND /*hWndDeactivated*/)
{
OcView->EvActivate(hWndActivated == *Parent);
}
uint
TOleWindow::EvMouseActivate(HWND topParent, uint /*hitCode*/, uint /*msg*/)
{
if (topParent)
ForwardMessage(topParent);
return MA_ACTIVATE;
}
//
// May need to pass focus to an in-place server if there is one
//
void
TOleWindow::EvSetFocus(HWND hWndLostFocus)
{
TWindow::EvSetFocus(hWndLostFocus);
OcView->EvSetFocus(true); // Maybe active part (if any) wants focus
}
//
// response method for an incoming WM_VSCROLL message
//
void
TOleWindow::EvHScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
{
TWindow::EvHScroll(scrollCode, thumbPos, hWndCtl);
InvalidatePart(invView);
}
//
// response method for an incoming WM_VSCROLL message
//
void
TOleWindow::EvVScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
{
TWindow::EvVScroll(scrollCode, thumbPos, hWndCtl);
InvalidatePart(invView);
}
//
// Handle WM_MENUSELECT to provide hint text in the container's status bar
// based on the menu item id. Treat popup items seperatly and ask them for
// their ids. Similar to code in TDecoratedFrame.
//
void
TOleWindow::EvMenuSelect(uint menuItemId, uint flags, HMENU hMenu)
{
if (GetOcRemView()) {
if (flags == 0xFFFF && hMenu == 0) { // menu closing
GetOcRemView()->SetContainerStatusText("");
return;
}
else if (flags & MF_POPUP) {
TMenu popupMenu(hMenu);
int count = popupMenu.GetMenuItemCount();
for (int pos = 0;
pos < count && popupMenu.GetSubMenu(pos) != HMENU(menuItemId);
pos++)
;
menuItemId = popupMenu.GetMenuItemID(pos);
}
else if (flags & (MF_SEPARATOR | MF_MENUBREAK | MF_MENUBARBREAK)
|| (menuItemId >= IDW_FIRSTMDICHILD && menuItemId < IDW_FIRSTMDICHILD+9)) {
menuItemId = 0; // display an empty help message
}
string text = GetModule()->LoadString(menuItemId);
GetOcRemView()->SetContainerStatusText(text.c_str());
}
else
TWindow::EvMenuSelect(menuItemId, flags, hMenu);
}
//
// Handle & sub-dispatch the OC event message.
//
LRESULT
TOleWindow::EvOcEvent(WPARAM wParam, LPARAM lParam)
{
TEventHandler::TEventInfo eventInfo(WM_OCEVENT, wParam);
if (Find(eventInfo))
return Dispatch(eventInfo, wParam, lParam);
return 0;
}
//
// Return our frame's title
//
const char far*
TOleWindow::EvOcViewTitle()
{
char title[128];
Parent->GetWindowText(title, sizeof title);
ContainerName = title;
return ContainerName.c_str();
}
//
// Set our frame's title
//
void
TOleWindow::EvOcViewSetTitle(const char far* title)
{
Parent->SetWindowText(title);
}
//
// Can the server put toolbars in our view? Say no--make him use the app frame
//
bool
TOleWindow::EvOcViewBorderSpaceReq(TRect far* /*space*/)
{
return false;
}
//
// Can the server put toolbars in our view? Say no--make him use the app frame
//
bool
TOleWindow::EvOcViewBorderSpaceSet(TRect far* /*space*/)
{
return false;
}
//
// Can the indicated ole object be dropped here? Say yes to everything as a
// default
//
bool
TOleWindow::EvOcViewDrop(TOcDragDrop far& /*ddInfo*/)
{
return true; // ok to drop anything, we can take it...
}
//
// Provide drag UI feedback
//
bool
TOleWindow::EvOcViewDrag(TOcDragDrop far& ddInfo)
{
TClientDC dc(*this);
TPen pen(TColor(128, 128, 128), 4, PS_DOT);
dc.SelectObject(pen);
dc.SelectStockObject(HOLLOW_BRUSH);
dc.SetROP2(R2_NOTXORPEN);
dc.Rectangle(*ddInfo.Pos);
return true;
}
//
// Scroll our view window. Update any internal state as needed. This is called
// when the server is sizing, or a drop interaction is near the edge
//
bool
TOleWindow::EvOcViewScroll(TOcScrollDir /*scrollDir*/)
{
return false;
}
//
// Convert the part rect into device units
//
bool
TOleWindow::EvOcViewGetSiteRect(TRect far* rect)
{
TOleClientDC dc(*this);
return dc.LPtoDP((TPoint*)rect, 2);
}
//
// Convert the part rect into logical units
//
bool
TOleWindow::EvOcViewSetSiteRect(TRect far* rect)
{
TOleClientDC dc(*this);
return dc.DPtoLP((TPoint*)rect, 2);
}
//
// Handle the scaling for server app
//
bool
TOleWindow::EvOcViewGetScale(TOcScaleFactor& scaleFactor)
{
scaleFactor = Scale;
return true;
}
//
// Handle the scaling for server app
//
bool
TOleWindow::EvOcViewPartActivate(TOcPart& ocPart)
{
SetSelection(&ocPart);
return true;
}
//
// Handle the scaling for server app
//
bool
TOleWindow::EvOcViewPasteObject(TOcInitInfo& init)
{
TRect rect;
GetInsertPosition(rect);
new TOcPart(*GetOcDoc(), init, rect);
init.ReleaseDataObject();
return true;
}
//
// Ask server to paint itself in the position and dc provided
//
bool
TOleWindow::EvOcViewPaint(TOcViewPaint far& vp)
{
// paint according to the view paint structure
//
TDC dc(vp.DC);
Pos = *vp.Pos;
// Paint embedded objects
//
bool metafile = dc.GetDeviceCaps(TECHNOLOGY) == DT_METAFILE;
SetupDC(dc, !metafile);
if (vp.Moniker) {
PaintLink(dc, true, Pos, *vp.Moniker);
}
else if (vp.PaintSelection) {
PaintSelection(dc, true, Pos, vp.UserData);
}
else {
Paint(dc, true, Pos);
PaintParts(dc, true, Pos, metafile);
}
Pos.SetNull();
return true;
}
//
// TOcRemView is going away, disconnect TOleWindow with it so we don't use it
// later. If this is a remote view, then close the doc too.
//
bool
TOleWindow::EvOcViewClose()
{
if (IsRemote() && OcDoc)
OcDoc->Close();
OcView = 0;
return true;
}
//
// Ask server to save itself in the IStorage
//
bool
TOleWindow::EvOcViewSavePart(TOcSaveLoad far& /*ocSave*/)
{
return true;
}
//
// Ask server to load itself from the IStorage
//
bool
TOleWindow::EvOcViewLoadPart(TOcSaveLoad far& /*ocLoad*/)
{
return true;
}
//
// Let container know about the server view size in pixels
//
bool
TOleWindow::EvOcViewPartSize(TOcPartSize far& /*size*/)
{
return false;
}
//
// Ask container to open an existing document
// Used for linking from embedding
//
bool
TOleWindow::EvOcViewOpenDoc(const char far* /*path*/)
{
return true;
}
//
// Insert server menu into the composite one
//
bool
TOleWindow::EvOcViewInsMenus(TOcMenuDescr far& /*sharedMenu*/)
{
return false;
}
//
// Request for server to put up its toolbar. This implementation assume that
// this server is single use, and the MainWindow's ToolBar is ours to snarf
//
bool
TOleWindow::EvOcViewShowTools(TOcToolBarInfo far& tbi)
{
TWindow* mainWindow = GetApplication()->GetMainWindow();
CHECK(mainWindow);
TWindow* toolBar = mainWindow->ChildWithId(IDW_TOOLBAR);
if (!toolBar)
return false;
tbi.HTopTB = (HWND)*toolBar;
return true;
}
//
// Get server's color palette
//
bool
TOleWindow::EvOcViewGetPalette(LOGPALETTE far* far* /*palette*/)
{
return false;
}
//
// Ask server to provide data according to the format in a handle
//
bool
TOleWindow::EvOcViewClipData(TOcFormatData far& /*format*/)
{
return false;
}
//
// Set format data into server
//
bool
TOleWindow::EvOcViewSetData(TOcFormatData far& /*format*/)
{
return false;
}
//
// Paint the embedded objects
//
bool
TOleWindow::PaintParts(TDC& dc, bool, TRect&, bool metafile)
{
if (!GetOcDoc())
return false;
TRect clientRect;
TRect logicalRect = GetClientRect();
if (IsRemote()) {
clientRect = GetWindowRect();
clientRect.Offset(-clientRect.left, -clientRect.top);
}
else {
clientRect = logicalRect;
}
TPoint scrollPos(0, 0);
if (!metafile) {
dc.DPtoLP((TPoint*)&logicalRect, 2);
}
else {
if (Scroller) {
scrollPos.x = (int)Scroller->XPos;
scrollPos.y = (int)Scroller->YPos;
}
}
for (TOcPartCollectionIter i(GetOcDoc()->GetParts()); i; i++) {
TOcPart& p = *i.Current();
if (p.IsVisible(logicalRect) || metafile) {
TRect r = p.GetRect();
r.Offset(-scrollPos.x, -scrollPos.y);
p.Draw(dc, r, clientRect, asDefault);
if (metafile)
continue;
// Paint selection
//
if ((p.IsSelected() || ShowObjects) && r.Width() > 0 && r.Height() > 0) {
uint handleStyle = p.IsLink() ? TUIHandle::DashFramed : TUIHandle::Framed;
if (p.IsSelected())
handleStyle |= TUIHandle::Grapples;
TUIHandle(r, handleStyle).Paint(dc);
}
}
}
return true;
}
//
// Change the scaling factor
//
void
TOleWindow::SetScale(uint16 percent)
{
Scale.SetScale(percent);
Invalidate();
}
//
// Get the logical unit per inch for document
//
void
TOleWindow::GetLogPerUnit(TSize& logPerUnit)
{
TScreenDC dc;
logPerUnit.cx = dc.GetDeviceCaps(LOGPIXELSX);
logPerUnit.cy = dc.GetDeviceCaps(LOGPIXELSY);
}
//
// Setup the dc before painting
//
void
TOleWindow::SetupDC(TDC& dc, bool scale)
{
dc.SetMapMode(MM_ANISOTROPIC);
// Setup window and viewport origin according to scroll amount
//
TPoint scrollPos(0, 0);
if (Scroller) {
scrollPos.x = (int)Scroller->XPos;
scrollPos.y = (int)Scroller->YPos;
}
if (!scale) {
dc.SetWindowOrg(scrollPos);
return;
}
// Don't scale the scrolling amount
//
if (Scale.SiteSize.cx)
scrollPos.x = (int)(((uint32)scrollPos.x * Scale.PartSize.cx +
Scale.SiteSize.cx/2) / Scale.SiteSize.cx);
if (Scale.SiteSize.cy)
scrollPos.y = (int)(((uint32)scrollPos.y * Scale.PartSize.cy +
Scale.SiteSize.cy/2) / Scale.SiteSize.cy);
dc.SetWindowOrg(scrollPos);
dc.SetViewportOrg(Pos.TopLeft());
// set the window and viewport extaccording to zoom factor
//
TSize ext;
GetLogPerUnit(ext);
dc.SetWindowExt(ext);
ext.cx = dc.GetDeviceCaps(LOGPIXELSX);
ext.cy = dc.GetDeviceCaps(LOGPIXELSY);
if (Scale.PartSize.cx)
ext.cx = (int)(((uint32)ext.cx * Scale.SiteSize.cx + Scale.PartSize.cx/2) /
Scale.PartSize.cx);
if (Scale.PartSize.cy)
ext.cy = (int)(((uint32)ext.cy * Scale.SiteSize.cy + Scale.PartSize.cy/2) /
Scale.PartSize.cy);
dc.SetViewportExt(ext);
}
//
// response method for an incoming WM_PAINT message
//
void
TOleWindow::EvPaint()
{
if (IsFlagSet(wfAlias))
DefaultProcessing(); // use application-defined wndproc
else {
TPaintDC dc(*this);
TRect& rect = *(TRect*)&dc.Ps.rcPaint;
if (Scroller)
Scroller->BeginView(dc, rect);
bool metafile = dc.GetDeviceCaps(TECHNOLOGY) == DT_METAFILE;
SetupDC(dc, !metafile);
Paint(dc, dc.Ps.fErase, rect);
PaintParts(dc, dc.Ps.fErase, rect, metafile);
if (Scroller)
Scroller->EndView();
}
}
//
// Notify the active view of part data changes
//
bool
TOleWindow::EvOcViewPartInvalid(TOcPartChangeInfo& changeInfo)
{
// Our document is now dirty...
// Reflect the change in part in other (non-active) views
//
TRect rect(changeInfo.GetPart()->GetRect());
rect.right++;
rect.bottom++;
TOleClientDC dc(*this);
dc.LPtoDP((TPoint*)&rect, 2);
InvalidateRect(rect); // Multiview support to be done in derived classes
// Notify container if this is an intermediate container
//
InvalidatePart((TOcInvalidate)changeInfo.GetType());
return true; // stop further processing by OCF
}
//
//
//
TPopupMenu*
TOleWindow::CreateVerbPopup(const TOcVerb& ocVerb)
{
TPopupMenu* verbMenu = new TPopupMenu(NoAutoDelete);
while (DragPart->EnumVerbs(ocVerb)) {
verbMenu->AppendMenu(MF_STRING|MF_ENABLED,
(uint)CM_EDITFIRSTVERB + ocVerb.VerbIndex,
(const char far*)OleStr(ocVerb.VerbName));
}
verbMenu->AppendMenu(MF_SEPARATOR, 0, 0);
string optName = GetModule()->LoadString(IDS_EDITCONVERT);
verbMenu->AppendMenu(MF_STRING, CM_EDITCONVERT, optName.c_str());
return verbMenu;
}
//
// Execute a verb pertaining to the selected object
//
void
TOleWindow::EvDoVerb(uint whichVerb)
{
DragPart->DoVerb(whichVerb);
}
//
// Attach this view back to its owl parent for either open editing, or
// mearly inplace de-activating
//
bool
TOleWindow::EvOcViewAttachWindow(bool attach)
{
TOleFrame* mainWindow = TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(),
TOleFrame);
if (!mainWindow)
return false; // server app is shutting down
if (attach) {
if (IsOpenEditing()) {
// Derived class needs to managed setting up frame differently, like
// for MDI etc.
//
mainWindow->SetClientWindow(this);
}
}
else {
if (IsOpenEditing() && Parent != mainWindow)
Parent->PostMessage(WM_CLOSE);
SetParent(mainWindow->GetRemViewBucket()); // simple reparent
}
return true;
}
//
// Perform the action indentified by verb
//
bool
TOleWindow::EvOcViewDoVerb(uint /*verb*/)
{
return false;
}
//
// Shut down the associated OCF partners if possible
//
bool
TOleWindow::OleShutDown()
{
if (IsRemote()) {
TOcRemView* ocRemView = GetOcRemView();
if (IsOpenEditing())
ocRemView->Disconnect();
}
else {
if (OcView)
OcView->EvClose();
}
return true;
}
//
// Perform normal CleanupWindow, plus let the OcView object know we have closed
//
void
TOleWindow::CleanupWindow()
{
TOleFrame* mainWindow = TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(),
TOleFrame);
if (mainWindow)
mainWindow->OleViewClosing(true);
OleShutDown();
if (mainWindow)
mainWindow->OleViewClosing(false);
TWindow::CleanupWindow();
}
static void
DoIdleAction(TWindow* win, void* idleCount)
{
win->IdleAction(*(long*)idleCount);
}
//
// TOleWindow processes idle action occurs once per block of messages
//
bool
TOleWindow::IdleAction(long idleCount)
{
if (idleCount == 0) {
// give child windows an opportunity to do any idle processing
//
ForEach(DoIdleAction, &idleCount);
}
return false; // we don't need any more time for now
}
//
// Handle the scaling for server app
//
bool
TOleWindow::EvOcViewSetScale(TOcScaleFactor& scaleFactor)
{
Scale = scaleFactor;
return true;
}
//
// Find the item name for whole doc or selection
//
bool
TOleWindow::EvOcViewGetItemName(TOcItemName& /*item*/)
{
return false;
}
//----------------------------------------------------------------------------
// Linking Spport
//
//
// Establish link with whole doc or selection
//
bool
TOleWindow::EvOcViewSetLink(TOcLinkView& /*view*/)
{
return false;
}
//
// Break link with whole doc or selection
//
bool
TOleWindow::EvOcViewBreakLink(TOcLinkView& /*view*/)
{
return false;
}