#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("Class");

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
      ,LPSTR lpszCmdParam,int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=(WNDPROC)WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW | CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
  NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);
 hWndMain=hWnd;

 while(GetMessage(&Message,0,0,0)) {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }
 return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;

 switch(iMessage)
 {
 case WM_CREATE:
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd, &ps);
  EndPaint(hWnd, &ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
/*
http://blog.daum.net/cprogramer/10178315 <- api 정복...

http://tong.nate.com/ljh9477/25163557
비트맵은 DDB방식과 DIB방식이 있습니다.
디스크상에 저장된 비트맵은 DIB방식으로 저장이 되어 있죠.
DIB방식으로 저장된 비트맵은 BITMAPFILEHEADER 구조체를 읽어들여 비트맵 파일정보를 분석하고 BITMAPINFOHEADER 구조체를 읽어들여
비트맵의 크기, 색상, 포멧정보를 읽어들인뒤에 SetDIBitsToDevice 함수로 출력하면 됩니다.
즉 비트맵은 다음과 같은 방식으로 디스크에 저장되어 있는 것이죠

_____________________________
BITMAPFILEHEADER
_____________________________
BITMAPINFOHEADER
_____________________________
RGBQUARD 배열
_____________________________
비트정보


~~~~~~~~~~~~~~~~~~~~

아래는 비트맵을 읽어들이고 출력하는 코드입니다.
*/
BITMAPFILEHEADER *pBFH;
BITMAPINFOHEADER *pBIH;
PBYTE pRaster;
HANDLE hFile;
DWORD dwFileSize, dwRead;
HDC hDC;

void LoadBitmap()
{
 // 파일을 열고 비트맵 파일의 크기를 얻어온다
 hFile = CreateFile( "C:\\test.bmp", GENERIC_READ, FILE_SHARE_READ, NULL,
  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

 if( INVALID_HANDLE_VALUE == hFile )
  return FALSE;

 dwFileSize = GetFileSize( hFile, NULL );

 // 비트맵 크기만큼 메모리를 할당
 pBFH = VirtualAlloc( NULL, dwFileSize, MEM_RESERVE | MEM_COMMIT, PAGE_READONLY );
 if( NULL == pBFH )
  return FALSE;

 // 비트맵을 읽어들임
 ReadFile( hFile, pBFH, dwFileSize, &dwRead, NULL );

 // 비트정보가 들어있는 포인터를 얻어냄
 pBIH = (BITMAPINFOHEADER *)( (PBYTE)pBFH + sizeof(BITMAPFILEHEADER) );
 pRaster = (PBYTE)pBFH + pBFH->bfOffBits;
}

void PrintBitmap()
{
 // 윈도우의 핸들을 얻고 DIB를 출력
 hDC = GetDC( hWnd );
 SetDIBitsToDevice( hDC, 0, 0, pBIH->biWidth, pBIH->biHeight, 0, 0,
  pBIH->biHeight, pRaster, (BITMAPINFO *)pBIH, DIB_RGB_COLORS );

 ReleaseDC( hWnd, hDC );
}
/*
## 출처 : http://www.devpia.com
## 쓴이 : oOOo(oselo79)


비트맵 핸들 얻기
 
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, strFilePath, IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);  //strFilePath는
비트맵파일의 풀네임
 
CBitmap으로 가져오기
 
CBitmap *pbitmap=CBitmap::FromHandle(hBitmap);
 
비트맵 정보 얻기
 
BITMAP bmInfo;
pbitmap->GetBitmap(&bmInfo);
 
bmInfo 를 이용해서 다음과 같은 정보를 얻을 수 있습니다.
 
ttypedef struct tagBITMAP
{  // bm
   LONG   bmType;
   LONG   bmWidth;
   LONG   bmHeight;
   LONG   bmWidthBytes;
   WORD   bmPlanes;
   WORD   bmBitsPixel;
   LPVOID bmBits;
} BITMAP;
 
비트맵의 각 픽셀값 가져오기
 
DWORD bmpSize = bmInfo.bmHeight * bmInfo.bmWidthBytes;
BYTE* pbiBitData  = new BYTE[bmpSize];
 
pbitmap->GetBitmapBits(bmpSize, pbiBitData);
 
이렇게 하면 pbiBitData에 비트맵의 모든 pixel 값들이 들어옵니다.
 
Pixel 값들을 화면에 뿌려주기(memDC 이용)
 
INT i, j;
DWORD k = 0;
BYTE br, bg, bb;
 
for(i = 0 ; i< bmInfo.bmHeight; i++)
{
        for(j = 0; j< bmInfo.bmWidth
; j++)
        {
            br = *(pbiBitData + k+2);
            bg = *(pbiBitData + k+1);
            bb = *(pbiBitData + k);
            memDC.SetPixel(j,i, RGB(br, bg, bb));
            k+=3;
        }
        if(k%2 != 0)    k++;        //
한 Width 당 4의 배수의 Bit가 셋되어 있으므로
}
 
어디에 뿌려줄지는 모르겠지만, 뿌려줄 곳의 DC를 얻은 후
dc.BitBlt(0, 0, m_rcClient.Width(),m_rcClient.Height(), &memDC, 0,
0, SRCCOPY);
로 뿌려줌
 
물론
m_bitmap.CreateCompatibleBitmap(&dc,width,height );
memDC.CreateCompatibleDC(&dc); 등 dc 에 뿌려주기 위해
해야할 일이 다수 있는데, 그건 검색해보면 많이 나옵니다.
 
잘라내기 위한 드래그
 
CRect m_recOldVaid, m_recCurDrag; 두개를 선언
m_recCurDrag 는 뿌려주고 있는 컨트롤 또는 다이얼로그에서의
마우스 상대좌표값이 들어가야함
즉, 마우스 Move 이벤트시, 좌표를 m_recCurDrag 에 설정한
후, 다음 루틴을 실행한다.
 
if(m_bDraging)        // Key Press 이벤트가
들어온 상태에서, Mouse Move 이벤트가 발생할때마다 TRUE
{
        dc->DrawDragRect(&m_rectCurDrag,
CSize(1,1), &m_rectOldValid, CSize(0,0), &m_validRectBrush, &m_validRectBrush);
        m_rectOldValid = m_rectCurDrag;
        m_bDraging = FALSE;
}
 
이 부분을 dc.Bitblt(...); 다음에 추가하면 드래깅 됨
 
 
드래그한 부분의 Pixel 값들 가져오기
 
    int i, j;
    ULONG l = 0;
    COLORREF color;
    BYTE* pBitBuff = new BYTE[rect.Width() * rect.Height()];
 
    for(i = rect.top; i m_recCurDrag 가 바로 rect 입니다.
    {
        for(j = rect.left; j j++)
        {
            color = memDC.GetPixel(CPoint(j, i));
            *(pBitBuff+(l++)) = (BYTE)(color & 0x000000FF);
            *(pBitBuff+(l++)) = (BYTE)((color & 0x0000FF00) >> 8);
            *(pBitBuff+(l++)) = (BYTE)((color & 0x00FF0000) >> 16);
        }
    }
 
 
여기까지하면 pBitBuff 에 선택된 Pixel 값이 들가가게
되고, preview를 구현하고자 한다면, 위에서 설명한 방법으로 다른곳에 뿌려주면됩니다.
 
원래는 소스를 통채로 올릴려고 했는데.. 넘 급하게 만든거라..
소스도 허접하고, 상용툴은 아니지만 회사 재산이라는 생각도 들고..
GNU~~~~ 를 좋아하지만, 참... 아쉽지만 이정도로.. 방향은
잡히실꺼라 생각됩니다.
 
즐프요~

http://web.search.naver.com/search.naver?where=webkr&query=%BA%F1%C6%AE%B8%CA+%A4%B1api&sm=tab_hty
*/

'알고리즘 > 이미지 처리' 카테고리의 다른 글

GDI+에서의 투명색 처리...  (0) 2008.01.25
이미지 회전 알고리즘  (0) 2008.01.18
Image Processing  (0) 2008.01.18
그림 띄우기  (0) 2008.01.07
[본문스크랩] BMP(비트맵) 파일  (0) 2007.09.06
BMP 에 관해서  (0) 2007.07.08
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

댓글을 달아 주세요

음...

한자 출력, API, MFC(미완성) 소스
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

댓글을 달아 주세요

학교에 깔린 VC6.0 엔 GDI+ 가 안깔린 경우가 많아서... ㅠ_ㅠ


http://www.microsoft.com/downloads/thankyou.aspx?familyId=6a63ab9c-df12-4d41-933c-be590feaa05a&displayLang=en&hash=IVMnSFncU2%2bv%2bXqwA2DkLjpFW2XbSQ5tIOfJqxkDhXkFZZ6AMgLRRxqLLM3mxCYQxsX2M80K6LYMwLGOOvpLpQ%3d%3d

여기서 일단 다운로드 하구..

이파일을 다운해도 됨..
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

댓글을 달아 주세요

소스파일입니다.


우선..
"stdafx.h" 파일을 만들고
==================================================================
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#ifndef DWORD
#define DWORD unsigned long
#endif
// TODO: reference additional headers your program requires here
==================================================================
를 써줍니다.

다음.. 소스가 들어갈 파일..
파일명은 "LaunchBrowser.cpp" 로 해줍니다.
==================================================================

#include "stdafx.h"
#include <comutil.h>
#include <exdisp.h>
#include <process.h>    /* _beginthread, _endthread */
#include <stddef.h>

#pragma comment(lib, "comsupp.lib")

// Get a string from the registry
BOOL GetRegistryString(HKEY rootKey, const char *pzPath, const char *pzKey, char *zBuf, int nBufSize)
{
  HKEY hKey = NULL;
  LONG lReturnValue = RegOpenKeyEx (rootKey, pzPath, 0L, KEY_QUERY_VALUE, &hKey);
  if(lReturnValue != ERROR_SUCCESS)
    return FALSE;
  DWORD dwType = 0;
  DWORD dwSize = nBufSize;
  lReturnValue = RegQueryValueEx (hKey, pzKey, NULL, &dwType, (BYTE *) zBuf, &dwSize);
  RegCloseKey (hKey);
  if (lReturnValue != ERROR_SUCCESS)
    return FALSE;
  return TRUE;
}

// Determine if the version of MSIE is version 7
BOOL IsIE7()
{
  char szVersion[128];
  BOOL bRet = GetRegistryString(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer", "Version", szVersion, sizeof(szVersion));
  if (bRet == TRUE && szVersion[0] == '7')
    return TRUE;
  return FALSE;
}

// simple data structure for our browser settings
typedef struct
{
  char zUrl[1024];
  int nWidth;
  int nHeight;
 HICON hIcon;
}BROWSER_INFO;

BROWSER_INFO g_BrowserInfo;

// This thread demonstrates how to initialize OLE such that we have an exclusive COM apartment for this
// thread separate from the main thread.
//
// It also shows how to manipulate the IWebBrowser interface to do some interesting things such as:
//   1.  Make the IE window resizable or static (non-resizable) based on IE version number.
//  2.  Turn off the address bar, menu bar, status bar, and tool bar buttons.
//  3.  Set the width and height of the resulting window.
//  4.  Change the icon of the MSIE window to one of your own.
//
void BrowserThread( void* pParams )
{
  OleInitialize(NULL);
  BROWSER_INFO *pBrowserInfo = (BROWSER_INFO *)pParams;
   IWebBrowser2* m_pInetExplorer;

    HRESULT hr;
  HICON hIcon;
    CLSID clsid;
    LPUNKNOWN punk=NULL;
    CLSIDFromProgID (OLESTR("InternetExplorer.Application"), &clsid);
    hr = CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (LPVOID *) &punk);
    if (SUCCEEDED(hr))
   {
    punk->QueryInterface (IID_IWebBrowser2, (LPVOID *) &m_pInetExplorer);
    punk->Release();
    VARIANT vars[4];
        memset(vars,0,sizeof(vars));
        BSTR BStrURL = _com_util::ConvertStringToBSTR((const char *)(pBrowserInfo->zUrl));
    if (IsIE7())
      m_pInetExplorer->put_Resizable(VARIANT_TRUE);
    else
      m_pInetExplorer->put_Resizable(VARIANT_FALSE);
        m_pInetExplorer->put_ToolBar(FALSE);
        m_pInetExplorer->put_AddressBar(VARIANT_FALSE);
        m_pInetExplorer->put_MenuBar(VARIANT_FALSE);
        m_pInetExplorer->put_StatusBar(VARIANT_FALSE);
        m_pInetExplorer->put_Width(pBrowserInfo->nWidth);
        m_pInetExplorer->put_Height(pBrowserInfo->nHeight);

        m_pInetExplorer->put_Visible(VARIANT_TRUE);
        HRESULT hrie = m_pInetExplorer->Navigate(BStrURL,vars,vars+1,vars+2,vars+3);
        SysFreeString(BStrURL);
    if (SUCCEEDED(hrie))
    {
      VARIANT_BOOL bBusy = VARIANT_TRUE;
      while(bBusy == VARIANT_TRUE)
      {
        Sleep(500);
        m_pInetExplorer->get_Busy(&bBusy);
      }
       HWND hWnd = NULL;
      m_pInetExplorer->get_HWND ((long*)(&hWnd));
      if (IsWindow(hWnd) && pBrowserInfo->hIcon != NULL)
      {
        hIcon = pBrowserInfo->hIcon;
        SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
      }
  // Do other interesting IE stuff here while the window is valid.
  //   while(IsWindow(hWnd))
  //   {
  //     Sleep(500);
  //     m_pInetExplorer->get_HWND ((long*)(&hWnd));
  //   }
    }
    m_pInetExplorer->Release();
   }
    OleUninitialize();
  // thread exiting.
}

/*
 * Spawn the M browser
 */
void spawn_browser(
  const char *uri, // URL
  int nWidth,    // Window Width
  int nHeight,   // Window Height
 HICON hIcon)   // Handle to the icon
{
  g_BrowserInfo.nWidth = nWidth;
  g_BrowserInfo.nHeight = nHeight;
  memset(g_BrowserInfo.zUrl,0,(sizeof(g_BrowserInfo.zUrl)*sizeof(char)));
  strncpy(g_BrowserInfo.zUrl,uri,min(strlen(uri),(sizeof(g_BrowserInfo.zUrl)*sizeof(char))));
  g_BrowserInfo.hIcon = hIcon;
  HANDLE hThread = (HANDLE) _beginthread( BrowserThread, 0, &g_BrowserInfo );

  // Wait until IE is done loading before we return.
    WaitForSingleObject( hThread, INFINITE );
}

==================================================================

해줍니다..

구조상...
spawn_browser으로 구동시키며,
이거 쓰레드를 사용합니다... 허...
어쨋든..

spawn_browser("http://www.codeproject.com", 800, 600, hIcon);
식으로 쓰면, codeproject.com 웹을  800,600 크기, hIcon 이미지를 가진 대화상자를 만들어
거기에 띄워줍니다.

음...
이거.. 소스찾는데 애먹었습니다..허.. 조금만 수정하면 다용도로 사용가능할꺼 같네요

블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

댓글을 달아 주세요

/* CWebPage.c
 
This is a Win32 C application (ie, no MFC, WTL, nor even any C++ -- just plain C) that demonstrates
how to embed a browser "control" (actually, an OLE object) in your own window (in order to display a
web page, or an HTML file on disk).

This is very loosely based upon a C++ example written by Chris Becke. I used that to learn the minimum
of what I needed to know about hosting the browser object. Then I wrote this example from the ground up
in C.
*/



#include <windows.h>
#include <exdisp.h>  // Defines of stuff like IWebBrowser2. This is an include file with Visual C 6 and above
#include <mshtml.h>  // Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above
#include <crtdbg.h>  // for _ASSERT()




// A running count of how many windows we have open that contain a browser object
unsigned char WindowCount = 0;

// The class name of our Window to host the browser. It can be anything of your choosing.
static const TCHAR ClassName[] = "Browser Example";

// This is used by DisplayHTMLStr(). It can be global because we never change it.
static const SAFEARRAYBOUND ArrayBound = {1, 0};



// Our IStorage functions that the browser may call
HRESULT STDMETHODCALLTYPE Storage_QueryInterface(IStorage FAR* This, REFIID riid, LPVOID FAR* ppvObj);
HRESULT STDMETHODCALLTYPE Storage_AddRef(IStorage FAR* This);
HRESULT STDMETHODCALLTYPE Storage_Release(IStorage FAR* This);
HRESULT STDMETHODCALLTYPE Storage_CreateStream(IStorage FAR* This, const WCHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm);
HRESULT STDMETHODCALLTYPE Storage_OpenStream(IStorage FAR* This, const WCHAR * pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm);
HRESULT STDMETHODCALLTYPE Storage_CreateStorage(IStorage FAR* This, const WCHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage **ppstg);
HRESULT STDMETHODCALLTYPE Storage_OpenStorage(IStorage FAR* This, const WCHAR * pwcsName, IStorage * pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg);
HRESULT STDMETHODCALLTYPE Storage_CopyTo(IStorage FAR* This, DWORD ciidExclude, IID const *rgiidExclude, SNB snbExclude,IStorage *pstgDest);
HRESULT STDMETHODCALLTYPE Storage_MoveElementTo(IStorage FAR* This, const OLECHAR *pwcsName,IStorage * pstgDest, const OLECHAR *pwcsNewName, DWORD grfFlags);
HRESULT STDMETHODCALLTYPE Storage_Commit(IStorage FAR* This, DWORD grfCommitFlags);
HRESULT STDMETHODCALLTYPE Storage_Revert(IStorage FAR* This);
HRESULT STDMETHODCALLTYPE Storage_EnumElements(IStorage FAR* This, DWORD reserved1, void * reserved2, DWORD reserved3, IEnumSTATSTG ** ppenum);
HRESULT STDMETHODCALLTYPE Storage_DestroyElement(IStorage FAR* This, const OLECHAR *pwcsName);
HRESULT STDMETHODCALLTYPE Storage_RenameElement(IStorage FAR* This, const WCHAR *pwcsOldName, const WCHAR *pwcsNewName);
HRESULT STDMETHODCALLTYPE Storage_SetElementTimes(IStorage FAR* This, const WCHAR *pwcsName, FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime);
HRESULT STDMETHODCALLTYPE Storage_SetClass(IStorage FAR* This, REFCLSID clsid);
HRESULT STDMETHODCALLTYPE Storage_SetStateBits(IStorage FAR* This, DWORD grfStateBits, DWORD grfMask);
HRESULT STDMETHODCALLTYPE Storage_Stat(IStorage FAR* This, STATSTG * pstatstg, DWORD grfStatFlag);

// Our IStorage VTable. This is the array of pointers to the above functions in our C
// program that someone may call in order to store some data to disk. We must define a
// particular set of functions that comprise the IStorage set of functions (see above),
// and then stuff pointers to those functions in their respective 'slots' in this table.
// We want the browser to use this VTable with our IStorage structure (object).
IStorageVtbl MyIStorageTable = {Storage_QueryInterface,
Storage_AddRef,
Storage_Release,
Storage_CreateStream,
Storage_OpenStream,
Storage_CreateStorage,
Storage_OpenStorage,
Storage_CopyTo,
Storage_MoveElementTo,
Storage_Commit,
Storage_Revert,
Storage_EnumElements,
Storage_DestroyElement,
Storage_RenameElement,
Storage_SetElementTimes,
Storage_SetClass,
Storage_SetStateBits,
Storage_Stat};

// Our IStorage structure. NOTE: All it contains is a pointer to our IStorageVtbl, so we can easily initialize it
// here instead of doing that programmably.
IStorage   MyIStorage = { &MyIStorageTable };



// Our IOleInPlaceFrame functions that the browser may call
HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame FAR* This, REFIID riid, LPVOID FAR* ppvObj);
HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame FAR* This);
HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame FAR* This);
HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame FAR* This, HWND FAR* lphwnd);
HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame FAR* This, BOOL fEnterMode);
HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame FAR* This, LPRECT lprectBorder);
HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths);
HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths);
HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame FAR* This, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName);
HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame FAR* This, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared);
HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame FAR* This, LPCOLESTR pszStatusText);
HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame FAR* This, BOOL fEnable);
HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame FAR* This, LPMSG lpmsg, WORD wID);

