سئوالات و مباحث WPF

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مشکل از BindingFlags نیست، از ()GetType ئه. کلاسی که شما ساخته اید خودش که فیلد private ای به نام dialogResult_ نداره، وارث کلاسی است که اون فیلد رو داره. فیلد private هم که در وراثت دخالتی نداره.
به جای ()GetType از typeof(Xceed.Wpf.Toolkit.MessageBox) استفاده کنید.

خیلی ممنون استاد .
استاد ، پس چرا درون کلاسِ AlarmBox (ای که نوشتم که والدش Xceed.Wpf.Toolkit.MessageBox هست) ، بجای this.GetType ، از base.GetType هم استفاده کردم ، باز همین مشکل را داره اما به قول شما از عملگر typeof(Xceed.Wpf.Toolkit.MessageBox) که استفاده کردم ، درست شد؟

بعد اینکه چرا اتریباتسِ [EditorBrowsable(EditorBrowsableState.Never)] را برای متدِ ShowMessageBox درون کلاس AlarmBox استفاده میکنم ، باعث نمیشه که شی ای که از AlarmBox ساخته میشه ، در ویرایشگر و اینتلیسنس ، متد ShowMessageBox ، پنهان بشه؟ :

C#:
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new void ShowMessageBox()
        {

        }

اما قبلا در جریان ساخت کنترل TransparentControl ، این کد را که استفاده میکردم ، باعث میشد اون متدی که در والدش تعریف شده بود ، زمانی که شی ای از فرزندش میساختیم ، از اینتلیسنس پنهان بمونه .

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

استاد یه سئوال شرعی در این باره (هر چند ربطی به این موضوع نداره و صرفا نظر شخصی تون را میخوام بدونم) .
اینکه الان من که دارم بخشی از کدهای اعضای کلاس Xceed.Wpf.Toolkit.MessageBox را کپی میکنم (از طریق نرم افزار ILSpy) و همچنین از اعضای private ئه این کلاس ، برای کلاسِ AlarmBox ام استفاده میکنم ، مشکل شرعی داره؟ درست میگم؟
به نظرتون بی خیالِ این کار بشم و خودم کد را از اول بنویسیم؟
اگه از اول بنویسم ، به نظر میاد کار خیلی سخت تر بشه .

تشکر استاد :rose:
 

the_king

مدیرکل انجمن
استاد ، پس چرا درون کلاسِ AlarmBox (ای که نوشتم که والدش Xceed.Wpf.Toolkit.MessageBox هست) ، بجای this.GetType ، از base.GetType هم استفاده کردم ، باز همین مشکل را داره اما به قول شما از عملگر typeof(Xceed.Wpf.Toolkit.MessageBox) که استفاده کردم ، درست شد؟
نوع شیء شما یکی بیشتر نیست، از نوع AlarmBox ئه، چه در کلاس AlarmBox و چه در کلاس MessageBox و چه کلاس های جد و آبادش نوع شیء همون AlarmBox ئه، اینطوری نیست که در کلاس MessageBox یهو instance تغییر نوع بده به MessageBox
قبلا یک صحبتی شبیه به این مورد رو داشتیم : پست #419 رو ببینید.
و این مثال رو امتحان کنید :
C#:
            var b = new ClassB();
            MessageBox.Show(b.A() + " " + b.B());
C#:
    public class ClassA
    {
        public string A()
        {
            return GetType().Name;
        }
    }

    public class ClassB : ClassA
    {
        public string B()
        {
            return GetType().Name;
        }
    }

بعد اینکه چرا اتریباتسِ [EditorBrowsable(EditorBrowsableState.Never)] را برای متدِ ShowMessageBox درون کلاس AlarmBox استفاده میکنم ، باعث نمیشه که شی ای که از AlarmBox ساخته میشه ، در ویرایشگر و اینتلیسنس ، متد ShowMessageBox ، پنهان بشه؟ :

C#:
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new void ShowMessageBox()
        {

        }

اما قبلا در جریان ساخت کنترل TransparentControl ، این کد را که استفاده میکردم ، باعث میشد اون متدی که در والدش تعریف شده بود ، زمانی که شی ای از فرزندش میساختیم ، از اینتلیسنس پنهان بمونه .
رجوع شود به #1296

استاد یه سئوال شرعی در این باره (هر چند ربطی به این موضوع نداره و صرفا نظر شخصی تون را میخوام بدونم) .
اینکه الان من که دارم بخشی از کدهای اعضای کلاس Xceed.Wpf.Toolkit.MessageBox را کپی میکنم (از طریق نرم افزار ILSpy) و همچنین از اعضای private ئه این کلاس ، برای کلاسِ AlarmBox ام استفاده میکنم ، مشکل شرعی داره؟ درست میگم؟
به نظرتون بی خیالِ این کار بشم و خودم کد را از اول بنویسیم؟
اگه از اول بنویسم ، به نظر میاد کار خیلی سخت تر بشه .
از روال هر کدی می توانید ایده بگیرید تا پروژه مستقل خودتون رو طراحی کنید، تا اینجا مشکلی نداره.
مثلا اینکه ببینید چطور MessageBox طراحی کرده و خودتون به اون شیوه یک MessageBox طراحی کنید صرفا استفاده از ایده است.

اما اینکه کدی رو مبنا قرار بدهید و چیزی رو ازش کپی کنید، تغییرش بدهید یا ازش وراثت بگیرید یا از کد در پروژه خودتون استفاده کنید، منوط به رعایت شرایط قرارداد لیسانس اون کد ئه.
قرارداد لیسانس اش اینه :
خلاصه اش اینه که اگر محصول رایگانی بر پایه کد wpftoolkit طراحی کنید نباید به بیش از 10 کاربر داده بشه (برای اون منظور مجوز غیر رایگان میخواد)
و برای طراحی محصول غیر رایگانی که از wpftoolkit استفاده می کنه هم باید مجوز غیر رایگان اش رو بگیرید.
و ابدا نباید محصول رقیبی طراحی کنید که بر پایه کد wpftoolkit طراحی شده باشه.
و نهایتا باید در محصول تون نام و لوگو و توضیحات حق مولف Xceed باید بصورت آشکارا نمایش داده بشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نوع شیء شما یکی بیشتر نیست، از نوع AlarmBox ئه، چه در کلاس AlarmBox و چه در کلاس MessageBox و چه کلاس های جد و آبادش نوع شیء همون AlarmBox ئه، اینطوری نیست که در کلاس MessageBox یهو instance تغییر نوع بده به MessageBox
قبلا یک صحبتی شبیه به این مورد رو داشتیم : پست #419 رو ببینید.
و این مثال رو امتحان کنید :
C#:
            var b = new ClassB();
            MessageBox.Show(b.A() + " " + b.B());
C#:
    public class ClassA
    {
        public string A()
        {
            return GetType().Name;
        }
    }

    public class ClassB : ClassA
    {
        public string B()
        {
            return GetType().Name;
        }
    }


رجوع شود به #1296

خیلی ممنون استاد.
بله ، البته میدونستم که شی ، در کلاس پدر ، همون شیِ فرزند هم هست اما فکر میکردم چون شیِ فرزند ، شیِ پدر هم محسوب میشه ، پس نباید مشکل داشته باشه .
پس برای اعضای private ، چون این سطح دسترسی فقط مخصوص همون کلاس هست و به کلاس والد یا فرزندان اش مربوط نمیشه ، برای دسترسی به اعضای private ، فقط باید از همون کلاس ، Type مون را اون هم با عملگر typeof بگیریم (نه توسط شی ساختن از کلاس فرزند یا اجدادش) .

از روال هر کدی می توانید ایده بگیرید تا پروژه مستقل خودتون رو طراحی کنید، تا اینجا مشکلی نداره.
مثلا اینکه ببینید چطور MessageBox طراحی کرده و خودتون به اون شیوه یک MessageBox طراحی کنید صرفا استفاده از ایده است.

اما اینکه کدی رو مبنا قرار بدهید و چیزی رو ازش کپی کنید، تغییرش بدهید یا ازش وراثت بگیرید یا از کد در پروژه خودتون استفاده کنید، منوط به رعایت شرایط قرارداد لیسانس اون کد ئه.
قرارداد لیسانس اش اینه :
خلاصه اش اینه که اگر محصول رایگانی بر پایه کد wpftoolkit طراحی کنید نباید به بیش از 10 کاربر داده بشه (برای اون منظور مجوز غیر رایگان میخواد)
و برای طراحی محصول غیر رایگانی که از wpftoolkit استفاده می کنه هم باید مجوز غیر رایگان اش رو بگیرید.
و ابدا نباید محصول رقیبی طراحی کنید که بر پایه کد wpftoolkit طراحی شده باشه.
و نهایتا باید در محصول تون نام و لوگو و توضیحات حق مولف Xceed باید بصورت آشکارا نمایش داده بشه.

خیلی ممنون استاد .
برای محصول غیر رایگان مون ، که اول اینکه خودشون محصول رایگان را گذاشتن و دوم اینکه خوب این جوری باشه همه ی نرم افزارهایی که استفاده میکنم ، این مجوز را ندارن . از ویندوز گرفته تا ویژال استودیو و ... . یعنی بجز پادویش ، بقیه ی نرم افزارهام ، هیچ کدوم شون را نخریدم (مثل اغلب ایرانی ها) .

از این لحاظ زیاد مد نظرم نیست . اینکه کدهای کلاس MessageBox شون را برای کلاس AlarmBox ئه خودم کپی کنم (و این کلاس AlarmBox را هم به کسی ندم و فقط خودم استفاده کنم ، چون گفتید که میگن به بیش از 10 نفر نباید داد) در صورتی که بخوام نرم افزارم را بفروشم ، مشکلی نیست؟ (البته از لحاظ فروش ، همون طور که گفتم ، از این لحاظ بخوایم حساب کنیم ، همونطور که گفتم ، خوب ، هیچ کدوم از نرم افزارهام را نخریدم چه برسه به این کنترل که رایگان اش را خودشون منتشر کردن) .
بالاخره نمیدونم چی کار کنم . کپی کنم و فقط برای خودم استفاده کنم؟

تشکر استاد . :rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد .
برای محصول غیر رایگان مون ، که اول اینکه خودشون محصول رایگان را گذاشتن و دوم اینکه خوب این جوری باشه همه ی نرم افزارهایی که استفاده میکنم ، این مجوز را ندارن . از ویندوز گرفته تا ویژال استودیو و ... . یعنی بجز پادویش ، بقیه ی نرم افزارهام ، هیچ کدوم شون را نخریدم (مثل اغلب ایرانی ها) .

