راسخون

هزاران نکته در سی شارپ

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

با سلام

در این تاپیک ، یک سری نکات ریز و پر کاربرد در برنامه نویسی سی شارپ را خدمتتان ارائه می دهیم که امید است مورد توجه و رضایت شما کاربران عزیز قرار گیرد./.

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

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

تا قبل از انتشار Dot Net Framework 2.0 این عمل توسط GDI انجام می شد. ولی اکنون با استفاده از متدی به نام CopyFromScreen ، این عمل به سادگی قابل انجام می باشد.

شروع:

برای انجام این کار، ابتدا نیاز داریم یک تصویر Bitmap به اندازه طول و عرض صفحه نمایش ایجاد نماییم.

Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);

سپس یک شی گرافیک از نوع این Bitmap ایجاد نموده و متد CopyFromScreen را روی آن اعمال می نماییم.

Graphics g = Graphics.FromImage(bmp);

 

g.CopyFromScreen(0, 0, 0, 0, bmp.Size);

اکنون شی Bitmap،  دارای تصویر مورد نظر ما می باشد و می توانیم آن را ذخیره نموده (bmp.Save) و یا در داخل یک PictureBox نمایش دهیم.

 

در قطعه کد زیر، یک تصویر از صفحه نمایش تهیه نموده و داخل یک کنترل PictureBox نمایش داده ایم.

if (pictureBox1.Image != null) pictureBox1.Image.Dispose();

Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);

Graphics g = Graphics.FromImage(bmp);

g.CopyFromScreen(0, 0, 0, 0, bmp.Size);

g.Dispose();

pictureBox1.Image = bmp;

pictureBox1.Size = bmp.Size;

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 
01.public partial class Form1 : Form
02.{
03.    public Form1()    {
04.        InitializeComponent();
05.        this.KeyPreview = true; //Form handles keyinput
06.                        // BEFORE textbox/list/... does
07.        this.KeyUp += new KeyEventHandler(Form1_KeyUp);
08.    }
09.    void Form1_KeyUp(object sender, KeyEventArgs e)
10.    {
11.        if (e.KeyCode == Keys.F5)
12.        {
13.            Form5 frm = new Form5();
14.            frm.ShowDialog();
15.            }
16.    }
17.}

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

معمولا متدهایی که بار پردازشی زیادی دارند موجب کندی برنامه میشن
برای جلوگیری از این کار میشه این متد هارو با استفاده از یک Thread متفاوت از Thread اصلی برنامه فراخوانی کرد.

 
1.     
2.using System.Threading;

فرض کنیم این متد رو داریم :

 
1.void DoSomething()
2.{
3....
4.}

تعریف Thread جدید برای متد مورد نظر :

 
1.Thread  myThread = new Thread(new ThreadStart(this.DoSomthing));

فراخوانی متد با استفاده از متد تعریف شده‌:

 
1.myThread.Start();

برای متوقف کردن Thread‌ایجاد شده :

 
1.myThread.Abort();

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

آبجکتهای string در دات نت immutable (غیرقابل تغییر) هستند :‌به این معنا که پس از مقدار گرفتن، دیگر قابل تغییر نیستند.

به مثال زیر دقت کنید :

 
1.string temp = "a";
2.temp = temp + "b";
3.temp += "c";
4.temp += "d";

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

 
1.string s2 = new String('x', Int32.Parse(args[0]));
2.int loops = Int32.Parse(args[1]);
3.  
4.for (int j = 0; j < 10000000; j++) {
5.  string s = "";
6.  for (int i = loops; i > 0; --i)
7.    s += s2;
8.}

بصورت کلی در حالتیکه اعمال تغییرات زیاد روی رشته ها نیاز باشد بهتر است آبجکتی از کلاس StringBuilder ساخته و با خاصیت Append آن کار کنیم.

مثال - پیاده سازی همان کد قبلی :

 
01.string s2 = new String('x', Int32.Parse(args[0]));
02.int loops = Int32.Parse(args[1]);
03.  
04.for (int j = 0; j < 10000000; j++) {
05.  StringBuilder sb = new StringBuilder();
06.  for (int i = loops; i > 0; --i)
07.    sb.Append(s2);
08.  sb.ToString();
09.}

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 
01.private string GenerateRandomString(int size)
02.{
03.    Random r = new Random();
04.    string legalChars = "1234567890";
05.    StringBuilder sb = new StringBuilder();
06.    for (int i = 0; i < size; i++)
07.        sb.Append(legalChars.Substring(r.Next(0, legalChars.Length - 1), 1));
08.    return sb.ToString();
09.}

