首页 \ 问答 \ C#:迷你应用程序结构设计(类/接口/等)(C# : Mini Application Structural Design (Classes/Interfaces/etc.))

C#:迷你应用程序结构设计(类/接口/等)(C# : Mini Application Structural Design (Classes/Interfaces/etc.))

我一直在创建一个小应用程序,允许用户将图像转换为各种大小和格式。 我一直在努力获得这个应用程序的良好的设计。 我已经启动并运行了该应用程序,但它确实集成了良好的面向对象设计。 由于这是一个个人项目,我一直想了解更多关于集成接口,良好的类继承,对象组合以及面向对象设计的其他元素的信息。

不过,我一直在努力做到这一点。 不要误会我的意思,我知道OO设计和它是什么,我只是不知道如何在项目中实现良好的OO设计。 当然,您可以轻松查看您在书籍或在线阅读的课程示例。 示例可能有简单的情况,如下所示。

接口IPerson具有成员函数Walk()Run()抽象类人使用IPerson接口Class ManClass女性抽象类人物继承而来。

但是当涉及到Real Projects时,我很难实现良好的设计。 我希望得到一些见解。 这是我现在拥有的。

接口:

interface IPicture
{
    Bitmap ReturnImage(string path, int width, int height);
}

保存图片信息的主要类。 这个类基本上存储关于传递的图像的信息,以及关于用户想要的新值的信息(即,新大小,新文件位置,新图片格式等)

public class MyPictures : IPicture
{
    //All Private variables below are properties.  Property get/set's have been removed
    //for the sake of space
    private int _NewWidth;
    private int _NewHeight;
    private string _NewImgName;
    private string _NewImgPath;
    private string _NewImgFullPath;
    private ImageFormat _NewImgFormat;
    //Declare variables to hold values that have been determined
    private int _OldWidth;
    private int _OldHeight;
    private string _OldImgName;
    private string _OldImgPath;
    //Old Image Format is in String format because of certain extension scenarios.
    private string _OldImgFormat;

         public MyPictures(Image img, string file)
    {
        ClearProperties();
        //...set properties based on passed variables in constructor...
    }
    public void ClearProperties()
    {
        _NewWidth = 0;
        _NewHeight = 0;
        _NewImgName = "";
        _NewImgPath = "";
        _NewImgFullPath = "";
        _NewImgFormat = null;
        _OldWidth = 0;
        _OldHeight = 0;
        _OldImgName = "";
        _OldImgPath = "";
        _OldImgFormat = null;
    }

    public override string ToString()
    {  
        return _OldImgPath;
    }
    public void ImageSave()
    {
        Bitmap tempBmp = new Bitmap(_OldImgPath);
        Bitmap bmp = new Bitmap(tempBmp, _NewWidth, _NewHeight);
        bmp.Save(_NewImgPath + @"\" + _NewImgName + "." +  _NewImgFormat.ToString().ToLower(), _NewImgFormat);
    }
    public Bitmap ImageClone()
    {
        Bitmap bmp = new Bitmap(_OldImgPath);
        return bmp;
    }
    Bitmap IPicture.ReturnImage(string path, int width, int height)
    {
        return new Bitmap(new Bitmap(path), width, height);
    }
}

主类; 应用程序的起点。 这肯定需要一些工作......

public partial class Form1 : Form
{
    static bool hasThreadBeenStopped = false;
    static bool imageProcessingComplete = false;
    static bool imgConstrained = false;
    //Default text when user selects 'All' checkbox for new image name
    static string newNameDefault = "'Name' + #";
    Utility.Validation.Validate valid = new Utility.Validation.Validate();

    public Form1()
    {
        InitializeComponent();
        //Populate Combo Box With Possible Image Formats...
        //Conditionally show Image Properties...
        ImgPropertiesEnabled();
        //Set static progress bar properties...
        progressBar1.Minimum = 0;
        progressBar1.Step = 1;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        lblImgProcessed.Text = "";
        lblFile.Text = "";
        txtContentFolder.Text = "";
    }
    //Delegate declarations.  Used for multi-thread processing
    public delegate void PopulateTextboxDelegate(Label lbl, string text);
    public delegate void ThreadWorkDelegate(Label lbl, string text);
    public delegate void ImageDisplayDelegate(Image i);
    public delegate void ProgressBarDelegate(ProgressBar p, int step, int value);

