Thursday, September 26

Properties.Settings.Default.Save(); จำค่าไว้ก่อนปิด

พอดีมีคนถามมา ก็เลยลองหาดูในเนต ก็เจอว่ามีวิธีการเก็บบันทึกค่าต่างๆ ที่เรากรอกทิ้งไว้ในฟอร์ม ก่อนปิดหน้าต่างโปรแกรม แล้ว สามารถเรียกกลับมาคืนได้ ผมเคยคิดว่าจะเก็บลง Registry ของ windows (ซึ่งไม่น่าจะง่าย) แต่ มาเจอวิธีที่ง่ายกว่านั้นอีก เรามาดูกันเลย

เริ่มแรกก็สร้างฟอร์มง่ายๆ ก่อน ให้มีแค่ Textbox อันเดียวก็พอ

จากนั้นคลิกขวาที่โปรเจคของเรา ในหน้าต่าง Solution Explorer แล้วเลือก Properties เลือกที่ Tab setting และทำการกรอกค่าตามรูป

simple form

------+-------+-------
Name          Type         Scope
------+-------+-------
text             string       User
x                  int           User
y                   int          User

Properties Settings

ในที่นี้ เราจะให้ text เก็บค่าใน textbox ที่เคยพิมพ์ไว้ ส่วน x และ y จะเก็บค่าตำแหน่ง form ก่อนปิดหน้าต่างโปรแกรม เมื่อกำหนดเรียบร้อยแล้วให้ทำการบันทึกไฟล์ไว้ก่อน

จากนั้นทำการกำหนดและเขียนโค๊ดดังนี้

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace persistingForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.Manual;
        }

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            Properties.Settings.Default.text = textBox1.Text; // เก็บค่าสตริงจาก textbox1 ลงใน properties text
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.x = this.Location.X;
            Properties.Settings.Default.y = this.Location.Y;
            Properties.Settings.Default.Save(); // อย่าลืมสั่ง save ก่อนปิดโปรแกรม
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Location = new Point(Properties.Settings.Default.x, Properties.Settings.Default.y);
            textBox1.Text = Properties.Settings.Default.text;
        }
    }
}

ลองรันโปรแกรม ดูครับ แล้วลองเปรียบเทียบกับโปรแกรมก่อนๆ หน้านี้ดูครับ จะเห็นว่า โปรแกรมนี้ที่เราเขียนขึ้น จะมีการจดจำค่าก่อนปิดโปรแกรมตามที่เรากำหนดไว้ในโค๊ด  ลองเอาไปประยุกต์ดูครับ

ขอให้สนุกกับ .NET ครับ

อ้างอิง:  http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx

อ่านเพิ่มเติม...

Saturday, September 14

List video devices from PC by DirectShowLib

ในกรณีที่เราอยากทำให้ Application ของเราสามารถเลือกได้ว่าจะติดต่อกับกล้องตัวใน ถ้าเครื่องคอมพิวเตอร์ของเรามีมากกว่า 2 ตัว เราจะทำอย่างไร ถึงจะทำให้ application ที่เรากำลังสร้างนั้นมองเห็นกล้องทั้งหมดในเครื่องคอมพิวเตอร์เครื่องนั้นได้

วันนี้ผมจะแนะนำความสามารถของ Library ตัวหนึ่งชื่อ DirectShowLib ที่เอาไว้ดึงรายชื่อกล้องทั้งหมดที่ต่ออยู่ในเครื่องคอมพิวเตอร์ของเราออกมาเป็นตัวแปร array จากนั้นเราก็สามารถที่จะใช้ ComboBox ใช้แสดงรายชื่อกล้องทั้งหมด ไว้ให้ user เอาไว้เลือกต่อได้ ว่าจะติดต่อกับกล้องตัวไหน

