opposite of HB_FUNC( REGISTERDRAGDROP ) ?

opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Jimmy » Wed Dec 13, 2023 9:25 am

hi,

Fivewin can use REGISTERDRAGDROP() to use App "as Target" where i can drop to
i´m searching how to use App "as Source" to drag Data to "external" App, how :?:
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

Re: opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Antonio Linares » Wed Dec 13, 2023 9:49 am

Dear Jimmy,

Is this what you are looking for ?

Code: Select all  Expand view  RUN
#include <windows.h>
#include <ole2.h>
#include <shlobj.h>

// Definir una estructura para almacenar los datos del destino de arrastre
typedef struct {
  IDropTargetVtbl *lpVtbl; // Puntero a la tabla de funciones virtuales
  DWORD refCount; // Contador de referencias
  HWND hwnd; // Control de ventana asociado al destino de arrastre
  BOOL isOver; // Indica si el cursor está sobre el destino de arrastre
  BOOL allowDrop; // Indica si se permite soltar el objeto
  IDataObject *dataObject; // Puntero al objeto de datos arrastrado
} DropTarget;

// Definir las funciones de la interfaz IDropTarget
HRESULT STDMETHODCALLTYPE QueryInterface (IDropTarget *, REFIID, void **);
ULONG STDMETHODCALLTYPE AddRef (IDropTarget *);
ULONG STDMETHODCALLTYPE Release (IDropTarget *);
HRESULT STDMETHODCALLTYPE DragEnter (IDropTarget *, IDataObject *, DWORD, POINTL, DWORD *);
HRESULT STDMETHODCALLTYPE DragOver (IDropTarget *, DWORD, POINTL, DWORD *);
HRESULT STDMETHODCALLTYPE DragLeave (IDropTarget *);
HRESULT STDMETHODCALLTYPE Drop (IDropTarget *, IDataObject *, DWORD, POINTL, DWORD *);

// Crear la tabla de funciones virtuales
static IDropTargetVtbl dropTargetVtbl = {
  QueryInterface,
  AddRef,
  Release,
  DragEnter,
  DragOver,
  DragLeave,
  Drop
};

// Crear una instancia de la interfaz IDropTarget
DropTarget *CreateDropTarget (HWND hwnd) {
  DropTarget *dropTarget = (DropTarget *) GlobalAlloc (GMEM_FIXED, sizeof (DropTarget));
  dropTarget->lpVtbl = &dropTargetVtbl;
  dropTarget->refCount = 1;
  dropTarget->hwnd = hwnd;
  dropTarget->isOver = FALSE;
  dropTarget->allowDrop = FALSE;
  dropTarget->dataObject = NULL;
  return dropTarget;
}

// Implementar la función QueryInterface
HRESULT STDMETHODCALLTYPE QueryInterface (IDropTarget *this, REFIID riid, void **ppvObject) {
  if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDropTarget)) {
    this->lpVtbl->AddRef (this);
    *ppvObject = this;
    return S_OK;
  }
  else {
    *ppvObject = NULL;
    return E_NOINTERFACE;
  }
}

// Implementar la función AddRef
ULONG STDMETHODCALLTYPE AddRef (IDropTarget *this) {
  return InterlockedIncrement (&(((DropTarget *) this)->refCount));
}

// Implementar la función Release
ULONG STDMETHODCALLTYPE Release (IDropTarget *this) {
  ULONG refCount = InterlockedDecrement (&(((DropTarget *) this)->refCount));
  if (refCount == 0) {
    GlobalFree (this);
    return 0;
  }
  else {
    return refCount;
  }
}