// Our IOleInPlaceFrame VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleInPlaceFrame set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleInPlaceFrame structure.
IOleInPlaceFrameVtbl MyIOleInPlaceFrameTable = {Frame_QueryInterface,
Frame_AddRef,
Frame_Release,
Frame_GetWindow,
Frame_ContextSensitiveHelp,
Frame_GetBorder,
Frame_RequestBorderSpace,
Frame_SetBorderSpace,
Frame_SetActiveObject,
Frame_InsertMenus,
Frame_SetMenu,
Frame_RemoveMenus,
Frame_SetStatusText,
Frame_EnableModeless,
Frame_TranslateAccelerator};

// We need to pass an IOleInPlaceFrame struct to the browser object. And one of our IOleInPlaceFrame
// functions (Frame_GetWindow) is going to need to access our window handle. So let's create our own
// struct that starts off with an IOleInPlaceFrame struct (and that's important -- the IOleInPlaceFrame
// struct *must* be first), and then has an extra data field where we can store our own window's HWND.
//
// And because we may want to create multiple windows, each hosting its own browser object (to
// display its own web page), then we need to create a IOleInPlaceFrame struct for each window. So,
// we're not going to declare our IOleInPlaceFrame struct globally. We'll allocate it later using
// GlobalAlloc, and then stuff the appropriate HWND in it then, and also stuff a pointer to
// MyIOleInPlaceFrameTable in it. But let's just define it here.
typedef struct _IOleInPlaceFrameEx {
 IOleInPlaceFrame frame;  // The IOleInPlaceFrame must be first!

 ///////////////////////////////////////////////////
 // Here you add any variables that you need
 // to access in your IOleInPlaceFrame functions.
 // You don't want those functions to access global
 // variables, because then you couldn't use more
 // than one browser object. (ie, You couldn't have
 // multiple windows, each with its own embedded
 // browser object to display a different web page).
 //
 // So here is where I added my extra HWND that my
 // IOleInPlaceFrame function Frame_GetWindow() needs
 // to access.
 ///////////////////////////////////////////////////
 HWND    window;
} IOleInPlaceFrameEx;




