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 / chap10 / datauser / datauser.cpp next >
C/C++ Source or Header  |  1995-05-03  |  18KB  |  667 lines

  1. /*
  2.  * DATAUSER.CPP
  3.  * Data Object User Chapter 10
  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 "datauser.h"
  15.  
  16.  
  17. //These are for displaying clipboard formats textually.
  18. static TCHAR * rgszCF[13]={TEXT("Unknown"), TEXT("CF_TEXT")
  19.                  , TEXT("CF_BITMAP"), TEXT("CF_METAFILEPICT")
  20.                  , TEXT("CF_SYLK"), TEXT("CF_DIF"), TEXT("CF_TIFF")
  21.                  , TEXT("CF_OEMTEXT"), TEXT("CF_DIB")
  22.                  , TEXT("CF_PALETTE"), TEXT("CF_PENDATA")
  23.                  , TEXT("CF_RIFF"), TEXT("CF_WAVE")};
  24.  
  25.  
  26. static TCHAR szSuccess[]    =TEXT("succeeded");
  27. static TCHAR szFailed[]     =TEXT("failed");
  28. static TCHAR szExpected[]   =TEXT("expected");
  29. static TCHAR szUnexpected[] =TEXT("unexpected!");
  30.  
  31.  
  32. /*
  33.  * WinMain
  34.  *
  35.  * Purpose:
  36.  *  Main entry point of application.
  37.  */
  38.  
  39. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  40.     , LPSTR pszCmdLine, int nCmdShow)
  41.     {
  42.     MSG         msg;
  43.     PAPP        pApp;
  44.  
  45.     SETMESSAGEQUEUE(96);
  46.  
  47.     pApp=new CApp(hInst, hInstPrev, nCmdShow);
  48.  
  49.     if (NULL==pApp)
  50.         return -1;
  51.  
  52.     if (pApp->Init())
  53.         {
  54.         while (GetMessage(&msg, NULL, 0,0 ))
  55.             {
  56.             TranslateMessage(&msg);
  57.             DispatchMessage(&msg);
  58.             }
  59.         }
  60.  
  61.     delete pApp;
  62.     return msg.wParam;
  63.     }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. /*
  70.  * DataUserWndProc
  71.  *
  72.  * Purpose:
  73.  *  Window class procedure.  Standard callback.
  74.  */
  75.  
  76. LRESULT APIENTRY DataUserWndProc(HWND hWnd, UINT iMsg
  77.     , WPARAM wParam, LPARAM lParam)
  78.     {
  79.     HRESULT         hr;
  80.     PAPP            pApp;
  81.     HMENU           hMenu;
  82.     FORMATETC       fe;
  83.     WORD            wID;
  84.  
  85.     pApp=(PAPP)GetWindowLong(hWnd, DATAUSERWL_STRUCTURE);
  86.  
  87.     switch (iMsg)
  88.         {
  89.         case WM_NCCREATE:
  90.             pApp=(PAPP)((LPCREATESTRUCT)lParam)->lpCreateParams;
  91.             SetWindowLong(hWnd, DATAUSERWL_STRUCTURE, (LONG)pApp);
  92.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  93.  
  94.         case WM_DESTROY:
  95.             PostQuitMessage(0);
  96.             break;
  97.  
  98.         case WM_PAINT:
  99.             pApp->Paint();
  100.             break;
  101.  
  102.         case WM_COMMAND:
  103.             SETDefFormatEtc(fe, 0, TYMED_HGLOBAL | TYMED_GDI
  104.                 | TYMED_MFPICT);
  105.  
  106.             hMenu=GetMenu(hWnd);
  107.             wID=LOWORD(wParam);
  108.  
  109.             switch (wID)
  110.                 {
  111.                 case IDM_OBJECTUSEDLL:
  112.                     if (!pApp->m_fEXE)
  113.                         break;
  114.  
  115.                     pApp->m_fEXE=FALSE;
  116.                     pApp->FReloadDataObjects(TRUE);
  117.                     break;
  118.  
  119.  
  120.                 case IDM_OBJECTUSEEXE:
  121.                     if (pApp->m_fEXE)
  122.                         break;
  123.  
  124.                     pApp->m_fEXE=TRUE;
  125.                     pApp->FReloadDataObjects(TRUE);
  126.                     break;
  127.  
  128.                 case IDM_OBJECTDATASIZESMALL:
  129.                 case IDM_OBJECTDATASIZEMEDIUM:
  130.                 case IDM_OBJECTDATASIZELARGE:
  131.                     CheckMenuItem(hMenu
  132.                         , IDM_OBJECTDATASIZESMALL,  MF_UNCHECKED);
  133.                     CheckMenuItem(hMenu
  134.                         , IDM_OBJECTDATASIZEMEDIUM, MF_UNCHECKED);
  135.                     CheckMenuItem(hMenu
  136.                         , IDM_OBJECTDATASIZELARGE,  MF_UNCHECKED);
  137.                     CheckMenuItem(hMenu, wID,  MF_CHECKED);
  138.  
  139.                     //Kill old advise.
  140.                     if (NULL!=pApp->m_pIDataObject
  141.                         || 0!=pApp->m_dwConn)
  142.                         {
  143.                         pApp->m_pIDataObject->DUnadvise(pApp
  144.                             ->m_dwConn);
  145.                         }
  146.  
  147.                     if (IDM_OBJECTDATASIZELARGE==wID)
  148.                         pApp->m_pIDataObject=pApp->m_pIDataLarge;
  149.                     else if (IDM_OBJECTDATASIZEMEDIUM==wID)
  150.                         pApp->m_pIDataObject=pApp->m_pIDataMedium;
  151.                     else
  152.                         pApp->m_pIDataObject=pApp->m_pIDataSmall;
  153.  
  154.                     //Setup new advise.
  155.                     fe.cfFormat=pApp->m_cfAdvise;
  156.                     pApp->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
  157.                         , pApp->m_pIAdviseSink, &pApp->m_dwConn);
  158.  
  159.                     break;
  160.  
  161.                 case IDM_OBJECTQUERYGETDATA:
  162.                     if (NULL==pApp->m_pIDataObject)
  163.                         break;
  164.  
  165.                     fe.tymed=TYMED_HGLOBAL | TYMED_GDI
  166.                          | TYMED_MFPICT;
  167.  
  168.                     pApp->TryQueryGetData(&fe, CF_TEXT, TRUE, 0);
  169.                     pApp->TryQueryGetData(&fe, CF_BITMAP, TRUE, 1);
  170.                     pApp->TryQueryGetData(&fe, CF_DIB, FALSE, 2);
  171.                     pApp->TryQueryGetData(&fe, CF_METAFILEPICT
  172.                         , TRUE, 3);
  173.                     pApp->TryQueryGetData(&fe, CF_WAVE, FALSE, 4);
  174.                     break;
  175.  
  176.  
  177.                 case IDM_OBJECTGETDATATEXT:
  178.                 case IDM_OBJECTGETDATABITMAP:
  179.                 case IDM_OBJECTGETDATAMETAFILEPICT:
  180.                     if (NULL==pApp->m_pIDataObject)
  181.                         break;
  182.  
  183.                     //Clean up whatever we currently have.
  184.                     pApp->m_cf=0;
  185.                     ReleaseStgMedium(&pApp->m_stm);
  186.  
  187.                     if (IDM_OBJECTGETDATATEXT==wID)
  188.                         SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
  189.  
  190.                     if (IDM_OBJECTGETDATABITMAP==wID)
  191.                         SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  192.  
  193.                     if (IDM_OBJECTGETDATAMETAFILEPICT==wID)
  194.                         {
  195.                         SETDefFormatEtc(fe, CF_METAFILEPICT
  196.                             , TYMED_MFPICT);
  197.                         }
  198.  
  199.                     hr=pApp->m_pIDataObject->GetData(&fe
  200.                         , &(pApp->m_stm));
  201.  
  202.                     if (SUCCEEDED(hr))
  203.                         pApp->m_cf=fe.cfFormat;
  204.  
  205.                     InvalidateRect(hWnd, NULL, TRUE);
  206.                     UpdateWindow(hWnd);
  207.                     break;
  208.  
  209.                 case IDM_OBJECTEXIT:
  210.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  211.                     break;
  212.  
  213.  
  214.                 case IDM_ADVISETEXT:
  215.                 case IDM_ADVISEBITMAP:
  216.                 case IDM_ADVISEMETAFILEPICT:
  217.                     if (NULL==pApp->m_pIDataObject)
  218.                         break;
  219.  
  220.                     //Terminate the old connection
  221.                     if (0!=pApp->m_dwConn)
  222.                         {
  223.                         pApp->m_pIDataObject->DUnadvise(pApp
  224.                             ->m_dwConn);
  225.                         }
  226.  
  227.                     CheckMenuItem(hMenu, pApp->m_cfAdvise
  228.                         +IDM_ADVISEMIN, MF_UNCHECKED);
  229.                     CheckMenuItem(hMenu, wID, MF_CHECKED);
  230.  
  231.                     //New format is wID-IDM_ADVISEMIN
  232.                     pApp->m_cfAdvise=(UINT)(wID-IDM_ADVISEMIN);
  233.                     fe.cfFormat=pApp->m_cfAdvise;
  234.                     pApp->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
  235.                         , pApp->m_pIAdviseSink, &pApp->m_dwConn);
  236.  
  237.                     break;
  238.  
  239.                 case IDM_ADVISEGETDATA:
  240.                     pApp->m_fGetData=!pApp->m_fGetData;
  241.                     CheckMenuItem(hMenu, wID, pApp->m_fGetData
  242.                         ? MF_CHECKED : MF_UNCHECKED);
  243.                     break;
  244.  
  245.                 case IDM_ADVISEREPAINT:
  246.                     pApp->m_fRepaint=!pApp->m_fRepaint;
  247.                     CheckMenuItem(hMenu, wID, pApp->m_fRepaint
  248.                         ? MF_CHECKED : MF_UNCHECKED);
  249.                     break;
  250.  
  251.                 default:
  252.                     break;
  253.                 }
  254.             break;
  255.  
  256.         default:
  257.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  258.         }
  259.  
  260.     return 0L;
  261.     }
  262.  
  263.  
  264.  
  265.  
  266.  
  267. /*
  268.  * CApp::CApp
  269.  * CApp::~CApp
  270.  *
  271.  * Constructor Parameters: (from WinMain)
  272.  *  hInst           HINSTANCE of the application.
  273.  *  hInstPrev       HINSTANCE of a previous instance.
  274.  *  nCmdShow        UINT specifying how to show the app window.
  275.  */
  276.  
  277. CApp::CApp(HINSTANCE hInst, HINSTANCE hInstPrev
  278.     , UINT nCmdShow)
  279.     {
  280.     m_hInst=hInst;
  281.     m_hInstPrev=hInstPrev;
  282.     m_nCmdShow=nCmdShow;
  283.  
  284.     m_hWnd=NULL;
  285.     m_fEXE=FALSE;
  286.  
  287.     m_pIAdviseSink=NULL;
  288.     m_dwConn=0;
  289.     m_cfAdvise=0;
  290.     m_fGetData=FALSE;
  291.     m_fRepaint=FALSE;
  292.  
  293.     m_pIDataSmall =NULL;
  294.     m_pIDataMedium=NULL;
  295.     m_pIDataLarge =NULL;
  296.     m_pIDataObject=NULL;
  297.  
  298.     m_cf=0;
  299.     m_stm.tymed=TYMED_NULL;
  300.     m_stm.lpszFileName=NULL;      //Initializes union to NULL
  301.     m_stm.pUnkForRelease=NULL;
  302.  
  303.     m_fInitialized=FALSE;
  304.     return;
  305.     }
  306.  
  307.  
  308. CApp::~CApp(void)
  309.     {
  310.     //This releases the data object interfaces and advises
  311.     FReloadDataObjects(FALSE);
  312.  
  313.     ReleaseStgMedium(&m_stm);
  314.  
  315.     //We called AddRef before so we could do this
  316.     ReleaseInterface(m_pIAdviseSink);
  317.  
  318.     if (IsWindow(m_hWnd))
  319.         DestroyWindow(m_hWnd);
  320.  
  321.     if (m_fInitialized)
  322.         CoUninitialize();
  323.  
  324.     return;
  325.     }
  326.  
  327.  
  328.  
  329.  
  330. /*
  331.  * CApp::Init
  332.  *
  333.  * Purpose:
  334.  *  Initializes an CApp object by registering window classes,
  335.  *  creating the main window, and doing anything else prone to
  336.  *  failure such as calling CoInitialize.  If this function fails
  337.  *  the caller should insure that the destructor is called.
  338.  *
  339.  * Parameters:
  340.  *  None
  341.  *
  342.  * Return Value:
  343.  *  BOOL            TRUE if successful, FALSE otherwise.
  344.  */
  345.  
  346. BOOL CApp::Init(void)
  347.     {
  348.     WNDCLASS    wc;
  349.     BOOL        fRet;
  350.  
  351.     CHECKVER_COM;
  352.  
  353.     if (FAILED(CoInitialize(NULL)))
  354.         return FALSE;
  355.  
  356.     m_fInitialized=TRUE;
  357.  
  358.     //Register our window classes.
  359.     if (!m_hInstPrev)
  360.         {
  361.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  362.         wc.lpfnWndProc    = DataUserWndProc;
  363.         wc.cbClsExtra     = 0;
  364.         wc.cbWndExtra     = CBWNDEXTRA;
  365.         wc.hInstance      = m_hInst;
  366.         wc.hIcon          = LoadIcon(m_hInst, TEXT("Icon"));
  367.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  368.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  369.         wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU);
  370.         wc.lpszClassName  = TEXT("DATAUSER");
  371.  
  372.         if (!RegisterClass(&wc))
  373.             return FALSE;
  374.         }
  375.  
  376.     //Create the main window.
  377.     m_hWnd=CreateWindow(TEXT("DATAUSER"), TEXT("Data Object User")
  378.         , WS_OVERLAPPEDWINDOW,35, 35, 350, 250, NULL
  379.         , NULL, m_hInst, this);
  380.  
  381.     if (NULL==m_hWnd)
  382.         return FALSE;
  383.  
  384.     ShowWindow(m_hWnd, m_nCmdShow);
  385.     UpdateWindow(m_hWnd);
  386.  
  387.     m_pIAdviseSink=new CAdviseSink(this);
  388.  
  389.     if (NULL==m_pIAdviseSink)
  390.         return FALSE;
  391.  
  392.     m_pIAdviseSink->AddRef();
  393.  
  394.     CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTUSEDLL, MF_CHECKED);
  395.     CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTDATASIZESMALL
  396.         , MF_CHECKED);
  397.  
  398.     //Load the initial objects
  399.     fRet=FReloadDataObjects(TRUE);
  400.     m_pIDataObject=m_pIDataSmall;
  401.  
  402.     return fRet;
  403.     }
  404.  
  405.  
  406.  
  407.  
  408.  
  409. /*
  410.  * CApp::FReloadDataObjects
  411.  *
  412.  * Purpose:
  413.  *  Releases the old data objects we're holding on to and reloads
  414.  *  the new ones from either EXE or DLL depending on m_fEXE.
  415.  *
  416.  * Parameters:
  417.  *  fReload         BOOL indicating if we are to recreate everything
  418.  *                  or just release the old ones (so we can use this
  419.  *                  from the destructor).
  420.  *
  421.  * Return Value:
  422.  *  BOOL            TRUE if there are usable objects in us now.
  423.  */
  424.  
  425. BOOL CApp::FReloadDataObjects(BOOL fReload)
  426.     {
  427.     HRESULT     hr1, hr2, hr3;
  428.     DWORD       dwClsCtx;
  429.     HCURSOR     hCur, hCurT;
  430.     HMENU       hMenu;
  431.     UINT        uTempD, uTempE;
  432.  
  433.     //Clean out any data we're holding
  434.     m_cf=0;
  435.     ReleaseStgMedium(&m_stm);
  436.  
  437.     //Turn off whatever data connection we have
  438.     if (NULL!=m_pIDataObject && 0!=m_dwConn)
  439.         m_pIDataObject->DUnadvise(m_dwConn);
  440.  
  441.     ReleaseInterface(m_pIDataLarge);
  442.     ReleaseInterface(m_pIDataMedium);
  443.     ReleaseInterface(m_pIDataSmall);
  444.  
  445.     m_pIDataObject=NULL;
  446.     CoFreeUnusedLibraries();
  447.  
  448.     //Exit if we just wanted to free.
  449.     if (!fReload)
  450.         return FALSE;
  451.  
  452.  
  453.     hCur=LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
  454.     hCurT=SetCursor(hCur);
  455.     ShowCursor(TRUE);
  456.  
  457.     dwClsCtx=(m_fEXE) ? CLSCTX_LOCAL_SERVER : CLSCTX_INPROC_SERVER;
  458.  
  459.     hr1=CoCreateInstance(CLSID_DataObjectSmall, NULL, dwClsCtx
  460.         , IID_IDataObject, (PPVOID)&m_pIDataSmall);
  461.  
  462.     hr2=CoCreateInstance(CLSID_DataObjectMedium, NULL, dwClsCtx
  463.         , IID_IDataObject, (PPVOID)&m_pIDataMedium);
  464.  
  465.     hr3=CoCreateInstance(CLSID_DataObjectLarge, NULL, dwClsCtx
  466.         , IID_IDataObject, (PPVOID)&m_pIDataLarge);
  467.  
  468.     ShowCursor(FALSE);
  469.     SetCursor(hCurT);
  470.  
  471.     //If anything fails, recurse to clean up...
  472.     if (FAILED(hr1) || FAILED(hr2) || FAILED(hr3))
  473.         return FReloadDataObjects(FALSE);
  474.  
  475.     //Reset the state of the menus for Small, no advise, no options.
  476.     hMenu=GetMenu(m_hWnd);
  477.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZESMALL,  MF_CHECKED);
  478.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZEMEDIUM, MF_UNCHECKED);
  479.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZELARGE,  MF_UNCHECKED);
  480.  
  481.     m_pIDataObject=m_pIDataSmall;
  482.     CheckMenuItem(hMenu, m_cfAdvise+IDM_ADVISEMIN, MF_UNCHECKED);
  483.  
  484.     uTempE=m_fEXE  ? MF_CHECKED : MF_UNCHECKED;
  485.     uTempD=!m_fEXE ? MF_CHECKED : MF_UNCHECKED;
  486.  
  487.     CheckMenuItem(hMenu, IDM_OBJECTUSEDLL, uTempD);
  488.     CheckMenuItem(hMenu, IDM_OBJECTUSEEXE, uTempE);
  489.  
  490.     CheckMenuItem(hMenu, IDM_ADVISEGETDATA, MF_UNCHECKED);
  491.     CheckMenuItem(hMenu, IDM_ADVISEREPAINT, MF_UNCHECKED);
  492.  
  493.     m_fGetData=FALSE;
  494.     m_fRepaint=FALSE;
  495.  
  496.     //Cannot request data using async advises, so disable these.
  497.     uTempE=m_fEXE  ? MF_DISABLED | MF_GRAYED : MF_ENABLED;
  498.     EnableMenuItem(hMenu,  IDM_ADVISEGETDATA, uTempE);
  499.     EnableMenuItem(hMenu, IDM_ADVISEREPAINT, uTempE);
  500.  
  501.     return TRUE;
  502.     }
  503.  
  504.  
  505.  
  506. /*
  507.  * CApp::TryQueryGetData
  508.  *
  509.  * Purpose:
  510.  *  Centralized function call and output code for displaying results
  511.  *  of various IDataObject::QueryGetData calls.
  512.  *
  513.  * Parameters:
  514.  *  pFE             LPFORMATETC to test.
  515.  *  cf              UINT specific clipboard format to stuff in pFE
  516.  *                  before calling.  If zero, use whatever is
  517.  *                  already in pFE.
  518.  *  fExpect         BOOL indicating expected results
  519.  *  y               UINT line on which to print results.
  520.  *
  521.  * Return Value:
  522.  *  None
  523.  */
  524.  
  525. void CApp::TryQueryGetData(LPFORMATETC pFE, UINT cf
  526.     , BOOL fExpect, UINT y)
  527.     {
  528.     TCHAR       szTemp[80];
  529.     LPTSTR      psz1;
  530.     LPTSTR      psz2;
  531.     UINT        cch;
  532.     HRESULT     hr;
  533.     HDC         hDC;
  534.  
  535.     if (0!=cf)
  536.         pFE->cfFormat=cf;
  537.  
  538.     hr=m_pIDataObject->QueryGetData(pFE);
  539.     psz1=(NOERROR==hr) ? szSuccess : szFailed;
  540.     psz2=((NOERROR==hr)==fExpect) ? szExpected : szUnexpected;
  541.  
  542.     hDC=GetDC(m_hWnd);
  543.     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  544.     SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  545.  
  546.     if (CF_WAVE < cf || 0==cf)
  547.         {
  548.         cch=wsprintf(szTemp, TEXT("QueryGetData on %d %s (%s)")
  549.             , cf, psz1, psz2);
  550.         }
  551.     else
  552.         {
  553.         cch=wsprintf(szTemp, TEXT("QueryGetData on %s %s (%s)")
  554.             , (LPTSTR)rgszCF[cf], psz1, psz2);
  555.         }
  556.  
  557.     //Don't overwrite other painted display.
  558.     SetBkMode(hDC, TRANSPARENT);
  559.     TextOut(hDC, 0, 16*y, szTemp, cch);
  560.  
  561.     ReleaseDC(m_hWnd, hDC);
  562.  
  563.     return;
  564.     }
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571. /*
  572.  * CApp::Paint
  573.  *
  574.  * Purpose:
  575.  *  Handles WM_PAINT for the main window by drawing whatever
  576.  *  data we have sitting in the STGMEDIUM at this time.
  577.  *
  578.  * Parameters:
  579.  *  None
  580.  *
  581.  * Return Value:
  582.  *  None
  583.  */
  584.  
  585. void CApp::Paint(void)
  586.     {
  587.     PAINTSTRUCT     ps;
  588.     HDC             hDC;
  589.     HDC             hMemDC;
  590.     LPMETAFILEPICT  pMF;
  591.     LPTSTR          psz;
  592.     RECT            rc;
  593.     FORMATETC       fe;
  594.  
  595.     GetClientRect(m_hWnd, &rc);
  596.  
  597.     hDC=BeginPaint(m_hWnd, &ps);
  598.  
  599.     //May need to retrieve the data with EXE objects
  600.     if (m_fEXE)
  601.         {
  602.         if (TYMED_NULL==m_stm.tymed && 0!=m_cf)
  603.             {
  604.             SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL
  605.                 | TYMED_MFPICT | TYMED_GDI);
  606.  
  607.             if (NULL!=m_pIDataObject)
  608.                 m_pIDataObject->GetData(&fe, &m_stm);
  609.             }
  610.         }
  611.  
  612.     switch (m_cf)
  613.         {
  614.         case CF_TEXT:
  615.             psz=(LPTSTR)GlobalLock(m_stm.hGlobal);
  616.  
  617.             if (NULL==psz)
  618.                 break;
  619.  
  620.             SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  621.             SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  622.  
  623.             DrawText(hDC, psz, lstrlen(psz), &rc
  624.                 , DT_LEFT | DT_WORDBREAK);
  625.             GlobalUnlock(m_stm.hGlobal);
  626.             break;
  627.  
  628.  
  629.         case CF_BITMAP:
  630.             hMemDC=CreateCompatibleDC(hDC);
  631.  
  632.             if (NULL!=SelectObject(hMemDC, (HGDIOBJ)m_stm.hGlobal))
  633.                 {
  634.                 BitBlt(hDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top
  635.                     , hMemDC, 0, 0, SRCCOPY);
  636.                 }
  637.  
  638.             DeleteDC(hMemDC);
  639.             break;
  640.  
  641.  
  642.         case CF_METAFILEPICT:
  643.             pMF=(LPMETAFILEPICT)GlobalLock(m_stm.hGlobal);
  644.  
  645.             if (NULL==pMF)
  646.                 break;
  647.  
  648.             SetMapMode(hDC, pMF->mm);
  649.             SetWindowOrgEx(hDC, 0, 0, NULL);
  650.             SetWindowExtEx(hDC, pMF->xExt, pMF->yExt, NULL);
  651.  
  652.             SetViewportExtEx(hDC, rc.right-rc.left
  653.                 , rc.bottom-rc.top, NULL);
  654.  
  655.             PlayMetaFile(hDC, pMF->hMF);
  656.             GlobalUnlock(m_stm.hGlobal);
  657.             break;
  658.  
  659.  
  660.         default:
  661.             break;
  662.         }
  663.  
  664.     EndPaint(m_hWnd, &ps);
  665.     return;
  666.     }
  667.