// Implementar la función DragEnter
HRESULT STDMETHODCALLTYPE DragEnter (IDropTarget *this, IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
  // Comprobar si el objeto de datos contiene archivos
  FORMATETC formatEtc;
  formatEtc.cfFormat = CF_HDROP;
  formatEtc.ptd = NULL;
  formatEtc.dwAspect = DVASPECT_CONTENT;
  formatEtc.lindex = -1;
  formatEtc.tymed = TYMED_HGLOBAL;
  HRESULT hr = pDataObject->lpVtbl->QueryGetData (pDataObject, &formatEtc);
  if (hr == S_OK) {
    // Guardar una referencia al objeto de datos
    ((DropTarget *) this)->dataObject = pDataObject;
    pDataObject->lpVtbl->AddRef (pDataObject);
    // Indicar que el cursor está sobre el destino de arrastre
    ((DropTarget *) this)->isOver = TRUE;
    // Indicar que se permite soltar el objeto
    ((DropTarget *) this)->allowDrop = TRUE;
    // Establecer el efecto de la operación
    *pdwEffect = DROPEFFECT_COPY;
  }
  else {
    // Indicar que no se permite soltar el objeto
    ((DropTarget *) this)->allowDrop = FALSE;
    // Establecer el efecto de la operación
    *pdwEffect = DROPEFFECT_NONE;
  }
  return S_OK;
}

// Implementar la función DragOver
HRESULT STDMETHODCALLTYPE DragOver (IDropTarget *this, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
  if (((DropTarget *) this)->isOver) {
    if (((DropTarget *) this)->allowDrop) {
      // Establecer el efecto de la operación
      *pdwEffect = DROPEFFECT_COPY;
    }
    else {
      // Establecer el efecto de la operación
      *pdwEffect = DROPEFFECT_NONE;
    }
  }
  return S_OK;
}

// Implementar la función DragLeave
HRESULT STDMETHODCALLTYPE DragLeave (IDropTarget *this) {
  if (((DropTarget *) this)->isOver) {
    // Liberar la referencia al objeto de datos
    ((DropTarget *) this)->dataObject->lpVtbl->Release (((DropTarget *) this)->dataObject);
    // Indicar que el cursor ha salido del destino de arrastre
    ((DropTarget *) this)->isOver = FALSE;
  }
  return S_OK;
}