    //Populate textbox fields with image processed, and image path being processed
    public void PopulateTextbox(Label lbl, string text)
    {
        lbl.Text = "";
        lbl.Text = text;
    }
    public void ThreadWork(Label lbl, string text)
    {
        this.Invoke(new PopulateTextboxDelegate(PopulateTextbox),
                    new object[] { lbl, text });
    }
    //Display Currently Processed Image
    public void ImageDisplay(Image i)
    {
        pbMain.Image = null;
        pbMain.Image = i;
    }
    public void ThreadWorkImg(Image i)
    {
        this.Invoke(new ImageDisplayDelegate(ImageDisplay),
                    new object[] {i});
    }
    //Increment Progress Bar
    public void ProgressBarDisplay(ProgressBar pg, int max, int value)
    {
        //Dynamically set the Progress Bar properties
        pg.Maximum = max;
        pg.Value = value;
    }
    public void ThreadProgress(ProgressBar p, int max, int value)
    {
        this.Invoke(new ProgressBarDelegate(ProgressBarDisplay),
                    new object[] { p, max, value });
    }        
    private void btnStart_Click(object sender, EventArgs e)
    {
        string IsValidResult = IsValid();
        //If string is empty, Utility passed
        if (IsValidResult == "")
        {
            Thread t = new Thread(new ThreadStart(ProcessFiles));
            t.Start();
        }
        else
        {
            MessageBox.Show(IsValidResult);
        }
    }
    public void ProcessFiles()
    {
        int count = 0;

        ThreadWorkDelegate w = ThreadWork;
        ImageDisplayDelegate im = ThreadWorkImg;
        ProgressBarDelegate pb = ThreadProgress;

        try
        {
            foreach (MyPictures mp in lstHold.Items)
            {
                try
                {
                    if (hasThreadBeenStopped == false)
                    {
                        //Disable certain controls during process.  We will use the generic
                        //MethodInvoker, which Represents a delegate that can execute any method 
                        //in managed code that is declared void and takes no parameters.
                        //Using the MethodInvoker is good when simple delegates are needed.  Ironically,
                        //this way of multi-thread delegation was used because the traditional way as used
                        //by the rest of the delegates in this method, was not working.
                        btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = false; }));
                        btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = false; }));

                        //Call delegate to show current picture being processed
                        im.BeginInvoke(mp.ImageClone(), null, null);
                        mp.ImageSave();

                        //Increment Count; Image has been processed
                        count++;

                        //Invoke Img Proceessed Output
                        w.BeginInvoke(lblImgProcessed, count.ToString() +
                                      " of " + lstHold.Items.Count.ToString() + " processed",
                                      null, null);
                        //Invoke File Process Output
                        w.BeginInvoke(lblFile, mp.NewImgPath, null, null);