از این لحاظ زیاد مد نظرم نیست . اینکه کدهای کلاس MessageBox شون را برای کلاس AlarmBox ئه خودم کپی کنم (و این کلاس AlarmBox را هم به کسی ندم و فقط خودم استفاده کنم ، چون گفتید که میگن به بیش از 10 نفر نباید داد) در صورتی که بخوام نرم افزارم را بفروشم ، مشکلی نیست؟ (البته از لحاظ فروش ، همون طور که گفتم ، از این لحاظ بخوایم حساب کنیم ، همونطور که گفتم ، خوب ، هیچ کدوم از نرم افزارهام را نخریدم چه برسه به این کنترل که رایگان اش را خودشون منتشر کردن) .
بالاخره نمیدونم چی کار کنم . کپی کنم و فقط برای خودم استفاده کنم؟

تشکر استاد . :rose:

استاد ، الان برای ساخت کلاس AlarmBox ، نمیدونم چی کار کنم . فعلا بلاتکلیفم و نوشتنِ کدها را متوقف کردم بخاطر همین قضیه ی شرعی بودن یا نبودنِ کدهایی که از کلاسِ Xceed.Wpf.Toolkit.MessageBox کپی میکنم .
به نظرتون چی کار کنم؟
ادامه بدم (با کپی کردن) یا کلا از اول خودم یه همچین کلاسی بسازم که خیلی طول میکشه؟

چه گیری افتادیم . درست کردنِ استایل و تمپلیت و کلاس های کنترل دیگه برای wpf ، تا همین جاش ، چند ماه وقتم را گرفت (که هنوزم کنترل ها و کلا ظاهر برنامه ام تکمیل نشد) .
هیچ کس نیست که کنترل های رایگانی برای wpf درست کرده باشه (مثل همین AlarmBox) تا کسای دیگه استفاده کنن .

البته ساخت همچین کنترل ها (مثل همین AlarmBox) و استایل ها و تمپلیت ها ، کار آسونی هست و سخت نیست اما وقتی برای طیف وسیعی از کنترل ها بخوایم این کار را کنیم ، جمعا ، مدت طولانی ای برای ساخت شون به زمان نیازه .
مخصوصا اینکه ، اولین برنامه ام را دارم میسازم و از طرفی هم محدودیت کنترل در wpf (توسط مایکروسافت که ارائه کرد نسبت به winform) هست.
 
آخرین ویرایش:

the_king

مدیرکل انجمن
استاد ، الان برای ساخت کلاس AlarmBox ، نمیدونم چی کار کنم . فعلا بلاتکلیفم و نوشتنِ کدها را متوقف کردم بخاطر همین قضیه ی شرعی بودن یا نبودنِ کدهایی که از کلاسِ Xceed.Wpf.Toolkit.MessageBox کپی میکنم .
به نظرتون چی کار کنم؟
ادامه بدم (با کپی کردن) یا کلا از اول خودم یه همچین کلاسی بسازم که خیلی طول میکشه؟
من در مسائل شرعی صاحبنظر نیستم.
 

SajjadKhati

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

استاد ، میخوام در این کلاس AlarmBox (که دارم مینویسم و از کلاس Xceed.Wpf.Toolkit.MessageBox ارث بری میکنه) ، این قابلیت را بذارم که وقتی موس ، در بیرون از Window ئه این AlarmBox ، کلیک شد ، رویدادی را برام اجرا کنه تا در اون رویداد ، حالا Background یا Foreground ئه یک یا چند کنترل را بصورت انیمیشن دربیارم تا کاربر بصورت بصری متوجه بشه که باید با کدوم پنجره در حال حاضر تعامل کنه (چون این قابلیت را نداره) (مثلِ MessageBox ئه مایکروسافت که ارائه کرد) .

حالا انگار برای capture کردنِ موس در بیرون از پنجره ، باید متدِ UIElement.CaptureMouse را اول فراخونی کنیم .
اما من وقتی این متد را فراخونی میکنم ، نخ ام دیگه جوابگو نیست و برنامه قفل میکنه و پنجره ی AlarmBox و دکمه های درونش ، دیگه جواب نمیدن :

C#:
        public void ShowModelessInstance()
        {
            bool flag = base.Parent != null;
            if (flag)
            {
                throw new InvalidOperationException("This method is not intended to be called while displaying a Message Box inside a WindowContainer. Use 'ShowMessageBox()' instead.");
            }

            FieldInfo _dialogResultFieldInfo = typeof(ToolKit.MessageBox).GetField("_dialogResult", BindingFlags.NonPublic | BindingFlags.Instance);
            _dialogResultFieldInfo?.SetValue(this, MessageBoxResult.None);
            base.Visibility = Visibility.Visible;
            MethodInfo createContainerMethodInfo = typeof(ToolKit.MessageBox).GetMethod("CreateContainer", BindingFlags.NonPublic | BindingFlags.Instance);
            createContainerMethodInfo?.Invoke(this, null);

            this.Container.Loaded += Container_Loaded;
            this.Container.GotMouseCapture += Container_GotMouseCapture;
            this.Container.ShowDialog();
        }

        private void Container_GotMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

        private void Container_Loaded(object sender, RoutedEventArgs e)
        {
            this.Container.CaptureMouse();
        }

اون کدِ :

C#:
this.Container.Loaded += Container_Loaded;
this.Container.GotMouseCapture += Container_GotMouseCapture;

درون متد ShowModelessCore را اضافه کردم و همچنین اون رویدادها رو .
مشکل از کجاست؟

یا بهتره بجای این روش ، از قضیه ی hook mouse استفاده کنم؟
تشکر استاد .
 

SajjadKhati

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

استاد ، میخوام در این کلاس AlarmBox (که دارم مینویسم و از کلاس Xceed.Wpf.Toolkit.MessageBox ارث بری میکنه) ، این قابلیت را بذارم که وقتی موس ، در بیرون از Window ئه این AlarmBox ، کلیک شد ، رویدادی را برام اجرا کنه تا در اون رویداد ، حالا Background یا Foreground ئه یک یا چند کنترل را بصورت انیمیشن دربیارم تا کاربر بصورت بصری متوجه بشه که باید با کدوم پنجره در حال حاضر تعامل کنه (چون این قابلیت را نداره) (مثلِ MessageBox ئه مایکروسافت که ارائه کرد) .

حالا انگار برای capture کردنِ موس در بیرون از پنجره ، باید متدِ UIElement.CaptureMouse را اول فراخونی کنیم .
اما من وقتی این متد را فراخونی میکنم ، نخ ام دیگه جوابگو نیست و برنامه قفل میکنه و پنجره ی AlarmBox و دکمه های درونش ، دیگه جواب نمیدن :

C#:
        public void ShowModelessInstance()
        {
            bool flag = base.Parent != null;
            if (flag)
            {
                throw new InvalidOperationException("This method is not intended to be called while displaying a Message Box inside a WindowContainer. Use 'ShowMessageBox()' instead.");
            }

            FieldInfo _dialogResultFieldInfo = typeof(ToolKit.MessageBox).GetField("_dialogResult", BindingFlags.NonPublic | BindingFlags.Instance);
            _dialogResultFieldInfo?.SetValue(this, MessageBoxResult.None);
            base.Visibility = Visibility.Visible;
            MethodInfo createContainerMethodInfo = typeof(ToolKit.MessageBox).GetMethod("CreateContainer", BindingFlags.NonPublic | BindingFlags.Instance);
            createContainerMethodInfo?.Invoke(this, null);

            this.Container.Loaded += Container_Loaded;
            this.Container.GotMouseCapture += Container_GotMouseCapture;
            this.Container.ShowDialog();
        }

        private void Container_GotMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

        private void Container_Loaded(object sender, RoutedEventArgs e)
        {
            this.Container.CaptureMouse();
        }

اون کدِ :

C#:
this.Container.Loaded += Container_Loaded;
this.Container.GotMouseCapture += Container_GotMouseCapture;

درون متد ShowModelessCore را اضافه کردم و همچنین اون رویدادها رو .
مشکل از کجاست؟

یا بهتره بجای این روش ، از قضیه ی hook mouse استفاده کنم؟
تشکر استاد .

سلامی مجدد
استاد ، بجای رویداد GotMouseCapture ، از رویدادِ MouseDown استفاده کردم ، درست شد و مشکل هنگی دیگه نداره :

C#:
this.Container.MouseDown += Container_MouseDown;

ولی علتش را هنوز متوجه نشدم .
 

the_king

مدیرکل انجمن
سلام
خیلی ممنون استاد .

استاد ، میخوام در این کلاس AlarmBox (که دارم مینویسم و از کلاس Xceed.Wpf.Toolkit.MessageBox ارث بری میکنه) ، این قابلیت را بذارم که وقتی موس ، در بیرون از Window ئه این AlarmBox ، کلیک شد ، رویدادی را برام اجرا کنه تا در اون رویداد ، حالا Background یا Foreground ئه یک یا چند کنترل را بصورت انیمیشن دربیارم تا کاربر بصورت بصری متوجه بشه که باید با کدوم پنجره در حال حاضر تعامل کنه (چون این قابلیت را نداره) (مثلِ MessageBox ئه مایکروسافت که ارائه کرد) .

حالا انگار برای capture کردنِ موس در بیرون از پنجره ، باید متدِ UIElement.CaptureMouse را اول فراخونی کنیم .
اما من وقتی این متد را فراخونی میکنم ، نخ ام دیگه جوابگو نیست و برنامه قفل میکنه و پنجره ی AlarmBox و دکمه های درونش ، دیگه جواب نمیدن :

C#:
        public void ShowModelessInstance()
        {
            bool flag = base.Parent != null;
            if (flag)
            {
                throw new InvalidOperationException("This method is not intended to be called while displaying a Message Box inside a WindowContainer. Use 'ShowMessageBox()' instead.");
            }

            FieldInfo _dialogResultFieldInfo = typeof(ToolKit.MessageBox).GetField("_dialogResult", BindingFlags.NonPublic | BindingFlags.Instance);
            _dialogResultFieldInfo?.SetValue(this, MessageBoxResult.None);
            base.Visibility = Visibility.Visible;
            MethodInfo createContainerMethodInfo = typeof(ToolKit.MessageBox).GetMethod("CreateContainer", BindingFlags.NonPublic | BindingFlags.Instance);
            createContainerMethodInfo?.Invoke(this, null);

            this.Container.Loaded += Container_Loaded;
            this.Container.GotMouseCapture += Container_GotMouseCapture;
            this.Container.ShowDialog();
        }

        private void Container_GotMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

        private void Container_Loaded(object sender, RoutedEventArgs e)
        {
            this.Container.CaptureMouse();
        }

اون کدِ :

C#:
this.Container.Loaded += Container_Loaded;
this.Container.GotMouseCapture += Container_GotMouseCapture;

درون متد ShowModelessCore را اضافه کردم و همچنین اون رویدادها رو .
مشکل از کجاست؟

