April 17th, 2012, 09:43 AM
#1
IAutoComplete tutorial
Hi All,
I have been using this tutorial to implement Auto completion in one of my text boxes. However I don't understand what they mean by Implementing IEnumString...
I've looked at this link http://www.codeproject.com/Articles/...-implementatio and they skip the actual reasoning and explanation of the implementation. I guess it is just my unfamiliarity with Interfaces in general. You take a new object (say CCustomAutoComplete) and implement the following functions as (public/private?) functions:
Clone(), Next(), Reset(), Skip()
the question is... how do you know how they are implemented? is each CCustomAutoComplete just a string that links to another CCustomAutoComplete (like a linked list?) Can I use TCHARS?
Thanks for the help.. I'm quite clueless on COM and OOP
MSDN Tutorial:
http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
UPDATE:
I've created a skeleton for the new class:
My questions are:
1) am I on the right track here? Am I even defining this class correctly, and do i need more auxiliary functions and members and what not?
2) Is it OK to create the object using a pointer to an array of TCHAR arrays (essentially a TCHAR **)?
3) How does memory allocation work in this case?
4) Do I even need the COM IUnknown implementation if this is just a simple enumString implementation (I don't think IenumString is derived from IUnknown).
I probably have more questions but I can't think of anymore right now. I would also like to stick with a simple TCHAR implementation of this...
Code:
// custom auto complete
class CCustomAutoComplete : public IEnumString
{
private:
// Private members
TCHAR m_CurrList[256][64];
ULONG m_nCurrentElement;
ULONG m_nRefCount;
BOOL m_fBound;
public:
// Constructors/destructors
CCustomAutoComplete()
{
InternalInit();
}
CCustomAutoComplete(TCHAR ** p_ArrayList)
{
InternalInit();
SetList(p_ArrayList);
}
~CCustomAutoComplete()
{
// free array...?
}
public:
// Implementation
BOOL SetList(TCHAR ** p_ArrayList)
{
return TRUE;
}
BOOL AddItem(TCHAR * p_Item)
{
return TRUE;
}
BOOL RemoveItem(TCHAR * p_RemoveItem)
{
return TRUE;
}
BOOL Clear()
{
return TRUE;
}
public:
//
// IUnknown implementation
//
STDMETHODIMP_(ULONG) AddRef()
{
return ::InterlockedIncrement(reinterpret_cast<LONG*>(&m_nRefCount));
}
STDMETHODIMP_(ULONG) Release()
{
ULONG nCount = 0;
nCount = (ULONG) ::InterlockedDecrement(reinterpret_cast<LONG*>(&m_nRefCount));
if (nCount == 0)
delete this;
return nCount;
}
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
{
HRESULT hr = E_NOINTERFACE;
if (ppvObject != NULL)
{
*ppvObject = NULL;
if (IID_IUnknown == riid)
*ppvObject = static_cast<IUnknown*>(this);
if (IID_IEnumString == riid)
*ppvObject = static_cast<IEnumString*>(this);
if (*ppvObject != NULL)
{
hr = S_OK;
((LPUNKNOWN)*ppvObject)->AddRef();
}
}
else
{
hr = E_POINTER;
}
return hr;
}
public:
//
// IEnumString implementation
//
STDMETHODIMP Next(ULONG celt, LPOLESTR* rgelt, ULONG* pceltFetched)
{
return S_OK;
}
STDMETHODIMP Skip(ULONG celt)
{
return S_OK;
}
STDMETHODIMP Reset(void)
{
return S_OK;
}
STDMETHODIMP Clone(IEnumString** ppenum)
{
return S_OK;
}
private:
// Internal implementation
void InternalInit()
{
m_nCurrentElement = 0;
m_nRefCount = 0;
m_fBound = FALSE;
}
};
Last edited by kingting; April 17th, 2012 at 05:15 PM .
April 18th, 2012, 12:55 PM
#2
Re: IAutoComplete tutorial
I think I have it implemented and everything creates properly. When I place a break point at the CCustomAutoComplete::Next() it returns a string, however I do not see anything appear.... any thoughts?
UPDATE:
Code:
// custom auto complete
class CCustomAutoComplete : public IEnumString
{
private:
TCHAR **m_CurrList;
// Private members
ULONG m_nLastElement;
ULONG m_nCurrentElement;
ULONG m_nRefCount;
BOOL m_fBound;
CComPtr<IAutoComplete> m_pac;
public:
// Constructors/destructors
CCustomAutoComplete()
{
Clear();
InternalInit();
}
CCustomAutoComplete(TCHAR ** p_ArrayList)
{
m_CurrList = (TCHAR**)malloc(sizeof(TCHAR *)*256);
for(int i = 0; i <256; i++)
{
m_CurrList[i] = (TCHAR *)malloc(sizeof(TCHAR)*256);
ZeroMemory(m_CurrList[i], sizeof(TCHAR)*256);
}
InternalInit();
Clear();
SetList(p_ArrayList);
}
~CCustomAutoComplete()
{
for(int i = 0; i <256; i++)
{
free(m_CurrList[i]);
m_CurrList[i] = NULL;
}
free(m_CurrList);
}
public:
// Implementation
BOOL Bind(HWND p_hWndEdit, DWORD p_dwOptions = 0, LPCTSTR p_lpszFormatString = NULL)
{
ATLASSERT(::IsWindow(p_hWndEdit));
if ((m_fBound) || (m_pac))
return FALSE;
HRESULT hr = S_OK;
hr = m_pac.CoCreateInstance(CLSID_AutoComplete);
if (SUCCEEDED(hr))
{
if (p_dwOptions)
{
CComQIPtr<IAutoComplete2> pAC2(m_pac);
ATLASSERT(pAC2);
hr = pAC2->SetOptions(p_dwOptions); // This never fails?
pAC2.Release();
}
hr = m_pac->Init(p_hWndEdit, this, NULL, p_lpszFormatString);
if (SUCCEEDED(hr))
{
m_fBound = TRUE;
return TRUE;
}
}
return FALSE;
}
VOID Unbind()
{
if (!m_fBound)
return;
ATLASSERT(m_pac);
if (m_pac)
{
m_pac.Release();
m_fBound = FALSE;
}
}
BOOL SetList(TCHAR ** p_ArrayList)
{
Clear();
for(int i = 0; i < 256; i++)
{
_tcscpy(m_CurrList[i],p_ArrayList[i]);
}
return TRUE;
}
BOOL AddItem(TCHAR * p_Item)
{
for(int i = 0; i < 256; i++)
{
if(!_tcscmp(p_Item, m_CurrList[i]))
return FALSE;
}
_tcscpy(m_CurrList[m_nLastElement], p_Item);
m_nLastElement++;
return TRUE;
}
BOOL RemoveItem(TCHAR * p_RemoveItem)
{
return TRUE;
}
BOOL Clear()
{
for(int i = 0; i < 256; i++)
ZeroMemory(m_CurrList[i],256);
m_nLastElement = 0;
m_nCurrentElement = 0;
return TRUE;
}
public:
//
// IUnknown implementation
//
STDMETHODIMP_(ULONG) AddRef()
{
return ::InterlockedIncrement(reinterpret_cast<LONG*>(&m_nRefCount));
}
STDMETHODIMP_(ULONG) Release()
{
ULONG nCount = 0;
nCount = (ULONG) ::InterlockedDecrement(reinterpret_cast<LONG*>(&m_nRefCount));
if (nCount == 0)
delete this;
return nCount;
}
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
{
HRESULT hr = E_NOINTERFACE;
if (ppvObject != NULL)
{
*ppvObject = NULL;
if (IID_IUnknown == riid)
*ppvObject = static_cast<IUnknown*>(this);
if (IID_IEnumString == riid)
*ppvObject = static_cast<IEnumString*>(this);
if (*ppvObject != NULL)
{
hr = S_OK;
((LPUNKNOWN)*ppvObject)->AddRef();
}
}
else
{
hr = E_POINTER;
}
return hr;
}
public:
//
// IEnumString implementation
//
STDMETHODIMP Next(ULONG celt, LPOLESTR* rgelt, ULONG* pceltFetched)
{
HRESULT hr = S_FALSE;
if (!celt)
celt = 1;
ULONG celtFetched = 0;
pceltFetched = &celtFetched;
for (ULONG i = 0; i < celt; i++)
{
if (m_nCurrentElement == (ULONG)m_nLastElement+1)
break;
rgelt[i] = (LPWSTR)::CoTaskMemAlloc((ULONG) sizeof(TCHAR) * (256));
lstrcpy(rgelt[i],m_CurrList[m_nCurrentElement]);
if (pceltFetched)
celtFetched++;
m_nCurrentElement++;
if (i == celt)
hr = S_OK;
}
return hr;
}
STDMETHODIMP Skip(ULONG celt)
{
m_nCurrentElement += celt;
if (m_nCurrentElement > m_nLastElement)
m_nCurrentElement = 0;
return S_OK;
}
STDMETHODIMP Reset(void)
{
m_nCurrentElement = 0;
return S_OK;
}
STDMETHODIMP Clone(IEnumString** ppenum)
{
if (!ppenum)
return E_POINTER;
CCustomAutoComplete* pnew = new CCustomAutoComplete();
pnew->AddRef();
*ppenum = pnew;
return S_OK;
}
private:
// Internal implementation
void InternalInit()
{
m_nCurrentElement = 0;
m_nRefCount = 0;
m_fBound = FALSE;
m_nLastElement = 0;
}
};
Here is how I use it...
Code:
// Initialize Autocomplete object and source object
IAutoComplete *pac;
HRESULT hr = CoCreateInstance(CLSID_AutoComplete,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pac));
// case
IUnknown *punkSource;
/* CUSTOM STRING CODE*/
TCHAR **commandsArray = (TCHAR**)malloc(sizeof(TCHAR *)*256);
for(int i = 0; i <256; i++)
{
commandsArray[i] = (TCHAR *)malloc(sizeof(TCHAR)*256);
ZeroMemory(commandsArray[i], sizeof(TCHAR)*256);
}
_tcscpy(commandsArray[0],_T("CUBE <name>, <width>, <height>, <length>"));
_tcscpy(commandsArray[1],_T("adasdasdas <name>, <width>, <height>, <length>"));
_tcscpy(commandsArray[2],_T("JESUSs <name>, <width>, <height>, <length>"));
_tcscpy(commandsArray[3],_T("RECTANGLE <name>, <width>, <height>, <length>"));
_tcscpy(commandsArray[4],_T("SKETCASDSAHD <name>, <width>, <height>, <length>"));
_tcscpy(commandsArray[5],_T("WAASDASDASD"));
CCustomAutoComplete *pes = new CCustomAutoComplete(commandsArray);
hr = pes->QueryInterface(IID_PPV_ARGS(&punkSource));
// initialize the IUnknown Interface
hr = pes->QueryInterface(IID_PPV_ARGS(&punkSource));
if(!SUCCEEDED(hr))
{
return 0;// ...
}
// release objects
for(int i = 0; i <256; i++)
{
if(commandsArray[i])
free(commandsArray[i]);
commandsArray[i] = NULL;
}
free(commandsArray);
hr = pac->Init(GetDlgItem(hwndTabCtrl,IDC_CONSOLE), punkSource, NULL, NULL);
IAutoComplete2 *pac2;
hr = pac->QueryInterface(IID_PPV_ARGS(&pac2));
if (SUCCEEDED(hr))
{
hr = pac2->SetOptions(ACO_AUTOSUGGEST|ACO_AUTOAPPEND);
}
Here is another implementation that also does not work
Code:
// Initialize Autocomplete object and source object
IAutoComplete *pac;
HRESULT hr = CoCreateInstance(CLSID_AutoComplete,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pac));
// case
IUnknown *punkSource;
/* CUSTOM STRING CODE*/
// INITIALIZE STRINGS
LPOLESTR newArr[6] = {_T("CUBE <name>, <width>, <height>, <length>"),
_T("adasdasdas <name>, <width>, <height>, <length>"),
_T("JESUSs <name>, <width>, <height>, <length>"),
_T("RECTANGLE <name>, <width>, <height>, <length>"),
_T("SKETCASDSAHD <name>, <width>, <height>, <length>"),
_T("WAASDASDASD")};
CComObject<CComEnumString> *pes = 0;
hr = CComObject<CComEnumString>::CreateInstance( &pes); // CRASH HERE
pes->AddRef();
pes->Init(newArr,&newArr[6],NULL,AtlFlagNoCopy);
// initialize the IUnknown Interface
hr = pes->QueryInterface(IID_PPV_ARGS(&punkSource));
if(!SUCCEEDED(hr))
{
return 0;// ...
}
// release objects
for(int i = 0; i <256; i++)
{
if(commandsArray[i])
free(commandsArray[i]);
commandsArray[i] = NULL;
}
free(commandsArray);
hr = pac->Init(GetDlgItem(hwndTabCtrl,IDC_CONSOLE), punkSource, NULL, NULL);
IAutoComplete2 *pac2;
hr = pac->QueryInterface(IID_PPV_ARGS(&pac2));
if (SUCCEEDED(hr))
{
hr = pac2->SetOptions(ACO_AUTOSUGGEST|ACO_AUTOAPPEND);
}
However the program crashes on the CreateInstance call as shown in the code....
I appreciate any help I can get on this....
Last edited by kingting; April 19th, 2012 at 04:18 PM .
Posting Permissions
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
Forum Rules
Click Here to Expand Forum to Full Width
Bookmarks