                        //Invoke Progressbar output.  Delegate is passed The count of images,
                        //which will be set as the progressbar max value.  the 'count' variable is
                        //passed to determine the current value.
                        pb.BeginInvoke(progressBar1, lstHold.Items.Count, count, null, null);
                    }
                    else //Thread has been called to stop
                    {
                        MessageBox.Show("Image Processing Stopped: " + count + "of " +
                                        lstHold.Items.Count + " processed");
                        //Enable controls after process
                        btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = true; }));
                        btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = true; }));
                        break;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error while processing pictures");
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error while attempting to execute pictures: " + ex.ToString());
        }
        finally
        {
            //Loop has ended:
            //In finally statement, re-enable disabled controls
            //Enable certain controls during process
            btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = true; }));
            btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = true; }));
            //Reset class variables
            hasThreadBeenStopped = false;
            imageProcessingComplete = false;
        }
    }

    private void btnContent_Click(object sender, EventArgs e)
    {
        string selection = null;
        string[] files = null;

        lstAll.Items.Clear();
        contentBrowser.ShowDialog();

        selection = contentBrowser.SelectedPath;
        txtContentFolder.Text = selection;
        if (selection != "" || selection != null)
        {
            try
            {
                files = System.IO.Directory.GetFiles(selection.Trim());
                foreach (string file in files)
                {
                    lstAll.Items.Add(file);
                }
            }
            catch (Exception ex)
            {
               // MessageBox.Show(ex.ToString());
            }

        }
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
        //Grab files from folder based on user input in the textbox.  
        string selection = txtContentFolder.Text.Trim();
        string[] files = null;

        lstAll.Items.Clear();

        if (valid.IsNull(selection) == false || valid.IsEmpty(selection) == false)
        {
            try
            {
                files = System.IO.Directory.GetFiles(selection);
                foreach (string file in files)
                {
                    lstAll.Items.Add(file);
                }
            }
            catch (Exception ex)
            {
               MessageBox.Show("Invalid Directory");
            }
        }
        txtContentFolder.Text = selection;
    }
    private void btnDestination_Click(object sender, EventArgs e)
    {
        string selection = null;
        destinationBrowser.ShowDialog();
        selection = destinationBrowser.SelectedPath;
        txtNewImgPath.Text = selection;
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        this.Close();
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        //Flag variable that the stop button has been called.  This variable is checked
        //conditionally when looping over each picture.
        hasThreadBeenStopped = true;
    }

    public string IsValid()
    { 
        StringBuilder sb = new StringBuilder("");

        if (lstHold.Items.Count <= 0)
        {
            return "No items exist to process";
        }
        //Validate that there is a value in each field for every object in lstHold.  All the fields will be
        //validated.  Note:  If there is one invalid field, the rest do not need to be considered.  
        foreach (MyPictures mp in lstHold.Items)
        {
            if (mp.NewImgName == "")
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewImgPath == "")
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewImgFormat == null)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewWidth == 0)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewHeight == 0)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
        }
        //If the returned string is empty, the image is valid.  The check for the listbox's count
        //will return a string immediatly if false.  Because of this, we know that the returning
        //string at this level will either be empty (validation passed) or filled with image paths
        //of images missing required values.  If image is not valid, return this concatenated string of image paths
        //that are missing values, and insert a prefixed string literal to this list.
        if (sb.ToString() != "")
        {
            sb.Insert(0, "The following images are missing required values: ");
            return sb.ToString();
        }
        else //String is empty and has passed validation
        {
            return sb.ToString();
        }

    }

    private void btnMoveOne_Click(object sender, EventArgs e)
    {
        //Loop through All strings in the lstAll list box.  Then use each picture path to convert 
        //each picture into their own class
        foreach (string file in lstAll.SelectedItems)
        {
            //isImgExistFlag is a flag indicating wheter the image coming from lstAll already exists
            //in lstHold.  By default, the variable is false.  It is set to true if an image does exist
            //This variable must be re-created within the scope of the main foreach loop to ensure a proper
            //reset of the variable for each image comparison.
            bool isImgExistFlag = false;
            try
            {
                Image img;
                img = Image.FromFile(file);

                MyPictures mp = new MyPictures(img,file);

                //If lstHold contains no items, add the item with no validation check.  
                if (lstHold.Items.Count == 0)
                {
                    lstHold.Items.Add(mp);
                }
                else
                {
                    //Run through each object in the lstHold to determine if the newly created object
                    //already exists in list box lstHold.
                    for (int i = 0; i < lstHold.Items.Count; i++)
                    {
                        MyPictures p = (MyPictures)lstHold.Items[i];
                        //Unique objects will be identified by their Original Image Path, because
                        //this value will be unique
                        if (p.OldImgPath == mp.OldImgPath)
                        {
                            isImgExistFlag = true;
                        }
                    }
                    //If isImgExistFlag is false, the current Image object doesnt currently exist 
                    //in list box.  Therefore, add it to the list.  
                    if (isImgExistFlag == false)
                    {
                        lstHold.Items.Add(mp);
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }                    
        }
      }

    private void btnMoveAll_Click(object sender, EventArgs e)
    {
        //This event has the same functionality as btnMoveOne_Click, except the main foreach loop
        //is based on all of lstAll's items, rather than just the selected items.
        foreach (string file in lstAll.Items)
        {
            bool isImgExistFlag = false;
            try
            {
                Image img;
                img = Image.FromFile(file);

                MyPictures mp = new MyPictures(img, file);

                if (lstHold.Items.Count == 0)
                {
                    lstHold.Items.Add(mp);
                }
                else
                {
                    for (int i = 0; i < lstHold.Items.Count; i++)
                    {
                        MyPictures p = (MyPictures)lstHold.Items[i];

                        if (p.OldImgPath == mp.OldImgPath)
                        {
                            isImgExistFlag = true;
                        }
                    }
                    if (isImgExistFlag == false)
                    {
                        lstHold.Items.Add(mp);
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

    private void btnRemoveOne_Click(object sender, EventArgs e)
    {
        /*
        Create a seperate List to populate:
        This is necessary because if you explicitly remove an item from the listbox
        you will get the following error:
        "List that this enumerator is bound to has been modified. An enumerator can 
        only be used if the list does not change."
         */
        //This variable will keep track of the first index processed. 
        int first_index = 0;
        int count = 0;
        List<MyPictures> TempMp = new List<MyPictures>();

        if (lstHold.Items.Count >= 1)
        {
            try
            {
                foreach (MyPictures mp in lstHold.SelectedItems)
                {
                    if (count == 0)
                    {
                        first_index = lstHold.SelectedIndex;
                    }
                    //Add objects to be removed
                    TempMp.Add(mp);
                }
                foreach (MyPictures mp2 in TempMp)
                {
                    lstHold.Items.Remove(mp2);
                }
            }
            catch (Exception ex)
            {
                //Hide Error: MessageBox.Show(ex.ToString());
            }
            //Select new item in list if possible, as long as there is a item in the list
            if (lstHold.Items.Count >= 1)
            {
                //If the first_index variable = the amount of items in the list, the new selected index
                //should be the first index -1.  This is because the variable first_index would be the 
                //index of the now deleted item in the list.  Therefore we must subtract the variable by 1 
                //before assigning it to the selected value.  Otherwise, we'll be assigning a selected index that
                //no longer exists. 
                //There is also a check to make sure there is more than one item in the list.  Otherwise, we could
                //potentially assign a selected index of -1.
                if (first_index == lstHold.Items.Count && lstHold.Items.Count != 1)
                {
                    lstHold.SelectedIndex = first_index - 1;
                }
                else if (lstHold.Items.Count == 1)
                {
                    lstHold.SelectedIndex = 0;
                }
                else
                {
                    lstHold.SelectedIndex = first_index;
                }
            }
            else
            {
                ClearTextBoxes();
            }
        }

    }

    private void btnRemoveAll_Click(object sender, EventArgs e)
    {
        lstHold.Items.Clear();
        ClearTextBoxes();
        ImgPropertiesEnabled();
    }

    private void lstHold_SelectedIndexChanged(object sender, EventArgs e)
    {
        //This prevents trying to access a negative index.  This can happen when a item is removed.
        if (lstHold.SelectedIndex >= 0)
        {
            try
            {
                MyPictures mp = (MyPictures)lstHold.Items[lstHold.SelectedIndex];
                txtOldName.Text = mp.OldImgName;
                txtOldImgPath.Text = mp.OldImgPath;
                txtOldImgFormat.Text = mp.OldImgFormat.ToString();
                txtOldWidth.Text = mp.OldWidth.ToString();
                txtOldHeight.Text = mp.OldHeight.ToString();

                txtNewName.Text = mp.NewImgName;
                cbFormat.SelectedItem = mp.NewImgFormat;
                txtNewWidth.Text = mp.NewWidth.ToString();
                txtNewHeight.Text = mp.NewHeight.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        //Call function to determine which controls should be enabled/disabled
        ImgPropertiesEnabled();
    }

    private void btnApply_Click(object sender, EventArgs e)
    {

        //Reset color.  It could be grey depending on if user changed default name.
        txtNewName.ForeColor = Color.Black;

        if (lstHold.SelectedIndex == -1)
        {
            MessageBox.Show("Picture not selected.  Select picture to apply properties to.");
        }
        else if (lstHold.SelectedIndex >= 0)
        {
            MyPictures mp = (MyPictures)lstHold.Items[lstHold.SelectedIndex];

            //User wants to apply a generated name to all pictures within the list
            if (chkNewPicName.Checked == true)
            {
                int count = 0;
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgName = txtNewName.Text + count.ToString();
                    ++count;
                }
                txtNewName.Text = mp.NewImgName;
            }
            //User wants to apply a custom name to this picture only
            else
            {
                mp.NewImgName = txtNewName.Text;
            }
            //User wants to apply this path to all pictures within the list
            if (chkNewPicPath.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgPath = txtNewImgPath.Text;
                }
                txtNewImgPath.Text = mp.NewImgPath;
            }
            //User wants to apply this path to this picture only
            else
            {
                mp.NewImgPath = txtNewImgPath.Text;
            }
            //User wants to apply this image format to all pictures within the list
            if (chkNewPicFormat.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
                }
            }
            //User wants to apply this image format to this picture only
            else
            {
                mp.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
            }
            //User wants to apply this size to all pictures 
            if (chkNewSize.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewWidth = Convert.ToInt32(txtNewWidth.Text);
                    pic.NewHeight = Convert.ToInt32(txtNewHeight.Text);
                }
                txtNewWidth.Text = mp.NewWidth.ToString();
                txtNewHeight.Text = mp.NewHeight.ToString();
            }
            //User wants to apply this size to this picture only
            else
            {
                mp.NewWidth = Convert.ToInt32(txtNewWidth.Text);
                mp.NewHeight = Convert.ToInt32(txtNewHeight.Text);
            }

            mp.NewImgName = txtNewName.Text;
            mp.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
            mp.NewWidth = Convert.ToInt32(txtNewWidth.Text);
            mp.NewHeight = Convert.ToInt32(txtNewHeight.Text);
        }
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (chkSelectAll.Checked)
        {
            chkNewPicName.Checked = true;
            chkNewPicPath.Checked = true;
            chkNewPicFormat.Checked = true;
            chkNewSize.Checked = true;
        }
        else
        {
            chkNewPicName.Checked = false;
            chkNewPicPath.Checked = false;
            chkNewPicFormat.Checked = false;
            chkNewSize.Checked = false;
        }
    }

    private void previewToolStripMenuItem_Click(object sender, EventArgs e)
    {
        MessageBox.Show("hi there!");
    }

    private void btnPreview_Click(object sender, EventArgs e)
    {
        try
        {
            if (lstHold.Items.Count <= 0)
            {
                MessageBox.Show("No pictures are available to preview");
            }
            else if (lstHold.SelectedItem == null)
            {
                MessageBox.Show("No picture is selected to preview");
            }
            else
            {
                MyPictures mp = (MyPictures)lstHold.SelectedItem;
                //Bitmap bmp = new Bitmap(mp.OldImgPath);
                Form2 frm = new Form2(mp);
                frm.Show();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("An Error has occured:\n " + ex.ToString());
        }
    }
    public void ImgPropertiesEnabled()
    {
        //Enable Image properties when an image is selected
        if (lstHold.SelectedIndex >= 0)
        {
            gbCheckAll.Enabled = true;
            gbImgProperties.Enabled = true;
        }
        else
        {
            //Disable Image properties when an image is not selected
            gbCheckAll.Enabled = false;
            gbImgProperties.Enabled = false;

        }
        //Preview buttons enablement will depend on the same conditions
        btnPreview.Enabled = gbImgProperties.Enabled;
    }
    public void ClearTextBoxes()
    {
        txtNewImgPath.Text = "";
        txtNewName.Text = "";
        txtNewHeight.Text = Convert.ToString(0);
        txtNewWidth.Text = Convert.ToString(0);
        cbFormat.SelectedItem = null;
        chkSelectAll.Checked = false;
    }

}


I've been creating a small application that allows a user to convert images to various sizes and formats. I've been struggling on getting a good solid design with this application. I have the application up and running, but it does integrate good Object-Oriented design. Since this is a personal project, I've been wanting to learn more about integrating interfaces, good class inheritance, object composition, and other elements of OO design.

However, I've been struggling to do so. Don't get me wrong, I know about OO design and what it is, I just don't know how to implement good OO design in projects. Of course its easy to look at class Examples that you read in books, or online. Examples may have simple scenarios such as the following.

Interface IPerson has member functions Walk(), Run() . Abstract Class Person uses IPerson Interface. Class Man and Class Female inherit from Abstract Class Person.

but when it comes to Real Projects I struggle to implement good design. I was hoping for some insight. Here is what I currently have.

Interface:

interface IPicture
{
    Bitmap ReturnImage(string path, int width, int height);
}

Main Class that Holds Picture Information. This class basically stores information about the image passed, and information about the new values the user wants (i.e. new size, new file location, new pic format, etc.)

public class MyPictures : IPicture
{
    //All Private variables below are properties.  Property get/set's have been removed
    //for the sake of space
    private int _NewWidth;
    private int _NewHeight;
    private string _NewImgName;
    private string _NewImgPath;
    private string _NewImgFullPath;
    private ImageFormat _NewImgFormat;
    //Declare variables to hold values that have been determined
    private int _OldWidth;
    private int _OldHeight;
    private string _OldImgName;
    private string _OldImgPath;
    //Old Image Format is in String format because of certain extension scenarios.
    private string _OldImgFormat;

         public MyPictures(Image img, string file)
    {
        ClearProperties();
        //...set properties based on passed variables in constructor...
    }
    public void ClearProperties()
    {
        _NewWidth = 0;
        _NewHeight = 0;
        _NewImgName = "";
        _NewImgPath = "";
        _NewImgFullPath = "";
        _NewImgFormat = null;
        _OldWidth = 0;
        _OldHeight = 0;
        _OldImgName = "";
        _OldImgPath = "";
        _OldImgFormat = null;
    }

    public override string ToString()
    {  
        return _OldImgPath;
    }
    public void ImageSave()
    {
        Bitmap tempBmp = new Bitmap(_OldImgPath);
        Bitmap bmp = new Bitmap(tempBmp, _NewWidth, _NewHeight);
        bmp.Save(_NewImgPath + @"\" + _NewImgName + "." +  _NewImgFormat.ToString().ToLower(), _NewImgFormat);
    }
    public Bitmap ImageClone()
    {
        Bitmap bmp = new Bitmap(_OldImgPath);
        return bmp;
    }
    Bitmap IPicture.ReturnImage(string path, int width, int height)
    {
        return new Bitmap(new Bitmap(path), width, height);
    }
}

Main Class; Starting point of application. This definatly needs some work...

public partial class Form1 : Form
{
    static bool hasThreadBeenStopped = false;
    static bool imageProcessingComplete = false;
    static bool imgConstrained = false;
    //Default text when user selects 'All' checkbox for new image name
    static string newNameDefault = "'Name' + #";
    Utility.Validation.Validate valid = new Utility.Validation.Validate();

    public Form1()
    {
        InitializeComponent();
        //Populate Combo Box With Possible Image Formats...
        //Conditionally show Image Properties...
        ImgPropertiesEnabled();
        //Set static progress bar properties...
        progressBar1.Minimum = 0;
        progressBar1.Step = 1;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        lblImgProcessed.Text = "";
        lblFile.Text = "";
        txtContentFolder.Text = "";
    }
    //Delegate declarations.  Used for multi-thread processing
    public delegate void PopulateTextboxDelegate(Label lbl, string text);
    public delegate void ThreadWorkDelegate(Label lbl, string text);
    public delegate void ImageDisplayDelegate(Image i);
    public delegate void ProgressBarDelegate(ProgressBar p, int step, int value);

    //Populate textbox fields with image processed, and image path being processed
    public void PopulateTextbox(Label lbl, string text)
    {
        lbl.Text = "";
        lbl.Text = text;
    }
    public void ThreadWork(Label lbl, string text)
    {
        this.Invoke(new PopulateTextboxDelegate(PopulateTextbox),
                    new object[] { lbl, text });
    }
    //Display Currently Processed Image
    public void ImageDisplay(Image i)
    {
        pbMain.Image = null;
        pbMain.Image = i;
    }
    public void ThreadWorkImg(Image i)
    {
        this.Invoke(new ImageDisplayDelegate(ImageDisplay),
                    new object[] {i});
    }
    //Increment Progress Bar
    public void ProgressBarDisplay(ProgressBar pg, int max, int value)
    {
        //Dynamically set the Progress Bar properties
        pg.Maximum = max;
        pg.Value = value;
    }
    public void ThreadProgress(ProgressBar p, int max, int value)
    {
        this.Invoke(new ProgressBarDelegate(ProgressBarDisplay),
                    new object[] { p, max, value });
    }        
    private void btnStart_Click(object sender, EventArgs e)
    {
        string IsValidResult = IsValid();
        //If string is empty, Utility passed
        if (IsValidResult == "")
        {
            Thread t = new Thread(new ThreadStart(ProcessFiles));
            t.Start();
        }
        else
        {
            MessageBox.Show(IsValidResult);
        }
    }
    public void ProcessFiles()
    {
        int count = 0;

        ThreadWorkDelegate w = ThreadWork;
        ImageDisplayDelegate im = ThreadWorkImg;
        ProgressBarDelegate pb = ThreadProgress;

        try
        {
            foreach (MyPictures mp in lstHold.Items)
            {
                try
                {
                    if (hasThreadBeenStopped == false)
                    {
                        //Disable certain controls during process.  We will use the generic
                        //MethodInvoker, which Represents a delegate that can execute any method 
                        //in managed code that is declared void and takes no parameters.
                        //Using the MethodInvoker is good when simple delegates are needed.  Ironically,
                        //this way of multi-thread delegation was used because the traditional way as used
                        //by the rest of the delegates in this method, was not working.
                        btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = false; }));
                        btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = false; }));

                        //Call delegate to show current picture being processed
                        im.BeginInvoke(mp.ImageClone(), null, null);
                        mp.ImageSave();

                        //Increment Count; Image has been processed
                        count++;

                        //Invoke Img Proceessed Output
                        w.BeginInvoke(lblImgProcessed, count.ToString() +
                                      " of " + lstHold.Items.Count.ToString() + " processed",
                                      null, null);
                        //Invoke File Process Output
                        w.BeginInvoke(lblFile, mp.NewImgPath, null, null);

                        //Invoke Progressbar output.  Delegate is passed The count of images,
                        //which will be set as the progressbar max value.  the 'count' variable is
                        //passed to determine the current value.
                        pb.BeginInvoke(progressBar1, lstHold.Items.Count, count, null, null);
                    }
                    else //Thread has been called to stop
                    {
                        MessageBox.Show("Image Processing Stopped: " + count + "of " +
                                        lstHold.Items.Count + " processed");
                        //Enable controls after process
                        btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = true; }));
                        btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = true; }));
                        break;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error while processing pictures");
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error while attempting to execute pictures: " + ex.ToString());
        }
        finally
        {
            //Loop has ended:
            //In finally statement, re-enable disabled controls
            //Enable certain controls during process
            btnApply.Invoke(new MethodInvoker(delegate { btnApply.Enabled = true; }));
            btnStart.Invoke(new MethodInvoker(delegate { btnStart.Enabled = true; }));
            //Reset class variables
            hasThreadBeenStopped = false;
            imageProcessingComplete = false;
        }
    }

    private void btnContent_Click(object sender, EventArgs e)
    {
        string selection = null;
        string[] files = null;

        lstAll.Items.Clear();
        contentBrowser.ShowDialog();

        selection = contentBrowser.SelectedPath;
        txtContentFolder.Text = selection;
        if (selection != "" || selection != null)
        {
            try
            {
                files = System.IO.Directory.GetFiles(selection.Trim());
                foreach (string file in files)
                {
                    lstAll.Items.Add(file);
                }
            }
            catch (Exception ex)
            {
               // MessageBox.Show(ex.ToString());
            }

        }
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
        //Grab files from folder based on user input in the textbox.  
        string selection = txtContentFolder.Text.Trim();
        string[] files = null;

        lstAll.Items.Clear();

        if (valid.IsNull(selection) == false || valid.IsEmpty(selection) == false)
        {
            try
            {
                files = System.IO.Directory.GetFiles(selection);
                foreach (string file in files)
                {
                    lstAll.Items.Add(file);
                }
            }
            catch (Exception ex)
            {
               MessageBox.Show("Invalid Directory");
            }
        }
        txtContentFolder.Text = selection;
    }
    private void btnDestination_Click(object sender, EventArgs e)
    {
        string selection = null;
        destinationBrowser.ShowDialog();
        selection = destinationBrowser.SelectedPath;
        txtNewImgPath.Text = selection;
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        this.Close();
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        //Flag variable that the stop button has been called.  This variable is checked
        //conditionally when looping over each picture.
        hasThreadBeenStopped = true;
    }

    public string IsValid()
    { 
        StringBuilder sb = new StringBuilder("");

        if (lstHold.Items.Count <= 0)
        {
            return "No items exist to process";
        }
        //Validate that there is a value in each field for every object in lstHold.  All the fields will be
        //validated.  Note:  If there is one invalid field, the rest do not need to be considered.  
        foreach (MyPictures mp in lstHold.Items)
        {
            if (mp.NewImgName == "")
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewImgPath == "")
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewImgFormat == null)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewWidth == 0)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
            else if (mp.NewHeight == 0)
            {
                sb.Append(mp.OldImgPath + ", ");
            }
        }
        //If the returned string is empty, the image is valid.  The check for the listbox's count
        //will return a string immediatly if false.  Because of this, we know that the returning
        //string at this level will either be empty (validation passed) or filled with image paths
        //of images missing required values.  If image is not valid, return this concatenated string of image paths
        //that are missing values, and insert a prefixed string literal to this list.
        if (sb.ToString() != "")
        {
            sb.Insert(0, "The following images are missing required values: ");
            return sb.ToString();
        }
        else //String is empty and has passed validation
        {
            return sb.ToString();
        }

    }

    private void btnMoveOne_Click(object sender, EventArgs e)
    {
        //Loop through All strings in the lstAll list box.  Then use each picture path to convert 
        //each picture into their own class
        foreach (string file in lstAll.SelectedItems)
        {
            //isImgExistFlag is a flag indicating wheter the image coming from lstAll already exists
            //in lstHold.  By default, the variable is false.  It is set to true if an image does exist
            //This variable must be re-created within the scope of the main foreach loop to ensure a proper
            //reset of the variable for each image comparison.
            bool isImgExistFlag = false;
            try
            {
                Image img;
                img = Image.FromFile(file);

                MyPictures mp = new MyPictures(img,file);

                //If lstHold contains no items, add the item with no validation check.  
                if (lstHold.Items.Count == 0)
                {
                    lstHold.Items.Add(mp);
                }
                else
                {
                    //Run through each object in the lstHold to determine if the newly created object
                    //already exists in list box lstHold.
                    for (int i = 0; i < lstHold.Items.Count; i++)
                    {
                        MyPictures p = (MyPictures)lstHold.Items[i];
                        //Unique objects will be identified by their Original Image Path, because
                        //this value will be unique
                        if (p.OldImgPath == mp.OldImgPath)
                        {
                            isImgExistFlag = true;
                        }
                    }
                    //If isImgExistFlag is false, the current Image object doesnt currently exist 
                    //in list box.  Therefore, add it to the list.  
                    if (isImgExistFlag == false)
                    {
                        lstHold.Items.Add(mp);
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }                    
        }
      }

    private void btnMoveAll_Click(object sender, EventArgs e)
    {
        //This event has the same functionality as btnMoveOne_Click, except the main foreach loop
        //is based on all of lstAll's items, rather than just the selected items.
        foreach (string file in lstAll.Items)
        {
            bool isImgExistFlag = false;
            try
            {
                Image img;
                img = Image.FromFile(file);

                MyPictures mp = new MyPictures(img, file);

                if (lstHold.Items.Count == 0)
                {
                    lstHold.Items.Add(mp);
                }
                else
                {
                    for (int i = 0; i < lstHold.Items.Count; i++)
                    {
                        MyPictures p = (MyPictures)lstHold.Items[i];

                        if (p.OldImgPath == mp.OldImgPath)
                        {
                            isImgExistFlag = true;
                        }
                    }
                    if (isImgExistFlag == false)
                    {
                        lstHold.Items.Add(mp);
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

    private void btnRemoveOne_Click(object sender, EventArgs e)
    {
        /*
        Create a seperate List to populate:
        This is necessary because if you explicitly remove an item from the listbox
        you will get the following error:
        "List that this enumerator is bound to has been modified. An enumerator can 
        only be used if the list does not change."
         */
        //This variable will keep track of the first index processed. 
        int first_index = 0;
        int count = 0;
        List<MyPictures> TempMp = new List<MyPictures>();

        if (lstHold.Items.Count >= 1)
        {
            try
            {
                foreach (MyPictures mp in lstHold.SelectedItems)
                {
                    if (count == 0)
                    {
                        first_index = lstHold.SelectedIndex;
                    }
                    //Add objects to be removed
                    TempMp.Add(mp);
                }
                foreach (MyPictures mp2 in TempMp)
                {
                    lstHold.Items.Remove(mp2);
                }
            }
            catch (Exception ex)
            {
                //Hide Error: MessageBox.Show(ex.ToString());
            }
            //Select new item in list if possible, as long as there is a item in the list
            if (lstHold.Items.Count >= 1)
            {
                //If the first_index variable = the amount of items in the list, the new selected index
                //should be the first index -1.  This is because the variable first_index would be the 
                //index of the now deleted item in the list.  Therefore we must subtract the variable by 1 
                //before assigning it to the selected value.  Otherwise, we'll be assigning a selected index that
                //no longer exists. 
                //There is also a check to make sure there is more than one item in the list.  Otherwise, we could
                //potentially assign a selected index of -1.
                if (first_index == lstHold.Items.Count && lstHold.Items.Count != 1)
                {
                    lstHold.SelectedIndex = first_index - 1;
                }
                else if (lstHold.Items.Count == 1)
                {
                    lstHold.SelectedIndex = 0;
                }
                else
                {
                    lstHold.SelectedIndex = first_index;
                }
            }
            else
            {
                ClearTextBoxes();
            }
        }

    }

    private void btnRemoveAll_Click(object sender, EventArgs e)
    {
        lstHold.Items.Clear();
        ClearTextBoxes();
        ImgPropertiesEnabled();
    }

    private void lstHold_SelectedIndexChanged(object sender, EventArgs e)
    {
        //This prevents trying to access a negative index.  This can happen when a item is removed.
        if (lstHold.SelectedIndex >= 0)
        {
            try
            {
                MyPictures mp = (MyPictures)lstHold.Items[lstHold.SelectedIndex];
                txtOldName.Text = mp.OldImgName;
                txtOldImgPath.Text = mp.OldImgPath;
                txtOldImgFormat.Text = mp.OldImgFormat.ToString();
                txtOldWidth.Text = mp.OldWidth.ToString();
                txtOldHeight.Text = mp.OldHeight.ToString();

                txtNewName.Text = mp.NewImgName;
                cbFormat.SelectedItem = mp.NewImgFormat;
                txtNewWidth.Text = mp.NewWidth.ToString();
                txtNewHeight.Text = mp.NewHeight.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        //Call function to determine which controls should be enabled/disabled
        ImgPropertiesEnabled();
    }

    private void btnApply_Click(object sender, EventArgs e)
    {

        //Reset color.  It could be grey depending on if user changed default name.
        txtNewName.ForeColor = Color.Black;

        if (lstHold.SelectedIndex == -1)
        {
            MessageBox.Show("Picture not selected.  Select picture to apply properties to.");
        }
        else if (lstHold.SelectedIndex >= 0)
        {
            MyPictures mp = (MyPictures)lstHold.Items[lstHold.SelectedIndex];

            //User wants to apply a generated name to all pictures within the list
            if (chkNewPicName.Checked == true)
            {
                int count = 0;
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgName = txtNewName.Text + count.ToString();
                    ++count;
                }
                txtNewName.Text = mp.NewImgName;
            }
            //User wants to apply a custom name to this picture only
            else
            {
                mp.NewImgName = txtNewName.Text;
            }
            //User wants to apply this path to all pictures within the list
            if (chkNewPicPath.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgPath = txtNewImgPath.Text;
                }
                txtNewImgPath.Text = mp.NewImgPath;
            }
            //User wants to apply this path to this picture only
            else
            {
                mp.NewImgPath = txtNewImgPath.Text;
            }
            //User wants to apply this image format to all pictures within the list
            if (chkNewPicFormat.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
                }
            }
            //User wants to apply this image format to this picture only
            else
            {
                mp.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
            }
            //User wants to apply this size to all pictures 
            if (chkNewSize.Checked == true)
            {
                foreach (MyPictures pic in lstHold.Items)
                {
                    pic.NewWidth = Convert.ToInt32(txtNewWidth.Text);
                    pic.NewHeight = Convert.ToInt32(txtNewHeight.Text);
                }
                txtNewWidth.Text = mp.NewWidth.ToString();
                txtNewHeight.Text = mp.NewHeight.ToString();
            }
            //User wants to apply this size to this picture only
            else
            {
                mp.NewWidth = Convert.ToInt32(txtNewWidth.Text);
                mp.NewHeight = Convert.ToInt32(txtNewHeight.Text);
            }

            mp.NewImgName = txtNewName.Text;
            mp.NewImgFormat = (ImageFormat)cbFormat.SelectedItem;
            mp.NewWidth = Convert.ToInt32(txtNewWidth.Text);
            mp.NewHeight = Convert.ToInt32(txtNewHeight.Text);
        }
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (chkSelectAll.Checked)
        {
            chkNewPicName.Checked = true;
            chkNewPicPath.Checked = true;
            chkNewPicFormat.Checked = true;
            chkNewSize.Checked = true;
        }
        else
        {
            chkNewPicName.Checked = false;
            chkNewPicPath.Checked = false;
            chkNewPicFormat.Checked = false;
            chkNewSize.Checked = false;
        }
    }

    private void previewToolStripMenuItem_Click(object sender, EventArgs e)
    {
        MessageBox.Show("hi there!");
    }

    private void btnPreview_Click(object sender, EventArgs e)
    {
        try
        {
            if (lstHold.Items.Count <= 0)
            {
                MessageBox.Show("No pictures are available to preview");
            }
            else if (lstHold.SelectedItem == null)
            {
                MessageBox.Show("No picture is selected to preview");
            }
            else
            {
                MyPictures mp = (MyPictures)lstHold.SelectedItem;
                //Bitmap bmp = new Bitmap(mp.OldImgPath);
                Form2 frm = new Form2(mp);
                frm.Show();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("An Error has occured:\n " + ex.ToString());
        }
    }
    public void ImgPropertiesEnabled()
    {
        //Enable Image properties when an image is selected
        if (lstHold.SelectedIndex >= 0)
        {
            gbCheckAll.Enabled = true;
            gbImgProperties.Enabled = true;
        }
        else
        {
            //Disable Image properties when an image is not selected
            gbCheckAll.Enabled = false;
            gbImgProperties.Enabled = false;

        }
        //Preview buttons enablement will depend on the same conditions
        btnPreview.Enabled = gbImgProperties.Enabled;
    }
    public void ClearTextBoxes()
    {
        txtNewImgPath.Text = "";
        txtNewName.Text = "";
        txtNewHeight.Text = Convert.ToString(0);
        txtNewWidth.Text = Convert.ToString(0);
        cbFormat.SelectedItem = null;
        chkSelectAll.Checked = false;
    }

}


原文:https://stackoverflow.com/questions/2259822
更新时间:2024-02-14 13:02

最满意答案

要显示所选行,我在行中使用此单击函数:

$('body').on("click",'#collectionsList tbody tr',function() {
  if ($(this).hasClass('row_selected')) 
    $(this).removeClass('row_selected'); // select or deselect row
  else {
    /* I don't put this line below
    //---> $(this).siblings('.row_selected').removeClass('row_selected');
    */
    $(this).addClass('row_selected'); // add selected row
  }
  var aData = oTable.fnGetData(this); // get tha data array from columns
  var col0 = aData[0];  // get the first column value
  var col1 = aData[1];  // get the second column value
  var rowsID=this.id; // rowsID is your id of <tr>
});

To show the selected rows, I use this click function at the rows :

$('body').on("click",'#collectionsList tbody tr',function() {
  if ($(this).hasClass('row_selected')) 
    $(this).removeClass('row_selected'); // select or deselect row
  else {
    /* I don't put this line below
    //---> $(this).siblings('.row_selected').removeClass('row_selected');
    */
    $(this).addClass('row_selected'); // add selected row
  }
  var aData = oTable.fnGetData(this); // get tha data array from columns
  var col0 = aData[0];  // get the first column value
  var col1 = aData[1];  // get the second column value
  var rowsID=this.id; // rowsID is your id of <tr>
});

相关问答

更多

相关文章

更多

最新问答

更多
  • 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
  • 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
  • OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
  • 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
  • codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
  • 在计算机拍照在哪里进入
  • 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
  • No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
  • 单页应用程序:页面重新加载(Single Page Application: page reload)
  • 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
  • System.StackOverflow错误(System.StackOverflow error)
  • KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • C#类名中允许哪些字符?(What characters are allowed in C# class name?)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 在Angular 5中不是一个函数(is not a function in Angular 5)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • 常见的python rpc和cli接口(Common python rpc and cli interface)
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)