อันดับแรก ก็ให้ไปดาวน์โหลด Library ตัวนี้ก่อนครับ อยู่ใน sourceforge ก็มี ดาวน์โหลดได้ที่นี่ http://sourceforge.net/projects/directshownet/files/ เมื่อดาวน์โหลดมาได้แล้ว เราต้องการไฟล์ DirectShowLib-2005.dll ที่อยู่ในโฟลเดอร์ \DirectShowLibV2-1\lib ของมัน

เรามาเริ่มสร้างโปรเจคกัน ในที่นี้ผมให้เป็น Windows Forms Application ที่เมนู Project เลือก Add reference หรือคลิกขวาที่ References ที่ ใต้ชื่อ Project เราที่ solution explorer ทำการ Browse หาไฟล์  DirectShowLib-2005.dll

image

สร้างหน้าต่าง form ตามรูป แล้วทำการเขียนโค๊ด (อันนี้ผมไม่บอกละเอียดแล้วนะ ถือว่า พอมีประสบการณ์กันบ้างหล่ะ)

image

เรามาดูที่โค๊ดกันครับ หัวใจของเรื่องนี้ ก็อยู่ตรงที่ เราสร้างตัวแปร object จาก Class DsDevice ที่อยู่ใน namespace ของ DirectShowLib (ฉะนั้นอย่าลืมที่ using DirectShowLib; ด้วยนะครับ)

ผมประกาศตัวแปร DsDevice[] videoDevices; ก่อน

จากนั้น ผมก็ทำการสร้างอินสแตนซ์จาก Class DsDevice แล้วก็เอามาวนลูปแสดงใน ComboBox


videoDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
if (videoDevices.Length == 0)
{
     throw new Exception();
}

for (int i = 1, n = videoDevices.Length; i <= n; i++)
{
     string cameraName = i + " : " + videoDevices[i - 1].Name;
     cameraCombo.Items.Add(cameraName);
}
cameraCombo.SelectedIndex = 0;

ทีเหลือก็ไม่มีอะไรมาก เอา index ที่ได้จากการเลือก combobox สร้างอินสแตนซ์ Capture แล้วก็โยนให้ picturebox แสดงผล

ลองดูโค๊ดเต็มๆ

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;

using DirectShowLib;

namespace AnyCameras
{
    public partial class Form1 : Form
    {
        DsDevice[] videoDevices;
        private Capture capture = null;

        public Form1()
        {
            InitializeComponent();
            timer.Interval = 100;

            // show device list
            try
            {
                videoDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
                if (videoDevices.Length == 0)
                {
                    throw new Exception();
                }

                for (int i = 1, n = videoDevices.Length; i <= n; i++)
                {
                    string cameraName = i + " : " + videoDevices[i - 1].Name;
                    cameraCombo.Items.Add(cameraName);
                }
                cameraCombo.SelectedIndex = 0;
            }
            catch
            {
                cameraCombo.Items.Clear();
                cameraCombo.Items.Add("No cameras found");
                cameraCombo.SelectedIndex = 0;
                cameraCombo.Enabled = false;
            }       
       
        }

        private void StartCamera()
        {
            capture = new Capture(cameraCombo.SelectedIndex);
            timer.Start();
        }

