IAutoComplete tutorial
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2

Thread: IAutoComplete tutorial

  1. #1
    Join Date
    Sep 2011
    Posts
    75

    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.

  2. #2
    Join Date
    Sep 2011
    Posts
    75

    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
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center