I've been trying to implement some Drag and Drop (using the OLE method) functionality into my Win32 program, and have been hitting a roadblock. I've been trying to follow
this tutorial I found. From what I understand, I needed to create a class that inherits from IDropTarget
Below is the extremelty stubbed out class.
DropTarget.hpp
#ifndef DEFINE_KS_GUI_WIN32_DROPTARGET_HPP
#define DEFINE_KS_GUI_WIN32_DROPTARGET_HPP
#include <OleIdl.h>
class DropTarget : public IDropTarget
{
public:
DropTarget();
~DropTarget();
/* IUnknown functions */
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
/* IDropTarget functions */
HRESULT STDMETHODCALLTYPE DragEnter(IDataObject* in_DataObject, DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect);
HRESULT STDMETHODCALLTYPE DragOver(DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect);
HRESULT STDMETHODCALLTYPE DragLeave();
HRESULT STDMETHODCALLTYPE Drop(IDataObject* in_DataObject, DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect);
private:
ULONG m_RefCount;
};
#endif // DEFINE_KS_GUI_WIN32_DROPTARGET_HPP
DropTarget.cpp
#include "DropTarget.hpp"
#include <iostream>
DropTarget::DropTarget() :
m_RefCount(1)
{
}
DropTarget::~DropTarget()
{
}
HRESULT STDMETHODCALLTYPE DropTarget::QueryInterface(REFIID riid, void** ppvObject)
{
if(ppvObject == 0)
{
return E_POINTER;
}
return S_OK;
}
ULONG STDMETHODCALLTYPE DropTarget::AddRef()
{
return ++m_RefCount;
}
ULONG STDMETHODCALLTYPE DropTarget::Release()
{
if((--m_RefCount) == 0)
{
/* Release resources */
}
return m_RefCount;
}
HRESULT STDMETHODCALLTYPE DropTarget::DragEnter(IDataObject* in_DataObject, DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE DropTarget::DragOver(DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE DropTarget::DragLeave()
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE DropTarget::Drop(IDataObject* in_DataObject, DWORD in_KeyState, POINTL in_Point, DWORD* inout_Effect)
{
return S_OK;
}
Below is a simple program a rigged up to try and get it to work, when it wouldn't inside my bigger project. I create an instance of DropTarget and register it to the window. When a file is dragged onto the window, the DropTarget::DragEnter should be called, followed by DropTarget::DragOver until the mouse is released and DropTarget::Drop is called, or the mouse leaves the window and DropTarget::DragLeave is called. The DropTarget functions never seem to be called, when a file icon is dragged over the window. I set break points on all of the returns in the DropTarget functions, and none of them are ever tripped (Debugging using MSVC2005).
#include <windows.h>
#include <iostream>
#include <exception>
#include "DropTarget.hpp"
LRESULT CALLBACK WindowProcedure(HWND in_WindowHandle, UINT in_Message, WPARAM in_wParam, LPARAM in_lParam)
{
switch(in_Message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
}
default:
{
return DefWindowProc(in_WindowHandle, in_Message, in_wParam, in_lParam);
}
}
}
int WINAPI WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, PSTR CmdLine, int ShowCommand)
{
try
{
OleInitialize(0);
WNDCLASSEX _WindowClass;
ZeroMemory(&_WindowClass, sizeof(_WindowClass));
const HINSTANCE _InstanceHandle(GetModuleHandle(0));
_WindowClass.cbClsExtra = 0;
_WindowClass.cbSize = sizeof(_WindowClass);
_WindowClass.cbWndExtra = 0;
_WindowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_APPWORKSPACE + 1);
_WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
_WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
_WindowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
_WindowClass.hInstance = _InstanceHandle;
_WindowClass.lpfnWndProc = WindowProcedure;
_WindowClass.lpszClassName = TEXT("MyForm");;
_WindowClass.lpszMenuName = 0;
_WindowClass.style = CS_HREDRAW | CS_VREDRAW;
ATOM _Atom(RegisterClassEx(&_WindowClass));
if(_Atom == 0)
{
const DWORD _Error(GetLastError());
throw std::exception("Error");
}
const LPTSTR _ClassName(MAKEINTATOM(_Atom));
/* Create the window */
HWND _WindowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW | WS_EX_CONTROLPARENT, _ClassName, TEXT(""), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, Instance, 0);
if(_WindowHandle == 0)
{
const DWORD _Error(GetLastError());
throw std::exception("Error");
}
ShowWindow(_WindowHandle, SW_SHOW);
/* Create the OLE Target */
DropTarget _DropTarget;
/* Register it with the window */
if(RegisterDragDrop(_WindowHandle, &_DropTarget) != S_OK)
{
throw std::exception("Error");
}
MSG _Message;
do
{
GetMessage(&_Message, 0, 0, 0);
TranslateMessage(&_Message);
DispatchMessage(&_Message);
}
while(_Message.message != WM_QUIT);
OleUninitialize();
}
catch(std::exception&)
{
return -1;
}
return 0;
}
I tried compiling the tutorial example, but it actually seems to be more geared torwards using the clipboard and a textbox instead of dragging an actual file into the window.
Does anyone know if I'm missing something in the code?