یا بهتره بجای این روش ، از قضیه ی hook mouse استفاده کنم؟
تشکر استاد .
از اساس ایده بدی ئه، ابدا توصیه اش نمی کنم.
کاری به نحوه پیاده سازی ایده ندارم که بگم فلان شیوه خوبه و فلان شیوه بد، خود اینکه پنجره Modeless بخواد ادای پنجره Modal رو در بیاره ایده بدی ئه.
هم در اجرای این ایده مشکل پیش میاد و هم برای پنجره ای که نمیخواد Modal باشه منطقی نیست.
اگر قراره پنجره ای Modal باشه باید Modal نمایش داده بشه، نه اینکه Modeless ای باشه که بخواد خصوصیات پنجره Modal رو تقلید کنه.
سیستم عامل برای پیاده سازی اون ویژگی Modal کلی نکات رو رعایت کرده و روال های متعددی داره، تقلید اش همچین کار کوچکی نیست.
اون مساله که پنجره Modal موقع کلیک روی سایر پنجره ها با چشمک زدن هشدار میده خصوصیت ذاتی همه پنجره های Modal ویندوز ئه و برای انجامش در MessageBox کار خاصی صورت نگرفته که شما هم بخواهید انجام بدهید.
 

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، بجای رویداد GotMouseCapture ، از رویدادِ MouseDown استفاده کردم ، درست شد و مشکل هنگی دیگه نداره :

C#:
this.Container.MouseDown += Container_MouseDown;

ولی علتش را هنوز متوجه نشدم .
GotMouseCapture موقعی که پنجره ماوس رو به هر دلیلی Capture کرد رخ میده، فقط همون لحظه. ربطی به رخداد های ماوس ای که بعدا می خواهید ازشون باخبر بشید نداره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
از اساس ایده بدی ئه، ابدا توصیه اش نمی کنم.
کاری به نحوه پیاده سازی ایده ندارم که بگم فلان شیوه خوبه و فلان شیوه بد، خود اینکه پنجره Modeless بخواد ادای پنجره Modal رو در بیاره ایده بدی ئه.
هم در اجرای این ایده مشکل پیش میاد و هم برای پنجره ای که نمیخواد Modal باشه منطقی نیست.
اگر قراره پنجره ای Modal باشه باید Modal نمایش داده بشه، نه اینکه Modeless ای باشه که بخواد خصوصیات پنجره Modal رو تقلید کنه.
سیستم عامل برای پیاده سازی اون ویژگی Modal کلی نکات رو رعایت کرده و روال های متعددی داره، تقلید اش همچین کار کوچکی نیست.

سلامی مجدد
خیلی ممنون استاد . :rose:
نه ، پنجره ی Modeless نیست . بلکه Modal هست .
علاوه بر Modeless بودن ، میخوام یه بارِ دیگه متدهای Show را در کلاسِ AlarmBox ، بصورت new بنویسیم تا بتونم این قضیه اش را پیاده سازی کنم .

اون مساله که پنجره Modal موقع کلیک روی سایر پنجره ها با چشمک زدن هشدار میده خصوصیت ذاتی همه پنجره های Modal ویندوز ئه و برای انجامش در MessageBox کار خاصی صورت نگرفته که شما هم بخواهید انجام بدهید.

متدِ Show ئه کلاسِ Xceed.Wpf.Toolkit.MessageBox ، همچین ویژگی ای را نداره .

GotMouseCapture موقعی که پنجره ماوس رو به هر دلیلی Capture کرد رخ میده، فقط همون لحظه. ربطی به رخداد های ماوس ای که بعدا می خواهید ازشون باخبر بشید نداره.

خیلی ممنون استاد .

سلام
خیلی ممنون استاد .

استاد ، میخوام در این کلاس AlarmBox (که دارم مینویسم و از کلاس Xceed.Wpf.Toolkit.MessageBox ارث بری میکنه) ، این قابلیت را بذارم که وقتی موس ، در بیرون از Window ئه این AlarmBox ، کلیک شد ، رویدادی را برام اجرا کنه تا در اون رویداد ، حالا Background یا Foreground ئه یک یا چند کنترل را بصورت انیمیشن دربیارم تا کاربر بصورت بصری متوجه بشه که باید با کدوم پنجره در حال حاضر تعامل کنه (چون این قابلیت را نداره) (مثلِ MessageBox ئه مایکروسافت که ارائه کرد) .

حالا انگار برای capture کردنِ موس در بیرون از پنجره ، باید متدِ UIElement.CaptureMouse را اول فراخونی کنیم .
اما من وقتی این متد را فراخونی میکنم ، نخ ام دیگه جوابگو نیست و برنامه قفل میکنه و پنجره ی AlarmBox و دکمه های درونش ، دیگه جواب نمیدن :

C#:
        public void ShowModelessInstance()
        {
            bool flag = base.Parent != null;
            if (flag)
            {
                throw new InvalidOperationException("This method is not intended to be called while displaying a Message Box inside a WindowContainer. Use 'ShowMessageBox()' instead.");
            }

            FieldInfo _dialogResultFieldInfo = typeof(ToolKit.MessageBox).GetField("_dialogResult", BindingFlags.NonPublic | BindingFlags.Instance);
            _dialogResultFieldInfo?.SetValue(this, MessageBoxResult.None);
            base.Visibility = Visibility.Visible;
            MethodInfo createContainerMethodInfo = typeof(ToolKit.MessageBox).GetMethod("CreateContainer", BindingFlags.NonPublic | BindingFlags.Instance);
            createContainerMethodInfo?.Invoke(this, null);

            this.Container.Loaded += Container_Loaded;
            this.Container.GotMouseCapture += Container_GotMouseCapture;
            this.Container.ShowDialog();
        }

        private void Container_GotMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

        private void Container_Loaded(object sender, RoutedEventArgs e)
        {
            this.Container.CaptureMouse();
        }