// Implementar la función Drop
HRESULT STDMETHODCALLTYPE Drop (IDropTarget *this, IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
  if (((DropTarget *) this)->isOver) {
    if (((DropTarget *) this)->allowDrop) {
      // Obtener los nombres de los archivos arrastrados
      FORMATETC formatEtc;
      formatEtc.cfFormat = CF_HDROP;
      formatEtc.ptd = NULL;
      formatEtc.dwAspect = DVASPECT_CONTENT;
      formatEtc.lindex = -1;
      formatEtc.tymed = TYMED_HGLOBAL;
      STGMEDIUM storageMedium;
      HRESULT hr = pDataObject->lpVtbl->GetData (pDataObject, &formatEtc, &storageMedium);
      if (SUCCEEDED (hr)) {
        HDROP hDrop = (HDROP) GlobalLock (storageMedium.hGlobal);
        if (hDrop != NULL) {
          UINT fileCount = DragQueryFile (hDrop, 0xFFFFFFFF, NULL, 0);
          for (UINT i = 0; i < fileCount; i++) {
            TCHAR fileName[MAX_PATH];
            if (DragQueryFile (hDrop, i, fileName, MAX_PATH) > 0) {
              // Hacer algo con el nombre del archivo
              MessageBox (((DropTarget *) this)->hwnd, fileName, TEXT ("Archivo arrastrado"), MB_OK);
            }
          }
          GlobalUnlock (storageMedium.hGlobal);
          DragFinish (hDrop);
        }
        ReleaseStgMedium (&storageMedium);
      }
      // Establecer el efecto de la operación
      *pdwEffect = DROPEFFECT_COPY;
    }
    else {
      // Establecer el efecto de la operación
      *pdwEffect = DROPEFFECT_NONE;
    }
    // Liberar la referencia al objeto de datos
    ((DropTarget *) this)->dataObject->lpVtbl->Release (((DropTarget *) this)->dataObject);
    // Indicar que el cursor ha salido del destino de arrastre
    (
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Jimmy » Wed Dec 13, 2023 10:35 am

hi Antonio,

thx for Answer

it seems me that Sample is to react on
DragEnter
DragOver
DragLeave
Drop
to receive in "my App" when use "as Target"

but i like to Dragdrop Data from "my App" and send to external App e.g. Picture to Outlook Email

---

i have read at https://www.catch22.net/tuts/ole/ about OLE Dragdrop and play with samples\imgdrop.prg
it use source\winapi\dropfile.c where i found HB_FUNC( REGISTERDRAGDROP )

now i want to register "my App" for Dragdrop "as Source", how :?:
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

Re: opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Jimmy » Mon Dec 18, 2023 2:43 am

hi

how can i use this https://www.catch22.net/assets/tuts/zips/dropsource.zip *.CPP CODE with harbour :?:
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

Re: opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Antonio Linares » Wed Dec 20, 2023 10:55 am

Dear Jimmy,

As a first approach I have taken all C++ code out of main.c (previously main.cpp) and created a new file builddrop.cpp

This way we can simply compile the cpp files and use them from Harbour. I am building it from Visual Studio and it properly builds :-)

Next is to properly use it from FWH and Harbour:

main.c
Code: Select all  Expand view  RUN
//
//  MAIN.CPP
//
//  DragSource
//
//  Freeware written by J Brown 2004
//
//  www.catch22.net
//

#define STRICT

#include <windows.h>
#include "resource.h"

#define APPNAME "IDropSource"

#pragma comment(linker, "/OPT:NOWIN98")

void BuildDrop(HWND, BOOL *, BOOL * );

HWND        hwndMain;
HWND        hwndEdit;
HINSTANCE   hInstance;

WNDPROC     OldEditWndProc;

HRESULT CreateDropSource(IDropSource **ppDropSource);
HRESULT CreateDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject);

//
//  Is the mouse cursor within the edit control's selected text?
//
//  Return TRUE/FALSE
//
BOOL MouseInSelection(HWND hwndEdit, LPARAM MouseMsgParam)
{
    DWORD nSelStart;
    DWORD nSelEnd;

    // get the selection inside the edit control
    SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&nSelStart, (LPARAM)&nSelEnd);

    if(nSelStart != nSelEnd)
    {
        DWORD nCurPos;

        // Get the cursor position the mouse has clicked on
        nCurPos = SendMessage(hwndEdit, EM_CHARFROMPOS, 0, MouseMsgParam);
        nCurPos = LOWORD(nCurPos);

        // Did the mouse click inside the active selection?
        return (nCurPos >= nSelStart && nCurPos < nSelEnd) ? TRUE : FALSE;
    }

    return FALSE;
}

//
//  Remove any selection from the edit control
//
void ClearSelection(HWND hwndEdit)
{
    SendMessage(hwndEdit, EM_SETSEL, -1, -1);
}

//
//  Copy selected text to a HGLOBAL and return it
//
HGLOBAL CopySelection(HWND hwndEdit)
{
    DWORD   nSelStart, nSelEnd;
    DWORD   nSelLength, nEditLength;
    HGLOBAL hMem;
    char   *ptr;
    char   *tmp;

    SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&nSelStart, (LPARAM)&nSelEnd);

    nSelLength = nSelEnd - nSelStart;

    // get the entire contents of the control
    nEditLength = SendMessage(hwndEdit, EM_GETLIMITTEXT, 0, 0);
    tmp  = (char *)malloc(nEditLength);

    SendMessage(hwndEdit, WM_GETTEXT, nEditLength, (LPARAM)tmp);

    hMem = GlobalAlloc(GHND, nSelLength+1);
    ptr  = (char *)GlobalLock(hMem);

    // copy the selected text and nul-terminate
    memcpy(ptr, tmp+nSelStart, nSelLength);
    ptr[nSelLength] = '\0';

    GlobalUnlock(hMem);

    free(tmp);

    return hMem;
}