        private void StopCamera()
        {
            timer.Stop();
            if (capture != null)
            {
                capture.Dispose();
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            Image<Bgr, Byte> frame = capture.QueryFrame();
            cameraPictureBox.Image = frame.ToBitmap();
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            StartCamera();
            startButton.Enabled = false;
            stopButton.Enabled = true;
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            StopCamera();
            startButton.Enabled = true;
            stopButton.Enabled = false;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer.Stop();
            if (capture != null)
            {
                capture.Dispose();
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://vs-visual-studio.blogspot.com/");
        }

    }
}

 

ลองดาวน์โหลดโค๊ดไปเล่นกันครับ https://dl.dropboxusercontent.com/u/65353188/AnyCameras.zip

อ่านเพิ่มเติม...

Thursday, September 12

AdvancedHMI with Visual C# 2010

HMI หรือ Human Machine Interface คือ อุปกรณ์ที่ใช้ในการติดต่อระหว่่างผู้ใช้ กับ เครื่องจักร เพื่อใช้ในการควบคุมและการแสดงผล ผ่านทางหน้าจอ เรามักใช้ในการแสดงผลแบบกราฟฟิก ซึ่งส่วนใหญ่ จะแสดงผลในเชิงสัญลักษณ์ หรือไอค่อนที่เป็นตัวแทน เครื่องจักร ถังน้ำ ปั้ม วาล์วน้ำ มอเตอร์ไฟฟ้า และอื่นๆ ที่เป็นส่วนที่เราต้องการติดตามการทำงานของพวกมัน โดยจะแสดงสถานะ ค่าต่างๆ บนหน้าจอแสดงผล พร้อมกับโครงสร้างของระบบการทำงานที่เรายกมาแสดง
ในปัจจุบันมีโปรแกรมหลายๆ ค่ายที่สามารถแสดงผลแบบ HMI ได้ ซึ่งมีทั้งแบบที่ง่าย แต่เสียเงิน และแบบที่ยาก แต่ ฟรี ก็มี วันนี้ เรามาลองติดตั้ง AdvancedHMI กับ C# กันดูครับ
AdvancedHMI
เริ่มแรกก็ไปดาวน์โหลด AdvancedHMI จากที่นี่ http://advancedhmi.com/ จากนั้น ทำการแตกไฟล์ออก ไปวางไว้ที่ไหนก็ได้ครับ เพราะเราจะสนใจแค่ dll ไฟล์ของมัน
เปิดโปรแกรม Visual C# 2010 express ขึ้นมาครับ เริ่มสร้างโปรเจค ตามปกติ ในที่นี้ผมสร้างโปรเจคเป็น windows form application นะครับ
ต่อมาให้เราทำการ add toolbox ที่เป็นของ AdvancedHMI ขึ้นมา  อาจจะสร้าง Add tab ขึ้นมาแล้วตั้งชื่อ AdvancedHMI แล้วคลิกขวา Choose items.. ไปที่
Add components AdvancedHMI
แท๊ป .NET Framework Components ให้เรา Browse ไปที่เก็บไฟล์  AdvancedHMIBeta358\AdvancedHMIDrivers\Support\MfgControl.AdvancedHMI.Drivers.dll แล้วคลิกเลือก OK
AdvancedHMI components
เราจะได้ Components ที่ทาง AdvancedHMI สร้างมาให้
ทำการ Add reference MfgControl.AdvancedHMI.Drivers.dll เข้าไปกับโปรเจคด้วย
Add reference MfgControl.AdvancedHMI.Controls.dll
จากนั้น ก็ลาากวางๆ ได้เลยครับ จินตนาการเอาว่า เราจะสร้างระบบเฝ้าติดตามอะไร ในที่นี้ ผมสร้างระบบปั้มน้ำ โดยให้มอเตอร์ปั้มน้ำเข้าถัง หากระดับน้ำต่ำกว่า ระดับที่เราตั้งไว้ และมีวาล์วคอยปิดเปิดทางน้ำออก ซึ่งสามารถปรับอัตราการไหลได้
AdvancedHMI Form design
ที่ส่วนหัวของโค๊ด ให้ทำการ using MfgControl.AdvancedHMI.Controls; เข้าไปด้วย ถ้าต้องการสร้าง object เพิ่ม
ในการเขียนโค๊ดส่งค่าให้แต่ละ Component ไม่ว่าจะเป็น Guage , Tank  หรืออะไรก็ตามแต่ ที่มีการแสดงผล แสดงค่าต่างๆ ต้องเช็คให้ดีด้วย ว่ามันรับค่าเป็น float , int หรือว่า double ถ้าเราส่งค่าให้มันไม่ตรงชนิดที่มันจะรับ มันจะแสดงผลผิดพลาด ลองเอา mouse ชี้ค้างไว้ตอนเรา กำหนดค่า ให้ field ที่ชื่อ value ของมันดูครับ มันจะบอกไว้อยู่
image
AdvancedHMI object
ในที่นี้ ผมใช้ Timer 3 ตัวในการกำหนดจังหวะให้กับระบบ มาดูโค๊ดเต็มๆ กันเลยครับ
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MfgControl.AdvancedHMI.Controls;
namespace AdvanceHMI
{
    public partial class Form1 : Form
    {
        Random rnd = new Random();
        float waterActual = 100.0f;
        float flowrateIn = 2.0f;
        float flowrateOut = 2.0f;
       
