گفتگو هایی در باب سی شارپ

the_king

مدیرکل انجمن
ممنون استاد علی
میگم null کردن یه آرایه یا یک ArrayList در سی شارپ چجوری هه؟
الان مثلا یه ArrayList اگه هیچ چی توش نرفت (یه تابعی که ArrayList رو برمیگردونه ، هیچ مقداری رو توش نزاشت) ، در این صورت میخوام null رو برگردونه و اون شی و متغییری که این ArrayListاز تابع رو هم برمیگردونه رو میخوام بگم اگه null برنگردوند کارشو ادامه بده . باید چی بنویسم؟
من الان بجای قضیه ی null فقط میتونم بگم که چک کن و ببین اگه تعداد اعضای ArrayList صفر نبود ، کار رو ادامه بده
ArrayList کلاس ئه و null پذیر.
کد:
        private ArrayList GetArrayList()
        {
            return null;
        }

            ArrayList a = GetArrayList();
            if (a == null)
            {

            }
            else
            {

            }

درباره ی جواب آرایه های چند بعدی ای که تعداد عضوشونو نمیدونیم ، به نظرم بهتره از آرایه ای از ArrayList ها استفاده بشه . درسته؟
خود ArrayList که به عنوان آرایه عمل میکنه اما اگه چند بعدی خواستیم ، آرایه ای از ArrayList ها درست کنیم فکر کنم به جواب مون برسیم (یا حتی آرایه ی چند بعدی از ArrayList ها درست کنیم)
شدنش میشه فقط دقت کنید که تعداد ستون های هر سطر مستقل از سطر های دیگه است چون هر کدوم یک ArrayList متغیر ئه. و باز هم تاکید می کنم که List بهتر از ArrayList ئه، مگر زمانی که اعضاء از یک نوع داده یکسان نباشند.

درباره ی کپی کردن هم انگار بهتر روش برای trace کردن HashTable ها ، حلقه ی foreach هه (نه حلقه ی for)
فقط توی مثال هایی که پیدا کردم ، نمیدونم چرا شی item رو از نوع DictionaryEntry میگیرن؟ یعنی کسی که اینو نمیدونه از کجا باید تشخیص بده؟ همیشه کلاسی که برگردونده میشد توسط اعضای آرایه ، برای شی item در نظر گرفته میشد یعنی اینجا اگه طبق روش مرسوم پیش میرفت ، باید کلاس object ها میبود!! :


کد:
int[] myArr=new int[10];
            SortedList abc = new SortedList();
            abc[5] = 456;
            abc[0] = 97;
            abc[3] = 521;
            abc[8] = -28;
            abc[6] = 689;
            abc[2] = 101;
            abc[9] = -10;
            abc[1] = 0;
foreach (DictionaryEntry item in abc)
            {
                MessageBox.Show("key : " + item.Key + "\nvalue : " + item.Value);
            }
SortedList یک Dictionary ئه چون از اینترفیس IDictionary ارث بری می کنه، طبق تعریف IDictionary اون enumerator که شما با foreach ازش استفاده می کنید با نوع DictionaryEntry سازگاره. روی اسم هر کلاسی کلید F12 رو بزنید ساختار اش رو می بینید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
پس میشه کلاس هایی که از هم ارث بری کرد رو توی foreach از همه شون استفاده کرد . البته برای کنترل ها هم همین کار رو میکردیم اما الان بهتر درک کردم :)

----------------------------

میگم استادمون یه پروژه ی کوچیک گفت ، پروژه ی اسبی که جوری حرکت کنه که تمام خونه های شطرنج رو بدون تکرار بره . گفتم بد نیست اینجا هم بزارم ، پروژه ی قشنگی هه به نظرم
البته سودوکدش رو استاد گفت ولی من درک نکردم چرا؟!!! گفت برای دیدن تمام خونه ها ، اسب توی هر خونه ای که هست ، باید دید خونه های بعدی اش که میخواد بره ، هر کدوم از اون خونه ها ، چند تا خونه ی دیگه میتونن برن و بره توی خونه ای که کمترین تعداد خونه رو میتونه بره .
کلا نفهمیدم چرا کمترین تعداد خونه رو گفت ولی پروژه درست از آب در اومد .

اینم کدش که پروژه ی جالبی هه (چون توی یه پست همه ی کدها جا نمیگیره ، توی چند پست میزارم) :