اون کدِ :

C#:
this.Container.Loaded += Container_Loaded;
this.Container.GotMouseCapture += Container_GotMouseCapture;

درون متد ShowModelessCore را اضافه کردم و همچنین اون رویدادها رو .
مشکل از کجاست؟

یا بهتره بجای این روش ، از قضیه ی hook mouse استفاده کنم؟
تشکر استاد .

استاد ، بجای رویداد GotMouseCapture ، از رویدادِ MouseDown استفاده کردم ، اما هنوز درست نشد و هنگ میکنه .
مگر اینکه متد ReleaseMouseCapture را فراخونی کنم و تازه بعدش ، درست میشه .

اما بالاخره برای اینکه به هدفم برسم ، بصورت استاندارد ، اول ، همون متدِ CaptureMouse را باید فراخونی کنم (چون نمیدونم کاربر ، کِی قراره جاهای مختلفِ ویندوز ، کلیک کنه) . و زمانی هم که قراره پنجره ی مربوط به AlarmBox بسته بشه ، اون متد ReleaseMouseCapture را فراخونی کنم .

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

استاد ، به نظرتون چطوره که برای پیاده سازیِ این ایده ، بجای اینکار ، برم Owner ئه این AlarmBox (را در صورتی که کاربر ، Owner اش را مشخص کرده باشه) را بگیرم و ببینم درونِ اون Owner یا فرزندانش آیا کلیکی صورت میگیره یا نه؟
این روش دوم ، بهتر هه . درست میگم؟ هم دردسر کمتری داره .
 

the_king

مدیرکل انجمن
نه ، پنجره ی Modeless نیست . بلکه Modal هست .
علاوه بر Modeless بودن ، میخوام یه بارِ دیگه متدهای Show را در کلاسِ AlarmBox ، بصورت new بنویسیم تا بتونم این قضیه اش را پیاده سازی کنم .

متدِ Show ئه کلاسِ Xceed.Wpf.Toolkit.MessageBox ، همچین ویژگی ای را نداره .
برای اون جلوه چشمک زدن Modal بودن کافی نیست، Owner پنجره رو مشخص کنید.

استاد ، به نظرتون چطوره که برای پیاده سازیِ این ایده ، بجای اینکار ، برم Owner ئه این AlarmBox (را در صورتی که کاربر ، Owner اش را مشخص کرده باشه) را بگیرم و ببینم درونِ اون Owner یا فرزندانش آیا کلیکی صورت میگیره یا نه؟
این روش دوم ، بهتر هه . درست میگم؟ هم دردسر کمتری داره .
نظرم رو گفتم، ایده بدی دارید. برای یک ایده بد که پیشنهاد مناسبی وجود نداره.
اگر پنجره Modal میخواهید با ShowDialog نمایش اش بدهید و Owner اش رو هم مشخص کنید.
اگر هم می خواهید کارکرد کل پنجره های ویندوز تحت تاثیر اون MessageBox قرار بگیره بهتره پشت پنجره اش یک پنجره بدون کادر نیمه شفاف قرار بدهید.
 

SajjadKhati

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


نظرم رو گفتم، ایده بدی دارید. برای یک ایده بد که پیشنهاد مناسبی وجود نداره.
اگر پنجره Modal میخواهید با ShowDialog نمایش اش بدهید و Owner اش رو هم مشخص کنید.
اگر هم می خواهید کارکرد کل پنجره های ویندوز تحت تاثیر اون MessageBox قرار بگیره بهتره پشت پنجره اش یک پنجره بدون کادر نیمه شفاف قرار بدهید.

خیلی ممنون استاد .
دقیقا متوجه ی منظورتون نشدم .
منظورتون اینه که برای ایجاد جلوه ی چشمک زن ، علاوه بر ShowDialog کردن ، فقط کافی هست که پروپرتیِ Owner ئه اون پنجره را مشخص کنیم تا خودش (بدون نیاز به کدهای دیگه ای) ، این قابلیت بهش اضافه بشه؟
منظورتون اینه؟
اگه آره ، من این کار رو کردم ولی نشد .

اما اگه منظورتون اینه ، پس چرا گفتید که ایده ی بدی هست و پیشنهاد مناسبی نمیشه داد؟
اگه منظورتون این نیست ،دقیق متوجه نشدم .
تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
دقیقا متوجه ی منظورتون نشدم .
منظورتون اینه که برای ایجاد جلوه ی چشمک زن ، علاوه بر ShowDialog کردن ، فقط کافی هست که پروپرتیِ Owner ئه اون پنجره را مشخص کنیم تا خودش (بدون نیاز به کدهای دیگه ای) ، این قابلیت بهش اضافه بشه؟
منظورتون اینه؟
اگه آره ، من این کار رو کردم ولی نشد.
نشد یا ندیدید؟ چشمک بزنه هم چیزی از کادر پنجره باقی نمونده که چشمک زدنش دیده بشه.
پنجره ای که MessageBox نشون میده کادر داره، میتونه چشمک بزنه، اما پنجره ای که CreateContainer میسازه کادر نداره که چشمک بزنه، سیستم عامل FlashWindow رو هم اجرا کنه چیزی نیست که چشمک بزنه. (window.WindowStyle = WindowStyle.None)

