Thursday, December 13, 2007

From Nish.

//code starts here
namespace msclr
{
    namespace interop
    {
        template<> ref class context_node<System::Drawing::Font^, HFONT> : public context_node_base
        {
        private:
            System::Drawing::Font^ _font;
	
        public:
            context_node(System::Drawing::Font^% to, HFONT from)
            {
                to = _font = System::Drawing::Font::FromHfont((IntPtr)from);
            }
	
            ~context_node()
            {
                this->!context_node();
            }
	
        protected:
            !context_node()
            {
                delete _font;
            }
        };
	
        template<> ref class context_node<HFONT, System::Drawing::Font^> : public context_node_base
        {
        private:
            HFONT _hFont;
	
        public:
            context_node(HFONT& to, System::Drawing::Font^ from)
            {
                to = _hFont = (HFONT)from->ToHfont().ToPointer();
            }
	
            ~context_node()
            {
                this->!context_node();
            }
	
        protected:
            !context_node()
            {
                DeleteObject(_hFont);
            }
        };
    }
}
//code ends here

Wow. Our first use of a context. Instead of writing a function that implements a specialization of the template function, you write a class that implements a specialization of the template class. Since it's a class, it can have member variables, which you clean up when the context goes out of scope.

Here's how you might use it:

HFONT hFont = CreateSampleFont();
	
//...
	
marshal_context context;
	
System::Drawing::Font^ font =
    context.marshal_as<System::Drawing::Font^>(hFont);
HFONT hFontCopy = context.marshal_as<HFONT>(font);
	
//...
	
DeleteObject(hFont);

Kate

posted on 12/13/2007 5:15:57 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1]

From Nish.

//code starts here
namespace msclr
{
    namespace interop
    {
        template<> System::Drawing::Rectangle
            marshal_as<System::Drawing::Rectangle, RECT> (
            const RECT& from)
        {
            return System::Drawing::Rectangle(from.left, from.top,
                from.right - from.left, from.bottom - from.top);
        } 
	
        template<> System::Drawing::Rectangle marshal_as<
            System::Drawing::Rectangle, CRect> (
            const CRect& from)
        {
            return System::Drawing::Rectangle(from.left, from.top,
                from.Width(), from.Height());
        } 
	
        template<> RECT marshal_as<RECT, System::Drawing::Rectangle>(
            const System::Drawing::Rectangle& from)
        {
            System::Drawing::Rectangle rectangle = from; //remove const
            RECT rect = {rectangle.Left, rectangle.Top,
                rectangle.Right, rectangle.Bottom};
            return rect;
        }
	
        template<> CRect marshal_as<CRect, System::Drawing::Rectangle>(
            const System::Drawing::Rectangle& from)
        {
            System::Drawing::Rectangle rectangle = from; //remove const
            return CRect (rectangle.Left, rectangle.Top,
                rectangle.Right, rectangle.Bottom);
        }
    }
}
//code ends here

Why cast away const? Because System::Drawing::Rect is CLS-compliant and the properties (Top, Bottom, Left Right) are not flagged as keeping the object const. We know they don't change it, so we make a copy to use the properties on, thus keeping the compiler happy about our const ref argument.

To use these, it's as you'd expect:

//To Rectangle
RECT rect = {10, 10, 110, 110};
System::Drawing::Rectangle rectangle = marshal_as<System::Drawing::Rectangle>(rect);
	
CRect mfcRect(20, 20, 220, 220);
rectangle = marshal_as<System::Drawing::Rectangle>(mfcRect);
	
//From Rectangle
RECT rectBack = marshal_as<RECT>(rectangle);
CRect mfcRectBack = marshal_as<CRect>(rectangle);

Kate

posted on 12/13/2007 5:05:57 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, November 22, 2007

From Jason Olson.

//code starts here

#pragma once
#include
<msclr\marshal.h>
#include <msclr\marshal_windows.h>

namespace msclr {
namespace interop {

////////////////////////////////////////////////////////////////////
// GUID Conversions
////////////////////////////////////////////////////////////////////

template<>
inline _GUID marshal_as<_GUID, System::Guid>(const System::Guid& from) {

    System::Guid^ source = from;
    array<Byte>^ guidData = source->ToByteArray();
    pin_ptr<Byte> data = &(guidData[ 0 ]);
    return *(_GUID *)data;

}

template<>
inline Guid marshal_as<System::Guid, _GUID>(const _GUID& from) {
    
return System::Guid( from.Data1, from.Data2, from.Data3, from.Data4[ 0 ], from.Data4[ 1 ],
                                 from.Data4[ 2 ], from.Data4[ 3 ], from.Data4[ 4 ], from.Data4[ 5 ],
                                 from.Data4[ 6 ], from.Data4[ 7 ] );

}

}

}

//code ends here

At first glance the pin_ptr is a little scary, but this code doesn't return it, it dereferences it. So no "GC hole" to worry about.

Kate

posted on 11/22/2007 8:41:32 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]

From Jason Olson.

//code starts here

#pragma once
#include
<msclr\marshal.h>
#include <msclr\marshal_windows.h>
namespace msclr {
namespace interop {

////////////////////////////////////////////////////////////////////
// File I/O Conversions (constants from System::IO)
///////////////////////////////////////////////////////////////////

template<>
inline DWORD marshal_as<DWORD, System::IO::FileMode>(const System::IO::FileMode& from) {

if (from != System::IO::FileMode::Append)
   
return (DWORD)from;
else
   
return (DWORD)System::IO::FileMode::OpenOrCreate;

}

template<>
inline DWORD marshal_as<DWORD, System::IO::FileAccess>(const System::IO::FileAccess& from) {
if (from == System::IO::FileAccess::Read)
   
return GENERIC_READ;
else
   
return GENERIC_WRITE;

}

template<>
inline DWORD marshal_as<DWORD, System::IO::FileShare>(const System::IO::FileShare& from) {
   
return (DWORD)from;

}

}

}

//code ends here

Nice and simple.

Kate

posted on 11/22/2007 8:35:35 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]