//
//  Subclass window-procedure for EDIT control
//
LRESULT CALLBACK EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static BOOL  fMouseDown   = FALSE;
    static BOOL  fDidDragDrop = FALSE;
           
    switch(msg)
    {
    case WM_KEYDOWN:
       
        // when ESCAPE is pressed clear the current selection
        if(wParam == VK_ESCAPE)
            ClearSelection(hwnd);

        break;

    case WM_LBUTTONDOWN:
    case WM_LBUTTONDBLCLK:

        // if the mouse is pressed when it is over a selection,
        // then start a drag-drop as soon as the mouse moves next
        if(MouseInSelection(hwndEdit, lParam))
        {
            fMouseDown = TRUE;
            fDidDragDrop = FALSE;
            SetCapture(hwnd);
            return 0;
        }

        break;

    case WM_SETCURSOR:

        // set the mouse cursor to an ARROW when it intersects the
        // current selection, or the default IBEAM otherwise
        if((HWND)wParam == hwnd)
        {
            POINT pt;
            GetCursorPos(&pt);
            ScreenToClient(hwndEdit, &pt);

            if(MouseInSelection(hwndEdit, MAKELPARAM(pt.x, pt.y)))
            {
                SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW)));
            }
            else
            {
                SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_IBEAM)));
            }
        }

        return TRUE;

    case WM_MOUSEMOVE:

        // if the mouse is held down then start a drag-drop
        if(fMouseDown)
        {
            BuildDrop( hwndEdit, &fMouseDown, &fDidDragDrop );
        }

        break;

    case WM_LBUTTONUP:
       
        // stop drag-drop from happening when the mouse is released.
        if(fMouseDown)
        {
            ReleaseCapture();
            fMouseDown = FALSE;

            if(fDidDragDrop == FALSE)
                ClearSelection(hwnd);
        }

        break;
    }

    return CallWindowProc(OldEditWndProc, hwnd, msg, wParam, lParam);
}

//
//  Main Window message handler
//
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:

        // create a child-window EDIT control
        hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
            WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL,
            0,0,0,0, hwnd, 0, hInstance, 0);

        // fixed-width font
        SendMessage(hwndEdit, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), 0);

        // subclass the edit control so we can add drag+drop support to it
        OldEditWndProc = (WNDPROC)SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)EditWndProc);

        SetFocus(hwndEdit);

        return TRUE;

    case WM_COMMAND:
   
        // react to menu messages
        switch(LOWORD(wParam))
        {
        case IDM_FILE_EXIT:
            CloseWindow(hwnd);
            return 0;

        case IDM_FILE_ABOUT&#058;
            MessageBox(hwnd, "IDropSource Test Application\r\n\r\n"

                             "Copyright(c) 2004 by Catch22 Productions\t\r\n"
                             "Written by J Brown.\r\n\r\n"
                             "Homepage at www.catch22.net", APPNAME, MB_ICONINFORMATION);
            return 0;
        }

        break;
    case WM_CLOSE:

        // shut program down
        DestroyWindow(hwnd);
        PostQuitMessage(0);
        return 0;

    case WM_SIZE:
       
        // resize editbox to fit in main window
        MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
        return 0;
    }

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

void InitMainWnd()
{
    WNDCLASSEX wc = { sizeof(wc) };

    wc.lpfnWndProc   = WndProc;
    wc.lpszClassName = APPNAME;
    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU1);
    wc.hInstance     = hInstance;

    RegisterClassEx(&wc);
}

