5. رابطهای کاربری گرافیکی با VB.NET و VS.NET
در اینجا، هدف ما نشان دادن نحوه ساخت رابطهای کاربری گرافیکی با استفاده از VB.NET است. ابتدا، ما به کلاسهای پایه پلتفرم .NET که امکان ساخت یک رابط کاربری گرافیکی را برای ما فراهم میکنند، نگاهی خواهیم انداخت. در ابتدا، ما از هیچ ابزار تولید خودکار استفاده نخواهیم کرد. سپس از Visual Studio.NET (VS.NET) استفاده خواهیم کرد، که یک ابزار توسعه مایکروسافت است و توسعه برنامهها با استفاده از زبانهای .NET را تسهیل میکند و بهویژه ایجاد رابطهای کاربری گرافیکی را آسان میسازد. نسخهٔ مورد استفاده از VS.NET، نسخهٔ انگلیسی است.
5.1. مبانی رابطهای کاربری گرافیکی
5.1.1. یک پنجره ساده
کد زیر را در نظر بگیرید:
' گزینهها
Option Strict On
Option Explicit On
' فضاهای نام
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' کلاس فرم
Public Class Form1
Inherits Form
'سازنده
Public Sub New()
' عنوان پنجره
Me.Text = "Mon premier formulaire"
'ابعاد پنجره
Me.Size = New System.Drawing.Size(300, 100)
End Sub
' تابع آزمایشی
Public Shared Sub Main(ByVal args() As String)
' فرم نمایش داده میشود
Application.Run(New Form1)
End Sub
End Class
کد بالا کامپایل شده و سپس اجرا میشود
اجرا پنجره زیر را نمایش میدهد:

یک رابط کاربری گرافیکی معمولاً از کلاس پایه System.Windows.Forms.Form مشتق میشود:
کلاس پایه Form یک پنجرهٔ پایه را با دکمههای بستن و حداکثر/حداقل کردن، اندازهٔ قابل تنظیم و غیره تعریف میکند و رویدادهای این اشیاء گرافیکی را مدیریت میکند. در اینجا با تنظیم عنوان، عرض (300) و ارتفاع (100) آن، کلاس پایه را تخصصی میکنیم. این کار در سازندهٔ آن انجام میشود:
Public Sub New()
' عنوان پنجره
Me.Text = "Mon premier formulaire"
'ابعاد پنجره
Me.Size = New System.Drawing.Size(300, 100)
End Sub
عنوان پنجره توسط خاصیت Text و ابعاد توسط خاصیت Size تعیین میشوند. Size در فضای نام System.Drawing تعریف شده و یک ساختار است. روال Main برنامه گرافیکی را به شرح زیر راهاندازی میکند:
Application.Run(New Form1)
یک فرم از نوع Form1 ایجاد و نمایش داده میشود؛ سپس برنامه منتظر رویدادهایی که روی فرم رخ میدهند (کلیکها، حرکت ماوس و غیره) میماند و آنهایی را که فرم مسئول رسیدگی به آنهاست اجرا میکند. در این مورد، فرم ما هیچ رویدادی را به جز رویدادهایی که توسط کلاس پایه Form مدیریت میشوند (کلیک روی دکمههای بستن و حداکثر/حداقل کردن، تغییر اندازه پنجره، جابجایی پنجره و غیره) مدیریت نمیکند.
5.1.2. یک فرم با یک دکمه
حال بیایید یک دکمه به پنجره خود اضافه کنیم:
' گزینهها
Option Strict On
Option Explicit On
' فضاهای نام
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' کلاس فرم
Public Class Form1
Inherits Form
' ویژگیها
Private cmdTest As Button
' سازنده
Public Sub New()
' عنوان
Me.Text = "Mon premier formulaire"
' ابعاد
Me.Size = New System.Drawing.Size(300, 100)
' یک دکمه
' ایجاد
Me.cmdTest = New Button
' موقعیت
cmdTest.Location = New System.Drawing.Point(110, 20)
' اندازه
cmdTest.Size = New System.Drawing.Size(80, 30)
' برچسب
cmdTest.Text = "Test"
' پردازشگر رویداد
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' افزودن دکمه به فرم
Me.Controls.Add(cmdTest)
End Sub
' پردازشگر رویداد
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' دکمه کلیک شده است – این را گزارش کنید
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' تابع آزمایشی
Public Shared Sub Main(ByVal args() As String)
' نمایش فرم
Application.Run(New Form1)
End Sub
End Class
ما یک دکمه به فرم اضافه کردهایم:
' یک دکمه
' ایجاد
Me.cmdTest = New Button
' موقعیت
cmdTest.Location = New System.Drawing.Point(110, 20)
' اندازه
cmdTest.Size = New System.Drawing.Size(80, 30)
' برچسب
cmdTest.Text = "Test"
' پردازشگر رویداد
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' افزودن دکمه به فرم
Me.Controls.Add(cmdTest)
ویژگی Location با استفاده از ساختار Point مختصات (110,20) گوشه بالا-چپ دکمه را تعیین میکند. عرض و ارتفاع دکمه با استفاده از ساختار Size روی (80،30) تنظیم شدهاند. ویژگی Text دکمه به شما امکان میدهد برچسب دکمه را تنظیم کنید. کلاس دکمه دارای رویداد Click است که به شرح زیر تعریف شده است:
که در آن EventHandler یک تابع «واگذارشده» با امضای زیر است:
این بدان معناست که رویدادپرداز [Click] برای دکمه باید امضای دلیگیت [EventHandler] را داشته باشد. در اینجا، وقتی دکمه cmdTest کلیک میشود، متد cmdTest_Click فراخوانی خواهد شد. این متد مطابق با قالب قبلی EventHandler به صورت زیر تعریف شده است:
' پردازشگر رویداد
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' دکمه کلیک شد – این گزارش میشود
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
ما صرفاً یک پیام را نمایش میدهیم:

کلاس کامپایل و اجرا میشود:
dos>vbc /r:system.dll /r:system.drawing.dll /r:system.windows.forms.dll frm2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>frm2
کلاس MessageBox برای نمایش پیامها در یک پنجره استفاده میشود. در اینجا، ما از سازنده استفاده کردهایم
Overloads Public Shared Function Show(ByVal owner As IWin32Window,ByVal text As String,ByVal caption As String,ByVal buttons As MessageBoxButtons,ByVal icon As MessageBoxIcon) As DialogResult
متن | پیامی که باید نمایش داده شود |
سربرگ | عنوان پنجره |
دکمهها | دکمهها در پنجره |
آیکون | آیکون نمایشدادهشده در پنجره |
پارامتر buttons میتواند مقادیری از ثابتهای زیر بگیرد:
ثابت | دکمهها |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
پارامتر icon میتواند مقادیری از ثابتهای زیر بگیرد:
![]() | همان متوقف | ||
همان هشدار | ![]() | ||
همانند Asterisk | ![]() | ||
![]() | همان دست | ||
![]() |
متد Show یک متد ایستا است که نتیجهای از نوع System.Windows.Forms.DialogResult را بازمیگرداند، که یک شمارشپذیر است:
public enum System.Windows.Forms.DialogResult
{
Abort = 0x00000003,
Cancel = 0x00000002,
Ignore = 0x00000005,
No = 0x00000007,
None = 0x00000000,
OK = 0x00000001,
Retry = 0x00000004,
Yes = 0x00000006,
}
برای اینکه بفهمیم کاربر کدام دکمه را برای بستن پنجره از نوع MessageBox کلیک کرده است، مینویسیم:
dim res as DialogResult=MessageBox.Show(..)
if res=DialogResult.Yes then
'کاربر دکمه «بله» را کلیک کرد
...
end if
5.2. ساخت یک رابط کاربری گرافیکی با ویژوال Studio.NET
ما برخی از مثالهای قبلی را دوباره بررسی خواهیم کرد، این بار با استفاده از Visual Studio.NET آنها را میسازیم.
5.2.1. ایجاد اولیه پروژه
- VS.NET را اجرا کنید و گزینه Fichier/Nouveau/Projet را انتخاب کنید

- جزئیات پروژه خود را وارد کنید
![]() |
- نوع پروژهای را که میخواهید بسازید انتخاب کنید؛ در این مورد، یک پروژه VB.NET (1)
- نوع برنامهای را که میخواهید بسازید انتخاب کنید؛ در این مورد، یک برنامه ویندوز (2)
- پوشهای را که میخواهید زیرپوشه پروژه را در آن قرار دهید مشخص کنید (3)
- نام پروژه را وارد کنید (4). این نام همچنین نام پوشهای خواهد بود که فایلهای پروژه را در خود جای میدهد
- نام این پوشه در (5) نمایش داده میشود
- سپس تعدادی پوشه و فایل در داخل پوشه i4 ایجاد میشوند:
زیرپوشههای پوشهٔ «project1» ![]() |
از میان این فایلها، تنها یک فایل مورد توجه است: فایل form1.cs که فایل منبع مرتبط با فرم ایجادشده توسط VS.NET است. بعداً به این موضوع باز خواهیم گشت.
5.2.2. پنجرههای رابط کاربری VS.NET
رابط کاربری VS.NET اکنون برخی از عناصر پروژه i4 ما را نمایش میدهد:
ما یک پنجره طراحی رابط کاربری گرافیکی داریم:
![]() |
با انتخاب کنترلها از نوار ابزار (جعبه ابزار ۲) و کشیدن آنها روی ناحیه پنجره (۱)، میتوانیم یک رابط کاربری گرافیکی بسازیم. اگر ماوس را روی «جعبه ابزار» قرار دهیم، آن باز میشود و تعدادی کنترل را نشان میدهد:

در حال حاضر، از هیچکدام از آنها استفاده نمیکنیم. همچنان در صفحه VS.NET، پنجره «Explorer Solution» را مییابیم:

در ابتدا، ما زیاد از این پنجره استفاده نخواهیم کرد. این پنجره تمام فایلهایی را که پروژه را تشکیل میدهند، نشان میدهد. ما فقط به یکی از آنها علاقهمند هستیم: فایل منبع برنامه ما، که در این مورد Form1.vb است. با کلیک راست روی Form1.vb، منویی ظاهر میشود که به شما امکان میدهد به کد منبع رابط کاربری گرافیکی ما (View Code) یا خود رابط کاربری گرافیکی (View Designer) دسترسی پیدا کنید:

شما میتوانید مستقیماً از پنجره «کاوشگر راهحل» به هر دوی این موارد دسترسی پیدا کنید:
![]() | ![]() |
«ستاک» پنجرههای باز در پنجرهٔ اصلی طراحی:

در اینجا، Form1.vb[Design] به پنجره طراحی و Form1.vb به پنجره کد اشاره دارد. به سادگی برای جابجا شدن بین این دو پنجره، روی یکی از برگهها کلیک کنید. پنجرهٔ مهم دیگری که روی صفحهٔ VS.NET نمایش داده میشود، پنجرهٔ ویژگیها است:

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

این منو پنجرههای اصلی توصیفشده در بالا را به همراه میانبرهای صفحهکلیدشان فهرست میکند.
5.2.3. اجرای یک پروژه
با اینکه هنوز هیچ کدی ننوشتهایم، یک پروژه قابل اجرا داریم. برای اجرای آن، F5 یا Déboguer/Démarrer را انتخاب کنید. پنجره زیر ظاهر میشود:

این پنجره را میتوان به حالت تمامصفحه درآورد، به حداقل برد، اندازهاش را تغییر داد و بست.
5.2.4. کد تولید شده توسط VS.NET
بیایید نگاهی به کد (Affichage/Code) برنامه خود بیندازیم:
Public Class Form1
Inherits System.Windows.Forms.Form
#منطقه "کد تولید شده توسط طراح فرمهای ویندوز"
Public Sub New()
MyBase.New()
'این فراخوانی توسط طراح فرمهای ویندوز مورد نیاز است.
InitializeComponent()
'مقداری инициализация پس از فراخوانی InitializeComponent() اضافه کنید
End Sub
'متد بازنوشتهشده فرم را برای پاک کردن لیست اجزا آزاد میکند.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'مورد نیاز طراح فرمهای ویندوز
Private components As System.ComponentModel.IContainer
'REMARQUE: رویه زیر توسط طراح فرمهای ویندوز مورد نیاز است
'میتوان آن را با استفاده از طراح فرمهای ویندوز ویرایش کرد.
'آن را با ویرایشگر کد تغییر ندهید.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "Form2"
End Sub
#پایان منطقه
End Class
یک رابط کاربری گرافیکی از کلاس پایه System.Windows.Forms.Form مشتق میشود:
کلاس پایه Form یک پنجرهٔ پایه را با دکمههای بستن و حداکثر/حداقل کردن، اندازهٔ قابل تنظیم و غیره تعریف میکند و رویدادهای این اشیاء گرافیکی را مدیریت میکند. سازندهٔ فرم از متد InitializeComponent استفاده میکند که در آن کنترلهای فرم ایجاد و مقداردهی اولیه میشوند.
Public Sub New()
MyBase.New()
'این فراخوانی توسط طراح فرمهای ویندوز مورد نیاز است.
InitializeComponent()
'هرگونه مقداردهی اولیه را پس از فراخوانی InitializeComponent() اضافه کنید
End Sub
هر کار دیگری که باید در سازنده انجام شود، میتواند پس از فراخوانی InitializeComponent انجام شود. متد InitializeComponent
Private Sub InitializeComponent()
'
'فرم1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 53)
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
عنوان پنجره «Form1»، عرض آن (292) و ارتفاع آن (53) را تعیین میکند. عنوان پنجره توسط خاصیت Text و ابعاد توسط خاصیت Size تنظیم میشوند. Size در فضای نام System.Drawing تعریف شده و یک ساختار است. برای اجرای این برنامه، باید ماژول اصلی پروژه را تعریف کنیم. برای این کار، از گزینه [Projets/Propriétés] استفاده میکنیم:

در [Objet de démarrage]، ما [Form1] را مشخص میکنیم که همان فرمی است که به تازگی ایجاد کردهایم. برای شروع اجرای برنامه، از گزینه [Déboguer/Démarrer] استفاده میکنیم:

5.2.5. کامپایل در یک پنجره DOS
اکنون، بیایید این برنامه را در یک پنجره DOS کامپایل و اجرا کنیم:
dos>dir form1.vb
14/03/2004 11:53 514 Form1.vb
dos>vbc /r:system.dll /r:system.windows.forms.dll form1.vb
vbc : error BC30420: 'Sub Main' est introuvable dans 'Form1'.
مترجم گزارش میدهد که نمیتواند رویه [Main] را پیدا کند. این به این دلیل است که VS.NET آن را تولید نکرده است. با این حال، ما قبلاً در مثالهای قبلی با آن مواجه شدهایم. این رویه به شکل زیر است:
Shared Sub Main()
' اپلیکیشن راهاندازی میشود
Application.Run(New Form1) ' où Form1 est le formulaire
End Sub
بیایید کد بالا را به کد [Form1.vb] اضافه کرده و دوباره کامپایل کنیم:
dos>vbc /r:system.dll /r:system.windows.forms.dll form2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
Form2.vb(41) : error BC30451: Le nom 'Application' n'est pas déclaré.
Application.Run(New Form2)
~~~~~~~~~~~
این بار، نام [Application] شناسایی نشد. این به سادگی به این معنی است که ما فضای نام آن [System.Windows.Forms] را وارد نکردهایم. بیایید عبارت زیر را اضافه کنیم:
سپس دوباره کامپایل کنید:
این بار، کار میکند. بیایید اجرا کنیم:

یک فرم از نوع Form1 ایجاد و نمایش داده میشود. شما میتوانید با استفاده از گزینه /m کامپایلر، از افزودن رویه [Main] اجتناب کنید، که به شما امکان میدهد کلاسی را که از System.Windows.Form ارث میبرد، برای اجرا مشخص کنید:
گزینه /m:form2 مشخص میکند که کلاس اجرایی، کلاسی به نام [form2] است.
5.2.6. پردازش رویداد
پس از نمایش فرم، برنامه به رویدادهای رخداده روی فرم (کلیکها، حرکات ماوس و غیره) گوش میدهد و رویدادهایی را که فرم مسئول رسیدگی به آنهاست، اجرا میکند. در اینجا، فرم ما هیچ رویدادی را به جز رویدادهایی که توسط کلاس پایه Form مدیریت میشوند (کلیک روی دکمههای بستن و حداکثر/حداقل کردن، تغییر اندازه پنجره، جابجایی پنجره و غیره) مدیریت نمیکند. فرم تولیدشده از یک ویژگی components استفاده میکند که در هیچکجا مورد استفاده قرار نمیگیرد. متد dispose نیز در اینجا هیچ کاربردی ندارد. همین امر در مورد برخی از فضاهای نام (namespaces) که استفاده شدهاند (مانند Collections، ComponentModel، Data) و فضایی که برای پروژه تعریف شده است (projet1) نیز صدق میکند. بنابراین، در این مثال، کد را میتوان به شکل زیر سادهسازی کرد:
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
' سازنده
Public Sub New()
'فرم با اجزای خود ساخته میشود
InitializeComponent()
End Sub
Private Sub InitializeComponent()
' اندازه پنجره
Me.Size = New System.Drawing.Size(300, 300)
' عنوان پنجره
Me.Text = "Form1"
End Sub
Shared Sub Main()
' راهاندازی برنامه
Application.Run(New Form1)
End Sub
End Class
5.2.7. نتیجهگیری
اکنون کد تولیدشده توسط VS.NET را همانطور که هست میپذیریم و صرفاً کد خود را اضافه میکنیم، بهویژه برای رسیدگی به رویدادهای مربوط به کنترلهای مختلف فرم.
5.3. پنجره با فیلد ورودی، دکمه و برچسب
5.3.1. طراحی گرافیک
در مثال قبلی، ما هیچ کامپوننتی را در پنجره قرار نداده بودیم. ما یک پروژه جدید به نام interface2 را شروع میکنیم. برای این کار، مراحل توضیحدادهشده قبلی برای ایجاد یک پروژه را دنبال میکنیم:

اکنون بیایید یک پنجره با یک دکمه، یک برچسب و یک فیلد ورودی بسازیم:
![]() |
میدانها به شرح زیر هستند:
خیر. | name | نوع | نقش |
1 | lblSaisie | برچسب | یک توضیح |
2 | txtSaisie | TextBox | یک فیلد ورودی |
3 | btnAfficher | دکمه | برای نمایش محتویات فیلد ورودی در یک کادر محاورهای txtSaisie |
برای ایجاد این پنجره میتوانید به روش زیر عمل کنید: در داخل پنجره و خارج از هر کامپوننت، روی پنجره کلیک راست کرده و گزینه Properties را برای دسترسی به ویژگیهای پنجره انتخاب کنید:

پنجرهٔ ویژگیها سپس در سمت راست ظاهر میشود:

برخی از این ویژگیها شایان ذکر هستند:
برای تنظیم رنگ پسزمینه پنجره | |
برای تعیین رنگ گرافیک یا متن در پنجره | |
برای مرتبط کردن یک منو با پنجره | |
برای دادن عنوان به پنجره | |
برای تعیین نوع پنجره | |
برای تنظیم قلم متن در پنجره | |
برای تعیین نام پنجره |
در اینجا، ما ویژگیهای Text و Name را تنظیم میکنیم:
ورودیها و دکمهها - ۱ | |
frmSaisiesBoutons |
استفاده از نوار «جعبهابزار»
- کامپوننتهای مورد نیاز خود را انتخاب کنید
- آنها را به داخل پنجره بکشید و ابعاد صحیح آنها را تنظیم کنید
![]() | ![]() |
پس از انتخاب کامپوننت از «جعبهابزار»، دکمه را فشار دهید کلید Esc را برای پنهان کردن نوار ابزار فشار دهید، سپس بکشید و اندازهٔ کامپوننت را تغییر دهید. این کار را برای هر سه انجام دهید. لوازم ضروری: Label, TextBox, Button. برای همترازی و برای تنظیم صحیح اندازهٔ مؤلفهها، از منوی Format استفاده کنید: | ![]() |
قالببندی به شرح زیر عمل میکند:
گزینه Align به شما امکان میدهد اجزا را تراز کنید | ![]() |
گزینه «یکاندازه کردن» تضمین میکند که اجزا دارای ارتفاع یکسان یا یکسان باشند عرض: | ![]() |
گزینه «فاصله افقی» به شما امکان میدهد، برای مثال، برای همتراز کردن افقی مؤلفهها با فاصلهای با اندازهٔ یکسان بین آنها. همین امر در مورد برای گزینهٔ «فاصلهٔ عمودی» نیز همینطور است که برای همترازی عمودی استفاده میشود. گزینه «مرکز در فرم» به شما امکان میدهد که مرکز را تنظیم کنید یک مؤلفه را بهصورت افقی یا عمودی درون پنجره: | ![]() |
پس از اینکه اجزا بهدرستی در پنجره قرار داده شدند، ویژگیهای آنها را تنظیم کنید. برای این کار، روی کامپوننت کلیک راست کرده و گزینه Properties را انتخاب کنید:
برای باز کردن، مؤلفه را انتخاب کنید پنجرهٔ ویژگیهای آن را باز کنید. در این پنجره، ویژگیهای زیر را تغییر دهید: نام: lblSaisie، متن: ورودی
کامپوننت را برای باز کردن آن انتخاب کنید پنجرهٔ ویژگیها. در این پنجره، ویژگیهای زیر را ویرایش کنید: ویژگیهای زیر: name: txtSaisie, text: خالی بگذارید
name: cmdAfficher, text: Show
متن: ورودیها و دکمهها - ۱ | ![]() |
میتوانیم پروژهٔ خود را با (Ctrl+F5) اجرا کنیم برای مشاهده پیشنمایش اولیه پنجره در عمل: | ![]() |
پنجره را ببندید. اکنون باید رویهٔ مربوط به کلیک روی دکمهٔ Afficher را بنویسیم.
5.3.2. پردازش رویدادهای فرم
بیایید نگاهی به کدی که توسط طراح گرافیکی تولید شده است بیندازیم:
...
Public Class frmSaisiesBoutons
Inherits System.Windows.Forms.Form
' اجزا
Private components As System.ComponentModel.Container = Nothing
Friend WithEvents btnAfficher As System.Windows.Forms.Button
Friend WithEvents lblsaisie As System.Windows.Forms.Label
Friend WithEvents txtsaisie As System.Windows.Forms.TextBox
' سازنده
Public Sub New()
InitializeComponent()
End Sub
...
' ابتداییسازی مؤلفهها
Private Sub InitializeComponent()
...
End Sub
End Class
ابتدا، توجه کنید که اعلان خاص کامپوننتها به این صورت است:
- کلمه کلیدی 'Friend' نشان میدهد که دیدپذیری کامپوننت به تمام کلاسهای پروژه گسترش مییابد
- کلیدواژه WithEvents نشان میدهد که کامپوننت رویداد تولید میکند. اکنون به نحوهٔ رسیدگی به این رویدادها میپردازیم
پنجره کد فرم را نمایش دهید (View/Code یا F7):
![]() |
پنجره بالا دو لیست کشویی (۱) و (۲) را نشان میدهد. لیست (۱) فهرست اجزای فرم است:

