home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap09 / linkuser / linkuser.cpp next >
C/C++ Source or Header  |  1996-05-14  |  12KB  |  529 lines

  1. /*
  2.  * LINKUSER.CPP
  3.  * Link User Chapter 9
  4.  *
  5.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  6.  *
  7.  * Kraig Brockschmidt, Microsoft
  8.  * Internet  :  kraigb@microsoft.com
  9.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  10.  */
  11.  
  12.  
  13. #define INITGUIDS
  14. #include "linkuser.h"
  15.  
  16.  
  17. /*
  18.  * WinMain
  19.  *
  20.  * Purpose:
  21.  *  Main entry point of application.
  22.  */
  23.  
  24. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  25.     , LPSTR pszCmdLine, int nCmdShow)
  26.     {
  27.     MSG         msg;
  28.     PAPP        pApp;
  29.  
  30.     SETMESSAGEQUEUE(96);
  31.  
  32.     pApp=new CApp(hInst, hInstPrev, nCmdShow);
  33.  
  34.     if (NULL==pApp)
  35.         return -1;
  36.  
  37.     if (pApp->Init())
  38.         {
  39.         while (GetMessage(&msg, NULL, 0,0 ))
  40.             {
  41.             TranslateMessage(&msg);
  42.             DispatchMessage(&msg);
  43.             }
  44.         }
  45.  
  46.     delete pApp;
  47.     return msg.wParam;
  48.     }
  49.  
  50.  
  51.  
  52.  
  53.  
  54. /*
  55.  * DataUserWndProc
  56.  *
  57.  * Purpose:
  58.  *  Window class procedure.  Standard callback.
  59.  */
  60.  
  61. LRESULT APIENTRY LinkUserWndProc(HWND hWnd, UINT iMsg
  62.     , WPARAM wParam, LPARAM lParam)
  63.     {
  64.     PAPP    pApp;
  65.     RECT    rc;
  66.  
  67.     COMMANDPARAMS(wID, wCode, hWndMsg);
  68.  
  69.     pApp=(PAPP)GetWindowLong(hWnd, LINKUSERWL_STRUCTURE);
  70.  
  71.     switch (iMsg)
  72.         {
  73.         case WM_NCCREATE:
  74.             pApp=(PAPP)((LPCREATESTRUCT)lParam)->lpCreateParams;
  75.             SetWindowLong(hWnd, LINKUSERWL_STRUCTURE, (LONG)pApp);
  76.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  77.  
  78.         case WM_DESTROY:
  79.             PostQuitMessage(0);
  80.             break;
  81.  
  82.         case WM_SIZE:
  83.             //Keep the listbox filling the client area
  84.             GetClientRect(hWnd, &rc);
  85.             SetWindowPos(pApp->m_hWndList, NULL, rc.left, rc.top
  86.                 , rc.right-rc.left, rc.bottom-rc.top
  87.                 , SWP_NOZORDER | SWP_NOACTIVATE);
  88.             break;
  89.  
  90.         case WM_COMMAND:
  91.             wID=LOWORD(wParam);
  92.  
  93.             switch (wID)
  94.                 {
  95.                 case ID_LISTOLINKS:
  96.                     switch (wCode)
  97.                         {
  98.                         case LBN_DBLCLK:
  99.                             pApp->ShowDescription();
  100.                             break;
  101.                         }
  102.  
  103.                     break;
  104.  
  105.                 case IDM_LINKSHOWDESCRIPTION:
  106.                     //Same as double-clicking in listbox
  107.                     pApp->ShowDescription();
  108.                     break;
  109.  
  110.                 case IDM_LINKPARSEANDBIND:
  111.                     pApp->ParseAndBind();
  112.                     break;
  113.  
  114.                 case IDM_LINKEXIT:
  115.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  116.                     break;
  117.  
  118.                 default:
  119.                     break;
  120.                 }
  121.             break;
  122.  
  123.         default:
  124.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  125.         }
  126.  
  127.     return 0L;
  128.     }
  129.  
  130.  
  131.  
  132.  
  133.  
  134. /*
  135.  * CApp::CApp
  136.  * CApp::~CApp
  137.  *
  138.  * Constructor Parameters: (from WinMain)
  139.  *  hInst           HINSTANCE of the application.
  140.  *  hInstPrev       HINSTANCE of a previous instance.
  141.  *  nCmdShow        UINT specifying how to show the app window.
  142.  */
  143.  
  144. CApp::CApp(HINSTANCE hInst, HINSTANCE hInstPrev
  145.     , UINT nCmdShow)
  146.     {
  147.     UINT        i;
  148.  
  149.     m_hInst=hInst;
  150.     m_hInstPrev=hInstPrev;
  151.     m_nCmdShow=nCmdShow;
  152.  
  153.     m_hWnd=NULL;
  154.     m_fInitialized=FALSE;
  155.     m_hWndList=NULL;
  156.  
  157.     for (i=0; i < CMONIKERS; i++)
  158.         m_rgpmk[i]=NULL;
  159.  
  160.     return;
  161.     }
  162.  
  163.  
  164. CApp::~CApp(void)
  165.     {
  166.     UINT        i;
  167.  
  168.     for (i=0; i < CMONIKERS; i++)
  169.         ReleaseInterface(m_rgpmk[i]);
  170.  
  171.     if (IsWindow(m_hWnd))
  172.         DestroyWindow(m_hWnd);  //Destroys listbox
  173.  
  174.     if (m_fInitialized)
  175.         CoUninitialize();
  176.  
  177.     return;
  178.     }
  179.  
  180.  
  181.  
  182.  
  183. /*
  184.  * CApp::Init
  185.  *
  186.  * Purpose:
  187.  *  Initializes an CApp object by registering window classes,
  188.  *  creating the main window, and doing anything else prone to
  189.  *  failure such as calling CoInitialize.  If this function fails
  190.  *  the caller should insure that the destructor is called.
  191.  *
  192.  * Parameters:
  193.  *  None
  194.  *
  195.  * Return Value:
  196.  *  BOOL            TRUE if successful, FALSE otherwise.
  197.  */
  198.  
  199. BOOL CApp::Init(void)
  200.     {
  201.     WNDCLASS    wc;
  202.     BOOL        fRet;
  203.     RECT        rc;
  204.  
  205.     CHECKVER_COM;
  206.  
  207.     if (FAILED(CoInitialize(NULL)))
  208.         return FALSE;
  209.  
  210.     m_fInitialized=TRUE;
  211.  
  212.     //Register our window classes.
  213.     if (!m_hInstPrev)
  214.         {
  215.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  216.         wc.lpfnWndProc    = LinkUserWndProc;
  217.         wc.cbClsExtra     = 0;
  218.         wc.cbWndExtra     = CBWNDEXTRA;
  219.         wc.hInstance      = m_hInst;
  220.         wc.hIcon          = LoadIcon(m_hInst, TEXT("Icon"));
  221.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  222.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  223.         wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU);
  224.         wc.lpszClassName  = TEXT("LINKUSER");
  225.  
  226.         if (!RegisterClass(&wc))
  227.             return FALSE;
  228.         }
  229.  
  230.     //Create the main window.
  231.     m_hWnd=CreateWindow(TEXT("LINKUSER"), TEXT("Link User")
  232.         , WS_OVERLAPPEDWINDOW,35, 35, 420, 250, NULL
  233.         , NULL, m_hInst, this);
  234.  
  235.     if (NULL==m_hWnd)
  236.         return FALSE;
  237.  
  238.     //Create the list of monikers
  239.     GetClientRect(m_hWnd, &rc);
  240.     m_hWndList=CreateWindow(TEXT("listbox"), TEXT("LinkList")
  241.         , WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT
  242.         , rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top
  243.         , m_hWnd, (HMENU)ID_LISTOLINKS, m_hInst, NULL);
  244.  
  245.     if (NULL==m_hWndList)
  246.         return FALSE;
  247.  
  248.     if (!CreateMonikers())
  249.         return FALSE;
  250.  
  251.     if (!ListInitialize())
  252.         return FALSE;
  253.  
  254.     ShowWindow(m_hWnd, m_nCmdShow);
  255.     UpdateWindow(m_hWnd);
  256.  
  257.     return fRet;
  258.     }
  259.  
  260.  
  261.  
  262. /*
  263.  * CApp::CreateMonikers
  264.  *
  265.  * Purpose:
  266.  *  Creates monikers and stores them in m_rgpmk.
  267.  *
  268.  * Parameters:
  269.  *  None
  270.  *
  271.  * Return Value:
  272.  *  BOOL            TRUE if successful, FALSE otherwise.
  273.  */
  274.  
  275. BOOL CApp::CreateMonikers(void)
  276.     {
  277.     TCHAR       szFile[]=TEXT("c:\\inole\\chap09\\linksrc\\goop.lks");
  278.     TCHAR       szItem1[]=TEXT("Object 2");
  279.     TCHAR       szItem2[]=TEXT("Sub-Object 3");
  280.     TCHAR       szDelim[]=TEXT("!");
  281.     IMoniker   *pmkItem;
  282.     HRESULT     hr;
  283.  
  284.     //Create a simple file moniker
  285.     if (FAILED(CreateFileMoniker(szFile, &m_rgpmk[0])))
  286.         return FALSE;
  287.  
  288.     //Create File!Item moniker, item first, then composite
  289.     if (FAILED(CreateItemMoniker(szDelim, szItem1, &pmkItem)))
  290.         return FALSE;
  291.  
  292.     //The output here will be the File!Item moniker
  293.     hr=m_rgpmk[0]->ComposeWith(pmkItem, FALSE, &m_rgpmk[1]);
  294.     pmkItem->Release();
  295.  
  296.     if (FAILED(hr))
  297.         return FALSE;
  298.  
  299.     /*
  300.      * Now create the File!Item!Item by appending another item
  301.      * onto the File!Item just created.
  302.      */
  303.     if (FAILED(CreateItemMoniker(szDelim, szItem2, &pmkItem)))
  304.         return FALSE;
  305.  
  306.     hr=m_rgpmk[1]->ComposeWith(pmkItem, FALSE, &m_rgpmk[2]);
  307.     pmkItem->Release();
  308.  
  309.     if (FAILED(hr))
  310.         return FALSE;
  311.  
  312.     return TRUE;
  313.     }
  314.  
  315.  
  316.  
  317.  
  318. /*
  319.  * CApp::ListInitialize
  320.  *
  321.  * Purpose:
  322.  *  Retrieves the display names for each moniker in our
  323.  *  array and displays that name in the listbox.
  324.  *
  325.  * Parameters:
  326.  *  None
  327.  *
  328.  * Return Value:
  329.  *  BOOL            TRUE if successful, FALSE otherwise.
  330.  */
  331.  
  332. BOOL CApp::ListInitialize(void)
  333.     {
  334.     UINT        i;
  335.  
  336.     for (i=0; i < CMONIKERS; i++)
  337.         {
  338.         LPOLESTR    pszName;
  339.         HRESULT     hr;
  340.         IBindCtx   *pbc;
  341.  
  342.         if (FAILED(CreateBindCtx(0, &pbc)))
  343.             return FALSE;
  344.  
  345.         hr=m_rgpmk[i]->GetDisplayName(pbc, NULL, &pszName);
  346.         pbc->Release();
  347.  
  348.         if (FAILED(hr))
  349.             return FALSE;
  350.  
  351.        #ifdef WIN32ANSI
  352.         char    szTemp[256];
  353.  
  354.         WideCharToMultiByte(CP_ACP, 0, pszName, -1, szTemp, 256
  355.             , NULL, NULL);
  356.         SendMessage(m_hWndList, LB_ADDSTRING, 0, (LPARAM)szTemp);
  357.        #else
  358.         SendMessage(m_hWndList, LB_ADDSTRING, 0, (LPARAM)pszName);
  359.        #endif
  360.         }
  361.  
  362.     return TRUE;
  363.     }
  364.  
  365.  
  366.  
  367.  
  368. /*
  369.  * CApp::ShowDescription
  370.  *
  371.  * Purpose:
  372.  *  Tells CApp to retrieve the description text for a particular
  373.  *  item in its listbox.  This is done in response to a double-click
  374.  *  on a moniker display name which we bind to an ask for
  375.  *  IDescription.
  376.  *
  377.  * Parameters:
  378.  *  None
  379.  *
  380.  * Return Value:
  381.  *  None
  382.  */
  383.  
  384. void CApp::ShowDescription(void)
  385.     {
  386.     int             i;
  387.  
  388.     i=(int)SendMessage(m_hWndList, LB_GETCURSEL, 0, 0L);
  389.  
  390.     if (LB_ERR==i)
  391.         return;
  392.  
  393.     BindAndShow(m_rgpmk[i], NULL);
  394.     return;
  395.     }
  396.  
  397.  
  398.  
  399.  
  400. /*
  401.  * CApp::ParseAndBind
  402.  *
  403.  * Purpose:
  404.  *  Recreates a moniker from the display name under the current
  405.  *  selection then attempts to bind as with ShowDescription.
  406.  *
  407.  * Parameters:
  408.  *  None
  409.  *
  410.  * Return Value:
  411.  *  None
  412.  */
  413.  
  414. void CApp::ParseAndBind(void)
  415.     {
  416.     HRESULT         hr;
  417.     IBindCtx       *pbc;
  418.     IMoniker       *pmk;
  419.     int             i;
  420.     TCHAR           szName[512];
  421.     ULONG           chEaten=0;
  422.  
  423.     i=(int)SendMessage(m_hWndList, LB_GETCURSEL, 0, 0L);
  424.  
  425.     if (LB_ERR==i)
  426.         return;
  427.  
  428.     SendMessage(m_hWndList, LB_GETTEXT, i, (LPARAM)(LPTSTR)szName);
  429.  
  430.     if (FAILED(CreateBindCtx(0, &pbc)))
  431.         {
  432.         MessageBox(m_hWnd, TEXT("Failed to create bind context")
  433.             , TEXT("Link User"), MB_OK);
  434.         return;
  435.         }
  436.  
  437.  
  438.     hr=MkParseDisplayName(pbc, szName, &chEaten, &pmk);
  439.  
  440.     if (SUCCEEDED(hr))
  441.         {
  442.         MessageBox(m_hWnd, TEXT("Name parsed.  Press OK to bind...")
  443.             , TEXT("Link User"), MB_OK);
  444.  
  445.         BindAndShow(pmk, pbc);
  446.         pmk->Release();
  447.         }
  448.     else
  449.         {
  450.         //Tell the user how far parsing got
  451.         wsprintf(szName, TEXT("Parsing failed after %lu characters")
  452.             , chEaten);
  453.  
  454.         MessageBox(m_hWnd, szName, TEXT("Link User"), MB_OK);
  455.         }
  456.  
  457.     pbc->Release();
  458.     return;
  459.     }
  460.  
  461.  
  462.  
  463.  
  464. /*
  465.  * CApp::BindAndShow
  466.  *
  467.  * Purpose:
  468.  *  Binds to a given moniker to given moniker and requests
  469.  *  IDescription, asking that object for display text.
  470.  *
  471.  * Parameters:
  472.  *  pmk             IMoniker * naming the object.
  473.  *  pbc             IBindCtx * to use.  If NULL, this will use
  474.  *                  a default.
  475.  *
  476.  * Return Value:
  477.  *  None
  478.  */
  479.  
  480. void CApp::BindAndShow(IMoniker *pmk, IBindCtx *pbc)
  481.     {
  482.     HRESULT         hr;
  483.     IDescription    *pIDescription;
  484.  
  485.     if (NULL==pbc)
  486.         {
  487.         hr=BindMoniker(pmk, 0, IID_IDescription
  488.             , (void **)&pIDescription);
  489.         }
  490.     else
  491.         {
  492.         hr=pmk->BindToObject(pbc, NULL, IID_IDescription
  493.             , (void **)&pIDescription);
  494.         }
  495.  
  496.     if (SUCCEEDED(hr))
  497.         {
  498.         const ULONG cch=512;
  499.         TCHAR       szText[cch];
  500.  
  501.        #ifdef WIN32ANSI
  502.         WCHAR       szw[cch];
  503.         hr=pIDescription->GetText(szw, cch);
  504.         WideCharToMultiByte(CP_ACP, 0, szw, -1, szText, cch, NULL, NULL);
  505.        #else
  506.         hr=pIDescription->GetText(szText, cch);
  507.        #endif
  508.         pIDescription->Release();
  509.  
  510.         if (SUCCEEDED(hr))
  511.             {
  512.             MessageBox(m_hWnd, szText, TEXT("Description Is:")
  513.                 , MB_OK);
  514.             }
  515.         else
  516.             {
  517.             MessageBox(m_hWnd, TEXT("Failed to get description text")
  518.                 , TEXT("Link User"), MB_OK);
  519.             }
  520.         }
  521.     else
  522.         {
  523.         MessageBox(m_hWnd, TEXT("BindMoniker failed")
  524.             , TEXT("Link User"), MB_OK);
  525.         }
  526.  
  527.     return;
  528.     }
  529.