Skip to content

Instantly share code, notes, and snippets.

@egtra
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egtra/7a3ca22888b970a364f1 to your computer and use it in GitHub Desktop.
Save egtra/7a3ca22888b970a364f1 to your computer and use it in GitHub Desktop.
非同期ドロップ処理フリースレッドマーシャラー + CFSTR_FILEDESCRIPTOR (Windows Forms)
#define UNICODE
#define _UNICODE
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#include <string.h>
#include <Windows.h>
#include <ShlObj.h>
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Diagnostics;
using namespace System::IO;
using namespace System::Runtime::InteropServices;
using namespace System::Threading;
using namespace System::Windows::Forms;
namespace ComTypes = System::Runtime::InteropServices::ComTypes;
namespace NativeTypes
{
[ComVisible(true)]
[InterfaceTypeAttribute(ComInterfaceType::InterfaceIsIUnknown)]
[GuidAttribute("3D8B0590-F691-11d2-8EA9-006097DF5BD4")]
public interface class IDataObjectAsyncCapability
{
public:
void SetAsyncMode([MarshalAs(UnmanagedType::Bool)] bool fDoOpAsync);
[returnvalue:MarshalAs(UnmanagedType::Bool)]
bool GetAsyncMode();
void StartOperation(ComTypes::IBindCtx^ pbcReserved);
[returnvalue:MarshalAs(UnmanagedType::Bool)]
bool InOperation();
void EndOperation(HRESULT hResult, ComTypes::IBindCtx^ pbcReserved, DWORD dwEffects);
};
}
ref class AsyncDataObject : public DataObject, public NativeTypes::IDataObjectAsyncCapability
{
public:
virtual void SetAsyncMode([MarshalAs(UnmanagedType::Bool)] bool fDoOpAsync)
{
if (fDoOpAsync == false)
{
throw gcnew ArgumentException();
}
}
[returnvalue:MarshalAs(UnmanagedType::Bool)]
virtual bool GetAsyncMode()
{
return true;
}
virtual void StartOperation(ComTypes::IBindCtx^ /*pbcReserved*/)
{
Debug::WriteLine("StartOperation: " + Thread::CurrentThread->ManagedThreadId);
Interlocked::Increment(m_inOperationCount);
}
[returnvalue:MarshalAs(UnmanagedType::Bool)]
virtual bool InOperation()
{
return m_inOperationCount > 0;
}
virtual void EndOperation(HRESULT /*hResult*/, ComTypes::IBindCtx^ /*pbcReserved*/, DWORD /*dwEffects*/)
{
Debug::WriteLine("EndOperation: " + Thread::CurrentThread->ManagedThreadId);
Interlocked::Decrement(m_inOperationCount);
}
private:
int m_inOperationCount = 0;
};
DataObject^ GetFileDescriptorAndContent()
{
auto dataObj = gcnew AsyncDataObject;
auto buffer = gcnew array<BYTE>(sizeof FILEGROUPDESCRIPTOR);
pin_ptr<BYTE> p = &buffer[0];
auto fileGroupDescriptor = reinterpret_cast<FILEGROUPDESCRIPTOR*>(p);
fileGroupDescriptor->cItems = 1;
fileGroupDescriptor->fgd[0].dwFlags = static_cast<DWORD>(FD_PROGRESSUI | FD_UNICODE);
wcscpy_s(fileGroupDescriptor->fgd[0].cFileName, L"test.txt");
dataObj->SetData(CFSTR_FILEDESCRIPTOR, gcnew MemoryStream(buffer));
auto data = gcnew array<BYTE> { 'a', 'b', 'c' };
auto content = gcnew MemoryStream;
content->Write(data, 0, data->Length);
dataObj->SetData(CFSTR_FILECONTENTS, content);
return dataObj;
}
void OnMouseDown(Object^ sender, MouseEventArgs^ e)
{
if ((e->Button & MouseButtons::Left) != MouseButtons())
{
Debug::WriteLine("Before DoDragDrop: " + Thread::CurrentThread->ManagedThreadId);
safe_cast<Control^>(sender)->DoDragDrop(GetFileDescriptorAndContent(), DragDropEffects::Copy);
Debug::WriteLine("After DoDragDrop: " + Thread::CurrentThread->ManagedThreadId);
}
}
[STAThread]
int main(array<System::String ^> ^args)
{
auto f = gcnew Form;
f->MouseDown += gcnew MouseEventHandler(OnMouseDown);
Application::Run(f);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment