//********************************************************************** // File name: hlp_app.cxx // // Implementation file for the CSimpleApp Class // // Functions: // // See app.hxx for a list of member functions. // // Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved. //********************************************************************** #include "hlp_pre.hxx" #include "hlp_iocs.hxx" #include "hlp_ias.hxx" #include "hlp_app.hxx" #include "hlp_site.hxx" #include "hlp_doc.hxx" HWND m_hAppWnd; // main window handle HINSTANCE m_hInst; // application instance CMDIWnd* v_pMDIWnd; //********************************************************************** // // CSimpleApp::CSimpleApp() // // Purpose: // // Constructor for CSimpleApp // // Parameters: // // None // // Return Value: // // None // // Function Calls: // Function Location // // OutputDebugString Windows API // SetRectEmpty Windows API // // Comments: // // CSimpleApp has a contained COleInPlaceFrame. On construction // of CSimpleApp, we explicitly call the constructor of this // contained class and pass a copy of the this pointer, so that // COleInPlaceFrame can refer back to this class // //******************************************************************** #pragma warning(disable : 4355) // turn off this warning. This warning // tells us that we are passing this in // an initializer, before "this" is through // initializing. This is ok, because // we just store the ptr in the other // constructor CSimpleApp::CSimpleApp() : m_OleInPlaceFrame(this) #pragma warning (default : 4355) // Turn the warning back on { DEBUGOUT("In CSimpleApp's Constructor \r\n"); // Set Ref Count m_nCount = 0; // clear members m_hAppWnd = NULL; m_hInst = NULL; m_lpDoc = NULL; m_hwndUIActiveObj = NULL; // clear flags m_fInitialized = FALSE; m_fCSHMode = FALSE; m_fMenuMode = FALSE; // used for inplace SetRectEmpty(&nullRect); } //********************************************************************** // // CSimpleApp::~CSimpleApp() // // Purpose: // // Destructor for CSimpleApp Class. // // Parameters: // // None // // Return Value: // // None // // Function Calls: // Function Location // // OutputDebugString Windows API // OleUninitialize OLE API // // Comments: // //******************************************************************** CSimpleApp::~CSimpleApp() { DEBUGOUT("In CSimpleApp's Destructor\r\n"); if (m_hStdPal) DeleteObject(m_hStdPal); // need to uninit the library... if (m_fInitialized) OleUninitialize(); } //********************************************************************** // // CSimpleApp::DestroyDocs() // // Purpose: // // Destroys all of the open documents in the application (Only one // since this is an SDI app, but could easily be modified to // support MDI). // // Parameters: // // None // // Return Value: // // None // // Function Calls: // Function Location // // Comments: // //******************************************************************** void CSimpleApp::DestroyDocs() { m_lpDoc->Close(); // we have only 1 document } //********************************************************************** // // CSimpleApp::QueryInterface // // Purpose: // // Used for interface negotiation at the Frame level. // // Parameters: // // REFIID riid - A reference to the interface that is // being queried. // // LPVOID FAR* ppvObj - An out parameter to return a pointer to // the interface. // // Return Value: // // S_OK - The interface is supported. // S_FALSE - The interface is not supported // // Function Calls: // Function Location // // OutputDebugString Windows API // IsEqualIID OLE API // ResultFromScode OLE API // COleInPlaceFrame::AddRef IOIPF.cxx // // Comments: // // Note that this QueryInterface is associated with the frame. // Since the application could potentially have multiple documents // and multiple objects, a lot of the interfaces are ambiguous. // (ie. which IOleObject is returned?). For this reason, only // pointers to interfaces associated with the frame are returned. // In this implementation, Only IOleInPlaceFrame (or one of the // interfaces it is derived from) can be returned. // //******************************************************************** STDMETHODIMP CSimpleApp::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { DEBUGOUT("In CSimpleApp::QueryInterface\r\n"); *ppvObj = NULL; // must set out pointer parameters to NULL // looking for IUnknown if ( riid == IID_IUnknown) { AddRef(); *ppvObj = this; return ResultFromScode(S_OK); } // looking for IOleWindow if ( riid == IID_IOleWindow) { m_OleInPlaceFrame.AddRef(); *ppvObj=&m_OleInPlaceFrame; return ResultFromScode(S_OK); } // looking for IOleInPlaceUIWindow if ( riid == IID_IOleInPlaceUIWindow) { m_OleInPlaceFrame.AddRef(); *ppvObj=&m_OleInPlaceFrame; return ResultFromScode(S_OK); } // looking for IOleInPlaceFrame if ( riid == IID_IOleInPlaceFrame) { m_OleInPlaceFrame.AddRef(); *ppvObj=&m_OleInPlaceFrame; return ResultFromScode(S_OK); } // Not a supported interface return ResultFromScode(E_NOINTERFACE); } //********************************************************************** // // CSimpleApp::AddRef // // Purpose: // // Adds to the reference count at the Application level. // // Parameters: // // None // // Return Value: // // ULONG - The new reference count of the application. // // Function Calls: // Function Location // // OutputDebugString Windows API // // Comments: // // Due to the reference counting model that is used in this // implementation, this reference count is the sum of the // reference counts on all interfaces of all objects open // in the application. // //******************************************************************** STDMETHODIMP_(ULONG) CSimpleApp::AddRef() { DEBUGOUT("In CSimpleApp::AddRef\r\n"); return ++m_nCount; } //********************************************************************** // // CSimpleApp::Release // // Purpose: // // Decrements the reference count at this level // // Parameters: // // None // // Return Value: // // ULONG - The new reference count of the application. // // Function Calls: // Function Location // // OutputDebugString Windows API // // Comments: // //******************************************************************** STDMETHODIMP_(ULONG) CSimpleApp::Release() { DEBUGOUT("In CSimpleApp::Release\r\n"); if (--m_nCount == 0) { delete this; return 0; } return m_nCount; } //********************************************************************** // // CSimpleApp::fInitApplication // // Purpose: // // Initializes the application // // Parameters: // // HANDLE hInstance - Instance handle of the application. // // Return Value: // // TRUE - Application was successfully initialized. // FALSE - Application could not be initialized // // Function Calls: // Function Location // // LoadIcon Windows API // LoadCursor Windows API // GetStockObject Windows API // RegisterClass Windows API // // Comments: // //******************************************************************** BOOL CSimpleApp::fInitApplication(HANDLE hInstance) { WNDCLASS wc; // Fill in window class structure with parameters that describe the // main window. wc.style = NULL; // Class style(s). wc.lpfnWndProc = MainWndProc; // Function to retrieve messages for // windows of this class. wc.cbClsExtra = 0; // No per-class extra data. wc.cbWndExtra = 0; // No per-window extra data. wc.hInstance = hInstance; // Application that owns the class. wc.hIcon = LoadIcon(hInstance, "SimpCntr"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "SIMPLEMENU"; // Name of menu resource in .RC file. wc.lpszClassName = "SimpCntrAppWClass"; // Name used in CreateWindow call if (!RegisterClass(&wc)) return FALSE; wc.style = CS_DBLCLKS; // Class style(s). allow DBLCLK's wc.lpfnWndProc = DocWndProc; // Function to retrieve messages for // windows of this class. wc.cbClsExtra = 0; // No per-class extra data. wc.cbWndExtra = 0; // No per-window extra data. wc.hInstance = hInstance; // Application that owns the class. wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "SimpCntrDocWClass"; // Name used in CreateWindow call. // Register the window class and return success/failure code. return (RegisterClass(&wc)); } //********************************************************************** // // CSimpleApp::fInitInstance // // Purpose: // // Instance initialization. // // Parameters: // // HANDLE hInstance - App. Instance Handle. // // int nCmdShow - Show parameter from WinMain // // Return Value: // // TRUE - Initialization Successful // FALSE - Initialization Failed. // // // Function Calls: // Function Location // // CreateWindow Windows API // ShowWindow Windows API // UpdateWindow Windows API // OleBuildVersion OLE API // OleInitialize OLE API // // Comments: // // Note that successful Initalization of the OLE libraries // is remembered so the UnInit is only called if needed. // //******************************************************************** BOOL CSimpleApp::fInitInstance (HANDLE hInstance, int nCmdShow) { DWORD dwVer = OleBuildVersion(); LPMALLOC lpMalloc = NULL; // check to see if we are compatible with this version of the libraries if (HIWORD(dwVer) != rmm || LOWORD(dwVer) < rup) { #ifdef _DEBUG OutputDebugString("WARNING: Incompatible OLE library version\r\n"); #else return FALSE; #endif } #if defined( _DEBUG ) /* OLE2NOTE: Use a special debug allocator to help track down ** memory leaks. */ OleStdCreateDbAlloc(0, &lpMalloc); #endif if (OleInitialize(lpMalloc) == NOERROR) m_fInitialized = TRUE; #if defined( _DEBUG ) /* OLE2NOTE: release the special debug allocator so that only OLE is ** holding on to it. later when OleUninitialize is called, then ** the debug allocator object will be destroyed. when the debug ** allocator object is destoyed, it will report (to the Output ** Debug Terminal) whether there are any memory leaks. */ if (lpMalloc) lpMalloc->Release(); #endif m_hInst = hInstance; // Create the "application" windows m_hAppWnd = CreateWindow ("SimpCntrAppWClass", "Simple OLE 2.0 In-Place Container", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!m_hAppWnd) return FALSE; m_pMDIWnd = new (CMDIWnd); v_pMDIWnd.Create(); m_hStdPal = OleStdCreateStandardPalette(); ShowWindow (m_hAppWnd, nCmdShow); UpdateWindow (m_hAppWnd); return m_fInitialized; } //********************************************************************** // // CSimpleApp::lCommandHandler // // Purpose: // // Handles the processing of WM_COMMAND. // // Parameters: // // HWND hWnd - Handle to the application Window // // UINT message - message (always WM_COMMAND) // // WPARAM wParam - Same as passed to the WndProc // // LPARAM lParam - Same as passed to the WndProc // // Return Value: // // NULL // // Function Calls: // Function Location // // IOleInPlaceActiveObject::QueryInterface Object // IOleInPlaceObject::ContextSensitiveHelp Object // IOleInPlaceObject::Release Object // IOleObject::DoVerb Object // GetClientRect Windows API // MessageBox Windows API // DialogBox Windows API // MakeProcInstance Windows API // FreeProcInstance Windows API // SendMessage Windows API // DefWindowProc Windows API // CSimpleDoc::InsertObject DOC.cxx // // Comments: // //******************************************************************** long CSimpleApp::lCommandHandler (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rect; // context sensitive help... if (m_fMenuMode || m_fCSHMode) { if (m_fCSHMode) { // clear context sensitive help flag m_fCSHMode = FALSE; // if there is an InPlace active object, call its context sensitive help // method with the FALSE parameter to bring the object out of the // csh state. See the technotes for details. if (m_lpDoc->m_lpActiveObject) { LPOLEINPLACEOBJECT lpInPlaceObject; m_lpDoc->m_lpActiveObject->QueryInterface(IID_IOleInPlaceObject, (LPVOID FAR *)&lpInPlaceObject); lpInPlaceObject->ContextSensitiveHelp(FALSE); lpInPlaceObject->Release(); } } // see the technotes for details on implementing context sensitive // help if (m_fMenuMode) { m_fMenuMode = FALSE; if (m_lpDoc->m_lpActiveObject) m_lpDoc->m_lpActiveObject->ContextSensitiveHelp(FALSE); } // if we provided help, we would do it here... MessageBox (hWnd, "Help", "Help", MB_OK); return NULL; } // see if the command is a verb selections if (wParam >= IDM_VERB0) { // get the rectangle of the object m_lpDoc->m_lpSite->GetObjRect(&rect); m_lpDoc->m_lpSite->m_lpOleObject->DoVerb(wParam - IDM_VERB0, NULL, &m_lpDoc->m_lpSite->m_OleClientSite, -1, m_lpDoc->m_hDocWnd, &rect); } else { switch (wParam) { // bring up the About box case IDM_ABOUT: { FARPROC lpProcAbout = MakeProcInstance((FARPROC)About, m_hInst); DialogBox(m_hInst, // current instance "AboutBox", // resource to use m_hAppWnd, // parent handle lpProcAbout); // About() instance address FreeProcInstance(lpProcAbout); break; } // bring up the InsertObject Dialog case IDM_INSERTOBJECT: m_lpDoc->InsertObject(); break; // exit the application case IDM_EXIT: SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L); break; case IDM_NEW: m_lpDoc->Close(); m_lpDoc = NULL; lCreateDoc(hWnd, 0, 0, 0); break; case IDM_COPYLINE: case IDM_ADDLINE: case IDM_UNINDENTLINE: m_lpDoc->HandleDispatch(wParam); break; default: //return (DefWindowProc(hWnd, message, wParam, lParam)); return (DefFrameProc(hWnd, v_pMDIWnd->hwndMDIClient, message, wParam, lParam)); } // end of switch } // end of else return NULL; } //********************************************************************** // // CSimpleApp::lSizeHandler // // Purpose: // // Handles the WM_SIZE message // // Parameters: // // HWND hWnd - Handle to the application Window // // UINT message - message (always WM_SIZE) // // WPARAM wParam - Same as passed to the WndProc // // LPARAM lParam - Same as passed to the WndProc // // Return Value: // // LONG - returned from the "document" resizing // // Function Calls: // Function Location // // GetClientRect Windows API // CSimpleDoc::lResizeDoc DOC.cxx // // Comments: // //******************************************************************** long CSimpleApp::lSizeHandler (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rect; GetClientRect(m_hAppWnd, &rect); return m_lpDoc->lResizeDoc(&rect); } //********************************************************************** // // CSimpleApp::lCreateDoc // // Purpose: // // Handles the creation of a document. // // Parameters: // // HWND hWnd - Handle to the application Window // // UINT message - message (always WM_CREATE) // // WPARAM wParam - Same as passed to the WndProc // // LPARAM lParam - Same as passed to the WndProc // // Return Value: // // NULL // // Function Calls: // Function Location // // GetClientRect Windows API // CSimpleDoc::CSimpleDoc DOC.cxx // // Comments: // //******************************************************************** long CSimpleApp::lCreateDoc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rect; GetClientRect(hWnd, &rect); m_lpDoc = CSimpleDoc::Create(this, &rect, hWnd); return NULL; } //********************************************************************** // // CSimpleApp::AddFrameLevelUI // // Purpose: // // Used during InPlace negotiation. // // Parameters: // // None // // Return Value: // // None // // Function Calls: // Function Location // // COleInPlaceFrame::SetMenu IOIPF.cxx // CSimpleApp::AddFrameLevelTools APP.cxx // // Comments: // // Be sure to read the Technotes included in the OLE 2.0 toolkit // //******************************************************************** void CSimpleApp::AddFrameLevelUI() { m_OleInPlaceFrame.SetMenu(NULL, NULL, NULL); AddFrameLevelTools(); } //********************************************************************** // // CSimpleApp::AddFrameLevelTools // // Purpose: // // Used during InPlace negotiation. // // Parameters: // // None // // Return Value: // // None // // Function Calls: // Function Location // // COleInPlaceFrame::SetBorderSpace IOIPF.cxx // InvalidateRect Windows API // // Comments: // // Be sure to read the Technotes included in the OLE 2.0 toolkit // //******************************************************************** void CSimpleApp::AddFrameLevelTools() { m_OleInPlaceFrame.SetBorderSpace(&nullRect); InvalidateRect(m_hAppWnd, NULL, TRUE); } //********************************************************************** // // CSimpleApp::HandleAccelerators // // Purpose: // // To properly handle accelerators in the Message Loop // // Parameters: // // LPMSG lpMsg - A pointer to the message structure. // // Return Value: // // TRUE - The accelerator was handled // FALSE - The accelerator was not handled // // Function Calls: // Function Location // // IOleInPlaceActiveObject::TranslateAccelerator Object // // Comments: // // If an object is InPlace active, it gets the first shot at // handling the accelerators. // //******************************************************************** BOOL CSimpleApp::HandleAccelerators(LPMSG lpMsg) { HRESULT hResult; BOOL retval = FALSE; // if we have an InPlace Active Object if (m_lpDoc->m_lpActiveObject) { // Pass the accelerator on... hResult = m_lpDoc->m_lpActiveObject->TranslateAccelerator(lpMsg); if (hResult == NOERROR) retval = TRUE; } return retval; } //********************************************************************** // // CSimpleApp::PaintApp // // Purpose: // // Handles the painting of the doc window. // // // Parameters: // // HDC hDC - hDC to the Doc Window. // // Return Value: // // None // // Function Calls: // Function Location // // CSimpleDoc::PaintDoc DOC.cxx // // Comments: // // This is an app level function in case we want to do palette // management. // //******************************************************************** void CSimpleApp::PaintApp (HDC hDC) { // at this level, we could enumerate through all of the // visible objects in the application, so that a palette // that best fits all of the objects can be built. // This app is designed to take on the same palette // functionality that was provided in OLE 1.0, the palette // of the last object drawn is realized. Since we only // support one object at a time, it shouldn't be a big // deal. // if we supported multiple documents, we would enumerate // through each of the open documents and call paint. if (m_lpDoc) m_lpDoc->PaintDoc(hDC); } //********************************************************************** // // CSimpleApp::ContextSensitiveHelp // // Purpose: // Used in supporting context sensitive haelp at the app level. // // // Parameters: // // BOOL fEnterMode - Entering/Exiting Context Sensitive // help mode. // // Return Value: // // None // // Function Calls: // Function Location // // IOleInPlaceActiveObject::QueryInterface Object // IOleInPlaceObject::ContextSensitiveHelp Object // IOleInPlaceObject::Release Object // // Comments: // // This function isn't used because we don't support Shift+F1 // context sensitive help. Be sure to look at the technotes // in the OLE 2.0 toolkit. // //******************************************************************** void CSimpleApp::ContextSensitiveHelp (BOOL fEnterMode) { if (m_fCSHMode != fEnterMode) { m_fCSHMode = fEnterMode; // this code "trickles" the context sensitive help via shift+f1 // to the inplace active object. See the technotes for implementation // details. if (m_lpDoc->m_lpActiveObject) { LPOLEINPLACEOBJECT lpInPlaceObject; m_lpDoc->m_lpActiveObject->QueryInterface(IID_IOleInPlaceObject, (LPVOID FAR *)&lpInPlaceObject); lpInPlaceObject->ContextSensitiveHelp(fEnterMode); lpInPlaceObject->Release(); } } } /* OLE2NOTE: forward the WM_QUERYNEWPALETTE message (via ** SendMessage) to UIActive in-place object if there is one. ** this gives the UIActive object the opportunity to select ** and realize its color palette as the FOREGROUND palette. ** this is optional for in-place containers. if a container ** prefers to force its color palette as the foreground ** palette then it should NOT forward the this message. or ** the container can give the UIActive object priority; if ** the UIActive object returns 0 from the WM_QUERYNEWPALETTE ** message (ie. it did not realize its own palette), then ** the container can realize its palette. ** (see ContainerDoc_ForwardPaletteChangedMsg for more info) ** ** (It is a good idea for containers to use the standard ** palette even if they do not use colors themselves. this ** will allow embedded object to get a good distribution of ** colors when they are being drawn by the container) ** */ LRESULT CSimpleApp::QueryNewPalette(void) { if (m_hwndUIActiveObj) { if (SendMessage(m_hwndUIActiveObj, WM_QUERYNEWPALETTE, (WPARAM)0, (LPARAM)0)) { /* Object selected its palette as foreground palette */ return (LRESULT)1; } } return wSelectPalette(m_hAppWnd, m_hStdPal, FALSE/*fBackground*/); } /* This is just a helper routine */ LRESULT wSelectPalette(HWND hWnd, HPALETTE hPal, BOOL fBackground) { HDC hdc; HPALETTE hOldPal; UINT iPalChg = 0; if (hPal == 0) return (LRESULT)0; hdc = GetDC(hWnd); hOldPal = SelectPalette(hdc, hPal, fBackground); iPalChg = RealizePalette(hdc); SelectPalette(hdc, hOldPal, TRUE /*fBackground*/); ReleaseDC(hWnd, hdc); if (iPalChg > 0) InvalidateRect(hWnd, NULL, TRUE); return (LRESULT)1; }