5245 lines
165 KiB
C++
5245 lines
165 KiB
C++
/*************************************************************************/
|
|
/* Copyright (C) 1999 Microsoft Corporation */
|
|
/* File: MFBar.cpp */
|
|
/* Description: Control that is scriptable and contains other controls. */
|
|
/* Designed specifically for DVD/TV control plates. */
|
|
/* Author: David Janecek */
|
|
/*************************************************************************/
|
|
#include "stdafx.h"
|
|
#include "MFBar.h"
|
|
#include "ccobj.h"
|
|
#include "eobj.h"
|
|
#include "CBitmap.h"
|
|
|
|
/*************************************************************************/
|
|
/* Local defines */
|
|
/* Could not find these under windows headers, so if there is a conflict */
|
|
/* it is good idea to ifdef these out. */
|
|
/*************************************************************************/
|
|
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
|
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
|
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
|
|
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
|
|
#define NOHIT 1
|
|
#define LEFT 2
|
|
#define TOP 4
|
|
#define RIGHT 8
|
|
#define BOTTOM 16
|
|
#define ID_EV_TIMER 0xff
|
|
|
|
/*************************************************************************/
|
|
/* Windows defines not present, remove when doing the real BUILD. */
|
|
/*************************************************************************/
|
|
typedef WINUSERAPI BOOL ( WINAPI * SETLAYEREDWINDATR)(
|
|
HWND hwnd,
|
|
COLORREF crKey,
|
|
BYTE bAlpha,
|
|
DWORD dwFlags);
|
|
#if 0
|
|
#define LWA_COLORKEY 0x00000001
|
|
#endif
|
|
/*************************************************************************/
|
|
/* Local functions */
|
|
/*************************************************************************/
|
|
inline long MAX(long l1, long l2){return(l1 > l2 ? l1 : l2);}
|
|
inline long MIN(long l1, long l2){return(l1 < l2 ? l1 : l2);}
|
|
|
|
/*************************************************************************/
|
|
/* Statics for window class info */
|
|
/*************************************************************************/
|
|
HICON CMFBar::m_hIcon = NULL;
|
|
|
|
/*****************************************************************/
|
|
/* change this depending if the file was saved as Unicode or not */
|
|
/*****************************************************************/
|
|
//#define _UNICODE_SCRIPT_FILE
|
|
|
|
/*************************************************************************/
|
|
/* CMFBar Implementation */
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* Function: Init */
|
|
/* Description: Initializes memeber variables. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::Init(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// #### BEGIN CONTAINER SUPPORT ####
|
|
m_bCanWindowlessActivate = true;
|
|
// #### END CONTAINER SUPPORT ####
|
|
|
|
#if 1 // used for getting the windowed case working DJ
|
|
m_bWindowOnly = TRUE;
|
|
#endif
|
|
m_fSelfHosted = false;
|
|
|
|
// TODO: Investigate if it works in pallete mode
|
|
m_clrBackColor = ::GetSysColor(COLOR_BTNFACE);
|
|
m_lMinWidth = -1; // disable it
|
|
m_lMinHeight = -1; // disable it by default
|
|
m_fHandleHelp = false;
|
|
m_blitType = DISABLE;
|
|
m_bMouseDown = false;
|
|
m_ptMouse.x = 0;
|
|
m_ptMouse.y = 0;
|
|
m_nReadyState = READYSTATE_LOADING;
|
|
m_fAutoLoad = VARIANT_TRUE;
|
|
m_pBackBitmap = NULL;
|
|
m_fForceKey = false;
|
|
m_lTimeout = 0;
|
|
m_fUserActivity = false;
|
|
m_fWaitingForActivity = false;
|
|
|
|
// setup the default resource DLL to be this binary
|
|
m_hRes = _Module.m_hInstResource; // set the resource DLL Name
|
|
TCHAR szModule[_MAX_PATH+10];
|
|
::GetModuleFileName(m_hRes, szModule, _MAX_PATH);
|
|
|
|
USES_CONVERSION;
|
|
m_strResDLL = T2OLE(szModule);
|
|
|
|
if(NULL == m_hIcon){
|
|
|
|
m_hIcon = ::LoadIcon(m_hRes, MAKEINTRESOURCE(IDI_ICON1));
|
|
//m_hIcon = (HICON)::LoadImage(_Module.m_hInstResource, MAKEINTRESOURCE(IDI_ICON1),
|
|
// IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
|
|
}/* end of if statement */
|
|
|
|
|
|
return(hr);
|
|
}/* end of function Init */
|
|
|
|
/*************************************************************************/
|
|
/* Function: Cleanup */
|
|
/* Description: Makes sure the script engine is released. Also cleans */
|
|
/* up the contained objects in the containers. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::Cleanup(){
|
|
// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
|
|
// Release the language engine, since it may hold on to us
|
|
if (m_psp){
|
|
|
|
m_psp.Release();
|
|
}/* end of if statement */
|
|
|
|
if (m_ps){
|
|
|
|
m_ps->Close();
|
|
m_ps.Release();
|
|
}/* end of if statement */
|
|
|
|
// cleanup the event list
|
|
for(CNTEVNT::iterator i = m_cntEvnt.begin(); false == m_cntEvnt.empty(); ){
|
|
|
|
CEventObject* pObj = (*i);
|
|
delete pObj;
|
|
i = m_cntEvnt.erase(i);
|
|
}/* end of if statement */
|
|
|
|
CContainerObject* pSelfContainerObj = NULL;
|
|
// cleanup the object list
|
|
for(CNTOBJ::iterator j = m_cntObj.begin(); false == m_cntObj.empty(); ){
|
|
|
|
CHostedObject* pObj = (*j);
|
|
|
|
// delete the container object as well
|
|
CContainerObject* pContainerObj;
|
|
HRESULT hrCont = pObj->GetContainerObject(&pContainerObj);
|
|
|
|
IUnknown* pUnk = pObj->GetUnknown();
|
|
#if _DEBUG
|
|
|
|
BSTR strOBJID = ::SysAllocString(pObj->GetID());
|
|
#endif
|
|
try {
|
|
|
|
delete pObj;
|
|
}
|
|
catch(...){
|
|
#if _DEBUG
|
|
USES_CONVERSION;
|
|
ATLTRACE(TEXT(" Failed to destroy %s "), OLE2T(strOBJID));
|
|
::SysFreeString(strOBJID);
|
|
#endif
|
|
}/* end of catch statement */
|
|
|
|
if(SUCCEEDED(hrCont)){
|
|
|
|
#if 1
|
|
if(GetUnknown() != pUnk){
|
|
|
|
delete pContainerObj; // do not delete our self
|
|
}
|
|
else {
|
|
|
|
pSelfContainerObj = pContainerObj;
|
|
}/* end of if statement */
|
|
#endif
|
|
}/* end of if statement */
|
|
|
|
j = m_cntObj.erase(j);
|
|
}/* end of if statement */
|
|
|
|
ResetFocusArray();
|
|
|
|
delete pSelfContainerObj;
|
|
|
|
if(m_pBackBitmap){
|
|
|
|
delete m_pBackBitmap;
|
|
m_pBackBitmap = NULL;
|
|
}/* end of if statement */
|
|
|
|
HRESULT hr = Init();
|
|
// ##### END ACTIVEX SCRIPTING SUPPORT #####
|
|
|
|
return (hr);
|
|
}/* end of function Cleanup */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ~CMFBar */
|
|
/*************************************************************************/
|
|
CMFBar::~CMFBar(){
|
|
|
|
Cleanup();
|
|
ATLTRACE(TEXT("Exiting CMFBar destructor! \n"));
|
|
}/* end of function ~CMFBar */
|
|
|
|
/*************************************************************************/
|
|
/* Message handling. */
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnPaint */
|
|
/* Description: Had to overwrite the the deafult OnPaint so I could */
|
|
/* somehow get the real update rects. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnPaint(UINT /* uMsg */, WPARAM wParam,
|
|
LPARAM /* lParam */, BOOL& /* lResult */){
|
|
|
|
RECT rc;
|
|
PAINTSTRUCT ps;
|
|
|
|
HDC hdc = (wParam != NULL) ? (HDC)wParam : ::BeginPaint(m_hWndCD, &ps);
|
|
if (hdc == NULL)
|
|
return 0;
|
|
::GetClientRect(m_hWndCD, &rc);
|
|
|
|
ATL_DRAWINFO di;
|
|
memset(&di, 0, sizeof(di));
|
|
di.cbSize = sizeof(di);
|
|
di.dwDrawAspect = DVASPECT_CONTENT;
|
|
di.lindex = -1;
|
|
di.hdcDraw = hdc;
|
|
// DJ change here, keep the real update rect from the PAINTSTRUCT
|
|
// Set the window size to the size of the window
|
|
di.prcWBounds = (LPCRECTL)&rc;
|
|
di.prcBounds = (LPCRECTL)&ps.rcPaint;
|
|
|
|
OnDrawAdvanced(di); // Eventually propagates to OnDraw
|
|
if (wParam == NULL)
|
|
::EndPaint(m_hWndCD, &ps);
|
|
return 0;
|
|
}/* end of function OnPaint */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnDraw */
|
|
/* Description: Just Draws the rectangular background and contained */
|
|
/* windowless controls. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::OnDraw(ATL_DRAWINFO& di){
|
|
|
|
try {
|
|
HDC hdc = di.hdcDraw;
|
|
|
|
RECT rcClient = *(RECT*)di.prcBounds;
|
|
RECT rcWClient = *(RECT*)di.prcWBounds;
|
|
|
|
// this might not work if you overlapp the controls
|
|
// controls like to be painted as a whole so if
|
|
// we need to update the are that contains the control
|
|
// we need to find all the controls that intersect it, combine the
|
|
// rectangle and then repaint the whole region
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
if(!::EqualRect(&rcClient, &rcWClient)){
|
|
|
|
RECT rcNewClient = rcClient; // the original update are which we are enlarging
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained objects and draw them
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if((NULL != pObj) && (pObj->IsActive())){
|
|
|
|
if(pObj->IsWindowless()){
|
|
|
|
RECT rcCntrl;
|
|
pObj->GetPos(&rcCntrl); // get the position of the object
|
|
|
|
RECT rcInt;
|
|
if(!::IntersectRect(&rcInt, &rcCntrl, &rcClient)){
|
|
|
|
continue;
|
|
}
|
|
else {
|
|
// OK we need to add this control rect to our rect union
|
|
::UnionRect(&rcNewClient, &rcClient, &rcCntrl);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
rcClient = rcNewClient; // update our are with enlarged client
|
|
}/* end of if statement */
|
|
// else if the rects are the same we are updating the whole
|
|
// window so there is no point to do the calculations
|
|
}/* end of if statement */
|
|
|
|
COLORREF clr;
|
|
HPALETTE hPal = NULL;
|
|
|
|
if(m_pBackBitmap){
|
|
|
|
hPal = m_pBackBitmap->GetPal();
|
|
|
|
if(NULL != hPal){
|
|
|
|
::SelectPalette(hdc, hPal, FALSE);
|
|
::RealizePalette(hdc);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
::OleTranslateColor (m_clrBackColor, hPal, &clr);
|
|
|
|
// fill in the background and get ready to fill in the objects
|
|
LONG lBmpWidth = RECTWIDTH(&rcWClient);
|
|
LONG lBmpHeight = RECTHEIGHT(&rcWClient);
|
|
|
|
HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, lBmpWidth, lBmpHeight);
|
|
|
|
if(NULL == hBitmap){
|
|
|
|
ATLASSERT(FALSE);
|
|
return(0);
|
|
}/* end of if statement */
|
|
|
|
HDC hdcCompatible = ::CreateCompatibleDC(hdc);
|
|
|
|
if(NULL == hBitmap){
|
|
|
|
ATLASSERT(FALSE);
|
|
::DeleteObject(hBitmap);
|
|
return(0);
|
|
}/* end of if statement */
|
|
|
|
// Draw background on the faceplate bitmap
|
|
::SelectObject(hdcCompatible, hBitmap);
|
|
|
|
if (!m_pBackBitmap){
|
|
// fill background of specific color
|
|
HBRUSH hbrBack = ::CreateSolidBrush(clr);
|
|
//::FillRect(hdc, &rcClient, hbrBack);
|
|
::FillRect(hdcCompatible, &rcClient, hbrBack);
|
|
::DeleteObject(hbrBack);
|
|
}
|
|
else {
|
|
|
|
//BOOL bRet = m_pBackBitmap->PaintTransparentDIB(hdc, &rcWClient, &rcClient, m_blitType, true);
|
|
BOOL bRet = m_pBackBitmap->PaintTransparentDIB(hdcCompatible, &rcWClient, &rcClient, m_blitType, true);
|
|
|
|
if(!bRet){
|
|
|
|
ATLTRACE(TEXT(" The transparent Blit did not work!"));
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained objects and draw them
|
|
CHostedObject* pObj = (*i);
|
|
|
|
CComPtr<IViewObjectEx> pViewObject = NULL;
|
|
|
|
if((NULL != pObj) && (pObj->IsActive()) && (SUCCEEDED(pObj->GetViewObject(&pViewObject)))){
|
|
|
|
if(pObj->IsWindowless()){
|
|
|
|
if(pViewObject){
|
|
|
|
if(GetUnknown() == pObj->GetUnknown()){
|
|
// in case we are windowless and we are trying to draw our self again
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
RECT rcCntrl;
|
|
pObj->GetPos(&rcCntrl);
|
|
|
|
RECT rcInt;
|
|
if(!::IntersectRect(&rcInt, &rcCntrl, &rcClient)){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
LONG lBmpWidth = RECTWIDTH(&rcCntrl);
|
|
LONG lBmpHeight = RECTHEIGHT(&rcCntrl);
|
|
RECT rcCntrlBitmap = {0, 0, lBmpWidth, lBmpHeight};
|
|
|
|
POINT ptNewOffset = {rcCntrl.left, rcCntrl.top};
|
|
|
|
POINT ptOldOffset;
|
|
|
|
::GetViewportOrgEx(hdcCompatible, &ptOldOffset);
|
|
LPtoDP(hdcCompatible, &ptNewOffset, 1);
|
|
// offset the rect we are catually going to draw
|
|
//::OffsetRect(&rcInt, -ptNewOffset.x, -ptNewOffset.y);
|
|
// offset the DC
|
|
::OffsetViewportOrgEx(hdcCompatible, ptNewOffset.x, ptNewOffset.y, &ptOldOffset);
|
|
|
|
// draw
|
|
ATLTRACE2(atlTraceWindowing, 31, TEXT("Drawing CONTROL into rcClient.left = %d, rcClient.right = %d, rcClient.bottom =%d, rcClient.top = %d\n"),rcCntrl.left, rcCntrl.right, rcCntrl.bottom, rcCntrl.top);
|
|
#if 1 // used to redraw the whole control, now we are just doinf part of it
|
|
//HRGN hrgnOld = NULL;
|
|
//HRGN hrgnNew = NULL;
|
|
//if(::IsWindow(m_hWnd)){
|
|
//
|
|
// hrgnNew = ::CreateRectRgnIndirect(&rcInt);
|
|
// hrgnOld = (HRGN)::SelectObject(hdc, hrgnNew);
|
|
//}/* end of if statement */
|
|
|
|
pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcCompatible, (RECTL*)&rcCntrlBitmap, (RECTL*)&rcCntrlBitmap, NULL, NULL);
|
|
#else
|
|
pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcCompatible, (RECTL*)&rcInt, (RECTL*)&rcCntrlBitmap, NULL, NULL);
|
|
#endif
|
|
::SetViewportOrgEx(hdcCompatible, ptOldOffset.x, ptOldOffset.y, NULL);
|
|
}
|
|
#ifdef _DEBUG
|
|
else {
|
|
|
|
ATLTRACE2(atlTraceWindowing, 30,TEXT("FAILED Drawing the object since pView is NULL\n"));
|
|
}/* end of if statement */
|
|
#endif
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
::BitBlt(hdc, rcClient.left, rcClient.top, lBmpWidth, lBmpHeight, hdcCompatible, rcClient.left, rcClient.top, SRCCOPY);
|
|
// cleanup
|
|
::DeleteDC(hdcCompatible);
|
|
::DeleteObject(hBitmap);
|
|
|
|
return(1);
|
|
}/* end of try statement */
|
|
catch(...){
|
|
return(0);
|
|
}/* end of catch statement */
|
|
}/* end of function OnDraw */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnErase */
|
|
/* Description: Skip the erasing to avoid flickers. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnErase(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
ATLTRACE2(atlTraceWindowing, 32, TEXT("Received WM_ERASE MESSAGE \n"));
|
|
|
|
#if 0
|
|
POINT pt; pt.x =0; pt.y = 0;
|
|
::MapWindowPoints(m_hWnd, hWndPar, &pt, 1);
|
|
::OffsetWindowOrgEx(hdc, pt.x, pt.y, &pt);
|
|
::SendMessage(hWndPar, WM_ERASEBKGND, (WPARAM) hdc, 0);
|
|
::SetWindowOrgEx(hdc, pt.x, pt.y, NULL);
|
|
|
|
#endif
|
|
|
|
//InvalidateRect(&m_rcPos, FALSE);
|
|
|
|
bHandled = TRUE;
|
|
return 1;
|
|
}/* end of function OnErase */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnQueryNewPalette */
|
|
/* Description: Called when we are about to be instantiated. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnQueryNewPalette(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
if(NULL == ::IsWindow(m_hWnd)){
|
|
|
|
bHandled = FALSE;
|
|
return FALSE;
|
|
}/* end of if statement */
|
|
|
|
HPALETTE hPal = NULL;
|
|
|
|
if(NULL == m_pBackBitmap){
|
|
|
|
hPal = m_pBackBitmap->GetPal();
|
|
}/* end of if statement */
|
|
|
|
if(NULL == hPal){
|
|
|
|
//bHandled = FALSE;
|
|
return FALSE;
|
|
}/* end of if statement */
|
|
|
|
HDC hdc = ::GetDC(m_hWnd);
|
|
::SelectPalette(hdc, hPal, FALSE);
|
|
::RealizePalette(hdc);
|
|
::InvalidateRect(m_hWnd, NULL, FALSE);
|
|
|
|
::ReleaseDC(m_hWnd, hdc);
|
|
|
|
return TRUE;
|
|
}/* end of function OnQueryNewPalette */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnPaletteChanged */
|
|
/* Description: Called when palette is chaning. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnPaletteChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
if(NULL == ::IsWindow(m_hWnd)){
|
|
|
|
bHandled = FALSE;
|
|
return FALSE;
|
|
}/* end of if statement */
|
|
|
|
if((HWND) wParam == m_hWnd){
|
|
|
|
bHandled = FALSE;
|
|
return FALSE;
|
|
}/* end of if statement */
|
|
|
|
HPALETTE hPal = NULL;
|
|
|
|
if(NULL == m_pBackBitmap){
|
|
|
|
hPal = m_pBackBitmap->GetPal();
|
|
}/* end of if statement */
|
|
|
|
if(NULL == hPal){
|
|
|
|
bHandled = FALSE;
|
|
return FALSE;
|
|
}/* end of if statement */
|
|
|
|
HDC hdc = ::GetDC(m_hWnd);
|
|
::SelectPalette(hdc, hPal, FALSE);
|
|
::RealizePalette(hdc);
|
|
::UpdateColors(hdc);
|
|
|
|
::ReleaseDC(m_hWnd, hdc);
|
|
|
|
bHandled = FALSE;
|
|
|
|
return TRUE;
|
|
}/* end of function OnPaletteChanged */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnClose */
|
|
/* Description: Skip the erasing to avoid flickers. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnClose(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::DestroyWindow(m_hWnd);
|
|
}/* end of if statement */
|
|
|
|
HRESULT hr = Close(OLECLOSE_SAVEIFDIRTY);
|
|
ATLTRACE(TEXT("Closing \n"));
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
bHandled = TRUE;
|
|
}/* end of if statement */
|
|
|
|
return 0;
|
|
}/* end of function OnClose */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnSysCommand */
|
|
/* Description: Handles the on syscommand. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnSysCommand(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
ATLTRACE2(atlTraceWindowing, 20, TEXT("Received WM_SYSCOMMAND MESSAGE \n"));
|
|
|
|
if(wParam == SC_CONTEXTHELP){
|
|
|
|
m_fHandleHelp = true;
|
|
}/* end of if statement */
|
|
|
|
bHandled = FALSE;
|
|
return(1);
|
|
}/* end of function OnSysCommand */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnTimer */
|
|
/* Description: Handles the timer message. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnTimer(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
WPARAM wTimerID = wParam;
|
|
|
|
if(ID_EV_TIMER == wTimerID){
|
|
|
|
if(false == m_fUserActivity && false == m_fWaitingForActivity){
|
|
|
|
// fire message that there is no activity going on
|
|
m_fWaitingForActivity = true;
|
|
Fire_ActivityDeclined();
|
|
}/* end of if statement */
|
|
|
|
m_fUserActivity = false; // reset the flag
|
|
}
|
|
else {
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::KillTimer(m_hWnd, wTimerID);
|
|
}/* end of if statement */
|
|
|
|
Fire_Timeout(wTimerID);
|
|
}/* end of if statement */
|
|
|
|
bHandled = TRUE;
|
|
return(1);
|
|
}/* end of function OnTimer */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnCaptureChanged */
|
|
/* Description: Handles the on syscommand. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnCaptureChanged(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
ATLTRACE2(atlTraceWindowing, 20, TEXT("Received WM_CAPTURECHANGED MESSAGE \n"));
|
|
|
|
if(m_fHandleHelp){
|
|
|
|
HWND h;
|
|
if(SUCCEEDED(GetWindow(&h))){
|
|
|
|
POINT pt;
|
|
::GetCursorPos(&pt);
|
|
RECT rc;
|
|
::GetWindowRect(h, &rc);
|
|
|
|
if(!::PtInRect(&rc, pt)){
|
|
// we clicked somewhere outiside in our help mode
|
|
m_fHandleHelp = false; // otherwise we are going to get lbutton up and we will
|
|
// turn it off then
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
|
|
m_fHandleHelp = false; // could not get the window, but better trun off
|
|
// the help mode
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
bHandled = TRUE;
|
|
return(0);
|
|
}/* end of function OnCaptureChanged */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnSetIcon */
|
|
/* Description: Fires the help event. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnSetIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
LRESULT lr = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
|
|
|
|
return(lr);
|
|
}/* end of function OnSetIcon */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnInitDialog */
|
|
/* Description: Fires the help event. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
ATLASSERT(FALSE);
|
|
LRESULT lr = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
|
|
|
|
return(lr);
|
|
}/* end of function OnInitDialog */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnHelp */
|
|
/* Description: Fires the help event. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
HELPINFO* pHpi = (LPHELPINFO) lParam;
|
|
bHandled = TRUE;
|
|
|
|
if(NULL == pHpi){
|
|
|
|
return 0;
|
|
}/* end of if statement */
|
|
|
|
// first check if we have fired help on message box
|
|
HWND hCntrlWnd = (HWND)pHpi->hItemHandle;
|
|
|
|
if(::GetWindowLong(hCntrlWnd, GWL_STYLE) & WS_DLGFRAME == WS_DLGFRAME){
|
|
// we have a message box up
|
|
|
|
HWND hwndText;
|
|
|
|
hwndText = ::FindWindowEx(hCntrlWnd, NULL, TEXT("Static"), NULL);
|
|
|
|
if(hwndText){
|
|
|
|
TCHAR strWindowText[MAX_PATH];
|
|
::GetWindowText(hwndText, strWindowText, MAX_PATH);
|
|
|
|
::DestroyWindow(hCntrlWnd);
|
|
|
|
BSTR strToolbarName;
|
|
|
|
if(SUCCEEDED(GetToolbarName(&strToolbarName))){
|
|
|
|
USES_CONVERSION;
|
|
Fire_OnHelp(strToolbarName, ::SysAllocString(T2OLE(strWindowText)));
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
|
|
::DestroyWindow(hCntrlWnd);
|
|
}/* end of if statement */
|
|
|
|
return(TRUE);
|
|
}/* end of if statement */
|
|
|
|
// then check if a windowed control has fired help
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE); // should not be null
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj->IsActive() && !pObj->IsWindowless()){
|
|
|
|
HWND hwnd = NULL;
|
|
|
|
HRESULT hr = pObj->GetWindow(&hwnd);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(hwnd == hCntrlWnd){
|
|
|
|
Fire_OnHelp(::SysAllocString(pObj->GetID()));
|
|
return(TRUE);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
// now look into windowless control
|
|
POINT ptMouse = pHpi->MousePos;
|
|
|
|
m_fHandleHelp = false; // get our self out of the help mode in case we clicked
|
|
// on windowed control and we did not get notified about this
|
|
|
|
// convert the point to client coordinates
|
|
HWND h = NULL;
|
|
HRESULT hr = GetWindow(&h);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLASSERT(FALSE);
|
|
return(0);
|
|
}/* end of if statement */
|
|
|
|
if(!::ScreenToClient(h, &ptMouse)){
|
|
|
|
ATLASSERT(FALSE);
|
|
return(0);
|
|
}/* end of if statement */
|
|
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE); // should not be null
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
|
|
// send the message to the control over which we are howering or on which we
|
|
// have clicked, check if we already are ready to send the message
|
|
// in that case do not bother with the rect interstec bussines
|
|
if(pObj->IsActive()){
|
|
|
|
CComPtr<IViewObjectEx> pViewObject;
|
|
HRESULT hr = pObj->GetViewObject(&pViewObject);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLASSERT(FALSE); // should have a view
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
DWORD dwHitResult = HITRESULT_OUTSIDE;
|
|
|
|
RECT rcCntrl;
|
|
pObj->GetPos(&rcCntrl);
|
|
|
|
pViewObject->QueryHitPoint(DVASPECT_CONTENT, &rcCntrl, ptMouse, 0, &dwHitResult);
|
|
|
|
if(HITRESULT_HIT == dwHitResult){
|
|
Fire_OnHelp(::SysAllocString(pObj->GetID()));
|
|
return(TRUE);
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
// Get toolbar name
|
|
BSTR strToolbarName;
|
|
|
|
if(SUCCEEDED(GetToolbarName(&strToolbarName))){
|
|
|
|
Fire_OnHelp(strToolbarName);
|
|
}/* end of if statement */
|
|
|
|
return(TRUE);
|
|
}/* end of function OnHelp */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnSize */
|
|
/* Description: Handles the onsize message if we are self contained. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnSize(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
if(false == m_fSelfHosted){
|
|
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}/* end of if statement */
|
|
|
|
LONG lWidth = LOWORD(lParam);
|
|
LONG lHeight = HIWORD(lParam);
|
|
|
|
Fire_OnResize(lWidth, lHeight, wParam);
|
|
|
|
if (m_pBackBitmap) {
|
|
InvalidateRgn();
|
|
if (::IsWindow(m_hWnd))
|
|
::UpdateWindow(m_hWnd);
|
|
}
|
|
|
|
bHandled = true;
|
|
|
|
return 0;
|
|
}/* end of function OnSize */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnSizing */
|
|
/* Description: Does not let us scale beyond the minimum size. If it */
|
|
/* tries to we fix up the rect on it. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnSizing(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
if(false == m_fSelfHosted){
|
|
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}/* end of if statement */
|
|
|
|
RECT* lpRect = (LPRECT)lParam;
|
|
|
|
LONG lWidth = RECTWIDTH(lpRect);
|
|
LONG lHeight = RECTHEIGHT(lpRect);
|
|
|
|
// if we are going to be to small fix the rect
|
|
if(lWidth < m_lMinWidth){
|
|
|
|
lpRect->right = lpRect->left + m_lMinWidth;
|
|
}/* end of if statement */
|
|
|
|
if(lHeight < m_lMinHeight){
|
|
|
|
lpRect->bottom = lpRect->top + m_lMinHeight;
|
|
}/* end of if statement */
|
|
|
|
bHandled = true;
|
|
|
|
return 0;
|
|
}/* end of function OnSizing */
|
|
|
|
/*************************************************************************/
|
|
/* Function: Close */
|
|
/* Description: Just exposes the underlaying Close functionality to our */
|
|
/* custom interface. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::Close(){
|
|
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::PostMessage(m_hWnd, WM_CLOSE, NULL, NULL);
|
|
|
|
return(S_OK);
|
|
//::DestroyWindow(m_hWnd);
|
|
}/* end of if statement */
|
|
|
|
return(Close(OLECLOSE_SAVEIFDIRTY));
|
|
}/* end of function Close */
|
|
|
|
/*************************************************************************/
|
|
/* Function: Close */
|
|
/* Description: Calls OLECLOSE the contained objects, then itself. */
|
|
/* The cleans up the containers and send WM_QUIT if we are self hosting. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::Close(DWORD dwSaveOption){
|
|
|
|
HRESULT hr = DestroyScriptEngine();
|
|
|
|
ATLASSERT(SUCCEEDED(hr));
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
// iterate through all the contained objects and call on the Close
|
|
CHostedObject* pObj = (*i);
|
|
|
|
CComPtr<IOleObject> pIOleObject;
|
|
HRESULT hrIOleObj = pObj->GetOleObject(&pIOleObject);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(GetUnknown() == pObj->GetUnknown()){
|
|
|
|
continue; // that is us we close our self later after the contained objects
|
|
}/* end of if statement */
|
|
|
|
pIOleObject->Close(dwSaveOption);
|
|
|
|
//pIOleObject->Release(); // we added a reference, we better clean it up now
|
|
}/* end of for loop */
|
|
|
|
hr = IOleObjectImpl<CMFBar>::Close(dwSaveOption);
|
|
|
|
bool fSelfHosted = m_fSelfHosted; // cache up the variable, since we are going to
|
|
// wipe it out
|
|
|
|
Cleanup(); // delete all the objects
|
|
|
|
if(fSelfHosted){
|
|
|
|
::PostMessage(NULL, WM_QUIT, NULL, NULL); // tell our container to give up
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function Close */
|
|
|
|
/*************************************************************************/
|
|
/* Function: AddFocusObject */
|
|
/* Description: Adds an object to the end of the focus array. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::AddFocusObject(BSTR strObjectID){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
CHostedObject* pObj;
|
|
|
|
hr = FindObject(strObjectID, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
m_cntFocus.insert(m_cntFocus.end(), pObj);
|
|
}
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}/* end of try statement */
|
|
|
|
return (hr);
|
|
}/* end of function AddFocusObject */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ResetFocusArray */
|
|
/* Description: Resets the focus array. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::ResetFocusArray(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
ResetFocusFlags();
|
|
|
|
// cleanup the focus array
|
|
for(CNTOBJ::iterator k = m_cntFocus.begin(); false == m_cntFocus.empty(); ){
|
|
|
|
k = m_cntFocus.erase(k);
|
|
}/* end of for loop */
|
|
}
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}/* end of try statement */
|
|
|
|
return (hr);
|
|
}/* end of function ResetFocusArray */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnSetFocus */
|
|
/* Description: Iterates through the container and sends the focus */
|
|
/* message to the control that thinks it has the focus. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
bHandled = TRUE;
|
|
LONG lRes = 0;
|
|
|
|
if(m_cntObj.empty() == true){
|
|
|
|
return 0;
|
|
}/* end of if statement */
|
|
|
|
MoveFocus(TRUE, lRes);
|
|
|
|
return lRes;
|
|
}/* end of function OnSetFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnUserFocus */
|
|
/* Description: Iterates through the container and sends the focus */
|
|
/* message to the control that thinks it has the focus. In this case */
|
|
/* the control is specified by hwnd and that it is a windowed control. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnUserFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
bHandled = TRUE;
|
|
LONG lRes = 0;
|
|
|
|
HRESULT hr = E_FAIL; // did not find the object
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
HWND hwndCtrl = NULL;
|
|
hr = pObj->GetWindow(&hwndCtrl);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(hwndCtrl == (HWND) wParam){
|
|
|
|
SetClosestFocus(lRes, pObj);
|
|
|
|
//SetObjectFocus(pObj, TRUE, lRes);
|
|
return(lRes);
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return lRes;
|
|
}/* end of function OnUserFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnKillFocus */
|
|
/* Description: Sends the kill focus message to the control that has */
|
|
/* Itterates through the container and removes the focus */
|
|
/* from the contained objects. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){
|
|
|
|
bHandled = TRUE;
|
|
LONG lRes = 0;
|
|
|
|
if(m_cntObj.empty() == true){
|
|
|
|
return 0;
|
|
}/* end of if statement */
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
if(pObj->HasFocus()){
|
|
|
|
HRESULT hr = SetObjectFocus(pObj, FALSE, lRes);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
return lRes;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
//ResetFocusFlags(); // cleanup the focus flags
|
|
|
|
return lRes;
|
|
}/* end of function OnKillFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnMouseMessage */
|
|
/* Description: Handles the mouse messages, distrubutes to proper */
|
|
/* controls if needed. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
|
|
BOOL& bHandled){
|
|
|
|
LONG lRes = 0;
|
|
bHandled = FALSE; // indicated if we dispatched the message
|
|
|
|
if(m_lTimeout > 0){
|
|
|
|
//WM_MOUSEMOVE messages keep comming over even if we really do not move the mouse
|
|
|
|
bool bResetActivity = false;
|
|
if(WM_MOUSEMOVE == uMsg){
|
|
|
|
static WPARAM wParTmp = 0;
|
|
static LPARAM lParTmp = 0;
|
|
|
|
if(wParam != wParTmp || lParam != lParTmp){
|
|
|
|
bResetActivity = true;
|
|
}/* end of if statement */
|
|
|
|
if(wParam & MK_CONTROL ||
|
|
wParam & MK_CONTROL ||
|
|
wParam & MK_LBUTTON ||
|
|
wParam & MK_MBUTTON ||
|
|
wParam & MK_RBUTTON ||
|
|
wParam & MK_SHIFT ){
|
|
|
|
bResetActivity = true;
|
|
}/* end of if statement */
|
|
|
|
lParTmp = lParam;
|
|
wParTmp = wParam;
|
|
}
|
|
else {
|
|
|
|
bResetActivity = true;
|
|
}/* end of if statement */
|
|
|
|
if(bResetActivity){
|
|
|
|
m_fUserActivity = true;
|
|
|
|
if(m_fWaitingForActivity){
|
|
|
|
Fire_ActivityStarted();
|
|
m_fWaitingForActivity = false;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
ATLTRACE2(atlTraceWindowing, 32, TEXT("R WM_ button message : "));
|
|
|
|
if(!m_bMouseDown){
|
|
|
|
CHostedObject* pMouseCaptureObj = NULL;
|
|
|
|
// send the message to the control(s) that have the capture
|
|
if(false == m_fHandleHelp && GetCapture() == S_OK){
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained controls
|
|
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE); // should not be null
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
// need to be able send message to the button with the capture
|
|
if(pObj->HasCapture()){
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Sending WM_ buttons message to button %ls \n"), pObj->GetID());
|
|
HRESULT hr = SendMessageToCtl(pObj, uMsg, wParam, lParam, bHandled, lRes);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
|
|
if (WM_LBUTTONDOWN == uMsg) {
|
|
|
|
CComPtr<IViewObjectEx> pViewObject;
|
|
HRESULT hr = pObj->GetViewObject(&pViewObject);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLASSERT(FALSE); // should have a view
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
DWORD dwHitResult = HITRESULT_OUTSIDE;
|
|
|
|
POINT ptMouse = { LOWORD(lParam), HIWORD(lParam) };
|
|
RECT rcCntrl;
|
|
pObj->GetPos(&rcCntrl);
|
|
|
|
pViewObject->QueryHitPoint(DVASPECT_CONTENT, &rcCntrl, ptMouse, 0, &dwHitResult);
|
|
|
|
if(HITRESULT_HIT == dwHitResult){
|
|
|
|
if (WM_LBUTTONDOWN == uMsg) {
|
|
|
|
LONG lRes;
|
|
//SetObjectFocus(pObj, TRUE, lRes);
|
|
SetClosestFocus(lRes, pObj);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
pMouseCaptureObj = pObj;
|
|
break; // send mouse message to only the one control that has capture
|
|
// then to the ones we hower over
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
}/* end of if statement */
|
|
|
|
// send the message to the control(s) that we are over, but not to the one
|
|
// that which had focus and we already send one
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE); // should not be null
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
// need to be able send message to the button with the capture
|
|
|
|
// send the message to the control over which we are howering or on which we
|
|
// have clicked, check if we already are ready to send the message
|
|
// in that case do not bother with the rect interstec bussines
|
|
if(!bHandled && pObj->IsWindowless() && pObj->IsActive()){
|
|
|
|
CComPtr<IViewObjectEx> pViewObject;
|
|
HRESULT hr = pObj->GetViewObject(&pViewObject);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLASSERT(FALSE); // should have a view
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
DWORD dwHitResult = HITRESULT_OUTSIDE;
|
|
|
|
POINT ptMouse = { LOWORD(lParam), HIWORD(lParam) };
|
|
RECT rcCntrl;
|
|
pObj->GetPos(&rcCntrl);
|
|
|
|
pViewObject->QueryHitPoint(DVASPECT_CONTENT, &rcCntrl, ptMouse, 0, &dwHitResult);
|
|
|
|
if(HITRESULT_HIT == dwHitResult){
|
|
|
|
// see if we are handling help, if so do not do anything else, but
|
|
// fire help with the control ID we are howering over
|
|
if(m_fHandleHelp){
|
|
|
|
if (WM_LBUTTONUP == uMsg) {
|
|
Fire_OnHelp(::SysAllocString(pObj->GetID()));
|
|
m_fHandleHelp = false;
|
|
}/* end of if statement */
|
|
|
|
bHandled = TRUE;
|
|
return(lRes);
|
|
}
|
|
else {
|
|
|
|
if(pMouseCaptureObj == pObj){
|
|
|
|
continue; // we already have send message to this control
|
|
// do not do it again
|
|
}/* end of if statememt */
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Sending WM_ buttons message to button %ls \n"), pObj->GetID());
|
|
SendMessageToCtl(pObj, uMsg, wParam, lParam, bHandled, lRes);
|
|
|
|
if (WM_LBUTTONDOWN == uMsg) {
|
|
|
|
LONG lRes;
|
|
//SetObjectFocus(pObj, TRUE, lRes);
|
|
SetClosestFocus(lRes, pObj);
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
}/* end of if statement */
|
|
|
|
|
|
if(TRUE == bHandled){
|
|
// we send some messages to a control, so there is no need to handle container now
|
|
|
|
return(lRes);
|
|
}/* end of if statement */
|
|
|
|
// we are not over any control so we might be over container itself, so handle
|
|
// the mouse message appropriately
|
|
|
|
ATLTRACE2(atlTraceWindowing, 32, TEXT("Not forwarding the message to the controls\n"));
|
|
if(WM_LBUTTONUP == uMsg || WM_LBUTTONDBLCLK == uMsg){
|
|
|
|
// TODO: Fire the click only if we are on our window or bitmap
|
|
if(m_fHandleHelp){
|
|
BSTR strToolbarName;
|
|
|
|
if(SUCCEEDED(GetToolbarName(&strToolbarName))){
|
|
Fire_OnHelp(strToolbarName);
|
|
}/* end of if statement */
|
|
m_fHandleHelp = false;
|
|
}
|
|
else {
|
|
|
|
if(WM_LBUTTONUP == uMsg){
|
|
|
|
Fire_OnClick();
|
|
}
|
|
else {
|
|
|
|
Fire_OnDblClick();
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
// handle the moving of the container window
|
|
if(m_fSelfHosted && !m_fHandleHelp){
|
|
|
|
if(WM_LBUTTONDOWN == uMsg){
|
|
OnButtonDown(uMsg, wParam, lParam, bHandled);
|
|
}/* end of if statement */
|
|
|
|
if(WM_MOUSEMOVE == uMsg){
|
|
OnMouseMove(uMsg, wParam, lParam, bHandled);
|
|
}/* end of if statement */
|
|
|
|
if(WM_LBUTTONUP == uMsg){
|
|
OnButtonUp(uMsg, wParam, lParam, bHandled);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return(lRes);
|
|
}/* end of function OnMouseMessage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnKeyMessage */
|
|
/* Description: Distrubutes the keyboard messages properly. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnKeyMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
|
|
BOOL& bHandled){
|
|
|
|
m_fUserActivity = true;
|
|
|
|
if(m_fWaitingForActivity){
|
|
|
|
Fire_ActivityStarted();
|
|
m_fWaitingForActivity = false;
|
|
}/* end of if statement */
|
|
|
|
bHandled = FALSE;
|
|
LONG lRes = 0;
|
|
VARIANT_BOOL fEat = VARIANT_FALSE;
|
|
|
|
LONG lEnable = 1; // using long since the framework will not handle short
|
|
|
|
LONG lVirtKey = (LONG)wParam;
|
|
LONG lKeyData = (LONG) lParam;
|
|
|
|
m_fForceKey = false; // reset the flag, the change in the value would indicate
|
|
// that we have received call to force key during the event
|
|
// processing
|
|
|
|
if(WM_KEYDOWN == uMsg){
|
|
|
|
Fire_OnKeyUp(lVirtKey, lKeyData);
|
|
}/* end of if statement */
|
|
|
|
if(WM_KEYUP == uMsg){
|
|
|
|
Fire_OnKeyDown(lVirtKey, lKeyData);
|
|
}/* end of if statement */
|
|
|
|
if(WM_SYSKEYDOWN == uMsg){
|
|
|
|
Fire_OnSysKeyUp(lVirtKey, lKeyData);
|
|
}/* end of if statement */
|
|
|
|
if(WM_SYSKEYUP == uMsg){
|
|
|
|
Fire_OnSysKeyDown(lVirtKey, lKeyData);
|
|
}/* end of if statement */
|
|
|
|
if(m_fForceKey){
|
|
|
|
fEat = m_fEat;
|
|
lVirtKey = m_lVirtKey;
|
|
lKeyData = m_lKeyData;
|
|
}/* end of if statement */
|
|
|
|
if(VARIANT_FALSE == fEat){
|
|
|
|
if(WM_KEYUP == uMsg ){
|
|
switch(lVirtKey){
|
|
|
|
case VK_TAB:
|
|
bool fForward = true;
|
|
|
|
if(::GetKeyState(VK_SHIFT) < 0){
|
|
|
|
fForward = false;
|
|
}/* end of if statement */
|
|
|
|
MoveFocus(fForward, lRes);
|
|
return(lRes);
|
|
}/* end of switch statement */
|
|
}/* end of if statement */
|
|
|
|
// iterates through the controls and send these key messages to the one
|
|
// with focus
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj->HasFocus()){
|
|
|
|
HRESULT hr = SendMessageToCtl(pObj, uMsg, lVirtKey, lKeyData, bHandled, lRes, false);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
return(lRes);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
}/* end of if statement */
|
|
|
|
return(lRes);
|
|
}/* end of function OnKeyMessage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: AdvanceIterator */
|
|
/* Description: Helper inline function that helps to keep track which */
|
|
/* direction we are advancing. */
|
|
/*************************************************************************/
|
|
void AdvanceIterator(CNTOBJ::iterator& i, bool fForward){
|
|
|
|
if(fForward){
|
|
|
|
i++;
|
|
}
|
|
else {
|
|
|
|
i--;
|
|
}/* end of if statement */
|
|
}/* end of function AdvanceIterator */
|
|
|
|
/*************************************************************************/
|
|
/* Function: MoveFocus */
|
|
/* Descrition: Moves focus through the objects in forward or reverse */
|
|
/* direction. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::MoveFocus(bool fForward, LONG& lRes){
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// first remove the focus and remeber the object
|
|
CHostedObject* pLastFocusObject = NULL;
|
|
|
|
CNTOBJ::iterator i, iEnd;
|
|
|
|
if(fForward){
|
|
|
|
i = m_cntFocus.begin();
|
|
iEnd = m_cntFocus.end();
|
|
}
|
|
else {
|
|
i = m_cntFocus.end();
|
|
i--;
|
|
iEnd = m_cntFocus.begin();
|
|
}/* end of if statement */
|
|
|
|
for( ;i!= iEnd; AdvanceIterator(i, fForward)){
|
|
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj->HasFocus()){
|
|
|
|
LONG lRes;
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
pLastFocusObject = pObj;
|
|
continue; // get to the next object
|
|
}/* end of if statement */
|
|
|
|
// try to set the focus to the next object
|
|
if(NULL != pLastFocusObject){
|
|
|
|
if(pObj->IsActive()){
|
|
|
|
LONG lRes = 0;
|
|
HRESULT hr = SetObjectFocus(pObj, TRUE, lRes);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue; // this is the container so skip it
|
|
}/* end of if statement */
|
|
|
|
if(-1 == lRes){
|
|
// did not want to handle focus, since the button is disabled
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
// OK lets try to set focus to somebody before
|
|
//CNTOBJ::iterator i;
|
|
if(fForward){
|
|
|
|
i = m_cntFocus.begin();
|
|
iEnd = m_cntFocus.end();
|
|
}
|
|
else {
|
|
i = m_cntFocus.end();
|
|
i--;
|
|
iEnd = m_cntFocus.begin();
|
|
}/* end of if statement */
|
|
|
|
for( ;i!= iEnd; AdvanceIterator(i, fForward)){
|
|
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj->IsActive()){
|
|
|
|
LONG lRes = 0;
|
|
HRESULT hr = SetObjectFocus(pObj, TRUE, lRes);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue; // this is the container so skip it
|
|
}/* end of if statement */
|
|
|
|
if(-1 == lRes){
|
|
// did not want to handle focus, since the button is disabled
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
//ATLASSERT(FALSE); // should not really hapen, to have all the objects disabled
|
|
return(hr);
|
|
}/* end of function MoveFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetClosestFocus */
|
|
/* Descrition: Sets the focus to the closes object to pObj if specified. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::SetClosestFocus(LONG& lRes, CHostedObject* pStartObj, bool fForward){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_cntFocus.empty()){
|
|
|
|
hr = S_FALSE;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
ResetFocusFlags();
|
|
|
|
// first remove the focus and remeber the object
|
|
bool fStartSettingFocus = false;
|
|
|
|
CNTOBJ::iterator i, iEnd;
|
|
|
|
if(fForward){
|
|
|
|
i = m_cntFocus.begin();
|
|
iEnd = m_cntFocus.end();
|
|
}
|
|
else {
|
|
i = m_cntFocus.end();
|
|
i--;
|
|
iEnd = m_cntFocus.begin();
|
|
}/* end of if statement */
|
|
|
|
if(NULL == pStartObj){
|
|
|
|
pStartObj = (*i); // initialize our start object
|
|
}/* end of if statement */
|
|
|
|
for( ;i!= iEnd; AdvanceIterator(i, fForward)){
|
|
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj == pStartObj){
|
|
|
|
fStartSettingFocus = true;
|
|
}/* end of if statement */
|
|
|
|
// try to set the focus to the next object
|
|
if(fStartSettingFocus ){
|
|
|
|
if(pObj->IsActive()){
|
|
|
|
LONG lRes = 0;
|
|
HRESULT hr = SetObjectFocus(pObj, TRUE, lRes);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue; // this is the container so skip it
|
|
}/* end of if statement */
|
|
|
|
if(-1 == lRes){
|
|
// did not want to handle focus, since the button is disabled
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
if(!fStartSettingFocus){
|
|
|
|
hr = S_FALSE;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// OK lets try to set focus to somebody before
|
|
//CNTOBJ::iterator i;
|
|
if(fForward){
|
|
|
|
i = m_cntFocus.begin();
|
|
iEnd = m_cntFocus.end();
|
|
}
|
|
else {
|
|
i = m_cntFocus.end();
|
|
i--;
|
|
iEnd = m_cntFocus.begin();
|
|
}/* end of if statement */
|
|
|
|
for( ;i!= iEnd; AdvanceIterator(i, fForward)){
|
|
|
|
// iterate through all the contained controls
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
ATLASSERT(FALSE);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(pObj->IsActive()){
|
|
|
|
LONG lRes = 0;
|
|
HRESULT hr = SetObjectFocus(pObj, TRUE, lRes);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
continue; // this is the container so skip it
|
|
}/* end of if statement */
|
|
|
|
if(-1 == lRes){
|
|
// did not want to handle focus, since the button is disabled
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
ATLASSERT(FALSE); // should not really hapen, to have all the objects disabled
|
|
return(hr);
|
|
|
|
}/* end of function SetClosestFocus */
|
|
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnForwardMsg */
|
|
/* Description: Forwards the message to the active object. */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/){
|
|
|
|
ATLTRACE2(atlTraceHosting, 2, TEXT("CMFBar::OnForwardMsg\n"));
|
|
|
|
ATLASSERT(lParam != 0);
|
|
LPMSG lpMsg = (LPMSG)lParam;
|
|
|
|
if(m_spActiveObject){
|
|
|
|
if(m_spActiveObject->TranslateAccelerator(lpMsg) == S_OK)
|
|
return 1;
|
|
}/* end of function OnForwardMessage */
|
|
return 0;
|
|
}/* end of function OnForwardMessage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ReflectNotifications */
|
|
/* Description: Reflects the messages to the child windows */
|
|
/*************************************************************************/
|
|
LRESULT CMFBar::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam,
|
|
BOOL& bHandled){
|
|
HWND hWndChild = NULL;
|
|
|
|
switch(uMsg){
|
|
|
|
case WM_COMMAND:
|
|
if(lParam != NULL) // not from a menu
|
|
hWndChild = (HWND)lParam;
|
|
break;
|
|
case WM_NOTIFY:
|
|
hWndChild = ((LPNMHDR)lParam)->hwndFrom;
|
|
break;
|
|
case WM_PARENTNOTIFY:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case WM_CREATE:
|
|
case WM_DESTROY:
|
|
hWndChild = (HWND)lParam;
|
|
break;
|
|
default:
|
|
hWndChild = GetDlgItem(HIWORD(wParam));
|
|
break;
|
|
}
|
|
break;
|
|
case WM_DRAWITEM:
|
|
if(wParam) // not from a menu
|
|
hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
|
|
break;
|
|
case WM_MEASUREITEM:
|
|
if(wParam) // not from a menu
|
|
hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
|
|
break;
|
|
case WM_COMPAREITEM:
|
|
if(wParam) // not from a menu
|
|
hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
|
|
break;
|
|
case WM_DELETEITEM:
|
|
if(wParam) // not from a menu
|
|
hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
|
|
break;
|
|
case WM_VKEYTOITEM:
|
|
case WM_CHARTOITEM:
|
|
case WM_HSCROLL:
|
|
case WM_VSCROLL:
|
|
hWndChild = (HWND)lParam;
|
|
break;
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORLISTBOX:
|
|
case WM_CTLCOLORMSGBOX:
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
case WM_CTLCOLORSTATIC:
|
|
hWndChild = (HWND)lParam;
|
|
break;
|
|
default:
|
|
break;
|
|
}/* end of switch statement */
|
|
|
|
if(hWndChild == NULL){
|
|
|
|
bHandled = FALSE;
|
|
return 1;
|
|
}/* end of if statememnt */
|
|
|
|
ATLASSERT(::IsWindow(hWndChild));
|
|
return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
|
|
}/* end of function ReflectNotifications */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_Caption */
|
|
/* Description: Sets the caption to the window if present and handles */
|
|
/* the ambient property implementation. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_Caption(BSTR bstrCaption){
|
|
|
|
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Caption\n"));
|
|
|
|
if (FireOnRequestEdit(DISPID_CAPTION) == S_FALSE){
|
|
|
|
return S_FALSE;
|
|
}/* end of if statement */
|
|
|
|
m_bstrCaption.Empty();
|
|
m_bstrCaption.Attach(::SysAllocString(bstrCaption));
|
|
m_bRequiresSave = TRUE;
|
|
FireOnChanged(DISPID_CAPTION);
|
|
FireViewChange();
|
|
SendOnDataChange(NULL);
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
#ifdef _UNICODE
|
|
::SetWindowText(m_hWnd, bstrCaption);
|
|
#else
|
|
USES_CONVERSION;
|
|
::SetWindowText(m_hWnd, OLE2T(bstrCaption));
|
|
#endif
|
|
}/* end of if statement */
|
|
|
|
return S_OK;
|
|
}/* end of function put_Caption */
|
|
|
|
|
|
// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
|
|
/*************************************************************************/
|
|
/* IActiveScriptSite Interface Implementation */
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_CmdLine */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_CmdLine(BSTR *pVal){
|
|
|
|
if(NULL == pVal){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pVal = m_strCmdLine.Copy();
|
|
return S_OK;
|
|
}/* end of function get_CmdLine */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_CmdLine */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_CmdLine(BSTR newVal){
|
|
|
|
m_strCmdLine = newVal;
|
|
return S_OK;
|
|
}/* end of function put_CmdLine */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetUserLCID */
|
|
/* Description: Gets the user default LCID */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetUserLCID(long *plcid){
|
|
|
|
*plcid = ::GetUserDefaultLCID();
|
|
return (S_OK);
|
|
}/* end of function GetUserLCID */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetLCID */
|
|
/* Description: Gets the user default LCID */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetLCID(LCID *plcid){
|
|
|
|
*plcid = ::GetUserDefaultLCID();
|
|
return (S_OK);
|
|
}/* end of function GetLCID */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetItemInfo */
|
|
/* Description: Returns IUnknown or TypeInfo of the contained (embedded) */
|
|
/* objects in the active script, in this case we return also a container,*/
|
|
/* since we can script it as well (but the script container is inserted */
|
|
/* in the list as well, so no special case for it. */
|
|
/* TODO: Might want to optimize and use hash table for faster compares. */
|
|
/* on the other hand it seems like a script engine calls this just once */
|
|
/* for an object an then reuses its internal reference. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetItemInfo(LPCOLESTR strObjectID, DWORD dwReturnMask,
|
|
IUnknown** ppunkItemOut, ITypeInfo** pptinfoOut){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (dwReturnMask & SCRIPTINFO_ITYPEINFO){
|
|
|
|
if (!pptinfoOut){
|
|
|
|
return E_INVALIDARG;
|
|
}/* end of if statement */
|
|
|
|
*pptinfoOut = NULL;
|
|
}/* end of if statement */
|
|
|
|
if (dwReturnMask & SCRIPTINFO_IUNKNOWN){
|
|
|
|
if (!ppunkItemOut){
|
|
return E_INVALIDARG;
|
|
}/* end of if statement */
|
|
|
|
*ppunkItemOut = NULL;
|
|
}/* end of if statement */
|
|
|
|
CHostedObject* pObj;
|
|
|
|
if(SUCCEEDED(FindObject(const_cast<BSTR>(strObjectID), &pObj))){
|
|
|
|
if (dwReturnMask & SCRIPTINFO_ITYPEINFO){
|
|
|
|
hr = pObj->GetTypeInfo(0, ::GetUserDefaultLCID(), pptinfoOut);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
if (dwReturnMask & SCRIPTINFO_IUNKNOWN){
|
|
|
|
*ppunkItemOut = pObj->GetUnknown(); // does AddRef under the hood
|
|
}/* end of if statement */
|
|
|
|
return(hr); // found out item no need to dig around longer
|
|
}/* end of for loop */
|
|
|
|
return TYPE_E_ELEMENTNOTFOUND;
|
|
}/* end of function GetItemInfo */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetDocVersionString */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetDocVersionString(BSTR *pbstrVersion ){
|
|
|
|
return (E_NOTIMPL);
|
|
}/* end of function GetDocVersionString */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnScriptTerminate */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::OnScriptTerminate(const VARIANT *pvarResult,
|
|
const EXCEPINFO *pexcepinfo){
|
|
|
|
return (E_NOTIMPL);
|
|
}/* end of function OnScriptTerminate */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnStateChange */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::OnStateChange(SCRIPTSTATE ssScriptState){
|
|
|
|
return (E_NOTIMPL);
|
|
}/* end of function OnStateChange */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnScriptError */
|
|
/* Description: Display the script error in debug mode, skip it in */
|
|
/* release mode for now. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::OnScriptError(IActiveScriptError *pse){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifdef _DEBUG
|
|
WCHAR szError[1024];
|
|
EXCEPINFO ei;
|
|
DWORD dwSrcContext;
|
|
ULONG ulLine;
|
|
LONG ichError;
|
|
BSTR bstrLine = NULL;
|
|
|
|
|
|
hr = pse->GetExceptionInfo(&ei);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = pse->GetSourcePosition(&dwSrcContext, &ulLine, &ichError);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = pse->GetSourceLineText(&bstrLine);
|
|
|
|
if (hr){
|
|
|
|
hr = S_OK; // Ignore this error, there may not be source available
|
|
}/* end of if statement */
|
|
|
|
if (!hr){
|
|
|
|
wsprintfW(szError, L"Source:'%s'\n Line:%d Description:%s\n",
|
|
ei.bstrSource, ulLine, ei.bstrDescription);
|
|
#ifdef _DEBUG
|
|
USES_CONVERSION;
|
|
ATLTRACE(W2T(szError));
|
|
::MessageBeep((UINT)-1);
|
|
::MessageBoxW(::GetFocus(), szError, L"Error", MB_OK);
|
|
#endif
|
|
// TODO: Add real error handling for released version
|
|
}/* end of if statment */
|
|
|
|
if (bstrLine){
|
|
|
|
::SysFreeString(bstrLine);
|
|
}/* end of if statement */
|
|
|
|
#endif
|
|
return hr;
|
|
}/* end of function OnScriptError */
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
STDMETHODIMP CMFBar::OnEnterScript
|
|
(
|
|
void
|
|
)
|
|
{
|
|
// No need to do anything
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
STDMETHODIMP CMFBar::OnLeaveScript
|
|
(
|
|
void
|
|
)
|
|
{
|
|
// No need to do anything
|
|
return S_OK;
|
|
}
|
|
|
|
// ##### END ACTIVEX SCRIPTING SUPPORT #####
|
|
|
|
/*************************************************************************/
|
|
/* Function: About */
|
|
/* Description: Displayes about box. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::About(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
const INT ciMaxBuffSize = MAX_PATH; // enough for the text
|
|
TCHAR strBuffer[ciMaxBuffSize];
|
|
TCHAR strBufferAbout[ciMaxBuffSize];
|
|
|
|
if(!::LoadString(m_hRes, IDS_BAR_ABOUT, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(!::LoadString(m_hRes, IDS_ABOUT, strBufferAbout, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
::MessageBox(::GetFocus(), strBuffer, strBufferAbout, MB_OK);
|
|
|
|
return (hr);
|
|
}/* end of function About */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetObjectUnknown */
|
|
/* Description: Iterates throught the object collection, finds the */
|
|
/* object that has the specific ID then returns it IUnknown. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetObjectUnknown(BSTR strObjectID, IUnknown **ppUnk){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
return E_POINTER;
|
|
}/* end of if statement */
|
|
|
|
if(NULL == ppUnk){
|
|
|
|
return E_POINTER;
|
|
}/* end of if statement */
|
|
|
|
*ppUnk = NULL;
|
|
|
|
CHostedObject* pObj;
|
|
|
|
hr = FindObject(strObjectID, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
*ppUnk = pObj->GetUnknown();
|
|
hr = S_OK;
|
|
|
|
if(*ppUnk == NULL){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
(*ppUnk)->AddRef(); // adds the reference, since we are giving out
|
|
|
|
return (hr);
|
|
}/* end of function GetObjectUnknown */
|
|
|
|
/*************************************************************************/
|
|
/* Function: EnableObject */
|
|
/* Description: Goes trough the objects and enables or disables it */
|
|
/* depending on the flag. Invalidates the objects rect as well. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::EnableObject(BSTR strObjectID, VARIANT_BOOL fEnable){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
return E_POINTER;
|
|
}/* end of if sattement */
|
|
|
|
CHostedObject* pObj;
|
|
hr = FindObject(strObjectID, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
bool fTmpEnable = VARIANT_FALSE == fEnable ? false: true;
|
|
|
|
CContainerObject* pCnt;
|
|
hr = pObj->GetContainerObject(&pCnt);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
if(pObj->GetUnknown() == GetUnknown()){
|
|
// special case when we are invalidating our self/ the self hosted container
|
|
if(fTmpEnable){
|
|
|
|
InvalidateRect(NULL, false);
|
|
}/* end of if statement */
|
|
pObj->SetActive(fTmpEnable);
|
|
hr = S_OK;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of if statemenet */
|
|
|
|
if (pObj->IsActive() == fTmpEnable)
|
|
return S_OK;
|
|
|
|
pObj->SetActive(fTmpEnable);
|
|
|
|
if(false == fTmpEnable){
|
|
|
|
LONG lRes = 0;
|
|
SetClosestFocus(lRes);
|
|
//MoveFocus(true, lRes);
|
|
//SetObjectFocus(pObj, FALSE, lRes);
|
|
|
|
if(pObj->HasCapture()){
|
|
|
|
pCnt->SetCapture(FALSE);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
// invalidate area where the object lives
|
|
if(pObj->IsWindowless()){
|
|
|
|
// invalidate the rect only if we are windowless control
|
|
// the windowed control shopuld be able
|
|
// to update itself depending on the SW_SHOW, HIDE messagess
|
|
hr = pCnt->InvalidateObjectRect();
|
|
}/* end of if statement */
|
|
|
|
return (hr);
|
|
}/* end of function EnableObject */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ObjectEnabled */
|
|
/* Description: Goes trough the objects and checks if the particular */
|
|
/* object is enabled or disabled. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::ObjectEnabled(BSTR strObjectID, VARIANT_BOOL *pfEnabled){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == pfEnabled){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if sattement */
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
if(!_wcsicmp((*i)->GetID(), strObjectID)){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
*pfEnabled = pObj->IsActive()? VARIANT_TRUE : VARIANT_FALSE;
|
|
hr = S_OK; // might have to turn it on
|
|
return(hr); // already have set the state and invalidated and bail out
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return (hr);
|
|
}/* end of function ObjectEnabled */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ForceKey */
|
|
/* Description: Forces the in the eventa handling code. */
|
|
/* The fEat disables or enables default key handler. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::ForceKey(LONG lVirtKey, LONG lKeyData, VARIANT_BOOL fEat){
|
|
|
|
m_fForceKey = true; // set the flag for key handler routine
|
|
|
|
m_fEat = (fEat == VARIANT_FALSE ? VARIANT_FALSE : VARIANT_TRUE); // disable or enable this call
|
|
m_lVirtKey = lVirtKey; // put in data
|
|
m_lKeyData = lKeyData; // put in data
|
|
|
|
return S_OK;
|
|
}/* end of function ForceKey */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_ScriptLanguage */
|
|
/* Description: Gets current script language such as JScript, VBScript */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_ScriptLanguage(BSTR *pstrScriptLanguage){
|
|
|
|
if(NULL == pstrScriptLanguage){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pstrScriptLanguage = m_strScriptLanguage.Copy();
|
|
return S_OK;
|
|
}/* end of function get_ScriptLanguage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_ScriptLanguage */
|
|
/* Description: Gets current script language such as JScript, VBScript */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_ScriptLanguage(BSTR strScriptLanguage){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_ps){
|
|
|
|
hr = E_FAIL; // Already created the script engine, so it
|
|
// will not take an effect untill we unload it
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
m_strScriptLanguage = strScriptLanguage;
|
|
|
|
return (hr);
|
|
}/* end of function put_ScriptLanguage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_ScriptFile */
|
|
/* Description: Gets the current script file. */
|
|
/* By default we have empty string which means loading from Windows */
|
|
/* resources, which is not really a file. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_ScriptFile(BSTR *pstrScriptFile){
|
|
|
|
if(NULL == pstrScriptFile){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pstrScriptFile = m_strScriptFile.Copy();
|
|
return S_OK;
|
|
}/* end of function get_ScriptFile */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_ScriptFile */
|
|
/* Description: Sets the script file. Only valid before the load and */
|
|
/* unload. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_ScriptFile(BSTR strScriptFile){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
if(VARIANT_TRUE == m_fAutoLoad){
|
|
|
|
hr = DestroyScriptEngine();
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
m_strScriptFile = strScriptFile;
|
|
|
|
hr = Load();
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
const INT ciMaxBuffSize = MAX_PATH; // enough for the text
|
|
TCHAR strBuffer[ciMaxBuffSize];
|
|
|
|
if(!::LoadString(m_hRes, IDS_MAIN_ENTRY, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
USES_CONVERSION;
|
|
hr = Run(T2OLE(strBuffer));
|
|
|
|
}
|
|
else {
|
|
|
|
// case when we are loading manually
|
|
|
|
|
|
if (m_ps){
|
|
|
|
hr = E_FAIL; // Already created the script engine, so it
|
|
// will not take an effect untill we unload it
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
m_strScriptFile = strScriptFile;
|
|
}/* end of if statement */
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function put_ScriptFile */
|
|
|
|
/*************************************************************************/
|
|
/* IActiveScriptSiteWindow Interface Implementation */
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetWindow */
|
|
/* Description: Gets the window. If we are windowless we do not pass */
|
|
/* down the parent window, since that seems to confuse the control */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetWindow(HWND *phwndOut){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!phwndOut){
|
|
|
|
hr = E_INVALIDARG;
|
|
return (hr);
|
|
}/* end of if statement */
|
|
|
|
|
|
if(m_bWndLess){
|
|
if(!::IsWindow(m_hWnd)){
|
|
|
|
return(GetParentHWND(phwndOut));
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
if(!::IsWindow(m_hWnd)){
|
|
|
|
*phwndOut = NULL;
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
*phwndOut = m_hWnd;
|
|
|
|
return(hr);
|
|
}/* end of function GetWindow */
|
|
|
|
/*************************************************************************/
|
|
/* Function: EnableModeless */
|
|
/* Description: Sets the window from which the UI elemnt can come out */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::EnableModeless(BOOL fModeless){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_hWnd == NULL){
|
|
|
|
hr = E_NOTIMPL;
|
|
return (hr);
|
|
}/* end of if statement */
|
|
|
|
::EnableWindow(m_hWnd, fModeless);
|
|
return(hr);
|
|
}/* end of function EnableModeless */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_MinWidth */
|
|
/* Description: Gets the minimum width beyond which we do not resize. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_MinWidth(long *pVal){
|
|
|
|
if(NULL == pVal){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pVal = m_lMinWidth;
|
|
return S_OK;
|
|
}/* end of function get_MinWidth */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_MinWidth */
|
|
/* Description: Puts the minimum width beyond which we do not resize. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_MinWidth(long newVal){
|
|
|
|
m_lMinWidth = newVal;
|
|
return S_OK;
|
|
}/* end of function put_MinWidth */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_MinWidth */
|
|
/* Description: Gets the minimum height beyond which we do not resize. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_MinHeight(long *pVal){
|
|
|
|
if(NULL == pVal){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pVal = m_lMinHeight;
|
|
return S_OK;
|
|
}/* end of function get_MinHeight */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_MinHeight */
|
|
/* Description: Sets the minimum height beyond which we do not resize. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_MinHeight(long newVal){
|
|
|
|
m_lMinHeight = newVal;
|
|
return S_OK;
|
|
}/* end of function put_MinHeight */
|
|
|
|
// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
|
|
|
|
/*************************************************************************/
|
|
/* Function: CreateScriptEngine */
|
|
/* Description: Initializes the script engine. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::CreateScriptEngine(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifndef _UNICODE
|
|
USES_CONVERSION;
|
|
#endif
|
|
|
|
if (m_ps){
|
|
|
|
hr = S_FALSE; // Already created the script engine
|
|
return(hr); // so get out
|
|
}/* end of if statement */
|
|
|
|
/*************************************************************************/
|
|
/* add (this) the container as a scriptable object as well */
|
|
/* this is special case so we can call script on our self as well */
|
|
/*************************************************************************/
|
|
const INT ciMaxBuffSize = MAX_PATH; // should be enough for tlbr ID, keep ID small if can
|
|
TCHAR strBuffer[ciMaxBuffSize];
|
|
|
|
if(!::LoadString(m_hRes, IDS_ROOT_OBJECT, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CComPtr<IUnknown> pUnk = GetUnknown();
|
|
CComQIPtr<IDispatch> pDisp (pUnk);
|
|
|
|
if(!pDisp){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
#ifdef _UNICODE
|
|
BSTR strObjectID = ::SysAllocString(strBuffer); // gets freed in the destructor of the holding object
|
|
#else
|
|
BSTR strObjectID = ::SysAllocString(T2OLE(strBuffer));
|
|
#endif
|
|
|
|
hr = AddObject(strObjectID, pDisp); // this one adds the object to the list as well
|
|
|
|
::SysFreeString(strObjectID); // free up the sys string, since we allocate it in the contructor for the object
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(!m_strScriptLanguage){
|
|
// load what script language we decided to support if not set explicitly by user
|
|
if(!::LoadString(m_hRes, IDS_SCRIPT_LANGUAGE, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
m_strScriptLanguage = strBuffer;
|
|
}/* end of if statement */
|
|
|
|
CLSID clsid;
|
|
|
|
hr = ::CLSIDFromProgID(m_strScriptLanguage, &clsid); // get the language
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return hr;
|
|
}/* end of if statement */
|
|
|
|
hr = m_ps.CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER);
|
|
// Create the ActiveX Scripting Engine
|
|
//hr = ::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void **)&m_ps);
|
|
if (FAILED(hr)){
|
|
|
|
//s_pszError = "Creating the ActiveX Scripting engine failed. Scripting engine is probably not correctly registered or CLSID incorrect.";
|
|
return (hr);
|
|
}/* end of if statement */
|
|
|
|
// Script Engine must support IActiveScriptParse for us to use it
|
|
hr = m_ps->QueryInterface(IID_IActiveScriptParse, (void**) &m_psp);
|
|
|
|
if (FAILED(hr)){
|
|
|
|
//s_pszError = "ActiveX Scripting engine does not support IActiveScriptParse";
|
|
return (hr);
|
|
}/* end of if statement */
|
|
|
|
hr = m_ps->SetScriptSite(this);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return hr;
|
|
}/* end of if statement */
|
|
|
|
// InitNew the object:
|
|
hr = m_psp->InitNew();
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return hr;
|
|
}/* end of if statement */
|
|
|
|
// Adding dynamically added items so they can be recognized by name
|
|
// and scripted via script language such as VBScript or JScript
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
// iterate throw the array and see if we find matching ID
|
|
CHostedObject* pObj = (*i);
|
|
|
|
hr = m_ps->AddNamedItem((pObj)->GetID(), SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr); // might want to modify this later to not exit if we get one bad object
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
// Special case adding the root object
|
|
if(!::LoadString(m_hRes, IDS_ROOT_OBJECT, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
#ifdef _UNICODE
|
|
hr = m_ps->AddNamedItem(strBuffer, SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
|
|
#else
|
|
hr = m_ps->AddNamedItem(A2W(strBuffer), SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
|
|
#endif
|
|
|
|
// Add up the events that we have saved in the event array
|
|
for(CNTEVNT::iterator j = m_cntEvnt.begin(); j!= m_cntEvnt.end(); j++){
|
|
|
|
EXCEPINFO ei;
|
|
::ZeroMemory(&ei, sizeof(EXCEPINFO));
|
|
|
|
BSTR strName;
|
|
CEventObject* pObj = (*j);
|
|
|
|
hr = m_psp->AddScriptlet(NULL, pObj->m_strEventCode, pObj->m_strObjectID, NULL, pObj->m_strEvent, NULL, 0, 0, 0, &strName, &ei);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLTRACE(TEXT("Failed to add an event, might be using a different language or the object does not exists. \n"));
|
|
ATLASSERT(FALSE);
|
|
return(hr);
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return (hr);
|
|
}/* end of function CreateScriptEngine */
|
|
|
|
/*************************************************************************/
|
|
/* Function: DestroyScriptEngine */
|
|
/* Description: Destroys the engine. Might be usefull when using one */
|
|
/* script to initialize the objects and the other script to run the */
|
|
/* objects. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::DestroyScriptEngine(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Release the language engine, since it may hold on to us
|
|
if (m_psp){
|
|
|
|
m_psp.Release();
|
|
}/* end of if statement */
|
|
|
|
if (m_ps){
|
|
|
|
//HRESULT hrTmp = m_ps->InterruptScriptThread(SCRIPTTHREADID_CURRENT, NULL, SCRIPTINTERRUPT_DEBUG);
|
|
//ATLASSERT(SUCCEEDED(hrTmp));
|
|
|
|
hr = m_ps->Close();
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
m_ps.Release();
|
|
}/* end of if statement */
|
|
|
|
return (hr);
|
|
}/* end of function DestroyScriptEngine */
|
|
|
|
/*************************************************************************/
|
|
/* Function: Load */
|
|
/* Description: Loads the script. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::Load(){
|
|
|
|
#ifndef _UNICODE_SCRIPT_FILE
|
|
USES_CONVERSION;
|
|
#endif
|
|
|
|
HRESULT hr = CreateScriptEngine();
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLTRACE(TEXT("Failed to create a script engine.\n"));
|
|
ATLASSERT(FALSE);
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// see if we can find this resource DLL in the script
|
|
// TCHAR* strType = TEXT("SCRIPT");
|
|
HRSRC hrscScript = ::FindResource(m_hRes, OLE2T(m_strScriptFile), MAKEINTRESOURCE(23));
|
|
|
|
if(NULL != hrscScript){
|
|
|
|
/**********************************************************************/
|
|
/* load up the script from a resource */
|
|
/**********************************************************************/
|
|
|
|
if(NULL == hrscScript){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
HGLOBAL hScript = ::LoadResource(m_hRes, hrscScript);
|
|
|
|
if(NULL == hScript){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
DWORD dwSize = SizeofResource((HMODULE)m_hRes, hrscScript);
|
|
|
|
if(dwSize == 0){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
/*****************************************************************/
|
|
/* change this depending if the file was saved as Unicode or not */
|
|
/*****************************************************************/
|
|
#ifndef _UNICODE_SCRIPT_FILE
|
|
WCHAR* strCode = A2W((CHAR*)hScript);
|
|
#else
|
|
WCHAR* strCode = (WCHAR*)hScript;
|
|
#endif
|
|
|
|
const INT ciMaxBuffSize = MAX_PATH;
|
|
TCHAR strEOFMarker[ciMaxBuffSize]; // the end of file marker
|
|
|
|
// Load up the end of file delimiter
|
|
if(!::LoadString(m_hRes, IDS_END_FILE, strEOFMarker, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
EXCEPINFO ei;
|
|
::ZeroMemory(&ei, sizeof(EXCEPINFO));
|
|
|
|
#ifdef _UNICODE
|
|
hr = m_psp->ParseScriptText(strCode, NULL, NULL, strEOFMarker, 0, 0, SCRIPTTEXT_ISEXPRESSION|SCRIPTTEXT_ISVISIBLE, NULL, &ei);
|
|
#else
|
|
hr = m_psp->ParseScriptText(strCode, NULL, NULL, A2W(strEOFMarker), 0, 0, SCRIPTTEXT_ISEXPRESSION|SCRIPTTEXT_ISVISIBLE, NULL, &ei);
|
|
#endif
|
|
}
|
|
else {
|
|
/**********************************************************************/
|
|
/* load up the script from a file */
|
|
/**********************************************************************/
|
|
// Create File m_strScriptFile
|
|
HANDLE hFile = ::CreateFile(
|
|
OLE2T(m_strScriptFile), // pointer to name of the file
|
|
GENERIC_READ, // access (read-write) mode
|
|
FILE_SHARE_READ, // share mode
|
|
NULL, // pointer to security descriptor
|
|
OPEN_EXISTING, // how to create
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes
|
|
NULL // handle to file with attributes to copy
|
|
);
|
|
|
|
if(hFile == INVALID_HANDLE_VALUE){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
#if _DEBUG
|
|
|
|
TCHAR strBuffer[MAX_PATH + 25];
|
|
wsprintf(strBuffer, TEXT("Failed to open script file %s"), OLE2T(m_strScriptFile));
|
|
::MessageBox(::GetFocus(), strBuffer, TEXT("Error"), MB_OK);
|
|
#endif
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
DWORD dwBitsSize = GetFileSize(hFile,NULL);
|
|
|
|
if(0 == dwBitsSize){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr); // the file size should be definetly more then 0
|
|
}/* end of if statement */
|
|
|
|
BYTE* pbBuffer = new BYTE[dwBitsSize + sizeof(WCHAR)];
|
|
::ZeroMemory(pbBuffer, dwBitsSize + sizeof(WCHAR));
|
|
|
|
// load it up convert the text to UNICODE
|
|
DWORD dwBytesRead = 0;
|
|
|
|
if(!ReadFile(hFile, pbBuffer, dwBitsSize, &dwBytesRead, NULL)){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
delete[] pbBuffer;
|
|
::CloseHandle(hFile); // close the file
|
|
return (hr);
|
|
}/* end of function ReadFile */
|
|
|
|
if(dwBitsSize != dwBytesRead){
|
|
|
|
ATLTRACE(TEXT("Implement reading loop"));
|
|
delete[] pbBuffer; // free up the temp buffer
|
|
::CloseHandle(hFile); // close the file
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
/*****************************************************************/
|
|
/* change this depending if the file was saved as Unicode or not */
|
|
/*****************************************************************/
|
|
#ifndef _UNICODE_SCRIPT_FILE
|
|
WCHAR* strCode = A2W((CHAR*)pbBuffer);
|
|
#else
|
|
WCHAR* strCode = (WCHAR*)pbBuffer;
|
|
#endif
|
|
delete[] pbBuffer; // free up the temp buffer
|
|
::CloseHandle(hFile); // close the file
|
|
|
|
EXCEPINFO ei;
|
|
::ZeroMemory(&ei, sizeof(EXCEPINFO));
|
|
|
|
#ifdef _UNICODE
|
|
hr = m_psp->ParseScriptText(strCode, NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION|SCRIPTTEXT_ISVISIBLE, NULL, &ei);
|
|
#else
|
|
hr = m_psp->ParseScriptText(strCode, NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION|SCRIPTTEXT_ISVISIBLE, NULL, &ei);
|
|
#endif
|
|
}/* end of if statement */
|
|
|
|
// take out the extra character at the begining of the unicode file just in case it is garbled by editor
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = m_ps->SetScriptState(/* SCRIPTSTATE_STARTED */ SCRIPTSTATE_CONNECTED);
|
|
|
|
return hr;
|
|
}/* end of function Load */
|
|
|
|
/*************************************************************************/
|
|
/* Function: AddScriptlet */
|
|
/* Description: Using this method you can add events for JScript and */
|
|
/* other languages that do not support event handlers internally. This */
|
|
/* method just add these to the array which does get initializied on load*/
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::AddScriptlet(BSTR strObjectID, BSTR strEvent, BSTR strEventCode){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CEventObject* pObj = new CEventObject(strObjectID, strEvent, strEventCode);
|
|
|
|
if(NULL == pObj){
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
m_cntEvnt.insert(m_cntEvnt.end(), pObj);
|
|
|
|
return(hr);
|
|
}/* end of function AddScriptlet */
|
|
|
|
/*************************************************************************/
|
|
/* Function: HookScriptlet */
|
|
/* Description: Hooks the scrtiptlet for immidiate use, unlike the */
|
|
/* Add scriptlet which adds it, so it takes effect in the next Load. */
|
|
/* However, it also adds the callback to the array, so if needs to be */
|
|
/* loaded on the next load. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::HookScriptlet(BSTR strObjectID, BSTR strEvent, BSTR strEventCode){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
hr = AddScriptlet(strObjectID, strEvent, strEventCode);
|
|
|
|
if(!m_ps){
|
|
|
|
ATLTRACE(TEXT("No Script Engine!! No Run!!\n"));
|
|
ATLASSERT(FALSE);
|
|
throw(S_FALSE);
|
|
}/* end of if statement */
|
|
|
|
EXCEPINFO ei;
|
|
::ZeroMemory(&ei, sizeof(EXCEPINFO));
|
|
|
|
BSTR strName;
|
|
|
|
hr = m_ps->SetScriptState(SCRIPTSTATE_STARTED);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = m_psp->AddScriptlet(NULL, strEventCode, strObjectID, NULL, strEvent, NULL, 0, 0, 0, &strName, &ei);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = m_ps->SetScriptState(SCRIPTSTATE_CONNECTED);
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function HookScriptlet */
|
|
|
|
/*************************************************************************/
|
|
/* Function: Run */
|
|
/* Description: Runs the Script function. Right now I do not support */
|
|
/* TODO: parameters, but they can be added, by handling VARIANT. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::Run(BSTR strStatement){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(!m_ps){
|
|
|
|
ATLTRACE(TEXT("No Script Engine!! No Run!!\n"));
|
|
ATLASSERT(FALSE);
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CComPtr<IDispatch> pDispatch;
|
|
|
|
hr = m_ps->GetScriptDispatch(NULL, &pDispatch);
|
|
|
|
if (FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
DISPID dispidMain;
|
|
|
|
LCID lcid = ::GetUserDefaultLCID();
|
|
hr = pDispatch->GetIDsOfNames(IID_NULL, &strStatement, 1, lcid, &dispidMain);
|
|
|
|
if (hr == ResultFromScode(DISP_E_UNKNOWNNAME))
|
|
hr = NOERROR;
|
|
else if (FAILED(hr))
|
|
hr = E_UNEXPECTED;
|
|
else{
|
|
|
|
UINT uArgErr;
|
|
DISPPARAMS params;
|
|
EXCEPINFO ei;
|
|
|
|
params.cArgs = 0;
|
|
params.cNamedArgs = 0;
|
|
params.rgvarg = NULL;
|
|
params.rgdispidNamedArgs = NULL;
|
|
|
|
hr = pDispatch->Invoke(dispidMain, IID_NULL, lcid, DISPATCH_METHOD,
|
|
¶ms,NULL, &ei, &uArgErr);
|
|
if (FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
#ifdef _DEBUG
|
|
ULONG ulcstmt;
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CComQIPtr<IActiveScriptStats> pstat(m_ps);
|
|
|
|
if (pstat){
|
|
ULONG luT;
|
|
if (FAILED(pstat->GetStat(SCRIPTSTAT_STATEMENT_COUNT, &luT, &ulcstmt)))
|
|
ulcstmt = 0;
|
|
}/* end of if statement */
|
|
|
|
ATLTRACE("Statments executed %d\n", ulcstmt);
|
|
#endif
|
|
|
|
return(hr);
|
|
}/* end of function Run */
|
|
|
|
/*************************************************************************/
|
|
/* Function: CreateObject */
|
|
/* Description: Creates a new ActiveX object that can be scripted. */
|
|
/* Puts the newly created object into container and activates it. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::CreateObject(BSTR strID, BSTR strProgID,
|
|
long lx, long ly, long lWidth, long lHeight,
|
|
BSTR strPropBag, VARIANT_BOOL fDisabled,
|
|
BSTR strScriptHook){
|
|
|
|
HRESULT hr;
|
|
CHostedObject *pObj = NULL; // an ActiveX object
|
|
|
|
try {
|
|
|
|
hr = FindObject(strID, &pObj);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
ATLTRACE(TEXT("Duplicate Object \n!"));
|
|
throw(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
// create the object
|
|
hr = CHostedObject::CreateObject(strID, strProgID, strPropBag, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLTRACE2(atlTraceHosting, 2, TEXT("Failed to Create Object %ls \n"), strID);
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// initialize inPlaceObject
|
|
CComPtr<IUnknown> pObjectUnknown;
|
|
pObjectUnknown = pObj->GetUnknown();
|
|
|
|
// Get this container unknown
|
|
CComPtr<IUnknown> pContainerUnknown;
|
|
pContainerUnknown = GetUnknown();
|
|
|
|
if(!pContainerUnknown){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// this is just a container that delegates pretty
|
|
// much all the methods to this container
|
|
// only purpose for its being is that we need to connection
|
|
// between the container and a specific object
|
|
// for SetCapture and SetFocus calls
|
|
|
|
CContainerObject* pContainerObj = new CContainerObject(pContainerUnknown, pObj);
|
|
pContainerUnknown.Release();
|
|
|
|
if(NULL == pContainerObj){
|
|
|
|
throw(E_OUTOFMEMORY);
|
|
}/* end of if statement */
|
|
|
|
pObj->SetContainerObject(pContainerObj);
|
|
|
|
CComPtr<IUnknown> pUnkContainerObj;
|
|
|
|
hr = pContainerObj->QueryInterface(IID_IUnknown, (void**)&pUnkContainerObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
hr = E_FAIL;
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// insert it at the end of the list
|
|
// TODO: eventually check for duplicate IDs
|
|
m_cntObj.insert(m_cntObj.end(), pObj);
|
|
// add our self to the script engine, so we can hook up the events
|
|
HRESULT hrTmp = m_ps->AddNamedItem((pObj)->GetID(), SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
|
|
|
|
if(FAILED(hrTmp)){
|
|
|
|
ATLTRACE(TEXT("Engine is not initilized yet, but that is what I guess we intended\n"));
|
|
ATLASSERT(FALSE);
|
|
}/* end of if statement */
|
|
|
|
CComPtr<IOleObject> pOleObject;
|
|
HRESULT hrOle = pObj->GetOleObject(&pOleObject);
|
|
|
|
if(SUCCEEDED(hrOle)){
|
|
|
|
DWORD dwMiscStatus;
|
|
pOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
|
|
|
|
// set the OLE site
|
|
CComPtr<IOleClientSite> spClientSite;
|
|
|
|
hr = pUnkContainerObj->QueryInterface(&spClientSite);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
if(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST){
|
|
|
|
pOleObject->SetClientSite(spClientSite); // set the client site
|
|
}/* end of if statement */
|
|
|
|
// no property bag so try to initialze from stream
|
|
CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> spPSI(pOleObject);
|
|
|
|
// TODO: Eventaully load up stream via CreateStreamOnHGlobal
|
|
|
|
if (spPSI)
|
|
spPSI->InitNew(); // create new stream
|
|
|
|
|
|
// see if want to use the IPropertyBag to initialize our properties
|
|
CComQIPtr<IPersistPropertyBag, &IID_IPersistPropertyBag> pBag(pObjectUnknown);
|
|
|
|
if (pBag) {
|
|
CComQIPtr<IPropertyBag, &IID_IPropertyBag> pSBag(pUnkContainerObj);
|
|
|
|
if(!pSBag){
|
|
|
|
ATLTRACE2(atlTraceHosting, 0, _T("Could not get IPropertyBag.\r\n"));
|
|
ATLASSERT(FALSE);
|
|
throw(E_UNEXPECTED);
|
|
}/* end of if statement */
|
|
|
|
HRESULT hrTmp = pBag->Load(pSBag, NULL);
|
|
|
|
if(SUCCEEDED(hrTmp)){
|
|
|
|
pBag->Save(pSBag, FALSE, TRUE);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
if(0 == (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)){
|
|
|
|
pOleObject->SetClientSite(spClientSite); // set the client site
|
|
}/* end of if statement */
|
|
|
|
pObj->InitViewObject(); // cache view object
|
|
|
|
// hook up sink/notify for events
|
|
// via this call in which we have chance to hook them up
|
|
if(NULL != *strScriptHook){
|
|
|
|
HRESULT hrTmp = Run(strScriptHook);
|
|
|
|
if(FAILED(hrTmp)){
|
|
|
|
ATLTRACE(TEXT("Engine is not initilized yet, but that is what I guess we intended\n"));
|
|
ATLASSERT(FALSE);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
// Get the extents adjust them etc...
|
|
// TODO enhance this to handle generic size
|
|
RECT rcPos;
|
|
|
|
SIZEL sSize, shmSize;
|
|
sSize.cx = lWidth;
|
|
sSize.cy = lHeight;
|
|
AtlPixelToHiMetric(&sSize, &shmSize);
|
|
|
|
pOleObject->SetExtent(DVASPECT_CONTENT, &shmSize);
|
|
pOleObject->GetExtent(DVASPECT_CONTENT, &shmSize);
|
|
AtlHiMetricToPixel(&shmSize, &sSize);
|
|
|
|
// TODO: handle the moves on SetObjectRects
|
|
// right now we set offset once but this needs to be eventaully done
|
|
|
|
rcPos.left = lx; // use m_rcPos for the offsets these any time we get SetObjectRects call
|
|
rcPos.top = ly;
|
|
rcPos.right = rcPos.left + sSize.cx;
|
|
rcPos.bottom = rcPos.top + sSize.cy;
|
|
|
|
// TODO: we might want to wait till our rect is set
|
|
// and then let the script to go at it, that way we reduce the moves
|
|
// and possible flashes
|
|
pObj->SetRawPos(&rcPos); // remember our new position raw position
|
|
|
|
//pObj->SetOffset(&m_rcPos.left, &m_rcPos.top); // sets the pointers to the offset
|
|
|
|
//pObj->GetPos(&rcPos); // get the position back with adjusted rect
|
|
|
|
|
|
|
|
if(VARIANT_FALSE != fDisabled){
|
|
|
|
pObj->SetActive(false);
|
|
}/* end of if statement */
|
|
|
|
// IN_PLACE ACTIVATE
|
|
hrOle = pOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &rcPos);
|
|
}
|
|
else {
|
|
// use the liter interface when IOleObject is not available
|
|
CComQIPtr<IObjectWithSite> spSite(pObjectUnknown);
|
|
|
|
if(spSite){
|
|
|
|
spSite->SetSite(pUnkContainerObj);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
hr = hrTmp;
|
|
// cleanup our variables just in case
|
|
if(NULL != pObj){
|
|
|
|
delete pObj;
|
|
}/* end of if statement */
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function CreateObject */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ShowSelfSite */
|
|
/* Description: Show itself as an site for itself. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::ShowSelfSite(long nCmd)
|
|
{
|
|
if (::IsWindow(m_hWnd)) {
|
|
m_pBackBitmap->DeleteMemDC();
|
|
::ShowWindow(m_hWnd, nCmd);
|
|
InvalidateRgn();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetupSelfSite */
|
|
/* Description: Sets itself as an site for itself. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetupSelfSite(long lx, long ly, long lWidth,
|
|
long lHeight, BSTR strPropBag,
|
|
VARIANT_BOOL fDisabled,
|
|
VARIANT_BOOL fHelpDisabled,
|
|
VARIANT_BOOL fWindowDisabled){
|
|
|
|
HRESULT hr;
|
|
CHostedObject *pObj = NULL; // an ActiveX object
|
|
|
|
try {
|
|
if(true == m_fSelfHosted){
|
|
// we are already hosting our self so do not try to do so again
|
|
throw(S_FALSE);
|
|
}/* end of if statement */
|
|
|
|
if(m_nReadyState == READYSTATE_COMPLETE){
|
|
|
|
throw(S_FALSE); //we are already hosted (most likely IE)
|
|
}/* end of if statement */
|
|
|
|
m_bWindowOnly = TRUE; // create self as a window
|
|
m_fSelfHosted = true; // we are trying to self host so send a QUIT message
|
|
|
|
CComPtr<IDispatch> pDisp;
|
|
hr = GetUnknown()->QueryInterface(&pDisp);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
const INT ciMaxBuffSize = MAX_PATH; // should be enough for tlbr ID, keep ID small if can
|
|
TCHAR strBuffer[ciMaxBuffSize];
|
|
|
|
if(!::LoadString(m_hRes, IDS_ROOT_OBJECT, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
#ifndef _UNICODE
|
|
USES_CONVERSION;
|
|
BSTR strObjectID = ::SysAllocString(T2W(strBuffer));
|
|
|
|
#else
|
|
BSTR strObjectID = ::SysAllocString(strBuffer);
|
|
#endif
|
|
|
|
hr = CHostedObject::AddObject(strObjectID, strPropBag, pDisp, &pObj);
|
|
// strPropBag gets allocated as well
|
|
::SysFreeString(strObjectID);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// initialize inPlaceObject
|
|
CComPtr<IUnknown> pObjectUnknown;
|
|
pObjectUnknown = pObj->GetUnknown();
|
|
|
|
// Get this container unknown
|
|
CComPtr<IUnknown> pContainerUnknown;
|
|
pContainerUnknown = GetUnknown();
|
|
|
|
if(!pContainerUnknown){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// this is just a container that delegates pretty
|
|
// much all the methods to this container
|
|
// only purpose for its being is that we need to connection
|
|
// between the container and a specific object
|
|
// for SetCapture and SetFocus calls
|
|
|
|
CContainerObject* pContainerObj = new CContainerObject(pContainerUnknown, pObj);
|
|
pContainerUnknown.Release();
|
|
|
|
if(NULL == pContainerObj){
|
|
|
|
throw(E_OUTOFMEMORY);
|
|
}/* end of if statement */
|
|
|
|
pObj->SetContainerObject(pContainerObj);
|
|
|
|
CComPtr<IUnknown> pUnkContainerObj;
|
|
|
|
hr = pContainerObj->QueryInterface(IID_IUnknown, (void**)&pUnkContainerObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// DO NOT INSERT THIS OBJECT, SINCE IT IS OUR CONTAINER
|
|
// m_cntObj.insert(m_cntObj.end(), pObj);
|
|
|
|
CComPtr<IOleObject> pOleObject;
|
|
HRESULT hrOle = pObj->GetOleObject(&pOleObject);
|
|
|
|
if(FAILED(hrOle)){
|
|
|
|
throw(hrOle);
|
|
}/* end of if statement */
|
|
|
|
DWORD dwMiscStatus;
|
|
pOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
|
|
|
|
// set the OLE site
|
|
CComPtr<IOleClientSite> spClientSite;
|
|
|
|
hr = pUnkContainerObj->QueryInterface(&spClientSite);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
if(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST){
|
|
|
|
pOleObject->SetClientSite(spClientSite); // set the client site
|
|
}/* end of if statement */
|
|
|
|
// no property bag so try to initialze from stream
|
|
CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> spPSI(pOleObject);
|
|
|
|
// TODO: Eventaully load up stream via CreateStreamOnHGlobal
|
|
|
|
if (spPSI)
|
|
spPSI->InitNew(); // create new stream
|
|
|
|
// see if want to use the IPropertyBag to initialize our properties
|
|
CComQIPtr<IPersistPropertyBag, &IID_IPersistPropertyBag> pBag(pObjectUnknown);
|
|
|
|
if (pBag) {
|
|
CComQIPtr<IPropertyBag, &IID_IPropertyBag> pSBag(pUnkContainerObj);
|
|
|
|
if(!pSBag){
|
|
|
|
ATLTRACE2(atlTraceHosting, 0, _T("Could not get IPropertyBag.\r\n"));
|
|
ATLASSERT(FALSE);
|
|
throw(E_UNEXPECTED);
|
|
}/* end of if statement */
|
|
|
|
HRESULT hrTmp = pBag->Load(pSBag, NULL);
|
|
|
|
if(SUCCEEDED(hrTmp)){
|
|
|
|
pBag->Save(pSBag, FALSE, TRUE);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
if(0 == (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)){
|
|
|
|
pOleObject->SetClientSite(spClientSite); // set the client site
|
|
}/* end of if statement */
|
|
|
|
pObj->InitViewObject(); // cache view object
|
|
|
|
// TODO: hook up sink/notify for events
|
|
|
|
// Get the extents adjust them etc...
|
|
// TODO enhance this to handle generic size
|
|
RECT rcPos;
|
|
|
|
SIZEL sSize, shmSize;
|
|
sSize.cx = lWidth;
|
|
sSize.cy = lHeight;
|
|
AtlPixelToHiMetric(&sSize, &shmSize);
|
|
|
|
pOleObject->SetExtent(DVASPECT_CONTENT, &shmSize);
|
|
pOleObject->GetExtent(DVASPECT_CONTENT, &shmSize);
|
|
AtlHiMetricToPixel(&shmSize, &sSize);
|
|
|
|
// TODO: handle the moves on SetObjectRects
|
|
// right now we set offset once but this needs to be eventaully done
|
|
|
|
rcPos.left = lx; // use m_rcPos for the offsets these any time we get SetObjectRects call
|
|
rcPos.top = ly;
|
|
rcPos.right = rcPos.left + sSize.cx;
|
|
rcPos.bottom = rcPos.top + sSize.cy;
|
|
|
|
RECT rcClientRect;
|
|
|
|
rcClientRect.left = 0; // use m_rcPos for the offsets these any time we get SetObjectRects call
|
|
rcClientRect.top = 0;
|
|
rcClientRect.right = sSize.cx;
|
|
rcClientRect.bottom = sSize.cy;
|
|
|
|
// TODO: we might want to wait till our rect is set
|
|
// and then let the script to go at it, that way we reduce the moves
|
|
// and possible flashes
|
|
|
|
pObj->SetRawPos(&rcPos); // remember our new position raw position
|
|
|
|
// adjust rects
|
|
// IN_PLACE ACTIVATE OUR SELF ACTIVATION VERSION
|
|
|
|
if (m_spClientSite == NULL)
|
|
return S_OK;
|
|
|
|
CComPtr<IOleInPlaceObject> pIPO;
|
|
ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
|
|
ATLASSERT(pIPO != NULL);
|
|
|
|
m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void**)&m_spInPlaceSite);
|
|
if (m_spInPlaceSite)
|
|
m_bInPlaceSiteEx = TRUE;
|
|
else
|
|
hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void**) &m_spInPlaceSite);
|
|
|
|
ATLASSERT(m_spInPlaceSite);
|
|
if (!m_spInPlaceSite)
|
|
throw(E_FAIL);
|
|
|
|
m_bNegotiatedWnd = TRUE;
|
|
|
|
if (!m_bInPlaceActive){
|
|
|
|
BOOL bNoRedraw = FALSE;
|
|
if (m_bInPlaceSiteEx)
|
|
m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
|
|
else
|
|
{
|
|
hr = m_spInPlaceSite->CanInPlaceActivate();
|
|
// CanInPlaceActivate returns S_FALSE or S_OK
|
|
if (FAILED(hr))
|
|
throw(hr);
|
|
if ( hr != S_OK )
|
|
{
|
|
// CanInPlaceActivate returned S_FALSE.
|
|
throw( E_FAIL );
|
|
}
|
|
m_spInPlaceSite->OnInPlaceActivate();
|
|
}
|
|
}/* end of if statement */
|
|
|
|
m_bInPlaceActive = TRUE;
|
|
|
|
// get location in the parent window,
|
|
// as well as some information about the parent
|
|
//
|
|
OLEINPLACEFRAMEINFO frameInfo;
|
|
|
|
CComPtr<IOleInPlaceFrame> spInPlaceFrame;
|
|
CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
|
|
frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
|
|
|
|
if (!m_bWndLess){
|
|
|
|
DWORD dwStyle;
|
|
DWORD dwExStyle;
|
|
HWND hwndPar = NULL;
|
|
|
|
|
|
if(VARIANT_FALSE == fWindowDisabled){
|
|
// one with the frame
|
|
dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
|
}
|
|
else {
|
|
// one without the frame
|
|
dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
//dwExStyle = WS_EX_TRANSPARENT; //| WS_EX_LTRREADING| WS_EX_WINDOWEDGE;
|
|
//dwExStyle = 0x00080000; //WS_EX_LAYERED = 0x00080000;
|
|
dwExStyle = WS_EX_APPWINDOW;
|
|
//hwndPar = ::GetDesktopWindow();
|
|
}/* end of if statement */
|
|
|
|
if(VARIANT_FALSE == fDisabled){
|
|
|
|
dwStyle |= WS_VISIBLE;
|
|
}/* end of if statement */
|
|
|
|
if(VARIANT_FALSE == fHelpDisabled){
|
|
|
|
dwStyle &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX); // take out the min max style
|
|
// help does not work with it
|
|
dwExStyle |= WS_EX_CONTEXTHELP;
|
|
}/* end of if statement */
|
|
|
|
#ifdef _UNICODE
|
|
HWND h = Create(hwndPar, rcPos, m_bstrCaption /* window name */, dwStyle, dwExStyle);
|
|
#else
|
|
USES_CONVERSION;
|
|
HWND h = Create(hwndPar, rcPos, OLE2T(m_bstrCaption) /* window name */, dwStyle, dwExStyle);
|
|
#endif
|
|
|
|
// used instead of
|
|
// HWND h = CreateControlWindow(hwndParent, rcPos);
|
|
ATLASSERT(h != NULL); // will assert if creation failed
|
|
ATLASSERT(h == m_hWndCD);
|
|
if(NULL == h){
|
|
|
|
throw(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
if(VARIANT_TRUE == fWindowDisabled){
|
|
|
|
::SendMessage(h, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) m_hIcon);
|
|
::SendMessage(h, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM) m_hIcon);
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
if(VARIANT_FALSE != fDisabled){
|
|
|
|
pObj->SetActive(false);
|
|
}/* end of if statement */
|
|
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
hr = hrTmp;
|
|
m_fSelfHosted = false;
|
|
// cleanup our variables just in case
|
|
if(NULL != pObj){
|
|
|
|
delete pObj;
|
|
}/* end of if statement */
|
|
}
|
|
catch(...){
|
|
m_fSelfHosted = false;
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function SetupSelfSite */
|
|
|
|
/*************************************************************************/
|
|
/* Function: AddObject */
|
|
/* Description: Adds a scriptable only object that was created somewhere */
|
|
/* else into our object container. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::AddObject(BSTR strObjectID, LPDISPATCH pDisp){
|
|
|
|
HRESULT hr;
|
|
CHostedObject *pObj = NULL; // an ActiveX object
|
|
|
|
try {
|
|
// add an object that was already created
|
|
// this object does not get the Active flag set which
|
|
// means we will not try to draw it and do other
|
|
// activities on it, such as we would do on the objects
|
|
// that are contained and have a site
|
|
hr = CHostedObject::AddObject(strObjectID, NULL, pDisp, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
// now add the object to the container
|
|
// insert it at the end of the list
|
|
// TODO: eventually check for duplicate IDs
|
|
m_cntObj.insert(m_cntObj.end(), pObj);
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
hr = hrTmp;
|
|
// cleanup our variables just in case
|
|
if(NULL != pObj){
|
|
|
|
delete pObj;
|
|
}/* end of if statement */
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function AddObject */
|
|
|
|
// ##### END ACTIVEX SCRIPTING SUPPORT #####
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetParentHWND */
|
|
/* Description: Gets the parent window HWND where we are operating. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::GetParentHWND(HWND* pWnd){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
*pWnd = NULL;
|
|
|
|
if(m_bWndLess){
|
|
|
|
CComPtr<IOleClientSite> pClientSite;
|
|
|
|
hr = GetClientSite(&pClientSite);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CComQIPtr<IOleWindow> pOleWindow(pClientSite);
|
|
|
|
if(!pOleWindow){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
hr = pOleWindow->GetWindow(pWnd);
|
|
}
|
|
else {
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
*pWnd = ::GetParent(m_hWnd);
|
|
if(::IsWindow(*pWnd)){
|
|
|
|
hr = S_OK;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function GetParentHWND */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetClientRect */
|
|
/* Description: Gets the client rect. If we are windowless we pass down */
|
|
/* the m_rcPos. */
|
|
/*************************************************************************/
|
|
BOOL CMFBar::GetClientRect(LPRECT lpRect) const{
|
|
|
|
BOOL bRet = TRUE;
|
|
|
|
if (!lpRect){
|
|
|
|
bRet = FALSE;
|
|
return (bRet);
|
|
}/* end of if statement */
|
|
|
|
if(m_bWndLess){
|
|
|
|
*lpRect = m_rcPos;
|
|
return(bRet);
|
|
}/* end of if statement */
|
|
|
|
ATLASSERT(::IsWindow(m_hWnd));
|
|
bRet = ::GetClientRect(m_hWnd, lpRect);
|
|
|
|
return(bRet);
|
|
}/* end of function GetClientRect */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetParent */
|
|
/* Description: Gets the parent window. If we are windowless we pass */
|
|
/* down the parent container window, which is really in a sense parent. */
|
|
/*************************************************************************/
|
|
HWND CMFBar::GetParent(){
|
|
|
|
HWND hwnd = NULL;
|
|
|
|
if(m_bWndLess){
|
|
|
|
GetParentHWND(&hwnd);
|
|
return(hwnd);
|
|
}/* end of if statement */
|
|
|
|
ATLASSERT(::IsWindow(m_hWnd));
|
|
return ::GetParent(m_hWnd);
|
|
}/* end of function GetParent */
|
|
|
|
/*************************************************************************/
|
|
/* Function: AdjustRects */
|
|
/* Description: calls all our contained objects and the adjusts their */
|
|
/* rects in the case we have moved, if we do not have any that is OK, */
|
|
/* since the offset is kept in m_rcPos and set whenever the objects */
|
|
/* get created. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::AdjustRects(const LPCRECT prcPos){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//TODO: handle resizing
|
|
ATLTRACE2(atlTraceHosting, 2, TEXT("Resizing control prcPos->left = %d, prcPos.right = %d, prcPos.bottom =%d, prcPos.top = %d\n"),
|
|
prcPos->left, prcPos->right, prcPos->bottom, prcPos->top);
|
|
|
|
if(false == m_fSelfHosted){
|
|
|
|
Fire_OnResize(RECTWIDTH(prcPos), RECTHEIGHT(prcPos), SIZE_RESTORED);
|
|
}/* end of if statement */
|
|
|
|
#if 0
|
|
if(!m_bWndLess){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(m_cntObj.empty() == true){
|
|
|
|
hr = S_FALSE;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
ATLASSERT(pObj);
|
|
|
|
if(m_fSelfHosted && (GetUnknown() == pObj->GetUnknown())){
|
|
|
|
continue; // that is us we close our self later after the contained objects
|
|
}/* end of if statement */
|
|
|
|
pObj->SetObjectRects(); // adjust the current offset if it needs to be so
|
|
}/* end of for loop */
|
|
#endif
|
|
return(hr);
|
|
}/* end of function AdjustRects */
|
|
|
|
/*************************************************************************/
|
|
/* IOleInPlaceSiteEx Implementation */
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* Function: CanWindowlessActivate */
|
|
/* Description: Return if we can windowless activate or not. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::CanWindowlessActivate(){
|
|
|
|
return m_bCanWindowlessActivate ? S_OK : S_FALSE;
|
|
}/* end of function CanWindowlessActivate */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetDC */
|
|
/* Description: Gets a DC to draw with. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->GetDC(pRect, grfFlags, phDC);
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
*phDC = ::GetDC(m_hWnd);
|
|
}
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function GetDC */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ReleaseDC */
|
|
/* Description: Releases the DC */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::ReleaseDC(HDC hDC){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->ReleaseDC(hDC);
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::ReleaseDC(m_hWnd, hDC);
|
|
}
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function ReleaseDC */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnDefWindowMessage */
|
|
/* Description: Sends on messages to the default window procedure. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::OnDefWindowMessage(UINT msg, WPARAM wParam,
|
|
LPARAM lParam, LRESULT* plResult){
|
|
|
|
*plResult = DefWindowProc(msg, wParam, lParam);
|
|
return S_OK;
|
|
}/* end of function OnDefWindowMessage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: InvalidateRgn */
|
|
/* Description: Invalidates the whole rect in case we need to repaint it.*/
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::InvalidateRgn(HRGN hRGN, BOOL fErase){
|
|
|
|
HRESULT hr = S_OK;
|
|
#if 0
|
|
if (!hRGN) {
|
|
RECT rc;
|
|
GetClientRect(&rc);
|
|
hRGN = ::CreateRectRgn( rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
|
|
HRGN newRgn = ::CreateRectRgn(0, 0, 10, 10);
|
|
::CombineRgn(newRgn, hRGN, NULL, RGN_COPY) ;
|
|
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
ATLASSERT(pObj);
|
|
|
|
if(m_fSelfHosted && (GetUnknown() == pObj->GetUnknown())){
|
|
|
|
continue; // that is us we close our self later after the contained objects
|
|
}/* end of if statement */
|
|
|
|
if (!pObj->IsWindowless() && pObj->IsActive()) {
|
|
LONG x1, y1, w, h;
|
|
GetObjectPosition(pObj->GetID(), &x1, &y1, &w, &h);
|
|
HRGN objRgn = ::CreateRectRgn( x1, y1, x1+w, y1+h );
|
|
::CombineRgn(newRgn, newRgn, objRgn, RGN_DIFF);
|
|
//ATLTRACE(TEXT("Excluding Rgn %d %d %d %d\n"), x1, y1, x1+w, y1+h);
|
|
}
|
|
}/* end of for loop */
|
|
|
|
hRGN = newRgn;
|
|
#endif
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->InvalidateRgn(hRGN ,fErase);
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::InvalidateRgn(m_hWnd, hRGN, fErase); // see if we can get by by not erasing..
|
|
}
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function InvalidateRgn */
|
|
|
|
/*************************************************************************/
|
|
/* Function: InvalidateRect */
|
|
/* Description: Invalidates the rect, handles if we are windowless */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::InvalidateRect(LPCRECT pRect, BOOL fErase){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->InvalidateRect(pRect, fErase);
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::InvalidateRect(m_hWnd, pRect, fErase);
|
|
}
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function InvalidateRect */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetCapture */
|
|
/* Description: Used to determine if we have a cupature or not */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetCapture(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->GetCapture();
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
hr = ::GetCapture() == m_hWnd ? S_OK : S_FALSE;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function GetCapture */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetCapture */
|
|
/* Description: Used to set the capture for mouse events */
|
|
/* Only one container at the time can have a capture. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetCapture(BOOL fCapture){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// whatever we we are doing we need to reset the capture flags on all the object
|
|
// after this call is finished the specific site will set appropriate flag
|
|
ResetCaptureFlags();
|
|
|
|
if(fCapture){
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Setting Mouse Capture in the container \n"));
|
|
}
|
|
else {
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Resetting Mouse Capture in the container\n"));
|
|
}/* end of if statement */
|
|
|
|
if(m_bWndLess){
|
|
|
|
if (fCapture){
|
|
|
|
hr = m_spInPlaceSite->SetCapture(TRUE);
|
|
}
|
|
else {
|
|
|
|
hr = m_spInPlaceSite->SetCapture(FALSE);
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
if (fCapture){
|
|
// do not have a capture, so set it
|
|
::SetCapture(m_hWnd);
|
|
}
|
|
else{
|
|
// nobody more has a capture, so let it go
|
|
::ReleaseCapture();
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function SetCapture */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ResetCaptureFlags */
|
|
/* Description: Resets the capture on contained objects. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::ResetCaptureFlags(){
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained objects and draw them
|
|
CHostedObject* pObj = (*i);
|
|
|
|
pObj->SetCapture(false);
|
|
}/* end of for function */
|
|
|
|
return(S_OK);
|
|
}/* end of function ResetCaptureFlags */
|
|
|
|
/*************************************************************************/
|
|
/* Function: ResetFocusFlags */
|
|
/* Description: Resets the capture on contained objects. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::ResetFocusFlags(){
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// iterate through all the contained objects and draw them
|
|
CHostedObject* pObj = (*i);
|
|
if(pObj->HasFocus()){
|
|
|
|
LONG lRes;
|
|
SetObjectFocus(pObj, FALSE, lRes);
|
|
}/* end of if statement */
|
|
}/* end of for function */
|
|
|
|
return(S_OK);
|
|
}/* end of function ResetFocusFlags */
|
|
|
|
/*************************************************************************/
|
|
/* Function: EnumObjects */
|
|
/* Description: Returns IEnumUnknown */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::EnumObjects(DWORD /*grfFlags*/, IEnumUnknown** ppenum){
|
|
|
|
if (ppenum == NULL)
|
|
return E_POINTER;
|
|
|
|
*ppenum = NULL;
|
|
|
|
// TODO: handle flags
|
|
|
|
if(m_cntObj.empty() == true){
|
|
|
|
return E_FAIL;
|
|
}/* end of if statement */
|
|
|
|
typedef CComObject<CComEnum<IEnumUnknown, &IID_IEnumUnknown, IUnknown*, _CopyInterface<IUnknown> > > enumunk;
|
|
enumunk* p = NULL;
|
|
ATLTRY(p = new enumunk);
|
|
if(p == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// create an array to which we put our *IUnknowns
|
|
INT iSize = m_cntObj.size();
|
|
IUnknown** pArray = new IUnknown* [iSize];
|
|
|
|
if(pArray == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
INT iCount = 0;
|
|
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
// move the interfaces to the array
|
|
CHostedObject* pObj = (*i);
|
|
pArray[iCount] = pObj->GetUnknown();
|
|
iCount++;
|
|
}/* end of for loop */
|
|
|
|
HRESULT hRes = p->Init(pArray, pArray + iSize, GetUnknown(), AtlFlagCopy);
|
|
if (SUCCEEDED(hRes))
|
|
hRes = p->QueryInterface(IID_IEnumUnknown, (void**)ppenum);
|
|
if (FAILED(hRes))
|
|
delete p;
|
|
|
|
delete[] pArray;
|
|
|
|
return hRes;
|
|
}/* end of function EnumObjects */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SendMessageToCtl */
|
|
/* Description: Forwards message to a control */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::SendMessageToCtl(CHostedObject* pObj,
|
|
UINT uMsg, WPARAM wParam, LPARAM lParam,
|
|
BOOL& bHandled, LONG& lRes, bool fWndwlsOnly){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL == pObj){
|
|
|
|
hr = E_UNEXPECTED;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(fWndwlsOnly && (!pObj->IsWindowless())){
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("NOT SENDING message to control %ls !!!\n"), pObj->GetID());
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(!pObj->IsActive()){
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("NOT SENDING message to control %ls !!!\n"), pObj->GetID());
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
CComPtr<IUnknown> pUnk = pObj->GetUnknown();
|
|
|
|
if(!pUnk){
|
|
|
|
ATLASSERT(FALSE); // should not be null
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
CComQIPtr<IOleInPlaceObjectWindowless> spInPlaceObjectWindowless(pUnk);
|
|
|
|
if(spInPlaceObjectWindowless){
|
|
|
|
// more then one control can have have a capture
|
|
|
|
LRESULT lRes64;
|
|
spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes64);
|
|
|
|
//BUGBUG: Just to get this compiling for now. Will overhaul all
|
|
//datatypes later for 64-bit compatibility
|
|
|
|
lRes = (LONG)lRes64;
|
|
|
|
bHandled = TRUE;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function SendMessageToCtl */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetFocus */
|
|
/* Description: Determine if we have a focus or not. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetFocus(){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_bWndLess){
|
|
|
|
hr = m_spInPlaceSite->GetFocus();
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
hr = ::GetFocus() == m_hWnd ? S_OK : S_FALSE;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function GetFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetFocus */
|
|
/* Description: Sets focus to the control */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetFocus(BOOL fFocus){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// we reset the flags depending on WM_SET and WM_KILL focus messages
|
|
if(fFocus){
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Setting Mouse Focus in the container \n"));
|
|
}
|
|
else {
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Resetting Mouse Focus in the container\n"));
|
|
}/* end of if statement */
|
|
|
|
if(m_bWndLess){
|
|
|
|
if (fFocus){
|
|
|
|
hr = m_spInPlaceSite->SetFocus(TRUE);
|
|
}
|
|
else {
|
|
|
|
hr = m_spInPlaceSite->SetFocus(FALSE);
|
|
}/* end of if statement */
|
|
}
|
|
else {
|
|
if(NULL == m_hWnd){
|
|
|
|
hr = E_FAIL;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
if (fFocus){
|
|
|
|
::SetFocus(m_hWnd);
|
|
}
|
|
else {
|
|
|
|
// else could call ::SetFocus(NULL), but that does not seem like a good solution
|
|
// so instead reset the focus on contained conrols
|
|
// which is risky too, since some control could try to call SetFocus(false)
|
|
// when it does not have the focus, but that is handled in the caller
|
|
//ResetFocusFlags();
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
else {
|
|
hr = E_UNEXPECTED;
|
|
}/* end of if statement */
|
|
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function SetFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_ActivityTimeOut */
|
|
/* Description: Gets the currrent timout value. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_ActivityTimeout(long *plTimeout){
|
|
|
|
*plTimeout = m_lTimeout;
|
|
return(S_OK);
|
|
}/* end of function get_ActivityTimeOut */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_ActivityTimeOut */
|
|
/* Description: Creates a new timer if needed. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_ActivityTimeout(long lTimeout){
|
|
|
|
if(lTimeout < 0){
|
|
|
|
return(E_INVALIDARG);
|
|
}/* end of if statement */
|
|
|
|
if(!::IsWindow(m_hWnd)){
|
|
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
if(m_lTimeout != 0 || 0 == lTimeout ){
|
|
|
|
// kill it each time we set a new timer
|
|
::KillTimer(m_hWnd, ID_EV_TIMER);
|
|
}
|
|
else {
|
|
|
|
if(0 == ::SetTimer(m_hWnd, ID_EV_TIMER, lTimeout, NULL)){
|
|
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
m_lTimeout = lTimeout;
|
|
m_fUserActivity = false;
|
|
m_fWaitingForActivity = false;
|
|
|
|
return(S_OK);
|
|
}/* end of function put_ActivityTimeOut */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetObjectExtent */
|
|
/* Description: Sets specific object witdth and height. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetObjectExtent(BSTR strObjectID, long lWidth, long lHeight){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if sattement */
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(!_wcsicmp(pObj->GetID(), strObjectID)){
|
|
RECT rcOld;
|
|
hr = pObj->GetPos(&rcOld);
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
RECT rcNew;
|
|
rcNew.left = rcOld.left; rcNew.top = rcOld.top;
|
|
rcNew.right = rcNew.left + lWidth; rcNew.bottom = rcNew.top + lHeight;
|
|
|
|
if(::EqualRect(&rcOld, &rcNew)){
|
|
|
|
hr = S_FALSE; // no point to monkey around if the rects are the same
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// Set the objects new position
|
|
hr = pObj->SetRawPos(&rcNew);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// Set the objects new position
|
|
hr = pObj->SetRawPos(&rcNew);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(pObj->IsWindowless()){
|
|
|
|
hr = pObj->SetObjectRects();
|
|
}
|
|
else {
|
|
|
|
hr = pObj->SetObjectRects(&rcNew);
|
|
}/* end of if statement */
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
RECT rcUnion;
|
|
|
|
::UnionRect(&rcUnion, &rcOld, &rcNew);
|
|
|
|
if (pObj->IsWindowless())
|
|
hr = InvalidateRect(&rcUnion, FALSE);
|
|
|
|
break; // already have set the state and invalidated and bail out
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return (hr);
|
|
}/* end of function SetObjectExtent */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetObjectPosition */
|
|
/* Description: Sets specific object position. Looks up object by object */
|
|
/* ID. Sets also extents. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetObjectPosition(BSTR strObjectID, long xPos,
|
|
long yPos, long lWidth, long lHeight){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if sattement */
|
|
|
|
RECT rcNew;
|
|
rcNew.left = xPos; rcNew.top = yPos;
|
|
rcNew.right = rcNew.left + lWidth; rcNew.bottom = rcNew.top + lHeight;
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(!_wcsicmp(pObj->GetID(), strObjectID)){
|
|
RECT rcOld;
|
|
hr = pObj->GetPos(&rcOld);
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(::EqualRect(&rcOld, &rcNew)){
|
|
|
|
hr = S_FALSE; // no point to monkey around if the rects are the same
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// Set the objects new position
|
|
hr = pObj->SetRawPos(&rcNew);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
if(pObj->IsWindowless()){
|
|
|
|
hr = pObj->SetObjectRects();
|
|
}
|
|
else {
|
|
|
|
hr = pObj->SetObjectRects(&rcNew);
|
|
}/* end of if statement */
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
RECT rcUnion;
|
|
|
|
::UnionRect(&rcUnion, &rcOld, &rcNew);
|
|
|
|
if (pObj->IsWindowless())
|
|
hr = InvalidateRect(&rcUnion, FALSE);
|
|
|
|
break; // already have set the state and invalidated and bail out
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return (hr);
|
|
}/* end of function SetObjectPosition */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetObjectPosition */
|
|
/* Description: SetObjectPosition */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::GetObjectPosition(BSTR strObjectID, long* pxPos, long* pyPos, long* plWidth, long* plHeight){
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(NULL == strObjectID){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if sattement */
|
|
|
|
if(NULL == pxPos || NULL == pyPos || NULL == plWidth || NULL == plHeight){
|
|
|
|
return(E_POINTER);
|
|
}/* end of if statement */
|
|
|
|
*pxPos = *pyPos = *plWidth = *plHeight = 0;
|
|
|
|
bool bFirstElement = true;
|
|
CNTOBJ::iterator i;
|
|
for(i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
if(!_wcsicmp((*i)->GetID(), strObjectID)){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
// Set the objects new position
|
|
RECT rc;
|
|
hr = pObj->GetPos(&rc);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
*pxPos = rc.left; *pyPos = rc.top; *plWidth = RECTWIDTH(&rc); *plHeight = RECTHEIGHT(&rc);
|
|
}/* end of if statement */
|
|
|
|
break; // already have set the state and invalidated and bail out
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return (hr);
|
|
}/* end function GetObjectPosition */
|
|
|
|
/*************************************************************************/
|
|
/* Function: WinHelp */
|
|
/* Description: Called by the script to execute specific help topic. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::WinHelp(long lCommand, long dwData, BSTR strHelpFile){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
HWND h = NULL;
|
|
|
|
hr = GetWindow(&h);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
USES_CONVERSION;
|
|
BOOL bResult = ::WinHelp(h, OLE2T(strHelpFile), lCommand, dwData);
|
|
|
|
if(!bResult){
|
|
|
|
// failed so lets try to get some more meaningful result
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
}/* end of if statement */
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function WinHelp */
|
|
|
|
/*************************************************************************/
|
|
/* Function: MessageBox */
|
|
/* Description: Displays the message box using specified parameters. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::MessageBox(BSTR strText, BSTR strCaption, long lType){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
USES_CONVERSION;
|
|
|
|
HWND hWnd = NULL;
|
|
HRESULT hr = GetWindow(&hWnd);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
ATLASSERT(FALSE);
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
::MessageBox(hWnd, OLE2T(strText), OLE2T(strCaption), lType);
|
|
}
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
return S_OK;
|
|
}/* end of function MessageBox */
|
|
|
|
/*************************************************************************/
|
|
/* Function: GetToolbarName */
|
|
/* Description: Gets and allocates the toolbar name. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::GetToolbarName(BSTR* strToolbarName){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL == strToolbarName){
|
|
|
|
hr = E_POINTER;
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
const INT ciMaxBuffSize = MAX_PATH; // should be enough for tlbr ID, keep ID small if can
|
|
TCHAR strBuffer[ciMaxBuffSize];
|
|
|
|
if(!::LoadString(m_hRes, IDS_ROOT_OBJECT, strBuffer, ciMaxBuffSize)){
|
|
|
|
hr = E_FAIL;
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
#ifdef _UNICODE
|
|
*strToolbarName = ::SysAllocString(strBuffer);
|
|
#else
|
|
USES_CONVERSION;
|
|
*strToolbarName = ::SysAllocString(T2OLE(strBuffer));
|
|
#endif
|
|
|
|
return(hr);
|
|
}/* end of function GetToolbarName */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetPriority */
|
|
/* Description: Sets the thread priority. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetPriority(long lPriority){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
HANDLE hThread = ::GetCurrentThread();
|
|
|
|
if(!::SetThreadPriority(hThread, lPriority)){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
throw (hr);
|
|
}/* end of if statement */
|
|
}
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function SetPriority */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetPriorityClass */
|
|
/* Description: Sets the thread priority. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetPriorityClass(long lPriority){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
HANDLE hThread = ::GetCurrentThread();
|
|
|
|
if(!::SetPriorityClass(hThread, lPriority)){
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
throw (hr);
|
|
}/* end of if statement */
|
|
}
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return (hr);
|
|
}/* end of function SetPriorityClass */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_BackgroundImage */
|
|
/* Description: Gets the backround image. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_BackgroundImage(BSTR *pstrFilename){
|
|
|
|
*pstrFilename = m_bstrBackImageFilename.Copy();
|
|
return S_OK;
|
|
}/* end of function get_BackgroundImage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_BackgroundImage */
|
|
/* Description: Attempts to load the background image. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_BackgroundImage(BSTR strFilename){
|
|
|
|
USES_CONVERSION;
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL != m_pBackBitmap){
|
|
|
|
delete m_pBackBitmap;
|
|
}/* end of if statement */
|
|
|
|
m_pBackBitmap = new CBitmap;
|
|
|
|
m_pBackBitmap->LoadPalette(true); // load the palette if available, since this
|
|
// is the palette we use for the rest
|
|
// of the contained objects
|
|
|
|
m_bstrBackImageFilename = strFilename;
|
|
|
|
TCHAR strBuffer[MAX_PATH] = TEXT("\0");
|
|
|
|
bool fGrayOut = false;
|
|
|
|
hr = m_pBackBitmap->PutImage(strFilename, m_hRes, GetUnknown(),fGrayOut ,m_blitType);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
// we are updating image that is being used, refresh it
|
|
ATLTRACE2(atlTraceWindowing, 20, TEXT("Redrawing the image\n"));
|
|
InvalidateRgn(); // our helper function
|
|
|
|
return(hr);
|
|
}/* end of function put_BackgroundImage */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetReadyState */
|
|
/* Description: Sets ready state and fires event if it needs to be fired */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::SetReadyState(LONG lReadyState){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
bool bFireEvent = (lReadyState != m_nReadyState);
|
|
|
|
|
|
#ifdef _DEBUG
|
|
if(m_nFreezeEvents > 0){
|
|
|
|
::Sleep(10);
|
|
ATLTRACE("Container not expecting events at the moment");
|
|
}/* end of is statement */
|
|
|
|
#endif
|
|
|
|
if(bFireEvent){
|
|
|
|
put_ReadyState(lReadyState);
|
|
Fire_ReadyStateChange(lReadyState);
|
|
}
|
|
else {
|
|
// set the variable
|
|
m_nReadyState = lReadyState;
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function SetReadyState */
|
|
|
|
/*************************************************************************/
|
|
/* Function: OnPostVerbInPlaceActivate */
|
|
/* Description: Creates the in place active object. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::OnPostVerbInPlaceActivate(){
|
|
|
|
SetReadyState(READYSTATE_COMPLETE);
|
|
|
|
return(S_OK);
|
|
}/* end of function OnPostVerbInPlaceActivate */
|
|
|
|
/*************************************************************************/
|
|
/* Function: get_AutoLoad */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::get_AutoLoad(VARIANT_BOOL *pVal){
|
|
|
|
*pVal = m_fAutoLoad;
|
|
|
|
return S_OK;
|
|
}/* end of function get_AutoLoad */
|
|
|
|
/*************************************************************************/
|
|
/* Function: put_AutoLoad */
|
|
/* Description: Sets the flag to autolaod the engine after we set a */
|
|
/* script file or not. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::put_AutoLoad(VARIANT_BOOL newVal){
|
|
|
|
m_fAutoLoad = (VARIANT_FALSE == newVal ? VARIANT_FALSE : VARIANT_TRUE);
|
|
|
|
return S_OK;
|
|
}/* end of function put_AutoLoad */
|
|
|
|
/*************************************************************/
|
|
/* Name: SetRectRgn
|
|
/* Description: Set up a rectangular window update region
|
|
/*************************************************************/
|
|
STDMETHODIMP CMFBar::SetRectRgn(long x1, long y1, long x2, long y2)
|
|
{
|
|
HRGN hRgn = ::CreateRectRgn( x1, y1, x2, y2 );
|
|
::SetWindowRgn(m_hWnd, hRgn, TRUE);
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************/
|
|
/* Name: SetRoundRectRgn
|
|
/* Description: Set up a round corner window update region
|
|
/*************************************************************/
|
|
STDMETHODIMP CMFBar::SetRoundRectRgn(long x1, long y1, long x2, long y2, long width, long height){
|
|
|
|
HRGN hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, width, height);
|
|
::SetWindowRgn(m_hWnd, hRgn, TRUE);
|
|
return S_OK;
|
|
}/* end of function SetRoundRectRgn */
|
|
|
|
/*************************************************************/
|
|
/* Function: SetTimeout */
|
|
/* Description: Creates a timer and then calls events when */
|
|
/* timer proc gets called. */
|
|
/*************************************************************/
|
|
STDMETHODIMP CMFBar::SetTimeout(long lTimeout, long lId){
|
|
|
|
if(lTimeout < 0){
|
|
|
|
return(E_INVALIDARG);
|
|
}/* end of if statement */
|
|
|
|
if(!::IsWindow(m_hWnd)){
|
|
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
|
|
if(ID_EV_TIMER == lId){
|
|
|
|
return(E_INVALIDARG);
|
|
}/* end of if statement */
|
|
|
|
if(lTimeout == 0){
|
|
|
|
::KillTimer(m_hWnd, lId);
|
|
}
|
|
else{
|
|
|
|
if(0 != lTimeout){
|
|
|
|
if(0 == ::SetTimer(m_hWnd, lId, lTimeout, NULL)){
|
|
|
|
return(E_FAIL);
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return S_OK;
|
|
}/* end of function SetTimeout */
|
|
|
|
/*************************************************************/
|
|
/* Function: Sleep */
|
|
/*************************************************************/
|
|
STDMETHODIMP CMFBar::Sleep(long lMiliseconds){
|
|
|
|
::Sleep(lMiliseconds);
|
|
|
|
return S_OK;
|
|
}/* end of function Sleep */
|
|
|
|
/*************************************************************/
|
|
/* Name: OnButtonDown
|
|
/* Description: Handles WM_MOUSEDOWN
|
|
/*************************************************************/
|
|
LRESULT CMFBar::OnButtonDown(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
m_ptMouse.x = GET_X_LPARAM(lParam);
|
|
m_ptMouse.y = GET_Y_LPARAM(lParam);
|
|
::ClientToScreen(m_hWnd, &m_ptMouse);
|
|
::SetCapture(m_hWnd);
|
|
SetFocus(TRUE);
|
|
ATLTRACE(TEXT("Button down, starting to track\n"));
|
|
|
|
m_bMouseDown = TRUE;
|
|
|
|
// Test for resize hit region
|
|
::GetWindowRect(m_hWnd, &m_rcWnd);
|
|
m_HitRegion = ResizeHitRegion(m_ptMouse);
|
|
UpdateCursor(m_HitRegion);
|
|
}/* end of if statement */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************/
|
|
/* Name: OnButtonUp
|
|
/* Description: Handles WM_MOUSEUP
|
|
/*************************************************************/
|
|
LRESULT CMFBar::OnButtonUp(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
if(::IsWindow(m_hWnd)){
|
|
|
|
::ReleaseCapture();
|
|
ATLTRACE(TEXT("Done tracking the window\n"));
|
|
m_bMouseDown = false;
|
|
m_HitRegion = ResizeHitRegion(m_ptMouse);
|
|
UpdateCursor(m_HitRegion);
|
|
|
|
}/* end of if statement */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************/
|
|
/* Name: OnMouseMove
|
|
/* Description: Handles WM_MOUSEMOVE
|
|
/*************************************************************/
|
|
LRESULT CMFBar::OnMouseMove(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
|
|
if(::IsWindow(m_hWnd)){
|
|
::GetWindowRect(m_hWnd, &m_rcWnd);
|
|
|
|
POINT ptMouse;
|
|
ptMouse.x = GET_X_LPARAM(lParam);
|
|
ptMouse.y = GET_Y_LPARAM(lParam);
|
|
::ClientToScreen(m_hWnd, &ptMouse);
|
|
|
|
// Test for resize hit region
|
|
int hitRegion = ResizeHitRegion(ptMouse);
|
|
if (!m_bMouseDown)
|
|
UpdateCursor(hitRegion);
|
|
|
|
// No mouse movement, return
|
|
long xAdjustment = m_ptMouse.x - ptMouse.x;
|
|
long yAdjustment = m_ptMouse.y - ptMouse.y;
|
|
if (xAdjustment == 0 && yAdjustment == 0)
|
|
return 0;
|
|
|
|
m_ptMouse = ptMouse;
|
|
// ATLTRACE(TEXT("Mouse pos: %d %d\n"), m_ptMouse.x, m_ptMouse.y);
|
|
|
|
if (m_HitRegion!=NOHIT && m_bMouseDown) {
|
|
long resizeX = m_rcWnd.left;
|
|
long resizeY = m_rcWnd.top;
|
|
long resizeW = RECTWIDTH(&m_rcWnd);
|
|
long resizeH = RECTHEIGHT(&m_rcWnd);
|
|
if (m_HitRegion & LEFT) {
|
|
if (m_rcWnd.right-ptMouse.x >= m_lMinWidth) {
|
|
resizeW = m_rcWnd.right-ptMouse.x;
|
|
resizeX = ptMouse.x;
|
|
}
|
|
else {
|
|
resizeW = m_lMinWidth;
|
|
resizeX = m_rcWnd.right-m_lMinWidth;
|
|
}
|
|
ATLTRACE(TEXT("m_rcWnd right %d\n"), m_rcWnd.right);
|
|
}
|
|
if (m_HitRegion & RIGHT) {
|
|
if (ptMouse.x-m_rcWnd.left >= m_lMinWidth) {
|
|
resizeW = ptMouse.x-m_rcWnd.left;
|
|
}
|
|
else {
|
|
resizeW = m_lMinWidth;
|
|
}
|
|
|
|
}
|
|
if (m_HitRegion & TOP) {
|
|
if (m_rcWnd.bottom-ptMouse.y >= m_lMinHeight) {
|
|
resizeH = m_rcWnd.bottom-ptMouse.y;
|
|
resizeY = ptMouse.y;
|
|
}
|
|
else {
|
|
resizeH = m_lMinHeight;
|
|
resizeY = m_rcWnd.bottom - m_lMinHeight;
|
|
}
|
|
}
|
|
if (m_HitRegion & BOTTOM) {
|
|
if (ptMouse.y-m_rcWnd.top >= m_lMinHeight) {
|
|
resizeH = ptMouse.y-m_rcWnd.top;
|
|
}
|
|
else {
|
|
resizeH = m_lMinHeight;
|
|
}
|
|
}
|
|
|
|
if (resizeW >= m_lMinWidth || resizeH >= m_lMinHeight) {
|
|
|
|
if(NULL != m_pBackBitmap){
|
|
|
|
m_pBackBitmap->DeleteMemDC();
|
|
}/* end of if statement */
|
|
::MoveWindow(m_hWnd, resizeX, resizeY, resizeW, resizeH, TRUE);
|
|
ATLTRACE(TEXT("Resize window to: %d %d %d %d\n"), resizeX, resizeY, resizeX+resizeW, resizeY+resizeH);
|
|
}
|
|
|
|
}/* end of if statement */
|
|
|
|
|
|
else if(m_bMouseDown){
|
|
long x = m_rcWnd.left;
|
|
long y = m_rcWnd.top;
|
|
long width = RECTWIDTH(&m_rcWnd);
|
|
long height = RECTHEIGHT(&m_rcWnd);
|
|
::MoveWindow(m_hWnd, x - xAdjustment, y - yAdjustment, width, height, TRUE);
|
|
ATLTRACE2(atlTraceWindowing, 32, TEXT("Moving the window\n"));
|
|
m_ptMouse = ptMouse;
|
|
}/* end of if statement */
|
|
}/* end of if statement */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************/
|
|
/* Name: ResizeHitRegion */
|
|
/* Description: Test if mouse is in resize hit region */
|
|
/*************************************************************/
|
|
int CMFBar::ResizeHitRegion(POINT p){
|
|
|
|
// TODO: DO NOT HARDCODE THE REGION SIZES
|
|
int hitRegion = NOHIT;
|
|
if (abs(p.x-m_rcWnd.left)<=10) {
|
|
hitRegion |= LEFT;
|
|
}
|
|
else if (abs(p.x-m_rcWnd.right)<=10) {
|
|
hitRegion |= RIGHT;
|
|
}/* end of if statement */
|
|
|
|
if (abs(p.y-m_rcWnd.top)<=10) {
|
|
hitRegion |= TOP;
|
|
}
|
|
else if (abs(p.y-m_rcWnd.bottom)<=10) {
|
|
hitRegion |= BOTTOM;
|
|
}/* end of if statement */
|
|
|
|
return hitRegion;
|
|
}/* end of function ResizeHitRegion */
|
|
|
|
/*************************************************************/
|
|
/* Name: UpdateCursor */
|
|
/* Description: Change cursor shape to move arrows */
|
|
/*************************************************************/
|
|
HRESULT CMFBar::UpdateCursor(int hitRegion){
|
|
|
|
HCURSOR hCursor;
|
|
switch (hitRegion) {
|
|
case LEFT|NOHIT:
|
|
case RIGHT|NOHIT:
|
|
hCursor = ::LoadCursor(0, IDC_SIZEWE);
|
|
break;
|
|
case TOP|NOHIT:
|
|
case BOTTOM|NOHIT:
|
|
hCursor = ::LoadCursor(0, IDC_SIZENS);
|
|
break;
|
|
case LEFT|TOP|NOHIT:
|
|
case RIGHT|BOTTOM|NOHIT:
|
|
hCursor = ::LoadCursor(0, IDC_SIZENWSE);
|
|
break;
|
|
case RIGHT|TOP|NOHIT:
|
|
case LEFT|BOTTOM|NOHIT:
|
|
hCursor = ::LoadCursor(0, IDC_SIZENESW);
|
|
break;
|
|
default:
|
|
hCursor = ::LoadCursor(0, IDC_ARROW);
|
|
break;
|
|
|
|
}/* end of switch statement */
|
|
|
|
::SetCursor(hCursor);
|
|
|
|
return S_OK;
|
|
}/* end of function UpdateCursor */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetObjectFocus */
|
|
/* Description: Sets or resets focus to specific object. */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::SetObjectFocus(BSTR strObjectID, VARIANT_BOOL fEnable){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
CHostedObject* pObj;
|
|
|
|
hr = FindObject(strObjectID, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statetement */
|
|
|
|
LONG lRes = 0;
|
|
|
|
hr = SetObjectFocus(pObj, VARIANT_FALSE == fEnable ? FALSE : TRUE, lRes);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statement */
|
|
|
|
if(-1 == lRes){
|
|
|
|
throw(E_FAIL); // the control did not take the focus since it is disabled
|
|
}/* end of if statement */
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return(hr);
|
|
}/* end of function SetObjectFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: HasObjectFocus */
|
|
/*************************************************************************/
|
|
STDMETHODIMP CMFBar::HasObjectFocus(BSTR strObjectID, VARIANT_BOOL* pfEnable){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
CHostedObject* pObj;
|
|
|
|
hr = FindObject(strObjectID, &pObj);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
throw(hr);
|
|
}/* end of if statetement */
|
|
|
|
*pfEnable = pObj->HasFocus() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
}/* end of try statement */
|
|
catch(HRESULT hrTmp){
|
|
|
|
hr = hrTmp;
|
|
}
|
|
catch(...){
|
|
|
|
hr = E_UNEXPECTED;
|
|
}/* end of catch statement */
|
|
|
|
return(hr);
|
|
}/* end of function HasObjectFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: SetObjectFocus */
|
|
/* Description: Sets or resets focus to specific object. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::SetObjectFocus(CHostedObject* pObj, BOOL fSet, LONG& lRes){
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CContainerObject* pCnt;
|
|
hr = pObj->GetContainerObject(&pCnt);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
return(hr);
|
|
}/* end of if statement */
|
|
|
|
LONG lParam = 0;
|
|
BOOL bHandled = FALSE;
|
|
|
|
if(fSet){
|
|
|
|
ResetFocusFlags(); // reset old focus on other control
|
|
pCnt->SetFocus(TRUE);
|
|
SendMessageToCtl(pObj, WM_SETFOCUS, (WPARAM) m_hWnd, lParam, bHandled, lRes, false);
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Sending WM_SETFOCUS to %ls \n"), pObj->GetID());
|
|
}
|
|
else {
|
|
|
|
pCnt->SetFocus(FALSE); // disable focus and caputure if we are disabeling the object
|
|
SendMessageToCtl(pObj, WM_KILLFOCUS, (WPARAM) m_hWnd, lParam, bHandled, lRes, false);
|
|
|
|
ATLTRACE2(atlTraceUser, 31, TEXT("Sending WM_KILLFOCUS to %ls \n"), pObj->GetID());
|
|
}/* end of if statement */
|
|
|
|
return(hr);
|
|
}/* end of function SetObjectFocus */
|
|
|
|
/*************************************************************************/
|
|
/* Function: FindObject */
|
|
/* Description: Itterates the objects till it finds the one with matching*/
|
|
/* ID. */
|
|
/*************************************************************************/
|
|
HRESULT CMFBar::FindObject(BSTR strObjectID, CHostedObject** ppObj){
|
|
|
|
HRESULT hr = E_FAIL; // did not find the object
|
|
*ppObj = NULL;
|
|
|
|
for(CNTOBJ::iterator i = m_cntObj.begin(); i!= m_cntObj.end(); i++){
|
|
|
|
CHostedObject* pObj = (*i);
|
|
|
|
if(NULL == pObj){
|
|
|
|
continue;
|
|
}/* end of if statement */
|
|
|
|
if(!_wcsicmp(pObj->GetID(), strObjectID)){
|
|
|
|
*ppObj = pObj; // set the pointer and bail out
|
|
hr = S_OK;
|
|
break; // got the unknown get out
|
|
}/* end of if statement */
|
|
}/* end of for loop */
|
|
|
|
return(hr);
|
|
}/* end of function FindObject */
|
|
|
|
/*************************************************************************/
|
|
/* End of file: MFBar.cpp */
|
|
/*************************************************************************/
|