Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8006003
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T17:22:07+00:00 2026-06-04T17:22:07+00:00

Passing Graphics object between native C++ and C# I’m currently working on a Paint

  • 0

Passing Graphics object between native C++ and C#

I’m currently working on a Paint .NET-like application. I have mulitple types of layers which are implemented in C#. These layers are drawn into a .NET Graphics object that is provided by a WinForms user control – it is similar to the WPF canvas control. The layer base class has a Draw method that is implemented as follows:

public void Draw(IntPtr hdc)
{
    using (var graphics = Graphics.FromInternalHDC(hdc)
    {
         // First: Setup rendering settings like SmoothingMode, TextRenderingHint, ...
         // Layer specific drawing code goes here...
    }
}

For performance and decompiling issues I’m doing the composition of the layers in a mixed mode assembly since I’m also applying effects like bevel or drop shadow. The wrapper, of course written in C++/CLI, gets directly called from the canvas control and forwards the metadata of each layer and the target Graphics object (Graphics object from my C# written canvas user control) to a native 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);
     // Setup rendering settings (SmoothingMode, TextRenderingHint, ...)

     for each metaData in metaDataVector
     {
        // Create bitmap and graphics for current layer
        Bitmap* layerBitmap = new Bitmap(metaData.Width, metaData.Height, Format32bppArgb);
        Graphics* layerGraphics = new Graphics(layerBitmap);

        // Now the interesting interop part
        // Get HDC from layerGraphics
        HDC lgHDC = layerGraphics->GetHDC();

        // Call metaData.Delegate and pass the layerGraphics HDC to C#
        // By this call we are ending up in the Draw method of the C# Layer object
        metaData.layerDrawDelegate(lgHDC);     

        // Releasing HDC - leaving interop...
        layerGraphics->ReleaseHDC(lgHDC);

        // Apply bevel/shadow effects
        // Do some other fancy stuff

        graphics.DrawImage(layerBitmap, metaData.X, metaData.Y, metaData.Width, metaData.Height);        
     }
  }
}

So far so good. The above code works nearly as expected, but…

Problem

The only thing is that my current implementation is lacking of anti aliasing and semi transparency when rendering PNG with shadows for example. So I just have only 2 values for the Alpha channel: Transparent or full visible Color at 255. This side effect makes drawing PNGs with alpha channel and fonts looking very ugly. I cannot get the same smooth and nice semi transparent anti aliasing any more like before when I worked with pure C# code.

BUT: When drawing a string in the native Graphics object directly,

 layerGraphics->DrawString(...);

anti aliasing and semi transparency are back for good. So the problem is only evident when passing the Graphics HDC to .NET.

Questions

Is there any solution/workaround for this problem? I’ve tried to create the Bitmap directly in the C# Layer class and return the IntPtr for the HBITMAP to the native code. This approach is working, but in this case I have another problem since I cannot find a perfect solution for converting HBITMAP to GDI+ Bitmap with alpha channel (white pixel noise is surrounding the edges when drawing fonts).

Thanks for your input! 🙂

Demo Solution

Attached you’ll find a demo solution here: Sources

In this demo solution I’m testing 3 different rendering methods (all implemented in NativeRenderer.cpp), while the FIRST ONE shows the described problems:

Demo output

1) RenderViaBitmapFromCSharp() – a) Creates a new bitmap in C++, creates a new Graphics object in C++, calls the C# drawing code by passing the C++ Graphics object HDC – Fails

But: b) Drawing directly from C++ works via the created bitmap too

2) RenderDirectlyFromCSharp() – Creates a new Graphics object from C# Graphics handle in C++
, calls the C# drawing code by passing the C++ Graphics object HDC – Works

3) RenderDirectlyFromCPP() – Creates a new Graphics object from C# Graphics handle in C++, draws the text directly in C++ – Works

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T17:22:08+00:00Added an answer on June 4, 2026 at 5:22 pm

    I’ve ended up creating the Bitmap in C# and passing the object to C++/CLI. As already mentioned by Hans and Vincent you have to avoid GetHDC. So my workaround reads in pseudo code as follows:

    Layer.cs C#:

    public Bitmap Draw()
    {
         var bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
         using (var graphics = Graphics.FromBitmap(bitmap)
         {
              // First: Setup rendering settings like SmoothingMode, TextRenderingHint, ...
              // Layer specific drawing code goes here...
         }
         return bitmap;
    }
    

    NativeRenderer.cs C++:

    void NativeRenderer::RenderFromBitmapCSharp(System::Drawing::Bitmap^ bitmap)
    {
        // Create and lock empty native bitmap
        Bitmap *gdiBitmap = new Bitmap(bitmap->Width, bitmap->Height, PixelFormat32bppARGB);
        Rect rect(0, 0, bitmap->Width, bitmap->Height);
        BitmapData bitmapData;
        gdiBitmap->LockBits(&rect, Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
    
        // Lock managed bitmap
        System::Drawing::Rectangle rectangle(0, 0, bitmap->Width, bitmap->Height);
        System::Drawing::Imaging::BitmapData^ pBitmapData = bitmap->LockBits(rectangle, System::Drawing::Imaging::ImageLockMode::ReadOnly, System::Drawing::Imaging::PixelFormat::Format32bppArgb);
    
        // Copy from managed to unmanaged bitmap
        ::memcpy(bitmapData.Scan0, pBitmapData->Scan0.ToPointer(), bitmap->Width * bitmap->Height * 4);
        bitmap->UnlockBits(pBitmapData);
        gdiBitmap->UnlockBits(&bitmapData);
    
        // Draw it
        _graphics->DrawImage(gdiBitmap, 0, 0, bitmap->Width, bitmap->Height);
    }
    

    Hope that is helpful to others – have not found any code snippet on the web which actually does converting managed to unmanaged GDI+ Bitmap.

    Thank you all for your comments.

    Cheers,
    P

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to access the Graphics object of a Panel by passing it as
Possible Duplicate: passing a pointer by reference in c++ I have a function that
In my application I have rolled my own SVG converter that translates a raw
i have no idea why the following code doesn't work. i'm simply passing and
Here's the situation: We have some generic graphics code that we use for one
I am trying to design an asic graphics processor. I have done extensive research
I have a header file that has a number of declarations like this: extern
I have a windows form application with an SQL compact database. It runs on
I can't seem to make DrawBorder to work when passing a new rectangle object
I would like to have realtime like map. My main question is: How to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.