Listing 1: PBNISetWindowHook.h

BOOL WINAPI DllMain
(
  HANDLE hInst, 
  ULONG ul_reason_for_call,
  LPVOID lpReserved
) ;

PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription();

PBXEXPORT PBXRESULT PBXCALL PBX_CreateNonVisualObject
(
	IPB_Session*	pbsession,
	pbobject		pbobj,
	LPCTSTR			ClassName,
	IPBX_NonVisualObject	**obj
);

class CPBNISetWindowHook : public IPBX_NonVisualObject
{
virtual void Destroy();

public:
  CPBNISetWindowHook();
  CPBNISetWindowHook(IPB_Session* pIPB_Session, 
    pbobject pbobj);
  ~CPBNISetWindowHook();

  PBXRESULT CPBNISetWindowHook::Register
  (
    IPB_Session	*session, 
    pbobject	obj, 
    PBCallInfo	*ci
  ) ;

  PBXRESULT CPBNISetWindowHook::FilterFileTypes
  (
    IPB_Session	*session, 
    pbobject	obj, 
    PBCallInfo	*ci
  ) ;

  PBXRESULT CPBNISetWindowHook::SetDefaultFileType
  (
    IPB_Session	*session, 
    pbobject	obj, 
    PBCallInfo	*ci
  ) ;

  PBXRESULT Invoke
  (
    IPB_Session	*session, 
	pbobject	obj, 
	pbmethodID mid,
	PBCallInfo	*ci
  );
 
};

HHOOK	hHook ;
IPB_Session*	m_pSession; 
pbobject		m_pbobject ;
pbarray		m_filetypes = NULL ;
LPSTR		m_default  = NULL ;

LRESULT CALLBACK DialogHook(  
    int nCode,
    WPARAM wParam,
    LPARAM lParam
);

Listing 2: PBNISetWindowHook.cpp

#include <pbext.h>
#include "PBNISetWindowHook.H"

BOOL WINAPI DllMain
(
  HANDLE hInst, 
  ULONG ul_reason_for_call,
  LPVOID lpReserved
)
{
  return TRUE;
}

PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription()
{
  static const TCHAR class_descs[] = 
  {
    "class CustomSaveAs from nonvisualobject\n"
	"function long Register ( long windowHandle )\n"
	"function long FilterFileTypes ( string fileTypes[] )\n"
	"function long SetDefaultFileType ( string fileType )\n"
	"end class\n" 
  };

  return class_descs;
}

PBXEXPORT PBXRESULT PBXCALL PBX_CreateNonVisualObject
(
	IPB_Session*	pbsession,
	pbobject		pbobj,
	LPCTSTR		ClassName,
	IPBX_NonVisualObject	**obj
)
{
  PBXRESULT pbxResult = PBX_OK;

  if (stricmp(ClassName, TEXT("CustomSaveAs")) == 0)
  {
    CPBNISetWindowHook* pCPBNISetWindowHook = NULL;
    pCPBNISetWindowHook = new CPBNISetWindowHook(pbsession, 
       pbobj);
    *obj = (IPBX_NonVisualObject*)pCPBNISetWindowHook;
  }
  else
  {
    *obj = NULL;
    pbxResult = PBX_E_NO_SUCH_CLASS;
  }

  return pbxResult;
}

enum MethodIDs
{
REGISTER = 0,
FILTERFILETYPES = 1,
	SETDEFAULTFILETYPE = 2,
	ENTRYCOUNT
};

CPBNISetWindowHook::CPBNISetWindowHook()
{
}

CPBNISetWindowHook::CPBNISetWindowHook(IPB_Session* 
  pIPB_Session, pbobject pbobj)
{
	m_pSession = pIPB_Session;
	m_pbobject = pbobj;
}

CPBNISetWindowHook::~CPBNISetWindowHook()
{
}

PBXRESULT CPBNISetWindowHook::Register
(
  IPB_Session	*session, 
  pbobject	obj, 
  PBCallInfo	*ci
)
{
  PBXRESULT pbrRet = PBX_OK;

  HWND hWindow ;
  DWORD hInstance ;
  DWORD hThreadID ;

  hWindow = (HWND)ci->pArgs->GetAt(0)->GetLong() ;

  hInstance = GetWindowLong ( hWindow, GWL_HINSTANCE ) ;
  hThreadID = GetCurrentThreadId() ;
  
  hHook = SetWindowsHookEx ( WH_CALLWNDPROCRET, DialogHook, 
   (HINSTANCE)hInstance, hThreadID ) ;

  ci -> returnValue -> SetLong((pblong)0);

  return pbrRet;
}