        public Form1()
        {
            InitializeComponent();
            tank1.Value = waterActual;
            waterPump1.Value = false;
            txtWaterDetect.Text = "70";
            trackBar1.Value = 70;
            lbWaterLevel.Text = ((int)waterActual).ToString();
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true; // timer system
            timer2.Enabled = true; // timer water flow rate in
            timer3.Enabled = true; // timer water flow rate out
            timer1.Interval = 200;
            timer2.Interval = 200;
            timer3.Interval = 500;
            timer1.Start();
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            lbWaterLevel.Text = waterActual.ToString();
            if ((int)waterActual <100)
            {
                if ((int)waterActual <= trackBar1.Value)
                {
                    timer2.Start();
                    waterPump1.Value = true;
                }
               
            }
            else
            {
                timer2.Stop();
                waterPump1.Value = false;
            }
            if (pneumaticBallVave1.Value == true)
            {
                timer3.Start();
                pneumaticBallVave1.Value = true;
            }
            else
            {
                timer3.Stop();
                pneumaticBallVave1.Value = false;
            }
        }
        private void btnStop_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            timer2.Stop();
            timer3.Stop();
        }
        private void label1_Click(object sender, EventArgs e)
        {
        }
        private void timer3_Tick(object sender, EventArgs e)
        {
           
            waterActual = waterActual - flowrateOut;
            tank1.Value = waterActual;
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            waterActual = waterActual + flowrateIn;
            tank1.Value = waterActual;
        }
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            txtWaterDetect.Text = trackBar1.Value.ToString();
        }
        private void button1_Click(object sender, EventArgs e)
        {
        }
        private void pneumaticBallVave1_DoubleClick(object sender, EventArgs e)
        {
           
        }
        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            flowrateOut = (float)trackBar2.Value;
            label3.Text = trackBar2.Value.ToString();
        }
        private void pneumaticBallVave1_Click(object sender, EventArgs e)
        {
            pneumaticBallVave1.Value = !pneumaticBallVave1.Value;
        }
    }
}
ลองโหลดไฟล์ไปเปิดกันดูครับ ไม่รู้ว่าจะเปิดกันได้หรือเปล่า ถ้าไม่ได้ก็สร้างเอาใหม่ ก็แล้วกันครับ แลบลิ้น
https://dl.dropboxusercontent.com/u/65353188/AdvanceHMI.zip
อ่านเพิ่มเติม...
 

แจกฟรี พื้นที่ฝากไฟล์ 2 GB

ads

ติดตามข่าวสารผ่าน Twitter

ติดตาม Blog นี้

About Me

My photo

สวัสดีครับ ชื่อเปิ้ลนะครับ ถ้ามีอะไรให้ช่วยเหลือได้ ก็จะช่วยครับ
ผมได้สร้างบล๊อกไว้ เพื่อเก็บรวบรวมความรู้ และประสบการณ์ในการทำงานครับ แวะไปเยี่ยมชมกันได้ครับ http://mechacity.blogspot.com และบล๊อก http://faker-programmer.blogspot.com ครับ

Blog อื่นๆของฉัน

จำนวนการเยี่ยมชมบล๊อก