GDIPLUS: using Graphics, can i get HDC?

Jan 9, 2022 at 8:20pm
using Graphics, can i get HDC?
Jan 9, 2022 at 8:23pm
Net searches work wonders.....
Jan 9, 2022 at 8:32pm
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 Jan 9, 2022 at 8:33pm
Jan 9, 2022 at 10:25pm
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 Jan 9, 2022 at 10:29pm
Jan 9, 2022 at 10:46pm
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
Jan 10, 2022 at 7:04am
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(...).
Jan 11, 2022 at 10:10pm
@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());
    }
};
Jan 12, 2022 at 6:58am
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.
Jan 12, 2022 at 7:39pm
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 Jan 12, 2022 at 7:40pm
Jan 14, 2022 at 12:43pm
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.
Jan 16, 2022 at 4:37pm
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 Jan 16, 2022 at 4:40pm
Jan 16, 2022 at 4:48pm
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);
    }
Jan 16, 2022 at 5:04pm
heres the result:
https://imgur.com/IXtmQPB
Jan 19, 2022 at 8:19pm
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();

}
Jan 20, 2022 at 9:03am
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...
Topic archived. No new replies allowed.