فهرست (۲) رویدادهای مرتبط با مؤلفهٔ انتخابشده در (۱) را نشان میدهد:

یکی از رویدادهای مرتبط با کامپوننت به صورت پررنگ نمایش داده میشود (در این مورد، Click). این رویداد پیشفرض کامپوننت است. میتوانید با دوبار کلیک بر روی کامپوننت در پنجره طراحی، به هاندر (handler) این رویداد خاص دسترسی پیدا کنید. سپس VB.net بهطور خودکار اسکلت هاندر رویداد را در پنجره کد ایجاد کرده و مکاننما را روی آن قرار میدهد. برای دسترسی به هندلرهای رویدادهای دیگر، به پنجره کد بروید، کامپوننت را از لیست (۱) و رویداد را از (۲) انتخاب کنید. سپس VB.net اسکلت هندلر رویداد را ایجاد میکند یا اگر قبلاً ایجاد شده باشد، مکاننما را روی آن قرار میدهد:
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
بهطور پیشفرض، VB.net و C_E نامگذاری رویدادگیر برای رویداد E از مؤلفه C را انجام میدهند. این نام را در صورت تمایل میتوان تغییر داد؛ اما توصیه نمیشود. توسعهدهندگان VB معمولاً نام تولیدشده توسط VB را حفظ میکنند، که این امر نامگذاری یکنواخت را در تمامی برنامههای VB تضمین میکند. روال btnAfficher_Click با رویداد کلیک (Click) کامپوننت btnAfficher نه از طریق نام روال، بلکه از طریق کلمه کلیدی «handles» مرتبط میشود:
Handles btnAfficher.Click
در مثال بالا، کلیدواژه «handles» مشخص میکند که این رویه رویداد Click را برای کامپوننت btnAfficher مدیریت میکند. رویدادپرداز پیشین دو پارامتر دارد:
شیءای که رویداد را فعال کرده است (در این مورد، دکمه) | |
یک شیء EventArgs که رویداد رخداده را شرح میدهد |
ما در اینجا از هیچیک از این پارامترها استفاده نخواهیم کرد. تنها کاری که باقی مانده تکمیل کد است. در اینجا، میخواهیم یک کادر محاورهای را نمایش دهیم که حاوی محتویات فیلد txtSaisie است:
Private Sub btnAfficher_Click(ByVal sender As Object, ByVal e As System.EventArgs)
'نمایش متن واردشده در کادر ورودی TxtSaisie
MessageBox.Show("texte saisi= " + txtsaisie.Text, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
اگر برنامه را اجرا کنیم، خروجی زیر را دریافت میکنیم:

5.3.3. روش دیگر برای رسیدگی به رویدادها
برای دکمه btnAfficher، VS.NET کد زیر را تولید کرد:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
...
End Sub
...
' پردازشگر رویداد برای کلیک دکمه cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
ما میتوانیم رویه btnAfficher_Click را به رویداد کلیک دکمه btnAfficher به روش دیگری مرتبط کنیم:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
...
End Sub
...
' پردازشگر رویداد برای کلیک دکمه cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
...
End Sub
روند btnAfficher_Click کلیدواژه «Handles» را از دست داده و در نتیجه ارتباط خود را با رویداد btnAfficher.Click از دست داده است. این ارتباط اکنون با استفاده از کلیدواژه AddHandler برقرار میشود:
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
کد بالا، که در رویه InitializeComponent فرم قرار میگیرد، رویه با نام btnAfficher_Click را با رویداد btnAfficher.Click مرتبط میسازد. علاوه بر این، کامپوننت btnAfficher دیگر به کلمه کلیدی WithEvents نیاز ندارد:
Friend btnAfficher As System.Windows.Forms.Button
تفاوت بین این دو روش چیست؟
- کلمهٔ کلیدی 'handles' تنها اجازه میدهد یک رویداد در زمان طراحی با یک رویه مرتبط شود. طراح از قبل میداند که رویهٔ P باید رویدادهای E1، E2 و … را مدیریت کند و کد را مینویسد
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) handles E1, E2, ..., En
در واقع ممکن است یک رویه چندین رویداد را مدیریت کند.
- کلمه کلیدی `addhandler` امکان اختصاص یک رویداد به یک رویه در زمان اجرا را فراهم میکند. این در چارچوب رویداد تولیدکننده-مصرفکننده مفید است. یک شیء یک رویداد خاص تولید میکند که ممکن است برای سایر اشیاء جالب باشد. این اشیاء برای دریافت رویداد (برای مثال، دمایی که از یک آستانه بحرانی فراتر رفته است) به تولیدکننده مشترک میشوند. در طول اجرای برنامه، تولیدکننده رویداد ملزم به اجرای دستورالعملهای مختلفی خواهد بود:
که در آن E رویدادی است که توسط تولیدکننده تولید میشود و Piها رویههای متعلق به اشیاء مصرفکننده مختلف آن رویداد هستند. ما در فصل بعدی به یک کاربرد رویداد تولیدکننده-مصرفکننده باز خواهیم گشت.
5.3.4. نتیجهگیری
از دو پروژه مورد مطالعه، میتوان نتیجه گرفت که پس از ساخت رابط کاربری گرافیکی با استفاده از VS.NET، وظیفه توسعهدهنده نوشتن رویدادپردازها برای رویدادهایی است که میخواهد در آن رابط کاربری گرافیکی مدیریت کند. از این پس، ما فقط کد این رویدادپردازها را ارائه خواهیم داد.
5.4. برخی از کامپوننتهای مفید
اکنون برنامههای مختلفی را که از رایجترین کامپوننتها استفاده میکنند، ارائه خواهیم داد تا متدها و ویژگیهای اصلی آنها را بررسی کنیم. برای هر برنامه، رابط کاربری گرافیکی و کد مربوطه، بهویژه رویدادپردازها، را ارائه خواهیم داد.
5.4.1. کامپوننت فرم
ما با معرفی مؤلفهٔ ضروری شروع میکنیم: فرم (Form) که مؤلفهها روی آن قرار میگیرند. ما قبلاً برخی از ویژگیهای پایهای آن را پوشش دادهایم. در اینجا، بر چند رویداد مهم مرتبط با فرم تمرکز خواهیم کرد.
فرم در حال بارگذاری است | |
فرم در حال بستن است | |
فرم بسته شد |
رویداد Load حتی قبل از نمایش فرم رخ میدهد. رویداد Closing هنگام بستهشدن فرم رخ میدهد. هنوز میتوان این بستهشدن را بهصورت برنامهای متوقف کرد. ما یک فرم به نام Form1 بدون هیچیک از مؤلفهها ایجاد میکنیم:

ما سه رویداد قبلی را مدیریت میکنیم:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' بارگذاری اولیه فرم
MessageBox.Show("Evt Load", "Load")
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
'فرم در حال بستهشدن است
MessageBox.Show("Evt Closing", "Closing")
'تأیید درخواست شده
Dim réponse As DialogResult = MessageBox.Show("Voulez-vous vraiment quitter l'application", "Closing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If réponse = DialogResult.No Then
e.Cancel = True
End If
End Sub
Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
'فرم در حال بستهشدن است
MessageBox.Show("Evt Closed", "Closed")
End Sub
ما از تابع MessageBox برای مطلع شدن از رویدادهای مختلف استفاده میکنیم رویدادها. رویداد Closing زمانی رخ میدهد که کاربر پنجره را میبندد. | ![]() |
سپس از کاربر میپرسیم که آیا واقعاً میخواهد از برنامه خارج شود: | ![]() |
اگر پاسخ «خیر» باشد، ما ویژگی Cancel رویداد را تنظیم میکنیم CancelEventArgs که متد بهعنوان پارامتر دریافت کرده است. اگر این خاصیت را روی False تنظیم کنیم، بستن بستهشدن پنجره لغو میشود؛ در غیر این صورت، ادامه مییابد: | ![]() |
5.4.2. برچسبها و کادرهای ورودی TextBox
ما قبلاً با این دو کامپوننت مواجه شدهایم. Label یک کامپوننت متنی است و TextBox یک کامپوننت فیلد ورودی است. ویژگی اصلی آنها Text است که به محتوای فیلد ورودی یا متن برچسب اشاره دارد. این خاصیت قابل خواندن و نوشتن است. رویدادی که معمولاً برای TextBox استفاده میشود، TextChanged است که سیگنال میدهد کاربر فیلد ورودی را تغییر داده است. در اینجا مثالی آورده شده است که از رویداد TextChanged برای ردیابی تغییرات یک فیلد ورودی استفاده میکند:
![]() |
خیر. | نوع | نام | نقش |
۱ | TextBox | txtSaisie | میدان ورودی |
2 | برچسب | lblControle | متن موجود در 1 را بهصورت بلادرنگ نمایش میدهد |
3 | دکمه | cmdEffacer | برای پاک کردن فیلدهای ۱ و ۲ |
4 | دکمه | cmdQuitter | برای خروج از برنامه |
کد مرتبط برای این برنامه مربوط به رویدادپردازها است:
' روی دکمه خروج کلیک کنید
Private Sub cmdQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdQuitter.Click
' روی دکمه «خروج» کلیک کنید – برنامه بسته میشود
Application.Exit()
End Sub
' txtSaisie فیلد تغییر یافت
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
'محتوای TextBox تغییر کرده است – به برچسب lblControle کپی میشود
lblControle.Text = txtSaisie.Text
End Sub
' روی دکمه «پاک کردن» کلیک کنید
Private Sub cmdEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdEffacer.Click
'محتویات کادر متن پاک شدند
txtSaisie.Text = ""
End Sub
'یک کلید فشرده شده است
Private Sub txtSaisie_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles txtSaisie.KeyPress
'بررسی میکند کدام کلید فشرده شده است
Dim touche As Char = e.KeyChar
If touche = ControlChars.Cr Then
MessageBox.Show(txtSaisie.Text, "Contrôle", MessageBoxButtons.OK, MessageBoxIcon.Information)
e.Handled = True
End If
End Sub
توجه کنید که برنامه در رویه cmdQuitter_Click خاتمه مییابد: Application.Exit(). مثال زیر از TextBox چندخطی استفاده میکند:
![]() |
فهرست کنترلها به شرح زیر است:
خیر. | نوع | نام | نقش |
۱ | TextBox | txtMultiLignes | میدان ورودی چندخطی |
2 | TextBox | txtAjout | میدان ورودی تکخطی |
۳ | دکمه | btnAjouter | محتوا را از 2 به 1 اضافه میکند |
برای چندخطی کردن TextBox، ویژگیهای کنترل زیر را تنظیم کنید:
برای اجازه دادن به چند خط متن | |
برای مشخص کردن اینکه آیا کنترل باید نوار پیمایش (افقی، عمودی، هر دو) داشته باشد یا خیر (بدون) | |
اگر روی true تنظیم شود، فشردن کلید Enter به خط بعدی میرود | |
اگر روی true تنظیم شود، کلید Tab یک تب در متن وارد میکند |
کد مربوطه، کدی است که کلیک روی دکمه [Ajouter] و تغییرات در فیلد ورودی [txtAjout] را مدیریت میکند:
'احتمالاً btnAjouter_Click
Private Sub btnAjouter_Click1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
'محتوای txtAjout به محتوای txtMultilignes افزوده میشود
txtMultilignes.Text &= txtAjout.Text
txtAjout.Text = ""
End Sub
'یا txtAjout_TextChanged
Private Sub txtAjout_TextChanged1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtAjout.TextChanged
' وضعیت دکمه «افزودن» را تنظیم کنید
btnAjouter.Enabled = txtAjout.Text.Trim() <> ""
End Sub
5.4.3. لیستهای کشویی ComboBox
![]() | ![]() |
یک کامپوننت ComboBox یک لیست کشویی است که با یک فیلد ورودی ترکیب شده است: کاربر میتواند یا از (2) یک مورد را انتخاب کند یا در (1) متن تایپ نماید. سه نوع ComboBox وجود دارد که توسط خاصیت Style تعیین میشوند:
فهرست غیر کشویی با کادر ویرایش | |
لیست کشویی با کادر ویرایش | |
فهرست کشویی بدون کادر ویرایش |
به طور پیشفرض، نوع ComboBox، DropDown است. برای کسب اطلاعات درباره کلاس ComboBox، عبارت ComboBox را در نمایه راهنما (Aide/Index) تایپ کنید. کلاس ComboBox دارای یک سازنده واحد است:
Public Sub New() | یک شیء خالی ComboBox ایجاد میکند |
عناصر ComboBox در خصوصیت Items در دسترس هستند:
این یک خاصیت فهرستشده است که در آن Items(i) به عنصر i-ام از کادر ترکیبی اشاره میکند. فرض کنید C یک کادر ترکیبی و C.Items فهرست عناصر آن باشد. ما خاصیتهای زیر را داریم:
تعداد موارد در کادر ترکیبی | |
عنصر i از کادر ترکیبی | |
شیء o را به عنوان آخرین عنصر کامبو اضافه میکند | |
یک آرایه از اشیاء را به انتهای کامبو اضافه میکند | |
شیء o را در موقعیت i در کامبو اضافه میکند | |
عنصر i را از لیست کشویی حذف میکند | |
مورد o را از لیست کشویی حذف میکند | |
حذف تمام عناصر از لیست ترکیبی | |
موقعیت شیء o را در کادر ترکیبی روی i تنظیم میکند |
شاید تعجبآور باشد که یک کادر ترکیبی میتواند حاوی اشیاء باشد، در حالی که معمولاً حاوی رشتههای متنی است. از نظر بصری، این موضوع واقعاً صادق است. اگر یک ComboBox حاوی یک شیء obj باشد، رشته obj.ToString را نمایش میدهد(). به یاد داشته باشید که هر شیء دارای متدی به نام ToString است که از کلاس object به ارث رسیده و یک رشتهٔ کاراکتری را بازمیگرداند که «نماینده» آن شیء است. مورد انتخابشده در کادر ترکیبی C، C.SelectedItem یا C.Items(C.SelectedIndex) است، که در آن C.SelectedIndex شماره مورد انتخابشده است، این شماره از صفر برای آیتم اول شروع میشود.
هنگامی که یک مورد از لیست کشویی انتخاب میشود، رویداد SelectedIndexChanged فعال میشود؛ این رویداد سپس میتواند برای اطلاع از تغییر در انتخاب درون لیست کشویی استفاده شود. در برنامهٔ زیر، ما از این رویداد برای نمایش موردی که از لیست انتخاب شده است، استفاده میکنیم.

ما فقط کد مرتبط با پنجره را نمایش میدهیم. در سازنده فرم، کادر ترکیبی را پر میکنیم:
Public Sub New()
' ایجاد فرم
InitializeComponent()
' پر کردن لیست کشویی
cmbNombres.Items.AddRange(New String() {"zéro", "un", "deux", "trois", "quatre"})
' ما اولین مورد در لیست را انتخاب میکنیم
cmbNombres.SelectedIndex = 0
End Sub
ما رویداد SelectedIndexChanged را از لیست کشویی مدیریت میکنیم که نشان میدهد یک آیتم جدید انتخاب شده است:
Private Sub cmbNombres_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmbNombres.SelectedIndexChanged
' مورد انتخابی تغییر کرده است – آن را نمایش دهید
MessageBox.Show("Elément sélectionné : (" & cmbNombres.SelectedItem.ToString & "," & cmbNombres.SelectedIndex & ")", "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
5.4.4. کامپوننت ListBox
ما پیشنهاد میکنیم رابط کاربری زیر را بسازیم:
![]() |
اجزای این پنجره به شرح زیر است:
خیر. | نوع | name | نقش/ویژگیها |
0 | فرم | Form1 | فرم - BorderStyle=FixedSingle |
1 | TextBox | txtSaisie | میدان ورودی |
2 | دکمه | btnAjouter | دکمه برای افزودن محتویات فیلد ورودی 1 به لیست 3 |
۳ | ListBox | listBox1 | فهرست ۱ |
4 | ListBox | listBox2 | فهرست ۲ |
۵ | دکمه | btn1TO2 | موارد انتخابشده را از فهرست ۱ به فهرست ۲ منتقل میکند |
۶ | دکمه | cmd2T0 | برعکس عمل میکند |
۷ | دکمه | btnEffacer1 | فهرست ۱ را پاک میکند |
8 | دکمه | btnEffacer2 | پاک کردن فهرست ۲ |
- کاربر متن را در فیلد 1 تایپ میکند. او با استفاده از دکمه Ajouter (2) آن را به لیست 1 اضافه میکند. سپس فیلد ورودی (1) پاک میشود و کاربر میتواند یک آیتم جدید اضافه کند.
- آنها میتوانند با انتخاب آیتمی برای انتقال از یکی از لیستها و انتخاب دکمه انتقال مناسب، ۵ یا ۶، آیتمها را از یک لیست به لیست دیگر منتقل کنند. آیتم منتقلشده به انتهای لیست مقصد اضافه شده و از لیست مبدأ حذف میشود.
- آنها میتوانند روی یک آیتم در لیست ۱ دوبار کلیک کنند. این آیتم سپس برای ویرایش به کادر ورودی منتقل شده و از لیست ۱ حذف میشود.
دکمهها بر اساس قوانین زیر فعال یا غیرفعال میشوند:
- دکمه Ajouter تنها در صورتی روشن میشود که متن غیرخالی در فیلد ورودی وجود داشته باشد
- دکمه ۵ برای انتقال از لیست ۱ به لیست ۲ تنها زمانی روشن میشود که یک آیتم در لیست ۱ انتخاب شده باشد
- دکمه ۶ برای انتقال از فهرست ۲ به فهرست ۱ تنها زمانی روشن میشود که یک مورد در فهرست ۲ انتخاب شده باشد
- دکمههای ۷ و ۸ برای پاک کردن لیستهای ۱ و ۲ تنها در صورتی برجسته میشوند که لیست مورد نظر برای پاک کردن حاوی آیتم باشد.
در این شرایط، همه دکمهها باید هنگام شروع برنامه خاموش باشند. بنابراین، ویژگی Enabled دکمهها باید روی false تنظیم شود. این کار را میتوان در زمان طراحی انجام داد که در این صورت کد مربوطه در متد InitializeComponent تولید میشود، یا میتوان آن را به صورت دستی در کانستراکتور همانطور که در زیر نشان داده شده است انجام داد:
Public Sub New()
' ایجاد اولیه فرم
InitializeComponent()
' ابتکارات اضافی
' غیرفعال کردن تعدادی دکمه
btnAjouter.Enabled = False
btn1TO2.Enabled = False
btn2TO1.Enabled = False
btnEffacer1.Enabled = False
btnEffacer2.Enabled = False
End Sub
وضعیت دکمه Ajouter توسط محتویات فیلد ورودی کنترل میشود. این رویداد TextChanged است که به ما امکان میدهد تغییرات این محتوا را پیگیری کنیم:
'تغییر در فیلد ورودی متن
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
'محتوای txtSaisie تغییر کرده است
'دکمه Add تنها در صورتی فعال میشود که فیلد خالی نباشد
btnAjouter.Enabled = txtSaisie.Text.Trim() <> ""
End Sub
وضعیت دکمههای انتقال به این بستگی دارد که آیا موردی از فهرستی که کنترل میکنند انتخاب شده است یا خیر:
' تغییر در آیتم انتخابشده بدون listbox1
Private Sub listBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox1.SelectedIndexChanged
'یک آیتم انتخاب شده است
'دکمه انتقال از ۱ به ۲ فعال است
btn1TO2.Enabled = True
End Sub
'تغییر آیتم انتخابشده بدون listbox2
Private Sub listBox2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox2.SelectedIndexChanged
'یک آیتم انتخاب شده است
' دکمه «انتقال ۲ به ۱» فعال است
btn2TO1.Enabled = True
End Sub
کد مربوط به کلیک روی دکمه Ajouter به شرح زیر است:
' روی دکمه «Add» کلیک کنید
Private Sub btnAjouter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
'یک مورد جدید به لیست 1 اضافه شده است
listBox1.Items.Add(txtSaisie.Text.Trim())
' میدان ورودی پاک شد
txtSaisie.Text = ""
' فهرست ۱ خالی نیست
btnEffacer1.Enabled = True
'تمرکز به فیلد ورودی بازمیگردد
txtSaisie.Focus()
End Sub
توجه کنید به متد Focus که به شما امکان میدهد «تمرکز» را روی یک کنترل فرم قرار دهید. کد مربوط به کلیک روی دکمههای Effacer:
' روی دکمه Clear1 کلیک کنید
Private Sub btnEffacer1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer1.Click
' فهرست ۱ پاک شد
listBox1.Items.Clear()
btnEffacer1.Enabled = False
End Sub
' روی دکمه Clear2 کلیک کنید
Private Sub btnEffacer2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' فهرست ۲ پاک شد
listBox2.Items.Clear()
btnEffacer2.Enabled = False
End Sub
کد انتقال موارد انتخابشده از یک لیست به لیست دیگر:
'روی دکمه 'btn1to2' کلیک کنید
Private Sub btn1TO2_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn1TO2.Click
' انتقال آیتم انتخابشده از فهرست ۱ به فهرست ۲
transfert(listBox1, listBox2)
' دکمههای پاک کردن
btnEffacer2.Enabled = True
btnEffacer1.Enabled = listBox1.Items.Count <> 0
' انتقال دکمهها
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' روی دکمه btn2to1 کلیک کنید
Private Sub btn2TO1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn2TO1.Click
' انتقال آیتم انتخابشده از فهرست ۲ به فهرست ۱
transfert(listBox2, listBox1)
' دکمههای حذف
btnEffacer1.Enabled = True
btnEffacer2.Enabled = listBox2.Items.Count <> 0
'دکمههای انتقال
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
'انتقال
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
' انتقال آیتم انتخابشده از فهرست ۱ به فهرست ۲
' یک آیتم انتخابشده؟
If l1.SelectedIndex = -1 Then Return
' افزودن به l2
l2.Items.Add(l1.SelectedItem)
' حذف از l1
l1.Items.RemoveAt(l1.SelectedIndex)
End Sub
ابتدا، یک متد ایجاد میکنیم
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
که آیتم انتخابشده را از لیست l1 به لیست l2 منتقل میکند. این امکان را به ما میدهد که به جای دو متد، از یک متد واحد برای انتقال یک عنصر از listBox1 به listBox2 یا از listBox2 به listBox1 استفاده کنیم. قبل از انجام انتقال، اطمینان حاصل میکنیم که یک عنصر در لیست l1 انتخاب شده است:
' یک آیتم انتخابشده؟
If l1.SelectedIndex = -1 Then Return
ویژگی SelectedIndex در صورتی که هیچ آیتمی در حال حاضر انتخاب نشده باشد، روی -1 تنظیم میشود. در رویهها
Private Sub btnXTOY_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnXTOY.Click
فهرست X به فهرست Y منتقل میشود و وضعیت برخی دکمهها برای انعکاس وضعیت جدید فهرستها تغییر میکند.
5.4.5. تیکباکسها CheckBox، دکمههای رادیویی ButtonRadio
ما پیشنهاد میکنیم برنامه زیر را بنویسیم:
![]() |
اجزای پنجره به شرح زیر هستند:
خیر. | نوع | اسم | نقش |
۱ | RadioButton | radioButton1 radioButton2 radioButton3 | ۳ دکمهٔ رادیویی |
2 | CheckBox | chechBox1 chechBox2 chechBox3 | ۳ کادر تیکدار |
۳ | ListBox | lstValeurs | یک فهرست |
اگر سه دکمه رادیویی پشت سر هم ایجاد شوند، به طور پیشفرض بخشی از یک گروه واحد هستند. بنابراین، وقتی یکی از آنها انتخاب میشود، بقیه انتخاب نمیشوند. رویداد مورد نظر برای این شش کنترل، رویداد CheckChanged است که نشان میدهد وضعیت تیکباکس یا دکمه رادیویی تغییر کرده است. در هر دو حالت، این وضعیت با خاصیت بولین Check نشان داده میشود که وقتی مقدار آن true باشد، یعنی کنترل انتخاب شده است. در اینجا، ما از یک متد واحد برای رسیدگی به هر شش رویداد CheckChanged استفاده کردهایم: متد affiche:
'نمایش میدهد
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles checkBox1.CheckedChanged, checkBox2.CheckedChanged, checkBox3.CheckedChanged, _
radioButton1.CheckedChanged, radioButton2.CheckedChanged, radioButton3.CheckedChanged
'وضعیت دکمهٔ رادیویی یا خانهٔ تیک را نمایش میدهد
'آیا این یک چکباکس است؟
If (TypeOf (sender) Is CheckBox) Then
Dim chk As CheckBox = CType(sender, CheckBox)
lstValeurs.Items.Insert(0, chk.Name & "=" & chk.Checked)
End If
'آیا این دکمهٔ رادیویی است؟
If (TypeOf (sender) Is RadioButton) Then
Dim rdb As RadioButton = CType(sender, RadioButton)
lstValeurs.Items.Insert(0, rdb.Name & "=" & rdb.Checked)
End If
End Sub
سینتکس TypeOf (sender) Is CheckBox به ما امکان میدهد بررسی کنیم که آیا شیء sender از نوع CheckBox است. این امر سپس به ما امکان میدهد تا آن را به نوع دقیق sender تبدیل کنیم. متد affiche نام کامپوننتی را که رویداد را تحریک کرده و مقدار خاصیت Checked آن را در لیست lstValeurs مینویسد. در زمان اجرا، میتوانیم ببینیم که کلیک روی یک دکمه رادیویی دو رویداد CheckChanged را فعال میکند: یکی روی دکمه رادیویی قدیمی که به «unchecked» تغییر میکند و دیگری روی دکمه رادیویی جدید که به «checked» تغییر میکند.
5.4.6. اسلایدرهای ScrollBar
چندین نوع اسلایدر وجود دارد: اسلایدر افقی (hScrollBar)، اسلایدر عمودی (vScrollBar) و افزاینده (NumericUpDown). | ![]() |
بیایید برنامه زیر را پیادهسازی کنیم:
![]() |
خیر. | نوع | name | نقش |
۱ | hScrollBar | hScrollBar1 | یک واریاتور افقی |
2 | hScrollBar | hScrollBar2 | یک واریاتور افقی که تغییرات واریاتور ۱ را دنبال میکند |
3 | TextBox | txtValeur | مقدار درایو افقی را نمایش میدهد ReadOnly=true برای جلوگیری از هرگونه ورودی |
4 | NumericUpDown | افزاینده | امکان تنظیم مقدار اسلایدر ۲ را فراهم میکند |
- یک اسلایدر ScrollBar به کاربر اجازه میدهد از میان بازهای از مقادیر صحیح، مقداری را انتخاب کند که با «باند» اسلایدر نشان داده میشود و نشانگر روی آن حرکت میکند. مقدار اسلایدر در خاصیت Value آن در دسترس است.
- برای یک اسلایدر افقی، انتهای سمت چپ نشاندهنده حداقل مقدار محدوده، انتهای سمت راست نشاندهنده حداکثر مقدار و خود اسلایدر نشاندهنده مقدار انتخابشده در حال حاضر است. برای یک اسلایدر عمودی، حداقل با انتهای بالایی و حداکثر با انتهای پایینی نشان داده میشود. این مقادیر توسط خواص Minimum و Maximum نمایش داده میشوند و به طور پیشفرض روی 0 و 100 تنظیم شدهاند.
- کلیک کردن روی انتهای اسلایدر، مقدار را به اندازه یک گام (مثبت یا منفی) بسته به انتهای کلیکشده تغییر میدهد، که به آن SmallChange گفته میشود و به صورت پیشفرض روی 1 تنظیم شده است.
- کلیک کردن روی هر طرف اسلایدر، بسته به اینکه کدام انتها کلیک میشود، مقدار را یک واحد (مثبت یا منفی) تغییر میدهد، که این امر توسط پارامتر LargeChange تعریف شده و مقدار پیشفرض آن 10 است.
- وقتی روی انتهای بالایی یک اسلایدر عمودی کلیک میشود، مقدار آن کاهش مییابد. این موضوع ممکن است کاربر عادی را غافلگیر کند، زیرا او معمولاً انتظار دارد مقدار «افزایش» یابد. این مشکل را میتوان با تنظیم خواص SmallChange و LargeChange به یک مقدار منفی حل کرد.
- این پنج ویژگی (Value, Minimum, Maximum, SmallChange, LargeChange) برای خواندن و نوشتن در دسترس هستند.
- رویداد اصلی درایو، رویدادی است که تغییر مقدار را اعلام میکند: رویداد Scroll.
یک کامپوننت NumericUpDown در نزدیکی درایو قرار دارد: این کامپوننت نیز دارای خواص Minimum، Maximum و Value است که مقادیر پیشفرض آنها به ترتیب 0، 100 و 0 هستند. با این حال، در این مورد، ویژگی Value در یک کادر ورودی نمایش داده میشود که بخشی جداییناپذیر از کنترل را تشکیل میدهد. کاربر میتواند این مقدار را خود تغییر دهد، مگر اینکه ویژگی ReadOnly کنترل روی true تنظیم شده باشد. مقدار افزایشی توسط خاصیت Increment تعیین میشود که بهصورت پیشفرض برابر با 1 است. رویداد اصلی کامپوننت NumericUpDown همان رویدادی است که تغییر مقدار را اعلام میکند: رویداد ValueChanged. کد مربوطه برای برنامه ما به شرح زیر است:
فرم هنگام ایجاد قالببندی میشود:
' سازنده
Public Sub New()
' ایجاد اولیه فرم
InitializeComponent()
' درایو ۲ دارای همان ویژگیهای درایو ۱ است
hScrollBar2.Minimum = hScrollBar1.Value
hScrollBar2.Minimum = hScrollBar1.Minimum
hScrollBar2.Maximum = hScrollBar1.Maximum
hScrollBar2.LargeChange = hScrollBar1.LargeChange
hScrollBar2.SmallChange = hScrollBar1.SmallChange
' همین امر در مورد شمارنده نیز صدق میکند
incrémenteur.Minimum = hScrollBar1.Value
incrémenteur.Minimum = hScrollBar1.Minimum
incrémenteur.Maximum = hScrollBar1.Maximum
incrémenteur.Increment = hScrollBar1.SmallChange
' ارزش درایو ۱ را به TextBox اختصاص دهید
txtValeur.Text = "" & hScrollBar1.Value
End Sub
پردازشگری که تغییرات در مقدار درایو ۱ را نظارت میکند:
'مدیریت درایو hscrollbar1
Private Sub hScrollBar1_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar1.Scroll
' تغییر در مقدار درایو 1
'مقدار آن به اسلایدر ۲ و به کادر متن TxtValeur اعمال میشود
hScrollBar2.Value = hScrollBar1.Value
txtValeur.Text = "" & hScrollBar1.Value
End Sub
پردازشگری که تغییرات در مقدار درایو ۲ را نظارت میکند:
'کنترل اسلایدر hscrollbar2
Private Sub hScrollBar2_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar2.Scroll
' از هرگونه تغییر در اسلایدر 2 جلوگیری میکند
' با وادار کردن آن به حفظ مقدار درایو ۱
e.NewValue = hScrollBar1.Value
End Sub
مدیر نظارت بر تغییرات کنترل incrémenteur:
'کنترل افزاینده
Private Sub incrémenteur_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles incrémenteur.ValueChanged
' مقدار درایو ۲ را تنظیم کنید
hScrollBar2.Value = CType(incrémenteur.Value, Integer)
End Sub
5.5. رویدادهای ماوس
هنگام ترسیم در یک کانتینر، دانستن موقعیت ماوس مهم است تا برای مثال، هنگام کلیک روی ماوس بتوان یک نقطه نمایش داد. حرکت ماوس رویدادهایی را در کانتینری که ماوس در آن در حال حرکت است، فعال میکند.
![]() | ![]() |
موش به تازگی وارد ناحیه کنترل شده است | |
موش به تازگی ناحیه کنترل را ترک کرده است | |
موش در داخل ناحیه کنترل در حال حرکت است | |
دکمه چپ ماوس فشرده شده | |
رها شدن دکمه چپ ماوس | |
کاربر یک شیء را روی کنترل میاندازد | |
کاربر یک شیء را به داخل ناحیه کنترل میکشد | |
کاربر یک شیء را از ناحیه کنترل بیرون میکشد | |
کاربر هنگام کشیدن یک شیء، ماوس را بر روی ناحیه کنترل نگه میدارد |
در اینجا برنامهای برای کمک به درک بهتر زمان وقوع رویدادهای مختلف ماوس آورده شده است:
![]() |
خیر. | نوع | نام | نقش |
1 | برچسب | lblPosition | برای نمایش موقعیت ماوس در فرم 1، لیست 2 یا دکمه 3 |
2 | ListBox | lstEvts | برای نمایش رویدادهای ماوس به غیر از MouseMove |
3 | دکمه | btnEffacer | برای پاک کردن محتویات 2 |
پردازشگرهای رویداد به شرح زیر هستند. برای ردیابی حرکات ماوس در سهگانه کنترلها، تنها یک پردازشگر کافی است:
' در صورت لزوم form1_mousemove
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseMove, lstEvts.MouseMove, btnEffacer.MouseMove, lstEvts.MouseMove
'حرکت ماوس – نمایش مختصات (X,Y) آن
lblPosition.Text = "(" & e.X & "," & e.Y & ")"
End Sub
توجه به این نکته مهم است که هرگاه ماوس وارد محدوده یک کنترل شود، سیستم مختصات آن تغییر میکند. مبدا (0,0) آن، گوشه بالا سمت چپ کنترلی است که ماوس روی آن قرار دارد. بنابراین، در زمان اجرا، هنگام حرکت دادن ماوس از فرم به دکمه، تغییر در مختصات به وضوح قابل مشاهده است. برای نمایش بهتر این تغییرات در ناحیه ماوس، میتوانید از خاصیت Cursor کنترلها استفاده کنید:

این خاصیت به شما امکان میدهد شکل نشانگر ماوس را هنگام ورود به ناحیه کنترل تنظیم کنید. بنابراین، در مثال ما، ما نشانگر را برای خود فرم روی «Default» (پیشفرض)، برای لیست ۲ روی «Hand» (دست) و برای دکمه ۳ روی «No» (خیر) تنظیم کردهایم، همانطور که در اسکرینشاتهای زیر نشان داده شده است.



در متد [InitializeComponent]، کد تولید شده توسط این انتخابها به شرح زیر است:
Me.lstEvts.Cursor = System.Windows.Forms.Cursors.Hand
Me.btnEffacer.Cursor = System.Windows.Forms.Cursors.No
علاوه بر این، برای تشخیص حرکت ماوس به داخل و خارج لیست 2، رویدادهای MouseEnter و MouseLeave را از همان لیست پردازش میکنیم:
' رویداد lstEvts_MouseEnter
Private Sub lstEvts_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseEnter
affiche("MouseEnter sur liste")
End Sub
' رویداد lstEvts_MouseLeave
Private Sub lstEvts_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseLeave
affiche("MouseLeave sur liste")
End Sub
' نمایش میدهد
Private Sub affiche(ByVal message As String)
' پیام در بالای فهرست رویدادها نمایش داده میشود
lstEvts.Items.Insert(0, message)
End Sub

برای رسیدگی به کلیکها روی فرم، رویدادهای MouseDown و MouseUp را مدیریت میکنیم:
' رویداد Form1_MouseDown
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseDown
affiche("MouseDown sur formulaire")
End Sub
' رویداد Form1_MouseUp
Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseUp
affiche("MouseUp sur formulaire")
End Sub

در نهایت، کد برای رویدادپرداز کلیک دکمه Effacer:
'رویداد btnEffacer_Click
Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' فهرست رویدادها را پاک میکند
lstEvts.Items.Clear()
End Sub
5.6. ایجاد یک پنجره با منو
حال بیایید ببینیم چگونه یک پنجره با منو ایجاد کنیم. ما قصد داریم پنجره زیر را ایجاد کنیم:
![]() |
کنترل 1 یک TextBox (ReadOnly=true) فقط-خواندنی است که txtStatut نام دارد. درخت منو به شرح زیر است:
![]() | ![]() |
گزینههای منو کنترلهایی هستند درست مانند هر مؤلفهٔ بصری دیگر و دارای خواص و رویدادها میباشند. برای مثال، جدول خواص برای گزینهٔ منو A1:

در مثال ما از دو ویژگی استفاده میشود:
نام کنترل منو | |
برچسب گزینه منو |
ویژگیهای گزینههای مختلف منو در مثال ما به شرح زیر است:
نام | متن |
mnuA | گزینههای A |
mnuA1 | A1 |
mnuA2 | A2 |
mnuA3 | A3 |
mnuB | گزینههای B |
mnuB1 | B1 |
mnuSep1 | - (جداساز) |
mnuB2 | B2 |
mnuB3 | B3 |
mnuB31 | B31 |
mnuB32 | B32 |
برای ایجاد یک منو، کامپوننت "MainMenu" را از نوار "ToolBox" انتخاب کنید:

سپس یک منوی خالی خواهید داشت که در فرم با فیلدهای خالی برچسبگذاریشده «Type Here» ظاهر میشود. کافی است گزینههای مختلف منو را در آنجا وارد کنید:

برای قرار دادن یک جداکننده بین دو گزینه، همانطور که در بالا بین گزینههای B1 و B2 نشان داده شده است، مکان نما را در جایی که میخواهید جداکننده در منو ظاهر شود قرار دهید، کلیک راست کرده و گزینه «درج جداکننده» (Insert Separator) را انتخاب کنید:

اگر برنامه را با استفاده از Ctrl+F5 اجرا کنید، فرم با منویی را مشاهده خواهید کرد که در حال حاضر هیچ کاری انجام نمیدهد. گزینههای منو به عنوان کامپوننت در نظر گرفته میشوند: آنها دارای خواص و رویدادها هستند. در [fenêtre de code]، کامپوننت mnuA1 را انتخاب کنید، سپس رویدادهای مرتبط را انتخاب کنید:

اگر رویداد Click همانطور که در بالا توضیح داده شد ایجاد شود، VS.NET به طور خودکار رویه زیر را ایجاد میکند:
Private Sub mnuA1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuA.Click
....
End Sub
ما میتوانیم به همین ترتیب برای تمام گزینههای منو عمل کنیم. در اینجا، میتوان از همین رویه برای تمام گزینهها استفاده کرد. بنابراین، رویه قبلی را به affiche تغییر نام میدهیم و رویدادهایی را که مدیریت میکند، اعلام مینماییم:
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mnuA1.Click, mnuA2.Click, mnuB1.Click, mnuB2.Click, mnuB31.Click, mnuB32.Click
' نام زیرمنوی انتخابشده را در TextBox نمایش میدهد
txtStatut.Text = (CType(sender, MenuItem)).Text
End Sub
در این روش، ما به سادگی ویژگی Text گزینهی منو را در منبع رویداد نمایش میدهیم. منبع رویداد sender از نوع object است. از آنجا که گزینههای منو از نوع MenuItem هستند، در اینجا مجبوریم تبدیل نوع از object به MenuItem را انجام دهیم. برنامه را اجرا کنید و گزینه A1 را انتخاب کنید تا پیام زیر را مشاهده کنید:

کد مربوطه برای این برنامه، به جز کد مربوط به متد affiche، کد ساخت منو در سازنده فرم (InitializeComponent) است:
Private Sub InitializeComponent()
Me.mainMenu1 = New System.Windows.Forms.MainMenu
Me.mnuA = New System.Windows.Forms.MenuItem
Me.mnuA1 = New System.Windows.Forms.MenuItem
Me.mnuA2 = New System.Windows.Forms.MenuItem
Me.mnuA3 = New System.Windows.Forms.MenuItem
Me.mnuB = New System.Windows.Forms.MenuItem
Me.mnuB1 = New System.Windows.Forms.MenuItem
Me.mnuB2 = New System.Windows.Forms.MenuItem
Me.mnuB3 = New System.Windows.Forms.MenuItem
Me.mnuB31 = New System.Windows.Forms.MenuItem
Me.mnuB32 = New System.Windows.Forms.MenuItem
Me.txtStatut = New System.Windows.Forms.TextBox
Me.mnuSep1 = New System.Windows.Forms.MenuItem
Me.SuspendLayout()
'
' mainMenu1
'
Me.mainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA, Me.mnuB})
'
' mnuA
'
Me.mnuA.Index = 0
Me.mnuA.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA1, Me.mnuA2, Me.mnuA3})
Me.mnuA.Text = "Options A"
'
' mnuA1
'
Me.mnuA1.Index = 0
Me.mnuA1.Text = "A1"
'
' mnuA2
'
Me.mnuA2.Index = 1
Me.mnuA2.Text = "A2"
'
' mnuA3
'
Me.mnuA3.Index = 2
Me.mnuA3.Text = "A3"
'
' mnuB
'
Me.mnuB.Index = 1
Me.mnuB.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB1, Me.mnuSep1, Me.mnuB2, Me.mnuB3})
Me.mnuB.Text = "Options B"
'
' mnuB1
'
Me.mnuB1.Index = 0
Me.mnuB1.Text = "B1"
'
' mnuB2
'
Me.mnuB2.Index = 2
Me.mnuB2.Text = "B2"
'
' mnuB3
'
Me.mnuB3.Index = 3
Me.mnuB3.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB31, Me.mnuB32})
Me.mnuB3.Text = "B3"
'
' mnuB31
'
Me.mnuB31.Index = 0
Me.mnuB31.Text = "B31"
'
' mnuB32
'
Me.mnuB32.Index = 1
Me.mnuB32.Text = "B32"
'
' txtStatut
'
Me.txtStatut.Location = New System.Drawing.Point(8, 8)
Me.txtStatut.Name = "txtStatut"
Me.txtStatut.ReadOnly = True
Me.txtStatut.Size = New System.Drawing.Size(112, 20)
Me.txtStatut.TabIndex = 0
Me.txtStatut.Text = ""
'
' mnuSep1
'
Me.mnuSep1.Index = 1
Me.mnuSep1.Text = "-"
'
' Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(136, 42)
Me.Controls.Add(txtStatut)
Me.Menu = Me.mainMenu1
Me.Name = "Form1"
Me.Text = "Menus"
Me.ResumeLayout(False)
End Sub
به عبارت مربوط به اتصال منو به فرم توجه کنید:
Me.Menu = Me.mainMenu1
5.7. کامپوننتهای غیرگرافیکی
اکنون به تعدادی از کامپوننتهای غیرگرافیکی میپردازیم: اینها در حین طراحی استفاده میشوند اما در زمان اجرا قابل مشاهده نیستند.
5.7.1. جعبههای محاورهای OpenFileDialog و SaveFileDialog
ما قصد داریم برنامه زیر را بسازیم:
![]() |
کنترلها به شرح زیر هستند:
خیر. | نوع | نام | نقش |
1 | TextBox چندخطی | txtTexte | متن تایپشده توسط کاربر یا بارگذاریشده از یک فایل |
2 | دکمه | btnSauvegarder | امکان ذخیره متن موجود در 1 در یک فایل متنی را فراهم میکند |
3 | دکمه | btnCharger | امکان بارگذاری محتویات یک فایل متنی را در 1 برای شما فراهم میکند |
۴ | دکمه | btnEffacer | محتویات 1 را پاک میکند |
دو کنترل غیرگرافیکی استفاده میشوند:

وقتی آنها از «ToolBox» کشیده شده و روی فرم رها میشوند، در ناحیهای جداگانه در پایین فرم قرار میگیرند. کامپوننتهای «Dialog» از «ToolBox» کشیده میشوند:

کد دکمه Effacer ساده است:
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' جعبهی ورودی پاک میشود
txtTexte.Text = ""
End Sub
کلاس SaveFileDialog به صورت زیر تعریف شده است:

این کلاس از چندین سطح ارثبری میکند. از میان ویژگیها و متدهای فراوان آن، ما بر موارد زیر تمرکز خواهیم کرد:
انواع فایلهای موجود در فهرست کشویی نوع فایل در کادر محاورهای | |
شماره نوع فایلی که بهطور پیشفرض در لیست بالا پیشنهاد میشود. از ۰ شروع میشود. | |
پوشهای که در ابتدا برای ذخیره فایل نمایش داده میشود | |
نام فایل پشتیبان مشخصشده توسط کاربر | |
روشی که کادر محاورهای پشتیبانگیری را نمایش میدهد. مقدار بازگشتی از نوع DialogResult است. |
روش ShowDialog یک کادر محاورهای مشابه شکل زیر را نمایش میدهد:
![]() |
فهرست کشویی تولید شده از خاصیت Filter. نوع فایل پیشفرض توسط FilterIndex تنظیم میشود. | |
پوشهٔ جاری، که توسط InitialDirectory در صورتی که این خاصیت مشخص شده باشد، تنظیم میشود | |
نام فایل انتخابشده یا مستقیماً واردشده توسط کاربر. در خصوصیت FileName در دسترس خواهد بود | |
دکمههای ذخیره/لغو. اگر از دکمه Enregistrer استفاده شود، تابع ShowDialog نتیجه DialogResult.OK را برمیگرداند. |
روند ذخیره به صورت زیر نوشته میشود:
Private Sub btnSauvegarder_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnSauvegarder.Click
' ذخیرهٔ کادر ورودی در یک فایل متنی
' راهاندازی پنجرهٔ گفتگو savefileDialog1
saveFileDialog1.InitialDirectory = Application.ExecutablePath
saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
saveFileDialog1.FilterIndex = 0
' پنجرهٔ گفتگو را نمایش دهید و نتیجهٔ آن را بازیابی کنید
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
'نام فایل را بازیابی میکند
Dim nomFichier As String = saveFileDialog1.FileName
Dim fichier As StreamWriter = Nothing
Try
' فایل را برای نوشتن باز کنید
fichier = New StreamWriter(nomFichier)
'متن را اینجا تایپ کنید
fichier.Write(txtTexte.Text)
Catch ex As Exception
'مشکل
MessageBox.Show("Problème à l'écriture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' پایان فایل
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- پوشهٔ اولیه به پوشهای که حاوی فایل اجرایی برنامه است، پیوند داده شده است:
- انواع فایلهای نمایش داده شده را تنظیم کنید
به سینتکس فیلترها توجه کنید: filter1|filter2|..|filteren، که در آن filteri = Text|قالب فایل. در اینجا کاربر میتواند بین فایلهای *.txt و *.* انتخاب کند.
- ما نوع فایل نمایشدادهشده را در ابتدا مشخص میکنیم
در اینجا، فایلهای *.txt ابتدا به کاربر نمایش داده میشوند.
- جعبهی محاوره نمایش داده میشود و نتیجهی آن بازیابی میشود
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
- در حالی که کادر محاورهای نمایش داده میشود، کاربر دیگر به فرم اصلی دسترسی ندارد (این به عنوان کادر محاورهای مدال شناخته میشود). کاربر نام فایلی را که باید ذخیره شود مشخص میکند و با کلیک بر روی دکمه «ذخیره»، دکمه «لغو» یا بستن کادر محاورهای، آن را ترک میکند. نتیجه متد ShowDialog تنها در صورتی DialogResult.OK خواهد بود که کاربر از دکمه Enregistrer برای بستن کادر محاورهای استفاده کرده باشد.
- پس از انجام این کار، نام فایل مورد نظر برای ایجاد اکنون در ویژگی FileName از شیء saveFileDialog1 قرار دارد. سپس به فرایند استاندارد ایجاد یک فایل متنی بازمیگردیم. محتوای TextBox:txtTexte.Text را در آن مینویسیم، در حالی که هر استثنایی را که ممکن است رخ دهد، مدیریت میکنیم.
کلاس OpenFileDialog بسیار شبیه به کلاس SaveFileDialog است و از همان تبار کلاسها مشتق شده است. از میان ویژگیها و متدهای آن، ما بر موارد زیر تمرکز خواهیم کرد:
انواع فایلهای ارائهشده در فهرست کشویی نوع فایل در کادر محاورهای | |
شماره نوع فایلی که بهطور پیشفرض در لیست بالا پیشنهاد میشود. از 0 شروع میشود. | |
پوشهای که در ابتدا برای جستجوی فایل جهت باز کردن نمایش داده میشود | |
نام فایلی که باید باز شود، همانطور که توسط کاربر مشخص شده است | |
روشی که کادر محاورهای ذخیره را نمایش میدهد. مقدار بازگشتی از نوع DialogResult است. |
روش ShowDialog یک کادر محاورهای مشابه شکل زیر را نمایش میدهد:
![]() |
فهرست کشویی تولید شده از خاصیت Filter. نوع فایل پیشفرض توسط FilterIndex تنظیم میشود. | |
نام فایل انتخابشده یا مستقیماً واردشده توسط کاربر. این نام در ویژگی FileName در دسترس خواهد بود. | |
دکمههای باز کردن/لغو. اگر دکمه Ouvrir استفاده شود، تابع ShowDialog نتیجه DialogResult.OK را برمیگرداند. |
روند باز کردن را میتوان به صورت زیر نوشت:
Private Sub btnCharger_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCharger.Click
' بارگذاری یک فایل متنی در کادر ورودی
' راهاندازی کادر گفتگو openfileDialog1
openFileDialog1.InitialDirectory = Application.ExecutablePath
openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
openFileDialog1.FilterIndex = 0
' پنجرهٔ گفتگو را نمایش داده و نتیجهٔ آن را بازیابی میکند
If openFileDialog1.ShowDialog() = DialogResult.OK Then
' نام فایل را بازیابی کنید
Dim nomFichier As String = openFileDialog1.FileName
Dim fichier As StreamReader = Nothing
Try
' فایل را در حالت فقط خواندنی باز کنید
fichier = New StreamReader(nomFichier)
' کل فایل را میخواند و در TextBox ذخیره میکند
txtTexte.Text = fichier.ReadToEnd()
Catch ex As Exception
' مشکل
MessageBox.Show("Problème à la lecture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' بستن فایل
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- دایرکتوری اولیه روی دایرکتوری حاوی فایل اجرایی برنامه تنظیم میشود:
- ما انواع فایلهایی را که باید نمایش داده شوند مشخص میکنیم
- نوع فایلی را که باید ابتدا نمایش داده شود، تنظیم کنید
در اینجا، فایلهای نوع *.txt ابتدا به کاربر نمایش داده میشوند.
- جعبهی گفتوگو نمایش داده میشود و نتیجهی آن بازیابی میشود
If openFileDialog1.ShowDialog() = DialogResult.OK Then
در حالی که کادر محاورهای نمایش داده میشود، کاربر دیگر به فرم اصلی دسترسی ندارد (این به عنوان کادر محاورهای مدال شناخته میشود). کاربر نام فایلی را که باید باز شود مشخص میکند و با کلیک بر روی دکمه «باز کردن»، دکمه «لغو» یا بستن کادر محاورهای، آن را ترک میکند. نتیجه متد ShowDialog تنها در صورتی DialogResult.OK خواهد بود که کاربر از دکمه Ouvrir برای بستن کادر محاورهای استفاده کرده باشد.
- پس از انجام این کار، نام فایلی که باید ایجاد شود اکنون در خصوصیت FileName از شیء openFileDialog1 قرار دارد. سپس به فرآیند استاندارد خواندن یک فایل متنی بازمیگردیم. توجه داشته باشید که متدی که امکان خواندن کل فایل را فراهم میکند:
- محتویات فایل در اشیاء TextBox و txtTexte قرار داده میشوند. هرگونه استثنایی که ممکن است رخ دهد، مدیریت میشود.
5.7.2. جعبههای گفتگو FontColor و ColorDialog
با مثال قبلی ادامه میدهیم و دو دکمه جدید معرفی میکنیم:
![]() |
خیر. | نوع | name | نقش |
۶ | دکمه | btnCouleur | برای تنظیم رنگ متن برای TextBox |
۷ | دکمه | btnPolice | برای تنظیم قلم برای TextBox |
ما یک کنترل ColorDialog و یک کنترل FontDialog را روی فرم قرار میدهیم:

کلاسهای FontDialog و ColorDialog دارای متدی به نام ShowDialog هستند که مشابه متد ShowDialog در کلاسهای OpenFileDialog و ColorDialog است.P001334ZQX. متد ShowDialog از کلاس ColorDialog به شما امکان میدهد یک رنگ را انتخاب کنید:

اگر کاربر با استفاده از دکمه OK از کادر محاورهای خارج شود، نتیجه متد ShowDialog برابر با DialogResult.OK است و رنگ انتخابشده در خصوصیت Color شیء در حال استفاده ColorDialog ذخیره میشود. متد ShowDialog از کلاس FontDialog به شما امکان میدهد یک قلم را انتخاب کنید:

اگر کاربر با استفاده از دکمه OK از کادر محاورهای خارج شود، نتیجه روش ShowDialog برابر با DialogResult.OK است و فونت انتخابشده در ویژگی Font از شیء FontDialog در حال استفاده ذخیره میشود. ما عناصر لازم برای رسیدگی به کلیکهای روی دکمههای Couleur و Police را داریم:
Private Sub btnCouleur_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCouleur.Click
' رنگ متن را انتخاب کنید
If colorDialog1.ShowDialog() = DialogResult.OK Then
' تغییر ویژگی 'forecolor' از TextBox
txtTexte.ForeColor = colorDialog1.Color
End If
End Sub
Private Sub btnPolice_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnPolice.Click
'انتخاب قلم
If fontDialog1.ShowDialog() = DialogResult.OK Then
'تغییر ویژگی «font» در TextBox
txtTexte.Font = fontDialog1.Font
End If
End Sub
5.7.3. تایمر
در اینجا پیشنهاد میکنیم برنامه زیر را بنویسیم:
![]() |
خیر. | نوع | نام | نقش |
۱ | TextBox, ReadOnly=true | txtChrono | نمایش ساعتشمار |
2 | دکمه | btnArretMarche | دکمه توقف/شروع برای تایمر |
۳ | تایمر | تایمر۱ | کامپوننتی که هر ثانیه یک رویداد را فعال میکند |
ثانیهشمار در حال اجرا است:

ثانیهشمار متوقف شد:

برای تغییر محتوای TextBox و txtChrono هر ثانیه، به یک کامپوننت نیاز داریم که هر ثانیه یک رویداد تولید کند تا بتوانیم آن را برای بهروزرسانی نمایش تایمر متوقفشده رهگیری کنیم. این کامپوننت Timer است:

پس از نصب این کامپوننت روی فرم (در بخش کامپوننتهای غیرگرافیکی)، یک شیء از نوع Timer در سازنده فرم ایجاد میشود. کلاس System.Windows.Forms.Timer به شرح زیر تعریف شده است:

از میان ویژگیهای آن، تنها موارد زیر را بررسی خواهیم کرد:
تعداد میلیثانیهها پس از آن که یک رویداد Tick فعال میشود. | |
رویدادی که در پایان Interval میلیثانیه تولید میشود | |
تایمر را روی فعال (true) یا غیرفعال (false) تنظیم میکند |
در مثال ما، تایمر timer1 نامیده میشود و timer1.Interval روی 1000 میلیثانیه (1 ثانیه) تنظیم شده است. بنابراین رویداد Tick هر ثانیه یکبار رخ خواهد داد. کلیک روی دکمه Stop/Start با رویه زیر مدیریت میشود:
Private Sub btnArretMarche_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnArretMarche.Click
' متوقف یا شروع؟
If btnArretMarche.Text = "Marche" Then
' زمان شروع را یادداشت کنید
début = DateTime.Now
' آن را نمایش دهید
txtChrono.Text = "00:00:00"
' شروع تایمر
timer1.Enabled = True
' برچسب دکمه را تغییر دهید
btnArretMarche.Text = "Arrêt"
'پایان
Return
End If '
If btnArretMarche.Text = "Arrêt" Then
' تایمر را متوقف کنید
timer1.Enabled = False
' تغییر برچسب دکمه
btnArretMarche.Text = "Marche"
' پایان
Return
End If
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
'یک ثانیه سپری شده است
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
برچسب دکمه توقف/شروع یا «توقف» یا «شروع» است. بنابراین باید این برچسب را بررسی کنیم تا مشخص شود چه اقدامی باید انجام دهیم.
- اگر برچسب «On» باشد، زمان شروع در یک متغیر سراسری از نوع object ذخیره میشود، تایمر شروع میشود (Enabled=true) و برچسب دکمه به «Off» تغییر میکند.
- اگر برچسب «Stop» باشد، تایمر متوقف میشود (Enabled=false) و برچسب دکمه به «Start» تغییر میکند.
Public Class Timer1
Inherits System.Windows.Forms.Form
Private WithEvents timer1 As System.Windows.Forms.Timer
Private WithEvents btnArretMarche As System.Windows.Forms.Button
Private components As System.ComponentModel.IContainer
Private WithEvents txtChrono As System.Windows.Forms.TextBox
Private WithEvents label1 As System.Windows.Forms.Label
' متغیرهای نمونه
Private début As DateTime
ویژگی début بالا در تمام متدهای کلاس شناسایی میشود. اکنون باید رویداد Tick را روی شیء timer1 مدیریت کنیم، رویدادی که هر ثانیه رخ میدهد:
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' یک ثانیه سپری شده است
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
ما زمان سپریشده از زمان شروع تایمر را محاسبه میکنیم. ما یک شی از نوع TimeSpan به دست میآوریم که نشاندهنده یک بازه زمانی است. این باید در ساعتشمار به فرمت ساعت:دقیقه:ثانیه نمایش داده شود. برای این کار، از ویژگیهای Hours و Minutes استفاده میکنیم، Seconds از شیء TimeSPan، که به ترتیب نمایانگر ساعتها، دقیقهها و ثانیههای مدتزمان هستند. ما این را در قالب ToString("d2") نمایش میدهیم تا نمایش دو رقمی را تضمین کنیم.
5.8. مثال IMPOTS
به برنامه IMPOTS بازمیگردیم، که قبلاً دو بار آن را بررسی کردهایم. اکنون یک رابط کاربری گرافیکی به آن اضافه خواهیم کرد:
![]() |
کنترلها به شرح زیر هستند
خیر. | نوع | نام | نقش |
RadioButton | rdOui | در صورت متأهل بودن تیک خورده | |
RadioButton | rdNon | تیک خورده در صورت متأهل نبودن | |
NumericUpDown | incEnfants | تعداد فرزندان مؤدی حداقل=0، حداکثر=20، گام=1 | |
TextBox | txtSalaire | حقوق سالانه مالیاتدهنده در F | |
TextBox | txtImpots | مبلغ مالیات پرداختنی فقط خواندنی=true | |
دکمه | btnCalculer | شروع محاسبه مالیات | |
دکمه | btnEffacer | فرم را هنگام بارگذاری به حالت اولیه بازمیگرداند | |
دکمه | btnQuitter | برای خروج از برنامه |
قوانین عملکرد
- دکمه «حساب کردن» تا زمانی که چیزی در فیلد حقوق وارد نشده باشد غیرفعال باقی میماند
- اگر هنگام اجرای محاسبه، مشخص شود که حقوق نادرست است، خطایی گزارش میشود:

برنامه در زیر نشان داده شده است. این برنامه از کلاس impot که در فصل مربوط به کلاسها ایجاد شده است، استفاده میکند. برخی از کدهای تولیدشده بهطور خودکار توسط VS.NET در اینجا بازنشر نشدهاند.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
' گزینهها
Option Explicit On
Option Strict On
' فضاهای نام
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
'کلاس فرم
Public Class frmImpots
Inherits System.Windows.Forms.Form
Private WithEvents label1 As System.Windows.Forms.Label
Private WithEvents rdOui As System.Windows.Forms.RadioButton
Private WithEvents rdNon As System.Windows.Forms.RadioButton
Private WithEvents label2 As System.Windows.Forms.Label
Private WithEvents txtSalaire As System.Windows.Forms.TextBox
Private WithEvents label3 As System.Windows.Forms.Label
Private WithEvents label4 As System.Windows.Forms.Label
Private WithEvents groupBox1 As System.Windows.Forms.GroupBox
Private WithEvents btnCalculer As System.Windows.Forms.Button
Private WithEvents btnEffacer As System.Windows.Forms.Button
Private WithEvents btnQuitter As System.Windows.Forms.Button
Private WithEvents txtImpots As System.Windows.Forms.TextBox
Private components As System.ComponentModel.Container = Nothing
Private WithEvents incEnfants As System.Windows.Forms.NumericUpDown
' جدولهای داده مورد نیاز برای محاسبه مالیات
Private limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Private coeffR() As Decimal = {0D, 0.05D, 0.1D, 0.15D, 0.2D, 0.25D, 0.3D, 0.35D, 0.4D, 0.45D, 0.55D, 0.5D, 0.6D, 0.65D}
Private coeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' شیء مالیات
Private objImpôt As impot = Nothing
Public Sub New()
InitializeComponent()
' ابتداییسازی فرم
btnEffacer_Click(Nothing, Nothing)
btnCalculer.Enabled = False
' ایجاد یک شیء مالیات
Try
objImpôt = New impot(limites, coeffR, coeffN)
Catch ex As Exception
MessageBox.Show("Impossible de créer l'objet impôt (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
' غیرفعال کردن فیلد ورود حقوق
txtSalaire.Enabled = False
End Try 'try-catch
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
....
End Sub
Private Sub InitializeComponent()
Me.btnQuitter = New System.Windows.Forms.Button
Me.groupBox1 = New System.Windows.Forms.GroupBox
Me.btnEffacer = New System.Windows.Forms.Button
Me.btnCalculer = New System.Windows.Forms.Button
Me.txtSalaire = New System.Windows.Forms.TextBox
Me.label1 = New System.Windows.Forms.Label
Me.label2 = New System.Windows.Forms.Label
Me.label3 = New System.Windows.Forms.Label
Me.rdNon = New System.Windows.Forms.RadioButton
Me.txtImpots = New System.Windows.Forms.TextBox
Me.label4 = New System.Windows.Forms.Label
Me.rdOui = New System.Windows.Forms.RadioButton
Me.incEnfants = New System.Windows.Forms.NumericUpDown
Me.groupBox1.SuspendLayout()
CType(Me.incEnfants, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
....
End Sub 'InitializeComponent
Public Shared Sub Main()
Application.Run(New frmImpots)
End Sub 'Main
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' پاک کردن فرم
incEnfants.Value = 0
txtSalaire.Text = ""
txtImpots.Text = ""
rdNon.Checked = True
End Sub 'btnEffacer_Click
Private Sub txtSalaire_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSalaire.TextChanged
'وضعیت دکمه «حساب کردن»
btnCalculer.Enabled = txtSalaire.Text.Trim() <> ""
End Sub 'txtSalaire_TextChanged
Private Sub btnQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnQuitter.Click
'پایان برنامه
Application.Exit()
End Sub 'btnQuitter_Click
Private Sub btnCalculer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCalculer.Click
' آیا حقوق صحیح است؟
Dim intSalaire As Integer = 0
Try
' بازیابی حقوق
intSalaire = Integer.Parse(txtSalaire.Text)
' باید ≥۰ باشد
If intSalaire < 0 Then
Throw New Exception("")
End If
Catch ex As Exception
' پیام خطا
MessageBox.Show(Me, "Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error)
' تمرکز بر فیلد نادرست
txtSalaire.Focus()
' انتخاب متن در فیلد ورودی
txtSalaire.SelectAll()
'بازگشت به رابط کاربری
Return
End Try 'try-catch
' حقوق صحیح است – مالیات محاسبه شده است
txtImpots.Text = "" & CLng(objImpôt.calculer(rdOui.Checked, CInt(incEnfants.Value), intSalaire))
End Sub 'btnCalculer_Click
End Class
در اینجا ما از فایل اسمبلی impots.dll استفاده میکنیم که نتیجهٔ کامپایل کلاس impots از فصل ۲ است. به یاد داشته باشید که این فایل اسمبلی را میتوان در حالت کنسول با استفاده از دستور زیر تولید کرد
این دستور فایل impots.dll را که به آن اسمبلی گفته میشود، تولید میکند. این اسمبلی سپس میتواند در پروژههای مختلف استفاده شود. در اینجا، در پروژهٔ ما تحت VS.NET، از پنجرهٔ خواص پروژه استفاده میکنیم:

برای افزودن یک مرجع (یک اسمبلی)، روی گروه کلید «References» در بالا کلیک راست کرده، گزینه [Ajouter une référence] را انتخاب کرده و اسمبلی [impots.dll] را که با دقت در پوشه پروژه قرار دادهایم، مشخص میکنیم:
dos>dir
01/03/2004 14:39 9 250 gui_impots.vb
01/03/2004 14:37 4 096 impots.dll
01/03/2004 14:41 12 288 gui_impots.exe
پس از اینکه اسمبلی [impots.dll] به پروژه اضافه شد، کلاس [impots] برای پروژه قابل دسترس میشود. پیش از این، اینگونه نبود. روش دیگر این است که فایل منبع impots.vb را به پروژه اضافه کنید. برای انجام این کار، در پنجرهٔ خواص پروژه، روی پروژه کلیک راست کرده، گزینهٔ «[Ajouter/Ajouter un élément existant]» را انتخاب کرده و فایل «impots.vb» را مشخص کنید.















