void CreateMainWnd()
{
    hwndMain = CreateWindowEx(0, APPNAME, APPNAME,
        WS_VISIBLE|WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 512, 200, 0,0,
        hInstance, 0);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
    MSG msg;

    hInstance = hInst;

    // This program requires COM
    OleInitialize(0);
   
    InitMainWnd();
    CreateMainWnd();

    // message-pump
    while(GetMessage(&msg, 0, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // Shutdown COM
    OleUninitialize();

    return 0;
}


buildprop.cpp
Code: Select all  Expand view  RUN
#include <windows.h>

extern "C" HGLOBAL CopySelection(HWND hwndEdit);
HRESULT CreateDropSource(IDropSource** ppDropSource);
HRESULT CreateDataObject(FORMATETC* fmtetc, STGMEDIUM* stgmeds, UINT count, IDataObject** ppDataObject);

extern "C" void BuildDrop(HWND hwndEdit, BOOL * fMouseDown, BOOL * fDidDragDrop)
{
    IDataObject* pDataObject;
    IDropSource* pDropSource;
    DWORD        dwEffect;
    DWORD        dwResult;

    FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };

    // transfer the current selection into the IDataObject
    stgmed.hGlobal = CopySelection(hwndEdit);

    // Create IDataObject and IDropSource COM objects
    CreateDropSource(&pDropSource);
    CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject);

    //
    //  ** ** ** The drag-drop operation starts here! ** ** **
    //
    dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);

    // success!
    if (dwResult == DRAGDROP_S_DROP)
    {
        if (dwEffect & DROPEFFECT_MOVE)
        {
            // remove selection from edit control
        }
    }
    // cancelled
    else if (dwResult == DRAGDROP_S_CANCEL)
    {
    }

    pDataObject->Release();
    pDropSource->Release();

    ReleaseCapture();
    * fMouseDown = FALSE;
    * fDidDragDrop = TRUE;
}

dataobject.cpp
Code: Select all  Expand view  RUN
//
//  DATAOBJECT.CPP
//
//  Implementation of the IDataObject COM interface
//
//  By J Brown 2004
//
//  www.catch22.net
//

#define STRICT

#include <windows.h>

// defined in enumformat.cpp
HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);

class CDataObject : public IDataObject
{
public:
    //
    // IUnknown members
    //
    HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
    ULONG   __stdcall AddRef (void);
    ULONG   __stdcall Release (void);
       
