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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مشکل از اینجا است که راهنمای DrawMode رو نخوندید.
اصلا کاری با OnPaint یا OnPaintBackground نخواهید داشت، شما باید یک آیتم رو رسم کنید. هم در ListBox و هم در ComboBox از رخداد DrawItem استفاده می کنید. رجوع شود به :
ListBox های رنگارنگ و #1300 و 1298# و 1236# و ListBox.DrawItem Event و ComboBox.DrawItem

خیلی ممنون
خوب ، رویداد DrawItem ، آیتم هاش را فقط رسم میکنه (یعنی کنترل کردنِ رسمِ بخشِ list box از کنترلِ combo box را در اختیارمون میذاره) ولی من میخوام رنگ قسمتی از combobox که فِلِش داره (بصورت استاندارد ، در سمت چپ هست و با کلیک روی اون فلش ، listbox مربوط به combobox ، باز میشه) را تغییر بدم . همچنین میخوام رنگ border قسمت edit (رنگِ حاشیه ی قسمتی که میشه ویرایش کرد) را هم تغییر بدم .
 

the_king

مدیرکل انجمن
خیلی ممنون
خوب ، رویداد DrawItem ، آیتم هاش را فقط رسم میکنه (یعنی کنترل کردنِ رسمِ بخشِ list box از کنترلِ combo box را در اختیارمون میذاره) ولی من میخوام رنگ قسمتی از combobox که فِلِش داره (بصورت استاندارد ، در سمت چپ هست و با کلیک روی اون فلش ، listbox مربوط به combobox ، باز میشه) را تغییر بدم . همچنین میخوام رنگ border قسمت edit (رنگِ حاشیه ی قسمتی که میشه ویرایش کرد) را هم تغییر بدم .
باید کنترل خودتون رو از پایه بسازید، چون دیگه نمی خواهید از تم استاندارد ویندوز استفاده بشه.
 

the_king

مدیرکل انجمن
البته میتوانید با ترفند هایی مثل قرار دادن یک پنجره غیر فعال روی کنترل مواردی رو شبیه سازی کنید ولی به هر حال اونم دردسر داره
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کاری که من در اینجور موارد انجام میدم الگوریتم پیچیده ای نداره، یک struct به عنوان تنظیمات میسازم که فیلد های اون تنظیم های مورد نظر شما است، با نام مشخص و واضح. اون نام رو هم در اسامی فیلد ها رعایت می کنم و هم در نام کنترل های روی فرم تنظیمات.
با یک روتین مثل LoadSettings مقادیر فیلدهای اون struct پر میشه، حالا منبعش فایله یا Properties.Settings.Default یا Registry یا Stream فرقی نمی کنه. این روتینی است که قبل از اینکه فرم تنظیمات نمایش داده بشه اجرا خواهد شد.
با یک روتین مثل ShowSettings مقادیر فیلد های اون struct در فرم تنظیمات نمایش داده میشه، بنابر این داخل کلاس فرم نوشته میشه. این روتین برای مواقعی است که رخداد Form.Shown اجرا میشه.
با یک روتین مثل UpdateSettings مقادیر فیلد های اون struct با مقادیر انتخاب شده در فرم تنظیمات بروز میشن، این روتین برای مواقعی است که دارید فرم تنظیمات رو OK می کنید تا بسته بشه.
با یک روتین مثل SaveSettings تنظیمات داخل struct ثبت خواهند شد، در فایل یا Properties.Settings.Default یا Registry یا Stream یا هر چیز دیگری. این روتینی است که بعد از اینکه پنجره تنظیمات بسته شد و قصد ثبت شون رو دارید اجرا میشه.
از اونجایی که تنظیمات در struct ذخیره میشه می توانید یک نسخه قبل از ارسال به فرم تنظیمات داشته باشید و یک نسخه بعد از ارسال به فرم بدست بیارید و با هم مقایسه کنید.

از طرف دیگه شما لیست فیلد ها و لیست کنترل ها رو با اسم مشخص در اختیار دارید، چه در فرم که به Controls دسترسی دارید و چه در struct که به GetType().GetFields و مواردی از این دست دسترسی دارید.
پس نیازی نیست که حتما دونه دونه مقادیر رو سطر به سطر بین کنترل و struct با کد نویسی ربط بدید یا موقع خوندن مقادیر از فایل یا نوشتن در فایل دونه دونه شون رو با اسم مشخص کنید.
شما می توانید با حلقه foreach از قابلیت مجموعه Controls یا System.Reflection استفاده کنید و کدی رو بنویسید که حتی اگه تنظیمی به struct یا فرم اضافه شد بدون نیاز به تغییر کد درست عمل کنه.
مثلا وقتی میخواد برای فیلد bool AutoStartup کنترلی برای نمایش پیدا کنه، دنبال radioButton" + System.Reflection.FieldInfo.Name" روی فرم بگرده و برعکس.

