Link to home
Start Free TrialLog in
Avatar of derekthornton
derekthornton

asked on

Open With ...

I've written a handy little Image Viewing application, but I'm confused as to how I can make it be opened from Windows. For instance, when the user double clicks an image file, it will open my program AND load the image file. I can understand how to make WINDOWS open it up, but how can I make it pass the Image clicked on through a constructor to load it?
ASKER CERTIFIED SOLUTION
Avatar of Timbo87
Timbo87

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Timbo87
Timbo87

If you need any help with this, please ask.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of derekthornton

ASKER

But what if I want to have a constructor that loads the images 'IF' they opened it from an image? They might just open it normally, and in that case I don't want anything to be loaded.
Using my example above, in the Form_Load event you could add code like this:

if(filePath != null)
      // Construct object

That way if they launch the program normally without double-clicking a file, filePath will be null and the program will execute normally.
I've tried your code verbatim except I put the Image Loading method in the Load_Event and it doesn't work. Is there anything I may be missing?
Can you post your Form_Load event handler code?
Will it work to test it by compiling a Debug Project and going to an image, right clicking and using "Open With ..." and chosing the debug .exe file of my program to do it?
           private void PictureViewer_Load(object sender, System.EventArgs e)
            {
                  if(filePath != null)
                        OpenPictures(filePath);
            }

            private void OpenPictures(String File)
            {
                  Images.ImagesList.Add(Image.FromFile(File));
                  pbPlus.Image = Images.CurrentImage;
                  ImageSizeMode = SizeMode.Isotropic;
                  Invalidate();
            }
The form load code looks good. Yes, you can test it with the way you described.
Ok.Well. It still doesn't work.
What error are you getting?
No error. Just ..nothing happens.
Is this when you double-click a file associated with it or when you launch the program?
I go to a picture file, right click it, choose "Open With" find the Debug executable for my program, and select it, and the program opens up and nothing happens.
Did you add the mentioned code to the Main method? Also, as a debug measure, add this line as the first thing in your Form_Load event handler:

MessageBox.Show(filePath);

Try running the application normally and see what it says, then try opening a file and see what it says.
Done both  and it doesn't help.
           private void OpenPictures(String args)
            {
                  Images.ImagesList.Add(Image.FromFile(args));
                  pbPlus.Image = Images.CurrentImage;
                  ImageSizeMode = SizeMode.Isotropic;
                  Invalidate();
            }

            private void PictureViewer_Load(object sender, System.EventArgs e)
            {
                  if(filePath != null)
                        MessageBox.Show(filePath);
            }

            [STAThread]
            public static void Main(string[] args)
            {
                  if(args.Length > 0)
                        filePath = args[0];
                  Application.Run(new PictureViewer());
            }
No, I mean put the MessageBox above the rest of the code.

          private void PictureViewer_Load(object sender, System.EventArgs e)
          {
               MessageBox.Show(filePath);
          }
What do you mean?
Make the message box the first line of code in the Form_Load event handler. Do not enclose it in an if statement.
I do, and still nothing happens.
You should at least be getting an empty message box.
Not even an empty message box.
Sorry this is taking so long. Can you please paste your Form_Load again? Also make sure that you declared
private static string filePath; at the top of your class. I put together a dummy test program before I posted the original code and it all worked so I know this method works.
namespace PictureViewer
{
      using System;
      using System.Drawing;
      using System.Windows.Forms;
      using DevComponents.DotNetBar;

      public enum SizeMode
      {
            Isotropic,
            Scrollable
      }

      public sealed class PictureViewer : Form
      {
            #region -- Instance Fields --            