// Our IOleClientSite functions that the browser may call
HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject);
HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite FAR* This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk);
HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite FAR* This, LPOLECONTAINER FAR* ppContainer);
HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite FAR* This, BOOL fShow);
HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite FAR* This);

// Our IOleClientSite VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleClientSite set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleClientSite structure.
IOleClientSiteVtbl MyIOleClientSiteTable = {Site_QueryInterface,
Site_AddRef,
Site_Release,
Site_SaveObject,
Site_GetMoniker,
Site_GetContainer,
Site_ShowObject,
Site_OnShowWindow,
Site_RequestNewObjectLayout};




// Our IOleInPlaceSite functions that the browser may call
HRESULT STDMETHODCALLTYPE Site_GetWindow(IOleInPlaceSite FAR* This, HWND FAR* lphwnd);
HRESULT STDMETHODCALLTYPE Site_ContextSensitiveHelp(IOleInPlaceSite FAR* This, BOOL fEnterMode);
HRESULT STDMETHODCALLTYPE Site_CanInPlaceActivate(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_OnInPlaceActivate(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_OnUIActivate(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_GetWindowContext(IOleInPlaceSite FAR* This, LPOLEINPLACEFRAME FAR* lplpFrame,LPOLEINPLACEUIWINDOW FAR* lplpDoc,LPRECT lprcPosRect,LPRECT lprcClipRect,LPOLEINPLACEFRAMEINFO lpFrameInfo);
HRESULT STDMETHODCALLTYPE Site_Scroll(IOleInPlaceSite FAR* This, SIZE scrollExtent);
HRESULT STDMETHODCALLTYPE Site_OnUIDeactivate(IOleInPlaceSite FAR* This, BOOL fUndoable);
HRESULT STDMETHODCALLTYPE Site_OnInPlaceDeactivate(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_DiscardUndoState(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_DeactivateAndUndo(IOleInPlaceSite FAR* This);
HRESULT STDMETHODCALLTYPE Site_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect);

// Our IOleInPlaceSite VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleInPlaceSite set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleInPlaceSite structure.
IOleInPlaceSiteVtbl MyIOleInPlaceSiteTable =  {Site_QueryInterface, // This gives a compiler warning because we're using
               // the same function as the MyIOleClientSiteTable uses.
               // And the first arg to that Site_QueryInterface() is
               // a pointer to a IOleClientSite. What we really should
               // have here is a separate function with its first arg
               // as a pointer to a IOleInPlaceSite (even though what
               // will really get passed to it is a _IOleClientSiteEx *).
               // But it's easier to use one function for QueryInterface()
               // in order to support "inheritance". ie, Sometimes, the
               // browser may call your IOleClientSite's QueryInterface
               // in order to get a pointer to your IOleInPlaceSite, or
               // vice versa. This is because these two structs will be
               // passed to the browser inside of a single struct. And
               // that makes them "interconnected" as far as
               // QueryInterface is concerned.
Site_AddRef,    // Ditto as above.
Site_Release,    // Ditto as above.
Site_GetWindow,
Site_ContextSensitiveHelp,
Site_CanInPlaceActivate,
Site_OnInPlaceActivate,
Site_OnUIActivate,
Site_GetWindowContext,
Site_Scroll,
Site_OnUIDeactivate,
Site_OnInPlaceDeactivate,
Site_DiscardUndoState,
Site_DeactivateAndUndo,
Site_OnPosRectChange};

// The structure we need to pass to the browser object must contain an IOleClientSite structure. The
// IOleClientSite struct *must* be first. Our IOleClientSite's QueryInterface() may also be asked to
// return a pointer to our IOleInPlaceSite struct. So we'll need to have that object handy. Plus,
// some of our IOleClientSite and IOleInPlaceSite functions will need to have the HWND to our window,
// and also a pointer to our IOleInPlaceFrame struct. So let's create a single struct that has both
// the IOleClientSite and IOleInPlaceSite structs inside it, and also has an extra data field to
// store a pointer to our IOleInPlaceFrame struct. (The HWND is stored in the IOleInPlaceFrame
// struct, so we can get at it there). As long as the IOleClientSite struct is the first thing, it's
// all ok. We'll call this new struct a _IOleClientSiteEx.
//
// And because we may want to create multiple windows, each hosting its own browser object (to
// display its own web page), then we need to create IOleClientSite and IOleInPlaceSite structs for
// each window. (ie, Each window needs its own _IOleClientSiteEx struct). So, we're not going to
// declare this struct globally. We'll allocate it later using GlobalAlloc, and then store the
// appropriate IOleInPlaceFrame struct pointer then.

typedef struct __IOleInPlaceSiteEx {
 IOleInPlaceSite  inplace;  // My IOleInPlaceSite object. Must be first.

 ///////////////////////////////////////////////////
 // Here you add any variables that you need
 // to access in your IOleInPlaceSite functions.
 // You don't want those functions to access global
 // variables, because then you couldn't use more
 // than one browser object. (ie, You couldn't have
 // multiple windows, each with its own embedded
 // browser object to display a different web page.
 //
 // So here is where I added my extra pointer to my
 // IOleInPlaceFrame struct.
 ///////////////////////////////////////////////////
 IOleInPlaceFrameEx *frame;
} _IOleInPlaceSiteEx;

typedef struct __IOleClientSiteEx {
 IOleClientSite  client;   // My IOleClientSite object. Must be first.
 _IOleInPlaceSiteEx inplace;  // My IOleInPlaceSite object.

 ///////////////////////////////////////////////////
 // Here you add any variables that you need
 // to access in your IOleClientSite functions.
 ///////////////////////////////////////////////////

} _IOleClientSiteEx;



// This is a simple C example. There are lots more things you can control about the browser object, but
// we don't do it in this example. _Many_ of the functions we provide below for the browser to call, will
// never actually be called by the browser in our example. Why? Because we don't do certain things
// with the browser that would require it to call those functions (even though we need to provide
// at least some stub for all of the functions).
//
// So, for these "dummy functions" that we don't expect the browser to call, we'll just stick in some
// assembly code that causes a debugger breakpoint and tells the browser object that we don't support
// the functionality. That way, if you try to do more things with the browser object, and it starts
// calling these "dummy functions", you'll know which ones you should add more meaningful code to.
#define NOTIMPLEMENTED _ASSERT(0); return(E_NOTIMPL)



////////////////////////////////////// My IStorage functions  /////////////////////////////////////////
// NOTE: The browser object doesn't use the IStorage functions, so most of these are us just returning
// E_NOTIMPL so that anyone who *does* call these functions knows nothing is being done here.

HRESULT STDMETHODCALLTYPE Storage_QueryInterface(IStorage FAR* This, REFIID riid, LPVOID FAR* ppvObj)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_AddRef(IStorage FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Storage_Release(IStorage FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Storage_CreateStream(IStorage FAR* This, const WCHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_OpenStream(IStorage FAR* This, const WCHAR * pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_CreateStorage(IStorage FAR* This, const WCHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage **ppstg)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_OpenStorage(IStorage FAR* This, const WCHAR * pwcsName, IStorage * pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_CopyTo(IStorage FAR* This, DWORD ciidExclude, IID const *rgiidExclude, SNB snbExclude,IStorage *pstgDest)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_MoveElementTo(IStorage FAR* This, const OLECHAR *pwcsName,IStorage * pstgDest, const OLECHAR *pwcsNewName, DWORD grfFlags)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_Commit(IStorage FAR* This, DWORD grfCommitFlags)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_Revert(IStorage FAR* This)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_EnumElements(IStorage FAR* This, DWORD reserved1, void * reserved2, DWORD reserved3, IEnumSTATSTG ** ppenum)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_DestroyElement(IStorage FAR* This, const OLECHAR *pwcsName)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_RenameElement(IStorage FAR* This, const WCHAR *pwcsOldName, const WCHAR *pwcsNewName)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_SetElementTimes(IStorage FAR* This, const WCHAR *pwcsName, FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_SetClass(IStorage FAR* This, REFCLSID clsid)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Storage_SetStateBits(IStorage FAR* This, DWORD grfStateBits, DWORD grfMask)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Storage_Stat(IStorage FAR* This, STATSTG * pstatstg, DWORD grfStatFlag)
{
 NOTIMPLEMENTED;
}





///////////////////////////////// My IOleClientSite/IOleInPlaceSite functions  /////////////////////////////////

/************************* Site_QueryInterface() *************************
 * The browser object calls this when it wants a pointer to one of our
 * IOleClientSite or IOleInPlaceSite structures. They are both in the
 * _IOleClientSiteEx struct we allocated in EmbedBrowserObject() and
 * passed to DoVerb() and OleCreate().
 *
 * This =  A pointer to whatever _IOleClientSiteEx struct we passed to
 *    OleCreate() or DoVerb().
 * riid =  A GUID struct that the browser passes us to clue us as to
 *    which type of struct (object) it would like a pointer
 *    returned for.
 * ppvObject = Where the browser wants us to return a pointer to the
 *    appropriate struct. (ie, It passes us a handle to fill in).
 *
 * RETURNS: S_OK if we return the struct, or E_NOINTERFACE if we don't have
 * the requested struct.
 */

HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject)
{
 // It just so happens that the first arg passed to us is our _IOleClientSiteEx struct we allocated
 // and passed to DoVerb() and OleCreate(). Nevermind that 'This' is declared is an IOleClientSite *.
 // Remember that in EmbedBrowserObject(), we allocated our own _IOleClientSiteEx struct, and lied
 // to OleCreate() and DoVerb() -- passing our _IOleClientSiteEx struct and saying it was an
 // IOleClientSite struct. It's ok. An _IOleClientSiteEx starts with an embedded IOleClientSite, so
 // the browser didn't mind. So that's what the browser object is passing us now. The browser doesn't
 // know that it's really an _IOleClientSiteEx struct. But we do. So we can recast it and use it as
 // so here.

 // If the browser is asking us to match IID_IOleClientSite, then it wants us to return a pointer to
 // our IOleClientSite struct. Then the browser will use the VTable in that struct to call our
 // IOleClientSite functions. It will also pass this same pointer to all of our IOleClientSite
 // functions.
 //
 // Actually, we're going to lie to the browser again. We're going to return our own _IOleClientSiteEx
 // struct, and tell the browser that it's a IOleClientSite struct. It's ok. The first thing in our
 // _IOleClientSiteEx is an embedded IOleClientSite, so the browser doesn't mind. We want the browser
 // to continue passing our _IOleClientSiteEx pointer wherever it would normally pass a IOleClientSite
 // pointer.
 //
 // The IUnknown interface uses the same VTable as the first object in our _IOleClientSiteEx
 // struct (which happens to be an IOleClientSite). So if the browser is asking us to match
 // IID_IUnknown, then we'll also return a pointer to our _IOleClientSiteEx.

 if (!memcmp(riid, &IID_IUnknown, sizeof(GUID)) || !memcmp(riid, &IID_IOleClientSite, sizeof(GUID)))
  *ppvObject = &((_IOleClientSiteEx *)This)->client;

 // If the browser is asking us to match IID_IOleInPlaceSite, then it wants us to return a pointer to
 // our IOleInPlaceSite struct. Then the browser will use the VTable in that struct to call our
 // IOleInPlaceSite functions.  It will also pass this same pointer to all of our IOleInPlaceSite
 // functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get
 // the pointer to our _IOleClientSiteEx.
 //
 // Actually, we're going to lie to the browser. We're going to return our own IOleInPlaceSiteEx
 // struct, and tell the browser that it's a IOleInPlaceSite struct. It's ok. The first thing in
 // our IOleInPlaceSiteEx is an embedded IOleInPlaceSite, so the browser doesn't mind. We want the
 // browser to continue passing our IOleInPlaceSiteEx pointer wherever it would normally pass a
 // IOleInPlaceSite pointer. My, we're really playing dirty tricks on the browser here. heheh.
 else if (!memcmp(riid, &IID_IOleInPlaceSite, sizeof(GUID)))
  *ppvObject = &((_IOleClientSiteEx *)This)->inplace;

 // For other types of objects the browser wants, just report that we don't have any such objects.
 // NOTE: If you want to add additional functionality to your browser hosting, you may need to
 // provide some more objects here. You'll have to investigate what the browser is asking for
 // (ie, what REFIID it is passing).
 else
 {
  *ppvObject = 0;
  return(E_NOINTERFACE);
 }

 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite FAR* This)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite FAR* This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite FAR* This, LPOLECONTAINER FAR* ppContainer)
{
 // Tell the browser that we are a simple object and don't support a container
 *ppContainer = 0;

 return(E_NOINTERFACE);
}

HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite FAR* This)
{
 return(NOERROR);
}

HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite FAR* This, BOOL fShow)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite FAR* This)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_GetWindow(IOleInPlaceSite FAR* This, HWND FAR* lphwnd)
{
 // Return the HWND of the window that contains this browser object. We stored that
 // HWND in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for
 // Site_GetWindow says that 'This' is an IOleInPlaceSite *. Remember that in
 // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which
 // contained an embedded IOleInPlaceSite struct within it. And when the browser
 // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we
 // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But
 // we do. That's what we're really being passed, so we can recast it and use it as
 // so here.
 *lphwnd = ((_IOleInPlaceSiteEx FAR*)This)->frame->window;

 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_ContextSensitiveHelp(IOleInPlaceSite FAR* This, BOOL fEnterMode)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_CanInPlaceActivate(IOleInPlaceSite FAR* This)
{
 // Tell the browser we can in place activate
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_OnInPlaceActivate(IOleInPlaceSite FAR* This)
{
 // Tell the browser we did it ok
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_OnUIActivate(IOleInPlaceSite FAR* This)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_GetWindowContext(IOleInPlaceSite FAR* This, LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
 // Give the browser the pointer to our IOleInPlaceFrame struct. We stored that pointer
 // in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for
 // Site_GetWindowContext says that 'This' is an IOleInPlaceSite *. Remember that in
 // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which
 // contained an embedded IOleInPlaceSite struct within it. And when the browser
 // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we
 // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But
 // we do. That's what we're really being passed, so we can recast it and use it as
 // so here.
 //
 // Actually, we're giving the browser a pointer to our own IOleInPlaceSiteEx struct,
 // but telling the browser that it's a IOleInPlaceSite struct. No problem. Our
 // IOleInPlaceSiteEx starts with an embedded IOleInPlaceSite, so the browser is
 // cool with it. And we want the browser to pass a pointer to this IOleInPlaceSiteEx
 // wherever it would pass a IOleInPlaceSite struct to our IOleInPlaceSite functions.
 *lplpFrame = (LPOLEINPLACEFRAME)((_IOleInPlaceSiteEx FAR*)This)->frame;

 // We have no OLEINPLACEUIWINDOW
 *lplpDoc = 0;

 // Fill in some other info for the browser
 lpFrameInfo->fMDIApp = FALSE;
 lpFrameInfo->hwndFrame = ((IOleInPlaceFrameEx FAR*)*lplpFrame)->window;
 lpFrameInfo->haccel = 0;
 lpFrameInfo->cAccelEntries = 0;

 // Give the browser the dimensions of where it can draw. We give it our entire window to fill
 GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect);
 GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect);

 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_Scroll(IOleInPlaceSite FAR* This, SIZE scrollExtent)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_OnUIDeactivate(IOleInPlaceSite FAR* This, BOOL fUndoable)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_OnInPlaceDeactivate(IOleInPlaceSite FAR* This)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Site_DiscardUndoState(IOleInPlaceSite FAR* This)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_DeactivateAndUndo(IOleInPlaceSite FAR* This)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Site_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect)
{
 return(S_OK);
}




////////////////////////////////////// My IOleInPlaceFrame functions  /////////////////////////////////////////

HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame FAR* This, REFIID riid, LPVOID FAR* ppvObj)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame FAR* This)
{
 return(1);
}

HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame FAR* This, HWND FAR* lphwnd)
{
 // Give the browser the HWND to our window that contains the browser object. We
 // stored that HWND in our IOleInPlaceFrame struct. Nevermind that the function
 // declaration for Frame_GetWindow says that 'This' is an IOleInPlaceFrame *. Remember
 // that in EmbedBrowserObject(), we allocated our own IOleInPlaceFrameEx struct which
 // contained an embedded IOleInPlaceFrame struct within it. And then we lied when
 // Site_GetWindowContext() returned that IOleInPlaceFrameEx. So that's what the
 // browser is passing us. It doesn't know that. But we do. So we can recast it and
 // use it as so here.
 *lphwnd = ((IOleInPlaceFrameEx FAR*)This)->window;
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame FAR* This, BOOL fEnterMode)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame FAR* This, LPRECT lprectBorder)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame FAR* This, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame FAR* This, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared)
{
 NOTIMPLEMENTED;
}

HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame FAR* This, LPCOLESTR pszStatusText)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame FAR* This, BOOL fEnable)
{
 return(S_OK);
}

HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame FAR* This, LPMSG lpmsg, WORD wID)
{
 NOTIMPLEMENTED;
}





/*************************** UnEmbedBrowserObject() ************************
 * Called to detach the browser object from our host window, and free its
 * resources, right before we destroy our window.
 *
 * hwnd =  Handle to the window hosting the browser object.
 *
 * NOTE: The pointer to the browser object must have been stored in the
 * window's USERDATA field. In other words, don't call UnEmbedBrowserObject().
 * with a HWND that wasn't successfully passed to EmbedBrowserObject().
 */

void UnEmbedBrowserObject(HWND hwnd)
{
 IOleObject **browserHandle;
 IOleObject *browserObject;

 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
 // we initially attached the browser object to this window.
 if ((browserHandle = (IOleObject **)GetWindowLong(hwnd, GWL_USERDATA)))
 {
  // Unembed the browser object, and release its resources.
  browserObject = *browserHandle;
  browserObject->lpVtbl->Close(browserObject, OLECLOSE_NOSAVE);
  browserObject->lpVtbl->Release(browserObject);

  GlobalFree(browserHandle);

  return;
 }

 // You must have called this for a window that wasn't successfully passed to EmbedBrowserObject().
 // Bad boy!
 _ASSERT(0);
}




/******************************* DisplayHTMLStr() ****************************
 * Takes a string containing some HTML BODY, and displays it in the specified
 * window. For example, perhaps you want to display the HTML text of...
 *
 * <P>This is a picture.<P><IMG src="mypic.jpg">
 *
 * hwnd =  Handle to the window hosting the browser object.
 * string =  Pointer to nul-terminated string containing the HTML BODY.
 *    (NOTE: No <BODY></BODY> tags are required in the string).
 *
 * RETURNS: 0 if success, or non-zero if an error.
 *
 * NOTE: EmbedBrowserObject() must have been successfully called once with the
 * specified window, prior to calling this function. You need call
 * EmbedBrowserObject() once only, and then you can make multiple calls to
 * this function to display numerous pages in the specified window.
 */

long DisplayHTMLStr(HWND hwnd, LPCTSTR string)
{
 IWebBrowser2 *webBrowser2;
 LPDISPATCH  lpDispatch;
 IHTMLDocument2 *htmlDoc2;
 IOleObject  *browserObject;
 SAFEARRAY  *sfArray;
 VARIANT   myURL;
 VARIANT   *pVar;
 BSTR   bstr;

 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
 // we initially attached the browser object to this window.
 browserObject = *((IOleObject **)GetWindowLong(hwnd, GWL_USERDATA));

 // Assume an error.
 bstr = 0;

 // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
 // object, so we can call some of the functions in the former's table.
 if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
 {
  // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
  // webBrowser2->lpVtbl.

  // Before we can get_Document(), we actually need to have some HTML page loaded in the browser. So,
  // let's load an empty HTML page. Then, once we have that empty page, we can get_Document() and
  // write() to stuff our HTML string into it.
  VariantInit(&myURL);
  myURL.vt = VT_BSTR;
  myURL.bstrVal = SysAllocString(L"about:blank");

  // Call the Navigate2() function to actually display the page.
  webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0);

  // Free any resources (including the BSTR).
  VariantClear(&myURL);

  // Call the IWebBrowser2 object's get_Document so we can get its DISPATCH object. I don't know why you
  // don't get the DISPATCH object via the browser object's QueryInterface(), but you don't.
  if (!webBrowser2->lpVtbl->get_Document(webBrowser2, &lpDispatch))
  {
   // We want to get a pointer to the IHTMLDocument2 object embedded within the DISPATCH
   // object, so we can call some of the functions in the former's table.
   if (!lpDispatch->lpVtbl->QueryInterface(lpDispatch, &IID_IHTMLDocument2, (void**)&htmlDoc2))
   {
    // Ok, now the pointer to our IHTMLDocument2 object is in 'htmlDoc2', and so its VTable is
    // htmlDoc2->lpVtbl.

    // Our HTML must be in the form of a BSTR. And it must be passed to write() in an
    // array of "VARIENT" structs. So let's create all that.
    if ((sfArray = SafeArrayCreate(VT_VARIANT, 1, (SAFEARRAYBOUND *)&ArrayBound)))
    {
     if (!SafeArrayAccessData(sfArray, (void**)&pVar))
     {
      pVar->vt = VT_BSTR;
#ifndef UNICODE
      {
      wchar_t  *buffer;
      DWORD  size;

      size = MultiByteToWideChar(CP_ACP, 0, string, -1, 0, 0);
      if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) goto bad;
      MultiByteToWideChar(CP_ACP, 0, string, -1, buffer, size);
      bstr = SysAllocString(buffer);
      GlobalFree(buffer);
      }
#else
      bstr = SysAllocString(string);
#endif
      // Store our BSTR pointer in the VARIENT.
      if ((pVar->bstrVal = bstr))
      {
       // Pass the VARIENT with its BSTR to write() in order to shove our desired HTML string
       // into the body of that empty page we created above.
       htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);

       // Normally, we'd need to free our BSTR, but SafeArrayDestroy() does it for us
//       SysFreeString(bstr);
      }
     }

     // Free the array. This also frees the VARIENT that SafeArrayAccessData created for us,
     // and even frees the BSTR we allocated with SysAllocString
     SafeArrayDestroy(sfArray);
    }

    // Release the IHTMLDocument2 object.
bad:   htmlDoc2->lpVtbl->Release(htmlDoc2);
   }

   // Release the DISPATCH object.
   lpDispatch->lpVtbl->Release(lpDispatch);
  }

  // Release the IWebBrowser2 object.
  webBrowser2->lpVtbl->Release(webBrowser2);
 }

 // No error?
 if (bstr) return(0);

 // An error
 return(-1);
}