سلامی مجدد
خیلی ممنون استاد.
میگم به نظرتون بجای قضیه ی استفاده از استراکچر ، همین روشی که گفتید را بجای استراکچر ، از یک dictionary (یا از یک hashtable یا کلا از یک کلاسی که ساختار key/value داره) استفاده کنیم ، بهتر نیست؟
key اش را از نوع رشته در نظر میگیریم تا بجاش نام فیلدها را در نظر بگیریم و بجای value هم مقدار اون فیلد را میریزیم توش .
جستجو هم در این نوع کلاس های کالکشن ، بهتره .
نظرتون چیه؟
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد.
میگم به نظرتون بجای قضیه ی استفاده از استراکچر ، همین روشی که گفتید را بجای استراکچر ، از یک dictionary (یا از یک hashtable یا کلا از یک کلاسی که ساختار key/value داره) استفاده کنیم ، بهتر نیست؟
key اش را از نوع رشته در نظر میگیریم تا بجاش نام فیلدها را در نظر بگیریم و بجای value هم مقدار اون فیلد را میریزیم توش .
جستجو هم در این نوع کلاس های کالکشن ، بهتره .
نظرتون چیه؟
نه. دارید در مورد نگهداری داده در حافظه RAM صحبت می کنید که ربطی به قضیه نگهداری و فراخوانی داده از فایل نداره. در ضمن key در جداول مثل دیکشنری نیست که همیشه یک فیلد باشه. جدول ممکنه چند تا key داشته باشه که مربوط به ارتباط با جداول متفاوتی هستند.
شما دارید مثال برای نحوه نگهداری داده در حافظه RAM میزنید که ناپایدار ئه، ربطی به بحث سیستم ذخیره سازی داده پایدار و ساختار اش نداره. مثل اینه که بگید من بجای png از آرایه دو بعدی استفاده کنم. شما هر سیستم مدیریت پایگاه داده یا سیستم مدیریت فایل ای که استفاده کنید، می توانید داده هاتون رو بخونید و در Dictionary ها هر ساختار دیگری در حافظه RAM قرار بدید، اما ذخیره سازی پایدار ساختارش جدا است.
 

SajjadKhati

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

خیلی ممنون استاد .
استاد ، من دقیق متوجه نشدم . شاید شما منظور منو خوب درک نکردین .
اول بذارید یه سئوال بپرسم ازتون که ببینم درک من از درکی که شما از سئوال من کردین ، درسته.
شما فکر میکنید که من استفاده از dictionary یا hashtable را بجای ذخیره سازی در دیتابیس sqlite گفتم؟ یعنی اینکه فکر میکنید که من بجای اینکه از دیتابیس sqlite برای ذخیره سازی استفاده کنم ، گفتم بجاش از dictionary یا hashtable استفاده کنم؟
منظورم این نیست ها . منظورم اینه که همونطور که در پست 1229 گفتم :

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

میخوام در صفحه ی تنظیمات ، وقتی کاربر فقط دکمه ی ok را زد ، در اون صورت بفهمم که چه گزینه ای را تغییر داد تا فقط عملیات مربوط به همون تغییرات را هم ذخیره سازی و هم انجام بدم .
که شما قضیه ی استراکچر را گفتین که نقل قول کردم . (و گفتین که با Reflection میتونم مقایسه کنم)
حالا میگم بجای استراکچر ، از dictionary یا hashtable استفاده کنم ، بهتر نیست؟ (برای مقایسه کردن هم key داره و توابع خوبی واسه ی جستجو داره و حس میکنم کار باهاش خیلی راحت تر از ساختن یه استراکچر باشه) . جستجوش هم راحت تره .
یا حتی بجای اینها ، استفاده از DataTable . چطوره؟ (منظورم برای ذخیره سازی نیست . منظورم فقط برای مقایسه ی تغییرات دو جدول هست).
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
استاد ، من دقیق متوجه نشدم . شاید شما منظور منو خوب درک نکردین .
اول بذارید یه سئوال بپرسم ازتون که ببینم درک من از درکی که شما از سئوال من کردین ، درسته.
شما فکر میکنید که من استفاده از dictionary یا hashtable را بجای ذخیره سازی در دیتابیس sqlite گفتم؟ یعنی اینکه فکر میکنید که من بجای اینکه از دیتابیس sqlite برای ذخیره سازی استفاده کنم ، گفتم بجاش از dictionary یا hashtable استفاده کنم؟
منظورم این نیست ها . منظورم اینه که همونطور که در پست 1229 گفتم :

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

