Hi Ashley,
Your best bet would be to review the ToolWn Sample that ships with the VSIP
SDK. Then use the VSIP Package Wizard (in the New Project's dialog, under
"Other Projects\Extensibility Projects) to create a new VSIP package.
There's an option to create a package that implements a toolwindow.
By default, the wizard throws some code into the package's CreateTool
function, that calls IVsUIShell::CreateToolWindow with the CLSID of an OLE
ActiveX Document.
ToolWindows can host an activex control, an activex document, or you can
implement your own native dialog window by implementing IVsWindowPane. I've
done the latter more than a few times.
Ultimately, I've found that it's pretty easy to use the ATL Wizard support
to add an ATL dialog to your project, and then convert it into a COM object
that derives from IVsWindowPane and IOleCommandTarget. For example:
class CAddRefTestDlg :
public CDialogImpl<CAddRefTestDlg>,
public CComObjectRootEx<CComSingleThreadModel>,
public IVsWindowPane,
public IOleCommandTarget
{
public:
CAddRefTestDlg()
{
}
~CAddRefTestDlg()
{
}
DECLARE_NOT_AGGREGATABLE(CAddRefTestDlg)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CAddRefTestDlg)
COM_INTERFACE_ENTRY(IVsWindowPane)
COM_INTERFACE_ENTRY(IOleCommandTarget)
END_COM_MAP()
BEGIN_MSG_MAP(CAddRefTestDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
END_MSG_MAP()
enum { IDD = IDD_ADDREFTESTDLG };
// dialog methods
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&);
LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&);
LRESULT OnRButtonUp(UINT, WPARAM, LPARAM, BOOL&);
// IVsWindowPane methods
STDMETHOD(SetSite)(IServiceProvider* pSP);
STDMETHOD(CreatePaneWindow)(HWND hwndParent, int x, int y,
int cx, int cy, HWND* phwnd);
STDMETHOD(GetDefaultSize)(SIZE* pSize);
STDMETHOD(ClosePane)(void);
STDMETHOD(LoadViewState)(IStream* pStream);
STDMETHOD(SaveViewState)(IStream* pStream);
STDMETHOD(TranslateAccelerator)(LPMSG lpmsg);
// IOleCommandTarget methods
STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup,ULONG
cCmds,OLECMD prgCmds[],OLECMDTEXT* pCmdText);
STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID,
DWORD nCmdExecOpt, VARIANT* pvaIn, VARIANT* pvaOut);
public:
CComPtr<IServiceProvider> m_srpSiteSP;
CComPtr<IVsWindowFrame> m_srpWindowFrame;
};
Then to use the above class as your toolwindow, you just modify the
CreateTool implementation to look something like the following:
STDMETHODIMP CAddRefTestPackage::CreateTool(/*[in]*/ REFGUID rguid)
{
ATLTRACE(_T("CAddRefTestPackage::CreateTool\n"));
_ASSERTE(!m_fZombie);
USES_CONVERSION;
CComPtr<IVsUIShell> srpUIShell = NULL;
CComObject<CAddRefTestDlg>* spSimpToolWindow = NULL;
if (m_fZombie)
return E_UNEXPECTED;
if (rguid == GUID_guidPersistanceSlot)
{
// now get the IVsUIShell interface so we can create a tool window
//
HRESULT hr = _Module.QueryService(SID_SVsUIShell, IID_IVsUIShell,
(void **)&srpUIShell);
if (SUCCEEDED(hr))
{
hr = CComObject<CAddRefTestDlg>::CreateInstance(&spSimpToolWindow);
if (SUCCEEDED(hr))
{
TCHAR szTitle[128];
if (! ::LoadString(_Module.GetResourceInstance(), IDS_WINDOW_TITLE,
szTitle, countof(szTitle)))
return HRESULT_FROM_WIN32(::GetLastError());
CComQIPtr<IVsWindowPane> srpWindowPane(spSimpToolWindow);
hr = srpUIShell->CreateToolWindow(CTW_fInitNew|CTW_fForceCreate, 0,
srpWindowPane,
GUID_NULL, GUID_guidPersistanceSlot, GUID_NULL, NULL, T2OLE(szTitle),
NULL, &m_srpToolWinFrame);
if (FAILED(hr))
_Module.SetErrorInfo(hr, IDS_E_CANTCREATETOOL, 0);
else
{
spSimpToolWindow->m_srpWindowFrame = m_srpToolWinFrame;
// Set the bitmap for the frame to be the same as the one used for the
menu item
CComVariant srpvt;
srpvt.intVal = IDB_MENU_IMAGES;
m_srpToolWinFrame->SetProperty(VSFPROPID_BitmapResource, srpvt);
srpvt.intVal = 1;
m_srpToolWinFrame->SetProperty(VSFPROPID_BitmapIndex, srpvt);
}
return hr;
}
}
}
return E_INVALIDARG;
}
Note, the difference between the wizard generated code and my code above.
In my code, you create an instance of your dialog object using:
hr = CComObject<CAddRefTestDlg>::CreateInstance(&spSimpToolWindow);
Then you retrieve it's IVsWindowPane interface and pass this to the
IVsUIShell::CreateToolWindow function, instead of that clsid param.
Sincerely,
Ed Dore [MSFT]
This post is 'AS IS' with no warranties and confers no rights.