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