میخوام در صفحه ی تنظیمات ، وقتی کاربر فقط دکمه ی ok را زد ، در اون صورت بفهمم که چه گزینه ای را تغییر داد تا فقط عملیات مربوط به همون تغییرات را هم ذخیره سازی و هم انجام بدم .
که شما قضیه ی استراکچر را گفتین که نقل قول کردم . (و گفتین که با Reflection میتونم مقایسه کنم)
حالا میگم بجای استراکچر ، از dictionary یا hashtable استفاده کنم ، بهتر نیست؟ (برای مقایسه کردن هم key داره و توابع خوبی واسه ی جستجو داره و حس میکنم کار باهاش خیلی راحت تر از ساختن یه استراکچر باشه) . جستجوش هم راحت تره .
یا حتی بجای اینها ، استفاده از DataTable . چطوره؟ (منظورم برای ذخیره سازی نیست . منظورم فقط برای مقایسه ی تغییرات دو جدول هست).
در سوال تون سه بحث جدا داریم، یکی اعمال تغییرات، دوم ذخیره سازی تغییرات، سوم شیوه دسترسی و جنس تنظیمات. اولی که پیاده سازیش خیلی ساده و سر راسته، مقدار فعلی تنظیمات رو در حافظه برنامه دارید، چون ممکنه بارها بهش رجوع بشه. موقعی که روی OK کلیک میشه اول اطلاعات وارد شده رو Validate می کنید تا مقدار نامعتبر در فرم تون نباشه چون امکان استفاده اش نیست. بعد دونه دونه مقادیر جدید داخل فرم رو با مقدار فعلی تنظیم مقایسه می کنید، اگر تغییر کرد اعمال میشه، نکرد نمیشه. میمونه بخش ذخیره سازی. ذخیره سازی هم کل تنظیمات رو یکجا ذخیره میکنه.
در خیلی موارد اصلا مهم نیست که چیزی تغییر کرده یا نکرده، یعنی OK همه رو اعمال میکنه. اعمال کردنش هم سربار خاصی نداره که بگیم اگر تغییر نکرد نباید اعمال بشه. اما در بعضی موارد چرا، ارزش داره که قبلش بررسی بشه.

اما در بحث جنس تنظیمات، تنظیمات خیلی به ندرت از یک جنس مشابه هستند، Dictionary یا هر مورد دیگری خیلی برای این منظور که value ها از یک جنس نیستند ایده آل نیست. تبدیل شون به نوعی مثل string هم صرفا باید در بخش ذخیره سازی انجام بشه که برای دسترسی به مقادیر که بارها ممکنه انجام بگیره مناسب نیست. در ضمن تنظیمات اونقدر گسترده و جستجو و مقایسه عجیب غریبی نداره که نیازی به hashtable و DataTable و ... باشه. شما در روتین فراخوانی اطلاعات یا روتین ذخیره سازی شاید List و Dictionary و ... کمک تون کنه، اما برای برای نگهداری و دسترسی به تنظیمات، به نظر من نه. مناسب نیستند، اگر بودند که خودم توصیه می کردم.

در بحث ذخیره سازی، شما تنظیمات رو به این شکل می بینید و فرض می کنید که هر آیتم در یک محل جدا ذخیره سازی میشه و ارتباطی با سایرین نداره و ذخیره کردن یک آیتم هم تاثیری در روال ذخیره کردن سایر آیتم ها نداره. بنابر این فرض رو بر این میذارید که اگر من میخواهم x رو ذخیره کنم، پس کاری به y نداشته باشم چون تغییری نکرده. همچین چیزی فقط در مورد مواردی مثل Registry برقراره که ذخیره سازی ها ذاتا مستقل ئه. در سایر موارد چه دلتون بخواد و چه نخواد وقتی x رو ذخیره می کنید، تمامی محتویات تنظیمات بازنویسی میشه، y و z هم بازنویسی میشن، چه تغییر کرده باشن و چه نکرده باشن. مثل یک فایل option.ini، یا مثل فایل application.exe.config در Properties.Settings
در خود Registry هم ذخیره شدن مجددا تنظیمات روال عادی اغلب برنامه ها است، یعنی نرم افزار ها مشکلی با این قضیه ندارن که با OK کردن همه تنظیمات رو مجددا بنویسند، کاری ندارند که چی تغییر کرد و چی نکرد.
بنابر این لزومی نداره موقع ذخیره سازی به این فکر کنید که چی تغییر کرده بود و چی تغییر نکرده بود، همه شون رو باید از اول تا آخر بنویسید، هم کدش ساده تره و هم نتیجه همونه.
 

SajjadKhati

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

