Windows2003-3790/inetcore/outlookexpress/gwnote/envhost.cpp
2020-09-30 16:53:55 +02:00

809 lines
19 KiB
C++

/*
* e n v h o s t . c p p
*
* Purpose:
*
* History
*
* Copyright (C) Microsoft Corp. 1995, 1996.
*/
#include <pch.hxx>
#include "resource.h"
#include "envcid.h"
#include "commdlg.h"
#include "docobj.h"
#include "dllmain.h"
#include "msoert.h"
#include "mimeole.h"
#include "envhost.h"
#include "richedit.h"
#include "init.h"
#include "shellapi.h"
HINSTANCE s_hRichEdit;
HINSTANCE g_hLocRes ;
HACCEL g_hAccelMailSend;
HRESULT HrRicheditStreamOut(HWND hwndRE, LPSTREAM pstm, ULONG uSelFlags);
void SaveFocus(BOOL fActive, HWND *phwnd);
static const TCHAR c_szGWNoteWndClass[] = "GW_Note";
//+---------------------------------------------------------------
//
// Member: Constructor
//
// Synopsis:
//
//---------------------------------------------------------------
CEnvHost::CEnvHost(IUnknown *pUnkOuter) : CPrivateUnknown(pUnkOuter)
{
DllAddRef();
}
//+---------------------------------------------------------------
//
// Member: Destructor
//
// Synopsis:
//
//---------------------------------------------------------------
CEnvHost::~CEnvHost()
{
DllRelease();
}
//+---------------------------------------------------------------
//
// Member: PrivateQueryInterface
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CEnvHost::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
{
if(!lplpObj)
return E_INVALIDARG;
*lplpObj = NULL;
if (IsEqualIID(riid, IID_IUnknown))
*lplpObj = (LPVOID)(IMsoEnvelopeHost *)this;
else if (IsEqualIID(riid, IID_IMsoEnvelopeHost))
*lplpObj = (LPVOID)(IMsoEnvelopeHost *)this;
else
{
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
HRESULT CEnvHost::CreateNote(IUnknown *punk, REFCLSID clsidCreate, LPCWSTR wszTheme, LPCWSTR wszAuthor, LPCWSTR wszPrefix, DWORD grfCreate)
{
return HrCreateNote(clsidCreate, grfCreate);
}
HRESULT CEnvHost::LockServer(BOOL fLock)
{
return S_OK;
}
//+---------------------------------------------------------------
//
// Member: Constructor
//
// Synopsis:
//
//---------------------------------------------------------------
CGWNote::CGWNote(IUnknown *pUnkOuter) : CPrivateUnknown(pUnkOuter)
{
m_pEnv=NULL;
m_hwnd=NULL;
m_hwndRE=NULL;
m_pComponent=NULL;
m_hwndFocus=NULL;
DllAddRef();
}
//+---------------------------------------------------------------
//
// Member: Destructor
//
// Synopsis:
//
//---------------------------------------------------------------
CGWNote::~CGWNote()
{
DllRelease();
}
//+---------------------------------------------------------------
//
// Member: PrivateQueryInterface
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CGWNote::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
{
if(!lplpObj)
return E_INVALIDARG;
*lplpObj = NULL;
if (IsEqualIID(riid, IID_IUnknown))
*lplpObj = (LPVOID)(IPersistMime *)this;
else if (IsEqualIID(riid, IID_IServiceProvider))
*lplpObj = (LPVOID)(IServiceProvider *)this;
else if (IsEqualIID(riid, IID_IPersistMime))
*lplpObj = (LPVOID)(IPersistMime *)this;
else if (IsEqualIID(riid, IID_IMsoEnvelopeSite))
*lplpObj = (LPVOID)(IMsoEnvelopeSite *)this;
else if (IsEqualIID(riid, IID_IMsoComponentManager))
*lplpObj = (LPVOID)(IMsoComponentManager *)this;
else
{
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
//+---------------------------------------------------------------
//
// Member: GetClassID
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CGWNote::GetClassID(CLSID *pClassID)
{
*pClassID = CLSID_GWEnvelopeHost;
return NOERROR;
}
// *** IServiceProvider ***
//+---------------------------------------------------------------
//
// Member: QueryService
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CGWNote::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
if (IsEqualGUID(guidService, IID_IMsoComponentManager))
return PrivateQueryInterface(riid, ppvObject);
return E_NOINTERFACE;
}
// *** IPersistMime ***
//+---------------------------------------------------------------
//
// Member: Load
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CGWNote::Load(IMimeMessage *pMsg)
{
return E_NOTIMPL;
}
//+---------------------------------------------------------------
//
// Member: Save
//
// Synopsis:
//
//---------------------------------------------------------------
HRESULT CGWNote::Save(IMimeMessage *pMsg, DWORD dwFlags)
{
IPersistMime *pPM;
IStream *pstm;
HRESULT hr;
// save envelope props
if (m_pEnv &&
m_pEnv->QueryInterface(IID_IPersistMime, (LPVOID *)&pPM)==S_OK)
{
hr = pPM->Save(pMsg, dwFlags);
pPM->Release();
}
// save body props
if (MimeOleCreateVirtualStream(&pstm)==S_OK)
{
if (HrRicheditStreamOut(m_hwndRE, pstm, SF_TEXT)==S_OK)
pMsg->SetTextBody(TXT_PLAIN, IET_BINARY, NULL, pstm, NULL);
pstm->Release();
}
return hr;
}
HRESULT CGWNote::RequestResize(int *pcHeight)
{
RECT rc;
m_cyEnv = *pcHeight;
GetClientRect(m_hwnd, &rc);
rc.top +=2;
rc.bottom = m_cyEnv+2;
m_pEnv->Resize(&rc);
GetClientRect(m_hwnd, &rc);
rc.top += m_cyEnv + 4;
rc.bottom -=2;
SetWindowPos(m_hwndRE, NULL, 0, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
return S_OK;
}
HRESULT CGWNote::CloseNote(DWORD grfClose)
{
SendMessage(m_hwnd, WM_CLOSE, 0, 0);
return S_OK;
}
HRESULT CGWNote::GetBody(IStream *pstm, DWORD dwCodePage, DWORD grfBody)
{
return E_NOTIMPL;
}
HRESULT CGWNote::SetBody(IStream *pstm, DWORD dwCodePage, DWORD grfBody)
{
return S_OK;
}
HRESULT CGWNote::SetFocus(BOOL fTab)
{
if (fTab)
::SetFocus(m_hwndRE);
return S_OK;
}
HRESULT CGWNote::OnEnvSetFocus()
{
return S_OK;
}
HRESULT CGWNote::OnPropChange(ULONG dispid)
{
return S_OK;
}
HRESULT CGWNote::IsBodyDirty()
{
return S_OK;
}
HRESULT CGWNote::HandsOff()
{
return S_OK;
}
HRESULT CGWNote::GetMsoInst(HMSOINST *phinst)
{
return E_NOTIMPL;
}
HRESULT CGWNote::GetFrameWnd(HWND *phwndFrame)
{
return E_NOTIMPL;
}
HRESULT CGWNote::DisplayMessage(HRESULT hr, LPCWSTR wszError, DWORD grfMsg)
{
return S_OK;
}
LRESULT CGWNote::ExtWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CGWNote *pNote;
if(msg==WM_CREATE)
{
pNote=(CGWNote *)((LPCREATESTRUCT)lParam)->lpCreateParams;
if(!pNote)
return -1;
if(FAILED(pNote->OnCreate(hwnd)))
return -1;
}
pNote = (CGWNote *)GetWndThisPtr(hwnd);
if(pNote)
return pNote->WndProc(hwnd, msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
LRESULT CGWNote::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LONG lret;
switch (msg)
{
case WM_NOTIFY:
return (WMNotify(wParam, (NMHDR *)lParam)==S_OK);
case WM_COMMAND:
if (WMCommand( GET_WM_COMMAND_HWND(wParam, lParam),
GET_WM_COMMAND_ID(wParam, lParam),
GET_WM_COMMAND_CMD(wParam, lParam))==S_OK)
return 0;
break;
case WM_SIZE:
RequestResize((int *)&m_cyEnv);
break;
case WM_NCDESTROY:
OnNCDestroy();
break;
}
lret = DefWindowProc(hwnd, msg, wParam, lParam);
if(msg==WM_ACTIVATE)
{
// post-process wm_activates to set focus back to
// control
SaveFocus((BOOL)(LOWORD(wParam)), &m_hwndFocus);
g_pActiveNote = (LOWORD(wParam)==WA_INACTIVE)?NULL:this;
}
return lret;
}
HRESULT CGWNote::Init(REFCLSID clsidEnvelope, DWORD dwFlags)
{
HRESULT hr=S_OK;
HWND hwnd;
WNDCLASS wc;
HMENU hMenu;
TraceCall("CDocHost::Init");
if (!GetClassInfo(g_hInst, c_szGWNoteWndClass, &wc))
{
ZeroMemory(&wc, sizeof(WNDCLASS));
wc.lpfnWndProc = CGWNote::ExtWndProc;
wc.hInstance = g_hInst;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = c_szGWNoteWndClass;
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.style = CS_DBLCLKS;
if(!RegisterClass(&wc))
return E_OUTOFMEMORY;
}
hMenu = LoadMenu(g_hInst, "GWNOTEMENU");
if (!hMenu)
return E_OUTOFMEMORY;
hwnd=CreateWindowEx(WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT,
c_szGWNoteWndClass,
"GW Note Control",
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
0,
0,
400,
400,
NULL,
hMenu,
g_hInst,
(LPVOID)this);
if(!hwnd)
{
hr=E_OUTOFMEMORY;
goto error;
}
hr = InitEnvelope(clsidEnvelope, dwFlags);
error:
return hr;
}
HRESULT CGWNote::OnCreate(HWND hwnd)
{
CHARFORMAT cf={0};
m_hwnd = hwnd;
SetWindowLong(hwnd, GWL_USERDATA, (LPARAM)this);
m_hwndRE = CreateWindowEx(WS_EX_CLIENTEDGE,
"RichEdit",
"",
//ES_MULTILINE|ES_SAVESEL|ES_AUTOVSCROLL|ES_SELECTIONBAR|ES_WANTRETURN|WS_VSCROLL|WS_CHILD|WS_TABSTOP|WS_VISIBLE,
ES_SAVESEL|ES_WANTRETURN|ES_MULTILINE|WS_CHILD|WS_TABSTOP|WS_VISIBLE|ES_AUTOVSCROLL|WS_VSCROLL,
0, 0, 0, 0,
hwnd,
(HMENU)99,
g_hInst,
NULL);
if (!m_hwndRE)
return E_FAIL;
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR|CFM_FACE;
cf.crTextColor = RGB(0,0,255);
lstrcpy(cf.szFaceName, "Verdana");
SendMessage(m_hwndRE, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
SendMessage(m_hwndRE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
SendMessage(m_hwndRE, EM_SETEVENTMASK, 0, ENM_KEYEVENTS);
AddRef();
return S_OK;
}
HRESULT CGWNote::OnNCDestroy()
{
SafeRelease(m_pEnv);
if (m_pComponent)
{
m_pComponent->Terminate();
SafeRelease(m_pComponent);
}
SetWindowLong(m_hwnd, GWL_USERDATA, NULL);
m_hwnd = NULL;
Release();
return S_OK;
}
HRESULT CGWNote::Show()
{
ShowWindow(m_hwnd, SW_SHOW);
return S_OK;
}
HRESULT CGWNote::InitEnvelope(REFCLSID clsidEnvelope, DWORD dwFlags)
{
HRESULT hr;
RECT rc;
hr = CoCreateInstance(clsidEnvelope, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, IID_IMsoEnvelope, (LPVOID *)&m_pEnv);
if (FAILED(hr))
goto error;
hr = m_pEnv->Init(NULL, (IMsoEnvelopeSite *)this, dwFlags);
if (FAILED(hr))
goto error;
hr = m_pEnv->SetParent(m_hwnd);
if (FAILED(hr))
goto error;
hr = m_pEnv->Show(TRUE);
if (FAILED(hr))
goto error;
m_pEnv->SetFocus(ENV_FOCUS_INITIAL);
error:
return hr;
}
HRESULT CGWNote::TranslateAcclerator(MSG *lpmsg)
{
if (!g_hAccelMailSend)
g_hAccelMailSend= LoadAccelerators(g_hInst, MAKEINTRESOURCE(idacMail_SendNote));
if (::TranslateAccelerator(m_hwnd, g_hAccelMailSend, lpmsg))
return S_OK;
if (m_pComponent &&
m_pComponent->FPreTranslateMessage(lpmsg))
return S_OK;
return S_FALSE;
}
DWORD CALLBACK EditStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
{
return ((LPSTREAM)dwCookie)->Write(pbBuff, cb, (ULONG *)pcb);
}
HRESULT HrRicheditStreamOut(HWND hwndRE, LPSTREAM pstm, ULONG uSelFlags)
{
EDITSTREAM es;
if(!pstm)
return E_INVALIDARG;
if(!IsWindow(hwndRE))
return E_INVALIDARG;
HrRewindStream(pstm);
es.dwCookie = (DWORD)pstm;
es.pfnCallback=(EDITSTREAMCALLBACK)EditStreamOutCallback;
SendMessage(hwndRE, EM_STREAMOUT, uSelFlags, (LONG)&es);
return S_OK;
}
BOOL CGWNote::FRegisterComponent(IMsoComponent *piComponent, const MSOCRINFO *pcrinfo, DWORD *pdwComponentID)
{
if (m_pComponent) // only one register allowed
return E_FAIL;
ReplaceInterface(m_pComponent, piComponent);
*pdwComponentID=666;
return TRUE;
}
BOOL CGWNote::FRevokeComponent(DWORD dwComponentID)
{
return TRUE;
}
BOOL CGWNote::FUpdateComponentRegistration(DWORD dwComponentID, const MSOCRINFO *pcrinfo)
{
return FALSE;
}
BOOL CGWNote::FOnComponentActivate(DWORD dwComponentID)
{
return FALSE;
}
BOOL CGWNote::FSetTrackingComponent(DWORD dwComponentID, BOOL fTrack)
{
return FALSE;
}
void CGWNote::OnComponentEnterState(DWORD dwComponentID, ULONG uStateID, ULONG uContext,ULONG cpicmExclude,IMsoComponentManager **rgpicmExclude, DWORD dwReserved)
{
}
BOOL CGWNote::FOnComponentExitState(DWORD dwComponentID, ULONG uStateID, ULONG uContext,ULONG cpicmExclude,IMsoComponentManager **rgpicmExclude)
{
return FALSE;
}
BOOL CGWNote::FInState(ULONG uStateID, void *pvoid)
{
return FALSE;
}
BOOL CGWNote::FContinueIdle ()
{
return FALSE;
}
BOOL CGWNote::FPushMessageLoop(DWORD dwComponentID, ULONG uReason, void *pvLoopData)
{
return FALSE;
}
BOOL CGWNote::FCreateSubComponentManager(IUnknown *piunkOuter, IUnknown *piunkServProv,REFIID riid, void **ppvObj)
{
return FALSE;
}
BOOL CGWNote::FGetParentComponentManager(IMsoComponentManager **ppicm)
{
return FALSE;
}
BOOL CGWNote::FGetActiveComponent(DWORD dwgac, IMsoComponent **ppic, MSOCRINFO *pcrinfo, DWORD dwReserved)
{
return FALSE;
}
BOOL CGWNote::FDebugMessage(HMSOINST hinst, UINT message, WPARAM wParam, LPARAM lParam)
{
return FALSE;
}
HRESULT CGWNote::WMCommand(HWND hwndCmd, int id, WORD wCmd)
{
if (wCmd > 1)
return S_FALSE;
switch(id)
{
case idmNewMsg:
ShellExecute(m_hwnd, NULL, "mailto:", 0, 0, SW_SHOW);
return S_OK;
case idmProperties:
MessageBox(m_hwnd, "PlaceHolder", "Properties", MB_OK);
return S_OK;
case idmSaveAs:
return SaveAs();
case idmClose:
PostMessage(m_hwnd, WM_CLOSE, 0, 0);
return S_OK;
case idmCheckNames:
return HrHeaderExecCommand(MSOEENVCMDID_CHECKNAMES, MSOCMDEXECOPT_PROMPTUSER, NULL);
case idmPickRecipients:
return HrHeaderExecCommand(MSOEENVCMDID_SELECTRECIPIENTS, MSOCMDEXECOPT_DODEFAULT, NULL);
case idmViewContacts:
return HrHeaderExecCommand(MSOEENVCMDID_VIEWCONTACTS, MSOCMDEXECOPT_DODEFAULT, NULL);
default:
MessageBox(m_hwnd, "Not Yet Implemented", "Menu Command", MB_OK);
return S_OK;
}
return S_FALSE;
}
HRESULT CGWNote::HrHeaderExecCommand(UINT uCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn)
{
HRESULT hr = S_FALSE;
IOleCommandTarget *pCmdTarget;
if(m_pEnv &&
m_pEnv->QueryInterface(IID_IOleCommandTarget, (LPVOID *)&pCmdTarget)==S_OK)
{
hr = pCmdTarget->Exec(&CGID_Envelope, uCmdID, nCmdExecOpt, pvaIn, NULL);
pCmdTarget->Release();
}
return hr;
}
HRESULT CGWNote::WMNotify(int idFrom, NMHDR *pnmh)
{
MSGFILTER *pmf=(MSGFILTER *)pnmh;
BOOL fShift;
switch (pnmh->code)
{
case EN_MSGFILTER:
if (pmf->msg == WM_KEYDOWN && pmf->wParam == VK_TAB && !(GetKeyState(VK_CONTROL) & 0x8000))
{
// shift tab puts focus in the envelope
if (GetKeyState(VK_SHIFT)&0x8000 && m_pEnv)
{
m_pEnv->SetFocus(ENV_FOCUS_TAB);
return S_OK;
}
}
break;
}
return S_FALSE;
}
void SaveFocus(BOOL fActive, HWND *phwnd)
{
if(fActive&&IsWindow(*phwnd))
SetFocus(*phwnd);
else
*phwnd=GetFocus();
}
static char c_szFilter[] = "Rfc 822 Messages (*.eml)\0*.eml\0\0";
HRESULT CGWNote::SaveAs()
{
OPENFILENAME ofn;
TCHAR szFile[MAX_PATH];
TCHAR szTitle[MAX_PATH];
TCHAR szDefExt[30];
WCHAR szFileW[MAX_PATH];
lstrcpy(szFile, "c:\\*.eml");
lstrcpy(szDefExt, ".eml");
lstrcpy(szTitle, "Save Message As...");
ZeroMemory (&ofn, sizeof (ofn));
ofn.lStructSize = sizeof (ofn);
ofn.hwndOwner = m_hwnd;
ofn.lpstrFilter = c_szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof (szFile);
ofn.lpstrTitle = szTitle;
ofn.lpstrDefExt = szDefExt;
ofn.Flags = OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
if (*szFile==NULL)
return E_FAIL;
// Show OpenFile Dialog
if (!GetSaveFileName(&ofn))
return MIMEEDIT_E_USERCANCEL;
MultiByteToWideChar(CP_ACP, 0, szFile, -1, szFileW, MAX_PATH);
return SaveToFile(szFileW);
}
HRESULT CGWNote::SaveToFile(LPWSTR pszW)
{
IPersistMime *ppm;
IPersistFile *pPF;
IMimeMessage *pMsg;
HRESULT hr;
hr = CoCreateInstance(CLSID_IMimeMessage, NULL, CLSCTX_INPROC_SERVER, IID_IMimeMessage, (LPVOID *)&pMsg);
if (!FAILED(hr))
{
pMsg->InitNew();
hr = pMsg->QueryInterface(IID_IPersistFile, (LPVOID *)&pPF);
if (!FAILED(hr))
{
hr = Save(pMsg, 0);
if (!FAILED(hr))
{
hr = pPF->Save(pszW, FALSE);
}
pPF->Release();
}
pMsg->Release();
}
return hr;
}
HRESULT CGWNote::DirtyToolbars(void)
{
return S_OK;
}
HRESULT CGWNote::SetHelpMode(BOOL fEnter)
{
return S_OK;
}
HRESULT CGWNote::TranslateAccelerators(MSG *pMsg)
{
return S_FALSE;
}