windrag.cc

Go to the documentation of this file.
00001 /*
00002 * This file implements some Win32 OLE2 specific Drag and Drop structures.
00003 * Most of the code is a modification of the OLE2 SDK sample programs
00004 * "drgdrps" and "drgdrpt". If you want to see them, don't search at
00005 * Microsoft (I didn't find them there, seems they reorganised their servers)
00006 * but instead at
00007 *  http://ftp.se.kde.org/pub/vendor/microsoft/Softlib/MSLFILES/
00008 */
00009 
00010 #if defined(WIN32) && defined(USE_EXULTSTUDIO) && !defined(UNDER_CE)
00011 
00012 #include <iostream>
00013 
00014 #include "windrag.h"
00015 #include "u7drag.h"
00016 
00017 static UINT CF_EXULT = RegisterClipboardFormat("ExultData");
00018 
00019 // Statics
00020 
00021 void Windnd::CreateStudioDropDest(Windnd *& windnd, HWND &hWnd,
00022           Drop_shape_handler_fun shapefun,
00023           Drop_chunk_handler_fun cfun,
00024           Drop_shape_handler_fun facefun,
00025           void *udata)
00026 {
00027   hWnd = GetActiveWindow();
00028   windnd = new Windnd(hWnd, shapefun, cfun, facefun, udata);
00029   if (FAILED(RegisterDragDrop(hWnd, windnd))) {
00030     std::cout << "Something's wrong with OLE2 ..." << std::endl;
00031   }
00032 }
00033 
00034 void Windnd::DestroyStudioDropDest(Windnd *& windnd, HWND &hWnd)
00035 {
00036   RevokeDragDrop(hWnd);
00037   delete windnd;
00038   windnd = 0;
00039   hWnd = 0;
00040 }
00041 
00042 // IDropTarget implementation
00043 
00044 Windnd::Windnd(HWND hgwnd, Move_shape_handler_fun movefun,
00045       Move_combo_handler_fun movecmbfun,
00046       Drop_shape_handler_fun shapefun,
00047       Drop_chunk_handler_fun cfun, Drop_combo_handler_fun combfun
00048       ) : gamewin(hgwnd), udata(0), move_shape_handler(movefun),
00049         move_combo_handler(movecmbfun), shape_handler(shapefun),
00050         chunk_handler(cfun), face_handler(0), combo_handler(combfun),
00051         drag_id(-1)
00052 {
00053   std::memset (&data, 0, sizeof(data));
00054   m_cRef = 1;
00055 };
00056 
00057 Windnd::Windnd(HWND hgwnd,  Drop_shape_handler_fun shapefun,
00058          Drop_chunk_handler_fun cfun, Drop_shape_handler_fun ffun, void *d
00059          )
00060          :gamewin(hgwnd), udata(d), move_shape_handler(0), move_combo_handler(0),
00061         shape_handler(shapefun), chunk_handler(cfun),
00062       face_handler(ffun), combo_handler(0), drag_id(-1)
00063 {
00064   std::memset (&data, 0, sizeof(data));
00065   m_cRef = 1;
00066 };
00067 
00068 Windnd::~Windnd()
00069 {
00070 };
00071 
00072 STDMETHODIMP
00073 Windnd::QueryInterface(REFIID iid, void ** ppvObject)
00074 {
00075   *ppvObject=NULL;
00076   if (IID_IUnknown==iid || IID_IDropTarget==iid)
00077     *ppvObject=this;
00078   if (NULL==*ppvObject)
00079     return E_NOINTERFACE;
00080   ((LPUNKNOWN)*ppvObject)->AddRef();
00081   return NOERROR;
00082 };
00083 
00084 STDMETHODIMP_(ULONG)
00085 Windnd::AddRef(void)
00086 {
00087   return ++m_cRef;
00088 };
00089 
00090 STDMETHODIMP_(ULONG)
00091 Windnd::Release(void)
00092 {
00093   if (0!=--m_cRef)
00094     return m_cRef;
00095   delete this;
00096   return 0;
00097 };
00098 
00099 STDMETHODIMP
00100 Windnd::DragEnter(IDataObject * pDataObject,
00101       DWORD grfKeyState,
00102       POINTL pt,
00103       DWORD * pdwEffect)
00104 {
00105   if (!is_valid(pDataObject)) {
00106     *pdwEffect = DROPEFFECT_NONE;
00107   } else {
00108     *pdwEffect = DROPEFFECT_COPY;
00109   };
00110 
00111   std::memset (&data, 0, sizeof(data));
00112 
00113   FORMATETC fetc;
00114   fetc.cfFormat = CF_EXULT;
00115   fetc.ptd = NULL;
00116   fetc.dwAspect = DVASPECT_CONTENT;
00117   fetc.lindex = -1;
00118   fetc.tymed = TYMED_HGLOBAL;
00119 
00120   STGMEDIUM med;
00121   pDataObject->GetData(&fetc, &med);
00122   windragdata wdd((unsigned char *)GlobalLock(med.hGlobal));
00123   GlobalUnlock(med.hGlobal);
00124   ReleaseStgMedium(&med);
00125 
00126   drag_id=wdd.get_id();
00127   switch (drag_id) {
00128 
00129   case U7_TARGET_SHAPEID:
00130     Get_u7_shapeid(wdd.get_data(), data.shape.file, data.shape.shape, data.shape.frame);
00131     break;
00132 
00133   case U7_TARGET_CHUNKID:
00134     Get_u7_chunkid(wdd.get_data(), data.chunk.chunknum);
00135     break;
00136 
00137   case U7_TARGET_COMBOID:
00138     Get_u7_comboid(wdd.get_data(), data.combo.xtiles, data.combo.ytiles, data.combo.right, data.combo.below, data.combo.cnt, data.combo.combo);
00139     break;
00140 
00141   default:
00142     break;
00143   }
00144 
00145   prevx = -1;
00146   prevy = -1;
00147 
00148   return S_OK;
00149 };
00150 
00151 STDMETHODIMP
00152 Windnd::DragOver(DWORD grfKeyState,
00153      POINTL pt,
00154      DWORD * pdwEffect)
00155 {
00156   *pdwEffect = DROPEFFECT_COPY;
00157   // Todo 
00158 
00159   POINT pnt = { pt.x, pt.y};
00160   ScreenToClient(gamewin, &pnt);
00161 
00162   switch (drag_id) {
00163 
00164   case U7_TARGET_SHAPEID:
00165     if (data.shape.file == U7_SHAPE_SHAPES) {
00166       if (move_shape_handler) move_shape_handler(data.shape.shape, data.shape.frame,
00167         pnt.x, pnt.y, prevx, prevy, true);
00168     }
00169     break;
00170 
00171   case U7_TARGET_COMBOID:
00172     if (data.combo.cnt > 0) {
00173       if (move_combo_handler) move_combo_handler(data.combo.xtiles, data.combo.ytiles,
00174         data.combo.right, data.combo.below, pnt.x, pnt.y, prevx, prevy, true);
00175     }
00176     break;
00177 
00178   default:
00179     break;
00180   }
00181 
00182   prevx = pnt.x;
00183   prevy = pnt.y;
00184 
00185   return S_OK;
00186 };
00187 
00188 STDMETHODIMP
00189 Windnd::DragLeave(void)
00190 {
00191   move_shape_handler(-1, -1, 0, 0, prevx, prevy, true);
00192 
00193   switch (drag_id) {
00194   case U7_TARGET_SHAPEID:
00195     break;
00196   case U7_TARGET_COMBOID:
00197     delete data.combo.combo;
00198     break;
00199 
00200   default:
00201     break;
00202   }
00203   std::memset (&data, 0, sizeof(data));
00204   drag_id = -1;
00205 
00206   return S_OK;
00207 };
00208 
00209 STDMETHODIMP
00210 Windnd::Drop(IDataObject * pDataObject,
00211        DWORD grfKeyState,
00212        POINTL pt,
00213        DWORD * pdwEffect)
00214 {
00215   *pdwEffect = DROPEFFECT_COPY;
00216   ;
00217   
00218   // retrieve the dragged data
00219   FORMATETC fetc;
00220   fetc.cfFormat = CF_EXULT;
00221   fetc.ptd = NULL;
00222   fetc.dwAspect = DVASPECT_CONTENT;
00223   fetc.lindex = -1;
00224   fetc.tymed = TYMED_HGLOBAL;
00225   STGMEDIUM med;
00226   
00227   pDataObject->GetData(&fetc, &med);
00228   windragdata wdd((unsigned char *)GlobalLock(med.hGlobal));
00229   GlobalUnlock(med.hGlobal);
00230   ReleaseStgMedium(&med);
00231 
00232   POINT pnt = { pt.x, pt.y};
00233   ScreenToClient(gamewin, &pnt);
00234 
00235   int id = wdd.get_id();
00236   
00237   if (id == U7_TARGET_SHAPEID) {
00238     int file,shape,frame;
00239     Get_u7_shapeid(wdd.get_data(), file, shape, frame);
00240     if (file == U7_SHAPE_SHAPES) {
00241       if (shape_handler) (*shape_handler)(shape, frame, pnt.x, pnt.y, udata);
00242     }
00243     else if (file == U7_SHAPE_FACES) {
00244       if (face_handler) (*face_handler)(shape, frame, pnt.x, pnt.y, udata);
00245     }
00246   } else if (id == U7_TARGET_CHUNKID) {
00247     int chunknum;
00248     Get_u7_chunkid(wdd.get_data(), chunknum);
00249     if (chunk_handler) (*chunk_handler)(chunknum, pnt.x, pnt.y, udata);
00250   } else if (id == U7_TARGET_COMBOID) {
00251     int xtiles, ytiles;
00252     int right, below, cnt;
00253     U7_combo_data *combo;
00254     Get_u7_comboid(wdd.get_data(), xtiles, ytiles, right, below, cnt, combo);
00255     if (combo_handler) combo_handler(cnt, combo, pnt.x, pnt.y, udata);
00256     delete combo;
00257   }
00258   
00259   return S_OK;
00260 };
00261 
00262 bool Windnd::is_valid(IDataObject * pDataObject)
00263 {
00264   FORMATETC fetc;
00265   fetc.cfFormat = CF_EXULT;
00266   fetc.ptd = NULL;
00267   fetc.dwAspect = DVASPECT_CONTENT;
00268   fetc.lindex = -1;
00269   fetc.tymed = TYMED_HGLOBAL;
00270   
00271   if (FAILED(pDataObject->QueryGetData(& fetc))) {
00272     return false;
00273   } else {
00274     return true;
00275   }
00276 };
00277 
00278 // IDropSource implementation
00279 
00280 Windropsource::Windropsource(HBITMAP pdrag_bitmap, int x0, int y0)
00281 :drag_bitmap(pdrag_bitmap)
00282 {
00283   m_cRef = 1;
00284   drag_shape = 0;
00285   
00286 #if 0
00287   // doesn't work yet
00288   SIZE bsize;
00289   GetBitmapDimensionEx(drag_bitmap, &bsize);
00290   bsize.cx = 32; bsize.cy = 32;
00291   int shw = bsize.cx, shh = bsize.cy;
00292   drag_shape = CreateWindowEx(WS_EX_TRANSPARENT,
00293     "STATIC",
00294     NULL,
00295     WS_POPUP, // | SS_OWNERDRAW, /*SS_OWNERDRAW,*/
00296     x0, y0,
00297     shw, shh,
00298     GetForegroundWindow(), // TODO: owner window
00299     NULL,
00300     (HINSTANCE)GetWindowLong(GetForegroundWindow(), GWL_HINSTANCE),
00301     NULL);
00302   
00303   if (FAILED(drag_shape)) {
00304     g_warning("Create Window FAILED !");
00305   };
00306 #endif
00307 };
00308 
00309 Windropsource::~Windropsource()
00310 {
00311   DestroyWindow(drag_shape);
00312 };
00313 
00314 STDMETHODIMP
00315 Windropsource::QueryInterface(REFIID iid, void ** ppvObject)
00316 {
00317   *ppvObject=NULL;
00318   if (IID_IUnknown==iid || IID_IDropSource==iid)
00319     *ppvObject = this;
00320   if (NULL==*ppvObject)
00321     return E_NOINTERFACE;
00322   ((LPUNKNOWN)*ppvObject)->AddRef();
00323   return NOERROR;
00324 };
00325 
00326 STDMETHODIMP_(ULONG)
00327 Windropsource::AddRef(void)
00328 {
00329   m_cRef = m_cRef + 1;
00330   
00331   return m_cRef;
00332 };
00333 
00334 STDMETHODIMP_(ULONG)
00335 Windropsource::Release(void)
00336 {
00337   if (0!=--m_cRef)
00338     return m_cRef;
00339   delete this;
00340   return 0;
00341 };
00342 
00343 STDMETHODIMP
00344 Windropsource::QueryContinueDrag(
00345          BOOL fEscapePressed,
00346          DWORD grfKeyState
00347          )
00348 {
00349 #if 0
00350   // doesn't work yet
00351   POINT pnt;
00352   GetCursorPos(&pnt);
00353   
00354   MoveWindow(drag_shape,
00355     pnt.x, pnt.y,
00356     shw, shh,
00357     true);
00358 #endif
00359   
00360   if (fEscapePressed)
00361     return DRAGDROP_S_CANCEL;
00362   else if (!(grfKeyState & MK_LBUTTON))
00363     return DRAGDROP_S_DROP;
00364   else
00365     return NOERROR;                  
00366 };
00367 
00368 STDMETHODIMP
00369 Windropsource::GiveFeedback(
00370           DWORD dwEffect
00371           )
00372 {
00373   return DRAGDROP_S_USEDEFAULTCURSORS;
00374 };
00375 
00376 // IDataObject implementation
00377 
00378 Winstudioobj::Winstudioobj(windragdata pdata)
00379 :data(pdata)
00380 {
00381   m_cRef = 1;
00382   drag_image = 0;
00383 };
00384 
00385 Winstudioobj::~Winstudioobj()
00386 {
00387 };
00388 
00389 
00390 STDMETHODIMP
00391 Winstudioobj::QueryInterface(REFIID iid, void ** ppvObject)
00392 {
00393   *ppvObject=NULL;
00394   if (IID_IUnknown==iid || IID_IDataObject==iid)
00395     *ppvObject=this;
00396   if (NULL==*ppvObject)
00397     return E_NOINTERFACE;
00398   ((LPUNKNOWN)*ppvObject)->AddRef();
00399   return NOERROR;
00400 };
00401 
00402 STDMETHODIMP_(ULONG)
00403 Winstudioobj::AddRef(void)
00404 {
00405   return ++m_cRef;
00406 };
00407 
00408 STDMETHODIMP_(ULONG)
00409 Winstudioobj::Release(void)
00410 {
00411   if (0!=--m_cRef)
00412     return m_cRef;
00413   delete this;
00414   return 0;
00415 };
00416 
00417 STDMETHODIMP
00418 Winstudioobj::GetData(
00419           FORMATETC * pFormatetc,
00420           STGMEDIUM * pmedium
00421           )
00422 {
00423   std::cout << "In GetData"<< std::endl;
00424   
00425   HGLOBAL hText;
00426   unsigned char *ldata;
00427   
00428   pmedium->tymed = 0;
00429   pmedium->pUnkForRelease = NULL;
00430   pmedium->hGlobal = NULL;
00431   
00432   // This method is called by the drag-drop target to obtain the data
00433   // that is being dragged.
00434   if (pFormatetc->cfFormat == CF_EXULT &&
00435     pFormatetc->dwAspect == DVASPECT_CONTENT &&
00436     pFormatetc->tymed == TYMED_HGLOBAL)
00437   {
00438     hText = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, 8 + data.get_size());
00439     if (!hText)
00440       return E_OUTOFMEMORY;
00441     
00442     // This provides us with a pointer to the allocated memory
00443     ldata = (unsigned char *)GlobalLock(hText);
00444     data.serialize(ldata);
00445     GlobalUnlock(hText);
00446     
00447     pmedium->tymed = TYMED_HGLOBAL;
00448     pmedium->hGlobal = hText; 
00449     
00450     return S_OK;
00451   }
00452   
00453   return DATA_E_FORMATETC;
00454 };
00455 
00456 STDMETHODIMP
00457 Winstudioobj::GetDataHere(
00458         FORMATETC * pFormatetc,
00459         STGMEDIUM * pmedium
00460         )
00461 {
00462   return DATA_E_FORMATETC;
00463 };
00464 
00465 STDMETHODIMP
00466 Winstudioobj::QueryGetData(
00467          FORMATETC * pFormatetc
00468          )
00469 {
00470   // This method is called by the drop target to check whether the source
00471   // provides data is a format that the target accepts.
00472   if (pFormatetc->cfFormat == CF_EXULT
00473     && pFormatetc->dwAspect == DVASPECT_CONTENT
00474     && pFormatetc->tymed & TYMED_HGLOBAL)
00475     return S_OK; 
00476   else return S_FALSE;
00477 };
00478 
00479 STDMETHODIMP
00480 Winstudioobj::GetCanonicalFormatEtc(
00481             FORMATETC * pFormatetcIn,
00482             FORMATETC * pFormatetcOut
00483             )
00484 {
00485   pFormatetcOut->ptd = NULL; 
00486   return E_NOTIMPL;
00487 };
00488 
00489 STDMETHODIMP
00490 Winstudioobj::SetData(
00491           FORMATETC * pFormatetc,
00492           STGMEDIUM * pmedium,
00493           BOOL fRelease
00494           )
00495 {
00496   return E_NOTIMPL;
00497 };
00498 
00499 STDMETHODIMP
00500 Winstudioobj::EnumFormatEtc(
00501           DWORD dwDirection,
00502           IEnumFORMATETC ** ppenumFormatetc
00503           )
00504 {
00505   SCODE sc = S_OK;
00506   FORMATETC fmtetc;
00507   
00508   fmtetc.cfFormat = CF_EXULT;
00509   fmtetc.dwAspect = DVASPECT_CONTENT;
00510   fmtetc.tymed = TYMED_HGLOBAL;
00511   fmtetc.ptd = NULL;
00512   fmtetc.lindex = -1;
00513   
00514   if (dwDirection == DATADIR_GET){
00515     std::cout << "EnumFmt" << std::endl;
00516     // I was too lazy to implement still another OLE2 interface just for something
00517     //  we don't even use. This function is supposed to be called by a drop target
00518     //  to find out if it can accept the provided data type. I suppose with
00519     //  E_NOTIMPL, other drop targets don't care about Exult data.
00523     sc = E_NOTIMPL;
00524     
00525   } else if (dwDirection == DATADIR_SET){
00526     // A data transfer object that is used to transfer data
00527     //    (either via the clipboard or drag/drop does NOT
00528     //    accept SetData on ANY format.
00529     sc = E_NOTIMPL;
00530     goto error;
00531   } else {
00532     sc = E_INVALIDARG;
00533     goto error;
00534   }
00535   
00536 error:
00537   return sc;
00538 };
00539 
00540 STDMETHODIMP
00541 Winstudioobj::DAdvise(
00542           FORMATETC * pFormatetc,
00543           DWORD advf,
00544           IAdviseSink * pAdvSink,
00545           DWORD * pdwConnection
00546           )
00547 {
00548   return OLE_E_ADVISENOTSUPPORTED;
00549 };
00550 
00551 STDMETHODIMP
00552 Winstudioobj::DUnadvise(
00553       DWORD dwConnection
00554       )
00555 {
00556   return OLE_E_ADVISENOTSUPPORTED;
00557 };
00558 
00559 STDMETHODIMP
00560 Winstudioobj::EnumDAdvise(
00561         IEnumSTATDATA ** ppenumAdvise
00562         )
00563 {
00564   return OLE_E_ADVISENOTSUPPORTED;
00565 };
00566 
00567 #endif

Generated on Mon Jul 9 14:42:52 2007 for ExultEngine by  doxygen 1.5.1