/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name: Mainwind.cpp
*
*	Purpose: main window response function for moniker client sample
*
*********************************************************************
*/

#include <windows.h>		    /* required for all Windows applications */


/*
*****************************************************************************
Application header files
*****************************************************************************
*/

#include "main.h"
#include "resource.h"

/*
*****************************************************************************
Function prototype files
*****************************************************************************
*/

/*
*****************************************************************************
Global Variables defined here
*****************************************************************************
*/

LPDATAOBJECT lpd = NULL ;
LPMONIKER pMoniker = NULL ;
UINT cfLinkSource ;

char DisplayText [1024] ;
					
                           
/*
*****************************************************************************
EXTERNS ofglobal variables defined in other files
*****************************************************************************
*/

extern HWND	hMainWnd ;
extern HINSTANCE hInst ;



long WINAPI MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{


	switch (message)
	{

		case WM_CREATE:
		{
			cfLinkSource = RegisterClipboardFormat ("Link Source") ;
			return 0 ;
		}

/*
WM_COMMAND is a command from the application menu
*/

		case WM_COMMAND:
		{
                    
			switch (wParam)
			{

				case ID_MONIKER_PASTEFROMCLIPBOARD:
				{
					HRESULT hr ;
					LPDATAOBJECT pClip ;
					FORMATETC fe ;
					STGMEDIUM stg ;

/*
STEP 3
Get clipboard data object.  Get its data in link source format in
an IStream medium.Seek the stream to the beginning. Load the moniker from 
the stream.
*/
					

/*
STEP 4
Bind the moniker to the data object.  
*/


					if (!SUCCEEDED(hr))
					{
						MessageBox (NULL, TEXT("Couldn't bind to moniker"), TEXT("Error"), 0) ;
					}
					else
					{

/*
Get the data from the data object, draw on screen.
*/
						fe.cfFormat = CF_TEXT ;
						fe.lindex = -1 ;
						fe.dwAspect = DVASPECT_CONTENT ;
						fe.ptd = NULL ;
						fe.tymed = TYMED_HGLOBAL ;

						hr = lpd->GetData (&fe, &stg) ;

						char *cp = (char *) GlobalLock (stg.hGlobal) ;
						lstrcpyn (DisplayText, cp, sizeof(DisplayText)) ;
						GlobalUnlock (stg.hGlobal) ;
						ReleaseStgMedium (&stg) ;

						InvalidateRect (hWnd, NULL, TRUE) ;
					}
					return 0 ;
				}
/*
User picked "Moniker-Save" from the menu.  Ask the object for its moniker.
Then create a file containing a stream, and save the moniker to this
stream.
*/
				case ID_MONIKER_SAVEMONIKERAS:
				{
					HRESULT hr ;

/*
Pop up "Save As" dialog box, get file name from user, convert to WCHAR.
*/

					OPENFILENAME of ;
					char FileTitle [256] ;

					ZeroMemory (&of, sizeof(of)) ;
					
					of.lStructSize = sizeof (of) ;
					of.hwndOwner = hWnd ;
					of.lpstrFileTitle = FileTitle ;
					of.nMaxFileTitle = sizeof (FileTitle) ;
					of.lpstrFilter = "All Files\0*.*\0" ;

					if (GetSaveFileName (&of)) 
					{
	 					WCHAR wFileTitle [256]  ;

						MultiByteToWideChar (CP_ACP, 0, FileTitle, -1, wFileTitle, 80) ; 

/*
Create storage file, clobbering any previous version.
*/

						IStorage *pStor ;


						hr = StgCreateDocfile (wFileTitle, 
							STGM_CREATE | STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
							0, 
							&pStor) ;

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, "Could not create storage file", "Error", MB_ICONSTOP) ;
							return 0 ;
						}

/*
Create a stream within the storage file.
*/
						IStream *pStream ;

						hr = pStor->CreateStream (L"Moniker",
							STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 
 							0, 0, &pStream) ;

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, "Could not open stream", "Error", MB_ICONSTOP) ;
							pStor->Release ( ) ;
						}

/*
STEP 5
Tell the moniker to save its data into the stream.
*/

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, TEXT("Couldn't save moniker"), TEXT("Error"), 0) ;
						}

/*
Release interface pointers when done.
*/

						pStream->Release ( ) ;
						pStor->Release ( ) ;
					}

					return 0 ;
				}

				case ID_MONIKER_OPENMONIKERFILE:
				{
					HRESULT hr ;

/*
Get name of file from user, convert to wide char
*/
					OPENFILENAME of ;
					char FileTitle [256] ;

					ZeroMemory (&of, sizeof(of)) ;
					
					of.lStructSize = sizeof (of) ;
					of.hwndOwner = hWnd ;
					of.lpstrFileTitle = FileTitle ;
					of.nMaxFileTitle = sizeof (FileTitle) ;
					of.lpstrFilter = "All Files\0*.*\0" ;

					if (GetOpenFileName (&of)) 
					{
	 					WCHAR wFileTitle [256]  ;

						MultiByteToWideChar (CP_ACP, 0, FileTitle, -1, wFileTitle, 80) ; 
/*
Open existing storage file.
*/

						IStorage *pStor ;

						hr = StgOpenStorage (wFileTitle, 	// file name
								NULL,								// priority
								STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
								NULL, 		// exclude elements
								0, 			// reserved
								&pStor) ;

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, TEXT("Could not create storage file"), TEXT("Error"), MB_ICONSTOP) ;
							return 0 ;
						}

