//----------------------------------------------------------------------------
// ObjectComponents
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Implementation of TOleWindow. Window class that supports OLE 2
/// container & server using OCF TOcView & TOcRemView
//----------------------------------------------------------------------------
#include <ocf/pch.h>
#include <owl/window.h>
#include <owl/gdiobjec.h>
#include <owl/scroller.h>
#include <ocf/ocdoc.h>
#include <ocf/ocview.h>
#include <ocf/occtrl.h>
#include <ocf/oleframe.h>
#include <ocf/olewindo.h>
#include <owl/uimetric.h>
#include <owl/edit.rh>
#include <owl/docview.rh>
#include <ocf/oleview.rh>
namespace ocf {
using namespace owl;
using namespace std;
OWL_DIAGINFO;
DIAG_DECLARE_GROUP(OcfRemView);//????????????????????????????????????????????????????????
///----------------------------------------------------------------------------
/// Size of rectangle in two clks must occur to be a doubleClick
/// ---- moved in StartDrag ----
/// TSize DblClkDelta(TUIMetric::CxDoubleClk/2,
/// TUIMetric::CyDoubleClk/2);
//----------------------------------------------------------------------------
// TOleClientDC
//
//
/// Constructs a TOleClientDC object . The parameter win references the window that
/// TOleClientDC uses to create a device context (DC). If the scale parameter is
/// true, TOleClientDC takes care of scaling. However, if your application handles
/// scaling, you can pass scale as false.
/// Scrolling is controlled by the presence of a scroller (TScroller). TOleClientDC
/// by default takes care of both scaling and scrolling.
//
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(CM_EDITINSERTCONTROL, CmEditInsertControl),
EV_COMMAND_ENABLE(CM_EDITINSERTOBJECT, CeEditInsertObject),
EV_COMMAND_ENABLE(CM_EDITINSERTCONTROL, CeEditInsertControl),
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,
// Ambient properties
//
EV_OC_AMBIENT_GETBACKCOLOR,
EV_OC_AMBIENT_GETFORECOLOR,
EV_OC_AMBIENT_GETLOCALEID,
EV_OC_AMBIENT_GETTEXTALIGN,
EV_OC_AMBIENT_GETMESSAGEREFLECT,
EV_OC_AMBIENT_GETUSERMODE,
EV_OC_AMBIENT_GETUIDEAD,
EV_OC_AMBIENT_GETSHOWGRABHANDLES,
EV_OC_AMBIENT_GETSHOWHATCHING,
EV_OC_AMBIENT_GETDISPLAYASDEFAULT,
EV_OC_AMBIENT_GETSUPPORTSMNEMONICS,
EV_OC_AMBIENT_GETDISPLAYNAME,
EV_OC_AMBIENT_GETSCALEUNITS,
EV_OC_AMBIENT_GETFONT,
EV_OC_AMBIENT_SETBACKCOLOR,
EV_OC_AMBIENT_SETFORECOLOR,
EV_OC_AMBIENT_SETLOCALEID,
EV_OC_AMBIENT_SETTEXTALIGN,
EV_OC_AMBIENT_SETMESSAGEREFLECT,
EV_OC_AMBIENT_SETUSERMODE,
EV_OC_AMBIENT_SETUIDEAD,
EV_OC_AMBIENT_SETSHOWGRABHANDLES,
EV_OC_AMBIENT_SETSHOWHATCHING,
EV_OC_AMBIENT_SETDISPLAYASDEFAULT,
EV_OC_AMBIENT_SETSUPPORTSMNEMONICS,
EV_OC_AMBIENT_SETDISPLAYNAME,
EV_OC_AMBIENT_SETSCALEUNITS,
EV_OC_AMBIENT_SETFONT,
// Standard Events
//
EV_OC_CTRLEVENT_CLICK,
EV_OC_CTRLEVENT_DBLCLICK,
// Ctrl events
//
EV_OC_CTRLEVENT_CLICK,
EV_OC_CTRLEVENT_DBLCLICK,
EV_OC_CTRLEVENT_FOCUS,
EV_OC_CTRLEVENT_MOUSEDOWN,
EV_OC_CTRLEVENT_MOUSEMOVE,
EV_OC_CTRLEVENT_MOUSEUP,
EV_OC_CTRLEVENT_KEYDOWN,
EV_OC_CTRLEVENT_KEYUP,
EV_OC_CTRLEVENT_PROPERTYCHANGE,
EV_OC_CTRLEVENT_PROPERTYREQUESTEDIT,
EV_OC_CTRLEVENT_ERROREVENT,
EV_OC_CTRLEVENT_CUSTOMEVENT,
END_RESPONSE_TABLE;
//
/// Constructs a TOleWindow object associated with the specified parent window and
/// module instance.
//
TOleWindow::TOleWindow(TWindow* parent, TModule* module)
:
TWindow(parent, 0, module),
Pos(0, 0, 0, 0),
Remote(false),
ShowObjects(false)
{
// Initialize virtual base, in case the derived-most used default ctor
//
TWindow::Init(parent, 0, module);
// 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();
}
//
/// Initializes the TOleWindow object with the appropriate window style and
/// initializes the necessary data members (for example, sets the accelerator ID to
/// IDA_OLEVIEW).
//
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();
}
//
/// Checks to see if there are any open views, and, if no open views exist, destroys
/// the TOleWindow object.
//
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;
}
}
//
/// Establishes a connection between the TOcView object and the view's HWND so the
/// view can send notification messages to the window.
//
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
//
/// Creates an ObjectComponents view associated with the embedded object. Associates
/// the view with the document template specified in tpl. If isEmbedded is true, a
/// remote view is created (that is, a TOcRemView instead of a TOcView). The outer
/// parameter refers to the IUnknown interface with which the view will aggregate
/// itself.
///
/// 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 [capable of hosting OCXes or 'normal' servers]
//
if (isRemote)
OcView = new TOcRemView(*GetOcDoc(), regList, outer);
else
// By default, our 32-bit container support can 'hold' embedded objects
// and OCX controls. So we'll default to a 'TOcxView'. However, this
// can be optimized if the container will never contain any OLE controls.
//
#if !defined(OWL_NO_OCX_CONTAINER_SUPPORT)
OcView = new TOcxView(*GetOcDoc(), regList, outer);
#endif
Remote = isRemote;
}
return OcView;
}
//
/// Overrides the usual EvCommandEnable message in order to enable the OLE verbs
/// from CM_EDITFIRSTVERB to CM_EDITLASTVERB. These commands enable the OLE-specific
/// Edit menu selections, such as Edit, Open, and Play. Many of the other commands
/// are passed to TWindow::EvCommand for normal processing.
/// If a window is embedded, however, TOleWindow calls upon TWindow's
/// RouteCommandEnable to perform command enabling.
//
void
TOleWindow::EvCommandEnable(TCommandEnabler& commandEnabler)
{
if (CM_EDITFIRSTVERB <= commandEnabler.GetId() && commandEnabler.GetId() <= 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!
//
THandle hCmdTarget = ::GetFocus();
if (hCmdTarget != GetHandle() && !IsChild(hCmdTarget))
hCmdTarget = GetHandle();
RouteCommandEnable(hCmdTarget, commandEnabler);
}
else {
TWindow::EvCommandEnable(commandEnabler);
}
}
//
/// Overrides the usual EvCommand message to handle the OLE verbs from
/// CM_EDITFIRSTVERB to CM_EDITLASTVERB. These commands, which are defined in
/// oleview.rh, correspond to the OLE-specific Edit menu selections such as Edit,
/// Open, and Play. All of the other commands are passed to TWindow::EvCommand for
/// normal processing.
//
TResult
TOleWindow::EvCommand(uint id, THandle hCtl, uint notifyCode)
{
TRACEX(OcfRemView, 1, _T("TOleWindow::EvCommand - id(") << id << _T("), ctl(") <<\
hex << static_cast<void*>(hCtl) << _T("), code(") << notifyCode << _T(")"));
if (hCtl == 0) {
if (CM_EDITFIRSTVERB <= id && id <= CM_EDITLASTVERB) {
EvDoVerb(id - CM_EDITFIRSTVERB);
return 0;
}
}
return TWindow::EvCommand(id, hCtl, notifyCode);
}
//
/// Intercept CanClose() to interpose OpenEdit semantics. OLE2 servers don't
/// prompt the user on close--just save & close.
///
/// Returns true if the window can be closed. Checks all the server's child windows'
/// CanClose functions, which must return true before the window can be closed.
/// Terminates any open editing transactions before closing the window; otherwise,
/// passes control to TWindow::CanClose.
///
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;
}
//
/// Invalidates the area where the embedded object exists. The server uses this
/// function to tell OLE that the part (the embedded object), has changed. OLE then
/// asks the server to redraw the part into a new metafile so that OLE can redraw
/// the object for the container application even when the server application is not
/// active.
//
void
TOleWindow::InvalidatePart(TOcInvalidate invalid)
{
if (GetOcRemView())
GetOcRemView()->Invalidate(invalid);
}
//
/// Checks whether the window is in Open-Edit mode.
//
bool
TOleWindow::IsOpenEditing() const
{
TOcRemView* ocRemView = const_cast<TOleWindow*>(this)->GetOcRemView();
return ocRemView && ocRemView->GetState() == TOcRemView::OpenEditing;
}
//
//
//
TOcPart*
TOleWindow::InsertObject(TOcInitInfo& initInfo, TRect* pos)
{
TRect rect;
// Pass size request on if caller does not specify
//
if (!pos) {
pos = ▭
GetInsertPosition(*pos);
}
TOcPart* part;
try {
part = new TOcPart (*GetOcDoc());
part->Init(&initInfo, *pos);
SetSelection(part);
OcView->Rename();
InvalidatePart(invView);
}
catch (TXOle& /*xole*/) {
return 0;
}
return part;
}
//
//
//
TOcPart*
TOleWindow::InsertObject(CLSID& objIID, TRect* pos)
{
TOcInitInfo initInfo(OcView);
// Initialize InitInfo structure
//
initInfo.Where = iwNew; // Flag it's a new embedding
initInfo.CId = (DWORD_PTR) &objIID; // Object's GUID
initInfo.How = ihEmbed; // Want embedded
return InsertObject(initInfo, pos);
}
//
//
//
TOcPart*
TOleWindow::InsertObject(TString& objProgId, TRect* pos)
{
// Get IID of OCX from specified ProgID
//
CLSID objIID = CLSID_NULL;
HRESULT hr = ::CLSIDFromProgID(objProgId, &objIID);
if (FAILED(hr)) {
return 0;
}
return InsertObject(objIID, pos);
}
//
//
//
TOcControl*
TOleWindow::InsertControl(TOcInitInfo& initInfo, TRect* pos, int id)
{
TRect rect;
// Pass size request on if caller does not specify
//
if (!pos) {
pos = ▭
GetInsertPosition(*pos);
}
// If user did not specify the size (i.e. right & bottom), use
// some default values...
//
if (pos->left == pos->right)
pos->right = pos->left + 100;
if (pos->top == pos->bottom)
pos->bottom = pos->top + 100;
TOcControl* ctrl;
try {
ctrl = new TOcControl (*GetOcDoc());
ctrl->Init(&initInfo, *pos);
SetSelection(ctrl);
OcView->Rename();
InvalidatePart(invView);
ctrl->SetId(id);
}
catch (TXOle& /*xole*/) {
return 0;
}
return ctrl;
}
//
//
//
TOcControl*
TOleWindow::InsertControl(CLSID& ocxIID, TRect* pos, int id)
{
TOcInitInfo initInfo(OcView);
// Initialize InitInfo structure
//
initInfo.Where = iwNewOcx; // A new OCX
initInfo.CId = (DWORD_PTR) &ocxIID; // OCX's GUID, requires where == iwNewOcx
initInfo.How = ihEmbed; // Want embedded
return InsertControl(initInfo, pos, id);
}
//
//
//
TOcControl*
TOleWindow::InsertControl(const TString& ocxProgID, TRect* pos, int id)
{
// Get IID of OCX from specified ProgID
//
CLSID ocxIID = CLSID_NULL;
HRESULT hr = ::CLSIDFromProgID(ocxProgID, &ocxIID);
if (FAILED(hr)) {
return 0;
}
return InsertControl(ocxIID, pos, id);
}
//
//
//
TOcControl*
TOleWindow::GetOcControlOfOCX(CLSID ocxIID, uint id)
{
// Iterate through all parts of this window
//
for (TOcPartCollectionIter i(GetOcDoc()->GetParts()); i; i++) {
TOcPart* p = *i;
// NOTE: Here we'll simply dynamic_cast the TOcPart pointer to a
// TOcControl. A more OLEish approach would be to querry for
// a control interface [IBControl for example] as a safety
// measure first.
//
TOcControl* pCtrl = TYPESAFE_DOWNCAST(p, TOcControl);
if (pCtrl) {
IOleObject* pOleObject = 0;
if (SUCCEEDED(pCtrl->QueryServer(IID_IOleObject, (void**)&pOleObject))) {
// !BB Could add a call to pOleObject->GetUserType to retrieve
// !BB the name of the control for debugging purposes...
CLSID userClsId;
if (SUCCEEDED(pOleObject->GetUserClassID(&userClsId)) &&
userClsId == ocxIID) {
if (id == 0 || pCtrl->GetId() == id) {
pOleObject->Release();
return pCtrl;
}
}
pOleObject->Release();
}
}
}
// Control proxy was not found
//
return 0;
}
//
/// Enables the FileClose command, which lets the user exit from the window view.
//
void
TOleWindow::CeFileClose(TCommandEnabler& ce)
{
// if open editing server, reflect the container's name in "close" option
//
if (IsOpenEditing() && GetOcRemView() && GetOcRemView()->GetKind() != TOcRemView::Link) {
TCHAR strCloseMenu[128];
owl::tstring optName = GetModule()->LoadString(IDS_CLOSESERVER);
TString title = GetOcRemView()->GetContainerTitle();
if (title.Length() > 0) {
_tcscpy(strCloseMenu, optName.c_str());
_tcscat(strCloseMenu, title);
//LPCTSTR str = title;
//optName += str;
}
//ce.SetText(optName.c_str());
ce.SetText(&strCloseMenu[0]);
}
}
//
/// Enables a command with an ID of CM_EDITINSERTOBJECT if the OcApp and OcView
/// objects exist. Disables the command otherwise.
//
void
TOleWindow::CeEditInsertObject(TCommandEnabler& ce)
{
ce.Enable(OcApp && OcView);
}
//
/// Enables a command with an ID of CM_EDITINSERTCONTROL if the OcApp and OcView
/// objects exist. Disables the command otherwise.
//
void
TOleWindow::CeEditInsertControl(TCommandEnabler& ce)
{
ce.Enable(OcApp && OcView);
}
//
/// Gets the position (rect) where the embedded object is inserted. You need to
/// override this function if you want to override any default position.
///
/// \note 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;
}
//
/// Responds to a command with an ID of CM_EDITINSERTOBJECT by creating,
/// initializing, painting, and selecting an OLE object (TOcPart object).
//
void
TOleWindow::CmEditInsertObject()
{
PRECONDITION(OcView);
TOcInitInfo initInfo(OcView);
if (OcApp->Browse(initInfo)) {
InsertObject(initInfo);
}
}
//
/// Responds to a command with an ID of CM_EDITINSERTCONTROL by creating,
/// initializing, painting, and selecting an OCX control (TOcControl object).
//
void
TOleWindow::CmEditInsertControl()
{
PRECONDITION(OcView);
TOcInitInfo initInfo(OcView);
if (OcApp->BrowseControls(initInfo)) {
InsertControl(initInfo);
}
}
//
/// Enables a command with an ID of CM_EDITDELETE, which lets the user delete the
/// selected object from the view.
//
void
TOleWindow::CeEditDelete(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
//
/// Responds to a command with an ID of CM_EDITDELETE by deleting the selected text.
//
void
TOleWindow::CmEditDelete()
{
if (!DragPart)
return;
TOcPartChangeInfo changeInfo(DragPart, TOcInvalidate(invData | invView));
EvOcViewPartInvalid(changeInfo);
DragPart->Delete();
DragPart = 0;
}
//
/// Enables a command with an ID of CM_EDITCUT, which lets a user copy and delete
/// the selected object from the view.
//
void
TOleWindow::CeEditCut(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
//
/// Responds to a command with an ID of CM_EDITCUT by copying the selected text to
/// the clipboard before cutting the text.
//
void
TOleWindow::CmEditCut()
{
DragPart->Detach();
OcApp->Copy(DragPart);
SetSelection(0);
}
//
/// Enables a command with an ID of CM_EDITCOPY, which lets the user copy selected
/// object to the clipboard.
//
void
TOleWindow::CeEditCopy(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
//
/// Responds to a command with an ID of CM_EDITCOPY by copying the selected text to
/// the clipboard.
//
void
TOleWindow::CmEditCopy()
{
if (DragPart)
OcApp->Copy(DragPart);
}
//
/// Enables a PasteLink command with an ID of CM_EDITPASTELINK, which lets the user
/// link to the embedded object on the clipboard. See the ocrxxxx Clipboard
/// Constants for a description of the available clipboard formats.
//
void
TOleWindow::CeEditPasteLink(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnablePasteLink, OcView));
}
//
/// Responds to a command with an ID of CM_EDITPASTELINK by creating a link between
/// the current document and the object on the clipboard.
//
void
TOleWindow::CmEditPasteLink()
{
OcView->Paste(true);
}
//
/// Enables a command with an ID of CM_EDITPASTE, which lets the user paste the
/// embedded object from the clipboard.
//
void
TOleWindow::CeEditPaste(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnablePaste, OcView));
}
//
/// Responds to a command with an ID of CM_EDITPASTE by pasting an object from the
/// clipboard into the document.
//
void
TOleWindow::CmEditPaste()
{
OcView->Paste(false);
InvalidatePart(invView);
}
//
/// Enables the PasteSpecial command, which lets the user select a clipboard format
/// to be pasted or paste linked. See the ocrxxxx Clipboard Constants for a
/// description of the available clipboard formats.-
//
void
TOleWindow::CeEditPasteSpecial(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnableBrowseClipboard, OcView));
}
//
/// Responds to a command with an ID of CM_EDITPASTESPECIAL by letting the user
/// select an object from a list of available formats for pasting from the clipboard
/// onto the document.
//
void
TOleWindow::CmEditPasteSpecial()
{
TOcInitInfo initInfo(GetOcView());
if (GetOcView()->BrowseClipboard(initInfo)) {
if (!OcView->PasteNative(initInfo)) { // Not native data
EvOcViewPasteObject(initInfo);
}
InvalidatePart(invView);
}
}
//
/// Enables a command with an ID of CM_EDITOBJECT, which lets the user edit the
/// embedded object.
//
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());
owl::tstring 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);
owl::tstring newMenuName(OleStr(ocVerb.TypeName));
newMenuName += _T(" ");
newMenuName += optName;
editMenu.ModifyMenu(verbPos, MF_ENABLED | MF_BYPOSITION | MF_POPUP,
reinterpret_cast<TMenuItem>(verbMenu->GetHandle()), newMenuName.c_str());
delete verbMenu;
ce.Enable(true);
}
//
/// Enables a command with an ID of CM_EDITCONVERT, which lets the user convert the
/// selected object from one format to another. This is an OLE-specific pop-up menu option.
//
void
TOleWindow::CeEditConvert(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
/// Responds to a command with an ID of CM_EDITCONVERT by converting an object from
/// one type to another.
void
TOleWindow::CmEditConvert()
{
OcApp->Convert(DragPart, false);
}
//
/// Enables a command with an ID of CM_EDITLINKS, which lets the user manually
/// update the list of linked items in the current view.
//
void
TOleWindow::CeEditLinks(TCommandEnabler& ce)
{
PRECONDITION(OcApp && OcView);
ce.Enable(OcApp->EnableEditMenu(meEnableBrowseLinks, OcView));
}
//
/// Responds to a command with an ID of CM_EDITLINKS by updating the user-selected
/// list of linked items in the current view.
//
void
TOleWindow::CmEditLinks()
{
PRECONDITION(OcView);
OcView->BrowseLinks();
}
//
/// Enables the Edit|Verbs command, which lets the user select one of the
/// OLE-specific verbs from the Edit menu: for example, Edit, Open, or Play.
//
void
TOleWindow::CeEditVerbs(TCommandEnabler& ce)
{
ce.Enable(DragPart != 0);
}
//
/// Responds to a command with an ID of CM_EDITSHOWOBJECTS by toggling the value of
/// the ShowObjects data member.
//
void
TOleWindow::CmEditShowObjects()
{
ShowObjects = !ShowObjects;
Invalidate();
}
//
/// Checks or unchecks the Edit|Show Objects menu command according to the value of
/// the ShowObjects data member.
//
void
TOleWindow::CeEditShowObjects(TCommandEnabler& ce)
{
ce.SetCheck(ShowObjects ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
}
//
/// Returns true if the container's view holds an in-place active embedded object.
//
bool
TOleWindow::HasActivePart()
{
return OcView->GetActivePart() != 0;
}
//
/// Performs hit testing to tell where the cursor is located within the window and
/// what object the cursor is moving over. If the cursor is within an embedded
/// object, EvSetCursor changes the shape of the cursor.
/// When the cursor is over an inactive part and not on a handle, EvSetCursor uses
/// an arrow cursor. If the cursor is on one of the handles of the embedded part,
/// EvSetCursor changes the cursor to a resizing cursor.
//
bool
TOleWindow::EvSetCursor(THandle hWnd, 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(hWnd, hitTest, mouseMsg);
}
//
/// Handles the WM_NCHITTEST message, setting the cursor according to its position
/// on the screen. By default, the cursor is always an arrow. But by overriding the
/// ShowCursor function, you can specify the conditions under which the cursor
/// should change and to which bitmap it should change.
/// HWND is the window containing the cursor, hitTest is a constant that represents
/// the current position of the mouse (for a list of possible values, see the
/// WM_NCHITTEST topic), and mouseMsg is a constant that represents the current
/// mouse action, such as WM_MOUSEACTIVATE.
/// For an example of an implementation of the ShowCursor function, see Step 17 of
/// the OWL tutorial.
//
bool
TOleWindow::ShowCursor(THandle /*hWnd*/, uint /*hitTest*/, uint /*mouseMsg*/)
{
::SetCursor(::LoadCursor(0, IDC_ARROW));
return true;
}
//
// Find out if drag and drop needs to be started
//
bool
TOleWindow::StartDrag(uint modKeys, TPoint& point)
{
static TSize DblClkDelta(TUIMetric::CxDoubleClk/2,
TUIMetric::CyDoubleClk/2);
// no part no drag
if (!DragPart)
return false;
// maybe it was a double click
if (abs(point.X()-DragStart.X()) <= DblClkDelta.cx ||
abs(point.Y()-DragStart.Y()) <= DblClkDelta.cy)
return false;
// start drag and drop anyway if outside client area
if (!InClient(*DragDC, point))
return true;
// start if ctrl or ctrl-shift is pressed but not if alt since move inside client area
// doesn't really make sense (a move is a move don't bother ole for that)
if ((modKeys & MK_CONTROL))
return true;
return false;
}
//
/// This is a response method for an incoming EV_WM_DROPFILES message.
/// 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;
TAPointer<OLECHAR> filePath(new OLECHAR[fileLength]);
dropInfo.DragQueryFile(index, OleStr((OLECHAR*)filePath), fileLength);
TOcInitInfo initInfo(ihEmbed, iwFile, OcView);
initInfo.Path = filePath;
TRect rect;
GetInsertPosition(rect);
TOcPart* part = new TOcPart (*GetOcDoc());
part->Init(&initInfo, rect);
SetSelection(part);
OcView->Rename();
InvalidatePart(invView);
}
dropInfo.DragFinish();
}
//
/// Responds to a mouse button double click message. EvLButtonDblClk performs hit
/// testing to see which embedded object, if any, is being clicked on, then in-place
/// activates the embedded object.
//
void
TOleWindow::EvLButtonDblClk(uint modKeys, const TPoint& point_)
{
PRECONDITION(GetOcDoc() && GetOcView());
TOleClientDC dc(*this);
TPoint point(point_);
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
}
}
//
/// Selects the embedded object indicated in the part parameter. When the embedded
/// object is selected, a selection box is drawn around the area. After an embedded
/// object is selected, the user can perform operations on the embedded object: for
/// example, moving, sizing, or copying the embedded object to the clipboard.
//
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);
}
}
//
/// Responds to a right button down message. Performs additional hit testing to see
/// which embedded object, if any, is being clicked on and displays a local menu
/// with appropriate options for the embedded object.
/// point refers to the place where the mouse is located. modKeys holds the values
/// for a combined key and transaction, such as a Shift+Double-click of the mouse
/// button.
//
void
TOleWindow::EvRButtonDown(uint, const TPoint& point_)
{
PRECONDITION(GetOcDoc());
// Perform hit test on parts...
//
TPoint oldPoint = point_;
TOleClientDC dc(*this);
TPoint point(point_);
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);
owl::tstring optName = GetModule()->LoadString(IDS_EDITOBJECT);
owl::tstring newMenuName(OleStr(ocVerb.TypeName));
newMenuName += _T(" ");
newMenuName += optName;
popMenu.ModifyMenu(CM_EDITOBJECT, MF_ENABLED | MF_BYCOMMAND | MF_POPUP,
reinterpret_cast<TMenuItem>(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);
}
}
}
//
/// If an embedded object is no longer the active embedded object, either because
/// the user has ended an in-place editing session or because the user has clicked
/// outside the embedded object, call Deactivate to unselect the object. Returns
/// true if successful.
//
bool
TOleWindow::Deactivate()
{
// Deactivate active part, if any
//
if (DragPart && DragPart->IsActive()) {
SetSelection(0);
return true;
}
else
return false;
}
//
/// Selects the embedded object at the specified point (measured in logical units).
/// Returns true if the object is captured by the mouse drag; otherwise, returns
/// false.
//
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;
}
//
/// Responds to a left button down message by beginning a mouse drag transaction at
/// the given point. Performs additional hit testing to see which embedded object,
/// if any, is being clicked on. The modKeys parameter holds the values for a key
/// combination such as a shift and double click of the mouse button.
/// See also EvRButtonDown
//
void
TOleWindow::EvLButtonDown(uint modKeys, const TPoint& point_)
{
// Deactivating in-place active object, if any
//
if (Deactivate())
return;
// Convert the point to logical unit
//
if (!DragDC)
DragDC = new TOleClientDC(*this);
TPoint point(point_);
DragDC->DPtoLP(&point);
Select(modKeys, point);
}
//
/// Returns true if point is inside the client area of the window. Returns false otherwise.
//
bool
TOleWindow::InClient(TDC& dc, TPoint& point)
{
TRect logicalRect = GetClientRect();
dc.DPtoLP((TPoint*)&logicalRect, 2);
return logicalRect.Contains(point);
}
//
/// Responds to a mouse move message with the appropriate transaction. If the mouse
/// is being dragged, the embedded object is moved. If a resizing operation occurs,
/// then the embedded object is resized. This message is handled only when a mouse
/// dragging or resizing action involving the embedded object occurs.
//
void
TOleWindow::EvMouseMove(uint modKeys, const TPoint& point_)
{
if (!DragDC)
return;
// Convert the point to logical unit
//
TPoint point(point_);
DragDC->DPtoLP(&point);
// A MidCenter hit is a move
//
if (DragHit == TUIHandle::MidCenter) {
DragDC->DrawFocusRect(DragRect); // erase old rect
// check if initiate drag and drop
if (StartDrag(modKeys, point)) {
TOcDropAction outAction;
OcApp->Drag(DragPart, TOcDropAction(daDropCopy | daDropMove | daDropLink),
outAction);
TOcPartChangeInfo changeInfo(DragPart, TOcInvalidate(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;
}
//
/// Responds to a left button up message by ending a mouse drag action. point refers
/// to the place where the mouse is located. modKeys holds the values for a combined
/// key and mouse transaction.
//
void
TOleWindow::EvLButtonUp(uint /*modKeys*/, const TPoint& /*point*/)
{
if (DragPart) {
TOcPartChangeInfo changeInfo(DragPart, TOcInvalidate(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();
}
}
//
/// Passes the event to TWindow::EvSize for normal processing and forwards the event
/// to TOcView::EvResize to let a possible in-place server adjust its size.
//
void
TOleWindow::EvSize(uint sizeType, const TSize& size)
{
TWindow::EvSize(sizeType, size);
OcView->EvResize();
}
//
/// Responds to a message forwarded from the MDI child window (if one exists) and
/// lets the TOcView class know that the view window child window frame has been
/// activated or deactivated.
/// The hWndActivated parameter contains a handle to the MDI child window being
/// activated. Both the child window being activated being activated and the child
/// window (hWndDeactivated) being deactivated receive this message.
//
void
TOleWindow::EvMDIActivate(THandle hActivated, THandle /*hDeactivated*/)
{
if (OcView)
OcView->EvActivate(hActivated == *Parent);
}
/// Forwards the WM_MOUSEACTIVATE message to the top parent of the TOleWindow object.
uint
TOleWindow::EvMouseActivate(THandle topParent, uint /*hitCode*/, uint /*msg*/)
{
if (topParent)
ForwardMessage(topParent);
return MA_ACTIVATE;
}
//
/// Responds to a change in focus of the window. hWndLostFocus contains a handle to
/// the window losing the focus. EvSetFocus checks to see if an in-place server
/// exists and, if so, passes the focus to the in-place server.
//
void
TOleWindow::EvSetFocus(THandle hLostFocus)
{
TWindow::EvSetFocus(hLostFocus);
if (OcView)
OcView->EvSetFocus(true); // Maybe active part (if any) wants focus
}
//
/// In response to a WM_HSCROLL message, EvHScroll calls TWindow::EvHScroll and
/// invalidates the window.
//
void
TOleWindow::EvHScroll(uint scrollCode, uint thumbPos, THandle hCtl)
{
TWindow::EvHScroll(scrollCode, thumbPos, hCtl);
InvalidatePart(invView);
}
//
/// In response to a WM_VSCROLL message, EvVScroll calls TWindow::EvVScroll and
/// invalidates the window.
//
void
TOleWindow::EvVScroll(uint scrollCode, uint thumbPos, THandle hCtl)
{
TWindow::EvVScroll(scrollCode, thumbPos, hCtl);
InvalidatePart(invView);
}
//
/// Handles WM_MENUSELECT to provide hint text in the container's status bar, based
/// on the menu item id. It treats popup items separately and asks them for their
/// ids. This implementation is similar to the code in TDecoratedFrame.
//
void
TOleWindow::EvMenuSelect(uint menuItemId, uint flags, HMENU hMenu)
{
if (GetOcRemView()) {
if (flags == 0xFFFF && hMenu == 0) { // menu closing
GetOcRemView()->SetContainerStatusText(_T(""));
return;
}
else if (flags & MF_POPUP)
{
TMenu popupMenu(hMenu);
const int posItem = menuItemId;
menuItemId = popupMenu.GetMenuItemID(posItem);
}
else if (flags & (MF_SEPARATOR | MF_MENUBREAK | MF_MENUBARBREAK))
{
menuItemId = 0; // display an empty help message
}
owl::tstring text = GetModule()->LoadString(menuItemId);
GetOcRemView()->SetContainerStatusText(text.c_str());
}
else
TWindow::EvMenuSelect(menuItemId, flags, hMenu);
}
//
/// Responds to a WM_OCEVENT message and subdispatches the message based on wParam.
/// ObjectComponents sends WM_OCEVENT messages when it needs to communicate with an
/// OLE-generated event; for example, if a server wants to display toolbars.
//
TResult
TOleWindow::EvOcEvent(TParam1 param1, TParam2 param2)
{
TEventHandler::TEventInfo eventInfo(WM_OCEVENT, static_cast<uint>(param1));
if (Find(eventInfo))
return Dispatch(eventInfo, param1, param2);
return 0;
}
//
/// Asks the container for the caption in its frame window. Returns the frame
/// window's caption.
//
LPCTSTR
TOleWindow::EvOcViewTitle()
{
TCHAR title[128];
Parent->GetWindowText(title, 128);
ContainerName = title;
return ContainerName.c_str();
}
//
/// Sets the window's caption to title. The new caption is the name of the in-place
/// active server merged with the caption of the container's window. In the case of
/// an MDI child window, the new caption is the in-place server's name merged with
/// the caption of the MDI child window. When the child window is maximized, the
/// merged caption is appended to the end of the main frame window's caption.
//
void
TOleWindow::EvOcViewSetTitle(LPCTSTR title)
{
if (title && *title)
Parent->SetWindowText(title);
else if (GetOcRemView() && GetOcRemView()->GetKind() == TOcRemView::Link) {
LPCTSTR caption = GetFileName();
if (caption)
Parent->SetWindowText(caption);
}
}
//
/// Requests that the server create space for a tool bar in the view of an embedded
/// object.
/// If the TOleWindow object is unable to handle the message,
/// EvOcViewBorderSpaceReq returns false, the default value.
//
bool
TOleWindow::EvOcViewBorderSpaceReq(TRect * /*space*/)
{
return false;
}
//
/// Requests that the server's tool bar be placed in the container's view of an
/// embedded object.
/// If the TOleWindow object is unable to handle the message, EvOcViewBorderSpaceSet
/// returns false, the default value.
//
bool
TOleWindow::EvOcViewBorderSpaceSet(TRect * /*space*/)
{
return false;
}
//
/// Requests a given object be dropped at a specified place on the container's
/// window.
/// If the TOleWindow object is unable to handle the message, EvOcViewDrop returns
/// false.
//
bool
TOleWindow::EvOcViewDrop(TOcDragDrop & /*ddInfo*/)
{
return true; // ok to drop anything, we can take it...
}
//
/// Handles an OC_VIEWDRAG message asking the container to provide visual feedback
/// while the user is dragging the embedded object.
/// If the TOleWindow object is unable to handle the message, EvOcViewDrag returns
/// false.
//
bool
TOleWindow::EvOcViewDrag(TOcDragDrop & 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;
}
//
/// Asks the container to scroll the view window and updates any internal state as
/// needed. EvOcViewScroll is called when the server is resizing or a drop
/// interaction occurs near the edge of the window.
/// If the TOleWindow object is unable to handle the message, EvOcViewScroll returns
/// false.
//
bool
TOleWindow::EvOcViewScroll(TOcScrollDir /*scrollDir*/)
{
return false;
}
//
/// Gets the size of the rectangle (the site) where the embedded object is to be
/// placed. rect refers to the size of the bounding rectangle that encloses the
/// embedded object.
//
bool
TOleWindow::EvOcViewGetSiteRect(TRect * rect)
{
TOleClientDC dc(*this);
return dc.LPtoDP((TPoint*)rect, 2);
}
//
/// Converts the rect to logical units. This area, referred to as the site, is
/// measured in logical units that take into account any scaling factor. rect refers
/// to the size of the bounding rectangle that encloses the embedded object.
//
bool
TOleWindow::EvOcViewSetSiteRect(TRect * rect)
{
TOleClientDC dc(*this);
return dc.DPtoLP((TPoint*)rect, 2);
}
//
/// Responds to an OC_VIEWGETSCALE message and gets the scaling for the server
/// object, causing the embedded object to be displayed using the correct scaling
/// value (for example, 120%). scaleFactor indicates the scaling factor, the ratio
/// between the size of the embedded object and the size of the site where the
/// object is to be displayed.
/// If the TOleWindow object is unable to handle the message, EvOcViewGetScale
/// returns false.
//
bool
TOleWindow::EvOcViewGetScale(TOcScaleFactor& scaleFactor)
{
scaleFactor = Scale;
return true;
}
//
/// Notifies ObjectWindows container applications that an embedded object is active.
/// ocPart is the embedded object that has been activated. EvOcViewPartActivate
/// returns true after the embedded object has been activated.
//
bool
TOleWindow::EvOcViewPartActivate(TOcPart& ocPart)
{
SetSelection(&ocPart);
return true;
}
//
/// Pastes an OLE object into the document pointed to by the TOleWindow::OcDoc data
/// member.
//
bool
TOleWindow::EvOcViewPasteObject(TOcInitInfo& init)
{
TRect rect;
GetInsertPosition(rect);
TOcPart* part = new TOcPart (*GetOcDoc());
part->Init(&init, rect);
init.ReleaseDataObject();
return true;
}
//
/// Asks the server to paint an object at a given position on a specified device
/// context.
/// If the TOleWindow object is unable to handle the message, EvOcViewPaint returns
/// false.
//
bool
TOleWindow::EvOcViewPaint(TOcViewPaint & 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;
}
//
/// Asks the server to close a currently open document and its associated view.
/// If the TOleWindow object is unable to handle the message, EvOcViewClose returns
/// false.
///
/// 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;
}
//
/// Asks the server to write an embedded object's data (the part as represented by
/// the ocSave parameter) into storage.
/// If the TOleWindow object is unable to handle the message, EvOcViewSavePart
/// returns false.
//
bool
TOleWindow::EvOcViewSavePart(TOcSaveLoad & /*ocSave*/)
{
return true;
}
//
/// Requests that an embedded object load itself.
/// If the TOleWindow object is unable to handle the message, EvOcViewLoadPart
/// returns false.
//
bool
TOleWindow::EvOcViewLoadPart(TOcSaveLoad & /*ocLoad*/)
{
return true;
}
//
/// The server asks itself the size of its current rectangle and lets the container
/// know about the size of the server's view in pixels.
/// If the TOleWindow object is unable to handle the message, EvOcViewPartSize
/// returns false.
//
bool
TOleWindow::EvOcViewPartSize(TOcPartSize & /*size*/)
{
return false;
}
//
/// Asks the container to open an existing document, which will be used for linking
/// from the embedding site.
/// If the TOleWindow object is unable to handle the message, EvOcViewOpenDoc
/// returns false.
//
bool
TOleWindow::EvOcViewOpenDoc(LPCTSTR /*path*/)
{
return true;
}
//
/// Requests that the menus in a composite menu (a menu composed of both the
/// server's and the container's menus).
/// If the TOleWindow object is unable to handle the message, EvOcViewInsMenus
/// returns false.
//
bool
TOleWindow::EvOcViewInsMenus(TOcMenuDescr & /*sharedMenu*/)
{
return false;
}
//
/// Asks the server to provide its tool bars for display in the container's window.
/// Returns true if tool bars are supplied.
/// If the TOleWindow object is unable to handle the message, EvOcViewShowTools
/// returns false.
//
bool
TOleWindow::EvOcViewShowTools(TOcToolBarInfo & tbi)
{
TWindow* mainWindow = GetApplication()->GetMainWindow();
CHECK(mainWindow);
TWindow* toolBar = mainWindow->ChildWithId(IDW_TOOLBAR);
if (!toolBar)
return false;
tbi.HTopTB = THandle(*toolBar);
return true;
}
//
/// Requests the color palette to draw the object.
/// If the TOleWindow object is unable to handle the message, EvOcViewGetPalette
/// returns false.
//
bool
TOleWindow::EvOcViewGetPalette(LOGPALETTE * * /*palette*/)
{
return false;
}
//
/// Requests clipboard data in the specified format.
/// If the TOleWindow object is unable to handle the message, EvOcViewClipData
/// returns false.
//
bool
TOleWindow::EvOcViewClipData(TOcFormatData & /*format*/)
{
return false;
}
//
// Set format data into server
//
bool
TOleWindow::EvOcViewSetData(TOcFormatData & /*format*/)
{
return false;
}
//
/// Handles the EV_OC_AMBIENT_GETBACKCOLOR message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores the window background color in rgb and returns true.
//
bool
TOleWindow::EvOcAmbientGetBackColor(long* /*backColor*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETFORECOLOR message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores the window forecolor in rgb and returns true.
bool
TOleWindow::EvOcAmbientGetForeColor(long* /*foreColor*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETLOCALEID message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores the window locale ID in locale and returns true.
bool
TOleWindow::EvOcAmbientGetLocaleID(long* /*localeId*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETTEXTALIGN message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores the window text alignment in show and returns true.
bool
TOleWindow::EvOcAmbientGetTextAlign(short* /*align*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETMESSAGEREFLECT message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores whether or not the window reflects
/// messages back to the control in msgReflect and returns true.
bool
TOleWindow::EvOcAmbientGetMessageReflect(bool* /*reflectMessage*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETUSERMODE message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores whether or not the window is in user mode in mode and returns
/// true.
bool
TOleWindow::EvOcAmbientGetUserMode(bool* /*userMode*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETUIDEAD message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores whether or not the window's user interface is disabled in dead
/// and returns true.
bool
TOleWindow::EvOcAmbientGetUIDead(bool* /*deadUI*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETSHOWGRABHANDLES message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores whether or not the window shows grab
/// handles in show and returns true.
bool
TOleWindow::EvOcAmbientGetShowGrabHandles(bool* /*showGrabHandles*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETSHOWHATCHING message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores whether or not the window shows hatching
/// in show and returns true.
bool
TOleWindow::EvOcAmbientGetShowHatching(bool* /*showHatching*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETDISPLAYASDEFAULT message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores whether or not the control is a default
/// control (buttons only) in disp and returns true.
bool
TOleWindow::EvOcAmbientGetDisplayAsDefault(bool* /*displayAsDefault*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETSUPPORTSMNEMONICS message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores whether or not the window supports
/// mnemonics in support and returns true.
bool
TOleWindow::EvOcAmbientGetSupportsMnemonics(bool* /*supportMnemonics*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETDISPLAYNAME message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores a control name (used in error messages) in
/// name and returns true.
bool
TOleWindow::EvOcAmbientGetDisplayName(TString** /*name*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETSCALEUNITS message, which is sent by an OCX
/// control. Returns false by default. You should override the default
/// implementation so the function stores the window scale units in units and
/// returns true.
bool
TOleWindow::EvOcAmbientGetScaleUnits(TString** /*units*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_GETFONT message, which is sent by an OCX control.
/// Returns false by default. You should override the default implementation so the
/// function stores the window font information in font and returns true.
bool
TOleWindow::EvOcAmbientGetFont(IDispatch** /*font*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETBACKCOLOR message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window changes its background color to rgb and returns true.
bool
TOleWindow::EvOcAmbientSetBackColor(long /*backColor*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETFORECOLOR message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window changes its background color to rgb and returns true.
bool
TOleWindow::EvOcAmbientSetForeColor(long /*foreColor*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETLOCALEID message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window changes its locale ID to locale and returns true.
bool
TOleWindow::EvOcAmbientSetLocaleID(long /*localeId*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETTEXTALIGN message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window aligns text according to the value in align and returns true.
bool
TOleWindow::EvOcAmbientSetTextAlign(short /*align*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETMESSAGEREFLECT message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window does or doesn't reflect messages according to the value in
/// msgReflect.
bool
TOleWindow::EvOcAmbientSetMessageReflect(bool /*reflect*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETUSERMODE message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window sets user mode equal to the value in mode.
bool
TOleWindow::EvOcAmbientSetUserMode(bool /*userMode*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETUIDEAD message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window enables or disables itself according to the value in dead.
bool
TOleWindow::EvOcAmbientSetUIDead(bool /*dead*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETSHOWGRABHANDLES message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window shows or hides grab handles according to the value in show.
bool
TOleWindow::EvOcAmbientSetShowGrabHandles(bool /*showHandles*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETSETSHOWHATCHING message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window shows or hides hatching according to the value in hatching.
bool
TOleWindow::EvOcAmbientSetShowHatching(bool /*showHatching*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETDISPLAYASDEFAULT message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window displays itself as a default control (if the window represents a
/// button control) if disp is true.
bool
TOleWindow::EvOcAmbientSetDisplayAsDefault(bool /*displayAsDefault*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETSUPPORTSMNEMONICS message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window turns its support for mnemonics on or off according to the value
/// in support.
bool
TOleWindow::EvOcAmbientSetSupportsMnemonics(bool /*supportMnemonics*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETDISPLAYNAME message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window changes its display name (for error messages) to name and returns true.
bool
TOleWindow::EvOcAmbientSetDisplayName(TString* /*name*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETSCALEUNITS message, which is sent by an OCX
/// control. Returns false by default. You can override the default implementation
/// so the window sets its scale units equal to units and returns true.
bool
TOleWindow::EvOcAmbientSetScaleUnits(TString* /*units*/)
{
return false;
}
/// Handles the EV_OC_AMBIENT_SETFONT message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window changes its font to font and returns true.
bool
TOleWindow::EvOcAmbientSetFont(IDispatch* /*font*/)
{
return false;
}
//
// Control Event Dispatches
//
/// Handles the EV_OC_CTRLCLICK message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
//
bool
TOleWindow::EvOcCtrlClick(TCtrlEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLDBLCLICK message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
bool
TOleWindow::EvOcCtrlDblClick(TCtrlEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLMOUSEDOWN message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlMouseDown(TCtrlMouseEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLMOUSEUP message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
bool
TOleWindow::EvOcCtrlMouseUp(TCtrlMouseEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLMOUSEMOVE message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlMouseMove(TCtrlMouseEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLKEYDOWN message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
bool
TOleWindow::EvOcCtrlKeyDown(TCtrlKeyEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLKEYUP message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
bool
TOleWindow::EvOcCtrlKeyUp(TCtrlKeyEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLERROREVENT message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlErrorEvent(TCtrlErrorEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLFOCUS message, which is sent by an OCX control. Returns
/// false by default. You can override the default implementation so the window
/// responds to the message and returns true.
bool
TOleWindow::EvOcCtrlFocus(TCtrlFocusEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLPROPERTYCHANGE message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlPropertyChange(TCtrlPropertyEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_PROPERTYREQUESTEDIT message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlPropertyRequestEdit(TCtrlPropertyEvent* /*pev*/)
{
return false;
}
/// Handles the EV_OC_CTRLCUSTOMEVENT message, which is sent by an OCX control.
/// Returns false by default. You can override the default implementation so the
/// window responds to the message and returns true.
bool
TOleWindow::EvOcCtrlCustomEvent(TCtrlCustomEvent* /*pev*/)
{
return false;
}
//
/// Repaints the embedded objects on the given device context. The erase parameter
/// is true if the background of the embedded object is to be repainted. rect
/// indicates the area that needs repainting. metafile indicates whether or not the
/// object is a metafile.
//
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;
}
//
/// Sets the ratio of the embedded object's size to the size of the site.
//
void
TOleWindow::SetScale(uint16 percent)
{
Scale.SetScale(percent);
Invalidate();
}
//
/// Gets the logical units (typically pixels) per inch for a document so that the
/// document's embedded objects can be painted correctly on the screen device
/// context.
//
void
TOleWindow::GetLogPerUnit(TSize& logPerUnit)
{
TScreenDC dc;
logPerUnit.cx = dc.GetDeviceCaps(LOGPIXELSX);
logPerUnit.cy = dc.GetDeviceCaps(LOGPIXELSY);
}
//
/// Determines the viewport's origin and extent (the logical coordinates and the
/// size of the device context). Sets up the device context (DC) before painting the
/// embedded object. dc refers to the DC and scale indicates that the scaling factor
/// to use when painting the embedded object is a ratio between the site and the
/// embedded object.
//
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);
}
//
/// Sets up the dc for proper scaling and scrolling and then calls the derived
/// class's Paint method to paint the contents of the dc.
//
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();
}
}
//
/// Informs an active container that one of its embedded objects needs to be
/// redrawn. Changes in the container's part should be reflected in any other,
/// non-active views. Returns true after all views have been notified of the
/// necessary changes.
/// If the TOleWindow object is unable to handle the message, EvOcViewPartInvalid
/// returns false.
//
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
}
//
/// Creates and enables a pop-up menu option (ocVerb) on the Edit menu. The verb
/// describes an action (for example, Edit, Open, Play) that is appropriate for the
/// embedded object.
//
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,
(LPCTSTR)OleStr(ocVerb.VerbName));
}
verbMenu->AppendMenu(MF_SEPARATOR, 0, 0);
owl::tstring optName = GetModule()->LoadString(IDS_EDITCONVERT);
verbMenu->AppendMenu(MF_STRING, CM_EDITCONVERT, optName.c_str());
return verbMenu;
}
//
/// Executes an OLE-related menu option from the Edit menu (for example, Edit, Copy,
/// or Play) that is associated with the selected object.
//
void
TOleWindow::EvDoVerb(uint whichVerb)
{
DragPart->DoVerb(whichVerb);
}
//
/// Attaches the view to its ObjectWindows parent window so that the user can
/// perform open editing on the embedded object, or if the embedded object has been
/// de-activated while in-place editing was occurring.
/// If the TOleWindow object is unable to handle the message, EvOcViewAttachWindow
/// returns false.
//
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;
}
//
/// Handles the EV_OC_VIEWDOVERB message. Returns false. Implement your own event
/// handler to control how the window responds to verbs selected by the user.
//
bool
TOleWindow::EvOcViewDoVerb(uint /*verb*/)
{
return false;
}
//
// Perform the action indentified by verb
//
bool
TOleWindow::EvOcViewTransformCoords(uint /*verb*/)
{
return false;
}
//
/// Shuts down the associated ObjectComponents partners, if possible.
//
bool
TOleWindow::OleShutDown()
{
if (IsRemote()) {
TOcRemView* ocRemView = GetOcRemView();
if (IsOpenEditing())
ocRemView->Disconnect();
}
else {
if (OcView)
OcView->EvClose();
}
return true;
}
//
/// Performs normal window cleanup and informs the TOcView object that the window is closed.
//
void
TOleWindow::CleanupWindow()
{
TOleFrame* mainWindow = TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(),
TOleFrame);
if (mainWindow)
mainWindow->OleViewClosing(true);
OleShutDown();
if (mainWindow)
mainWindow->OleViewClosing(false);
TWindow::CleanupWindow();
}
//
/// Responds to an OC_VIEWSETSCALE message and handles the scaling for server
/// application, ensuring that the embedded object is displayed using the correct
/// scaling values (for example, 120%). The server uses this value in its paint
/// procedure when the embedded object needs to be redrawn. scaleFactor indicates
/// the scaling factor, the ratio between the size of the embedded object and the
/// size of the site where the object is to be displayed.
/// If the TOleWindow object is unable to handle the message, EvOcViewSetScale
/// returns false.
//
bool
TOleWindow::EvOcViewSetScale(TOcScaleFactor& scaleFactor)
{
Scale = scaleFactor;
return true;
}
//
/// Handles the EV_OC_VIEWGETITEMNAME. Returns false.
//
bool
TOleWindow::EvOcViewGetItemName(TOcItemName& /*item*/)
{
return false;
}
//----------------------------------------------------------------------------
// Linking Spport
//
//
/// Responds to an OC_VIEWSETLINK message TOcLinkView sends when the server document
/// provides a link to a container document. EvOcViewSetLink establishes the link
/// between a TOleLinkView and a TOcLinkView. view references the view with which
/// the document or selection is associated. Returns false if unsuccessful.
/// Doc/View applications use TOleView 's implementation of this function.
//
bool
TOleWindow::EvOcViewSetLink(TOcLinkView& /*view*/)
{
return false;
}
//
/// EvOcViewBreakLink responds to an OC_VIEWBREAKLINK message that TOcLinkView sends
/// when the server document that provides the link shuts down. EvOcViewBreakLink
/// breaks the link with a server document or a selection by deleting the
/// TOleLinkView associated with the TOcLinkView (view). Returns false if
/// unsuccessful. Doc/View applications use TOleView's EvOcViewBreakLink, which
/// overrides TOleWindow's version.
//
bool
TOleWindow::EvOcViewBreakLink(TOcLinkView& /*view*/)
{
return false;
}
IMPLEMENT_STREAMABLE1(TOleWindow, TWindow);
#if OWL_PERSISTENT_STREAMS
//
//
//
void*
TOleWindow::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
owl::ReadBaseObject((TWindow*)GetObject(), is);
GetObject()->Remote = false; // intialized in CreateOcView()
GetObject()->OcApp = 0; // initialized in Init()
GetObject()->OcDoc = 0;
GetObject()->OcView = 0;
GetObject()->Init();
is >> GetObject()->Scale; // current scaling factor
is >> GetObject()->Pos; // current position
is >> GetObject()->ShowObjects; // Show embedded part frames?
return GetObject();
}
//
//
//
void
TOleWindow::Streamer::Write(opstream& os) const
{
owl::WriteBaseObject((TWindow*)GetObject(), os);
os << GetObject()->Scale; // current scaling factor
os << GetObject()->Pos; // current position
os << GetObject()->ShowObjects; // Show embedded part frames?
}
#endif
} // OCF namespace
//==============================================================================
↑ V773 The function was exited without releasing the 'part' pointer. A memory leak is possible.
↑ V1004 The 'mainWindow' pointer was used unsafely after it was verified against nullptr. Check lines: 1838, 1839.
↑ V522 There might be dereferencing of a potential null pointer 'olefr'.
↑ V522 There might be dereferencing of a potential null pointer 'olefr'.
↑ V522 There might be dereferencing of a potential null pointer 'GetOcRemView()'.
↑ V522 There might be dereferencing of a potential null pointer 'GetOcRemView()'.
↑ V522 There might be dereferencing of a potential null pointer 'GetOcRemView()'.
↑ V522 There might be dereferencing of a potential null pointer 'ocRemView'.
↑ V614 Potentially uninitialized variable 'strCloseMenu[0]' used. Consider checking the first actual argument of the 'SetText' function.
↑ V524 It is odd that the body of 'CeEditInsertControl' function is fully equivalent to the body of 'CeEditInsertObject' function.
↑ V803 Decreased performance. In case 'i' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'i' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V813 Decreased performance. The 'ocxIID' argument should probably be rendered as a constant reference.
↑ V821 Decreased performance. The 'optName' variable can be constructed in a lower level scope.
↑ V821 Decreased performance. The 'changeInfo' variable can be constructed in a lower level scope.