Minimum count of irregular bitmap regions before multi-threading?

Minimum count of irregular bitmap regions before multi-threading?

Some conditions to set up the question:

If I have multiple irregular bitmap regions that I am moving around on a screen.

If the irregular bitmap regions change, like a game character turning in direction or looking like they are doing some activity.

If the irregular bitmap regions are all about 128x128 (BMP or jpg) and (128 million colors or 64K colors) then they are 48k in size.

The same irregular bitmap regions, using 256 colors "optimized" are not so nice looking, but it drops the size to 17K. I am using that as an average for this question.

Now the question:

How many of these individual irregular bitmap regions should I have before splitting them into different threads?

Given the following Examples:

Example: All as one continuous process
Create irregular Bitmap_45_degrees_right,
Create irregular Bitmap_90_degrees_right,
Create irregular Bitmap_135_degrees_right,
Create irregular Bitmap_480_degrees_right,
Create irregular Bitmap_225_degrees_right,
etc.
Then combine them all in a back buffer,
Then put them to the screen.

Or

Example: All as separate threads process
New thread Create irregular Bitmap_45_degrees_right,
New thread Create irregular Bitmap_90_degrees_right,
New thread Create irregular Bitmap_135_degrees_right,
New thread Create irregular Bitmap_480_degrees_right,
New thread Create irregular Bitmap_225_degrees_right,
etc.
Then combine them all in a back buffer,
Then put them to the screen.

If I have 3 of these, then I guess that one continuous process is ok.

If I have 300 of these then I guess that maybe I should be using some separate threads. What is an experienced opinion on this? There might be some programmers that view this site and have large game experience, and I am looking for experienced answers. Sending the whole thing to video cards and putting the burden on the end user does not work. I am learning C++11 and I want to learn it right.





Last edited on
What is an irregular bitmap?

How many of these individual irregular bitmap regions should I have before splitting them into different threads?
What are you doing with these bitmaps?

putting the burden on the end user
What could that mean?
Region ! It is called a "region." The shape of a cat or dog or horse, etc.

I guess that an irregular bitmap is a bitmap region that uses an original bitmap (like loaded from a file "horse.bmp") and then uses a bitmap mask (?) which is (I think) two color maybe and the bitmap mask is used to tell the software which areas of the bitmap to not include in the final bitblt (?). Example: A picture of a horse with a red background would be the starting bitmap loaded from a file. The bitmap mask would be everything in that picture except (?) the red area. WOW! This is a lot. I am barely keeping this process in my head. Then the original bitmap would be combined (or something) with(/without?) the mask to make an irregular bitmap. I looked at examples of bitmap stuff and found mostly shapes like circles, squares, etc. and they were difficult for me to understand how to use them. I found one example that used an irregular (?) bitmap all alone by itself and I have been trying to learn and understand from it.

Doing with these bitmaps... I want to write a game and to be able to have lots of things moving around. I want to learn, really learn, how that is done in C or C++ without ActiveX, etc.

I purchased some games years ago and they said that they required some special brand and version of a video card to be able to run. I did not have that. I shelved or threw away or returned the game. That game writer/publisher/people lost that customer. I had bought one video card and I thought that it was good quality, and if the game did not run using it, then I did not use that game. I do not want to put that burden of having to have a special video card on the end user, and I think that if I make a program that does not "require" such, then it is a good start.

Then, after that, I can maybe make options for various video cards. But, not a required exact card brand and model.

Thank you for asking.






Last edited on
Nowadays consumer software rarely has special requirements, because most of it is written to standards or known subsets of APIs supported on all mainstream systems.

Programmers wishing to specialize their software for the advanced features of particular hardware can do so if they wish, but when discussing consumer software this is often an optional "use-if-available" kind of arrangement, and not a hard requirement.

There are of course minimum requirements, but those are unavoidable, and can be made low enough that almost all users can satisfy them.
Last edited on
So, I researched a bit about 'irregular bitmaps'. It's sometimes referred to as bitmaps with transparent parts. Forget about regions. The exists but makes the system slow and are generally unnecessary.

So how to make a bitmap with transparent parts?
Lets assume you have an image where the white parts are supposed to be transparent.
Copy the bitmap and convert it with a drawing tool to black/white. Invert that b/w image.
Now you can use MaskBlt(...) with this two bitmaps to draw it transparent. See:

https://docs.microsoft.com/de-de/windows/win32/api/wingdi/nf-wingdi-maskblt

By the way: You can use the mask to determine whether or not it is hit withiin the transparent part or not.