کد:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Harkate_Asb
{
    public partial class Form1 : Form
    {
        #region//متغییرهای سراسری
        private Label[] chessCell = new Label[65];//از شماره 1 شروع میشن
        private int formWidth, formHeight;
        private int cellHorseInto = 1;//شماره سلولی که اسب توی اون خونه هست
        private int[] cellsLeftHorse = new int[65];//شماره خونه هایی که اسب از توشون رد شد
        private int counter = 2;//شمارنده برای ایندکس آرایه ی cellsLeftHorse _ دو شماره ی اول در رویداد فرم لود مقداردهی شدن
        private PictureBox picboxHorse;

        #endregion
        //----------------------------
        #region//رویدادها
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CreateChessCells();
            InitializeForm();
            HorseMoveTimer.Interval = 1000;
            cellsLeftHorse[0] = 0;
            cellsLeftHorse[1] = cellHorseInto;
            HorseMoveTimer.Enabled = true;
        }

        private void HorseMoveTimer_Tick(object sender, EventArgs e)
        {
            int cellsCountCapableGo;
            ArrayList cellsCapableGo = this.GetCellsCapableGo(cellHorseInto, out cellsCountCapableGo);
            if (cellsCapableGo != null && cellsCountCapableGo > 0)
            {
                int cellNumberHorseMustMove = this.CellNumberHorseMustMove(cellsCapableGo);
                if (cellNumberHorseMustMove > 0)
                {
                    this.CreateMarker(cellHorseInto);

                    cellHorseInto = cellNumberHorseMustMove;
                    cellsLeftHorse[counter] = cellHorseInto;
                    counter++;

                    picboxHorse.Location = new Point(chessCell[cellHorseInto].Left + 10, chessCell[cellHorseInto].Top + 10);
                }
            }
            else
            {
                HorseMoveTimer.Enabled = false;
                MessageBox.Show("همه ی خونه ها طی شدند");
            }
        }
        #endregion

        #region//متدهای تعریف شده توسط کاربر
        //----------------------------

        /// <summary>
        /// شماره خونه ای که اسب باید در حرکت بعدی اونجا بره رو برمیگردونه _ یعنی خونه ای که اسب کمترین جابجایی رو داره
        /// </summary>
        /// <param name="cellsNumberCapableGo"></param>شماره خونه هایی که اسب میتونه به اون خونه ها بره
        /// <returns></returns>
        private int CellNumberHorseMustMove(ArrayList cellsNumberCapableGo)
        {
            Hashtable cellsCountCapableGo = new Hashtable();//شماره ی خونه هایی که اسب در حرکت بعدی میتونه بره در ایندکسر کلید و تعداد خونه هایی که اسب از هر کدوم از اون خونه ها مینونه بره ، در ایندکسر وَلیو این هش تیبل ذخیره میشه
            int cellNumberHorseMustMove = 0;//مقدار بازگشتی نهایی تابع که شماره ی خونه ای که اسب ، کمترین میزان تحرک رو در اون خونه داره رو برمیگردونه
            int cellCountTemp;//تعداد خونه هایی که اسب در خونه ی خاصی میتونه (به خونه های دیگه) بره


            if (cellsNumberCapableGo.Count <= 1)//اگه تعداد خونه ای که اسب میتونه بره ، یکی خونه بیشتر نبود یعنی خونه ی آخر هست و دیگه بقیه ی چیزا رو حساب نکن و فقط همون اولین عضو خونه ی آرایه ای که شماره خونه توش هست رو برگردون
            {
                cellNumberHorseMustMove = ((int)cellsNumberCapableGo[0]);
                return cellNumberHorseMustMove;
            }

            foreach (object _cellsNumberNextGo in cellsNumberCapableGo)//به تعداد اعضای اری لیست (که شماره خونه هایی که اسب میتونه بره هست) ، دوباره تعداد خونه هایی که هر کدوم از این اعضا (شماره خونه ها) میتونن برن رو حساب میکنه
            {
                GetCellsCapableGo((int)_cellsNumberNextGo, out cellCountTemp);
                if (cellCountTemp > 0)
                {
                    cellsCountCapableGo.Add((int)_cellsNumberNextGo, (int)cellCountTemp);//بعد از حساب کردن در هش تیبل، کلیدش رو شماره ی خونه و مقدارش رو تعداد خونه هایی که اسب میتونهبره ، میریزه
                }
            }

            int[] cellsCountCopyTemp = new int[cellsCountCapableGo.Count];
            cellsCountCapableGo.Values.CopyTo(cellsCountCopyTemp, 0);//ایندکسر مقدار (ولیو) هش تیبل رو داخل آرایه بصورت موقت برای پیدا کردن کمنرین مقدارش میریزه
            int minimumValue = cellsCountCopyTemp.Min();//کمترین مقدار رو پیدا میکنه
            foreach (DictionaryEntry item in cellsCountCapableGo)
            {
                if (((int)item.Value) == minimumValue)
                {
                    cellNumberHorseMustMove = ((int)item.Key);//شماره ی کلید اون کمترین مقدار (ولیو) رو پیدا که همون مقدار بازگشتی تابع هست
                    break;
                }
            }

            return cellNumberHorseMustMove;//اگه خطا بده 0 وگرنه بزرگتر از 0 رو برمیگردونه
        }

        /// <summary>
        /// شماره ی خونه هایی که اسب میتونه توش بره _ بدون تکرار خونه هایی که رفت
        /// </summary>
        /// <param name="cellNumber"></param>شماره خونه ای که اسب در حال حاضر در اون هست برای محاسبه ی خونه هایی که میتونه ببینه
        /// <param name="numberCellsCapableGo"></param>مقدار بازگشتی دوم تعداد خونه هایی که اسب بدون تکرار میتونه بره
        /// <returns></returns>

        private ArrayList GetCellsCapableGo(int cellNumber, out int cellsCountCapableGo)///////cellNumber=36
        {
            ArrayList cellsCapableSee = GetCellsCapableSee(cellNumber);
            ArrayList cellsCapableGo = new ArrayList(9);
            foreach (object _cellsCapableSee in cellsCapableSee)
            {
                if (cellsLeftHorse.Contains((int)_cellsCapableSee) == false)
                {
                    cellsCapableGo.Add((int)_cellsCapableSee);
                }
            }


            if (cellsCapableGo.Count>0)
            {
                cellsCountCapableGo = cellsCapableGo.Count;
                return cellsCapableGo;
            }
            else
            {
                cellsCountCapableGo = 0;
                return null;
            }
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اینم ادامه اش :

کد:
        /// <summary>
        /// تمام سلول هایی که توی خونه ای که اسب وجود داره و اسب میتونه اون خونه ها رو ببینه رو برمیگردونه
        /// </summary>
        /// <param name="cellNumber"></param>شماره خونه ای که اسب در حال حاضر در اون هست برای محاسبه ی خونه هایی که میتونه ببینه
        /// <returns></returns>
        private ArrayList GetCellsCapableSee(int cellNumber)
        {
            int[] cellsChecking = { 0, -17, -15, -10, -6, 6, 10, 15, 17};//تمام خونه هایی که یک اسب به نسبت اونجایی (نسبت به اون خونه ای) که هست میتونه بره
            int row4CurrentCellNumber = ((cellNumber - 1) / 8) + 1;//شماره ی سطر اون خونه ای که اسب فعلا در اون خونه هست رو بگیر _شماره سطر با تقسیم و شماره ستون با هم باقی مانده بدست میاد
            ArrayList cellsCapableSee = new ArrayList(9);//شماره ی خونه هایی که اسب میتونه نسبت به اون خونه ای که توش هست رو ببینه ، در مقدار بازگشتی تابع توی اری لیست ریخته میشه
           
            for (int i = 1; i < cellsChecking.GetLength(0); i++)//هشت بار حلقه رو برای چک کردن هر خونه به نسبن اون خونه ای که اسب توش هست ، تکرار میکنه
            {
                int rangeCellsChecking = cellNumber + cellsChecking[i];
                if (rangeCellsChecking >= 1 && rangeCellsChecking <= 64)//اگه خونه هایی که اسب میتونه بره ، توی رنج صفحات شطرنج یعنی بین خونه ی 1 تا 64 بود ، کار رو ادامه میده
                {
                    int row4cellsChecking = ((rangeCellsChecking - 1) / 8) + 1;//شماره ی سطر اون خونه ای که اسب قراره توشون بره رو میگیره _شماره سطر با تقسیم و شماره ستون با هم باقی مانده بدست میاد
                    switch (cellsChecking[i])
                    {
                        case -17://اگه خونه های شماره 17 یا 15 تا کمتر، قراره اسب بره و اون خونه ها 2 سطر بالاتر از سطری که اسب هست ، هستن ، پس اون خونه رو اسب میتونه توش بره
                        case -15:
                            if (row4CurrentCellNumber - 2 == row4cellsChecking)
                            {
                                cellsCapableSee.Add(rangeCellsChecking);
                            }
                            break;
                        case -10://اگه خونه های شماره 17 یا 15 تا کمتر، قراره اسب بره و اون خونه ها 1 سطر بالاتر از سطری که اسب هست ، هستن ، پس اون خونه رو اسب میتونه توش بره
                        case -6:
                            if (row4CurrentCellNumber - 1 == row4cellsChecking)
                            {
                                cellsCapableSee.Add(rangeCellsChecking);
                            }
                            break;
                        case 6://اگه خونه های شماره 17 یا 15 تا کمتر، قراره اسب بره و اون خونه ها 1 سطر پایین تر از سطری که اسب هست ، هستن ، پس اون خونه رو اسب میتونه توش بره
                        case 10:
                            if (row4CurrentCellNumber + 1 == row4cellsChecking)
                            {
                                cellsCapableSee.Add(rangeCellsChecking);
                            }
                            break;
                        case 15://اگه خونه های شماره 17 یا 15 تا کمتر، قراره اسب بره و اون خونه ها 2 سطر پایین تر از سطری که اسب هست ، هستن ، پس اون خونه رو اسب میتونه توش بره
                        case 17:
                            if (row4CurrentCellNumber + 2 == row4cellsChecking)
                            {
                                cellsCapableSee.Add(rangeCellsChecking);
                            }
                            break;
                    }
                }
                else//وگرنه(اگه توی رنج صفحات شطرنج و بین خونه های 1 تا 64 نبود) دفعه ی بعد حلقه رو اجرا کنه
                    continue;
            }

            return cellsCapableSee;
        }

        /// <summary>
        /// تنظیمات اولیه ی فرم مثل اندازه و وضعیت قرارگیری در صفحه و متن و ... رو انجام میده
        /// </summary>
        private void InitializeForm()
        {
            this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            this.Size = new Size(formWidth, formHeight);
            this.Text = "Move Horse Project";
            this.MaximizeBox = false;
            this.StartPosition = FormStartPosition.Manual;
            int formPosationX = (Screen.PrimaryScreen.Bounds.Width/2)-(this.Width/2);
            int formPosationY = (Screen.PrimaryScreen.Bounds.Height / 2) - (this.Height / 2);
            this.Location = new Point(formPosationX,formPosationY);

            //create picture box
            picboxHorse = new PictureBox();
            picboxHorse.Image = Image.FromFile(Application.StartupPath + "\\Horse.png");
            picboxHorse.Size = new Size(80, 80);
            picboxHorse.SizeMode = PictureBoxSizeMode.Zoom;
            picboxHorse.Location = new Point(chessCell[cellHorseInto].Left + 10, chessCell[cellHorseInto].Top + 10);//تعیین مکان جای اسب _بصورت پیش فرض در خانه شماره اول
            this.Controls.Add(picboxHorse);
            picboxHorse.BringToFront();//حتما باید بعد از اضافه کردن شی به صفحه ، این تابع را برای جلو اومدن نسبت به همه ی اشیاء های دیگه نوشت نه قبل از اضافه کردن شی به صفحه
        }

        /// <summary>
        /// ایجاد لیبل به عنوان نشونه روی خونه هایی که رد شده
        /// </summary>
        /// <param name="cellHorseInto"></param>خونه ای که اسب در حال حاضر توی اون هست
        private void CreateMarker(int cellHorseInto)
        {
            Label lblMarker = new Label();
            lblMarker.AutoSize = false;
            lblMarker.Visible = true;
            lblMarker.BackColor = Color.Tomato;
            lblMarker.Size = new Size(80, 80);
            lblMarker.Location = new Point(chessCell[cellHorseInto].Left + 10, chessCell[cellHorseInto].Top + 10);
            this.Controls.Add(lblMarker);
            lblMarker.BringToFront();//حتما باید بعد از اضافه کردن شی به صفحه ، این تابع را برای جلو اومدن نسبت به همه ی اشیاء های دیگه نوشت نه قبل از اضافه کردن شی به صفحه
        }

        /// <summary>
        /// ایجاد 64 تا لیبل به عنوان سلول های شطرنج و رنگ بندی و چیدمان آنها
        /// </summary>
        private void CreateChessCells()
        {
            //MessageBox.Show("Left : " + label1.Left + "\nRight : " + label1.Right + "\nTop : " + label1.Top + "\nBottom : " + label1.Bottom);
            Point startPosition = new Point(10, 10);
            int positionY = 9;
            Color currentColor = Color.White;

            for (int i = 1; i < chessCell.GetLength(0); i++)
            {
                //----------------------------ایجاد و اضافه کردن لیبل(سلول شطرنج) به فرم
                chessCell[i] = new Label();
                chessCell[i].Size = new Size(100, 100);
                this.Controls.Add(chessCell[i]);
                //----------------------------رنگ بندی کردن سلول ها
                if (i != 1 && i % 8 == 1)//رنگ اولین سلول در شروع هر سطر ، با رنگ اولین سلول در شروع سطر قبلی ، از هم متفاوت باشه
                {
                    if (currentColor == Color.White)
                        currentColor = Color.Black;
                    else
                        currentColor = Color.White;
                }

                if (i % 2 == 0)//در هر سطر ، سلول ها را یکی در میون سیاه و سفید میکنه
                    if (currentColor == Color.White)
                        chessCell[i].BackColor = Color.Black;
                    else
                        chessCell[i].BackColor = Color.White;
                else
                    chessCell[i].BackColor = currentColor;
                //----------------------------چیدمان سلولها
                if (i != 1)//قرار دادن موقعیت بقیه ی سلول ها بجز سلول اولی
                {
                    if (i % 8 != 1)//هر 8 تا درمیون (خونه ی بعد از ضریب 8 مثل خونه ی نهمی و هفدهمی و ...) سلول ها رو کنار هم بچین
                        chessCell[i].Location = new Point(chessCell[i - 1].Right, positionY);
                    else//وگرنه به یکی بعد از ضریب 8 که رسیدی (یعنی خونه ی نهمی و هفدمی و ...) وضعیت ایگرگ اش رو بیار پایین سطر قبلی
                    {
                        positionY = chessCell[i - 1].Bottom;
                        chessCell[i].Location = new Point(10, positionY);
                    }
                }
                else//اولین سلول رو در موقعیت 10 و 10 قرار بده
                    chessCell[i].Location = startPosition;

                //----------------------------مقداردهی متغییرهای سراسری برای تعیین اندازه ی فرم
                if (i == 8)//از لحاظ عرض ، 10 تا بعد از خونه ی شماره ی 8 ، رو عرض فرم رو مشخص کن
                {
                    int borderFormWidth = this.Width - this.ClientSize.Width;
                    int clientFormWidth = chessCell[i].Right + 10;
                    formWidth = clientFormWidth + borderFormWidth;
                }
                else if (i == 64)//از لحاظ طول ، 10 تا بعد از خونه ی شماره ی 64 ، رو طول فرم رو مشخص کن
                {
                    int borderFormHeight = this.Height - this.ClientSize.Height;
                    int clientFormHeight = chessCell[i].Bottom + 10;
                    formHeight = clientFormHeight + borderFormHeight;
                }
                   
            }
        }
        #endregion

        //----------------------------end class
    }
}
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
استاد علی ، هر چند درباره ی رویداد کیبردها صحبت کردیم و گفته هاتون رو مرور کردم ولی الان نمیدونم توی رویداد Form1_KeyDown چرا کد زیر عمل نمیکنه :

