📄 dsofcontrol.cpp
字号:
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnResize
//
// Resize the window and notify the doc site.
//
STDMETHODIMP_(void) CDsoFramerControl::OnResize()
{
RECT rcPlace;
ODS("CDsoFramerControl::OnResize\n");
if (m_pDocObjFrame)
{
GetSizeRectForDocument(NULL, &rcPlace);
m_pDocObjFrame->OnNotifySizeChange(&rcPlace);
}
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnMouseMove
//
// We watch for mouse movement on menu bar (when visible).
//
STDMETHODIMP_(void) CDsoFramerControl::OnMouseMove(UINT x, UINT y)
{
// TRACE2("CDsoFramerControl::OnMouseMove(%d, %d)\n", x, y);
// When we are in mouse move, watch for menu selection. Only need to
// do this if bar is visible and we are not in modal state...
if ((m_fComponentActive) && (m_fShowMenuBar) &&
#ifdef DSO_ACTIVATION_ON_FOCUS_CHANGE
(m_fUIActive) &&
#endif
(!m_fModalState) && (!m_fNoInteractive))
{
UINT item;
POINT pt; pt.x = x; pt.y = y;
// If we already have item selected, check to see if we are still
// over it. If so, we can exit now. If not, we sould unselect it.
if (m_wSelMenuItem)
{
item = m_wSelMenuItem - 1;
if (PtInRect(&m_rgrcMenuItems[item], pt))
return;
ReleaseCapture(); m_wSelMenuItem = 0;
InvalidateRect(m_hwnd, &m_rgrcMenuItems[item], FALSE);
}
// Now loop through the menu items and see if mouse is over them.
// If it is, we set a mouse capture and draw item as selected...
for (item = 0; item < m_cMenuItems; item++)
{
if (PtInRect(&m_rgrcMenuItems[item], pt))
{
SetCapture(m_hwnd);
m_wSelMenuItem = (USHORT)(item + 1);
InvalidateRect(m_hwnd, &m_rgrcMenuItems[item], FALSE);
break;
}
}
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnButtonDown
//
// We watch for mouse button down events when the titlebar is visible
// so we can drop down our popup menu if the user clicks around the
// area of the file icon. This is our workaround for menu merging.
//
STDMETHODIMP_(void) CDsoFramerControl::OnButtonDown(UINT x, UINT y)
{
if(!m_fShowMenuBar) return;
HMENU hCurMenu = NULL;
RECT rc;
// Don't do anything if we are in modal state...
if (m_fModalState) return;
if (m_fNoInteractive)
{
// We don't handle commends when m_fNoInteractive is set, except for the
// condition where we are in print preview and want to display custom menu
// item to end the preview. Office apps have toolbar button to do this, but
// we will provide this option just in case user needs it to exit preview mode...
if ((m_fShowTitlebar) && ((x < 22) && (y < 22)) &&
(m_pDocObjFrame) && (m_pDocObjFrame->InPrintPreview()))
{
// Create a temp popup menu. I do this on fly to save resources since
// this is only needed in rare cases...
hCurMenu = CreatePopupMenu();
if (hCurMenu)
{
// Add the command to the menu...
AppendMenu(hCurMenu, MF_STRING, MNU_PRINTPV, "E&xit Preview");
// Display the menu...
GetSizeRectAfterTitlebar(NULL, &rc);
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&rc, 2);
TrackPopupMenu(hCurMenu, 0, rc.left, rc.top - 1, 0, m_hwnd, NULL);
// Cleanup...
DestroyMenu(hCurMenu);
hCurMenu = NULL;
}
}
// Otherwise we do nothing when m_fNoInteractive == TRUE.
return;
}
// If we don't have UI focus, take it...
if (!m_fUIActive) Activate();
// If the caption is showing, we are not modal, and user clicked in the
// area around the office doc icon, show the popup menu...
if ((m_fShowTitlebar) && (!m_fShowMenuBar) && ((x < 22) && (y < 22)))
{
// This will get the File menu or the merged menu based on current state...
hCurMenu = GetActivePopupMenu();
if (hCurMenu)
{
// We'll place it right below the titlebar just like sys menu...
GetSizeRectAfterTitlebar(NULL, &rc);
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&rc, 2);
TrackPopupMenu(hCurMenu, 0, rc.left, rc.top - 1, 0, m_hwnd, NULL);
}
}
else if ((m_fShowMenuBar) && (m_wSelMenuItem))
{
POINT pt;
UINT item = m_wSelMenuItem - 1;
// If we are over a visible menu bar item, find the right popup
// menu for the item using the selitem as an index...
if (item == 0)
{ hCurMenu = m_hmenuFilePopup; }
else
{
hCurMenu = GetActivePopupMenu();
if (hCurMenu) hCurMenu = GetSubMenu(hCurMenu, item);
}
// Map the location to display the popup into screen points...
pt.x = m_rgrcMenuItems[item].left;
pt.y = m_rgrcMenuItems[item].bottom;
MapWindowPoints(m_hwnd, HWND_DESKTOP, (POINT*)&pt, 1);
// Display the menu...
TrackPopupMenu(hCurMenu, 0, pt.x, pt.y, 0, m_hwnd, NULL);
// When user clicks off, we will resolve the mouse location to
// our control coordinates and call mousemove to free/reset selection...
if (GetCursorPos(&pt))
{
RECT rcMenu; GetSizeRectForMenuBar(NULL, &rcMenu);
MapWindowPoints(HWND_DESKTOP, m_hwnd, (POINT*)&pt, 1);
if (!PtInRect(&rcMenu, pt)) {pt.x = 0; pt.y = 0;}
}
else {pt.x = 0; pt.y = 0;}
OnMouseMove(pt.x, pt.y);
}
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnMenuMessage
//
// We should get these messages when we are displaying the popup menu.
// The "File" menu is ours, but the popup may have other menus copied
// from the merged menu set by the ui active docobject, so we need to
// forward those messages (as needed) to the right window handler.
//
// In addition, code is added to enable/disable File menu items based
// on flags set by developer in EnableFileCommand, and/or call the
// correct function if one of those commands was selected by user.
//
STDMETHODIMP_(void) CDsoFramerControl::OnMenuMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu, hmenuMerged = NULL;
BOOL fAlwaysSendMessage = FALSE;
HWND hwndObjectMenu = NULL;
if (m_pDocObjFrame)
{
hwndObjectMenu = m_pDocObjFrame->GetMenuHWND();
hmenuMerged = m_pDocObjFrame->GetMergedMenu();
}
switch (msg)
{
case WM_INITMENU: m_fObjectMenu = FALSE; //fall through...
case WM_ENTERIDLE: fAlwaysSendMessage = TRUE;
break;
case WM_MENUSELECT:
if ((lParam == 0) && (HIWORD(wParam) == 0xFFFF))
fAlwaysSendMessage = TRUE;
break;
case WM_INITMENUPOPUP:
hmenu = (HMENU)wParam;
m_fObjectMenu = ((hmenu != m_hmenuFilePopup) && (hmenu != hmenuMerged));
if ((!m_fObjectMenu) && (hmenu == m_hmenuFilePopup))
{
EnableMenuItem(hmenu, MNU_NEW, MF_BYCOMMAND | ((m_wFileMenuFlags & 1) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_OPEN, MF_BYCOMMAND | ((m_wFileMenuFlags & 2) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_CLOSE, MF_BYCOMMAND | (((m_wFileMenuFlags & 4) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_SAVE, MF_BYCOMMAND | (((m_wFileMenuFlags & 8) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_SAVEAS, MF_BYCOMMAND | (((m_wFileMenuFlags & 16) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PGSETUP, MF_BYCOMMAND | (((m_wFileMenuFlags & 64) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PRINTPV, MF_BYCOMMAND | (((m_wFileMenuFlags & 256) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PRINT, MF_BYCOMMAND | (((m_wFileMenuFlags & 32) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
EnableMenuItem(hmenu, MNU_PROPS, MF_BYCOMMAND | (((m_wFileMenuFlags & 128) && (m_pDocObjFrame)) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
}
break;
case WM_COMMAND:
// We handle one special case for print preview exit, but otherwise
// we need to either forward to the merged menu handler (if enabled),
// or handle command through an asynchronous callback...
if ((m_fNoInteractive) && (LOWORD(wParam) == MNU_PRINTPV))
{
PrintPreviewExit();
}
else if ((m_fObjectMenu) && (hwndObjectMenu))
{
PostMessage(hwndObjectMenu, msg, wParam, lParam);
}
else
{
DWORD dwCmd = 0;
switch ((int)LOWORD(wParam))
{
case MNU_NEW: dwCmd = OLECMDID_NEW; break;
case MNU_OPEN: dwCmd = OLECMDID_OPEN; break;
case MNU_SAVE: dwCmd = OLECMDID_SAVE; break;
case MNU_SAVEAS: dwCmd = OLECMDID_SAVEAS; break;
case MNU_PGSETUP: dwCmd = OLECMDID_PAGESETUP; break;
case MNU_PRINT: dwCmd = OLECMDID_PRINT; break;
case MNU_PROPS: dwCmd = OLECMDID_PROPERTIES; break;
case MNU_PRINTPV: dwCmd = OLECMDID_PRINTPREVIEW; break;
}
PostMessage(m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, dwCmd, 0);
}
return; // we just return
}
if ((hwndObjectMenu) && ((m_fObjectMenu) || (fAlwaysSendMessage)))
SendMessage(hwndObjectMenu, msg, wParam, lParam);
return;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::OnToolbarAction
//
// Does an associated OLECMDID action and raises the OnFileCommand event
// for developer to override as needed. The name comes from the fact that
// most Office servers will call this (via IOleCommandTarget) when user
// clicks on a toolbar button for file-command item. It also serves for
// our menu commands to keep the code consistant. Both menu and toolbar
// call this method asynchronously (via PostMessage) to avoid blocking the
// remote docobject server.
//
STDMETHODIMP_(void) CDsoFramerControl::OnToolbarAction(DWORD cmd)
{
ODS("CDsoFramerControl::OnToolbarAction\n");
HRESULT hr = S_OK;
VARIANT_BOOL wCancelAction = VARIANT_FALSE;
VARIANT rgargs[2];
VARIANT vtT = {0};
// We don't reenter if in a modal state already...
if (m_fModalState) return;
// If not interactive, we cannot run command...
if (m_fNoInteractive)
{
// unless we are in preview, in which case we can force exit
// and then run command after preview completes...
if ((m_pDocObjFrame) && (m_pDocObjFrame->InPrintPreview()))
{
PrintPreviewExit();
if (cmd != OLECMDID_PRINTPREVIEW)
PostMessage(m_hwnd, DSO_WM_ASYNCH_OLECOMMAND, cmd, 0);
}
return;
}
// We will do a default action by default, but give developer a chance
// to override in OnFileCommand event...
rgargs[0].vt = VT_BOOL|VT_BYREF;
rgargs[0].pboolVal = &wCancelAction;
// Map the OLECMDID to one of our values...
rgargs[1].vt = VT_I4;
switch (cmd)
{
case OLECMDID_NEW: rgargs[1].lVal = dsoFileNew; break;
case OLECMDID_OPEN: rgargs[1].lVal = dsoFileOpen; break;
case OLECMDID_SAVE: rgargs[1].lVal = dsoFileSave; break;
case OLECMDID_SAVEAS: rgargs[1].lVal = dsoFileSaveAs; break;
case OLECMDID_PRINT: rgargs[1].lVal = dsoFilePrint; break;
case OLECMDID_PAGESETUP: rgargs[1].lVal = dsoFilePageSetup; break;
case OLECMDID_PROPERTIES: rgargs[1].lVal = dsoFileProperties; break;
case OLECMDID_PRINTPREVIEW: rgargs[1].lVal = dsoFilePrintPreview; break;
default: rgargs[1].lVal = dsoFileClose;
}
// Only do action if item is enabled...
if ((1 << rgargs[1].lVal) & m_wFileMenuFlags)
{
// Let control developer handle the event first...
if ((m_dispEvents) && !(m_fFreezeEvents))
{
hr = DsoDispatchInvoke(m_dispEvents, NULL, DSOF_DISPID_FILECMD, 0, 2, rgargs, NULL);
TRACE1("Disp event returned 0x%X \n", hr);
}
// If the event was canceled (or event handler threw an
// unhandled error from user code), bail out now...
if ((wCancelAction) || (hr == DISP_E_EXCEPTION))
return;
// Do the action based on the event...
switch (rgargs[1].lVal)
{
case dsoFileClose: hr = Close(); break;
case dsoFilePrint: hr = ShowDialog(dsoDialogPrint); break;
case dsoFilePageSetup: hr = ShowDialog(dsoDialogPageSetup); break;
case dsoFileProperties: hr = ShowDialog(dsoDialogProperties); break;
case dsoFilePrintPreview: hr = PrintPreview(); break;
case dsoFileSave:
hr = Save(vtT, vtT, vtT, vtT);
if ((hr != DSO_E_DOCUMENTREADONLY) &&
(hr != DSO_E_NOTBEENSAVED))
break; // fall through to SaveAs if file is read-only or never been saved...
default:
hr = DoDialogAction(
(rgargs[1].lVal == dsoFileNew) ? dsoDialogNew :
(rgargs[1].lVal == dsoFileOpen) ? dsoDialogOpen : dsoDialogSave);
}
// Display error information to user if we failed...
if (FAILED(hr) && (hr != E_ABORT))
{
if (hr == DSO_E_COMMANDNOTSUPPORTED)
{
MessageBox(m_hwnd,
"This operation could not be performed because the document server "
"does not support the command, or it is disabled when embedded.",
"Command Not Supported", MB_ICONINFORMATION|MB_SETFOREGROUND);
}
else if (hr == DSO_E_DOCUMENTREADONLY)
{
MessageBox(m_hwnd,
"The operation could not be performed because the document was opened read-only.",
"Unable to Update Document", MB_ICONINFORMATION|MB_SETFOREGROUND);
}
else if ((hr == DSO_E_INVALIDSERVER) || (hr == DSO_E_INVALIDPROGID))
{
MessageBox(m_hwnd, "The item selected is not associated with an ActiveX "
"Document server. It cannot be loaded into the control.",
"Cannot Open Item", MB_ICONINFORMATION|MB_SETFOREGROUND);
}
else if (hr == DSO_E_REQUIRESMSDAIPP)
{
MessageBox(m_hwnd,
"You cannot open/save to a web folder unless MDAC 2.5 is installed. The operation cannot be performed.",
"Unable to Open/Save Document", MB_ICONINFORMATION|MB_SETFOREGROUND);
}
else
{
MessageBox(m_hwnd, "The program encountered an error trying to perform the command. "
"If the problem persists, contact the program vendor for a possible solution.",
"Command Error", MB_ICONHAND|MB_SETFOREGROUND);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -