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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد علی
ولی من همچین چیزی نمیخوام شبیه listbox که برنامه نویس ، رسم خاص خودش را انجام بده .
همونطور که در جریانید ، TransparentControl ، 2 بخش مهم داره . یکی رسم بیت مپ ها (بیت مپِ پیش فرض و بیت مپی که موس روی کنترل میره و بقیه ی بیت مپ ها) که اطلاعاتش توی کلاس TransparentControlBitmap هست و کدنویسی مربوط بهش ، تقریبا تمام شد . یکی دیگه هم رسمِ مربوط به string هاست . یعنی کاری بسیار شبیه عملکرد لیبل ها را خواهد داشت . اطلاعات مربوط به عملیات رشته ، درون کلاس TransparentControlText خواهد بود و کلاس TransparentControl ، توسط این اطلاعات و پروپرتی هایی که درون این کلاس (TransparentControlText) قرار داره ، رسمِ مربوط به string رو انجام میده . این کلاس هم فقط قراره کاری شبیه به label ها را انجام بده . یعنی پروپرتی های مختلف داشته باشه (مثل AutoSize وLocation ای که مربوط به String در داخل کنترل TransparentControl میشه و کلا همچنین پروپرتی های دیگه) و کلا کار محاسبات را انجام بده . منتها برای انجام این محاسبات ، نیازمندِ این هست که اطلاعات و پروپرتی های کلاس TransparentControl را اون هم در زمانی که متد سازنده اش (متد سازنده ی کلاس TransparentControlText) فراخونی میشه ، در دسترس داشته باشه که من اون دو روش را که گفتم ، میشناسم که حس میکنم ، یه روشِ ساده تر و کارآمدتری بجز اونها ، باید وجود داشته باشه که نمیدونم .

نمیدونم متوجه ی منظورم شدید یا نه . کلا چیزی شبیه به listbox نمیخوام . نمیخوام برنامه نویس ، خودش رسم را انجام بده . مثل کنترل label که با چند پروپرتی ، برنامه نویس ، رنگ دلخواهش را مشخص میکنه ، کسی که با این کنترل TransparentControl و TransparentControlText کار میکنه هم همین کار را کنه. منتها بتونم یه کارهای اضافی ترِ جزئیِ دیگه مثل تعیین location متن نسبت به کنترل TransparentControl و ... را خودم انجام بدم.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
ولی من همچین چیزی نمیخوام شبیه listbox که برنامه نویس ، رسم خاص خودش را انجام بده .
همونطور که در جریانید ، TransparentControl ، 2 بخش مهم داره . یکی رسم بیت مپ ها (بیت مپِ پیش فرض و بیت مپی که موس روی کنترل میره و بقیه ی بیت مپ ها) که اطلاعاتش توی کلاس TransparentControlBitmap هست و کدنویسی مربوط بهش ، تقریبا تمام شد . یکی دیگه هم رسمِ مربوط به string هاست . یعنی کاری بسیار شبیه عملکرد لیبل ها را خواهد داشت . اطلاعات مربوط به عملیات رشته ، درون کلاس TransparentControlText خواهد بود و کلاس TransparentControl ، توسط این اطلاعات و پروپرتی هایی که درون این کلاس (TransparentControlText) قرار داره ، رسمِ مربوط به string رو انجام میده . این کلاس هم فقط قراره کاری شبیه به label ها را انجام بده . یعنی پروپرتی های مختلف داشته باشه (مثل AutoSize وLocation ای که مربوط به String در داخل کنترل TransparentControl میشه و کلا همچنین پروپرتی های دیگه) و کلا کار محاسبات را انجام بده . منتها برای انجام این محاسبات ، نیازمندِ این هست که اطلاعات و پروپرتی های کلاس TransparentControl را اون هم در زمانی که متد سازنده اش (متد سازنده ی کلاس TransparentControlText) فراخونی میشه ، در دسترس داشته باشه که من اون دو روش را که گفتم ، میشناسم که حس میکنم ، یه روشِ ساده تر و کارآمدتری بجز اونها ، باید وجود داشته باشه که نمیدونم .

نمیدونم متوجه ی منظورم شدید یا نه . کلا چیزی شبیه به listbox نمیخوام . نمیخوام برنامه نویس ، خودش رسم را انجام بده . مثل کنترل label که با چند پروپرتی ، برنامه نویس ، رنگ دلخواهش را مشخص میکنه ، کسی که با این کنترل TransparentControl و TransparentControlText کار میکنه هم همین کار را کنه. منتها بتونم یه کارهای اضافی ترِ جزئیِ دیگه مثل تعیین location متن نسبت به کنترل TransparentControl و ... را خودم انجام بدم.
مشکل رو خودتون ایجاد کردید، چرا باید مشخصه های یک کنترل داخل یک کلاس مجزا قرار بگیره؟ چه مزیتی داره؟ مگر یک کنترل TransparentControl برای داشتن مشخصه Text مشکلی داشت که بخواد داخل TransparentControlText قرار بگیره؟ مگه ForeColor مشخص کننده رنگ نوشتار سایر کنترل ها نیست؟ چرا در کنترل شما باید بجایش یک Brush تعریف بشه؟
دو تا ایراد اساسی هم از کاری که کردید گرفتم. یکی اینکه پارامتر هایی که باید موقع رسم ایجاد بشه رو به عنوان مشخصه داخل کلاس TransparentControlText آوردید و ثانیا مشخصه های کنترل مثل Text رو کنار گذاشتید و بجایش مشخصه ها رو داخل کلاس جانبی دیگری قرار دادید. اگر کنترل شما یک چیزی مثل DataGridView بود که هر Cell اش میتوانست Style جداگانه ای داشته باشه هیچ ایرادی نمیشد به تعریف کلاسی مثل DataGridViewCellStyle گرفت چون هر Cell ای شیئ Style مجزا میتونه داشته باشه. اما کنترل شما که اینگونه نیست، کنترل شما کلاس چند تا مشخصه تصویر ثابت با کاربرد مشخص داره و فقط و فقط یک متن. تعداد نامشخص تصویر و متن که نداره که براشون کلاس سازی بخواد. کلاس Graphics رو ببینید، اونهمه متد و مشخصه داره، اومده برای گروه بندی تفکیک شون کنه و هر بخشی اش رو داخل یک کلاس مجزا قرار بده که بعدا به این فکر کنه که حالا چطور اون کلاس ها رو به Graphics ربط بده؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مشکل رو خودتون ایجاد کردید، چرا باید مشخصه های یک کنترل داخل یک کلاس مجزا قرار بگیره؟ چه مزیتی داره؟ مگر یک کنترل TransparentControl برای داشتن مشخصه Text مشکلی داشت که بخواد داخل TransparentControlText قرار بگیره؟ مگه ForeColor مشخص کننده رنگ نوشتار سایر کنترل ها نیست؟ چرا در کنترل شما باید بجایش یک Brush تعریف بشه؟
دو تا ایراد اساسی هم از کاری که کردید گرفتم. یکی اینکه پارامتر هایی که باید موقع رسم ایجاد بشه رو به عنوان مشخصه داخل کلاس TransparentControlText آوردید و ثانیا مشخصه های کنترل مثل Text رو کنار گذاشتید و بجایش مشخصه ها رو داخل کلاس جانبی دیگری قرار دادید. اگر کنترل شما یک چیزی مثل DataGridView بود که هر Cell اش میتوانست Style جداگانه ای داشته باشه هیچ ایرادی نمیشد به تعریف کلاسی مثل DataGridViewCellStyle گرفت چون هر Cell ای شیئ Style مجزا میتونه داشته باشه. اما کنترل شما که اینگونه نیست، کنترل شما کلاس چند تا مشخصه تصویر ثابت با کاربرد مشخص داره و فقط و فقط یک متن. تعداد نامشخص تصویر و متن که نداره که براشون کلاس سازی بخواد. کلاس Graphics رو ببینید، اونهمه متد و مشخصه داره، اومده برای گروه بندی تفکیک شون کنه و هر بخشی اش رو داخل یک کلاس مجزا قرار بده که بعدا به این فکر کنه که حالا چطور اون کلاس ها رو به Graphics ربط بده؟


خیلی ممنون استاد
اگه کلاس TransparentControlText را توی کلاس TransparentControl ادغام کنم ، مشکلی نداره . اتفاقا همین مشکلم هم حل میشه اما اولا یه کم ، مدیریت اش سخت تر میشه (مثلا شاید اگه این جوری ، ۶ تا متد سازنده برای کلاس TransparentControl بخوام بنویسم ، اون جوری ، تبدیل به ۱۲ متد سازنده بشه یا کارها و اورلودهای توابع و همچنین شرط گذاری هم ، بیشتر میشه) و کلا اینکه کدها ، بسیار زیادتر میشن . برای آپدیت های بعدی و کلا زمان کار با کلاس TransparentControl ، پیدا کردنِ اعضایی که فقط مربوط به بخشِ متن اش باشن ، سخت تره.

من آخر قضیه ی ربط این قضیه ، به لیست باکس و پارامتر DrawItemEventArgs را متوجه نشدم . من که نمیخوام به برنامه نویس بدم تا رسم را خودش خصوصی سازی کنه تا اون روش را بکار ببرم.
پس کلا نظرتون اینه که کدهاش را ادغام کنم؟ درسته؟
خیلی ممنون.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد
اگه کلاس TransparentControlText را توی کلاس TransparentControl ادغام کنم ، مشکلی نداره . اتفاقا همین مشکلم هم حل میشه اما اولا یه کم ، مدیریت اش سخت تر میشه (مثلا شاید اگه این جوری ، ۶ تا متد سازنده برای کلاس TransparentControl بخوام بنویسم ، اون جوری ، تبدیل به ۱۲ متد سازنده بشه یا کارها و اورلودهای توابع و همچنین شرط گذاری هم ، بیشتر میشه) و کلا اینکه کدها ، بسیار زیادتر میشن . برای آپدیت های بعدی و کلا زمان کار با کلاس TransparentControl ، پیدا کردنِ اعضایی که فقط مربوط به بخشِ متن اش باشن ، سخت تره.
کنترل شما نباید چند تا کلاس سازنده داشته باشه، سایر کنترل ها هم همین همینطور هستند. قبلا هم صحبت از این شد که ساختن شی از کلاس کنترل وظیفه Designer ویژوال استدیو است که اونم از متد های پارامتر دار شما استفاده نخواهد کرد. بجای اینکه برای کنترل تون متد های سازنده متعدد بسازید برای هر جزء مشخصه تعریف کنید. درست مثل ListView که مشخصه LargeImageList اش از SmallImageList مجزا است. ListView که نیومده سه تا متد سازنده برای مقدار دهی یکی از اونها یا هر دوشون تعریف کنه. خودتونم هم که در مثال ها دیده اید که چطور برنامه نویس در موقع ساختن شی با new میتونه با { } تمامی مشخصه های دلخواه خودش رو یکی یکی مقدار دهی کنه. هر ترکیبی از مقدار دهی مشخصه ها که نیازی به متد سازنده نداره. مثل سایر کنترل ها. چرا باید کنترل تون اون همه متد سازنده داشته باشه؟ چه نیازیه؟
من آخر قضیه ی ربط این قضیه ، به لیست باکس و پارامتر DrawItemEventArgs را متوجه نشدم . من که نمیخوام به برنامه نویس بدم تا رسم را خودش خصوصی سازی کنه تا اون روش را بکار ببرم.
شما اگر چنین چیزی نمی خواهید چرا برنامه نویس باید به مشخصه های StringFormat و Brush دسترسی داشته باشه؟ شما نهایت امکانات رسم متن خصوصی سازی شده رو در مشخصه ها قرار دادید، از انواع Brush های ساده و پیچیده گرفته تا تنظیمات رسم متن رو شامل شده، بعد میگید نمیخوام بتونه رسم رو خصوصی سازی کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد علی
البته من این روش را بکار گرفتم که رویداد ParentChanged را در کلاس TransparentControlText متصل کردم و همه ی پروپرتی هایی که مقداردهی نشدن را مقداردهی کنم . به این ترتیب اون مشکل ان شاء ا... حل میشه.
یه سئوال اینکه چجوری میشه جلوی تغییر اندازه ی کنترل را گرفت؟ یعنی برنامه نویس اگه مقدار پروپرتی Size کنترل مون را تغیییر اندازه بده و ما نخوایم اندازه شو تغییر بدیم ، باید چی کار کنیم؟ متد OnResize را اورراید کردم و کد base.OnResize(e); اش را حذف کردم اما باز هم تغییر اندازه میده . چیز خاص دیگه ای را هم پیدا نکردم.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
البته من این روش را بکار گرفتم که رویداد ParentChanged را در کلاس TransparentControlText متصل کردم و همه ی پروپرتی هایی که مقداردهی نشدن را مقداردهی کنم . به این ترتیب اون مشکل ان شاء ا... حل میشه.
یه سئوال اینکه چجوری میشه جلوی تغییر اندازه ی کنترل را گرفت؟ یعنی برنامه نویس اگه مقدار پروپرتی Size کنترل مون را تغیییر اندازه بده و ما نخوایم اندازه شو تغییر بدیم ، باید چی کار کنیم؟ متد OnResize را اورراید کردم و کد base.OnResize(e); اش را حذف کردم اما باز هم تغییر اندازه میده . چیز خاص دیگه ای را هم پیدا نکردم.
اون OnResize متدی است که وقتی Size تغییر کرد فراخوانی میشه و وظیفه اش اینه که رخداد Resize رو ایجاد کنه، تمامی OnEvent ها کارشون همینه که Event رو Invoke کنند.
با جلوگیری از Invoke شدن رخداد Resize که جلوی تغییر Size رو نمی گیرید، جلوی رخدادی که اعلام میکرد Size تغییر کرده رو می گیرید. مقادیر مشخصه های MinimumSize و MaximumSize رو تعیین کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اون OnResize متدی است که وقتی Size تغییر کرد فراخوانی میشه و وظیفه اش اینه که رخداد Resize رو ایجاد کنه، تمامی OnEvent ها کارشون همینه که Event رو Invoke کنند.
با جلوگیری از Invoke شدن رخداد Resize که جلوی تغییر Size رو نمی گیرید، جلوی رخدادی که اعلام میکرد Size تغییر کرده رو می گیرید. مقادیر مشخصه های MinimumSize و MaximumSize رو تعیین کنید.

خیلی ممنون استاد علی
من آخر قضیه ی این متدهایی که On دارن و آخرشون ، متدهای base شون را صدا میزنن را متوجه نشدم . الان وقتی متدهای base شون را صدا بزنن ، فقط باعث میشن که اون رویدادش اجرا بشه و کاری با عملیات شون ندارن و عملیات شون انجام میشه؟
یعنی مثل همین قضیه ی OnResize اگه متد base.OnResize را برداریم که فراخونی اش نکنه ، فقط باعث میشه که رویداد Resize اجرا نشه اما خود عملیاتِ Resize انجام میشه؟
اگه این طوره ، پس چرا توی متد OnPaint و OnPaintBackground ، متد base اش را برداریم ، رسم ای صورت نمیگیره؟
نمیدونم متوجه ی منظورم شدید یا نه؟
درباره ی قضیه ی MinimumSize و MaximumSize هم خیلی ممنون . متوجه شدم.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
من آخر قضیه ی این متدهایی که On دارن و آخرشون ، متدهای base شون را صدا میزنن را متوجه نشدم . الان وقتی متدهای base شون را صدا بزنن ، فقط باعث میشن که اون رویدادش اجرا بشه و کاری با عملیات شون ندارن و عملیات شون انجام میشه؟
یعنی مثل همین قضیه ی OnResize اگه متد base.OnResize را برداریم که فراخونی اش نکنه ، فقط باعث میشه که رویداد Resize اجرا نشه اما خود عملیاتِ Resize انجام میشه؟
اگه این طوره ، پس چرا توی متد OnPaint و OnPaintBackground ، متد base اش را برداریم ، رسم ای صورت نمیگیره؟
نمیدونم متوجه ی منظورم شدید یا نه؟
درباره ی قضیه ی MinimumSize و MaximumSize هم خیلی ممنون . متوجه شدم.
چه زمانی رخداد Resize اتفاق می افته؟ زمانی که Size تغییر کرده. یعنی بصورت طبیعی بعد از اینکه Size تغییر کرد تازه OnResize اجرا میشه. خود OnResize نیست که Size رو تغییر میده.
برای همینه که از کار انداختن روال OnResize از تغییر Size جلوگیری نمی کنه.
OnResize.png
حالا شما ممکن است بخواهید بدون اینکه واقعا Size ای تغییر کرده باشه OnResize رو فراخوانی کنید، یعنی بخواهید تمامی عملیاتی که بعد از تغییر Size انجام میشن در این لحظه دلخواه شما به دلیلی انجام بشن. عمل تغییر Size قبل از اینکه اون رخداد Resize اتفاق بیافته انجام شده، حالا در OnResize میتونه بجز Invoke شدن Resize صد تا کار دیگه هم انجام بشه، کنترل مجددا رسم بشه، پیامی نمایش داده بشه، ابعاد چیزی تغییر کنه و ... اینها تناقضی با چیزی که گفتم نداره.
Control.OnPaint خودش که چیزی رسم نمی کنه، اما رخداد Paint رو ایجاد می کنه تا هر رسم پیشفرضی که برای کلاس تعریف شده رو انجام بده. و در هر کلاس وارثی میتونه طوری تغییر کنه که رسمی هم انجام بده.
چه زمانی OnPaint اتفاق می افته؟ زمانی که کنترل لازم می بینه که رسم بشه، یعنی قبل از اینکه اصلا Paint ای رخ داده باشه. برای کنترلی که Paint هایش رو خودش انجام میده و به اصطلاح UserPaint ئه، خود OnPaint ایجاد کننده رخداد Paint ئه. در OnPaint رخداد Paint ئه ایجاد میشه تا هر رسمی که برای Paint در نظر گرفته شده انجام بشه. طبعا شما می توانید در OnPaint رسمی هم انجام بدید تا جلوی بروز رخداد Paint رو بگیرید، ولی طبعا اگر جلوی بروز رخداد Paint رو بگیرید آن کدی که بصورت پیشفرض رسم انجام میداد را از کار انداختید.
وقتی شما OnPaint رو تغییر میدید و عملیاتش رو حذف می کنید چه اتفاقی می افته؟ جلوی فراخوانی رخداد رسم گرفته میشه، به همین دلیله که دیگه رسم ای صورت نمی گیره، نه به این خاطر که در Control.OnPaint رسمی بوده :
OnPaint.png
 

SajjadKhati

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


کد:
DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format);

را فراخونی کنیم ، چرا وقتی مقدار stringFormat.FormatFlags = StringFormatFlags.DirectionRightToLeft; را ست کنیم ، جواب نمیده؟ اگه میخوایم مقدار راست به چپ را در FormatFlags ست کنیم ، فقط اورلود :


کد:
public void DrawString(string s, Font font, Brush brush, PointF point, StringFormat format);

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

the_king

مدیرکل انجمن
خیلی ممنون استاد علی.:rose:
عیدتون مبارک باشه. :rose:
اگه اورلود پنجم در متد DrawString ، یعنی :


کد:
DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format);

را فراخونی کنیم ، چرا وقتی مقدار stringFormat.FormatFlags = StringFormatFlags.DirectionRightToLeft; را ست کنیم ، جواب نمیده؟ اگه میخوایم مقدار راست به چپ را در FormatFlags ست کنیم ، فقط اورلود :


کد:
public void DrawString(string s, Font font, Brush brush, PointF point, StringFormat format);

را اگه فراخونی کنیم ، جواب میده.
چرا اون اورلود ، جواب نمیده؟
اشتباه از من هست؟ یا من اشتباه نمیکنم؟
یک جای کدتون یا تفسیری که از نتیجه دارید اشتباهه که به نظرتون جواب نمیده.
پیشنهاد می کنم برای آزمایش تاثیر StringFormatFlags.DirectionRightToLeft از متنی استفاده کنید که روی ترتیب کلماتش تاثیر داره، فرضا "متن Farsi است".
و البته StringFormatFlags.DirectionRightToLeft بجز ترتیب کلمات متن، روی جهت مبنای StringFormat.Alignment هم تاثیر میذاره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک جای کدتون یا تفسیری که از نتیجه دارید اشتباهه که به نظرتون جواب نمیده.
پیشنهاد می کنم برای آزمایش تاثیر StringFormatFlags.DirectionRightToLeft از متنی استفاده کنید که روی ترتیب کلماتش تاثیر داره، فرضا "متن Farsi است".
و البته StringFormatFlags.DirectionRightToLeft بجز ترتیب کلمات متن، روی جهت مبنای StringFormat.Alignment هم تاثیر میذاره.

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد علی .
استاد علی ، من توی قضیه ی همون کنترل TransparentControl ، تا اینجا پیش رفتم . (فایل اش را در زیر آپلود میکنم) . همونطور که میدونید ، در بخشِ مربوط به متن (همون TransparentControlText) هستم و کدهای این بخش را دارم مینویسم . بخش TransparentControlBitmap تقریبا تمام شد.
مشکلش اینه که وقتی کنترل ، لود میشه ، متن ای که (اطلاعاتش را از TransparentControlText میگیره) رسم میشه ، رسم اش پر رنگ هست . یعنی انگار مثل قضیه ی قسمت رسم bitmap بود که بدون اینکه رسم قبلی را پاک کنه ، همون بیت مپ را روی رسمِ قبلی ، رسم میکرد و باعثِ پر رنگ تر شدنش میشد . این هم انگار همون جوری هه منتها با این تفاوت که اولا موقع رسم متن ، کنترلِ والدِ کنترلِ TransparentControl را invalidate میکنم (همون بخشی از کنترل والد را invalidate میکنم که باندِ کنترلِ TransparentControl قرار داره) و دوما بخشِ رسمِ TransparentControlBitmap اش این مشکل را نداره. یعنی رسمِ بیت مپ برای کنترلِ TransparentControl ، این مشکل را نداره . نمیدونم برای چیه ؟
بعد اینکه اگه بعد از لود همین کنترل (کلا بعد از لود فرم دیگه) ، فرم را یه بار مینیمایز و بعد به حالتِ اولش برگردونین ، رسمِ متنِ درونِ کنترلِ TransparentControl ، رسم معمولی و نازک تر نشون میده.
خودم فکر میکردم برای فراخونیِ متدِ SetParentInvalidate (این متد درون کلاس TransparentControlText تعریف شد) که درون اغلب پروپرتی هایی که در کلاس TransparentControlText تعریف کرده بودم ، فراخونی کردم ، باشه . اما فراخونیِ اون متد را از درون اون پروپرتی ها حذف کردم (کامنت کردم) ولی این مشکل حل نشد.

این کد را درون کلاس فرم تون بذارید لطفا :

کد:
        private TransparentControl transparentControl;

        private void Form1_Load(object sender, EventArgs e)
        {
            TransparentControlText tcText = new TransparentControlText("salam");
            this.transparentControl = new TransparentControl(tcText, new Point(100, 200));
            this.transparentControl.AutoCalculateForeBackgroundControls = false;
            this.Controls.Add(this.transparentControl);
        }

یه چیز دیگه اینکه میخوام مثلا وقتی برنامه نویس ، مقدار هر پروپرتی ای که درون کنترل TransparentControlText هست را تغییر داد ، نتیجه اش را ببینه . پس باید با هر تغییر پروپرتی ، کنترل TransparentControl ، رسم مجدد انجام بده دیگه؟ پس باید درون هر پروپرتی (ای که داخل کلاس TransparentControlText هستند) ، متدِ SetParentInvalidate (که درون کلاس TransparentControlText هست) و کارش invalidate کردنِ کنترلِ والدِ TransparentControl هست را فراخونی کنم . درسته؟ این روی از این جهت گفتم که چون گاها در قسمت یا اکسسورِ set در یک پروپرتی یا کلا در قسمت های دیگه ی همین کلاس ، مجبور میشم ، یه پروپرتیِ دیگه را هم مقداردهی کنم که باعثِ این میشه که این متد ، چندین بار فراخونی بشه . کلا میخواستم بگم که فراخونیِ چندین باره ی (بجای یک بار) این متد ، باعثِ ایجادِ مشکلی نمیشه که؟
اگه در قسمت set هر پروپرتی ای که درون کلاس TransparentControlText تعریف کردم (کلا 11 تا 12 پروپرتی میشه) ، در بخشِ آخرِ اون set که متد this.SetParentInvalidate(); را کامنت کردم را از کامنت در بیارین و همچنین در ادامه ی کد قبلی ، این کد را اضافه کنید (البته یه دکمه با نام Button3 به فرم اضافه کنید و رویداد MouseUp اش را به متد زیر متصل کنید) ، بهتر متوجه میشید :


کد:
        private void Button3_MouseUp(object sender, MouseEventArgs e)
        {
            this.transparentControl.TextAutoSize = false;
            this.transparentControl.Bounds = new Rectangle(this.transparentControl.Location, new Size(400, 300));
            if (e.Button == MouseButtons.Left)
            {

                this.transparentControl.TransparentControlText.TextBound = new RectangleF(this.transparentControl.TransparentControlText.TextLocation, new Size(200, 100));
            }
            else if(e.Button == MouseButtons.Right)
            {
                this.transparentControl.TextAutoSize = true;
            }
        }

البته این رو هم بگم که رابطه ی بین متد SetParentInvalidate (که درون کلاس TransparentControlText تعریف شد) و رویداد AllParents_Invalidated ، یه اشکالی داره (اونم اینه که بصورت پیش فرض چون فلگ IsLocationChangeDoingFlag (که درون کلاس TransparentControl تعریف شد) ، زمانی که متد SetParentInvalidate فراخونی میشه ، مقدار true نداره ، متد InvalidateBackgroundsAndThisControl برای invalidate کردنِ کنترل TransparentControl اجرا نمیشه) که این اشکال ، در روندِ اجرا و مقداردهی اولیه دادنِ به پروپرتی های TransparentControlText ، فعلا برطرف میشه (با اجرای کد this.TransparentControl.Size = fontSize.ToSize(); در رویداد TransparentControl_TextAutoSizeChanged درون کلاس TransparentControlText ) که البته بعدا یه فکری براش میکنم . فعلا مشکل خاصی از این جهت نداره . احتمالا باید براش بعدا رویدادی از درون کلاس TransparentControlText درست کنم.

ببخشید زیاد شد . با تشکر فراوان :rose:
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد استاد علی .
استاد علی ، من توی قضیه ی همون کنترل TransparentControl ، تا اینجا پیش رفتم . (فایل اش را در زیر آپلود میکنم) . همونطور که میدونید ، در بخشِ مربوط به متن (همون TransparentControlText) هستم و کدهای این بخش را دارم مینویسم . بخش TransparentControlBitmap تقریبا تمام شد.
مشکلش اینه که وقتی کنترل ، لود میشه ، متن ای که (اطلاعاتش را از TransparentControlText میگیره) رسم میشه ، رسم اش پر رنگ هست . یعنی انگار مثل قضیه ی قسمت رسم bitmap بود که بدون اینکه رسم قبلی را پاک کنه ، همون بیت مپ را روی رسمِ قبلی ، رسم میکرد و باعثِ پر رنگ تر شدنش میشد . این هم انگار همون جوری هه منتها با این تفاوت که اولا موقع رسم متن ، کنترلِ والدِ کنترلِ TransparentControl را invalidate میکنم (همون بخشی از کنترل والد را invalidate میکنم که باندِ کنترلِ TransparentControl قرار داره) و دوما بخشِ رسمِ TransparentControlBitmap اش این مشکل را نداره. یعنی رسمِ بیت مپ برای کنترلِ TransparentControl ، این مشکل را نداره . نمیدونم برای چیه ؟
بعد اینکه اگه بعد از لود همین کنترل (کلا بعد از لود فرم دیگه) ، فرم را یه بار مینیمایز و بعد به حالتِ اولش برگردونین ، رسمِ متنِ درونِ کنترلِ TransparentControl ، رسم معمولی و نازک تر نشون میده.
خودم فکر میکردم برای فراخونیِ متدِ SetParentInvalidate (این متد درون کلاس TransparentControlText تعریف شد) که درون اغلب پروپرتی هایی که در کلاس TransparentControlText تعریف کرده بودم ، فراخونی کردم ، باشه . اما فراخونیِ اون متد را از درون اون پروپرتی ها حذف کردم (کامنت کردم) ولی این مشکل حل نشد.
چند تا مورد هست که اگر در نظر نگرفتید بدونید که باید حتما در نظر بگیرید :
مورد اول اینکه شما هر چقدر مشخصه و کلاس مرتبط با رسم داشته باشید، رسم تون باید یک روتین جامع و شامل همه شون باشه، نه تفکیک شده. یعنی رسم تون همیشه باید یکجا و شامل تمامی اجزاء رسم باشه، چه پارامتر های مربوط به اون بخش متن / تصویر تغییری کرده باشند و چه نکرده باشند. فرضا اگر متن تغییر کرد، معنی اش این نیست که باید بیخیال رسم تصویر بشید و فقط متن رو رسم کنید یا برعکس. باید والد و کنترل های پشتی رسم بشن و بعد تصویر و متن هر دو رسم بشن و بعد کنترل های رویی رسم بشن، این روتین رسم ابدا نباید تغییری بکنه، چه تصویر عوض بشه و چه متن و چه هر پارامتر دیگری که به رسم مربوط باشه، به هر حال روتین باید تمام و کمال اجرا بشه. نمیشه با تغییر متن صرفا متن مجددا رسم بشه.
مورد دوم اینکه وقتی تعداد پارامتر ها زیاده، باید دو تا متد Begin و End با اسامی دلخواه بسازید که یک متغیری رو true/false می کنند. این متغیر میتونه جلوی رسم مجدد رو موقعی که پارامتری رو با مشخصه ها تغییر می دهید بگیره. یعنی در مشخصه ها می نویسید که فقط وقتی کنترل رو مجددا رسم کن که اون متغیر true (یا false) بود. این Begin و End مشابهش در ListBox.BeginUpdate و ListBox.EndUpdate پیاده سازی شده.
فلسفه شون اینه که اگر شما صد تا آیتم به ListBox اضافه کردید، دلیلی نداره که برای اضافه کردن هر کدوم یکبار کنترل ListBox مجددا رسم بشه، پس قبل شروع به اضافه کردن اولین آیتم به ListBox متد BeginUpdate رو اجرا می کنید تا رسم موقتا غیر فعال بشه، صد تا آیتم رو با خیال آسوده اضافه می کنید و نهایتا با EndUpdate فقط و فقط یکبار رسم انجام میشه تا یهو صد تا آیتم در رسم نمایش داده بشن.
شما هم به مشابه ایندو تا متد نیاز دارید تا برنامه نویس بتونه موقع تغییر دادن چند مشخصه (پارامتر مربوط به رسم) رسم مجدد رو در بین این دو تا متد موقتا متوقف کنه.
که برای تغییر هر مشخصه هی کنترل تون رسم مجدد نشه، مخصوصا که رسم کنترل تون پیچیده است.

در سایر شرایط شما ناگزیر هستید که برای هر کدوم از مشخصه ها اون رسم مجدد رو انجام بدید، انتخاب دیگری وجود نداره، مجبورید در بخش set مشخصه ها این رسم مجدد رو داشته باشید، البته با شرط مربوط به اون متغیر.
مورد سوم اینکه با کلاس سازی تون برای تصویر و متن اصلا موافق نیستم. نه به شما کمکی می کنه و نه کسی که از کنترل تون استفاده می کنه.
 

SajjadKhati

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

خیلی ممنون استاد علی .
بله همین روال را در نظر گرفتم.
برای هر نوع رسم ای (چه رسم تصویر یا رسم متن) ، اول اون بخش از کنترلِ والدِ TransparentControl را invalidate میکنم . با این کار ، رویداد AllParents_Invalidated (درون کلاس TransparentControl) اجرا میشه . بعد هم متد InvalidateBackgroundsAndThisControl که باعث میشه اول ، کنترل های پشت زمینه و بعد درون یک تایمر ، همون کنترل TransparentControl عمل invalidate را انجام بده . درون OnPaint کنترل TransparentControl هم که اول عملیات رسم همین کنترل (شامل رسم تصویر و رسم متن که اگه هر کدوم شون وجود داشتند ، رسم میشن) و بعد کنترل های جلویی invalidate میشن .

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

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


مورد دوم اینکه وقتی تعداد پارامتر ها زیاده، باید دو تا متد Begin و End با اسامی دلخواه بسازید که یک متغیری رو true/false می کنند. این متغیر میتونه جلوی رسم مجدد رو موقعی که پارامتری رو با مشخصه ها تغییر می دهید بگیره. یعنی در مشخصه ها می نویسید که فقط وقتی کنترل رو مجددا رسم کن که اون متغیر true (یا false) بود. این Begin و End مشابهش در ListBox.BeginUpdate و ListBox.EndUpdate پیاده سازی شده.
فلسفه شون اینه که اگر شما صد تا آیتم به ListBox اضافه کردید، دلیلی نداره که برای اضافه کردن هر کدوم یکبار کنترل ListBox مجددا رسم بشه، پس قبل شروع به اضافه کردن اولین آیتم به ListBox متد BeginUpdate رو اجرا می کنید تا رسم موقتا غیر فعال بشه، صد تا آیتم رو با خیال آسوده اضافه می کنید و نهایتا با EndUpdate فقط و فقط یکبار رسم انجام میشه تا یهو صد تا آیتم در رسم نمایش داده بشن.
شما هم به مشابه ایندو تا متد نیاز دارید تا برنامه نویس بتونه موقع تغییر دادن چند مشخصه (پارامتر مربوط به رسم) رسم مجدد رو در بین این دو تا متد موقتا متوقف کنه.
که برای تغییر هر مشخصه هی کنترل تون رسم مجدد نشه، مخصوصا که رسم کنترل تون پیچیده است.

در سایر شرایط شما ناگزیر هستید که برای هر کدوم از مشخصه ها اون رسم مجدد رو انجام بدید، انتخاب دیگری وجود نداره، مجبورید در بخش set مشخصه ها این رسم مجدد رو داشته باشید، البته با شرط مربوط به اون متغیر.

آها خیلی ممنون.


مورد سوم اینکه با کلاس سازی تون برای تصویر و متن اصلا موافق نیستم. نه به شما کمکی می کنه و نه کسی که از کنترل تون استفاده می کنه.

چرا .
اتفاقا خیلی کمک میکنه . مخصوصا توی ترتیب و دسته بندی کدها . مخصوصا برای کسایی که مبتدی تر هستند.
با این دسته بندی ، الان کسی که میخواد فقط از بیت مپ و تصویرش استفاده کنه ، از همون کلاس شی میسازه ؛ اعضای مربوط به تصویر هم جدا هستند . کسی هم که میخواد با متن کار کنه هم همینطور و حتی کسی که با هر دوشون میخواد کار کنه ، اعضاش براش کاملا تفکیک شده هستن . اعضای TransparentControl هم کاملا تفکیک شده هستند . باور کنید اونجوری همه چیز قاتی پاتی میشد . الان مثلا 3 تا سایز داریم . تصویر (بیت مپ) میتونه یه سایز داشته باشه . بخش متن هم میتونه یه سایز داشته باشه . خود کنترل TransparentControl هم یه سایزِ مجزا میتونه داشته باشه . اگه همه ی این 3 سایز را داخل کلاس TransparentControl میذاشتم ، حتی اگه اسم هاشون را هم با مثما میدادم ولی باز گیج و گمراه کننده میشد . مخصوصا اینکه فقط سایز نیست . خیلی چیزهای دیگه هستن مثل location و bound و ... که برای هر کدوم مجزا هستند. علاوه بر اینها ، هر کدوم ، اعضای متفاوتی هم داشتن.

علاوه بر اینها ، قبلا کدنویسی ام سخت تر میشد . مثلا برای اینکه مطمئن بشم که طرف میخواد متن را رسم کنه یا نه ، روی متن ، و چندین مورد دیگه ، موقع رسم ، شرط بذارم اما با متدهای سازنده ای که برای TransparentControlText گذاشتم ، الان فقط روی همین شرط میذارم. هر چند هماهنگ سازی شو یه کم فقط سخت تر کرد.
 

the_king

مدیرکل انجمن
چرا .
اتفاقا خیلی کمک میکنه . مخصوصا توی ترتیب و دسته بندی کدها . مخصوصا برای کسایی که مبتدی تر هستند.

از خودتون سبک اختراع کردید، دسته بندی مشخصه ها رو با کلاس سازی انجام نمیدن. دسته بندی مشخصه ها توسط صفت CategoryAttribute انجام میشه، مثلا مشخصه های که جزو گروه Appearance یا Data یا Design یا Layout و ... هستند. در PropertyGrid مشخصه ها بر اساس اون گروه بندی که در صفت Category مشخص میشه قابل تفکیک هستند، خیلی واضح و مشخص و اصولی.
category.png


با این دسته بندی ، الان کسی که میخواد فقط از بیت مپ و تصویرش استفاده کنه ، از همون کلاس شی میسازه ؛ اعضای مربوط به تصویر هم جدا هستند . کسی هم که میخواد با متن کار کنه هم همینطور و حتی کسی که با هر دوشون میخواد کار کنه ، اعضاش براش کاملا تفکیک شده هستن . اعضای TransparentControl هم کاملا تفکیک شده هستند . باور کنید اونجوری همه چیز قاتی پاتی میشد . الان مثلا 3 تا سایز داریم . تصویر (بیت مپ) میتونه یه سایز داشته باشه . بخش متن هم میتونه یه سایز داشته باشه . خود کنترل TransparentControl هم یه سایزِ مجزا میتونه داشته باشه . اگه همه ی این 3 سایز را داخل کلاس TransparentControl میذاشتم ، حتی اگه اسم هاشون را هم با مثما میدادم ولی باز گیج و گمراه کننده میشد . مخصوصا اینکه فقط سایز نیست . خیلی چیزهای دیگه هستن مثل location و bound و ... که برای هر کدوم مجزا هستند. علاوه بر اینها ، هر کدوم ، اعضای متفاوتی هم داشتن.

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

تازه شما مواردی رو به انتخاب کاربر گذاشتید که اصلا وظیفه اش تنظیم شون نیست و اختلال ایجاد میکنه، فقط مشکل کلاس سازی که نیست. از نگهداری منابعی مثل Brush ها گرفته تا تنظیم StringFormat ای که باید بر اساس RightToLeft بودن کنترل و والد و کنترل جد و آبادش و مشخصه هایی مثل UseMnemonic و مواردی مثل فشار دادن کلید Alt در صفحه کلید تغییر مقدار بده و تنظیم دستی Rectangle متن در میان کنترل هایی که همگی بر اساس AutoScaleMode فرم عمل می کنند و ...
Rectangle متن و StringFormat و Brush و ... باید موقع رسم ساخته بشن و بعد رسم دور ریخته بشن، تنظیمات نیستند که جایی نگهشون دارید.
کار که شما در کنترل تون می کنید با اصول رعایت شده در ویژوال استدیو جور در نمیاد و ساز مخالف میزنه.
شما همیشه در کد نویسی مختارید که اصولی و غیر اصولی عمل کنید، دقیقا مثل اتاق مرتب یا شلخته و نامرتب میمونه. تا وقتی برای خودتون کد نویسی می کنید مثل اتاق شخصی نامرتب بودنش مهم نیست، می توانید با کلاس گروه بندی کنید. دست تون بازه. اما وقتی اینکار رو با کمپوننت ای که برای سایرین می نویسید بکنید مثل نامرتب بودن سالن پذیرایی مهم میشه.
تاثیر غیر اصولی بودن کد نویسی در نتیجه واضحه. فهمیدن اینکه کجا اصولی هست یا نیست هم راحته، همیشه می توانید با موارد مشابه مقایسه کنید و بببینید در خود NET. یا تولیدات شرکت های مطرح، پیاده سازی شون شبیه کار شما هست یا نه. اگر دیدید خیلی متفاوت از اونها شده بدونید دارید از اصول دور میشید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
از خودتون سبک اختراع کردید، دسته بندی مشخصه ها رو با کلاس سازی انجام نمیدن. دسته بندی مشخصه ها توسط صفت CategoryAttribute انجام میشه، مثلا مشخصه های که جزو گروه Appearance یا Data یا Design یا Layout و ... هستند. در PropertyGrid مشخصه ها بر اساس اون گروه بندی که در صفت Category مشخص میشه قابل تفکیک هستند، خیلی واضح و مشخص و اصولی.
مشاهده پیوست 112641


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

تازه شما مواردی رو به انتخاب کاربر گذاشتید که اصلا وظیفه اش تنظیم شون نیست و اختلال ایجاد میکنه، فقط مشکل کلاس سازی که نیست. از نگهداری منابعی مثل Brush ها گرفته تا تنظیم StringFormat ای که باید بر اساس RightToLeft بودن کنترل و والد و کنترل جد و آبادش و مشخصه هایی مثل UseMnemonic و مواردی مثل فشار دادن کلید Alt در صفحه کلید تغییر مقدار بده و تنظیم دستی Rectangle متن در میان کنترل هایی که همگی بر اساس AutoScaleMode فرم عمل می کنند و ...
Rectangle متن و StringFormat و Brush و ... باید موقع رسم ساخته بشن و بعد رسم دور ریخته بشن، تنظیمات نیستند که جایی نگهشون دارید.
کار که شما در کنترل تون می کنید با اصول رعایت شده در ویژوال استدیو جور در نمیاد و ساز مخالف میزنه.
شما همیشه در کد نویسی مختارید که اصولی و غیر اصولی عمل کنید، دقیقا مثل اتاق مرتب یا شلخته و نامرتب میمونه. تا وقتی برای خودتون کد نویسی می کنید مثل اتاق شخصی نامرتب بودنش مهم نیست، می توانید با کلاس گروه بندی کنید. دست تون بازه. اما وقتی اینکار رو با کمپوننت ای که برای سایرین می نویسید بکنید مثل نامرتب بودن سالن پذیرایی مهم میشه.
تاثیر غیر اصولی بودن کد نویسی در نتیجه واضحه. فهمیدن اینکه کجا اصولی هست یا نیست هم راحته، همیشه می توانید با موارد مشابه مقایسه کنید و بببینید در خود NET. یا تولیدات شرکت های مطرح، پیاده سازی شون شبیه کار شما هست یا نه. اگر دیدید خیلی متفاوت از اونها شده بدونید دارید از اصول دور میشید.

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

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