مثال زير در هر بار كليك دكمه يك رشته ي تصادفي و 6 رقمي از اعداد را نمايش ميدهد:

 
1.private void button1_Click(object sender, EventArgs e)
2.{
3.     MessageBox.Show(GenerateRandomString(6));
4.}

جهت تغيير دادن حروف رشته، متغير legalChars را تغيير دهيد. مثلا براي تركيب حروف بزرگ با اعداد :

 
1.string legalChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 
 
1.String ucode = String.Format("{0:x4}", (int)('a'));
2.  
3.// ucode = 0061

تبدیل به اسکی

 
1.String acode = (((int)('a')).ToString());
2.//acode=97

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

چطوری کلاسی بنویسیم که بتونه بک گراند مربوط به سیستم عامل ویندوز رو توی برنامه های نوشته شده با C# تغییر بده:
برای این کار نیاز به دسترسی به متدی داریم که داخل فایل user32.dll یکی از فایل های کتابخانه ای ویندوزه داریم برای این کار باید از سر فایل using System.Runtime.Interupservice استفاده کنیم که این قدرت رو به ما میده که از یه سری توابع مربوط به فایل های کتاب خانه ای که خارج از فایل پروژه ما هستن استفاده کنیم.

 

using System;
using System.Runtime.InteropServices;


namespace Wallpaper
{
public class WallpaperSetter
{
[DllImport("user32.dll")]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, string pvParam, uint fWinIni);


const uint SPI_SETDESKWALLPAPER = 0x14;
const uint SPIF_UPDATEINIFILE = 0x01;


public void SetWallpaper(string path)
{
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE);
}
}
}
 



و دست آخر ساده ترین حالت استفاده از این کلاس:

private void SetButton_Click(object sender, EventArgs e)
{
new WallpaperSetter().SetWallpaper(FilePath);
}


 
hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

اکثر برنامه نویس ها برای ایجاد آدرس از روش کدی زیر استفاده میکنن:
 

string myPath = rootPath + "\\"+ filename;
یا مانند زیر
string myPath = rootPath + @"\" + filename;

خروجی این کد چه بخواین چه نهواین به این صورت خواهد بود:
rootPath\filename

ولی مشکلی که اینجا ممکنه به وجود بیاد و خیلی وقتا شما متوجه نمیشین اینه که این مسیر تنها هنگام اجرا روی ویندوز جواب میده و اگر مثلا فردا یه کاربری بخواد با نصب فلترم های مربوطه برنامه شما رو روی لینوکس اجرا کنه این کد به هیچ عنوان جواب نخواهد داد!!!!(این کد باید توی لینوکس به این صورت باشه rootPath/filename)

اما برای این کار بهتره شما از تابع Path.Combine که توی سر فایل System.IO وجود داره استفاده کنین. که خودش با استفاده از

Path.DirectorySeperatorChar

و

Path.VolumeSeparatorChar

کاراکتر های مناسب برای ویندوز و هنگامی که برنامه روی لینوکس داره اجرا میشه و انتخاب میکنه و قرار میده.
یکی دیگه از ویژگی های این تابع اینه که در صورتی که شما بنا به هر دلیلی داده ای که از نظر سیستم عامل کاراکتر های نامناسب شناخته میشن و داخل مسیر استفاده کنین کنترل کرده و در صورت وجود کاراکتر نامناسب اقدام به پرتاب استثناء میکنه.

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

تا حالا شده برنامه ای تحت ویندوز نوشته باشین و بخواین که این برنامه بدون هیچ گونه تغییری در اون به همون شکل داخل بروزر های مختلف نمایش داده شود؟
در این صورت شما قادر خواهین بود که برنامه نوشته شده خودتون رو به صورت سایت در بیارین و به این صورت نمایش بدین با داشتن کمترین دانش برنامه نویسی در مورد وب نویسی

برای شروع یک برنامه WinForm ساده پیاده سازی کنین و بعد از تست عملکردش وقتی مطمئن شدین که برنامه به طور کامل کار میکنه کار اصلی ما شروع میشه.

بعد از ایجاد برنامه وارد صفحه تنظیمات پروژه خودتون توی ویژوال استودیو بشین و Output Type رو روی ClassLibrary قرار بدین و از برنامه کامپایل بگیرین. در این صورت کل برنامه نوشته شده شما به صورت فایل کتابخانه ای آماده میشه

قدم بعدی کار اصلی ما رو شامل میشه. برای این منظور از VS یک پروژه جدید از نوع Wpf Browser Application ایجاد کنین. داخل Solution Explorer روی References کلیک راست کنین و گزینه Add reference رو انتخاب کنین و فایل کتابخانه ای ساخته شده در مرحله قبل رو به این پروژه اضافه کنین. بعد از اضافه کردن فایل قبلی نیاز داریم تا 2 فایل کتابخانه ای زیر رو هم اضافه کنیم :
Windows Forms Integration و System Windows Forms