/*
Open a stream within the storage file.
*/
						IStream *pStream ;

						hr = pStor->OpenStream (L"Moniker", 0, 
							STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 
 							0, &pStream) ;

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, "Could not open stream", "Error", MB_ICONSTOP) ;
							pStor->Release ( ) ;
							return 0 ;
						}


/*
STEP 6
Load moniker from stream
*/

						if (!SUCCEEDED(hr))
						{
							MessageBox (NULL, "Couldn't load moniker from stream", "Error", 0) ;
						}

						pStor->Release ( ) ;
						pStream->Release( ) ;
/*
Bind to the object named by the moniker.  Release moniker.
*/
						if (pMoniker)
						{
							hr = BindMoniker (pMoniker, 0, IID_IDataObject, (void **) &lpd) ;

							if (!SUCCEEDED(hr))
							{
								MessageBox (NULL, "Couldn't bind to moniker", "Error", 0) ;
							}
							else
							{
/*
Get data from data object.  Establish advise sink.
*/
								FORMATETC fe ;
								STGMEDIUM stg ;

								fe.cfFormat = CF_TEXT ;
								fe.lindex = -1 ;
								fe.dwAspect = DVASPECT_CONTENT ;
								fe.ptd = NULL ;
								fe.tymed = TYMED_HGLOBAL ;

								hr = lpd->GetData (&fe, &stg) ;

								char *cp = (char *) GlobalLock (stg.hGlobal) ;
								lstrcpyn (DisplayText, cp, sizeof(DisplayText)) ;
								GlobalUnlock (stg.hGlobal) ;
								ReleaseStgMedium (&stg) ;

								InvalidateRect (hWnd, NULL, TRUE) ;
							}

							pMoniker->Release( ) ;
							pMoniker = NULL ;
						}


					}

					return 0 ;
				}


				case ID_MONIKER_EXIT:
				{
					if (lpd)
					{
					//	lpd->DUnadvise ( );
						lpd->Release ( ) ;
					}
					SendMessage (hWnd, WM_CLOSE, 0, 0L) ;        
					return 0 ;
				}

			}

			return 0 ;
		}

		case WM_INITMENU:
		{
			HMENU hMenu ;

			hMenu = GetMenu (hWnd) ;
			
			LPDATAOBJECT pClip ;
			FORMATETC fe ;

			fe.cfFormat = cfLinkSource ;
			fe.lindex = -1 ;
			fe.dwAspect = DVASPECT_CONTENT ;
			fe.ptd = NULL ;
			fe.tymed = TYMED_ISTREAM ;

			OleGetClipboard (&pClip) ;

			if (pClip && pClip->QueryGetData (&fe) == S_OK) 
			{
				EnableMenuItem (hMenu, ID_MONIKER_PASTEFROMCLIPBOARD, MF_ENABLED) ;
			}
			else
			{
				EnableMenuItem (hMenu, ID_MONIKER_PASTEFROMCLIPBOARD, MF_GRAYED) ;
			}


			if (pMoniker)
			{
				EnableMenuItem (hMenu, ID_MONIKER_SAVEMONIKERAS, MF_ENABLED) ;
			}
			else
			{
				EnableMenuItem (hMenu, ID_MONIKER_SAVEMONIKERAS, MF_GRAYED) ;
			}

			return 0 ;
		}


/*
Shutdown time.  
*/

		case WM_CLOSE:
		{
			DestroyWindow (hWnd) ;
			return 0 ;
		}

	
		case WM_DESTROY:
		{           
		  	PostQuitMessage (0) ;
		  	return 0 ;
		}
		
		case WM_PAINT:
		{
			PAINTSTRUCT ps ;
			HDC hDC ;
			RECT r ;

			
			hDC = BeginPaint (hWnd, &ps) ;
			
			if (!lpd)
			{
				TextOut (hDC, 0, 0, TEXT("<no object>"), 11) ;
			}
			else
			{
				GetClientRect (hWnd, &r) ;
				DrawText (hDC, DisplayText, -1, &r, DT_LEFT) ;
			} 

	
			EndPaint (hWnd, &ps) ;
			return 0 ;
		}

	}
       
	return DefWindowProc(hWnd, message, wParam, lParam) ;
	
}