منظورم از دسته بندی ، گروه بندی نبود . یعنی اینکه کلا از اون کلاس ، جدا باشن تا اعضای نامربوط به اون بخش ، در لیستِ اینتلایسنس قرار نگیرن .
تهش من با این منوال درستش میکنم ، چون این کنترل ، سورس باز هست ، هر کس خواست ، به نحوی که دوست داره ، میتونه تغییرش بده دیگه.
ولی من فکر میکنم این جوری بهتره.هم مدیریت کدنویسی اش و هم شلوغ نشدن و هم راحت تر شدن ارتباط برقرار کردن برنامه نویسی که ازش استفاده میکنه.
درباره ی گروه بندی هم خیلی ممنون.
 
آخرین ویرایش:

the_king

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

متنی که رسم اش ضخیم میشه نتیجه اینه که متن بیش از یکبار و روی رسم قبلی رسم شده، بدون اینکه زمینه اش کامل پاک بشه و دوباره رسم بشه. تا اینجای قضیه که بدیهی است.
حالا دلیلش رو باید در منطق پیشفرض کنترل رو ببینید. کنترل بصورت پیشفرض هر زمان که لازم باشه رسم مجدد بشه OnPaint رو فراخوانی می کنه. شما در کد هایی که خودتون می نویسید چنین کاری رو نکردید ولی روال پیشفرض در سایر بخش ها همینه. و در OnPaint هم توجهی به این نبوده که کنترل شما Transparent ئه و باید اول هر چی پشت اش هست رسم بشه.
در مثال کنترل شما ایراد اینطور معنی میده که کنترل، با تغییر یک مشخصه یا یک رخداد استاندارد، خیلی عادی درخواست رسم مجددش رو کرده، از این طریق که OnPaint فراخوانی شده. اون مشخصه یا رخداد پیشفرضی که OnPaint رو فراخوانی کرده هیچ توجهی به روال پیچیده کنترل های Transparent نداره، نمیدونه که کنترل شما همیشه پیش از رسم خودش باید والد و کنترل های پشت سری اش رو رسم کنه، شما در OnPaint هم همچین چیزی رو می بینید، OnPaint کلا هیچ کاری به رسم والد و کنترل های پشت سرش نداره. برای همین کافیه که فقط یکی از اون متد ها یا رخداد های پیشفرض کنترل تون که بر اساس OnPaint طراحی شدن و کدش رو شما ننوشته اید رسم کنترل رو به معنی فراخوانی OnPaint بدونند و اونو فراخوانی کنند.
شما باید OnPaint رو بر اساس ترتیب رسم منطقی (والد، کنترل های پشتی، کنترل خودتون، کنترل های جلویی) بازنویسی کنید تا فقط به رسم کنترل خودتون اکتفا نکنه.
 

SajjadKhati

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


خیلی ممنون استاد علی.
نه . اتفاقا هر جا خودش رسم کنترل ام را انجام داده (یعنی من کنترلِ والدِ TransparentControl را invalidate نکردم و خودش رسم را انجام داده . مثل زمانی که مینیمایز و بعد ماکزیمایز میکنیم) ، مشکلی نداره اما زمانی که من کدِ invalidate کردنِ کنترلِ والدِ TransparentControl را مینویسم ، اون موقع ، متن را ضخیم مینویسه . اتفاقا الان که نگاه کردم ، همون موقع ، بیت مپ را هم ضخیم تر میکنه.
مشکل از کجاست ، نمیدونم!
من که کنترلِ والدِ TransparentControl را invalidate میکنم .
یه زحمتی میکشین و کد را چک کنین؟ چون خیلی مهم هه . من هر چی میگردم و فکر میکنم ، نمیدونم مشکل از کجاست.


شما باید OnPaint رو بر اساس ترتیب رسم منطقی (والد، کنترل های پشتی، کنترل خودتون، کنترل های جلویی) بازنویسی کنید تا فقط به رسم کنترل خودتون اکتفا نکنه.

ترتیبِ رسم اش هم اینجوری هه که اول ، کنترلِ والدِ TransparentControl را فراخونی میکنم .
این کار ، باعثِ اجرایِ رویداد AllParents_Invalidated میشه . در این رویداد ، اول ، کنترل های پشت زمینه (در صورت وجود) ، invalidate میشن . بعد ، تایمر که invalidate کردنِ کنترلِ TransparentControl در اون انجام میشه ، اجرا میشه . چون تایمر ، بعد از اجرای کد قبلی ، اجرا میشه ، پس قبل اش ، کنترل های پشت زمینه ، رسم شدن. بعد هم که در قسمتِ آخرِ رویدادِ OnPaint ، کنترل های جلوی زمینه ، در صورت وجود ، invalidate میشن.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
انگار پروپرتی TextAutoSize در کلاس TransparentControl مشکل داره (مقدارش را true میکنیم) . الان این کد مشکل داره :

کد:
        private void Form1_Load(object sender, EventArgs e)
        {
            TransparentControlText text = new TransparentControlText("salam");
            this.transparentControl = new TransparentControl(text, new Rectangle(new Point(100, 200), new Size(250, 100)), true);

            this.Controls.Add(this.transparentControl);
        }

اما همین کد رو به false تغییر بدیم ، مشکلی نداره :


کد:
private void Form1_Load(object sender, EventArgs e)
        {
            TransparentControlText text = new TransparentControlText("salam");
            this.transparentControl = new TransparentControl(text, new Rectangle(new Point(100, 200), new Size(250, 100)), true);

            this.Controls.Add(this.transparentControl);
        }

نمیدونم مشکل دقیقش از کجاست.
 

SajjadKhati

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


کد:
        private void Form1_Load(object sender, EventArgs e)
        {
            Button btnAutoSize = new Button { Bounds = new Rectangle(10, 10, 100, 35), Parent = this, Text = "AutoSize", BackColor = Color.WhiteSmoke };
            btnAutoSize.MouseUp += new MouseEventHandler(this.Button3_MouseUp);


            TransparentControlText text = new TransparentControlText("salam");
            this.transparentControl = new TransparentControl(text, new Rectangle(new Point(100, 200), new Size(250, 100)), false);
            this.Controls.Add(this.transparentControl);
        }


        private void Button3_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.transparentControl.TextAutoSize = false;
            else if (e.Button == MouseButtons.Right)
                this.transparentControl.TextAutoSize = true;
        }

یه تغییر ریز دیگه ای دادم که فایل اش را آپلود میکنم.
خیلی ممنون
 

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

بالا