خودتون Window بسازید و شرایط رو باهاش تمرین کنید یا مشخصه های اون پنجره ای که CreateContainer میسازه رو تغییر بدهید تا ببینید.

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نشد یا ندیدید؟ چشمک بزنه هم چیزی از کادر پنجره باقی نمونده که چشمک زدنش دیده بشه.
پنجره ای که MessageBox نشون میده کادر داره، میتونه چشمک بزنه، اما پنجره ای که CreateContainer میسازه کادر نداره که چشمک بزنه، سیستم عامل FlashWindow رو هم اجرا کنه چیزی نیست که چشمک بزنه. (window.WindowStyle = WindowStyle.None)

خودتون Window بسازید و شرایط رو باهاش تمرین کنید یا مشخصه های اون پنجره ای که CreateContainer میسازه رو تغییر بدهید تا ببینید.


خیلی واضح گفتم که از نظر من ایده بدی است و برای پیاده سازی اش هم پیشنهادی ندارم، قرار هم نیست برای دفاع از نظرم کسی رو قانع کنم.

خیلی ممنون استاد .
من که ویندوزی را در لودِ ویندوزِ دیگه ساختم ، چیزی ندیدم :

C#:
        private void SettingWindow_Loaded(object sender, RoutedEventArgs e)
        {
                    (new Window { Title = "test", Owner = this }).ShowDialog();
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
الان استاد ، من موندم که چرا وقتی از متد CaptureMouse استفاده میکنم ، باعث میشه برنامه (و احتمالا در واقع همون نخ) ام قفل کنه . فقط دلیلِ همین قضیه را متوجه شم و رفع کنم ، تمومه :

C#:
        public void ShowModelessInstance()
        {
            this.Container.Loaded += (object sender, RoutedEventArgs e) => { this.Container.CaptureMouse(); };
            this.Container.PreviewMouseDown += Container_PreviewMouseDown;
            this.Container.ShowDialog();
        }

        private void Container_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

البته باز هم نمیشه گفت که قفل میکنه . چون به رویدادِ Container_PreviewMouseDown ، کاملا پاسخگوست و این رویداد را به خوبی اجرا میکنه ولی نمیدونم چرا نمیشه دیگه هیچ کنترلِ دیگه ای درون این AlarmBox را کلیک کرد (البته تا از متد ReleaseMouseCapture استفاده کنم که در اون صورت ویندوزِ این AlarmBox ام دیگه به متدِ Container_PreviewMouseDown گوش نمیده) . البته جوابش اینه که بخاطر این نمیذاره که روی کنترل های دیگه کلیک صورت بگیره چون رویدادِ Container_PreviewMouseDown را فقط اجرا میکنه و بس . ولی نمیدونم چی کار باید کرد که علاوه بر این رویداد ، رویدادِ کلیک و هر رویدادِ دیگه ای در کنترل هایی که درون AlarmBox هستن را هم اجرا کنه ؟

یا یه مقاله ای چیزی درباره ی اینکه استفاده ی درست و دقیق (با توضیحات کامل) برای متد CaptureMouse مثال بزنه ، بی زحمت میدین؟ توضیحات سایت مایکروسافت را خوندم ولی همین مقدار رو متوجه شدم . جاهای دیگه هم باز هم تا جایی که گشتم ، توضیح خاصی درباره ی این مشکل یا استفاده ی دقیق ندادن .

تشکر استاد .
 

the_king

مدیرکل انجمن
الان استاد ، من موندم که چرا وقتی از متد CaptureMouse استفاده میکنم ، باعث میشه برنامه (و احتمالا در واقع همون نخ) ام قفل کنه . فقط دلیلِ همین قضیه را متوجه شم و رفع کنم ، تمومه :

C#:
        public void ShowModelessInstance()
        {
            this.Container.Loaded += (object sender, RoutedEventArgs e) => { this.Container.CaptureMouse(); };
            this.Container.PreviewMouseDown += Container_PreviewMouseDown;
            this.Container.ShowDialog();
        }

        private void Container_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Debug.WriteLine(e.LeftButton);
        }

البته باز هم نمیشه گفت که قفل میکنه . چون به رویدادِ Container_PreviewMouseDown ، کاملا پاسخگوست و این رویداد را به خوبی اجرا میکنه ولی نمیدونم چرا نمیشه دیگه هیچ کنترلِ دیگه ای درون این AlarmBox را کلیک کرد (البته تا از متد ReleaseMouseCapture استفاده کنم که در اون صورت ویندوزِ این AlarmBox ام دیگه به متدِ Container_PreviewMouseDown گوش نمیده) . البته جوابش اینه که بخاطر این نمیذاره که روی کنترل های دیگه کلیک صورت بگیره چون رویدادِ Container_PreviewMouseDown را فقط اجرا میکنه و بس . ولی نمیدونم چی کار باید کرد که علاوه بر این رویداد ، رویدادِ کلیک و هر رویدادِ دیگه ای در کنترل هایی که درون AlarmBox هستن را هم اجرا کنه ؟

یا یه مقاله ای چیزی درباره ی اینکه استفاده ی درست و دقیق (با توضیحات کامل) برای متد CaptureMouse مثال بزنه ، بی زحمت میدین؟ توضیحات سایت مایکروسافت را خوندم ولی همین مقدار رو متوجه شدم . جاهای دیگه هم باز هم تا جایی که گشتم ، توضیح خاصی درباره ی این مشکل یا استفاده ی دقیق ندادن .