/******************************* DisplayHTMLPage() ****************************
 * Displays a URL, or HTML file on disk.
 *
 * hwnd =  Handle to the window hosting the browser object.
 * webPageName = Pointer to nul-terminated name of the URL/file.
 *
 * RETURNS: 0 if success, or non-zero if an error.
 *
 * NOTE: EmbedBrowserObject() must have been successfully called once with the
 * specified window, prior to calling this function. You need call
 * EmbedBrowserObject() once only, and then you can make multiple calls to
 * this function to display numerous pages in the specified window.
 */

long DisplayHTMLPage(HWND hwnd, LPTSTR webPageName)
{
 IWebBrowser2 *webBrowser2;
 VARIANT   myURL;
 IOleObject  *browserObject;

 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
 // we initially attached the browser object to this window.
 browserObject = *((IOleObject **)GetWindowLong(hwnd, GWL_USERDATA));

 // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
 // object, so we can call some of the functions in the former's table.
 if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
 {
  // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
  // webBrowser2->lpVtbl.

  // Our URL (ie, web address, such as "http://www.microsoft.com" or an HTM filename on disk
  // such as "c:\myfile.htm") must be passed to the IWebBrowser2's Navigate2() function as a BSTR.
  // A BSTR is like a pascal version of a double-byte character string. In other words, the
  // first unsigned short is a count of how many characters are in the string, and then this
  // is followed by those characters, each expressed as an unsigned short (rather than a
  // char). The string is not nul-terminated. The OS function SysAllocString can allocate and
  // copy a UNICODE C string to a BSTR. Of course, we'll need to free that BSTR after we're done
  // with it. If we're not using UNICODE, we first have to convert to a UNICODE string.
  //
  // What's more, our BSTR needs to be stuffed into a VARIENT struct, and that VARIENT struct is
  // then passed to Navigate2(). Why? The VARIENT struct makes it possible to define generic
  // 'datatypes' that can be used with all languages. Not all languages support things like
  // nul-terminated C strings. So, by using a VARIENT, whose first field tells what sort of
  // data (ie, string, float, etc) is in the VARIENT, COM interfaces can be used by just about
  // any language.
  VariantInit(&myURL);
  myURL.vt = VT_BSTR;

#ifndef UNICODE
  {
  wchar_t  *buffer;
  DWORD  size;

  size = MultiByteToWideChar(CP_ACP, 0, webPageName, -1, 0, 0);
  if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) goto badalloc;
  MultiByteToWideChar(CP_ACP, 0, webPageName, -1, buffer, size);
  myURL.bstrVal = SysAllocString(buffer);
  GlobalFree(buffer);
  }
#else
  myURL.bstrVal = SysAllocString(webPageName);
#endif
  if (!myURL.bstrVal)
  {
badalloc: webBrowser2->lpVtbl->Release(webBrowser2);
   return(-6);
  }

  // Call the Navigate2() function to actually display the page.
  webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0);

  // Free any resources (including the BSTR we allocated above).
  VariantClear(&myURL);

  // We no longer need the IWebBrowser2 object (ie, we don't plan to call any more functions in it,
  // so we can release our hold on it). Note that we'll still maintain our hold on the browser
  // object.
  webBrowser2->lpVtbl->Release(webBrowser2);

  // Success
  return(0);
 }

 return(-5);
}



