-
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
|