Jump to content
  • Advertisement
Sign in to follow this  
Rattrap

Win32 - Drag And Drop

This topic is 3128 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement
If it comes to that point, I'll fallback to WM_DROPFILES, but I was hoping to get this version working.

Share this post


Link to post
Share on other sites
Your QueryInterface seems wrong, ppvObject is an out parameter. You probably need to do AddRef and *ppvObject = this in QueryInterface.

Also, I would use something like InterlockedIncrement and InterlockedDecrement to change the reference count thread-safely.

Share this post


Link to post
Share on other sites
I tried putting a breakpoint into QueryInterface, and it doesn't look like it is ever envoked, which I don't know if that is a/the problem or not.

As far as the thread safety, like I said, it's just a stubbed version. The full version uses boost threads, I just didn't want the example to have the dependancy.

[edit]
I think you are on the right track, the demo he had seems to envoke QueryInterface.

Share this post


Link to post
Share on other sites
I just discovered what is wrong, the problem wasn't the code, but the fact that I often use Remote Desktop to access my PC. Aparently the OLE functionality doesn't work through Remote Desktop. When I tried the code on a local machine, it fired correctly.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!