            private System.ComponentModel.IContainer components;
            private ImageArray Images;
            private PictureBoxPlus.PictureBoxPlus pbPlus;
            private DevComponents.DotNetBar.DockSite barTopDockSite;
            private DevComponents.DotNetBar.DockSite barBottomDockSite;
            private DevComponents.DotNetBar.DockSite barLeftDockSite;
            private DevComponents.DotNetBar.DockSite barRightDockSite;
            private DevComponents.DotNetBar.DotNetBarManager dnbMenu;
            private System.Windows.Forms.Panel panel1;
            private SizeMode sizeMode;
            private static string filePath;
            #endregion
            #region -- Constructor and Destructor --
            public PictureViewer()
            {                  
                  // Required Windows Form Designer
                  InitializeComponent();
                  // Create the Images Array
                  Images = new ImageArray();
                  // ResizeRedraw
                  ResizeRedraw = true;
            }
            #endregion
            #region -- Loading Point --
            [STAThread]
            public static void Main(string[] args)
            {
                  if(args.Length > 0)
                        filePath = args[0];
                  Application.Run(new PictureViewer());
            }
            #endregion
            #region -- Windows Form Designer --            
            private void InitializeComponent()
            {
                  this.components = new System.ComponentModel.Container();
                  this.pbPlus = new PictureBoxPlus.PictureBoxPlus();
                  this.barTopDockSite = new DevComponents.DotNetBar.DockSite();
                  this.barBottomDockSite = new DevComponents.DotNetBar.DockSite();
                  this.barLeftDockSite = new DevComponents.DotNetBar.DockSite();
                  this.barRightDockSite = new DevComponents.DotNetBar.DockSite();
                  this.dnbMenu = new DevComponents.DotNetBar.DotNetBarManager(this.components);
                  this.panel1 = new System.Windows.Forms.Panel();
                  this.panel1.SuspendLayout();
                  this.SuspendLayout();
                  //
                  // pbPlus
                  //
                  this.pbPlus.Isotropic = true;
                  this.pbPlus.Location = new System.Drawing.Point(8, 8);
                  this.pbPlus.Name = "pbPlus";
                  this.pbPlus.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
                  this.pbPlus.TabIndex = 6;
                  this.pbPlus.TabStop = false;
                  //
                  // barTopDockSite
                  //
                  this.barTopDockSite.AccessibleRole = System.Windows.Forms.AccessibleRole.Window;
                  this.barTopDockSite.BackgroundImageAlpha = ((System.Byte)(255));
                  this.barTopDockSite.Dock = System.Windows.Forms.DockStyle.Top;
                  this.barTopDockSite.Location = new System.Drawing.Point(0, 0);
                  this.barTopDockSite.Name = "barTopDockSite";
                  this.barTopDockSite.Size = new System.Drawing.Size(496, 27);
                  this.barTopDockSite.TabIndex = 2;
                  this.barTopDockSite.TabStop = false;
                  //
                  // barBottomDockSite
                  //
                  this.barBottomDockSite.AccessibleRole = System.Windows.Forms.AccessibleRole.Window;
                  this.barBottomDockSite.BackgroundImageAlpha = ((System.Byte)(255));
                  this.barBottomDockSite.Dock = System.Windows.Forms.DockStyle.Bottom;
                  this.barBottomDockSite.Location = new System.Drawing.Point(0, 366);
                  this.barBottomDockSite.Name = "barBottomDockSite";
                  this.barBottomDockSite.Size = new System.Drawing.Size(496, 0);
                  this.barBottomDockSite.TabIndex = 3;
                  this.barBottomDockSite.TabStop = false;
                  //
                  // barLeftDockSite
                  //
                  this.barLeftDockSite.AccessibleRole = System.Windows.Forms.AccessibleRole.Window;
                  this.barLeftDockSite.BackgroundImageAlpha = ((System.Byte)(255));
                  this.barLeftDockSite.Dock = System.Windows.Forms.DockStyle.Left;
                  this.barLeftDockSite.Location = new System.Drawing.Point(0, 27);
                  this.barLeftDockSite.Name = "barLeftDockSite";
                  this.barLeftDockSite.Size = new System.Drawing.Size(0, 339);
                  this.barLeftDockSite.TabIndex = 0;
                  this.barLeftDockSite.TabStop = false;
                  //
                  // barRightDockSite
                  //
                  this.barRightDockSite.AccessibleRole = System.Windows.Forms.AccessibleRole.Window;
                  this.barRightDockSite.BackgroundImageAlpha = ((System.Byte)(255));
                  this.barRightDockSite.Dock = System.Windows.Forms.DockStyle.Right;
                  this.barRightDockSite.Location = new System.Drawing.Point(496, 27);
                  this.barRightDockSite.Name = "barRightDockSite";
                  this.barRightDockSite.Size = new System.Drawing.Size(0, 339);
                  this.barRightDockSite.TabIndex = 1;
                  this.barRightDockSite.TabStop = false;
                  //
                  // dnbMenu
                  //
                  this.dnbMenu.AllowUserBarCustomize = false;
                  this.dnbMenu.AlwaysShowFullMenus = true;
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.F1);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlC);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlA);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlV);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlX);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlZ);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.Del);
                  this.dnbMenu.AutoDispatchShortcuts.Add(DevComponents.DotNetBar.eShortcut.Ins);
                  this.dnbMenu.BottomDockSite = this.barBottomDockSite;
                  this.dnbMenu.DefinitionName = "PictureViewer.dnbMenu.xml";
                  this.dnbMenu.LeftDockSite = this.barLeftDockSite;
                  this.dnbMenu.MdiSystemItemVisible = false;
                  this.dnbMenu.ParentForm = this;
                  this.dnbMenu.RightDockSite = this.barRightDockSite;
                  this.dnbMenu.Style = DevComponents.DotNetBar.eDotNetBarStyle.Office2003;
                  this.dnbMenu.TopDockSite = this.barTopDockSite;
                  this.dnbMenu.UseHook = true;
                  this.dnbMenu.ItemClick += new System.EventHandler(this.dnbMenu_ItemClick);
                  //
                  // panel1
                  //
                  this.panel1.BackColor = System.Drawing.SystemColors.ActiveCaption;
                  this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                  this.panel1.Controls.Add(this.pbPlus);
                  this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
                  this.panel1.Location = new System.Drawing.Point(0, 27);
                  this.panel1.Name = "panel1";
                  this.panel1.Size = new System.Drawing.Size(496, 339);
                  this.panel1.TabIndex = 7;
                  //
                  // PictureViewer
                  //
                  this.AutoScale = false;
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(496, 366);
                  this.Controls.Add(this.panel1);
                  this.Controls.Add(this.barLeftDockSite);
                  this.Controls.Add(this.barRightDockSite);
                  this.Controls.Add(this.barTopDockSite);
                  this.Controls.Add(this.barBottomDockSite);
                  this.Name = "PictureViewer";
                  this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
                  this.Load += new System.EventHandler(this.PictureViewer_Load);
                  this.panel1.ResumeLayout(false);
                  this.ResumeLayout(false);

            }
            #endregion
            #region -- Menu --            
            private void dnbMenu_ItemClick(object sender, System.EventArgs e)
            {
                  BaseItem mnuItemClicked = sender as BaseItem;
                  switch(mnuItemClicked.Name)
                  {
                        case "mnuOpenPicture":
                              OpenPicture();
                              break;
                        case "mnuNEXT":
                              NextPicture();
                              break;
                        case "mnuBACK":
                              LastPicture();
                              break;
                        case "mnuLAYOUT":
                              ToggleItem(mnuItemClicked);
                              SetSizeMode(mnuItemClicked);
                              break;
                  }
            }
            #endregion
            #region -- Open Images --
            private void OpenPicture()
            {
                  OpenFileDialog OpenFile = new OpenFileDialog();
                  OpenFile.Filter = "All Images|*.*";
                  OpenFile.Multiselect = true;
                  if(OpenFile.ShowDialog() == DialogResult.OK)
                  {
                        foreach(string s in OpenFile.FileNames)
                        {
                              Images.ImagesList.Add(Image.FromFile(s));
                        }
                        pbPlus.Image = Images.CurrentImage;
                        ImageSizeMode = SizeMode.Isotropic;
                        Invalidate();
                  }
            }
            private void OpenPictures(String args)
            {
                  Images.ImagesList.Add(Image.FromFile(args));
                  pbPlus.Image = Images.CurrentImage;
                  ImageSizeMode = SizeMode.Isotropic;
                  Invalidate();
            }
            #endregion
            #region -- View Images --
            private void NextPicture()
            {
                  pbPlus.Image = Images.NextImage();
            }
            private void LastPicture()
            {
                  pbPlus.Image = Images.PreviousImage();
            }
            #endregion
            #region -- Image Viewing Methods --
            private void ToggleItem(object sender)
            {
                  // Retrieve the Button Clicked
                  ButtonItem btnObject = sender as ButtonItem;
                  // Swap it's status
                  btnObject.Checked = !btnObject.Checked;

                  if(btnObject.Checked)
                        btnObject.Text = "Isotropic ( Size to Fit )";
                  else if(!btnObject.Checked)
                        btnObject.Text = "Scrollable ( Full Size )";
            }
            private void SetSizeMode(object sender)
            {
                  ButtonItem btnObject = sender as ButtonItem;
                  if(btnObject.Checked)
                        ImageSizeMode = SizeMode.Isotropic;
                  if(!btnObject.Checked)
                        ImageSizeMode = SizeMode.Scrollable;
            }
            #endregion
            #region -- Layout Methods --
            private void SetLayout()
            {
                  switch(sizeMode)
                  {
                        case SizeMode.Isotropic:
                              pbPlus.Isotropic = true;
                              Invalidate();
                              break;
                        case SizeMode.Scrollable:
                              pbPlus.Isotropic = false;
                              Invalidate();
                              CenterImage();
                              break;
                        default:
                              pbPlus.Isotropic = true;
                              break;
                  }
            }
            private void CenterImage()
            {
                  if(pbPlus.Image != null)
                  {
                        pbPlus.Location = new Point(0,0);

                        Int32 iTop =  (Int32)((Height - pbPlus.Image.Height)/2.0);
                        Int32 iLeft = (Int32)((Width - pbPlus.Image.Width)/2.0);

                        switch(iTop.CompareTo(0))
                        {
                              case -1:
                                    iTop = 0;
                                    break;
                        }
                        switch(iLeft.CompareTo(0))
                        {
                              case -1:
                                    iLeft = 0;
                                    break;
                        }
                        pbPlus.Top  = iTop;
                        pbPlus.Left = iLeft;
                  }
            }
            #endregion
            #region -- Formatting Control --
            private void IsotropicScale(Rectangle DrawRectangle)
            {
                  panel1.AutoScroll = false;

                  SizeF sizeRatio =
                        new SizeF(
                        pbPlus.Image.Width / pbPlus.Image.HorizontalResolution,
                        pbPlus.Image.Height / pbPlus.Image.VerticalResolution
                        );

                  float IsotropicRatio =
                        Math.Min(DrawRectangle.Width / sizeRatio.Width,
                        DrawRectangle.Height / sizeRatio.Height);

                  sizeRatio.Width *= IsotropicRatio;
                  sizeRatio.Height *= IsotropicRatio;

                  pbPlus.Location = new Point(
                        (int)((DrawRectangle.X + (DrawRectangle.Width - sizeRatio.Width) /2)),
                        (int)(DrawRectangle.Y +  (DrawRectangle.Height - sizeRatio.Height) / 2) );
                  
                  pbPlus.Width = (int) sizeRatio.Width;
                  pbPlus.Height = (int) sizeRatio.Height;
            }
            private void ScrollableScale()
            {
                  pbPlus.Height = pbPlus.Image.Height;
                  pbPlus.Width = pbPlus.Image.Width;
                  panel1.AutoScroll = true;
            }
            #endregion
            #region -- Paint --
            protected override void OnPaint(PaintEventArgs e)
            {
                  if(pbPlus.Image != null)
                  {
                        if(pbPlus.Isotropic)
                        {
                              IsotropicScale(ClientRectangle);
                        }
                        else if (!pbPlus.Isotropic)
                        {
                              ScrollableScale();
                        }
                  }
                  base.OnPaint (e);
            }
            #endregion

            private void PictureViewer_Load(object sender, System.EventArgs e)
            {
                  //if(filePath != null)
                        MessageBox.Show(filePath);
            }
            #region -- Properties --
            /// <summary>
            /// Gets or sets the associated image
            /// </summary>
            public Image Image
            {
                  get
                  {
                        return this.pbPlus.Image;
                  }
                  set
                  {
                        this.pbPlus.Image = value;
                  }
            }
            /// <summary>
            /// Gets or Sets the Image Size Mode
            /// </summary>
            public SizeMode ImageSizeMode
            {
                  get
                  {
                        return sizeMode;
                  }
                  set
                  {
                        sizeMode = value;
                        SetLayout();
                  }
            }
            #endregion
      }
}

