//---------------------------------------------------------------------------- // 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 #include #include #include #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // 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(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; }