how that is done in C or C++ without ActiveX, etc.
ActiveX (web) would be wrong here. I think you mean DirectX.

Then, after that, I can maybe make options for various video cards.
Today this is usuall not required anymore.


I guess you need double buffer. It works like this:
In WM_SIZE create a buffer bitmap using CreateDIBSection(...) or CreateCompatibleBitmap(...) (hdc = NULL should work):
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdibsection
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap

When you want to draw use CreateCompatibleDC(...) (with hdc = NULL) to get the dc to draw to, and select the previously created bitmap:
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatibledc

In WM_PAINT you use BitBlt(...) to SRCCOPY to the screen dc.
coder777 Thanks !

That is so much. I am trying to do this a little at a time while keeping in mind what you said.

I have decided to do a test myself. But, I have to first get some more understanding of the basics of just starting this test.

Here is where I am:


I have part of my code here. Not yet ready for testing thread speeds. Now I have a question about a part of it. I do not know if I am double buffering or not.

I have set up (I think maybe) a program background and I have placed bitmaps in corners, etc. that I can change later. I want to create it all in one back buffer and then put that to the (front?) buffer and (then?) put that to the screen. I am struggling with this. This is what I have now.

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
                    case WM_PAINT:
                    {
                        W=ThisFormsWIDTH;   // 800
                        H=ThisFormsHEIGHT;   // 500


                        HDC hdcSource;     // I think that this is where I first put the bitmaps.
                        HDC hdcDest;       // I think that this looks like the a (?) front buffer, 
                                           // but why do I have to draw to it each time to get it to work? 
                                           // Why can't I just draw everything to a (another?) back buffer 
                                           // and then when it is all done, just draw that to 
                                           // a front buffer? 
                                           // This is sooooo difficult !

                        hdcDest = BeginPaint(MAIN_WINDOW, &ps);             // Begin paint
                                           // Why does the BeginPaint  have to be here instead
                                           // of later when this all done in back buffer(s)?

                        hdcSource = CreateCompatibleDC(GetDC(nullptr));     // Create a Memory Device Context
                                                                            
                                                                            

                        HBITMAP                 bmpWindow_Full_Background = (HBITMAP)LoadImage(nullptr,
                            L"Window_Full_Background_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindow_Full_Background);
                        StretchBlt(hdcDest, 0, 0, W, H, hdcSource, 0, 0, 100, 100, SRCCOPY);

                        HBITMAP                 bmpWindowTopBackPanel = (HBITMAP)LoadImage(nullptr,
                            L"window_top_center_BACK_PANEL_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowTopBackPanel);
                        StretchBlt(hdcDest, 0, 0, W, 18, hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowTopCenter = (HBITMAP)LoadImage(nullptr,
                            L"window_top_center_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowTopCenter);
                        StretchBlt(hdcDest, (W/2)-20, 0, 40, 40, hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowTopLeft = (HBITMAP)LoadImage(nullptr,
                            L"window_top_left_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowTopLeft);
                        BitBlt(hdcDest, 0, 0, 40, 40, hdcSource, 0, 0, SRCCOPY);

                        HBITMAP                 bmpWindowTopRight = (HBITMAP)LoadImage(nullptr,
                            L"window_top_right_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowTopRight);
                        BitBlt(hdcDest, (W - 40), 0, 40, 40, hdcSource, 0, 0, SRCCOPY);

                        HBITMAP                 bmpWindowBottomLeft = (HBITMAP)LoadImage(nullptr,
                            L"window_bottom_left_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowBottomLeft);
                        BitBlt(hdcDest, 0, (H - 40), 40, 40, hdcSource, 0, 0, SRCCOPY);

                        HBITMAP                 bmpWindowBottomRight = (HBITMAP)LoadImage(nullptr,
                            L"window_bottom_right_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowBottomRight);
                        BitBlt(hdcDest, (W - 40), (H - 40), 40, 40, hdcSource, 0, 0, SRCCOPY);

                        HBITMAP                 bmpWindowBottomCenter = (HBITMAP)LoadImage(nullptr,
                            L"window_bottom_center_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowBottomCenter);
                        StretchBlt(hdcDest, (W/2)-20, (H - 40), 40, 40, hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowLeftCenter = (HBITMAP)LoadImage(nullptr,
                            L"window_left_center_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowLeftCenter);
                        StretchBlt(hdcDest, 0, (H/2)-20, 40, 40 , hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowRightCenter = (HBITMAP)LoadImage(nullptr,
                            L"window_right_center_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowRightCenter);
                        StretchBlt(hdcDest, W-40, (H/2)-20, 40, 40, hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowCenter = (HBITMAP)LoadImage(nullptr,
                            L"window_center_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowCenter);
                        StretchBlt(hdcDest, (W/2)-20, (H/2)-20, 40, 40, hdcSource, 0, 0, 40, 40, SRCCOPY);

                        HBITMAP                 bmpWindowFloating001 = (HBITMAP)LoadImage(nullptr,
                            L"window_title.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        SelectObject(hdcSource, bmpWindowFloating001);
                        BitBlt(hdcDest, 10, 10, 10, 10, hdcSource, 0, 0, SRCCOPY);

                        EndPaint(MAIN_WINDOW, &ps); // End paint

                        DeleteDC(hdcDest);
                        DeleteDC(hdcSource);                        // Delete a Memory Device Context
                        DeleteObject(bmpWindow_Full_Background);
                        DeleteObject(bmpWindowTopBackPanel);
                        DeleteObject(bmpWindowTopCenter);
                        DeleteObject(bmpWindowTopLeft);
                        DeleteObject(bmpWindowTopRight);
                        DeleteObject(bmpWindowBottomLeft);
                        DeleteObject(bmpWindowBottomRight);
                        DeleteObject(bmpWindowBottomCenter);
                        DeleteObject(bmpWindowLeftCenter);
                        DeleteObject(bmpWindowRightCenter);
                        DeleteObject(bmpWindowCenter);
                        DeleteObject(bmpWindowFloating001);

                        break;
                    }


Thanks. Microsoft was so difficult to understand. I got this to all show up, but I want to do it right.

If I can get these to all work (back buffering stuff, etc.) then I can move forward to making each a thread (maybe) and (more maybes) do some testing (maybe).

Should this be a new question by itself? I do not know.

Thanks.

I have a screen capture of this working. It is at https://www.dropbox.com/h?preview=FullBackground.bmp


Last edited on
Actually it is correct but not double/back buffer. So let's simplify it a bit:
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
struct compatible_dc_type // Simplifies the handling of the compatible dc
{
  HDC m_Hdc;

  compatible_dc_type(const HDC& cur_hdc) : m_Hdc{CreateCompatibleDC(cur_hdc)}
  {
    assert(m_Hdc != NULL);
  }
  virtual ~compatible_dc_type()
  {
    if(m_Hdc != NULL)
      assert(DeleteDC(m_Hdc) != FALSE); // Ensures that there are no memory leaks!
  }
};

struct bitmap_dc_type : compatible_dc_type  // Simplifies the handling of the bitmaps
{
  HBITMAP m_OrgHbitmap;

  bitmap_dc_type(const HDC& cur_hdc, const HBITMAP& hbm) : compatible_dc_type{cur_hdc}
  {
    m_OrgHbitmap = SelectObject(m_Hdc, hbm);
  }
  bitmap_dc_type(const HBITMAP& hbm) : bitmap_dc_type{NULL, hbm}
  {
  }
  virtual ~bitmap_dc_type()
  {
    SelectObject(m_Hdc, m_OrgHbitmap);  // Ensures that that input bitmap remains valid!
  }
};

struct game_type
{
                        HBITMAP                 m_Hbitmap = NULL; // This is the double/back buffer which is used in WM_PAINT
                        HBITMAP                 bmpWindow_Full_Background = (HBITMAP)LoadImage(nullptr,
                            L"Window_Full_Background_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
                        HBITMAP                 bmpWindowTopBackPanel = (HBITMAP)LoadImage(nullptr,
                            L"window_top_center_BACK_PANEL_40_40.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
...

  game_type()
  {
    // Note you shall check bmpWindow_Full_Background etc. for success!
    // assuming that the bitmap has fixed sizes!
    HDC hdc = GetDC(NULL);
    assert(hdc != NULL);
    m_Hbitmap = CreateCompatibleBitmap(hdc, ThisFormsWIDTH, ThisFormsHEIGHT);
    ReleaseDC(NULL, hdc);
    bitmap_dc_type bitmap_dc{hdc, m_Hbitmap};

    // This can be done anywhere, including other threads. Note that you have to protect m_Hbitmap (back buffer) against simultaneous accesses.
    bitmap_dc_type bitmap_dc_1{bmpWindow_Full_Background};
    StretchBlt(bitmap_dc.m_Hdc, 0, 0, W, H, bitmap_dc_1.m_Hdc, 0, 0, 100, 100, SRCCOPY);

    bitmap_dc_type bitmap_dc_2{bmpWindowTopBackPanel};
    StretchBlt(bitmap_dc.m_Hdc, 0, 0, W, 18, bitmap_dc_2.m_Hdc, 0, 0, 40, 40, SRCCOPY);
...
  }

  ~game_type()
  {
     DeleteObject(bmpWindowTopBackPanel);
     DeleteObject(bmpWindow_Full_Background);
     DeleteObject(m_Hbitmap);
  }

  static game_type get_instance() // This is a singleton!
  {
    static game_type result;
    return result;
  }

};

                    case WM_PAINT:
                    {
                        HDC hdcDest = BeginPaint(MAIN_WINDOW, &ps);             // Begin paint

                        bitmap_dc_type bitmap_dc{hdcDest, game_type::get_instance().m_Hbitmap};

                        const RECT& r = ps.rcPaint;
                        BitBlt(hdcDest, r.left, r.top, r.right - r.left, r.bottom - r.top, bitmap_dc.m_Hdc, r.left, r.top, SRCCOPY); // This will copy only the invaild part of the back buffer

                        EndPaint(MAIN_WINDOW, &ps); // End paint

                        DeleteDC(hdcDest);

                        break;
                    }
Last edited on
coder777 Thanks !

I WILL learn C++! It will happen.


I am going to walk though a part of this and *please* explain where I am wrong.


I looked your code up in 5 big C++ books, and I looked on microsoft's page. Some information, and a lot of blanks in explaination.

bitmap_dc_type bitmap_dc{hdcDest, game_type::get_instance().m_Hbitmap};

I think that means that a variable bitmap_dc of type bitmap_dc_type is created; and bitmap_dc_type in itself is a type of compatible_dc_type.

The compatible_dc_type, which is sub-typed(?) bitmap_dc_type, which has the variable name bitmap_dc is sent information in two parts to work with.

I was wondering why you defined a type and then defined a sub type to that. I think that maybe the goal is so that what is done in the sub type is internal to it and deleted or cleaned up before returning some value to the compatible_dc_type. Or am I reading too much into this and it is just that compatible_dc_type can have lots of sub types and this is just one of them?

The first part is hdcDest which is the "handle" of the "device context" of the "destination" window(?). Is this the "display DC" meaning the monitor that I am looking at or is this where I am working with a back buffer? I am guessing that this hdcDest can be any device context that has a handle as long as that handle already exists?

The second part is game_type::get_instance().m_Hbitmap. I am would like to know if I understand this part in detail.

You say in game_type()

1
2
3
4
5
    HDC hdc = GetDC(NULL);
    assert(hdc != NULL);
    m_Hbitmap = CreateCompatibleBitmap(hdc, ThisFormsWIDTH, ThisFormsHEIGHT);
    ReleaseDC(NULL, hdc);
    bitmap_dc_type bitmap_dc{hdc, m_Hbitmap};


(I think maybe):

You create a variable hdc of type HDC and when you are defining it you use GetDC and do not get the DC of anything (because this is just the defining of "hdc") thus GetDC(NULL).

Then you use the word assert which tells the compiler that "if the following is not correct then end the compile and quit the run)" or something like that, just for compiling stuff and this is to be overridden later when the final executable is made.

assert(hdc !=NULL) I think might mean that if the hdc is "not equal to" not even nothing, beyond that to NULL, then go on with the compiling of the program.

ReleaseDC(NULL, hdc); I think might mean that the hdc has been used, now do a clean-up and release the device context to which the hdc is a handle. Thus it is gone. It no longer exits? It is erased from memory?

Now for the tough part. Here I am having difficulties beyond those previous.

bitmap_dc_type bitmap_dc{hdc, m_Hbitmap}; Looks like you got rid of the hdc in the previous sentence. How is it that you are now using it? You seem to be sending the hdc that no longer exists along with the m_Hbitmap to do something.

Please explain. I want to know and the books and other references seem to say just go with it. I can't accept their just go with it logic. I have to know.


coder777 Thanks !

Thanks so much for your help.

.

and bitmap_dc_type in itself is a type of compatible_dc_type.
No, bitmap_dc_type is derived from compatible_dc_type. See this:

http://www.cplusplus.com/doc/tutorial/polymorphism/

compatible_dc_type created/destroys a memory dc.
bitmap_dc_type additionally selects a hbitmap to the created memory dc. Then the m_Hdc can be used in drawing functions like StretchBlt(....).

GetDC(NULL) get the device context of the entire window. The memory bitmap is created according to the settings of this bittmap (number of colors).

assert(hdc !=NULL) I think might mean that if the hdc is "not equal to" not even nothing, beyond that to NULL, then go on with the compiling of the program.
It means that the return value of NULL is illegal and the program ends. This happens only in the debug version.

It no longer exits? It is erased from memory?
It still exist. It just means that the dc is now not longer locked for this use.

bitmap_dc_type bitmap_dc{hdc, m_Hbitmap}; Looks like you got rid of the hdc in the previous sentence. How is it that you are now using it? You seem to be sending the hdc that no longer exists along with the m_Hbitmap to do something.
It is wrong and should be bitmap_dc_type bitmap_dc{m_Hbitmap};.
When passing the hdc the memory dc is created compatible to this hdc. But it is not necessary.
Thank you coder777.

case WM_PAINT:
I think that I understand that.

HDC hdcDest = BeginPaint(MAIN_WINDOW, &ps); // Begin paint
I think that I understand that. Using the address of & the paint structure ps, which is set up and defined as to colors etc. in the MAIN_WINDOW, begin [re]painting a window (in this case the window that has the handle corresponding to the hdcDest which is of type HDC).

Now we know what paint structure to use and what window handle to work with.

bitmap_dc_type bitmap_dc{hdcDest, game_type::get_instance().m_Hbitmap};
Using game_type, get the instance of m_Hbitmap. In doing that, I guess that saying static made that a singleton.

But, it references the procedure struct game_type therefore, maybe each time that game_type::get_instance() is used it makes a new singleton get_instance. Is that correct or not? I want to know if I understand this.

const RECT& r = ps.rcPaint;
I guess that this is just defining (or declaring?) r as a RECT address & ; RECT& (struggling to follow that). I thought that & meant "address of". But, here is RECT&, does that read "rectangle address of". I did not find it explained via a google search. Is that RECT& r together like const x or const y or const RECT& r being similar? Meaning that RECT& r is maybe together a constant? But, there is a space between them and what does that mean?

BitBlt(hdcDest, r.left, r.top, r.right - r.left, r.bottom - r.top, bitmap_dc.m_Hdc, r.left, r.top, SRCCOPY); // This will copy only the invaild part of the back buffer
I think that I get that. blitting to the handle of the destination device context, while setting up the placement and size of the blit, and doing a source copy on top and replacing what was there before. I think that might be correct.

Backing up a little:
bitmap_dc.m_Hdc
I think that is the back buffer maybe?

But your comment
// This will copy only the invalid part of the back buffer
I do not quite understand. the invalid part, would that be the invisible part? And that would simply make an invisible blit? This is getting difficult again. Help!


Some more:
HBITMAP m_Hbitmap = NULL; // This is the double/back buffer which is used in WM_PAINT
Got that. Wow! Thank you coder777 for comments in the code.

You define m_Hbitmap in that line.

Then, later in game_type() you do something with it.
1
2
3
    HDC hdc = GetDC(NULL);
    assert(hdc != NULL);
    m_Hbitmap = CreateCompatibleBitmap(hdc, ThisFormsWIDTH, ThisFormsHEIGHT);

You create a compatible bitmap *in memory?*, with specific dimensions set up previously somewhere else, and you "assert" that it can not be NULL. This assert only works in the compiler, and does not have any effect on the final compiled program? Like an error checker that stops the compile and thus forces an error situation to be fixed? I think that I got that part maybe.

You use hdc which you defined (created?) with HDC hdc = GetDC(NULL);. Does that mean that with HDC hdc = GetDC(NULL); you are making something strictly in memory, because it is the device context of nothing NULL? Maybe?

You use the previously defined m_Hbitmap,

Then you get rid of it ReleaseDC(NULL, hdc);.
If you got rid of the DC or hdc, then you still have m_Hbitmap in memory and you used the hdc just to set it up? I think that I get that. Maybe? It looks like a device "context" is simply like a set of guidelines for a device and the DC actually does not exist except as a set of rules for a device. If that is so, then the Handle of the Device Context seems to be a handle (or reference like a library reference to a book location) to the location in memory of the guidelines that describe the "context" of the "device." Thus, when the m_Hbitmap has been made (created?) then the description and guidelines of how to make it can be deleted. Is that correct?

Then you create a new variable bitmap_dc which you make of type bitmap_dc_type, and you use the *purely in memory* m_Hbitmap as kind of like a guideline??? [I am lost here]. Help! Please explain this.

Are you creating something new with bitmap_dc_type bitmap_dc{m_Hbitmap};? I think so.

What does the "{...}"part, putting the previously worked on and adjusted m_Hbitmap into curly brackets with a variable bitmap_dc in front of it do? This is probably obvious, but I am having difficulty with this one line. Not in general as to the use of the curly brackets, but specifically this one line. What exactly, in baby level beginner explaining, does this one line do?

Then:

Hopefully I understand this part:
1
2
3
4
5
6
    // This can be done anywhere, including other threads. Note that you have to protect m_Hbitmap (back buffer) against simultaneous accesses.
    bitmap_dc_type bitmap_dc_1{bmpWindow_Full_Background};
    StretchBlt(bitmap_dc.m_Hdc, 0, 0, W, H, bitmap_dc_1.m_Hdc, 0, 0, 100, 100, SRCCOPY);

    bitmap_dc_type bitmap_dc_2{bmpWindowTopBackPanel};
    StretchBlt(bitmap_dc.m_Hdc, 0, 0, W, 18, bitmap_dc_2.m_Hdc, 0, 0, 40, 40, SRCCOPY);

Is this where all of the bitmaps are added to a "back buffer" bitmap_dc? It looks like that to me.

Then, that is what is used here BitBlt(hdcDest, r.left, r.top, r.right - r.left, r.bottom - r.top, bitmap_dc.m_Hdc, r.left, r.top, SRCCOPY); inside of the case WM_PAINT:.

I think that I get it. Maybe?

If I understand this, then I can change the bitmap_dc.m_Hdc anytime that I want.

What happens to the previously painted BitBlt(hdcDest, r.left, ...? If I change the bitmaps that are in the back buffer, and move the stuff to somewhere else on the window, does the entire window get replaced as soon as the screen refresh next is done?

Is there any other "cleanup" or "garbage collection" or such that should be done? This looks like clean code with automatic cleanup built in.

And, if I move the main windows around to different locations on the monitor screen, is this automatically taken care of by the Windows operating system or do I need to work on that? I think that the operating system takes care of it. Is that correct?


Please check line by line and tell me if my logic is incorrect.


Thank you coder777.
Last edited on
I don't know what MAIN_WINDOW actually is. Normally you use the handle of the window provided with the WM_PAINT message. See:

https://docs.microsoft.com/en-us/windows/win32/gdi/wm-paint

maybe each time that game_type::get_instance() is used it makes a new singleton get_instance. Is that correct or not?
No, it's not correct. The singleton is created once (when get_instance() is called for the first time) and the instance is used.

For assert see:

http://www.cplusplus.com/reference/cassert/assert/?kw=assert


For HDC hdc = GetDC(NULL) (particular what's the meaning of NULL) see:

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc

you still have m_Hbitmap in memory and you used the hdc just to set it up?
Yes.

then the description and guidelines of how to make it can be deleted. Is that correct?
Kind of. The graphic card is a resource that is shared with other programs. You need to lock (with get/release) this resource in order to use it.

and you use the *purely in memory* m_Hbitmap as kind of like a guideline??? [I am lost here]. Help! Please explain this.
The m_Hbitmap actually is a kind of pointer to a special formatted chunk of memory that can be copied to the screen using bitblt(...)

Are you creating something new with bitmap_dc_type bitmap_dc{m_Hbitmap};? I think so.
The bitmap is wrapped by a device context because the drawing functions like StretchBlt(...) need it.

What does the "{...}"part, putting the previously worked on and adjusted m_Hbitmap into curly brackets with a variable bitmap_dc in front of it do?
That's just one way to call the constructor for the object bitmap_dc.

Is this where all of the bitmaps are added to a "back buffer" bitmap_dc? It looks like that to me.
Yes.
I think that I get it. Maybe?
Yes.
If I change the bitmaps that are in the back buffer, and move the stuff to somewhere else on the window, does the entire window get replaced as soon as the screen refresh next is done?
Yes, but you need to initiate the refresh with InvalidateRect(...). See:

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidaterect

Is there any other "cleanup" or "garbage collection" or such that should be done? This looks like clean code with automatic cleanup built in.

And, if I move the main windows around to different locations on the monitor screen, is this automatically taken care of by the Windows operating system or do I need to work on that? I think that the operating system takes care of it. Is that correct?
I'm not sure whether I get this. There is no automatic involved.
Topic archived. No new replies allowed.