اما در بحث جنس تنظیمات، تنظیمات خیلی به ندرت از یک جنس مشابه هستند، Dictionary یا هر مورد دیگری خیلی برای این منظور که value ها از یک جنس نیستند ایده آل نیست. تبدیل شون به نوعی مثل string هم صرفا باید در بخش ذخیره سازی انجام بشه که برای دسترسی به مقادیر که بارها ممکنه انجام بگیره مناسب نیست. در ضمن تنظیمات اونقدر گسترده و جستجو و مقایسه عجیب غریبی نداره که نیازی به hashtable و DataTable و ... باشه. شما در روتین فراخوانی اطلاعات یا روتین ذخیره سازی شاید List و Dictionary و ... کمک تون کنه، اما برای برای نگهداری و دسترسی به تنظیمات، به نظر من نه. مناسب نیستند، اگر بودند که خودم توصیه می کردم.

در بحث ذخیره سازی، شما تنظیمات رو به این شکل می بینید و فرض می کنید که هر آیتم در یک محل جدا ذخیره سازی میشه و ارتباطی با سایرین نداره و ذخیره کردن یک آیتم هم تاثیری در روال ذخیره کردن سایر آیتم ها نداره. بنابر این فرض رو بر این میذارید که اگر من میخواهم x رو ذخیره کنم، پس کاری به y نداشته باشم چون تغییری نکرده. همچین چیزی فقط در مورد مواردی مثل Registry برقراره که ذخیره سازی ها ذاتا مستقل ئه. در سایر موارد چه دلتون بخواد و چه نخواد وقتی x رو ذخیره می کنید، تمامی محتویات تنظیمات بازنویسی میشه، y و z هم بازنویسی میشن، چه تغییر کرده باشن و چه نکرده باشن. مثل یک فایل option.ini، یا مثل فایل application.exe.config در Properties.Settings
در خود Registry هم ذخیره شدن مجددا تنظیمات روال عادی اغلب برنامه ها است، یعنی نرم افزار ها مشکلی با این قضیه ندارن که با OK کردن همه تنظیمات رو مجددا بنویسند، کاری ندارند که چی تغییر کرد و چی نکرد.
بنابر این لزومی نداره موقع ذخیره سازی به این فکر کنید که چی تغییر کرده بود و چی تغییر نکرده بود، همه شون رو باید از اول تا آخر بنویسید، هم کدش ساده تره و هم نتیجه همونه.


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

_____________________________________

بعد اینکه یه قضیه ی عجیبی که برام پیش اومد اینه که قبلا چند کنترل TransparentControl را توی پنل ای قرار دادم . توی انواع پروپرتی هاش هم دستکاری میکردم و کلا از موقعی که نوشته بودم تا حالا ، دارم ازش استفاده میکنم و مشکلی نبود .
اما الان توی رویداد shown فرم ، که قبلا متد Redraw شون (متدی هه که باعث invalidate شدن والد و بعد خود همین کنترل میشه) را صدا زدم را پاک کردم ، یه دفعه توی دیزاین فرم که برگشتم ، دیدم هیچ کنترل TransparentControl ای را نشون نمیده و همینطور پروژه را هم که استارت میزنم ، این کنترل ها را نشون نمیده اما توی کدهای قسمت دیزاین ، همه ی اشیای TransparentControl با همه اون پروپرتی هاش (مثل سایز و کلا هر مقادیری که داده بودم) و همچنین حتی پروپرتی های بیت مپ اش که در فایل resx فرم ذخیره شده بودند ، درست بود و حتی هیچ اروری نمیداد و پروژه هم اجرا میشد اما فقط TransparentControl ها را نشون نمیداد .
چرا؟
فکر هم نکنم ربطی به متدRedraw داشته باشه . این متد را دوباره هم گذاشتم اما درست نشد.
واسه ی من خیلی جای تعجب داره . همچین چیزی تا حالا ندیدم.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک چیز دیگه اینکه اون قضیه ی CoInitializeSecurity که قبلا بحث کرده بودیم ، آخر بخاطر این در پروژه های ویندوز فرم قابل استفاده نبود چون متد Main در این نوع پروژه ها ، اتریباتسِ STAThread داره که این اتریباتس ، داخل خودش ، این متد CoInitializeSecurity را فراخونی میکنه و چون این متدِ CoInitializeSecurity برای هر پروسه ، بیشتر از یکبار نمیتونه فراخونی بشه ، واسه ی همین در این نوع پروژه ها قابل استفاده نیست . درسته؟
یعنی مشکل از سی شارپ نیست . درسته؟
اگه آره ، پس میتونیم یه پروژه ی مثلا کنسول یا حتی سرویس ای بنویسیم که از طریق این نوع پروژه ها ، متد CoInitializeSecurity را فراخونی کنیم . درسته؟ (پروژه ی dll شدنی نیست . هست؟)
و بعد هم بجای اینکه عملیات مربوط به بکاپ (مثل بکاپ گرفتن و حذف بکاپ و ...) را از پروژه ی ویندوز فرم انجام بدیم ، از این نوع پروژه ها انجام بدیم اما دستورات را از توابع ویندوز فرم براشون ارسال کنیم . درسته؟

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

ویرایش :

نه .
لینک زیر میگه مشکل از clr هه که قبلا متد CoInitializeSecurity را توی خودش صدا زد . بنابراین وقتی متد Main یا هر کد دیگه ای در سی شارپ بخواد شروع بشه ، چون قبل اش clr شروع شده بود ، مشکل خواهئد داشت (البته قبلا هم اینو خونده بودم) :

pinvoke.net: CoInitializeSecurity (ole32)

اما من متوجه ی راه حلی که داد نشدم :

The workaround is to write an unmanaged "shim" that will call CoInitializeSecurity, then activate and call into managed code. You can do this via an export from a mixed-mode C++ DLL, by registering a managed component for use by COM, or by using the CLR hosting API.
RPC_E_TOO_LATE (Update from Yahor Sinkevich):
Usually RPC_E_TOO_LATE happens when CoInitializeSecurity already called (implicitly or explicitly, it does no matter). When you using Visual Studio, it use so called "Visual Studio Hosting Process" where CoInitializeSecurity already called. Turn off Visual Studio hosting process and have fun, now you can debug your application that calls CoInitializeSecurity with no RPC_E_TOO_LATE error.

اولش میگه توی سی پلاس پلاس ای که unmanaged هست ، اون تابع CoInitializeSecurity را فراخونی کنیم و بصورت فایل dll دربیاریم . بعد توی سی شارپ ، توسط استفاده از api های CLR hosting ازش میتونیم استفاده کنیم (استفاده از CLR hosting سخت هه؟) البته اون روش اش را که گفت با ثبت کردن کمپوننت managed برای استفاده توسط com را متوجه نشدم .
 
آخرین ویرایش:

SajjadKhati

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

استاد ، فکر کنم احتمالا زمان هایی که به هر دلیل (نه فقط به دلیل کنترل TransparentControl) ، مثلا به دلیل کنترل های دیگه ، دیزاینر ، ارور بده ، بعدش کنترل های TransparentControl ، نمایش داده نمیشن و قاتی میکنن کلا .
حالا دقیق نمیدونم . شاید این طور نباشه .
 

the_king

مدیرکل انجمن
یک چیز دیگه اینکه اون قضیه ی CoInitializeSecurity که قبلا بحث کرده بودیم ، آخر بخاطر این در پروژه های ویندوز فرم قابل استفاده نبود چون متد Main در این نوع پروژه ها ، اتریباتسِ STAThread داره که این اتریباتس ، داخل خودش ، این متد CoInitializeSecurity را فراخونی میکنه و چون این متدِ CoInitializeSecurity برای هر پروسه ، بیشتر از یکبار نمیتونه فراخونی بشه ، واسه ی همین در این نوع پروژه ها قابل استفاده نیست . درسته؟
یعنی مشکل از سی شارپ نیست . درسته؟
اگه آره ، پس میتونیم یه پروژه ی مثلا کنسول یا حتی سرویس ای بنویسیم که از طریق این نوع پروژه ها ، متد CoInitializeSecurity را فراخونی کنیم . درسته؟ (پروژه ی dll شدنی نیست . هست؟)
و بعد هم بجای اینکه عملیات مربوط به بکاپ (مثل بکاپ گرفتن و حذف بکاپ و ...) را از پروژه ی ویندوز فرم انجام بدیم ، از این نوع پروژه ها انجام بدیم اما دستورات را از توابع ویندوز فرم براشون ارسال کنیم . درسته؟

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

ویرایش :

نه .
لینک زیر میگه مشکل از clr هه که قبلا متد CoInitializeSecurity را توی خودش صدا زد . بنابراین وقتی متد Main یا هر کد دیگه ای در سی شارپ بخواد شروع بشه ، چون قبل اش clr شروع شده بود ، مشکل خواهئد داشت (البته قبلا هم اینو خونده بودم) :

pinvoke.net: CoInitializeSecurity (ole32)

اما من متوجه ی راه حلی که داد نشدم :

The workaround is to write an unmanaged "shim" that will call CoInitializeSecurity, then activate and call into managed code. You can do this via an export from a mixed-mode C++ DLL, by registering a managed component for use by COM, or by using the CLR hosting API.
RPC_E_TOO_LATE (Update from Yahor Sinkevich):
Usually RPC_E_TOO_LATE happens when CoInitializeSecurity already called (implicitly or explicitly, it does no matter). When you using Visual Studio, it use so called "Visual Studio Hosting Process" where CoInitializeSecurity already called. Turn off Visual Studio hosting process and have fun, now you can debug your application that calls CoInitializeSecurity with no RPC_E_TOO_LATE error.

اولش میگه توی سی پلاس پلاس ای که unmanaged هست ، اون تابع CoInitializeSecurity را فراخونی کنیم و بصورت فایل dll دربیاریم . بعد توی سی شارپ ، توسط استفاده از api های CLR hosting ازش میتونیم استفاده کنیم (استفاده از CLR hosting سخت هه؟) البته اون روش اش را که گفت با ثبت کردن کمپوننت managed برای استفاده توسط com را متوجه نشدم .
اولا یادتون نگهدارید که هیچ Attribute ای خودش هیچ کدی رو در مورد فلان چیزی که بهش نسبت میدید اجرا نمی کنه، صفت فقط یک نشانه است برای متد هایی که نسبت به وجود اون صفت حساس هستند.
این متد های دیگری هستند که ممکنه طوری کد نویسی بشن که بررسی کنند که آیا در مورد فلان آیتم Attribute خاصی بکار برده شده یا نه و اگر بکار برده شده پس حالا بیا فلان کار رو انجام بده.
پس اینکه بگیم STAThreadAttribute یا هر صفت دیگری فلان کار رو انجام داد اشتباهه. STAThreadAttribute موجب میشه که فلان کار صورت بگیره، خودش کاری انجام نمیده.

منظور اون راهنمایی اینه که شما فایل اجرایی برنامه تون یک ++C از نوع Unmanaged باشه که داخلش CoInitializeSecurity رو خودتون فراخوانی کنید و #C تون رو بصورت یک dll برایش بکار ببرید، یعنی برنامه اصلی تون رو به زبان #C نخواهید نوشت. برای ارتباط بین ++C و #C باید متد های dll تون که به زبان #C ئه رو باید بصورت متد های COM (مثل ActiveX) ها تعریف بشه که ++C بتونه بصورت یک کتابخانه ActiveX بهش دسترسی داشته باشه، چون ++C نمیتونه با کتابخانه ای که برای NET. نوشته شده ارتباط برقرار کنه :
ComVisibleAttribute Class

استاد ، فکر کنم احتمالا زمان هایی که به هر دلیل (نه فقط به دلیل کنترل TransparentControl) ، مثلا به دلیل کنترل های دیگه ، دیزاینر ، ارور بده ، بعدش کنترل های TransparentControl ، نمایش داده نمیشن و قاتی میکنن کلا .
حالا دقیق نمیدونم . شاید این طور نباشه .
خطا مربوط به کد کامپایل شده اسمبلی دیگری نیست، در کد پروژه خودتونه، جای دیگری نگردید. راهی که بتوانید محل پیدایش اش رو پیداش کنید همون استفاده از try catch در کدهاتونه.
 

SajjadKhati

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

منظور اون راهنمایی اینه که شما فایل اجرایی برنامه تون یک ++C از نوع Unmanaged باشه که داخلش CoInitializeSecurity رو خودتون فراخوانی کنید و #C تون رو بصورت یک dll برایش بکار ببرید، یعنی برنامه اصلی تون رو به زبان #C نخواهید نوشت. برای ارتباط بین ++C و #C باید متد های dll تون که به زبان #C ئه رو باید بصورت متد های COM (مثل ActiveX) ها تعریف بشه که ++C بتونه بصورت یک کتابخانه ActiveX بهش دسترسی داشته باشه، چون ++C نمیتونه با کتابخانه ای که برای NET. نوشته شده ارتباط برقرار کنه :
ComVisibleAttribute Class

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

خطا مربوط به کد کامپایل شده اسمبلی دیگری نیست، در کد پروژه خودتونه، جای دیگری نگردید. راهی که بتوانید محل پیدایش اش رو پیداش کنید همون استفاده از try catch در کدهاتونه.

حالا به نظرتون خطا در بخش کدهایی که مربوط به دیزاینرش میشه و نوشته بودم هست (مثل کلاس TransparentControlBitmapEditor و کلاس های مربوط به این کلاس) یا در بخش خود کدهای کنترل؟
یه چیز دیگه اینکه من الان که فقط از dll همین کنترلِ TransparentControl دارم استفاده میکنم ، در قسمت کد نویسی ، توضیحات مربوط به اون پروپرتی یا کلاس یا کلا هر چیزی که قبلا توضیحات را براش نوشته بودم (بصورت تگ summary نوشته بودم) را اصلا نمیاره . چرا؟
در صورتی که قبلا از dll استفاده نمیکردم ، موقع کدنویسی ، توضیحات را میآورد .
چی کار باید کنم که توضیحات تگ summary ای را که نوشته بودم ، توی dll ، زمان کدنویسی بیاره؟

استاد ، الان فکر میکنم ، میگم ای کاش وقتی داشتم این کنترل را میساختم ، بجای استفاده از قابلیت و فلگ Transparent ای که در api ویندوز قرار داشت ، در متد OnPaint ، خودم اول یه عکس از والدِ کنترلِ TransparentControl میگرفتم و بعد رسم دلخواه خودم را روش انجام میدادم . این جوری ، لازم نبود کدهای هماهنگ کردن کنترل های جلویی و پشتی را بنویسم . البته اون موقع نمیدونستم که در این حاتی که دارم کار میکنم ، هماهنگی لازم داره . لازم هم نبود کنترل والد را هی invalidate کنم .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
حالا به نظرتون خطا در بخش کدهایی که مربوط به دیزاینرش میشه و نوشته بودم هست (مثل کلاس TransparentControlBitmapEditor و کلاس های مربوط به این کلاس) یا در بخش خود کدهای کنترل؟
نظر دادنی نیست. مربوط به بخشی میشه که به هر دلیلی اجرا شده، اگر در طی مراحلی که از باز کردن ویژوال استدیو تا بروز مشکل داشتید، اون Editor رو بکار نبرده باشید، منطقی است که بهش ربطی نداشته باشه. وگرنه ملاکی برای پیش داوری ندارید.

یه چیز دیگه اینکه من الان که فقط از dll همین کنترلِ TransparentControl دارم استفاده میکنم ، در قسمت کد نویسی ، توضیحات مربوط به اون پروپرتی یا کلاس یا کلا هر چیزی که قبلا توضیحات را براش نوشته بودم (بصورت تگ summary نوشته بودم) را اصلا نمیاره . چرا؟
در صورتی که قبلا از dll استفاده نمیکردم ، موقع کدنویسی ، توضیحات را میآورد .
چی کار باید کنم که توضیحات تگ summary ای را که نوشته بودم ، توی dll ، زمان کدنویسی بیاره؟
اون فایل xml کنار dll ای که بهش رفرنس دادید هست یا اونو کپی نکردید؟

استاد ، الان فکر میکنم ، میگم ای کاش وقتی داشتم این کنترل را میساختم ، بجای استفاده از قابلیت و فلگ Transparent ای که در api ویندوز قرار داشت ، در متد OnPaint ، خودم اول یه عکس از والدِ کنترلِ TransparentControl میگرفتم و بعد رسم دلخواه خودم را روش انجام میدادم . این جوری ، لازم نبود کدهای هماهنگ کردن کنترل های جلویی و پشتی را بنویسم . البته اون موقع نمیدونستم که در این حاتی که دارم کار میکنم ، هماهنگی لازم داره . لازم هم نبود کنترل والد را هی invalidate کنم .
البته چند بار در مورد اینکه از اون ویژگی استفاده نکنید بهتون توصیه کرده بودم چون میدونستم چقدر دردسر داره و آخرش هم روش تمام عیاری نمیشه، ولی جدا از اون قضیه، روش استفاده از تصویر از پشت بیشتر مناسب مواقعی است که چیزی موقتا نمایش داده میشه و زود هم از حالت نمایش در میاد، مثلا سایه پشت یک Dialog یا یک پنجره Popup و Tooltip و چیزی شبیه به اینها. برای مواقعی که کنترل تون قراره از ابتدا و مدت طولانی باقی بمونه دردسر های خاص خودش رو داره. هم از این بابت که برای گرفتن تصویر از پشت لازمه که هم کنترل کاملا مخفی باشه، هم مکث کافی بکنه تا پشت اش بصورت کامل رسم بشه و هم بعد رسم اگر در پشت تغییری رخ داد یا اصلا متوجه نمیشه یا اگر شد مجبوره این روال رو تکرار کنه و خیلی واضح پر پر بزنه. این اصلا قابل قبول نیست که کنترل یهو مدتی مخفی بشه تا عکس پشت اش بروز بشه. در کل برای کنترل های روی فرم روش مناسبی نیست. اما برای مواقعی که فرضا میخواهید صفحه نمایش رو محو یا تیره کنید یا شدت رنگش رو کم کنید تا روی Dialog ای تاکید کنید روش مناسبیه.
اگه انجمن رو بگردید از اینجور مثال ها داریم :
مشکل در هم رنگ کردن پشت زمینه پیکچر باکس بر روی فرم و سایر کنترل ها
 

SajjadKhati

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

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

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

اون فایل xml کنار dll ای که بهش رفرنس دادید هست یا اونو کپی نکردید؟

فقط یه فایل دیگه با پسوند pdb بنام TransparentControl.pdb ، کنار فایل dll ام بود .
نه . فایل xml را من نه کنار dll و نه هیچ جای دیگه ندیدم .
 

the_king

مدیرکل انجمن
فقط یه فایل دیگه با پسوند pdb بنام TransparentControl.pdb ، کنار فایل dll ام بود .
نه . فایل xml را من نه کنار dll و نه هیچ جای دیگه ندیدم .
تیک گزینه XML documentation file رو در منوی Project > {projectname} Properties... > Build بزنید تا موقع Build شدن dll اون فایل xml رو هم بسازه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
خیلی ممنون استاد .
بله . همونطور که گفتید انجام دادم و فایل xml درست شد .
استاد ، فونت اپلیکیشن مون منتها در قسمت taskbar را میتونیم تغییر بدیم ؟ (متوجه ی منظورم شدین که کدوم قسمت را گفتم؟) اگه آره ، چجوری؟

همچنین استاد ، اگه توی پوشه ی bin مون ، فایل هایی داشته باشیم که چون خیلی زیاد هستن ، نمیدونیم کدوم هاشون توی پروژه مون به عنوان reference هستند و کدوم هاشون نیستند (تا اونهایی که نیستند را حذف کنیم) راهی داره که یه جوری متوجه بشیم؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
خیلی ممنون استاد .
بله . همونطور که گفتید انجام دادم و فایل xml درست شد .
استاد ، فونت اپلیکیشن مون منتها در قسمت taskbar را میتونیم تغییر بدیم ؟ (متوجه ی منظورم شدین که کدوم قسمت را گفتم؟) اگه آره ، چجوری؟
نه. متوجه نشدم.

همچنین استاد ، اگه توی پوشه ی bin مون ، فایل هایی داشته باشیم که چون خیلی زیاد هستن ، نمیدونیم کدوم هاشون توی پروژه مون به عنوان reference هستند و کدوم هاشون نیستند (تا اونهایی که نیستند را حذف کنیم) راهی داره که یه جوری متوجه بشیم؟
خودتون اضافه شون کردید، چطور متوجه نمیشید که کدومها رو لازم دارید. Build > Cleanup کنید و مجددا Build کنید تا اضافی ها حذف شن. فایل pdb برای داده های مربوط به debug کردن پروژه در ویژوال استدیو است، بدون اون هم اجرا میشه ولی در اصل وجودش برای debug لازمه. اصولا در Build نهایی با پروفایل release فایل اجرایی رو میسازید نه با پروفایل debug.
 

SajjadKhati

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

سلامی مجدد
خیلی ممنون
منظورم ، قسمت زیرین در عکسی که میذارم هست (کنار آیکون google chrome . جایی که در قسمت پایین نوشته "پشتیبانگیر طلوع") .

1.JPG

با اونکه فونت فرم ، همون فونتی هست که برابر با همون چیزی هست که متنِ "پشتیبانگیر طلوع" در قسمت نوار عنوان (بالا سمت چپ) نوشته هست اما فونت متنِ "پشتیبانگیر طلوع" ای که در قسمت taskbar (کنار آیکون google chrome) نوشته ، فرق داره .
این فونت را کاری میشه کرد که عوض بشه و براابر با فونت فرم بشه؟

خودتون اضافه شون کردید، چطور متوجه نمیشید که کدومها رو لازم دارید. Build > Cleanup کنید و مجددا Build کنید تا اضافی ها حذف شن. فایل pdb برای داده های مربوط به debug کردن پروژه در ویژوال استدیو است، بدون اون هم اجرا میشه ولی در اصل وجودش برای debug لازمه. اصولا در Build نهایی با پروفایل release فایل اجرایی رو میسازید نه با پروفایل debug.

خیلی ممنون
منظورتون این هست که اون فایل pdb ای که کنار dll تولید میشه را هم در وقتی میخوام از اون dll (در جاهای دیگه) استفاده کنم ، کنارش کپی کنم؟
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون
منظورم ، قسمت زیرین در عکسی که میذارم هست (کنار آیکون google chrome . جایی که در قسمت پایین نوشته "پشتیبانگیر طلوع") .

مشاهده پیوست 112880

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

منظورتون این هست که اون فایل pdb ای که کنار dll تولید میشه را هم در وقتی میخوام از اون dll (در جاهای دیگه) استفاده کنم ، کنارش کپی کنم؟
نه. dll رو وقتی در برنامه دیگری بکار می برید یعنی کد نویسی تموم شده و دیگه کاری با کد برنامه ندارید و debug اش نمی کنید. اینجور مواقع اصولا با پروفایل release کار می کنید و dll میسازید، نه debug.
اگر میخواستید به هر دلیلی موقع پیدا کردن خطا در کتابخانه debug اش کنید که اصلا در اون زمان از dll استفاده نمی کردید و به خود پروژه Reference میدادید، نه به dll
 

SajjadKhati

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

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

بالا