خوب حالا نوبت مار اصلی ما میرسه و اون آماده سازی فرم نمایشی هستش. اینجا برای سادگی کار از StackPanel استفاده میکنیم که نمونه کدش میشه مسه زیر(البته این کد رو باید توی فرم اصلی مربوط به این پروژه قرار بدیم)

<Grid>
<StackPanel Margin="0,0,0,0" Name="stackPanel"
HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>

خوب در قدم بعدی باید بریم توی قسمت کد زنی معمولی
من اینجا فقط کد ها رو میزارم چون بقیش خیلی سادس:
 

using System.Windows.Controls;
using System.Windows.Forms.Integration;
using WinFormProject;


namespace NewProject1
{

public partial class Page1 : Page
{
private readonly MainForm mainForm = new MainForm();//این شی از فایل WinFormProject ایجاد شده است


public Page1()
{
InitializeComponent();


//Create a Windows Forms Host to host a form
WindowsFormsHost windowsFormsHost = new WindowsFormsHost();

stackPanel.Width = mainForm.Width;
stackPanel.Height = mainForm.Height;
windowsFormsHost.Width = mainForm.Width;
windowsFormsHost.Height = mainForm.Height;

mainForm.TopLevel = false;


windowsFormsHost.Child = mainForm;


stackPanel.Children.Add(windowsFormsHost);
}
}
}

و اما آخرین قدم در اجرای این کار ها:

وارد Properties مربوط به پروژه جدید میشیم و میریم توی تب Security و اونجا گزینه This is a full trust application رو انتخاب میکنیم .

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

امیدوارم به کارتون بیاد

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if ((int)e.KeyChar >= 48 && (int)e.KeyChar < 58)
        e.KeyChar = (char)(1632 + int.Parse(e.KeyChar.ToString()));
}
hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 
private const int CP_NOCLOSE_BUTTON = 0x200;
 
 
 
protected override CreateParams CreateParams
 
{
 
    get
 
    {
 
        CreateParams myCp = base.CreateParams;
 
        myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
 
        return myCp;
 
    }
 
}

 

hosseinb68 کاربر طلایی1
|
تعداد پست ها : 1269
|
تاریخ عضویت : بهمن 1389 

private void GetInstalledPrograms()
        {
            RegistryKey localmachine = Registry.LocalMachine;
            RegistryKey Uninstall = localmachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninst  all");
 
            foreach (string key in Uninstall.GetSubKeyNames())
            {
                RegistryKey activeKey = Uninstall.OpenSubKey(key);
                string displayName = (string)activeKey.GetValue("DisplayName");
 
                if (!String.IsNullOrEmpty(displayName))
                    listBox1.Items.Add(displayName);
            }
        }

nazarianali کاربر طلایی3
|
تعداد پست ها : 1442
|
تاریخ عضویت : بهمن 1389 

نحوه ایجاد فرم About بدون کد نویسی و طراحی فرم


شما می توانید ، یک فرم About ("در باره برنامه" .. یا بعضا "در برباره ما ")، به پروژه خود اضافه کنید. بدون اینکه کد نویسی برای قسمت های مختلف آن انجام بدین.
برای این کار روی نام سولوشن برنامه کلیک راست کنید، و از گزینه properties ،تب مربوط به Application را انتخاب کنید. (Default Tab)
سپس روی گزینه Assembly Information کلیک کنید تا پنجره مربوط به Assembly Information باز شود.


پس از پر کردن فیلد ها با اطلاعات دلخواه شما، از منوی project و از گزینه Add New Item یک AboutBox به فرم خود اضافخ کنید. (به عنوان نمونه ABoutBox1)

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


 new AboutBox1().ShowDialog(this);

nazarianali کاربر طلایی3
|
تعداد پست ها : 1442
|
تاریخ عضویت : بهمن 1389 

جلوگیری از رخ دادن Unhandled Exceptions

در فایل program.cs مربوط به پروژه بعد از دستورات زیر


Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(fals  e);



دستور زیر رو قرار بدید
 


Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadExce  ption);


و در همون فایل program.cs متدی با همان نامی که در سازنده بالا دادید باید ایجاد کنید مثل متد زیر


static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)

{

    MessageBox.Show("خطا در اجرای دستور کاربر", "خطا");

}


از این به بعد در صورتی که خطایی در قطعه کدی از برنامه رخ بده که درون بلوک try قرار نداشته باشه به این متد فرستاده می شه و دیگه پیام پیش فرض دات نت فریم ورک نمایش داده نمی شه.
نکته : آرگومان e در متد فوق حاوی Exception ایجاد شده می باشد که از آن می توان استفاده های مختلفی کرد.