You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
746 lines
21 KiB
746 lines
21 KiB
#include "private.h"
|
|
#include "sapilayr.h"
|
|
#include "globals.h"
|
|
#include "lbarsink.h"
|
|
#include "immxutil.h"
|
|
#include "mui.h"
|
|
#include "slbarid.h"
|
|
#include "nui.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLangBarSink
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IUnknown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CLangBarSink::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfLangBarEventSink))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarEventSink *);
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDAPI_(ULONG) CLangBarSink::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
STDAPI_(ULONG) CLangBarSink::Release()
|
|
{
|
|
m_cRef--;
|
|
Assert(m_cRef >= 0);
|
|
|
|
if (m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return m_cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CLangBarSink::CLangBarSink(CSpTask *pSpTask)
|
|
{
|
|
Dbg_MemSetThisName(TEXT("CLangBarSink"));
|
|
|
|
Assert(pSpTask);
|
|
|
|
m_pSpTask = pSpTask;
|
|
m_pSpTask->AddRef();
|
|
|
|
m_nNumItem = 0;
|
|
m_fInitSink = FALSE;
|
|
m_fPosted = FALSE;
|
|
m_fGrammarBuiltOut = FALSE;
|
|
|
|
m_hDynRule = NULL;
|
|
|
|
m_cRef = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CLangBarSink::~CLangBarSink()
|
|
{
|
|
if (m_cplbm)
|
|
{
|
|
m_cplbm->UnadviseEventSink(m_dwlbimCookie);
|
|
}
|
|
_UninitItemList();
|
|
SafeRelease(m_pSpTask);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CLangBarSink::OnSetFocus(DWORD dwThreadId)
|
|
{
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::OnSetFocus, dwThreadId=%d",dwThreadId);
|
|
|
|
if (m_fPosted == TRUE) return S_OK;
|
|
|
|
HWND hwnd = m_pSpTask->GetTip()->_GetWorkerWnd();
|
|
if (hwnd)
|
|
{
|
|
PostMessage(hwnd, WM_PRIV_LBARSETFOCUS, 0, 0);
|
|
m_fPosted = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
HRESULT CLangBarSink::_OnSetFocus()
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
CSapiIMX *pime = m_pSpTask->GetTip();
|
|
|
|
TraceMsg(TF_LB_SINK, "LBSINK: _OnSetFocus is called back");
|
|
|
|
if ( !pime )
|
|
return E_FAIL;
|
|
|
|
// this _tim check is needed because on Win98 the worker window's
|
|
// winproc may get called after the window is destroyed.
|
|
// In theory we should be ok since we destory the window which calls
|
|
// _OnSetFocus() via private message before we release tim
|
|
//
|
|
if (pime->_tim &&
|
|
pime->IsActiveThread() == S_OK)
|
|
{
|
|
// do we have to do anything?
|
|
hr = _InitItemList();
|
|
BOOL fCmdOn;
|
|
|
|
fCmdOn = pime->GetOnOff( ) && pime->GetDICTATIONSTAT_CommandingOnOff( );
|
|
|
|
// the dynamic toolbar grammar is available only for Voice command mode.
|
|
if ( fCmdOn && pime->_LanguageBarCmdEnabled( ))
|
|
{
|
|
if (hr==S_OK && !m_fGrammarBuiltOut && pime->_IsDictationActiveForLang(GetPlatformResourceLangID()))
|
|
{
|
|
// build C/C grammar
|
|
hr = _BuildGrammar();
|
|
_ActivateGrammar(TRUE);
|
|
}
|
|
}
|
|
}
|
|
m_fPosted = FALSE;
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ThreadTerminate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CLangBarSink::OnThreadTerminate(DWORD dwThreadId)
|
|
{
|
|
//
|
|
// check if the thread is us, release the dynamic grammar object
|
|
// via sptask
|
|
//
|
|
_UninitItemList();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnThreadItemChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CLangBarSink::OnThreadItemChange(DWORD dwThreadId)
|
|
{
|
|
//PerfConsider: This is called many times when assembly changes
|
|
// This will be corrected in the future but for now
|
|
// we re-initialize unnecessary things again/again.
|
|
|
|
// check if the thread is us,
|
|
// to un-initialize the grammar then rebuild the one
|
|
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::OnThreadItemChange, dwThreadId=%d", dwThreadId);
|
|
|
|
_UninitItemList();
|
|
|
|
OnSetFocus(dwThreadId);
|
|
|
|
// call sptask to rebuild grammar here
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CLangBarSink::Init()
|
|
{
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::Init is called");
|
|
|
|
HRESULT hr = _EnsureLangBarMgrs();
|
|
|
|
if (!m_fInitSink)
|
|
{
|
|
// the sink leaks if we call this twice
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_cplbm->AdviseEventSink(this, NULL, 0, &m_dwlbimCookie);
|
|
}
|
|
m_fInitSink = TRUE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Uninit
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CLangBarSink::Uninit()
|
|
{
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::Uninit is called");
|
|
if (m_cplbm)
|
|
{
|
|
m_cplbm->UnadviseEventSink(m_dwlbimCookie);
|
|
m_cplbm.Release();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _EnsureLangBarMgrs
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CLangBarSink::_EnsureLangBarMgrs()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::_EnsureLangBarMgrs is called");
|
|
|
|
if (!m_cplbm)
|
|
{
|
|
hr = TF_CreateLangBarMgr(&m_cplbm);
|
|
}
|
|
|
|
if (S_OK == hr && !m_cplbim)
|
|
{
|
|
DWORD dw;
|
|
hr = m_cplbm->GetThreadLangBarItemMgr(GetCurrentThreadId(), &m_cplbim, &dw);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AddLBarItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CLangBarSink::_AddLBarItem(ITfLangBarItem *plbItem)
|
|
{
|
|
if (plbItem)
|
|
{
|
|
int nCnt = m_rgItem.Count();
|
|
if (m_rgItem.Insert(nCnt, 1))
|
|
{
|
|
plbItem->AddRef();
|
|
m_rgItem.Set(nCnt, plbItem);
|
|
m_nNumItem++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _InitItemList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CLangBarSink::_InitItemList()
|
|
{
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::_InitItemList is called");
|
|
|
|
if (0 != m_nNumItem)
|
|
{
|
|
TraceMsg(TF_LB_SINK, "m_nNumItem=%d, Don't continue InitItemList",m_nNumItem);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IEnumTfLangBarItems> cpEnum;
|
|
|
|
Assert(m_cplbim);
|
|
|
|
if (SUCCEEDED(hr = m_cplbim->EnumItems(&cpEnum)))
|
|
{
|
|
ITfLangBarItem * plbi;
|
|
while (S_OK == cpEnum->Next(1, &plbi, NULL))
|
|
{
|
|
hr = S_OK; // OK if there's at least one
|
|
DWORD dwStatus;
|
|
plbi->GetStatus(&dwStatus);
|
|
|
|
// add buttons that are not diabled or hidden
|
|
if ((dwStatus & (TF_LBI_STATUS_HIDDEN|TF_LBI_STATUS_DISABLED))==0)
|
|
{
|
|
_AddLBarItem(plbi);
|
|
}
|
|
plbi->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UninitItemList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CLangBarSink::_UninitItemList()
|
|
{
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::_UninitItemList is called");
|
|
|
|
if (int nCnt = m_rgItem.Count())
|
|
{
|
|
int i = 0;
|
|
while (i < nCnt)
|
|
{
|
|
ITfLangBarItem * plbi = m_rgItem.Get(i);
|
|
if (plbi)
|
|
plbi->Release();
|
|
i++;
|
|
}
|
|
m_rgItem.Clear();
|
|
}
|
|
|
|
m_nNumItem = 0;
|
|
_UnloadGrammar();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _BuildGrammar
|
|
//
|
|
// synopsis: build a C&C grammar based on text labels of langbar
|
|
// items
|
|
//
|
|
// BuildGrammar( ) works only when the mode is in Voice command mode.
|
|
//
|
|
// we have make sure only when voice command is ON and dictation command
|
|
// is enabled, this function is called.
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CLangBarSink::_BuildGrammar()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
// get sptask and create a grammar
|
|
|
|
TraceMsg(TF_LB_SINK, "_BuildGrammar is called");
|
|
if (m_pSpTask)
|
|
{
|
|
CComPtr<ISpRecoContext> cpReco;
|
|
|
|
// get the grammar loaded to the dictation reco context
|
|
//
|
|
// it will use the Voice command mode recon context.
|
|
|
|
hr = m_pSpTask->GetRecoContextForCommand(&cpReco);
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: GetRecoContextForCommand, hr=%x", hr);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// we don't need to re-create grammar object
|
|
if (!m_cpSpGrammar)
|
|
{
|
|
hr = cpReco->CreateGrammar(GRAM_ID_TBCMD, &m_cpSpGrammar);
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: Create TOOLBar Grammar");
|
|
}
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_cpSpGrammar->ResetGrammar(GetPlatformResourceLangID());
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: ResetGrammar");
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
// get the rule handle
|
|
m_cpSpGrammar->GetRule(GetToolbarCommandRuleName(), RULE_ID_TBCMD, SPRAF_TopLevel|SPRAF_Active|SPRAF_Dynamic, TRUE, &m_hDynRule);
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar:Get Rule Handle");
|
|
|
|
// then activate the rule
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// enumerate all the buttons,
|
|
// see if they are either ITfLangBarItemBitmapButton
|
|
// or ITfLangBarItemButton, that have OnClick method on them
|
|
BSTR bstr;
|
|
int nBtns = m_rgItem.Count();
|
|
|
|
for (int i = 0; i < nBtns; i++)
|
|
{
|
|
GUID guidItem;
|
|
|
|
if (_GetButtonText(i, &bstr, &guidItem) && bstr)
|
|
{
|
|
// item and property
|
|
// the item can include optional string (?please etc)
|
|
// if (_IsItemEnabledForCommand(guidItem))
|
|
|
|
if ( !IsEqualGUID(guidItem, GUID_LBI_SAPILAYR_COMMANDING) )
|
|
{
|
|
SPPROPERTYINFO pi = {0};
|
|
pi.pszName = bstr;
|
|
m_cpSpGrammar->AddWordTransition(m_hDynRule, NULL, bstr, L" ", SPWT_LEXICAL, (float)1.01, &pi);
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: button %S added to grammar", bstr);
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
}
|
|
}
|
|
//
|
|
// add a bogus string that has significant weight so we out weight
|
|
// others
|
|
//
|
|
SPPROPERTYINFO pi = {0};
|
|
const WCHAR c_szBogus[] = L"zhoulotskunosprok";
|
|
|
|
pi.pszName = c_szBogus;
|
|
m_cpSpGrammar->AddWordTransition(m_hDynRule, NULL, c_szBogus, L" ", SPWT_LEXICAL, (float)1000.01, &pi);
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: start commit ...");
|
|
m_cpSpGrammar->Commit(0);
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar:Done commit ...");
|
|
|
|
m_fGrammarBuiltOut = TRUE;
|
|
}
|
|
}
|
|
|
|
TraceMsg(TF_LB_SINK, "_BuildGrammar is done!!!!");
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UnloadGrammar
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CLangBarSink::_UnloadGrammar()
|
|
{
|
|
// clear the rule
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceMsg(TF_LB_SINK, "CLangBarSink::_UnloadGrammar is called");
|
|
|
|
if (m_cpSpGrammar)
|
|
{
|
|
hr = _ActivateGrammar(FALSE);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_cpSpGrammar->ClearRule(m_hDynRule);
|
|
|
|
if ( hr == S_OK )
|
|
m_fGrammarBuiltOut = FALSE; // Next time, the grammar needs to be rebuilt.
|
|
}
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _ActivateGrammar
|
|
//
|
|
// synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CLangBarSink::_ActivateGrammar(BOOL fActive)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: ActivateGrammar=%d", fActive);
|
|
|
|
if (m_cpSpGrammar)
|
|
{
|
|
m_cpSpGrammar->SetRuleState(GetToolbarCommandRuleName(), NULL, fActive ? SPRS_ACTIVE : SPRS_INACTIVE);
|
|
}
|
|
|
|
TraceMsg(TF_LB_SINK, "TBarGrammar: ActivateGrammar is done");
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ProcessToolBarCommand
|
|
//
|
|
// When return value is TRUE, there is corresponding button on the toolbar
|
|
// otherwise the return value is FALSE
|
|
//----------------------------------------------------------------------------
|
|
BOOL CLangBarSink::ProcessToolbarCmd(const WCHAR *szProperty)
|
|
{
|
|
BOOL fRet=FALSE;
|
|
|
|
Assert(szProperty);
|
|
|
|
// go through items in the array and call onclick method
|
|
// if there is a match
|
|
if (szProperty)
|
|
{
|
|
int nBtns = m_rgItem.Count();
|
|
|
|
for (int i = 0; i < nBtns; i++)
|
|
{
|
|
BSTR bstr;
|
|
if (_GetButtonText(i, &bstr, NULL) && bstr)
|
|
{
|
|
if (0 == wcscmp(szProperty, bstr))
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CComPtr<ITfLangBarItemButton> cplbiBtn ;
|
|
CComPtr<ITfLangBarItemBitmapButton> cplbiBmpBtn ;
|
|
POINT pt = {0, 0};
|
|
ITfLangBarItem * plbi = m_rgItem.Get(i);
|
|
if (plbi)
|
|
{
|
|
hr = plbi->QueryInterface(IID_ITfLangBarItemButton, (void **)&cplbiBtn);
|
|
#ifndef TOOLBAR_CMD_FOR_MENUS
|
|
// this code removes the toolbar command from thoese
|
|
// items with menus
|
|
|
|
TF_LANGBARITEMINFO info;
|
|
if (S_OK == hr)
|
|
{
|
|
hr = plbi->GetInfo(&info);
|
|
}
|
|
if (info.dwStyle & TF_LBI_STYLE_BTN_MENU)
|
|
{
|
|
// do not click on buttons with menu items
|
|
// since we don't hanle commands for the items
|
|
}
|
|
else
|
|
#endif
|
|
if (S_OK == hr)
|
|
{
|
|
// is it OK to call OnClick without specifying rect?
|
|
hr = cplbiBtn->OnClick(TF_LBI_CLK_LEFT, pt, NULL);
|
|
|
|
// OnClick would start a new edit session for some buttons, such
|
|
// as "Correction"
|
|
//
|
|
// The return value could be TS_S_ASYNC or S_OK depends on how
|
|
// the application grants the edit request.
|
|
//
|
|
// We need to check if the hr value is successful.
|
|
// not only S_OK.
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
fRet = TRUE;
|
|
}
|
|
#ifdef TOOLBAR_CMD_FOR_MENUS
|
|
TF_LANGBARITEMINFO info;
|
|
RECT rc = {0};
|
|
if (S_OK == hr)
|
|
{
|
|
hr = plbi->GetInfo(&info);
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_cplbim->GetItemFloatingRect(0, info.guidItem, &rc);
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
HWND hwnd = FindWindow(NULL, TF_FLOATINGLANGBAR_WNDTITLEA);
|
|
if (hwnd)
|
|
{
|
|
DWORD dw;
|
|
POINT poi;
|
|
|
|
poi.x = (rc.right + rc.left)/2,
|
|
poi.y = (rc.top + rc.bottom)/2,
|
|
|
|
::ScreenToClient(hwnd, &poi);
|
|
|
|
dw = MAKELONG(LOWORD(poi.x), LOWORD(poi.y));
|
|
|
|
PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, dw);
|
|
PostMessage(hwnd, WM_LBUTTONUP, 0, dw);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (!cplbiBtn)
|
|
{
|
|
hr = plbi->QueryInterface(IID_ITfLangBarItemBitmapButton, (void **)&cplbiBmpBtn);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = cplbiBtn->OnClick(TF_LBI_CLK_LEFT, pt, NULL);
|
|
|
|
if ( S_OK == hr )
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
} // if (0 == wcscmpi(szProperty, bstr))
|
|
|
|
SysFreeString(bstr);
|
|
} // if (_GetButtonText(i, bstr))
|
|
|
|
} // for
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetButtonText
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL CLangBarSink::_GetButtonText(int iBtn, BSTR *pbstr, GUID *pguid)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CComPtr<ITfLangBarItemButton> cplbiBtn ;
|
|
CComPtr<ITfLangBarItemBitmapButton> cplbiBmpBtn ;
|
|
|
|
Assert(iBtn < m_rgItem.Count());
|
|
Assert(pbstr);
|
|
*pbstr = NULL;
|
|
|
|
ITfLangBarItem * plbi = m_rgItem.Get(iBtn);
|
|
|
|
|
|
if (plbi)
|
|
{
|
|
hr = plbi->QueryInterface(IID_ITfLangBarItemButton, (void **)&cplbiBtn);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = cplbiBtn->GetTooltipString(pbstr);
|
|
}
|
|
}
|
|
// only in case when the button does not have a
|
|
// regular interface we'd qi for bitmapbutton
|
|
if (!cplbiBtn)
|
|
{
|
|
hr = plbi->QueryInterface(IID_ITfLangBarItemBitmapButton, (void **)&cplbiBmpBtn);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = cplbiBmpBtn->GetTooltipString(pbstr);
|
|
}
|
|
}
|
|
|
|
TF_LANGBARITEMINFO Info = {0};
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = plbi->GetInfo(&Info);
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
if (pguid)
|
|
{
|
|
memcpy(pguid, &(Info.guidItem), sizeof(GUID));
|
|
}
|
|
|
|
if (Info.dwStyle & TF_LBI_STYLE_BTN_MENU)
|
|
{
|
|
// do not create commands for buttons with menu items
|
|
// since we don't hanle commands for the items
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr && *pbstr)
|
|
{
|
|
// avoid mem leak
|
|
SysFreeString(*pbstr);
|
|
}
|
|
|
|
return S_OK == hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnModalInput
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CLangBarSink::OnModalInput(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ShowFloating
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CLangBarSink::ShowFloating(DWORD dwFlags)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetItemFloatingRect
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CLangBarSink::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|