namespace PictureBoxPlus
{
      using System;
      using System.Drawing;
      using System.Windows.Forms;

      public sealed class PictureBoxPlus : PictureBox
      {
            #region -- Instance Fields --
            /// <summary>
            /// Isotropic Evaluator
            /// </summary>
            private Boolean blnIsotropic;
            #endregion
            #region -- Constructor and Destructor --
            /// <summary>
            /// Constructor
            /// </summary>
            public PictureBoxPlus() { }
            /// <summary>
            /// Destructor
            /// </summary>
            ~PictureBoxPlus()
            {
            }
            #endregion
            #region -- Properties --
            #region -- [Properties] Isotropic --
            /// <summary>
            /// Gets or Sets the Isotropic Property of the PictureBox
            /// </summary>
            public Boolean Isotropic
            {
                  get
                  {
                        return blnIsotropic;
                  }
                  set
                  {
                        blnIsotropic = value;
                        Invalidate();
                  }
            }
            #endregion
            #endregion
      }
}

namespace PictureViewer
{
      using System;
      using System.Drawing;
      using System.Windows.Forms;
      using System.Collections;

      public sealed class ImageArray : Control
      {
            #region -- Instance Fields --
            /// <summary>
            /// The Images
            /// </summary>
            private ArrayList arrayListImages;
            /// <summary>
            /// Currently Selected Image
            /// </summary>
            private int CurrentIndex;
            #endregion
            #region -- Constructor, Destructor --
            /// <summary>
            /// Creates an array of images
            /// </summary>
            public ImageArray()
            {
                  // Initialize The Images Array
                  this.arrayListImages = new ArrayList();
            }
            #endregion
            #region -- Image Loading Methods --
            #region -- [ Internal ] --
            /// <summary>
            /// Gets the next image in the list
            /// </summary>
            /// <returns>The Index of the next image</returns>
            private int Next()
            {
                  return Selected += 1;
            }
            /// <summary>
            /// Gets the previous image in the list
            /// </summary>
            /// <returns>The index of the previous image</returns>
            private int Previous()
            {
                  return Selected -= 1;
            }
            #endregion
            #region -- [ External ] --
            /// <summary>
            /// Retrieves the next image
            /// </summary>
            /// <returns>The Next Image, or the first image,
            /// if the current image is the last</returns>
            public Image NextImage()
            {
                  if(Selected < ImagesList.Count - 1)
                        return (Image)ImagesList[Next()];
                  else
                        return (Image)ImagesList[Start()];
            }
            /// <summary>
            /// Retrieves the previous image
            /// </summary>
            /// <returns>The Previous Image, o
            /// r the last image, if the current image is the first</returns>
            public Image PreviousImage()
            {
                  if(Selected > 0)
                        return (Image)ImagesList[Previous()];
                  else
                        return (Image)ImagesList[End()];
            }
            #endregion
            #region -- [ Resets ] --
            private int Start()
            {
                  return (Selected = 0);
            }
            private int End()
            {
                  return (Selected = ImagesList.Count - 1);
            }
            #endregion
            #region -- [ Current Image ] --
            public Image CurrentImage
            {
                  get
                  {
                        return (Image)ImagesList[Selected];
                  }
            }
            #endregion
            #endregion

