Click here to Skip to main content
15,867,488 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am attempting to implement an image viewer in a Console Application. The viewer will be ported to a Raspberry Pi and executed using Mono replacing the debian-installed feh image viewer. I am replacing feh because that program uses a fixed number of seconds to delay before advancing the image. For a slideshow, variable delays are required, dependent on the content density of each slide. I have successfully implemented what I thought would be the hard part (parsing the arguments to obtain a file list and timing for each file). But I am stuck on what I thought would be the easy part - displaying the images. The following code does not work.
C#
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace debug
    {
    
    // ************************************************* class Program
    
    class Program
        {

        List  < string > file_list = new List < string > ( )
            {
            { @"Slide1.PNG" },
            { @"Slide2.PNG" } };
            
        // *********************************************** show_images
        
        void show_images ( )
            {
            Screen  screen = ( Screen.AllScreens.Length > 1 ) ? 
                                      Screen.AllScreens [ 1 ] : 
                                      Screen.PrimaryScreen;

            using ( Form form = new Form ( ) )
                {
                form.ControlBox = false;
                form.FormBorderStyle = FormBorderStyle.None;
                form.BackColor = Color.Azure;//Black;
                form.Location = new Point ( screen.Bounds.Left, 
                                            screen.Bounds.Top );
                form.Size = screen.Bounds.Size;
                form.Visible = true;
                form.Show ( );
                form.DoubleBuffered ( true );
                foreach ( string filename in file_list )
                    {
                    string          image_path = String.Empty;
                    StringBuilder   sb = new StringBuilder ( );

                    sb.AppendFormat ( 
                                @"{0}\{1}", 
                                Directory.GetCurrentDirectory ( ), 
                                filename );
                    image_path = sb.ToString ( );
                    if ( File.Exists ( image_path ) )
                        {
                        using ( PictureBox picture_box = 
                                           new PictureBox ( ) )
                            {
                            picture_box.BackColor = Color.Black;
                            picture_box.BorderStyle = 
                                BorderStyle.None;
                            picture_box.Dock = DockStyle.Fill;
                            picture_box.ImageLocation = image_path;
                            picture_box.SizeMode = 
                                PictureBoxSizeMode.Zoom;
                            picture_box.Visible = true;

                            form.Controls.Add ( picture_box );
                            
                            Thread.Sleep ( 2000 );
                            picture_box.Visible = false;
                            } // using picture_box
                        }
                    }
                } // using form
            
            } // show_images

        // ****************************************************** main
        
        void main ( string [ ] args )
            {

            show_images ( );
            
            } // main

        // ****************************************************** Main
        
        static void Main ( string [ ] args )
            {
            Program  p = new Program ( );
            
            p.main ( args );
            
            } // Main
            
        } // class Program
        
    // ********************************************** class Extensions
    
    public static class Extensions
        {
        
        // *******************************************  DoubleBuffered
        
        public static void DoubleBuffered ( this Control control, 
                                                 bool    enabled )
            {
            PropertyInfo  property_info;
            
            property_info = control.GetType ( ).
                                    GetProperty ( 
                                        "DoubleBuffered", 
                                        ( BindingFlags.Instance | 
                                          BindingFlags.NonPublic ) );
            property_info.SetValue ( control, enabled, null );
            
            } // DoubleBuffered
            
        } // class Extensions
        
    } // namespace debug

When executed, the program displays a full screen form with a background of Azure. But the picture box, that is intended to display each image, does not appear.

What I have tried:

Numerous Google searches and the preceding code.
Posted
Updated 21-Oct-21 19:46pm
Comments
PIEBALDconsult 21-Oct-21 17:31pm    
Look into ASCII art?
gggustafson 21-Oct-21 17:35pm    
It's a real problem!
[no name] 21-Oct-21 18:05pm    
Try displaying some text in the Form first; there's too much else going on for a first run. And, no, displaying images is not always "easy".

Since you don't see "black" (your background), perhaps you have a picture box size issue. (it's collapsed)
gggustafson 21-Oct-21 22:26pm    
As I stated in the Question "When executed, the program displays a full screen form with a background of Azure. But the picture box, that is intended to display each image, does not appear." There are no error messages.
gggustafson 21-Oct-21 23:22pm    
Wish I could plead that with regard the question

You can't "run" a Form without a message loop/pump. To get one, you need to call Application.Run()

Without a pump the Form will be dead, no events will occur, the PB will not show anything.

But then, with a pump, your Console App basically got turned into a WinForms app.

The work-around is to not rely on events, and orchestrate everything explicitly; this is the most compact piece of code that does so IMO:

using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleApplication1 {
	class Program {
		static void Main(string[] args) {
			Screen screen = Screen.PrimaryScreen;
			using (Form form = new Form()) {
				form.FormBorderStyle = FormBorderStyle.None;
				form.Bounds = screen.Bounds;
				PictureBox pb=new PictureBox();
				pb.Dock=DockStyle.Fill;
                pb.SizeMode=PictureBoxSizeMode.StretchImage;
				form.Controls.Add(pb);
				form.Show();
				string[] imageFiles = Directory.GetFiles("images", "*.jpg");
				while (true) {
					foreach (string imageFile in imageFiles) {
						pb.Load(imageFile);
						form.Refresh();
						Thread.Sleep(2000);
					}
				}
			}
		}

	}
}


Note doublebuffering was not used, I see no point to use it.
 
Share this answer
 
v6
Comments
Luc Pattyn 22-Oct-21 12:53pm    
Hi Bill, not sure what you are referring to. I did test my code before I published it, it worked satisfactorily (except maybe that terminating it is a bit hard). And in the mean time the OP accepted the solution.

The problem is that you forgot to add the picture box control to the form. I modified the code to work correctly. It's been tested and it works. The lines I added have the comment "Added" to it.

if (File.Exists(image_path))
          {
              using (PictureBox picture_box =
                                 new PictureBox())
              {
                  form.Controls.Add(picture_box); //Added

                  picture_box.BackColor = Color.Black;
                  picture_box.BorderStyle =
                      BorderStyle.None;
                  picture_box.Dock = DockStyle.Fill;
                  picture_box.ImageLocation = image_path;
                  picture_box.SizeMode =
                      PictureBoxSizeMode.Zoom;
                  picture_box.Visible = true;

                  picture_box.Load(); //Added
                  picture_box.Refresh(); //Added
                  form.Refresh(); //Added

                  Thread.Sleep(2000);
                  picture_box.Visible = false;
              } // using picture_box
          }
 
Share this answer
 
Comments
gggustafson 21-Oct-21 22:33pm    
Your solution worked. I guess the old say about being to close to see the problem is true.

Thank you.
Luc Pattyn 21-Oct-21 23:10pm    
Actually a lot of PB get created and disposed of, however they all get added to the Form.Controls collection which doesn't look quite right (although there is some built-in mechanism that might remove them on dispose, can't remember tthe details as I don't ever write code in that way).

What could be the reason to use different PB all the time??
gggustafson 21-Oct-21 23:24pm    
There is only one PB and it is deleted at the end of the using block and recreated at the start. Please supply your solution
Luc Pattyn 21-Oct-21 23:33pm    
Yes I did; I also added a comment to the OP.
Luc Pattyn 22-Oct-21 1:37am    
Yes every PB will be disposed of, however they also have been added to the Form.Controls collection (and never removed), so I expect them to be alive and invalid, i.e. all but the most recent one which hasn't been disposed of yet.

However, the problem lies elsewhere. I'm still working on it and will report to the OP when ready.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900