Passing Graphics object between native C ++ and C #
I am currently working on a Paint.NET application. I have several types of layers that are implemented in C #. These layers are inserted into the .NET Graphics object that is provided by the WinForms user control β it looks like a WPF canvas control. The base level class has a Draw method, which is implemented as follows:
public void Draw(IntPtr hdc) { using (var graphics = Graphics.FromInternalHDC(hdc) {
For performance and decompilation, I am composing the layers in a mixed-mode assembly, as I also apply effects like bevel or shadow. The wrapper, naturally written in C ++ / CLI, gets the direct name from the canvas control and transfers the metadata of each layer and the Graphics target (a graphic from my C # written by the user of the canvas user element) to its own C ++ class.
C ++ / CLI Wrapper:
public ref class RendererWrapper { public: void Render(IEnumerable<Layer^>^ layersToDraw, Graphics^ targetGraphics) { // 1) For each layer get metadata (position, size AND Draw delegate) // 2) Send layer metadata to native renderer // 3) Call native renderer Render(targetGraphics.GetHDC()) method // 4) Release targetGraphics HDC }; }
Native C ++ Renderer:
class NativeRenderer { void NativeRenderer::Render(vector<LayerMetaData> metaDataVector, HDC targetGraphicsHDC) { Graphics graphics(targetGraphicsHDC);
So far so good. The above code works almost as expected, but ...
Problem
The only thing in my current implementation is lack of antialiasing and translucency when rendering PNG with shadows, for example. Therefore, I have only 2 values ββfor the Alpha channel: transparent or full visible color at 255. This side effect makes PNG drawing with the alpha channel and fonts looking very ugly. I cannot get the same smooth and nice translucent anti-aliasing as before when I was working with pure C # code.
BUT: When drawing a line directly in your own graphic object
layerGraphics->DrawString(...);
smoothing and translucency are back forever. Therefore, the problem is only apparent when transferring Graphics HDC to .NET.
Questions
Is there any solution / workaround for this problem? I tried creating a Bitmap directly in the C # Layer class and returning IntPtr for HBITMAP to native code. This approach works, but in this case I have a different problem, since I cannot find the perfect solution for converting HBITMAP to GDI + Bitmap with alpha channel (white pixel noise surrounds the edges when drawing fonts).
Thanks for your input! :)
Demo solution
In the application you will find a demo solution here: Sources
In this demo solution, I am testing 3 different rendering methods (they are all implemented in NativeRenderer.cpp), and FIRST ONE shows the described problems:
1) RenderViaBitmapFromCSharp () - a) Creates a new bitmap in C ++, creates a new Graphics object in C ++, calls the C # drawing code, passing the C ++ Graphics HDC object - Fails
But: b) Drawing directly from C ++ also works using the generated bitmap
2) RenderDirectlyFromCSharp () - Creates a new Graphics object from C # Graphic descriptor in C ++, calls the C # drawing code, passing the C ++ Graphics HDC object - Works
3) RenderDirectlyFromCPP () - Creates a new Graphics object from C # Graphic descriptor in C ++, draws text directly in C ++ - Works