/***************************** EmbedBrowserObject() **************************
 * Puts the browser object inside our host window, and save a pointer to this
 * window's browser object in the window's GWL_USERDATA field.
 *
 * hwnd =  Handle of our window into which we embed the browser object.
 *
 * RETURNS: 0 if success, or non-zero if an error.
 *
 * NOTE: We tell the browser object to occupy the entire client area of the
 * window.
 *
 * NOTE: No HTML page will be displayed here. We can do that with a subsequent
 * call to either DisplayHTMLPage() or DisplayHTMLStr(). This is merely once-only
 * initialization for using the browser object. In a nutshell, what we do
 * here is get a pointer to the browser object in our window's GWL_USERDATA
 * so we can access that object's functions whenever we want, and we also pass
 * pointers to our IOleClientSite, IOleInPlaceFrame, and IStorage structs so that
 * the browser can call our functions in our struct's VTables.
 */

long EmbedBrowserObject(HWND hwnd)
{
 IOleObject   *browserObject;
 IWebBrowser2  *webBrowser2;
 RECT    rect;
 char    *ptr;
 IOleInPlaceFrameEx *iOleInPlaceFrameEx;
 _IOleClientSiteEx *_iOleClientSiteEx;

 // Our IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame functions need to get our window handle. We
 // could store that in some global. But then, that would mean that our functions would work with only that
 // one window. If we want to create multiple windows, each hosting its own browser object (to display its
 // own web page), then we need to create a unique IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame
 // structs for each window. (Actually, the IOleClientSite and IOleInPlaceSite must be allocated as a
 // single struct, with the IOleClientSite embedded first). And we'll put an extra field at the end of those
 // structs to store our extra data such as a window handle. Remember that a pointer to our IOleClientSite we
 // create here will be passed as the first arg to every one of our IOleClientSite functions. Ditto with the
 // IOleInPlaceFrame object we create here, and the IOleInPlaceFrame functions. So, our functions are able to
 // retrieve the window handle we'll store here, and then, they'll work with all such windows containing a
 // browser control. Of course, that means we need to GlobalAlloc the structs now. We'll just get all 3 with
 // a single call to GlobalAlloc, but you could do them separately if desired.
 //
 // Um, we're not actually allocating a IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame structs. Because
 // we're appending our own fields to them, we're getting an IOleInPlaceFrameEx and an _IOleClientSiteEx (which
 // contains both the IOleClientSite and IOleInPlaceSite. But as far as the browser is concerned, it thinks that
 // we're giving it the plain old IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame.
 //
 // One final thing. We're going to allocate extra room to store the pointer to the browser object.
 if (!(ptr = (char *)GlobalAlloc(GMEM_FIXED, sizeof(IOleInPlaceFrameEx) + sizeof(_IOleClientSiteEx) + sizeof(IOleObject *))))
  return(-1);
 
 // Initialize our IOleInPlaceFrame object with a pointer to our IOleInPlaceFrame VTable.
 iOleInPlaceFrameEx = (IOleInPlaceFrameEx *)(ptr + sizeof(IOleObject *));
 iOleInPlaceFrameEx->frame.lpVtbl = &MyIOleInPlaceFrameTable;

 // Save our HWND (in the IOleInPlaceFrame object) so our IOleInPlaceFrame functions can retrieve it.
 iOleInPlaceFrameEx->window = hwnd;

 // Initialize our IOleClientSite object with a pointer to our IOleClientSite VTable.
 _iOleClientSiteEx = (_IOleClientSiteEx *)(ptr + sizeof(IOleInPlaceFrameEx) + sizeof(IOleObject *));
 _iOleClientSiteEx->client.lpVtbl = &MyIOleClientSiteTable;

 // Initialize our IOleInPlaceSite object with a pointer to our IOleInPlaceSite VTable.
 _iOleClientSiteEx->inplace.inplace.lpVtbl = &MyIOleInPlaceSiteTable;

 // Save a pointer to our IOleInPlaceFrameEx object so that our IOleInPlaceSite functions can retrieve it.
 _iOleClientSiteEx->inplace.frame = iOleInPlaceFrameEx;

 // Get a pointer to the browser object and lock it down (so it doesn't "disappear" while we're using
 // it in this program). We do this by calling the OS function OleCreate().
 //
 // NOTE: We need this pointer to interact with and control the browser. With normal WIN32 controls such as a
 // Static, Edit, Combobox, etc, you obtain an HWND and send messages to it with SendMessage(). Not so with
 // the browser object. You need to get a pointer to its "base structure" (as returned by OleCreate()). This
 // structure contains an array of pointers to functions you can call within the browser object. Actually, the
 // base structure contains a 'lpVtbl' field that is a pointer to that array. We'll call the array a 'VTable'.
 //
 // For example, the browser object happens to have a SetHostNames() function we want to call. So, after we
 // retrieve the pointer to the browser object (in a local we'll name 'browserObject'), then we can call that
 // function, and pass it args, as so:
 //
 // browserObject->lpVtbl->SetHostNames(browserObject, SomeString, SomeString);
 //
 // There's our pointer to the browser object in 'browserObject'. And there's the pointer to the browser object's
 // VTable in 'browserObject->lpVtbl'. And the pointer to the SetHostNames function happens to be stored in an
 // field named 'SetHostNames' within the VTable. So we are actually indirectly calling SetHostNames by using
 // a pointer to it. That's how you use a VTable.
 //
 // NOTE: We pass our _IOleClientSiteEx struct and lie -- saying that it's a IOleClientSite. It's ok. A
 // _IOleClientSiteEx struct starts with an embedded IOleClientSite. So the browser won't care, and we want
 // this extended struct passed to our IOleClientSite functions.

 if (!OleCreate(&CLSID_WebBrowser, &IID_IOleObject, OLERENDER_DRAW, 0, (IOleClientSite *)_iOleClientSiteEx, &MyIStorage, (void**)&browserObject))
 {
  // Ok, we now have the pointer to the browser object in 'browserObject'. Let's save this in the
  // memory block we allocated above, and then save the pointer to that whole thing in our window's
  // USERDATA field. That way, if we need multiple windows each hosting its own browser object, we can
  // call EmbedBrowserObject() for each one, and easily associate the appropriate browser object with
  // its matching window and its own objects containing per-window data.
  *((IOleObject **)ptr) = browserObject;
  SetWindowLong(hwnd, GWL_USERDATA, (LONG)ptr);

  // We can now call the browser object's SetHostNames function. SetHostNames lets the browser object know our
  // application's name and the name of the document in which we're embedding the browser. (Since we have no
  // document name, we'll pass a 0 for the latter). When the browser object is opened for editing, it displays
  // these names in its titlebar.
  //
  // We are passing 3 args to SetHostNames. You'll note that the first arg to SetHostNames is the base
  // address of our browser control. This is something that you always have to remember when working in C
  // (as opposed to C++). When calling a VTable function, the first arg to that function must always be the
  // structure which contains the VTable. (In this case, that's the browser control itself). Why? That's
  // because that function is always assumed to be written in C++. And the first argument to any C++ function
  // must be its 'this' pointer (ie, the base address of its class, which in this case is our browser object
  // pointer). In C++, you don't have to pass this first arg, because the C++ compiler is smart enough to
  // produce an executable that always adds this first arg. In fact, the C++ compiler is smart enough to
  // know to fetch the function pointer from the VTable, so you don't even need to reference that. In other
  // words, the C++ equivalent code would be:
  //
  // browserObject->SetHostNames(L"My Host Name", 0);
  //
  // So, when you're trying to convert C++ code to C, always remember to add this first arg whenever you're
  // dealing with a VTable (ie, the field is usually named 'lpVtbl') in the standard objects, and also add
  // the reference to the VTable itself.
  //
  // Oh yeah, the L is because we need UNICODE strings. And BTW, the host and document names can be anything
  // you want.

  browserObject->lpVtbl->SetHostNames(browserObject, L"My Host Name", 0);

  GetClientRect(hwnd, &rect);

  // Let browser object know that it is embedded in an OLE container.
  if (!OleSetContainedObject((struct IUnknown *)browserObject, TRUE) &&

   // Set the display area of our browser control the same as our window's size
   // and actually put the browser object into our window.
   !browserObject->lpVtbl->DoVerb(browserObject, OLEIVERB_SHOW, NULL, (IOleClientSite *)_iOleClientSiteEx, -1, hwnd, &rect) &&

   // Ok, now things may seem to get even trickier, One of those function pointers in the browser's VTable is
   // to the QueryInterface() function. What does this function do? It lets us grab the base address of any
   // other object that may be embedded within the browser object. And this other object has its own VTable
   // containing pointers to more functions we can call for that object.
   //
   // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
   // object, so we can call some of the functions in the former's table. For example, one IWebBrowser2 function
   // we intend to call below will be Navigate2(). So we call the browser object's QueryInterface to get our
   // pointer to the IWebBrowser2 object.
   !browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
  {
   // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
   // webBrowser2->lpVtbl.

   // Let's call several functions in the IWebBrowser2 object to position the browser display area
   // in our window. The functions we call are put_Left(), put_Top(), put_Width(), and put_Height().
   // Note that we reference the IWebBrowser2 object's VTable to get pointers to those functions. And
   // also note that the first arg we pass to each is the pointer to the IWebBrowser2 object.
   webBrowser2->lpVtbl->put_Left(webBrowser2, 0);
   webBrowser2->lpVtbl->put_Top(webBrowser2, 0);
   webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right);
   webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom);

   // We no longer need the IWebBrowser2 object (ie, we don't plan to call any more functions in it
   // right now, so we can release our hold on it). Note that we'll still maintain our hold on the
   // browser object until we're done with that object.
   webBrowser2->lpVtbl->Release(webBrowser2);

   // Success
   return(0);
  }

  // Something went wrong!
  UnEmbedBrowserObject(hwnd);
  return(-3);
 }

 GlobalFree(ptr);
 return(-2);
}




/****************************** WindowProc() ***************************
 * Our message handler for our window to host the browser.
 */

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 if (uMsg == WM_CREATE)
 {
  // Embed the browser object into our host window. We need do this only
  // once. Note that the browser object will start calling some of our
  // IOleInPlaceFrame and IOleClientSite functions as soon as we start
  // calling browser object functions in EmbedBrowserObject().
  if (EmbedBrowserObject(hwnd)) return(-1);

  // Another window created with an embedded browser object
  ++WindowCount;

  // Success
  return(0);
 }

 if (uMsg == WM_DESTROY)
 {
  // Detach the browser object from this window, and free resources.
  UnEmbedBrowserObject(hwnd);

  // One less window
  --WindowCount;

  // If all the windows are now closed, quit this app
  if (!WindowCount) PostQuitMessage(0);

  return(TRUE);
 }

 // NOTE: If you want to resize the area that the browser object occupies when you
 // resize the window, then handle WM_SIZE and use the IWebBrowser2's put_Width()
 // and put_Height() to give it the new dimensions.

 return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}



/****************************** WinMain() ***************************
 * C program entry point.
 *
 * This creates a window to host the web browser, and displays a web
 * page.
 */

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hInstNULL, LPSTR lpszCmdLine, int nCmdShow)
{
 MSG   msg;

 // Initialize the OLE interface. We do this once-only.
 if (OleInitialize(NULL) == S_OK)
 {
  WNDCLASSEX  wc;

  // Register the class of our window to host the browser. 'WindowProc' is our message handler
  // and 'ClassName' is the class name. You can choose any class name you want.
  ZeroMemory(&wc, sizeof(WNDCLASSEX));
  wc.cbSize = sizeof(WNDCLASSEX);
  wc.hInstance = hInstance;
  wc.lpfnWndProc = WindowProc;
  wc.lpszClassName = &ClassName[0];
  RegisterClassEx(&wc);

  // Create a window. NOTE: We embed the browser object duing our WM_CREATE handling for
  // this window.
/*  if ((msg.hwnd = CreateWindowEx(0, &ClassName[0], "An HTML string", WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
       HWND_DESKTOP, NULL, hInstance, 0)))
  {
   // For this window, display a string in the BODY of a web page.
   DisplayHTMLStr(msg.hwnd, "<H2><CENTER>HTML string test</CENTER></H2><P><FONT COLOR=RED>This is a <U>HTML string</U> in memory.</FONT>");

   // Show the window.
   ShowWindow(msg.hwnd, nCmdShow);
   UpdateWindow(msg.hwnd);
  }
*/
  // Create another window with another browser object embedded in it.
  if ((msg.hwnd = CreateWindowEx(0, &ClassName[0], "Microsoft's web site", WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
      HWND_DESKTOP, NULL, hInstance, 0)))
  {
   // For this window, display a URL. This could also be a HTML file on disk such as "c:\\myfile.htm".
   DisplayHTMLPage(msg.hwnd, "http://www.naver.com/");

   // Show the window.
   ShowWindow(msg.hwnd, nCmdShow);
   UpdateWindow(msg.hwnd);
  }

  // Do a message loop until WM_QUIT.
  while (GetMessage(&msg, 0, 0, 0))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }

  // Free the OLE library.
  OleUninitialize();

  return(0);
 }

 MessageBox(0, "Can't open OLE!", "ERROR", MB_OK);
 return(-1);
}


코드 구루였나.. 거기서 가져온겁니다...
문제는 C언어라.. C++로 돌리면 컴파일 에러가 난다는거...
음... C++로 돌려야 할텐데..

블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

댓글을 달아 주세요