    //
    // IDataObject members
    //
    HRESULT __stdcall GetData               (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
    HRESULT __stdcall GetDataHere           (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
    HRESULT __stdcall QueryGetData          (FORMATETC *pFormatEtc);
    HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC *pFormatEct,  FORMATETC *pFormatEtcOut);
    HRESULT __stdcall SetData               (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium,  BOOL fRelease);
    HRESULT __stdcall EnumFormatEtc         (DWORD      dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
    HRESULT __stdcall DAdvise               (FORMATETC *pFormatEtc,  DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
    HRESULT __stdcall DUnadvise             (DWORD      dwConnection);
    HRESULT __stdcall EnumDAdvise           (IEnumSTATDATA **ppEnumAdvise);
   
    //
    // Constructor / Destructor
    //
    CDataObject(FORMATETC *fmt, STGMEDIUM *stgmed, int count);
    ~CDataObject();
   
private:

    int LookupFormatEtc(FORMATETC *pFormatEtc);

    //
    // any private members and functions
    //
    LONG       m_lRefCount;

    FORMATETC *m_pFormatEtc;
    STGMEDIUM *m_pStgMedium;
    LONG       m_nNumFormats;

};

//
//  Constructor
//
CDataObject::CDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
{
    m_lRefCount  = 1;
    m_nNumFormats = count;
   
    m_pFormatEtc  = new FORMATETC[count];
    m_pStgMedium  = new STGMEDIUM[count];

    for(int i = 0; i < count; i++)
    {
        m_pFormatEtc[i] = fmtetc[i];
        m_pStgMedium[i] = stgmed[i];
    }
}

//
//  Destructor
//
CDataObject::~CDataObject()
{
    // cleanup
    if(m_pFormatEtc) delete[] m_pFormatEtc;
    if(m_pStgMedium) delete[] m_pStgMedium;

    OutputDebugString("oof\n");
}

//
//  IUnknown::AddRef
//
ULONG __stdcall CDataObject::AddRef(void)
{
    // increment object reference count
    return InterlockedIncrement(&m_lRefCount);
}

//
//  IUnknown::Release
//
ULONG __stdcall CDataObject::Release(void)
{
    // decrement object reference count
    LONG count = InterlockedDecrement(&m_lRefCount);
       
    if(count == 0)
    {
        delete this;
        return 0;
    }
    else
    {
        return count;
    }
}

//
//  IUnknown::QueryInterface
//
HRESULT __stdcall CDataObject::QueryInterface(REFIID iid, void **ppvObject)
{
    // check to see what interface has been requested
    if(iid == IID_IDataObject || iid == IID_IUnknown)
    {
        AddRef();
        *ppvObject = this;
        return S_OK;
    }
    else
    {
        *ppvObject = 0;
        return E_NOINTERFACE;
    }
}

HGLOBAL DupMem(HGLOBAL hMem)
{
    // lock the source memory object
    DWORD   len    = GlobalSize(hMem);
    PVOID   source = GlobalLock(hMem);
   
    // create a fixed "global" block - i.e. just
    // a regular lump of our process heap
    PVOID   dest   = GlobalAlloc(GMEM_FIXED, len);

    memcpy(dest, source, len);

    GlobalUnlock(hMem);

    return dest;
}

int CDataObject::LookupFormatEtc(FORMATETC *pFormatEtc)
{
    for(int i = 0; i < m_nNumFormats; i++)
    {
        if((pFormatEtc->tymed    &  m_pFormatEtc[i].tymed)   &&
            pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat &&
            pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
        {
            return i;
        }
    }

    return -1;

}

//
//  IDataObject::GetData
//
HRESULT __stdcall CDataObject::GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    int idx;

    //
    // try to match the requested FORMATETC with one of our supported formats
    //
    if((idx = LookupFormatEtc(pFormatEtc)) == -1)
    {
        return DV_E_FORMATETC;
    }

    //
    // found a match! transfer the data into the supplied storage-medium
    //
    pMedium->tymed           = m_pFormatEtc[idx].tymed;
    pMedium->pUnkForRelease  = 0;
   
    switch(m_pFormatEtc[idx].tymed)
    {
    case TYMED_HGLOBAL:

        pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal);
        //return S_OK;
        break;

    default:
        return DV_E_FORMATETC;
    }

    return S_OK;
}

//
//  IDataObject::GetDataHere
//
HRESULT __stdcall CDataObject::GetDataHere (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    // GetDataHere is only required for IStream and IStorage mediums
    // It is an error to call GetDataHere for things like HGLOBAL and other clipboard formats
    //
    //  OleFlushClipboard
    //
    return DATA_E_FORMATETC;
}

//
//  IDataObject::QueryGetData
//
//  Called to see if the IDataObject supports the specified format of data
//
HRESULT __stdcall CDataObject::QueryGetData (FORMATETC *pFormatEtc)
{
    return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}

//
//  IDataObject::GetCanonicalFormatEtc
//
HRESULT __stdcall CDataObject::GetCanonicalFormatEtc (FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut)
{
    // Apparently we have to set this field to NULL even though we don't do anything else
    pFormatEtcOut->ptd = NULL;
    return E_NOTIMPL;
}

//
//  IDataObject::SetData
//
HRESULT __stdcall CDataObject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease)
{
    return E_NOTIMPL;
}

//
//  IDataObject::EnumFormatEtc
//
HRESULT __stdcall CDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
{
    if(dwDirection == DATADIR_GET)
    {
        // for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
        // to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
        return CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
    }
    else
    {
        // the direction specified is not support for drag+drop
        return E_NOTIMPL;
    }
}

//
//  IDataObject::DAdvise
//
HRESULT __stdcall CDataObject::DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
    return OLE_E_ADVISENOTSUPPORTED;
}

//
//  IDataObject::DUnadvise
//
HRESULT __stdcall CDataObject::DUnadvise (DWORD dwConnection)
{
    return OLE_E_ADVISENOTSUPPORTED;
}