کد:
private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == (Keys.Shift))
            {
                MessageBox.Show("kay(s) pressed");
            }
        }

با مرور بحث ها و کدهای گذشته که دادین ، فهمیدم که با
کد:
comboBox1.Parent = this;
هم میشه علاوه بر پرنت کردن کنترل ، یه کنترلی رو به یه کانتینر و فرم ، اضافه کرد (فکر میکردم فقط با پروپرتی Controls یه کانتینر میشه

دارم این پست تون رو هم بررسی میکنم
کد قسمت :

کد:
            [System.Runtime.InteropServices.DllImport("winmm.dll")]
        private static extern long mciSendString(string strCommand, StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback);

        public void Play(string filename)
        {
            mciSendString(string.Format("open \"{0}\" type mpegvideo alias MediaFile", filename), null, 0, IntPtr.Zero);
            mciSendString("play MediaFile", null, 0, IntPtr.Zero);
        }

که دادین ، هنوزم برام درکش آسون نیست
من فهمیدم با متد DllImport که در فضای نام System.Runtime.InteropServices در فایل winmm.dll هست ، میشه با این متد ، یک فایل حاوی کدهای Unmanaged رو پیوست کرد (چون این فایل winmm.dll ، فایل api ای که با ++C نوشته شد و Unmanaged هست) به پروژه و برای کدهای Unmanaged فقط باید از این متد پیوست کرد نه بصورت معمولی و با add reference کردن
اولین مشکلم توی خط دوم هه . انگار میخواین تابعی بنام mciSendString که در فایل winmm.dll تعریف شده هست رو فراخونی کنین . خوب اما توی خط دوم انگار دارین هدر تابع رو تعریف میکنین (چون نوشتین private static long) . چرا؟ برای فراخونی که دیگه تعیین سطح دسترسی و ... نمیخواد
حالا توجیه سطح دسترسی و این ها که دلخواهی هست دیگه. درسته؟ یعنی سطح دسترسی private و static بودن اش و ... که گرفتین
IntPtr چیه توی آرگومان چهارم تابع؟
بعد حالا چرا توی ورودی تابع play ، تابع mciSendString رو دو بار فراخونی کردین؟
کلا تا حالا کدهای Unmanaged رو فراخونی نکردم و روش کلی فراخونی شم توضیح بدیم ، ممنون میشم
علاوه بر این ، کمپوننت Managed ای ، چیزی برای سی شارپ وجود نداره برای لود mp3 ها؟ (بجز کلاس windows media player)

علاوه بر این ، ممنون میشم مهم ترین کمپوننت ها و پلاگین های کاربردی برای سی شارپ و اینکه توضیح مختصری برای اینکه هر کدوم شون به درد چه مواردی میخورن بدین
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
این چرا کار نمیکنه ؟ توی کلاس فرم 1 نوشتم :

کد:
[DllImport("User32.dll", EntryPoint = "MessageBox", CharSet = CharSet.Unicode)]
        public static extern int MessageBoxApi(IntPtr hWnd, string text, string caption, uint type);

و توی رویداد نوشتم :

کد:
private void button14_Click(object sender, EventArgs e)
        {
            Process[] processList = Process.GetProcesses();
            foreach (var singleProcess in processList)
            {
               
                if (singleProcess.MainWindowTitle.Contains("Task"))
                {
                    MessageBoxApi(singleProcess.MainWindowHandle, "salam", "title", (4 | 16384));
                }
            }
        }

میخوام هر وقت تسک منیجر بالا بود ، پنجره ی پیام به تسک منیجر متصل بشه
اصلا چنین امکانی وجود داره؟
 

the_king

مدیرکل انجمن
سلام
استاد علی ، هر چند درباره ی رویداد کیبردها صحبت کردیم و گفته هاتون رو مرور کردم ولی الان نمیدونم توی رویداد Form1_KeyDown چرا کد زیر عمل نمیکنه :

کد:
private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == (Keys.Shift))
            {
                MessageBox.Show("kay(s) pressed");
            }
        }