PBXRESULT CPBNISetWindowHook::FilterFileTypes
(
  IPB_Session	*session, 
  pbobject	obj, 
  PBCallInfo	*ci
)
{
  PBXRESULT pbrRet = PBX_OK;

  if ( ci->pArgs->GetAt(0)->IsNull() )
  {
	pbrRet = PBX_E_INVALID_ARGUMENT ;
  }
  else if ( !ci->pArgs->GetAt(0)->IsArray() )
  {
	pbrRet = PBX_E_INVALID_ARGUMENT;
  }
  else
  {
	int		pArrayItemCount ;
	pblong			dim[1] ;
	IPB_Value*		ipv ;
	int			i ;

	m_filetypes = m_pSession->NewUnboundedSimpleArray( 
  pbvalue_string ) ;

	pbarray pbaFileTypes = ci->pArgs->GetAt(0)->GetArray() ;

	pArrayItemCount = m_pSession->GetArrayLength(pbaFileTypes) ;

	for( i=1; i <= pArrayItemCount; i++)
	{
	    dim[0]= i;
	    ipv = m_pSession -> AcquireArrayItemValue ( pbaFile
        Types, dim ) ;
	    m_pSession -> SetArrayItemValue ( m_filetypes, dim, 
       ipv ) ;
	    m_pSession -> ReleaseValue ( ipv ) ;
	}

  }
  
  ci -> returnValue -> SetLong((pblong)0);

  return pbrRet;
}

PBXRESULT CPBNISetWindowHook::SetDefaultFileType
(
  IPB_Session	*session, 
  pbobject	obj, 
  PBCallInfo	*ci
)
{
  pbstring	pbDefault ;
  PBXRESULT pbrRet = PBX_OK;


  pbDefault = ci->pArgs->GetAt(0)->GetString() ;
  m_default = (LPSTR)m_pSession->GetString(pbDefault);

  ci -> returnValue -> SetLong((pblong)0);

  return pbrRet;
}

void CPBNISetWindowHook::Destroy()
{ 
	UnhookWindowsHookEx ( hHook ) ;
	delete this;
}

PBXRESULT CPBNISetWindowHook::Invoke
(
  IPB_Session	*session, 
  pbobject	obj, 
  pbmethodID	mid,
  PBCallInfo	*ci
)
{
  PBXRESULT pbrRet ;

  switch ( mid )
  {
	case REGISTER:
	
		pbrRet = (PBXRESULT)Register
		(
		  (IPB_Session*)session, 
		  (pbobject)obj, 
		  (PBCallInfo*)ci
		);
		return pbrRet;

	case FILTERFILETYPES:

		pbrRet = (PBXRESULT)FilterFileTypes
		(
		  (IPB_Session*)session, 
		  (pbobject)obj, 
		  (PBCallInfo*)ci
		);
		return pbrRet;

	case SETDEFAULTFILETYPE:

		pbrRet = (PBXRESULT)SetDefaultFileType
		(
		  (IPB_Session*)session, 
		  (pbobject)obj, 
		  (PBCallInfo*)ci
		);
		return pbrRet;

  }
  return PBX_E_INVOKE_FAILURE ;
}

LRESULT CALLBACK DialogHook(
    int nCode,
    WPARAM wParam,
    LPARAM lParam
)
{

	if ( nCode < 0 )
	{
		DWORD	lResult ;
		lResult = CallNextHookEx ( hHook, nCode, wParam, 
   lParam ) ;
		return lResult ;
	}

	CWPRETSTRUCT * cwpretStruct = (CWPRETSTRUCT*)(lParam);

	if ( ( cwpretStruct->message == CB_ADDSTRING ) && ( 
  m_filetypes ) )
	{
		int		pArrayItemCount ;
		int		i ;
		pblong		dim[1] ;
		DWORD		lResult ;
		pbstring	pbFileType ;
		pbboolean   bIsNull = 0;
		LPSTR		lpszFileType ;

		pArrayItemCount = m_pSession->GetArrayLength(m_filetypes) ;

		for( i=1; i <= pArrayItemCount; i++)
		{
			dim[0]= i;
			pbFileType = m_pSession->GetStringArrayItem ( m_file
			types, dim, bIsNull );
			lpszFileType = (LPSTR)m_pSession->GetString
			(pbFileType) ;
			if ( strcmp ( (LPCTSTR) cwpretStruct->lParam, 
			lpszFileType ) == 0 )
			{
	lResult = SendMessage( (HWND)cwpretStruct->hwnd, 
      (UINT)CB_FINDSTRINGEXACT, (WPARAM)0, (LPARAM)lpsz
       FileType ); 
				if ( lResult != CB_ERR )
				{
	lResult = SendMessage ( (HWND)cwpretStruct->hwnd, 
      (UINT)CB_DELETESTRING, (WPARAM)lResult, (LPARAM)0 );

				}
				break ;
			}
		}

	}
	if ( ( cwpretStruct->message == CB_SETCURSEL ) && ( 
  m_default ) )
	{
		DWORD lResult ;
lResult = SendMessage( (HWND)cwpretStruct->hwnd,
   (UINT)CB_FINDSTRING, (WPARAM)0, (LPARAM)m_default ); 
		if ( ( lResult != CB_ERR ) && ( cwpretStruct->wParam != 
    lResult ) )
		{
lResult = SendMessage ( (HWND)cwpretStruct->hwnd,  
    (UINT)CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0 ) ;
		}
	}
  return FALSE ;
}