//
//  IDataObject::EnumDAdvise
//
HRESULT __stdcall CDataObject::EnumDAdvise (IEnumSTATDATA **ppEnumAdvise)
{
    return OLE_E_ADVISENOTSUPPORTED;
}

//
//  Helper function
//
HRESULT CreateDataObject (FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject)
{
    if(ppDataObject == 0)
        return E_INVALIDARG;

    *ppDataObject = new CDataObject(fmtetc, stgmeds, count);

    return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}

dropsource.cpp
Code: Select all  Expand view  RUN
//
//  DROPSOURCE.CPP
//
//  Implementation of the IDropSource COM interface
//
//  By J Brown 2004
//
//  www.catch22.net
//

#define STRICT

#include <windows.h>

class CDropSource : public IDropSource
{
public:
    //
    // IUnknown members
    //
    HRESULT __stdcall QueryInterface    (REFIID iid, void ** ppvObject);
    ULONG   __stdcall AddRef            (void);
    ULONG   __stdcall Release           (void);
       
    //
    // IDropSource members
    //
    HRESULT __stdcall QueryContinueDrag (BOOL fEscapePressed, DWORD grfKeyState);
    HRESULT __stdcall GiveFeedback      (DWORD dwEffect);
   
    //
    // Constructor / Destructor
    //
    CDropSource();
    ~CDropSource();
   
private:

    //
    // private members and functions
    //
    LONG       m_lRefCount;
};

//
//  Constructor
//
CDropSource::CDropSource()
{
    m_lRefCount = 1;
}

//
//  Destructor
//
CDropSource::~CDropSource()
{
}

//
//  IUnknown::AddRef
//
ULONG __stdcall CDropSource::AddRef(void)
{
    // increment object reference count
    return InterlockedIncrement(&m_lRefCount);
}

//
//  IUnknown::Release
//
ULONG __stdcall CDropSource::Release(void)
{
    // decrement object reference count
    LONG count = InterlockedDecrement(&m_lRefCount);
       
    if(count == 0)
    {
        delete this;
        return 0;
    }
    else
    {
        return count;
    }
}

//
//  IUnknown::QueryInterface
//
HRESULT __stdcall CDropSource::QueryInterface(REFIID iid, void **ppvObject)
{
    // check to see what interface has been requested
    if(iid == IID_IDropSource || iid == IID_IUnknown)
    {
        AddRef();
        *ppvObject = this;
        return S_OK;
    }
    else
    {
        *ppvObject = 0;
        return E_NOINTERFACE;
    }
}

//
//  CDropSource::QueryContinueDrag
//
//  Called by OLE whenever Escape/Control/Shift/Mouse buttons have changed
//
HRESULT __stdcall CDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
    // if the <Escape> key has been pressed since the last call, cancel the drop
    if(fEscapePressed == TRUE)
        return DRAGDROP_S_CANCEL;   

    // if the <LeftMouse> button has been released, then do the drop!
    if((grfKeyState & MK_LBUTTON) == 0)
        return DRAGDROP_S_DROP;

    // continue with the drag-drop
    return S_OK;
}

//
//  CDropSource::GiveFeedback
//
//  Return either S_OK, or DRAGDROP_S_USEDEFAULTCURSORS to instruct OLE to use the
//  default mouse cursor images
//
HRESULT __stdcall CDropSource::GiveFeedback(DWORD dwEffect)
{
    return DRAGDROP_S_USEDEFAULTCURSORS;
}

//
//  Helper routine to create an IDropSource object
// 
HRESULT CreateDropSource(IDropSource **ppDropSource)
{
    if(ppDropSource == 0)
        return E_INVALIDARG;

    *ppDropSource = new CDropSource();

    return (*ppDropSource) ? S_OK : E_OUTOFMEMORY;

}
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: opposite of HB_FUNC( REGISTERDRAGDROP ) ?

Postby Jimmy » Wed Dec 20, 2023 9:20 pm

hi Antonio,
Antonio Linares wrote:Next is to properly use it from FWH and Harbour:

GREAT
it would be nice when include in next FWH Version
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 99 guests