Bitmaps don't always draw visibly

JonJacobs

Active member
Joined
Jul 28, 2022
Messages
35
Programming Experience
10+
In my continuing effort to bring over apps I used all the time on my wn 8.1 machine I ran into this problem.
I'm trying to reproduce in C#/winforms an app I wrote long ago in Delphi. It wasn't hard back then, but I have problems getting it to work properly a windows form under .Net.
The problem is that The image simply does not appear about 15% of the time. Any attempt to draw the same image at the same place gets the same result. Here is the basic method:
C#:
 private void DrawCard(string cardno, int x, int y)
        {
            string pattern = "card_" + cardno + "_*.bmp";
            string[] files = Directory.GetFiles(pth, pattern);
            if (files.Length < 1) return;//exactly 1 file fits the pattern
            string FQFN = files[0];
            Point p = new Point(x, y);
            Bitmap bmp = (Bitmap)Bitmap.FromFile(FQFN);
            int h = bmp.Height;
            int w = bmp.Width;

            int h2 = h / 2;
            int w2 = w / 2;

            Rectangle r = new Rectangle(x, y, w2, h2);

            g.DrawImage(bmp, r);
        }

In Form_Load I have: g = CreateGraphics();

If I draw on the form or on a PictureBox, the result is the same. If I draw on command from a menu choice or in an OnPaint event handler, the result is the same.

How can I get the images (cards) to draw visibly reliably?
Thanks - Jon
 
By hooking into the paint event.
 
By hooking into the paint event.

Thank you. Not sure what you mean by "hooking." The drawing code is called from the Paint event handler. A menu command executes the form Invalidate() and the images appear, usually with 1-3 images not visible out of 13.
 
If you are painting on the paint event, use the graphics object that was passed to you. You don't have to create your own graphics object on form load event.

Hooking used to be the old Win3x term for listening to windows messages and/or overriding the windows procedure of another control to listen to its events. Nowadays, most people associate hooking with just listening to the global windows messages to implement hotkeys, keyloggers, or mouse hotspots.
 
NEVER call CreateGraphics. As suggested, handle the Paint event of the form (or whatever control you want to draw on) and use e.Graphics.

The way WinForms works, controls are repeatedly erased and repainted. If you just draw on a control once, that drawing will almost certainly be erased at some point. Every time this erase and repaint cycle occurs, a Paint event is raised. You do your drawing in the Paint event handler and it will be repainted every time. If you want to change the drawing, you change the data used by your drawing code and force a Paint event - that might be an Image object in your case - which will erase the old drawing and paint the new.
 
If you are painting on the paint event, use the graphics object that was passed to you. You don't have to create your own graphics object on form load event.

Hooking used to be the old Win3x term for listening to windows messages and/or overriding the windows procedure of another control to listen to its events. Nowadays, most people associate hooking with just listening to the global windows messages to implement hotkeys, keyloggers, or mouse hotspots.

Thank you. I get it now.
 
NEVER call CreateGraphics. As suggested, handle the Paint event of the form (or whatever control you want to draw on) and use e.Graphics.

The way WinForms works, controls are repeatedly erased and repainted. If you just draw on a control once, that drawing will almost certainly be erased at some point. Every time this erase and repaint cycle occurs, a Paint event is raised. You do your drawing in the Paint event handler and it will be repainted every time. If you want to change the drawing, you change the data used by your drawing code and force a Paint event - that might be an Image object in your case - which will erase the old drawing and paint the new.

Yeah, it's coming back to me. I'll need to restructure my code, but I believe you're right: I need to redraw everything every time as images accumulate using the e.Graphics. Thanks.
 
And this is part of the reason why some people use PictureBoxes and Panels. They just set the image in those controls and the let the controls take care of repainting the images when asked by Windows to repaint. Depending on what you are doing and what your objectives are this might be very expensive/slow overhead, or it might be the perfect tool for the job. Need a high performance game with relatively fast frame rates, do your own painting or better yet, using DirectX or DirectDraw instead of GDI. Just need to render relatively static cards or tiles, just use PictureBoxes. On the other hand, there is also the number images and the limits of number of GDI objects you can have. You could possibly make Space Invaders work with just PictureBoxes, but trying to do Scrabble would still work, but is probably pushing things.
 

Latest posts

Back
Top Bottom