تشکر استاد .
Capture کردن ماوس صرفا در مواقع خاصی مثل انجام عملیات Drag Drop صورت میگیره که پنجره میخواد موقتا تمامی رخداد های ماوس مستقل از اینکه در چه ناحیه ای باشه رو خودش مدیریت کنه، مثلا میخواد با یک Cursor قطره چکان روی صفحه نمایش و سایر پنجره ها جابجا بشه و رنگ یک نقطه از صفحه نمایش رو تشخیص بده. یا فرضا وقتی یک پنجره با ماوس Resize میشه باید رخداد های ماوس رو مستقل از اینکه در این لحظه ماوس داخل ناحیه است یا بیرونش دریافت کنه.
وگرنه در حالت عادی پنجره ای ماوس رو Capture نمی کنه. مثلا ابزار Process Monitor یا ++Spy ازش برای انتخاب پنجره با ماوس استفاده می کنند. پنجره ای که ماوس رو Capture می کنه روال های عادی ماوس رو مختل می کنه، به همین خاطر استفاده ای جز اینها نداره. برای موردی که شما می خواهید هم ابدا مناسب نیست. شما با Capture کردن ماوس در هر روال عادی ای که مربوط به اون پنجره نیست اختلال ایجاد می کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
Capture کردن ماوس صرفا در مواقع خاصی مثل انجام عملیات Drag Drop صورت میگیره که پنجره میخواد موقتا تمامی رخداد های ماوس مستقل از اینکه در چه ناحیه ای باشه رو خودش مدیریت کنه، مثلا میخواد با یک Cursor قطره چکان روی صفحه نمایش و سایر پنجره ها جابجا بشه و رنگ یک نقطه از صفحه نمایش رو تشخیص بده. یا فرضا وقتی یک پنجره با ماوس Resize میشه باید رخداد های ماوس رو مستقل از اینکه در این لحظه ماوس داخل ناحیه است یا بیرونش دریافت کنه.
وگرنه در حالت عادی پنجره ای ماوس رو Capture نمی کنه. مثلا ابزار Process Monitor یا ++Spy ازش برای انتخاب پنجره با ماوس استفاده می کنند. پنجره ای که ماوس رو Capture می کنه روال های عادی ماوس رو مختل می کنه، به همین خاطر استفاده ای جز اینها نداره. برای موردی که شما می خواهید هم ابدا مناسب نیست. شما با Capture کردن ماوس در هر روال عادی ای که مربوط به اون پنجره نیست اختلال ایجاد می کنید.

آها ، خیلی ممنون استاد
استاد ، این به ذهنم رسید پس در رویدادِ MouseEnter ئه اون Window (که همون پروپرتیِ this.Container هست) ، متد ReleaseMouseCapture را فراخونی کنم و در رویداد MouseLeave ئه اون Window ، متد CaptureMouse را .

اما مشکل اینه که نمیدونم چرا رویدادِ MouseEnter و MouseLeave که در بدنه اش فقط کد Debug.WriteLine را مینویسم ، این دو رویداد ، گاها درست اجرا میشن اما گاها هم ممکنه یکی درمیون اجرا بشن و یا اجرا نشن (یعنی کلا ممکنه شانسی اجرا بشن یا نه) .
مشکل شانسی اجرا شدن یا نشدنِ این دو رویداد ، از کجاست؟ و چرا این طوره؟
تشکر استاد
 

the_king

مدیرکل انجمن
آها ، خیلی ممنون استاد
استاد ، این به ذهنم رسید پس در رویدادِ MouseEnter ئه اون Window (که همون پروپرتیِ this.Container هست) ، متد ReleaseMouseCapture را فراخونی کنم و در رویداد MouseLeave ئه اون Window ، متد CaptureMouse را .

اما مشکل اینه که نمیدونم چرا رویدادِ MouseEnter و MouseLeave که در بدنه اش فقط کد Debug.WriteLine را مینویسم ، این دو رویداد ، گاها درست اجرا میشن اما گاها هم ممکنه یکی درمیون اجرا بشن و یا اجرا نشن (یعنی کلا ممکنه شانسی اجرا بشن یا نه) .
مشکل شانسی اجرا شدن یا نشدنِ این دو رویداد ، از کجاست؟ و چرا این طوره؟
تشکر استاد
در روال نرم افزاری چیزی به مفهوم شانسی وجود نداره، حتی اعداد Random اش هم شانسی نیستند چه برسه به اینجور چیزها.
هر چیزی که به نظر شانسی باشه یک منطقی داره که فعلا ازش اطلاعی ندارید و وقتی درکش کنید دیگه نمیگید شانسی.
 

SajjadKhati

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

خیلی ممنون استاد .
بله ، میدونم .
منظورم این بود که منطقِ این دو رویداد چیه که من حس میکنم که شانسی اجرا میشن؟
یا مشکل از متد Debug.WriteLine در این قضیه هست؟ یا چیز دیگه ای؟

اصلا سردرگم شدم . پروپرتیِ Window.IsMouseOver رو که در تایمر اجرا میکنم (و هر 200 میلی ثانیه ، این پروپرتی را Debug.WriteLine میکنم) ، این بار ، در پنجره ای که تست میکنم ، مشکلی نداره و دقیق و درست کار میکنه اما در پنجره ی AlarmBox ، باز درست عمل نمیکنه .

اگه از طریقِ Hook کردنِ موس پیش برم ، جواب میگیرم (چون از این جهت میپرسم که اگه مشکلاتِ احتمالی ای وجود داره که ازش باخبرید برای این زمینه ، بیخودی روش وقت نذارم) .

یعنی ، هیچ کجا ، هیچ کس ، یه همچین چیزی (فلش زدن window) را پیاده سازی نکرده که الگو بگیرم؟!
خودِ مایکروسافت پس چی کار کرده؟ در سطح برنامه های کاربردی ، پیاده سازی کرده دیگه؟

تشکر استاد .
 

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

بالا