دلیلش اینه که KeyData شامل تمامی اطلاعات کلید فشرده است، اگر با عملگر == کار می کنید باید تمامی اطلاعات کلید رو بدهید، اگر اطلاعات ناقص باشد شرط == برقرار نخواهد بود. نکته ای که در نظر نگرفته اید اینه که کلید Shift جزو کلید های Modifiers است که شامل Shift, Control , Alt ئه. وقتی این کلید ها رو فشار بدهید علاوه بر کد خود کلید کد Modifier شون هم ارسال میشه. مثلا اگر Shift رو فشار بدید بجز Keys.ShiftKey که خود کلید ئه Keys.Shift که Modifier اش هم در KeyData قرار می گیره.

کد:
            if (e.KeyData == (Keys.Shift | Keys.ShiftKey))
            {
                MessageBox.Show("kay(s) pressed");
            }

با مرور بحث ها و کدهای گذشته که دادین ، فهمیدم که با
کد:
comboBox1.Parent = this;
هم میشه علاوه بر پرنت کردن کنترل ، یه کنترلی رو به یه کانتینر و فرم ، اضافه کرد (فکر میکردم فقط با پروپرتی Controls یه کانتینر میشه

دارم این پست تون رو هم بررسی میکنم
کد قسمت :

کد:
            [System.Runtime.InteropServices.DllImport("winmm.dll")]
        private static extern long mciSendString(string strCommand, StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback);

        public void Play(string filename)
        {
            mciSendString(string.Format("open \"{0}\" type mpegvideo alias MediaFile", filename), null, 0, IntPtr.Zero);
            mciSendString("play MediaFile", null, 0, IntPtr.Zero);
        }

که دادین ، هنوزم برام درکش آسون نیست
من فهمیدم با متد DllImport که در فضای نام System.Runtime.InteropServices در فایل winmm.dll هست ، میشه با این متد ، یک فایل حاوی کدهای Unmanaged رو پیوست کرد (چون این فایل winmm.dll ، فایل api ای که با ++C نوشته شد و Unmanaged هست) به پروژه و برای کدهای Unmanaged فقط باید از این متد پیوست کرد نه بصورت معمولی و با add reference کردن
اولین مشکلم توی خط دوم هه . انگار میخواین تابعی بنام mciSendString که در فایل winmm.dll تعریف شده هست رو فراخونی کنین . خوب اما توی خط دوم انگار دارین هدر تابع رو تعریف میکنین (چون نوشتین private static long) . چرا؟ برای فراخونی که دیگه تعیین سطح دسترسی و ... نمیخواد
حالا توجیه سطح دسترسی و این ها که دلخواهی هست دیگه. درسته؟ یعنی سطح دسترسی private و static بودن اش و ... که گرفتین
IntPtr چیه توی آرگومان چهارم تابع؟
بعد حالا چرا توی ورودی تابع play ، تابع mciSendString رو دو بار فراخونی کردین؟
کلا تا حالا کدهای Unmanaged رو فراخونی نکردم و روش کلی فراخونی شم توضیح بدیم ، ممنون میشم
علاوه بر این ، کمپوننت Managed ای ، چیزی برای سی شارپ وجود نداره برای لود mp3 ها؟ (بجز کلاس windows media player)
DllImport فراخوانی نمی کنه، تعریف می کنه. در اون خط دوم ما mciSendString رو تعریف می کنیم، نه فراخوانی. در نظر بگیرید که اگر اینکار رو نکنید کامپایلر نه winmm.dll رو می شناسه و نه mciSendString و نمیدونه چه پارامتر هایی و از چه نوعی داره. شما تعریف اش می کنید و بعد مشخص می کنید که کد mciSendString اینجا نیست و برای اجرا شدنش کامپایلر بره سراغ فراخوانی از فایل winmm.dll و طبق تعریف کتابخانه های dll عمل کنه.
و در تعریف کردن هر متدی شما سطح دسترسی خواهید داشت، در مورد static بودن و نبودن هم دست تون باز نیست، شما دارید متدی رو معرفی می کنید که در کد خودتون نیست و در یک کتابخانه خارج از برنامه تونه، ربطی به اشیاء کلاس شما نداره که برای هر شیء یک نسخه اش ایجاد بشه، بنابر این کامپایلر شما رو وادار می کنه static تعریف اش کنید، یعنی مستقل از اشیاء کلاس. اگر بخواهید خارج از کلاس به متد دسترسی داشته باشید می توانید public اش تعریف کنید ولی static بودنش به هر حال اجباری ئه. IntPtr اشاره گر تعریف شده برای NET. ئه، در #C اشاره گر ها بصورت مستقیم تعریف نمی شوند چون کاربرد داخل زبانی نداره ولی برای کار با محیط Unamanaged خارج از NET. مثل این کتابخانه های DLL اشاره گر لازم میشه، IntPtr برای همین کاربرد ها تعریف شده تا کامپایلر برای ارتباط با محیط Unmanaged ازش استفاده کنه. هر NET. توابعی که چیزی رو از اشاره گر به داده خاصی تبدیل می کنند یا برعکس از این IntPtr استفاده می کنند.


منطق برنامه این بوده که دو تا فرمان mciSendString لازم داشته، ربطی به نحوه فراخوانی اش نداره، در مرحله اول یه فایلی رو باز می کنیم و در مرحله بعد play اش می کنیم، دو مرحله است برای همین دو تا دستور mciSendString لازم داشته، شاید یک کدی داشته باشید که توش ده تا فراخوانی mciSendString باشه، تعدادش ربطی به نحوه فراخوانی mciSendString نداره.

تعداد پلیر های MP3 ئه که ActiveX باشند خیلی زیاده، هر کسی ممکنه یه دونه ساخته باشه که بین رایگان ها معروف ترین شون همون Windows Media Player ئه ولی هسته و موتور mp3 Player ها زیاد نیست چون مجوز شون برای طراح شون رایگان نیست، چند تا موتور mp3 player شناخته شده بیشتر نمیشناسم. بعضی هاشون احتمالا بر اساس Un4seen BASS خواهند بود.
علاوه بر این ، ممنون میشم مهم ترین کمپوننت ها و پلاگین های کاربردی برای سی شارپ و اینکه توضیح مختصری برای اینکه هر کدوم شون به درد چه مواردی میخورن بدین
در اینترنت سایت های زیادی هستند که کارشون معرفی کمپوننت های ActiveX و DLL ئه که هزاران مورد رو شامل میشه. گردآوری همچین اطلاعات مختصری سالها طول می کشه و بی فایده هم هست چون خودش ده ها جلد کتابه.
 

the_king

مدیرکل انجمن
سلام
این چرا کار نمیکنه ؟ توی کلاس فرم 1 نوشتم :

کد:
[DllImport("User32.dll", EntryPoint = "MessageBox", CharSet = CharSet.Unicode)]
        public static extern int MessageBoxApi(IntPtr hWnd, string text, string caption, uint type);

و توی رویداد نوشتم :

کد:
private void button14_Click(object sender, EventArgs e)
        {
            Process[] processList = Process.GetProcesses();
            foreach (var singleProcess in processList)
            {
            
                if (singleProcess.MainWindowTitle.Contains("Task"))
                {
                    MessageBoxApi(singleProcess.MainWindowHandle, "salam", "title", (4 | 16384));
                }
            }
        }

میخوام هر وقت تسک منیجر بالا بود ، پنجره ی پیام به تسک منیجر متصل بشه
اصلا چنین امکانی وجود داره؟
کار که می کنه، اما اینکه چیکار باید بکنه مهمه، وقتی اون دکمه رو فشار دادید در پنجره اصلی پروسه ها دنبال عنوان Task می گرده و برای هر مورد مطابقت یک پیغام نمایش میده.
اگر بخواهید موقع بالا اومدن تسک منیجر متوجه این رخداد بشوید بهترین کار اینه که با تایمر متوجه اش بشوید ولی برای اینکه پنجره Task manager رو پیدا کنید یا اینکه بدانید در حال نمایش ئه یا Minimize شده توابع بهتری هست و لازم نیست تمامی پروسه ها رو یکی یکی بررسی کنید.
کد:
        [StructLayout(LayoutKind.Sequential)]
        private struct POINTAPI
        {
            internal int x;
            internal int y;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            internal int Left;
            internal int Top;
            internal int Right;
            internal int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct WINDOWPLACEMENT
        {
            internal int Length;
            internal int flags;
            internal int showCmd;
            internal POINTAPI ptMinPosition;
            internal POINTAPI ptMaxPosition;
            internal RECT rcNormalPosition;
        }

        private const int SW_SHOWMINIMIZED = 2;

        [DllImport("User32.dll", EntryPoint = "MessageBox", CharSet = CharSet.Unicode)]
        public static extern int MessageBoxApi(IntPtr hWnd, string text, string caption, uint type);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Unicode)]
        private static extern IntPtr FindWindowEx(int hWndParent, int hWndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll")]
        private static extern int GetWindowPlacement(IntPtr hwnd, ref WINDOWPLACEMENT lpwndpl);

        private void button14_Click(object sender, EventArgs e)
        {
            var hwnd = FindWindowEx(0, 0, "#32770", "Windows Task Manager");
            if (hwnd != IntPtr.Zero)
            {
                var placement = new WINDOWPLACEMENT();
                if (GetWindowPlacement(hwnd, ref placement) != 0)
                {
                    if ((placement.showCmd & SW_SHOWMINIMIZED) != SW_SHOWMINIMIZED)
                    {
                        MessageBoxApi(hwnd, "salam", "title", (4 | 16384));
                    }
                }
            }
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی دوباره استاد علی
ممنون از جوابتون . خیلی بیشتر متوجه شدم
درباره ی کیبرد ،
ولی من نفهمیدم چرا با e.KeyCode این مشکل رو نداره!
ولی کد


کد:
if (e.KeyCode==(Keys.ShiftKey | Keys.S))

اینبار با KeyCode که بنویسیم ، فقط با زدن دکمه ی S به تنهایی هم جواب میده!
حالا میخواد شیفت هم همراش نگه داشته باشیم یا نه!
چرا KeyCode با KeyData این فرق رو دارن؟


درباره ی سئوال Task Manager هم ، من نمیخوام وقتی تسک منیجر بالا اومد ، چیزی رو متوجه شم
میخوام با اون کد ، تسک منیجر رو که خودم از قبل بصورت دستی بالا آوردم ، وقتی پیامی داد ، اون پیام بجای اینکه متصل بشه به فرم خودم (حالت انتظار برای پیام که تا پیام بسته نشه ، فرم اصلی در دسترس نیست) ، به پنجره ی Task Manager متصل بشه یعنی پیام تا بسته نشد ، اجزا و اشیاء در داخل پنجره ی Task Manager رو نشه کلیک کرد و کلا در دسترس نباشه
ولی کد بالا پنجره ی پیام رو به پنجره ی Task Manager متصل نمیکنه. چرا؟
بجز این ، میشه با متد MessageBox.Show خود ویژال استودیو این کار رو کرد؟ یعنی هندل ویندوزی رو داد و پیام به اون ویندوز بچسبه و متصل بشه؟
 

the_king

مدیرکل انجمن
سلامی دوباره استاد علی
ممنون از جوابتون . خیلی بیشتر متوجه شدم
درباره ی کیبرد ،
ولی من نفهمیدم چرا با e.KeyCode این مشکل رو نداره!
ولی کد


کد:
if (e.KeyCode==(Keys.ShiftKey | Keys.S))

اینبار با KeyCode که بنویسیم ، فقط با زدن دکمه ی S به تنهایی هم جواب میده!
حالا میخواد شیفت هم همراش نگه داشته باشیم یا نه!
چرا KeyCode با KeyData این فرق رو دارن؟
قبلا در مورد KeyCode و KeyData وتفاوت شون صحبت کرده ایم، باز هم تکرار می کنم، KeyCode اطلاعات یک کلید فشرده شده است که باعث فراخوانی این رخداد شده و KeyData اطلاعات تمامی کلید هایی است که الان در حالت فشرده قرار دارند. کد کلید Keys.S عدد 83 است و کد کلید Keys.ShiftKey هم 16 است، شما اینها را که دو تا کلید جدا و مستقل هستند رو با هم or کرده اید و به عدد 83 رسیده اید که کد همان کلید Keys.S است.
اینکه 83 | 16 برابر 83 است ربطی به خاص بودن KeyCode ندارد، یک عملیات بیتی است. عدد 83 بصورت باینری 01010011 است، شما با هر عددی که بیت های 1 اش جز این موقعیت ها در موقعیت دیگری نباشد or اش کنید،
همچنان همان 83 خواهد ماند. مثلا or کردن با 01000000 و 00000011 و 01010000 و ... از شانس شما ShiftKey با مقدار 16 یا همان 00010000 جزو همین اعداد است.
شما عملا در این شرط هیچ نشانه ای از فشرده شدن Keys.ShiftKey نخواهید داشت، فراموش نکنید که در KeyCode دو کلید ثبت نمی شوند که بخواهید با هم | کنید. عملگر | برای مقداری که در KeyCode بررسی می کنید کاربردی ندارد.

درباره ی سئوال Task Manager هم ، من نمیخوام وقتی تسک منیجر بالا اومد ، چیزی رو متوجه شم
میخوام با اون کد ، تسک منیجر رو که خودم از قبل بصورت دستی بالا آوردم ، وقتی پیامی داد ، اون پیام بجای اینکه متصل بشه به فرم خودم (حالت انتظار برای پیام که تا پیام بسته نشه ، فرم اصلی در دسترس نیست) ، به پنجره ی Task Manager متصل بشه یعنی پیام تا بسته نشد ، اجزا و اشیاء در داخل پنجره ی Task Manager رو نشه کلیک کرد و کلا در دسترس نباشه
ولی کد بالا پنجره ی پیام رو به پنجره ی Task Manager متصل نمیکنه. چرا؟
بجز این ، میشه با متد MessageBox.Show خود ویژال استودیو این کار رو کرد؟ یعنی هندل ویندوزی رو داد و پیام به اون ویندوز بچسبه و متصل بشه؟
متصل شدن نیست، اصلا به این معنا نیست که برنامه معطل بشو تا این پنجره MessageBox بسته بشه. شما فقط مشخص می کنید که این پنجره از طرف پنجره Task Manager باز شده. این یک راهنمایی برای ویندوز ئه که بدونه کدوم پنجره درخواست باز شدن این MessageBox رو کرده.
اون پنجره Modal که شما برای MessageBox مشخص می کنید ربطی به منتظر بودن برنامه نداره، اینکه برنامه خودتون موقع باز شدن یک پنجره Modal منتظر می مونه بخاطر اینه که دستورات در یک نخ Thread اجرا میشه و تا MessageBox کدی رو برنگردونه دستورات بعدی اجرا نمیشه. اون پارامتر پنجره صرفا به این جهت ئه که ویندوز بدونه این MessageBox از طرف کدوم پنجره دیگه باز شده و فرضا وقتی بسته شد Focus به کجا برگرده.
از اونجایی که شما هیچ تسلط ای رو کد برنامه Task Manager ندارید نمی توانید مستقیما اجرای کد های اون رو معطل یک پنجره MessageBox خارجی بکنید، اینکه Modal اش اون پنجره Task Manager باشه یا نباشه ربطی به این قضیه نداره. شما برای Task Manager پنجره MessageBox باز نمی کنید، برای برنامه خودتون باز می کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
برای کنترل درخت که شاخه ها و فرزندهای متفاوتی داره ، این الگوریتم که نوشتم خوبه یا بهتر از اینم وجود داره؟ :


کد:
TreeView treeViewTest = new TreeView();

private void Form1_Load(object sender, EventArgs e)
        {
            this.Controls.Add(treeViewTest);
            treeViewTest.Bounds = new Rectangle(12, 350, 240, 182);
            string[] rootNodes = { "Anti Virus", "Internet Tools" };
            string[][] childNodes = { new string[] { "Padvish", "Avast", "Bitdefender" },
                                      new string[] { "Browser", "Downloader" },
                                      new string[] { "Google Chrom", "Opera", "Mozila FireFox", "Apple Safari" },
                                      new string[] { "Internet Download Manager"} };

            TreeNode[] treeRootNodes = AddNodeInTree(null, rootNodes);
            TreeNode[][] treeChildNodes = new TreeNode[childNodes.Length][];

            for (int i = 0; i < childNodes.Length; i++)
            {
                if (i<2)
                    treeChildNodes[i] = AddNodeInTree(treeRootNodes[i], childNodes[i]);
                else
                    treeChildNodes[i] = AddNodeInTree(treeChildNodes[1][i - 2], childNodes[i]);
            }
        }




        private TreeNode[] AddNodeInTree(TreeNode parentPosation, string[] nodeName)
        {
            TreeNode[] treeNodesPosSave = new TreeNode[nodeName.Length];
            int index = 0;
            foreach (string nodeItem in nodeName)
            {
                if (parentPosation == null)
                {
                    treeNodesPosSave[index] = treeViewTest.Nodes.Add(nodeItem);
                    index++;
                }
                else
                {
                    treeNodesPosSave[index] = parentPosation.Nodes.Add(nodeItem);
                    index++;
                }
            }
            return treeNodesPosSave;
        }

اگه همه شون مثل هم یه زیر گروه داشته باشن مثلا 5 تا ریشه داریم و هر 5 تا ، 3 تا زیر مجموعه داشته باشن ، مشکلی نیست ولی اگه زیر مجموعه هاشون ناهمواره داشته باشه مثلا یک ریشه 3 تا و یه ریشه ی دیگه 10 تا و یکی دیگه 6 تا و ... زیر مجموعه داشته باشه ، باز هم باید از همین الگوریتم رفت؟
آخه این الگوریتم که یک ریشه اش 2 تا و یکی دیگه 3 تا زیر مجموعه داشت ، if و else نیاز داشت اما وقتی چندین ناهمواری با زیر مجموعه های مختلف وجود داشته باشه ، دیگه واقعا خیلی خیلی سخت و if های تو در تو زیاد میخواد و به نظرم اصلا اصولی به نظر نمیرسه
پس اگه این جوری نیست الگوریتمش (یا سودو کدش) ، چجوری هه؟
 

the_king

مدیرکل انجمن
ممنون استاد علی
برای کنترل درخت که شاخه ها و فرزندهای متفاوتی داره ، این الگوریتم که نوشتم خوبه یا بهتر از اینم وجود داره؟ :


کد:
TreeView treeViewTest = new TreeView();

private void Form1_Load(object sender, EventArgs e)
        {
            this.Controls.Add(treeViewTest);
            treeViewTest.Bounds = new Rectangle(12, 350, 240, 182);
            string[] rootNodes = { "Anti Virus", "Internet Tools" };
            string[][] childNodes = { new string[] { "Padvish", "Avast", "Bitdefender" },
                                      new string[] { "Browser", "Downloader" },
                                      new string[] { "Google Chrom", "Opera", "Mozila FireFox", "Apple Safari" },
                                      new string[] { "Internet Download Manager"} };

            TreeNode[] treeRootNodes = AddNodeInTree(null, rootNodes);
            TreeNode[][] treeChildNodes = new TreeNode[childNodes.Length][];

            for (int i = 0; i < childNodes.Length; i++)
            {
                if (i<2)
                    treeChildNodes[i] = AddNodeInTree(treeRootNodes[i], childNodes[i]);
                else
                    treeChildNodes[i] = AddNodeInTree(treeChildNodes[1][i - 2], childNodes[i]);
            }
        }




        private TreeNode[] AddNodeInTree(TreeNode parentPosation, string[] nodeName)
        {
            TreeNode[] treeNodesPosSave = new TreeNode[nodeName.Length];
            int index = 0;
            foreach (string nodeItem in nodeName)
            {
                if (parentPosation == null)
                {
                    treeNodesPosSave[index] = treeViewTest.Nodes.Add(nodeItem);
                    index++;
                }
                else
                {
                    treeNodesPosSave[index] = parentPosation.Nodes.Add(nodeItem);
                    index++;
                }
            }
            return treeNodesPosSave;
        }

اگه همه شون مثل هم یه زیر گروه داشته باشن مثلا 5 تا ریشه داریم و هر 5 تا ، 3 تا زیر مجموعه داشته باشن ، مشکلی نیست ولی اگه زیر مجموعه هاشون ناهمواره داشته باشه مثلا یک ریشه 3 تا و یه ریشه ی دیگه 10 تا و یکی دیگه 6 تا و ... زیر مجموعه داشته باشه ، باز هم باید از همین الگوریتم رفت؟
آخه این الگوریتم که یک ریشه اش 2 تا و یکی دیگه 3 تا زیر مجموعه داشت ، if و else نیاز داشت اما وقتی چندین ناهمواری با زیر مجموعه های مختلف وجود داشته باشه ، دیگه واقعا خیلی خیلی سخت و if های تو در تو زیاد میخواد و به نظرم اصلا اصولی به نظر نمیرسه
پس اگه این جوری نیست الگوریتمش (یا سودو کدش) ، چجوری هه؟
کد:
        private TreeView treeViewTest = new TreeView();

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Controls.Add(treeViewTest);
            treeViewTest.Bounds = new Rectangle(12, 350, 240, 182);
            AddNodeInTree(treeViewTest, "Anti Virus>Padvish,Avast,Bitdefender"
                , "Internet Tools>Browser>Google Chrom,Opera,Mozila FireFox,Apple Safari"
                , "Internet Tools>Downloader>Internet Download Manager");
        }

        private void AddNodeInTree(TreeView treeView, params string[] nodes)
        {
            foreach (var node in nodes)
            {
                TreeNode root = null;
                int j = -1;
                for (int i = 0; i < node.Length; i++)
                {
                    switch (node[i])
                    {
                        case '>':
                            bool found = false;
                            string text = node.Substring(j + 1, i - j - 1);
                            if (root == null)
                            {
                                foreach (TreeNode item in treeViewTest.Nodes)
                                {
                                    if (item.Text == text)
                                    {
                                        root = item;
                                        found = true;
                                        break;
                                    }
                                }
                                if (found == false)
                                {
                                    root = treeView.Nodes.Add(text);
                                }
                            }
                            else
                            {
                                foreach (TreeNode item in root.Nodes)
                                {
                                    if (item.Text == text)
                                    {
                                        root = item;
                                        found = true;
                                        break;
                                    }
                                }
                                if (found == false)
                                {
                                    root = root.Nodes.Add(text);
                                }
                            }
                            j = i;
                            break;
                        case ',':
                            if (root == null)
                            {
                                treeView.Nodes.Add(node.Substring(j + 1, i - j - 1));
                            }
                            else
                            {
                                root.Nodes.Add(node.Substring(j + 1, i - j - 1));
                            }
                            j = i;
                            break;
                    }
                }
                if (j < node.Length - 1)
                {
                    if (root == null)
                    {
                        treeView.Nodes.Add(node.Substring(j + 1));
                    }
                    else
                    {
                        root.Nodes.Add(node.Substring(j + 1));
                    }
                }
            }
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
منظورم این بود که سودوکدش چیه؟ یعنی سودوکدش رو میگفتین ، مینوشتم . ممنون که نوشتین . زحمت دادم :rose: . پس الگوریتم پیمایش عمقی درخت و این جور چیزا که توی ساختمان داده هست ، چی؟ اونا به درد این قضایا نمیخوره؟

بعد اینکه این کد چرا ارور میده؟ :


کد:
private int Factorial(int factValue)
        {
            if (factValue == 1)
                return factValue;
            else
                int result = factValue * Factorial(factValue - 1);
            return result;
        }

خطی که متغییر result تعریف شد برای چی اشکال داره؟
ممنون
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آها. چون بیشتر از یه دستور بود ، توی بلاک نذاشته بودم :)
 

the_king

مدیرکل انجمن
ممنون استاد علی
منظورم این بود که سودوکدش چیه؟ یعنی سودوکدش رو میگفتین ، مینوشتم . ممنون که نوشتین . زحمت دادم :rose: . پس الگوریتم پیمایش عمقی درخت و این جور چیزا که توی ساختمان داده هست ، چی؟ اونا به درد این قضایا نمیخوره؟
تو این مورد خاص نه، شما چیزی رو پیمایش نمی کنید که، خود TreeView کار نمایش رو انجام میده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون
این چرا چیزی پیدا نمیکنه توی شی درخت اما این TreeNode وجود داره در این شی درخت! :


کد:
if (treeViewName.Nodes.Contains(new TreeNode("Anti Virus")) )
                        MessageBox.Show("true");

ریشه ی اولش هم هست (نام TreeNode ریشه هم برام treeViewName هه)
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
فرق بین این دو تا چیه؟ :

کد:
TreeNode[] myTreeNodes = treeViewTest.Nodes.Find("Anti Virus", true);
            foreach (TreeNode item in myTreeNodes)
            {
                MessageBox.Show(item.Text);
            }

و

کد:
foreach (TreeNode item in treeViewTest.Nodes)
            {
                MessageBox.Show(item.Text);
            }

myTreeNodes ، آرایه ای از TreeNode هاست و treeViewTest.Nodes کالکشنی از TreeNode ها .
آرایه و کالکشن مگه هر دو یکی نیستن؟
فرق بین کد رو میدونم . فقط فرق بین آرایه و کالکشن در کد بالا
در ظاهر ، هر چند الگوریتم متفاوت ولی انگار باید هر دو یه جواب رو بدن ولی اولی جواب نمیده و دومی فقط جواب میده!
 

the_king

مدیرکل انجمن
ممنون
این چرا چیزی پیدا نمیکنه توی شی درخت اما این TreeNode وجود داره در این شی درخت! :


کد:
if (treeViewName.Nodes.Contains(new TreeNode("Anti Virus")) )
                        MessageBox.Show("true");

ریشه ی اولش هم هست (نام TreeNode ریشه هم برام treeViewName هه)
فرض کنید شما از Form1 چند شیء بسازید، این شیء ها عنوان و ظاهر و محتویاتشون عینا یکی ئه، ولی همچنان چند شیء متمایز اند. Contains هم همین دید رو داره. خودتون عملا دارید شیء جدیدی با new می سازید، این شیء جدید نمی تونه در Nodes ها باشه چون جدید ئه. مهم نیست که عنوانش اش چیه. TreeNode یک شی از کلاس ئه، شما می توانید ده تا شیء از این کلاس با عنوان های مشابه بسازید ولی اینها هیچکدوم Equals هم نیستند. تعریف کلاس شون اینطوری نیست که هر دو شیء ای که Text شون برابر باشه رو Equals هم در نظر بگیره. به همین دلیل بود که من در کدی که نوشتم برای جستجوی TreeNode حلقه ساختم، چون میدونستم که Contains همچین تعریفی از برابری نداره.

فرق بین این دو تا چیه؟ :

کد:
TreeNode[] myTreeNodes = treeViewTest.Nodes.Find("Anti Virus", true);
            foreach (TreeNode item in myTreeNodes)
            {
                MessageBox.Show(item.Text);
            }

و

کد:
foreach (TreeNode item in treeViewTest.Nodes)
            {
                MessageBox.Show(item.Text);
            }

myTreeNodes ، آرایه ای از TreeNode هاست و treeViewTest.Nodes کالکشنی از TreeNode ها .
آرایه و کالکشن مگه هر دو یکی نیستن؟
فرق بین کد رو میدونم . فقط فرق بین آرایه و کالکشن در کد بالا
در ظاهر ، هر چند الگوریتم متفاوت ولی انگار باید هر دو یه جواب رو بدن ولی اولی جواب نمیده و دومی فقط جواب میده!
نه، آرایه و Collection یکی نیستند، اینکه هر دوشون Enumerable اند و می توانید با foreach پیمایش شون کنید دلیلی بر این نیست که یکی باشند.
دو تا کد خیلی با هم فرق دارند، چطور یکی تصور شون می کنید؟ شما در مجموعه دنبال Node هایی می گردید که Name شون Anti Virus باشه که اصلا ندارید چون تو کد شما همه Node ها بدون Name اند، فقط Text دارند. Text بصورت خودکار داخل Name قرار نمی گیره.
کاربرد اصلی اون Name برای اینه که فرضا شما بتوانید دو تا Node متفاوت رو با عنوان های یکسان نمایش بدید و راحت از هم تفکیک شون کنید.
مثل Name ئه Button ها.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
فرض کنید شما از Form1 چند شیء بسازید، این شیء ها عنوان و ظاهر و محتویاتشون عینا یکی ئه، ولی همچنان چند شیء متمایز اند. Contains هم همین دید رو داره. خودتون عملا دارید شیء جدیدی با new می سازید، این شیء جدید نمی تونه در Nodes ها باشه چون جدید ئه. مهم نیست که عنوانش اش چیه. TreeNode یک شی از کلاس ئه، شما می توانید ده تا شیء از این کلاس با عنوان های مشابه بسازید ولی اینها هیچکدوم Equals هم نیستند. تعریف کلاس شون اینطوری نیست که هر دو شیء ای که Text شون برابر باشه رو Equals هم در نظر بگیره. به همین دلیل بود که من در کدی که نوشتم برای جستجوی TreeNode حلقه ساختم، چون میدونستم که Contains همچین تعریفی از برابری نداره.


نه، آرایه و Collection یکی نیستند، اینکه هر دوشون Enumerable اند و می توانید با foreach پیمایش شون کنید دلیلی بر این نیست که یکی باشند.
دو تا کد خیلی با هم فرق دارند، چطور یکی تصور شون می کنید؟ شما در مجموعه دنبال Node هایی می گردید که Name شون Anti Virus باشه که اصلا ندارید چون تو کد شما همه Node ها بدون Name اند، فقط Text دارند. Text بصورت خودکار داخل Name قرار نمی گیره.
کاربرد اصلی اون Name برای اینه که فرضا شما بتوانید دو تا Node متفاوت رو با عنوان های یکسان نمایش بدید و راحت از هم تفکیک شون کنید.
مثل Name ئه Button ها.

ممنون آقا علی
آها پس منظورتون اینه که متد Find ، دنبال مشخصه ی Name میگرده ، نه در مشخصه ی Text نودها؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
فرض کنید شما از Form1 چند شیء بسازید، این شیء ها عنوان و ظاهر و محتویاتشون عینا یکی ئه، ولی همچنان چند شیء متمایز اند. Contains هم همین دید رو داره. خودتون عملا دارید شیء جدیدی با new می سازید، این شیء جدید نمی تونه در Nodes ها باشه چون جدید ئه. مهم نیست که عنوانش اش چیه. TreeNode یک شی از کلاس ئه، شما می توانید ده تا شیء از این کلاس با عنوان های مشابه بسازید ولی اینها هیچکدوم Equals هم نیستند. تعریف کلاس شون اینطوری نیست که هر دو شیء ای که Text شون برابر باشه رو Equals هم در نظر بگیره. به همین دلیل بود که من در کدی که نوشتم برای جستجوی TreeNode حلقه ساختم، چون میدونستم که Contains همچین تعریفی از برابری نداره.
.

استاد علی من این تیکه رو چطور بگم؟ هم متوجه شدم و هم متوجه نشدم o_O
توی کلاس Program اون خطی که میگه :


کد:
Application.Run(new Form1());

این یه شی جدید داره از کلاس Form1 میسازه
الان پس منظورتون اینه که با متدی از شی ای که از کلاس TreeView ساختم (یعنی شی treeViewName در اینجا) ، یه متدی استفاده کنم که اون TreeNode هایی که توی این شی داره رو برگردونه و خروجی اون TreeNode رو در ورودی این آرگومان بکار ببرم تا مثل کد در پست بالا که دادم ، شی جدیدی از TreeNode ها نسازم؟
بهترین کار برای دریافت TreeNode ها هم استفاده از همون حلقه ی foreach هه؟
البته یه متدی نیست که یه شی درخت رو بدیم و خودش برامون تمام Node های پرنت و child رو تا آخر پیدا کنه؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
استاد علی ، توی قضیه ی درخت ، با الگو برداری از سودوکدی که شما دادین ، این الگوریتم رو نوشتم. واقعا بهینه تر از اون سودوکد اولی ای که نوشته بودم هست :
ممنون


کد:
private TreeView treeViewTest = new TreeView();

private void Form1_Load(object sender, EventArgs e)
        {
            this.Controls.Add(treeViewTest);
            treeViewTest.Bounds = new Rectangle(655, 400, 340, 282);
            string[] nodesNameInTree = { "Anti Virus>Padvish,Avast,Bitdefender", "Internet Tools>Browser>Google Chrom,Opera,Mozila FireFox,Apple Safari", "Anti Virus", "Internet Tools>Downloader>Internet Download Manager", "Internet Tools>Browser>Comodo Dragon" };
            AddNodeInTree(treeViewTest, nodesNameInTree);
        }


        /// <summary>
        /// رشته هایی رو به عنوان گره یا نود میگیره و به شی درخت اضافه میکنه
        /// </summary>
        /// <param name="treeViewName"></param>
        /// نام درخت
        /// <param name="allNodes"></param>
        /// آرایه ها (یا آرایه بصورت پارامز) با فرمت خاص (فرمت تعریف شده در بالا) دریافت و به درخت اضافه میکنه
        private void AddNodeInTree(TreeView treeViewName, params string[] allNodes)
        {
            foreach (string nodeNames in allNodes)  //هر رشته ی ورودی (اعضای آرایه) که بصورت درخت با پیمایش عمقی طراحی شد رو حساب میکنه
            {
                if (nodeNames.Contains('>'))  //اگه رشته ، دارای فرزند و نوادگان بودند ، اینجا اجرا میشه
                {
                    TreeNode[] treeNodesParents;  //اطلاعات تری نود های والدین ، در این آرایه ذخیره میشه
                    string[] nodeParents;  //اطلاعات نام های والدین در این آرایه ذخیره میشه
                    string[] nodeChilds;  // اطلاعات نام آخرین (آخرین دسته از نوادگان) یا ریشه ی آخر ، در این آرایه ذخیره میشه
                    // این بلاک فقط برای پر کردن 2 آرایه ی رشته ای بالا بکار میره تا بعد از بلاک ، از رم پاک بشن و نام اضافی برای متغییرها اشغال نشه
                    {
                        ArrayList nodeParentsTemp = new ArrayList();
                        string[] nodeParentsTempNum2 = nodeNames.Split('>');
                        string[] nodeChildsTempNum2 = nodeNames.Split(',');

                        nodeParentsTemp.AddRange(nodeParentsTempNum2);
                        nodeParentsTemp.RemoveAt(nodeParentsTemp.Count - 1);
                        nodeParents = new string[nodeParentsTemp.Count];
                        treeNodesParents = new TreeNode[nodeParentsTemp.Count];
                        nodeParentsTemp.CopyTo(nodeParents);

                        nodeChildsTempNum2[0] = nodeChildsTempNum2[0].Remove(0, nodeChildsTempNum2[0].LastIndexOf('>') + 1 );
                        nodeChilds = new string[nodeChildsTempNum2.Length];
                        nodeChildsTempNum2.CopyTo(nodeChilds, 0);
                    }

                    // در این حلقه ، فقط اعضای آرایه nodeParents رو اضافه میکنه به عنوان والدین و همینطور آرایه ی treeNodesParents رو پر و مقداردهی میکنه که اطلاعات نودهاست . البته در صورتی که نودهای هر گره ، قبلا وجود نداشته باشن
                    for (int index = 0; index < nodeParents.Length; index++)
                    {
                        if (index==0)  //اگه قسمت ریشه ی اصلی بود ، به ریشه ی اصلی اضافه میکنه و اطلاعات نودها رو توی عضو قبلی آرایه treeNodesParents میریزه
                        {
                            TreeNode searchedNode = SearchNodeInTree(nodeParents[index], treeViewName);
                            if (searchedNode == null)
                                treeNodesParents[index] = treeViewName.Nodes.Add(nodeParents[index]);
                            else
                                treeNodesParents[index] = searchedNode;
                        }
                        else  //وگرنه بقیه ی والدین ها را به زیر مجموعه ی ریشه ی اصلی اضافه میکنه و اطلاعات نودها رو توی عضو قبلی آرایه treeNodesParents میریزه
                        {
                            TreeNode searchedNode = SearchNodeInTree(nodeParents[index], treeViewName, treeNodesParents[index - 1]);
                            if (searchedNode == null)
                                treeNodesParents[index] = treeNodesParents[index - 1].Nodes.Add(nodeParents[index]);
                            else
                                treeNodesParents[index] = searchedNode;
                        }
                    }

                    // این حلقه آرایه ی nodeChilds که نام های بچه هاست رو در صورتی که در گره ی آخرین والد وجود نداشته باشه ، اضافه میکنه
                    for (int index = 0; index < nodeChilds.Length; index++)
                    {

                        TreeNode searchedNode = SearchNodeInTree(nodeChilds[index], treeViewName, treeNodesParents[treeNodesParents.Length - 1]);
                        if (searchedNode == null)
                            treeNodesParents[treeNodesParents.Length - 1].Nodes.Add(nodeChilds[index]);

                    }
                }
                else  //اگه رشته دارای فرزند یا نوادگان نبودند و فقط بصورت تکی (برای ریشه ی اصلی) درخت بودند ، اینجا اجرا و به همین ریشه ی اصلی درخت اضافه میکنه
                {
                    TreeNode searchedNode = SearchNodeInTree(nodeNames, treeViewName);
                    if (searchedNode == null)
                    {
                        treeViewName.Nodes.Add(nodeNames);
                    }
                }
            }
        }

        /// <summary>
        /// چک میکنه اگه نام رشته ای به عنوان گره و نود (تری نود) ای قبلا وجود داشته باشه (فقط در اون تری نود یا گره ی خاص) ، همون تری نود رو برمیگردونه وگرنه نال یا خالی رو برمیگردونه
        /// </summary>
        /// <param name="nodeName"></param>
        /// رشته ای به عنوان نام گره ای که میخوایم جستجو کنیم
        /// <param name="treeViewName"></param>
        /// نام درخت ای که میخوایم توش جستجو کنیم
        /// <param name="treeNode"></param>
        /// تری نود یا اطلاعات گره ای که میخوایم توش جستجو کنیم . اگه این پارامتر نال (که بصورت پیش فرض نال یا همون خالی هست) ، جستجو در ریشه ی اصلی شی درخت انجام میشه
        /// <returns></returns>
        private TreeNode SearchNodeInTree(string nodeName, TreeView treeViewName, TreeNode treeNode = null)
        {
            if (treeNode == null)  // اگه اطلاعات نود نال یا خالی باشه ، در ریشه ی اصلی شروع به جستجو میکنه
            {
                foreach (TreeNode node in treeViewName.Nodes)  // تمام نودهایی که در ریشه ی اصلی هست رو میگیره و نام دونه دونه ی اون نودها رو چک میکنه ببینه برابر اون رشته ی داده شده هست یا نه
                {
                    if (node.Text == nodeName)
                        return node;
                   
                }
            }
            else  // وگرنه جستجو رو داخل نود ای که بهش داده شده انجام میده و نام دونه دونه ی اون نودها رو چک میکنه ببینه برابر اون رشته ی داده شده هست یا نه
            {
                foreach (TreeNode node in treeNode.Nodes)
                {
                    if (node.Text == nodeName)
                        return node;
                   
                }
            }

            return null;
        }
 

جدیدترین ارسال ها

بالا