            #region -- Properties --
            /// <summary>
            /// Gets or Sets the images in the array
            /// </summary>
            public ArrayList ImagesList
            {
                  get
                  {
                        return this.arrayListImages;
                  }
                  set
                  {
                        this.arrayListImages = value;
                  }
            }
            /// <summary>
            /// Gets or Sets the selected image
            /// </summary>
            private int Selected
            {
                  get
                  {
                        return this.CurrentIndex;
                  }
                  set
                  {
                        this.CurrentIndex = value;
                  }
            }
            #endregion
      }
}
Unfortunately I cannot run this code because I don't have the DotNetBar. In your Form_Load add this and comment out everything else in the event handler:
MessageBox.Show("Form load");
If you don't get a message here, then your Form_Load event handler isn't working. Also, which file format are you try to open with your program?
JPEG
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for the confirmation, eternal_21. That's what I expected to happen. In this case, you can replace the MessageBox with:

if(filePath != null)
            OpenPictures(filePath);
It works if I compile, build the install, install it, and then run it ...but not if i just use the Debug or Release.exe. . . Strange..
ok.. so would it be plausible to make it work for a group of selected pictures?
When I open multiple files it opens multiple applications and I'm not really sure how to open them all in one window. Sorry.
Here is how I would do it, although I have no idea what common practices are!

First, I would create a method of detecting if an instance of my application is already running.  You could use something like Michael Potter's Single Process Instance object http://www.codeproject.com/csharp/cssingprocess.asp).  If you are starting a second instance of the program with no parameters, I would bring the first instance to the foreground.  The website previously mentioned has information to help you do this.

Here comes the tricky part.  If you are starting a second instance of the program with a filename, I would send a (custom) Windows message to the first application asking it to open the file (using user32.dll's SendMessage function - Single Process Instance object will be able to give you the main window handle of the first application instance).  If the application is opened, and it is the first (and only) instance, it would implement a custom message listener (using a custom System.Windows.Forms.IMessageFilter object), that waits for new instances of the application to request a file be opened.

Hope that made sense - If it doesn't let me know... And good work Timbo87 - It's good to see an expert putting so much effort into helping someone find a solution!
I found a viable solution.

Using the System.IO.FileInfo class, I can get the directory of the image selected.
From there, I can use the "GetFiles()" method of the FileInfo Class to get an Array of the files in the present directory, and check their file extensions in a loop. If it ends with a '.jpg' or a '.bmp' or any other image type I want to incorporate, I add it to the Image Array.