GDIPLUS: using Graphics, can i get HDC?

using Graphics, can i get HDC?
Net searches work wonders.....
i tried that with no luck :(
on my image class i have:
1
2
3
4
operator HDC()
    {
        return graphic->GetHDC();
    }

if i use it, the image isn't drawed :(
1
2
3
4
5
6
7
8
9
10
11
12
13
//....
img.FromFile("C:\\Users\\Joaquim\\Pictures\\1595973613452.jpg");
    image img2;
    img2.NewImage(300,300);
    img.DrawImage(img2.graphic,0,0);
	do
    {
       
        //img.DrawImage(WindowHDC,800,0);

        //img2.DrawImage(WindowHDC,0,0);
        BitBlt(WindowHDC,0,0,img2.SizeWidth, img2.SizeHeight,img2,0,0,SRCCOPY);
//... 
Last edited on
greate....
1
2
3
4
if(BitBlt(WindowHDC,0,0,img2.SizeWidth, img2.SizeHeight,img2.graphic->GetHDC(),0,0,SRCCOPY)>0)
        {
            MessageBox (NULL,getGdiplusStatusMessage(img2.graphic->GetLastStatus()).c_str(), "error", MB_OK);
        }

i get the messagebox, but with 0(zero)(OK)... if i use the GetLastError(), i get zero too.
1
2
3
4
5
HRESULT h = BitBlt(WindowHDC,0,0,img2.SizeWidth, img2.SizeHeight,img2.graphic->GetHDC(),0,0,SRCCOPY);
        if(h>0)
        {
            MessageBox (NULL,to_string(h).c_str(), "error", MB_OK);
        }

i get '1' - ERROR_INVALID_FUNCTION... from BitBlt()
i don't know why :(
Last edited on
i even tried these way(GetHDC, use GDI functions, and then ReleaseHDC):
1
2
3
4
5
6
7
8
 HDC imageHDC = img2.graphic->GetHDC();
        HRESULT h = BitBlt(WindowHDC,0,0,img2.SizeWidth, img2.SizeHeight,imageHDC,0,0,SRCCOPY);

        if(h>0)
        {
            MessageBox (NULL,to_string(h).c_str(), "error", MB_OK);
        }
        img2.graphic->ReleaseHDC(imageHDC);

i get '1' tooo
According to this:

https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-bitblt

BitBlt(...) returns a value >0 when successfull.


That you don't see the image might have to do with the target dc (WindowHDC). When used wrongly it might get over painted.

You rather need an event handler for the paint event. See:

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.painteventargs?view=windowsdesktop-6.0

The Graphics property of the PaintEventArgs let you draw the image without using BitBlt(...).
@coder777: i'm using the BitBlt() only for test the 'imageHDC'... because i'm not getting the right value :(
if i use Graphics::DrawImage() the 'WindowHDC' gets drawed.... i just need get the HDC correctly.
heres the entire image class:
1
2
3
4
5
6
7
8
9
10
11
//Convert the std::string to std::wstring:
//is for use on FromFile()...
std::wstring towstring(const std::string& v)
{
    std::wstring out(v.size()+1,L'\0');

    int size = MultiByteToWideChar(CP_UTF8, 0, v.c_str(), -1, &out[0], out.size());

    out.resize(size-1);
    return out;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class image
{
    public:

    ULONG_PTR m_gdiplusToken=NULL;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    Graphics *graphic=nullptr;
    Gdiplus::Bitmap *img;
    int SizeWidth=0;
    int SizeHeight=0;

    HDC GetHDC()
    {
        //i'm not getting the right HDC value :(
        return graphic->GetHDC();
    }

    void ReleaseHDC(HDC DestinationHDC)
    {
        graphic->ReleaseHDC(DestinationHDC);
    }

    COLORREF GetPixel(int PosX, int PosY)
    {
        Color clr;
        img->GetPixel(PosX, PosY, &clr);
        return  clr.ToCOLORREF();
    }

    void SetPixel(int PosX, int PosY, COLORREF color)
    {
        Color *clr;
        clr->SetFromCOLORREF(color);
        img->SetPixel(PosX, PosY,clr);
    }

    image()
    {
        //nothing:
    }

    image(int Width, int Height)
    {
        Dispose();
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img = new Bitmap( Width,  Height);
        graphic=new Graphics(img);
    }

    image(string strFile)
    {
        Dispose();
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img=new Bitmap(towstring(strFile).c_str());
        graphic=new Graphics(img);
    }

    void Clear(Color clr=Color::Black)
    {
        SolidBrush *Fill=new SolidBrush(Color::White);
        graphic->FillRectangle(Fill,0,0,SizeWidth,SizeHeight);
    }

    void NewImage(int Width, int Height)
    {
        Dispose();
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img=new Gdiplus::Bitmap(Width, Height);
        graphic=new Gdiplus::Graphics(img);
        SolidBrush *Fill=new SolidBrush(Color::White);
        graphic->FillRectangle(Fill,0,0,Width,Height);
        delete Fill;
    }

    void Dispose()
    {
        //clear all objects for avoid memory leaks:
        if(m_gdiplusToken)
        {
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
        }
        //by some reason, i can't delete the 'new' values: 'img' and 'graphic'
        //the program terminates with an exit error
    }

    ~image()
    {
        Dispose();
    }

    void FromFile(string strFile)
    {
        Dispose();
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img=new Bitmap(towstring(strFile).c_str());
    }

    //these 2 functions works and tested:
    void DrawImage(HDC DestinationHDC, float PosX, float PosY)
    {
        if(!img || !m_gdiplusToken) return;
        Gdiplus::Graphics graphics2(DestinationHDC);
        graphics2.DrawImage(img, PosX, PosY, img->GetWidth(), img->GetHeight());
    }

    void DrawImage(Graphics *Destination, float PosX, float PosY)
    {
        //if we don't have an image or the GDIPLUS isn't activated, we exit
        if(!img || !m_gdiplusToken) return; 

        Destination->DrawImage(img, PosX, PosY, img->GetWidth(), img->GetHeight());
    }
};
Whether you see the image depends on how and when you use BitBlt(...). The return value > 0 tells you that it succeeded.

What about SizeWidth/SizeHeight? I don't see where those values are set before using BitBlt(...). I would think they should be set in each of the constructors.
yes i tested that:
1
2
3
4
5
6
7
8
9
10
 img.DrawImage(WindowHDC,800,0);
        //img2.DrawImage(WindowHDC,0,0);
        HDC imageHDC = img2.GetHDC();
        HRESULT h = BitBlt(WindowHDC,0,0,100, 100,imageHDC,0,0,SRCCOPY);

        if(h>0)
        {
            MessageBox (NULL,to_string(h).c_str(), "error", MB_OK);
        }
        img2.ReleaseHDC(imageHDC);

but no image is drawed :(
i still get '1'.. but , like you said, more than zero the BitBlt() do the work.
and more: i did these sample:
1
2
img.DrawImage(WindowHDC,800,0);
BitBlt(WindowHDC,0,0,100, 100,WindowHDC,800,0,SRCCOPY);

i get results now.... like i said, the problem seems on:
HDC imageHDC = img2.GetHDC();
Last edited on
i get results now.... like i said, the problem seems on:
HDC imageHDC = img2.GetHDC();
Possible but unlikely. BitBlt(...) is suppose to fail when using an invalid HDC. I would rather think that the image gets overdrawn (by the background or something) which is likely when you try to draw outside the paint message.
please see these simple code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
do
    {
        //is drawed too:
        img.DrawImage(WindowHDC,800,0);

        //Get the HDC:
        HDC imghdc = img.graphic->GetHDC();

        //the rectangle is drawed on image(imghdc):
        Rectangle(imghdc,0,0,50,50);

        //the image isn't drawed on window:
        BitBlt(WindowHDC,0,0, 100,100,imghdc,0,0,SRCCOPY);

        //we must realease the HDC after use GDI functions
        //and before use GDIPlus functions:
        img.graphic->ReleaseHDC(imghdc);
        Sleep(1000);
    }while(!(GetKeyState(VK_ESCAPE) & 0x8000));//press escape for exit 

like i said, on comments: the rectangle is drawed on image.
but i can't draw the image using the BitBlt() :(
so what i'm doing wrong?
Last edited on
finally, i get something:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HDC imghdc = img.graphic->GetHDC();
    //img.DrawImage(WindowHDC,800,0);
	do
    {




        //the rectangle is drawed on image(imghdc):
        Rectangle(imghdc,0,0,50,50);

        //the image isn't drawed on window:
        BitBlt(WindowHDC,0,0, img.Width, img.Height,imghdc,0,0,SRCCOPY);


        Sleep(1000);
    }while(!(GetKeyState(VK_ESCAPE) & 0x8000));//press escape for exit
    //we must realease the HDC after use GDI functions
        //and before use GDIPlus functions:
        img.graphic->ReleaseHDC(imghdc);

the Rectangle is drawed on image... but when i use the BitBlt(), only the Rectangle is drawed.... but where is the image?
1
2
3
4
5
6
7
8
9
10
void FromFile(string strFile)
    {
        Dispose();
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img=new Bitmap(towstring(strFile).c_str());
        Width=img->GetWidth();
        Height=img->GetHeight();
        graphic=new Graphics(img);
        //graphic->DrawImage(img,0,0);
    }
heres the result:
https://imgur.com/IXtmQPB
we can't use BitBlt() correctly with Graphics->getDC()...
the best is create the Graphics with HDC window and use the Graphics from the GDIplus::image with DrawImage():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int main()
{
     //getting the HDC Console Window:
    HDC WindowHDC=GetDC(GetConsoleWindow());
    
    image img;
    img.FromFile("C:\\Users\\Joaquim\\Pictures\\1595973613452.jpg");
    
    //Get Graphics from HDC Window:
    Graphics *WindowGraphics;
    WindowGraphics=new Graphics(WindowHDC);


	do
    {

        //Get the HDC image:
        HDC imghdc = img.graphic->GetHDC();
        
        //the rectangle is drawed on image(imghdc):
        Rectangle(imghdc,0,0,50,50);
        //SetPixel(imghdc,0,0,RGB(255,0,0));
        
        
        //and before use GDIPlus functions, we must release the HDC:
        img.graphic->ReleaseHDC(imghdc);
        
        //now we draw the image on window:
        WindowGraphics->DrawImage(img.img, 0,0);
        
        //the frme delay:
        Sleep(1000);
        
    }while(!(GetKeyState(VK_ESCAPE) & 0x8000));//press escape for exit
    
    //we must realease the HDC Window:
    WindowGraphics->ReleaseHDC(WindowHDC);
    
    cout<<"Press return to end . . ."<<endl;
    cin.get();

}
Yes, I would think that BitBlt(...) is only reliable within the paint message.

I didn't know that you can use the console for graphics. But like any other window it needs to paint itself at some point...
Registered users can post here. Sign in or register to post.