-
نقل قول: یک سری آموزش و نمونه
برنامه زیر 20 جمله اول سری فیبوناچی را نمایش میدهد :
Private Sub Command24_Click()
Cls
Dim a As Integer, b As Integer, c As Integer, i As Integer
a = 1
For i = 1 To InputBox("Enter number of fibonacci series you want to make", , 20)
c = a + b
Print c
a = b
b = c
Next
End Sub
-
نقل قول: یک سری آموزش و نمونه
برنامه زیر دو عدد صحیح از ورودی خوانده و عمل ضرب را بدون استفاده از عملگر ضرب محاسبه و نمایش میدهد :
Private Sub Command25_Click()
Dim a As Integer, b As Integer, i As Integer, m As Integer
a = InputBox("Enter first num")
b = InputBox("Enter second num")
For i = 1 To b
m = m + a
Next
MsgBox a & " * " & b & " = " & m
End Sub
-
نقل قول: یک سری آموزش و نمونه
برنامه زیر رشته ای را از ورودی دریافت کرده و تعداد حروف بزرگ و کوچک آن را نمایش میدهد بصورت مجزا :
Private Sub Command1_Click()
Cls
Dim s As String
s = InputBox("")
For i = 1 To Len(s)
Select Case Mid(s, i, 1)
Case "A" To "Z"
u = u + 1
Case "a" To "z"
l = l + 1
End Select
Next
Print "horuf kuchak"; l
Print "horufe bozorg"; u
End Sub
-
نقل قول: یک سری آموزش و نمونه
برنامه زیر رشته ای را از ورودی دریافت کرده و تعیین میکند که آیا رشته از هردو طرف که در نظر گرفته شود یکسان است یا خیر؟ :
Private Sub Command2_Click()
Cls
Dim t As String
t = InputBox("Enter string")
If StrReverse(t) = t Then
Print "YES"
Else: Print "NO"
End If
End Sub
-
نقل قول: یک سری آموزش و نمونه
برنامه زیر بدون استفاده از تابع Replace، کار این تابع را شبیه سازی میکند :
Private Sub Command3_Click()
Cls
Dim s As Integer, f As Integer, r As Integer, p1 As Integer, p2 As Integer, i As Integer
s = InputBox("Enter string")
f = InputBox("Find")
r = InputBox("Replace with")
Do Until InStr(1, s, f) = 0
i = InStr(1, s, f)
p1 = Mid(s, 1, i - 1)
p2 = Mid(s, i + Len(f))
s = p1 + r + p2
Loop
Print s
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
برنامه زیر رشته ای را از ورودی دریافت میکند و مجموع ارقام نویسه ای موجود در رشته را محاسبه مینماید و نمایش میدهد :
Private Sub Command5_Click()
Cls
Dim t As String, i As Integer, s As Integer, p As String
t = InputBox("Enter string")
For i = 1 To Len(t)
p = Mid(t, i, 1)
If IsNumeric(p) Then s = s + p
Next
Print s
End Sub
-
نقل قول: یک سری آموزش و نمونه
این برنامه حاصل عبارت زیر را تا 10 جمله حساب کند:
Private Sub Command1_Click()
Dim i As Integer, a As Single
a = 1
For i = 1 To 9
a = a + i / (i + 1)
Next
Print a
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
خیلی از دوستان اصولاً متغیر ها رو نمیشناسن و نمیدونن چطور و کجا و از چه نوع متغیری استفاده کنند. در این پست اصول کلی از متغیر ها رو توضیح میدهم :
انواع متغیرها:
متغیرها در ویژوال بیسیک به دو دسته عددی و غیر عددی تقسیم بندی می شوند. داده های عددی نیز خود به دو گروه صحیح و اعشاری تقسیم می شوند. داده های غیر عددی شامل داده های منطقی ، رشته ای ، تاریخ و زمان و شیء می باشند ، که هر کدام را به اختصار توضیح می دهیم.
الف) متغیرهای عددی :
در زیر جدولی از این نوع برحسب میزان حافظه اشغالی مرتب شده اند، که دانستن آن برای پیشروی در آموختن لازم است:
باره قابل قبول
نوع متغیر
۰ تا ۲۵۵
Byte
۳۲۷۶۷- تا ۳۲۷۶۸
Integer
۲۱۴۷۴۸۳۶۷- تا ۲۱۴۷۴۸۳۶۴۸
Long
تمام متغیرهایی که از یکی از این سه نوع تعریف شوند فقط پذیرای اعداد صحیح خواهند بود. اگر یک عدد اعشاری به این نوع متغیرها نسبت داده شود فقط قسمت صحیح عدد در متغیر قرار می گیرد.
انواع متغیرهای اعشاری هم به این صورت هستند:
بازه قابل قبول
نوع متغیر
گستره وسیعی با ۶ رقم اعشار
Single
گستره وسیعی با ۱۴ رقم اعشار
Double
۴ رقم اعشار
Currency
نکته: توجه نمایید که نوع Currency بیشتر برای محاسبات مالی و اداری استفاده می شود.
ب ) متغیر رشته ای :
در نوشتن اکثر برنامه ها نیاز به متغیرهایی خواهد شد که حروف و کلماتی مثل نام افراد را نگهداری کنند. در ویژوال بیسیک این کار به عهده متغیرهایی هستند که از نوع String تعریف شوند.
ج ) متغیرهای دو مقداری ( منطقی ) :
گاهی متغیری لازم است که بتواند یکی از دو مقدار True یا False ( همان صفر و یک، یا درست و نادرست) را در خود نگهداری کند. این نوع در برنامه با کلمه کلیدی Boolean مشخص می شود. در ادامه با این متغیرها بیشتر آشنا خواهید شد.
د ) نوع تاریخ و زمان :
توضیح خاصی ندارد! فقط به یاد داشته باشید که با کلمه کلیدی Date مشخص می شود. همانگونه که از نام آن پیداست، برای کار با زمان و تاریخ کاربرد دارد.
ه ) نوع Variant:
این نوع می تواند انواع متغیرهای بالا را در خود جای دهد! یعنی در یک قسمت می تواند عدد باشد، و در قسمت دیگر رشته، و . . . !! البته بر خلاف گستردگی ظاهریش چندان پر کاربرد نیست.
تعریف متغیرها:
برای تعریف متغیر - و یا در واقع اعلان نوع آن - از ساختار زیر استفاده می کنیم:
Dim نام متغیر As نوع متغیر
به مثال های زیر توجه کنید:
Dim x As Double
Dim n , m As Integer
Dim fname , str1 , str2 As String * 10
دستور اول x را از نوع اعشاری double تعریف می کند.
در دستور دوم دو متغیر m و n از نوع صحیح integer تعریف می شوند (به علامت , بین دو متغیر توجه کنید).
در سطر سوم str1 ، fname و str2 هر سه از نوع String تعریف می شوند. با این تفاوت که رشته str2 حداکثر می تواند ۱۰ کاراکتر بپذیرد.
نکته بسیار مهم: در حقیقت تعریف کردن متغیرها در زبان ویژوال بیسیک باعث جلوگیری از بروز خطا وکمتر مصرف شدن حافظه می شود، و شما می توانید بدون این که متغیرها را تعریف کنید از آنها استفاده نمایید. اگر چه این امر بر وفق مراد تازه کاران است، ولی بهتر است در برنامه متغیرها را تعریف، و سپس استفاده کنید. یکی از مزایای این کار این است که اگر در برنامه ای نام متغیری را اشتباه تایپ کنید هنگام اجرای آن خطای عدم شناسایی متغیر دریافت می کنید. در صورتی که قصد دارید همواره از قاعده تعریف قبل از استفاده را به کار ببرید، کافی است عبارت Option Explicit را قبل از همه کدهای برنامه تایپ کنید.
برای مقدار دهی به متغیرهای تعریف شده دو روش وجود دارد: با دستورات انتساب - که با علامت = انجام می پذیرد - ، و با دستورات ورودی.
ما با دستور = به متغیرهای عددی که در بالا تعریف شده اند مقدار می دهیم:
x = -21.2
n = x
m = ( n + 2 ) * 3 ^ 2 / 5
fname = "ali"
در دستور اول عدد اعشاری 21.2- در x قرار می گیرد. دستور مقدار 21- را در n قرار می دهد.( چرا که n از نوع صحیح تعریف شده است.) مقدار m هم بر اساس تقدم عملگرها تعیین می شود. ترتیب این تقدم به صورت زیر است:
· ( ) : عبارتهای داخل جفت پرانتز بیشترین تقدم رو دارند.
· ^ : توان ریاضی
· * و / : ضرب و تقسیم اعشاری
· \ : تقسیم صحیح (یعنی حاصل این تقسیم همیشه عدد صحیح می باشد.)
· Mod : باقیمانده تقسیم را می دهد. مثلا در عبارت x = 15 Mod 2 مقدار x برابر 1 می شود.
· – و + : جمع و تفریق معمولی
بر اساس مطالب فوق مقدار m به این صورت محاسبه می شود:
m = ( -21 + 2 ) * 3 ^ 2 / 5 = -19 * 3 ^ 2 / 5 = -19 * 9 / 5 = -171 / 5 = -34.2
آخرین دستور کلمه ali را در متغیر رشته ای fname قرار می دهد. اما چرا ali داخل جفت گیومه قرار گرفته؟ عیارت زیر چرا درست عمل نمی کند؟
fname = ali
دو حالت مختلف را بررسی می کنیم:
اول: در ابتدای کدها از Option Explicit استفاده شده است. در این صورت برنامه به دنبال متغری با نام ali می گردد.
دوم: در ابتدای کدها از Option Explicit استفاده نشده است. در این صورت برنامه فرض می کند ali متغیری است رشته ای، و - چون هیچ مقدار خاصی ندارد - رشته تهی در fname قرار می گیرد.
هر دوی این حالتها برخلاف انتظار ماست. لذا برای جلوگیری از چنین اشتباهاتی در ویژوال بیسیک رشته ها (دقت کنید که رشته ها، نه متغیرهای رشته ای) درون " " قرار می گیرند.
حال به عبارات زیر توجه کنید:
str1 = ”Visual “ + ”Basic”
str2 = str1
str1 = 1 + 3
fname = str1 + ” is an integer number”
در دستور اول دو رشته داخل گیومه با هم الحاق شده ، و رشته “Visual Basic” درون str1 قرار می گیرد. با دستور & نیز می توان همانند + دو رشته را به هم متصل نمود.
در دستور دوم محتویات متغیر str1 جایگزین محتویات str2 می شود. اما با توجه به اینکه str2 حداکثر گنجایش ۱۰ کاراکتر را دارد، تنها عبارت "Visual Bas" در آن قرار می گیرد.
در خط سوم سمت راست عملگر انتساب یک عدد صحیح، و سمت چپ یک رشته است. اما چون مقدار سمت راست در متغیر سمت چپ قرار داده می شود - که از نوع رشته ای است - مقدار عددی ۴ به مقدار رشته ای ۴ تبدیل می شود. یعنی:
str1 = "4"
توجه داشته باشید که دو عبارت زیر با هم تفاوت دارند:
str1 = 1 + 3
str1 = "1 + 3"
بر اساس توضیحات فوق در نهایت مقدار متغیر fname به صورت زیر خواهد یود:
fname = str1 + " is an Integer number" = "4" + " is an Integer number" = "4 is an Integer number"
نکته بسیار مهم: البته در نام گذاری متغیر ها باید از قوانین خاصی پیروی کرد. فاصله در نام گذاری متغیر ها مجاز نیست.
مثلاً Dim Ali Reza As Integer غلط است چرا که بین دو کلمه Ali و Reza فاصله است.
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
استفاده از منو در فرمها:
لابد از اهميت فوق العاده زياد منوها در ويندوز مطلع هستيد. منوها علاوه بر تنوع و زيبايي فرمها، به شلوغ نشدن يك فرم توسط دكمه هاي زياد نيز كمك ميكنند.
براي درست كردن منو براي يك فرم از MenuEditor كه در منوي Tools قرار دارد استفاده مي كنيم. همچنين MenuEditor يك دكمه فوري نيز بر روي ميله ابزار استاندارد VB به شكل دارد كه با كليك بر روي آن نيز پنجره MenuEditor باز مي شود. اين پنجره مانند شكل 10 مي باشد:
شکل 10
در پنجره مذكور كافيست عنوان منوي اول (مثلاMenu1) را در كادر Caption بنويسيم و مانند ساير objectهاي VB به اين منو هم يك نام (مثلاmnuMenu1) در كادر Name وارد كنيم. حال براي وارد كردن نام و عنوان منوي بعدي كافيست كليد Next را بزنيم. اما معمولا منوي بعدي، آيتمي از منوي قبلي خواهد بود. اگر كليد را بزنيم، منوي جاري به عنوان زير منوي قبلي محسوب خواهد شد. پس از وارد كردن اولين آيتم كافيست بوسيله دكمه Next آيتم هاي بعدي اولين منو را نيز وارد كنيم. اگر يكي از آيتم ها خود شامل زير آيتم هايي بود باز هم مي توان از كليد سود برد. و بالاخره براي اينكه به سراغ منوي دوم برويم لازم است از كليد به تعدادي استفاده كنيم كه ديگر زيرمنوي يك منوي ديگر نباشد و به همين ترتيب ساير منوها و آيتمها را نيز نامگذاري و عنواندهي ميكنيم و ساختار مورد نظرمان را براي منوها ايجاد ميكنيم.
لذا اگر منوها را در MenuEditor طوري وارد كنيم كه پنجره پايين MenuEditor مطابق آنچه در شكل 10 ميبينيد، شود، انتظار داريم در هنگام اجرا، فرمی شبيه آنچه در شکل 11 می بينيد، حاصل شود:
شکل 11
توجه داشته باشيد كه در MenuEditor علاوه بر آنچه تابهحال گفته شد:
• دكمه Delete براي پاك كردن يك منو (يا آيتم) استفاده مي شود.
• دكمه Insert براي افزودن يك منو (يا آيتم) ميان دو منو (يا آيتم) ديگر استفاده مي شود
• Check Boxهاي Visible و Enable به ترتيب اگر انتخاب نشده شوند، منوي مذكور ديده نمي شود و يا اينكه فقط غيرفعال (و به رنگ خاكستري) خواهد شد.
• Check Box با عنوان Checked اگر انتخاب شود، باعث خواهد شد تا كنار آن منو (آيتم) يك "چكمارك" ديده شود. (معمولا اين مشخصه در Run Time و بر حسب نياز تنظيم مي شود)
• توسط Shortcut مي توانيم يك ميانبر (Shortcut) براي يكي از آيتمها درست كنيم..
• توسط Index مي توانيم آرايه اي از منوها را طراحي نماييم ( همانطوری که آرايه ای ازساير کنترلها درست می کرديم، يعنی بايد نام دو يا چند منو را يک نام واحد بگذاريم و Index متفاوت به هريک بدهيم.)
• و توسط NegotiatePosition ميتوان نوع چيدن آيتمها (راست چين، چپ چين، وسط چين) را تعيين نمود.
چند تذكر:
• براي دستيابي به مشخصه هاي منوها نيز مانند ساير كنترلها از نام آنها و يك نقطه(Dot) و سپس نام مشخصه مورد نظر استفاده مي كنيم. مثلا اگر منويي به نام mnuOpen داشته باشيم و بخواهيم آن را غيرفعال و يا ماركدار نماييم به ترتيب از دستورات زير استفاده خواهيم كرد:
mnuOpen.Enable = False
mnuOpen.Checked = True
• مشخصه WindowList در بحث MDI Forms خواهد آمد و از مشخصه HelpContentID نيز تنها زماني كه يك فايل HLP داشته باشيم ميتوانيم استفاده كنيم.
• اگر بخواهيم بين دو آيتم از منويي يك خط جداكننده آورده شود (آنچه در ويندوز براي جداكردن بخشهاي مختلف يك منوي خاص معمول است) كافي است بين آن دو آيتم، يك آيتم Insert نماييم، نام آن را يك نام دلخواه (مثلا mnuLine) و عنوان (Caption) آن را يك منفي (كاراكتر "-" يا اصطلاحا Dash) بگذاريم.
• اگر بخواهيم براي شي خاصی يك PopUpMenu طراحي كنيم (منوهاي بازشوندهاي كه وقتي بر روي شي كليك راست شود از آن خارج ميشود) كافيست يك منو (با آيتمهاي مورد نظر براي آن) را طراحي كنيم (و حتي در صورت نياز Visible آن را False كنيم) و در رويداد MouseDown از آن شي خاص، پس از اينكه شرط كرديم كليد زده شده كليد راست ماوس باشد (با استفاده از شرط برابري پارامتر Button از اين رويداد با مقدار ثابت VbRightButton)، با استفاده از دستور PopUpMenu، نام منوي مورد نظر را فراخواني مي كنيم يعني بايد چنين داشته باشيم:
Private Sub controlName_MouseDown (Button As Integer,…)
IF Button = VbRightButton Then
PopUpMenu mnuMenu1
End IF
End Sub
كه بجاي controlName نام آن كنترلي كه قرار است كاربر روي آن كليك راست نمايد و بجاي mnuMenu1 نام آن منويي كه قرار است به صورت PopUp آورده شود را ذكر مي كنيم.
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
شناسایی CD ROM در سیستم :
دو تا لیبل بزارید توی فرمتون به نام های Lable1 و l1
این کدها رو به فرمتون اضافه کنین :
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Private Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Const Drive_Removable = 2
Private Const Drive_Fixed = 3
Private Const Drive_Remote = 4
Private Const Drive_CDRom = 5
Private Const Drive_RamDisk = 6
Private Sub Form_Load()
Dim R As Long
Dim AllDrives As String
Dim JustOneDrive As String
Dim Pos As Integer
Dim DriveType As Long
Dim CDFound As Boolean
AllDrives = Space$(64)
R = GetLogicalDriveStrings(Len(AllDrives), AllDrives)
AllDrives = Left$(AllDrives, R)
Do
Pos = InStr(AllDrives, Chr$(0))
If Pos Then
JustOneDrive = Left$(AllDrives, Pos)
AllDrives = Mid$(AllDrives, Pos + 1, Len(AllDrives))
DriveType = GetDriveType(JustOneDrive)
If DriveType = 5 Then
CDFound = True
Exit Do
End If
End If
Loop Until AllDrives = "" Or DriveType = Drive_CDRom
If CDFound Then
L1 = UCase(JustOneDrive)
Else
L1 = "No CDRom"
End If
End Sub
-
2 ضمیمه
نقل قول: آموزش ویژوال بیسیک پیشرفته
برنامه ای که برایتان تهیه کرده ام ظرفیت درایوهای شما رو نشون میده که به نظر من خیلی میتونه کاربردی باشه :
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
با کد های زیر برنامه شما به Startup میرود : (از این نمونه خیلی دیدم اما 60% از آن اصلاً عمل نمیکند.)
یه کامند بزارین تو فرمتون و این کد ها رو اضافه کنین :
Private Sub Cmd_Run_Click()
Dim hregkey As Long
Dim subkey As String
Dim stringbuffer As String
subkey = "Software\Microsoft\Windows\CurrentVersion\Run "
retval = RegOpenKeyEx(HKEY_CURRENT_USER, subkey, 0, KEY_WRITE, hregkey)
If retval <> 0 Then
Debug.Print "Can't open the subkey"
Exit Sub
End If
stringbuffer = App.Path & "\" & App.EXEName & ".exe" & vbNullChar
retval = RegSetValueEx(hregkey, "My App", 0, REG_SZ, ByVal stringbuffer, Len(stringbuffer))
RegCloseKey hregkey
End Sub
اینها رو هم تو یه ماژول کپی کنین :
Public Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal _
hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Public Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Public Declare Function RegSetValueEx Lib "advapi32.dll" _
Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName _
As String, ByVal Reserved As Long, ByVal dwType As Long, _
lpData As Any, ByVal cbData As Long) As Long
Public Const HKEY_CURRENT_USER = &H80000001
Public Const KEY_WRITE = &H20006
Public Const REG_SZ = 1
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
خیلی از دوستان دوست دارن کار با TreeView رو یاد بگیرن ، گفتم آموزششو بزارم :
براي اضافه کردن اين کنترلها به جعبه ابزار ويژوال بيسيک اين کارا رو انجام بدين:
?- از منوي Project > Components را بزنيد يا کليدهاي crtl + T را بزنيد که در اين صورت کادر محاوره اي Components باز ميشود که در سربرگ(Tab) به نام Controls ليستي از کنترل هاي شناخته شده توسط ويژوال بيسيک مي آيد که شما بايد به دنبال Microsoft Windows Common Controls 6.0(SP4) a بگردين و تيک کنار اون رو فعال کنيد و بعد هم OK کنيد.
شما حتمآ حالت نمايش درختي را ديده ايد و بسيار از امکانتش بهرهمند شده ايد.
براي اينکه ياد بگيرين از اين کنترل چگونه استفاده کنيد ابتدا بايد بدانيد که ساختار درختي به صورتي است که در آن يک شاخه اصلي وجود دارد که شاخه هاي فرعي به آن منتصل شده اند. به شاخه هاي فرعي گره(Node)هم گفته مي شود. ما بايد ابتدا شاخه اصلي يا تنه را بسازيم و بعد گره ها را درست کنيم. براي يادگيري کامل به مثال زير توجه کنين:
ابتدا يک کنترل TreeView از جعبه ابزار به فرم اضافه کنيد . حالا اندازه آن را به طور دلخواه تغيير دهيد . روي فرم دابل کليک کنيد تا پنجره کدها و روال Form_Load باز شود.
حالا يک متغير از نوع Node به اسم MainNode تعريف مي کينم به اين صورت:
Dim MainNode as Node
و بعد هم یک متغیر دیگه به اسم ChidNode
Dim ChildNode as Node
بعد هم باید شروع کنیم به ست کردن متغیر ها . برای درست کردن شاخه اصلی به این صورت عمل میکنیم:
Set MainNode = TreeView1.nodes.add( , , "Main" , "Main") 'x
حالا ما شاخه اصلی رو ساختیم . بهتره الآن یه بار برنامه را اجرا کنید و نتیجه را ببینید.
شما میتونید به تعداد دلخواه شاخه درست کنید فقط کافیه به جای Main یک اسم دیگه بزارید.
برای ساختن گره ها یا شاخه های فرعی به جای ست کردن متغیر MainNode متغیر ChildNode را ست می کنیم . توجه داشته باشید که اگر بخواهید یک شاخه فرعی یا گره رو به یک تنه ( که در اینجا اسم تنه Main هست) متصل کنیم باید به صورت زیر عمل کنیم:
Set ChildNode = TreeView1.Nodes.Add("Main" , tvwChild , "Node1" , "Node1") 'x
همون طور که در خط بالا می بینید آرگومان اول Nodes.Add را برابر اسم تنه گذاشتیم و در آرگومان دوم از ثابت tvwChild استفاده کردیم که نشان دهنده این است که گره ای که قرار است اضافه شود زیر شاخه Main است. آرگومان سوم کلمه کلیدی یا یک شناسه است که برای گره ای که ساخته ایم قرار میدهیم در آرگومان چهارم هم خاصیت Text یا به عبارت دیگر کلمه ای که قرار است نمایش داده شود را اضافه کردیم.
در این حالت هم شما می تونید به تعداد دلخواه گره درست کنید فقط باید "Node1" رو در دو آرگومان آخر تغییر بدین.
توضیحات بالا در کل به این صورت است:
Private Sub Form_Load() 'x
Dim MainNode as Node
Dim ChildNode as Node
Set MainNode = TreeView1.Nodes.Add(,, "Main" , "Main") 'x
Set ChildNode = TreeView1.Nodes.Add ( "Main" , tvwChild , "Node1" , "Node1") 'x
End Sub
برای اینکه خوب بتونم آموزشم رو کامل کنم از یکی دو تا مثال استفاده می کنم.
نمایش درایو های موجود در My Computer .
یک پروژه جدید از نوع استاندارد باز کنید سپس یک کنترل TreeView به فرم برنام اضافه کنید و خاصیت آن را برابر TreeView1 قرار دهید .
حالا روی فرم برنامه دابل کلیک کنید تا روال Form_Load باز شود . کدهای زیر رو بنویسید.
Private Sub Form_Load()
Dim N as Node
Dim FSO , Drives
Set N = TreeView1.Nodes.Add(, , "HD" , "My Computer") 'x
set Fso = CreateObject("Scripting.FileSystemObject") 'x
Set Drives = Fso.Drives
For Each Drive In Drives
If Drive.isready then Set N = TreeView1.Nodes.Add("HD" , tvwChild , drive , drive) 'x
Next
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
این هم یه پروپرتی Override شده برای سایه دار کردن فرم ها . زمانی که یه کنترل خواستید بسازید این تکه کد خیلی به دردتون میخوره :
Private Const CS_DROPSHADOW As Integer = 131072
' Override the CreateParams property
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ClassStyle = cp.ClassStyle Or CS_DROPSHADOW
Return cp
End Get
End Property
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
فضانام My در Visual Basic
Visual Basic همواه خصوصیات و امکانات جدیدی به منظور توسعه سریع نرمافزار که باعث بهبود بهرهوری، سهولت در استفاده و بالا بردن قدرت برنامهنویسان میشود، ارائه مینماید. یکی از این امکانات My نام دارد. My امکان دسترسی به اطلاعاتی در مورد پروژه در حال اجرا و همچنین محیطی که پروژه در آن در حال اجرا میباشد را فراهم میسازد. مزیت مهم دیگر My در این است که به راحتی میتوان در قالب لیستهای پیشنهادی « IntelliSense » با امکانات آن کار کرد.
بالاترین سطح My، توسط اشیائی نشان داده میشود. هر کدام از این Objectها مانند یک فضانام و یا یک کلاس با اعضای Shared عمل مینمایند. در جدول زیر اشیاء سطح اول My و ارتباطات داخلی آنها مشخص شده است:
اعضای My عبارتند از:
Application: حاوی اطلاعاتی جامع و کاربردی در مورد پروژه جاری.
Computer: با این گزینه میتوان به خصوصیات و اطلاعات جامعی در مورد سخت افزارهای متصل به سیستم دست یافت.
Forms: با استفاده از این گزینه میتوان به تمامی فرمهای موجود در پروژه و طبعاً اطلاعات درونی آنها دست پیدا کرد.
Settings: از متدهای موجود در این گزینه میتوان تنظیمات پروژه را دستکاری نمود.
User: از این خصوصیت برای بدست آوردن اطلاعات در مورد کاربر جاری سیستم استفاده میشود.
Webservices: این خصوصیت برای فراهم کردن امکاناتی به منظور ایجاد و دستیابی به یک نمونه از وب سرویسهای XML که توسط پروژه جاری به آنها ارجاع شده است استفاده میکنیم.
Computer
این خصوصیت یکی از پرکاربردترین خصوصیات My می باشد. با به کارگیری این گزینه میتوان به راحتی هر چه تمامتر به اطلاعاتی در مورد وضعیت سختافزارهای متصل به سیستم درست پیدا کرد. این کار در یک خط کد و بدون انجام کارهای اضافی توسط برنامهنویس، صورت میپذیرد. به عنوان مثال برای اینکه متوجه شویم ماوس متصل به سیستم اسکرولدار است به راحتی میتوان از کد زیر استفاده کرد:
MsgBox(My.Computer.Mouse.WheelScrollLines)
از طریق Computers میتوان به سختافزارهایی مانند KeyBoard، Mouse، Audio و ... به راحتی دست پیدا کرد.
در ادامه چندین خصوصیت از computers را بررسی می كنیم:
1. Mouse: این شئ دارای 3 خصوصیت به شرح زیر میباشد:
ButtonsSwapped: تعیین جابجا شدن کلیک چپ و راست ماوس.
WheelExists: تعیین اسکرولدار بودن ماوس.
WheelScrollLines: تعیین تعداد سطوری که با یک بار حرکت ماوس رد میشوند.
2. Keyboard: این شئ دارای 6 خصوصیت و یک متد می باشد:
AltKeyDown: تعیین میکند که آیا کلید Alt پایین نگه داشته شده است یا نه؟!
CtrlKeyDown: پایین بودن کلید Ctrl را بررسی می کند.
ShiftKeyDown: تعیین پایین و یا بالا بودن کلید Shift.
NumLock، CapsLock و ScrollLock: تعیین فعال یا غیرفعال بودن کلیدهای مرتبط.
متد ()SendKeys: از این متد برای ارسال ضربات کلید به محیط سیستم عامل استفاده میشود. به عنوان مثال ("+%")My.Computer.Keyboard.SendKeys باعث ارسال ضربات کلید Alt و Shift به سیستم میگردد. لذا زبان سیستم شما تغییر میکند. البته اگر بیش از یک زبان وجود داشته باشد.
3. Name: این خصوصیت از شئ Computer حاوی نام کامپیوتر است.
4. Screen: اطلاعات در مورد صفحه نمایش را در اختیار برنامهنویس قرار میدهد. این کلاس حاوی خصوصیات متعددی است که عبارتند از:
BitsPerPixel: میزان Color فعلی ویندوز را نشان میدهد. به عنوان مثال اگر این گزینه در ویندوز بر روی True Color (32 Bit) تنظیم باشد، عدد 32 و اگر بر روی High Color (16 Bit) تنظیم باشد عدد 16 برگشت داده می شود.
Bounds: حاوی خصوصیاتی به منظور تعیین محدوده کاری تنظیم شده میباشد.
DeviceName: نامی که در سیستم برای مانیتور در نظر گرفته شده است را نمایش میدهد.
Primary: اگر دستگاه نمایش فعلی، دستگاه پیشفرض باشد true برگشت می دهد
WorkingArea: این گزینه اطلاعاتی راجع به میزان محیط کاری فعال در ویندوز را در بر دارد. تفاوت این گزینه با Bounds در این است که در Bounds مختصات کلی نمایش داده میشود اما در این گزینه، محیطی که واقعا میتوان از آن به عنوان Desktop استفاده کرد برگشت داده میشود. مثلاً در این گزینه ارتفاع نوار TaskBar از ارتفاع صفحه کسر میشود.
5. Clock: با استفاده از این شئ میتوان اطلاعات مفیدی در مورد ساعت سیستم بدست آورد. خصوصیات این شئ عبارتند از:
LocalTime: زمان جاری سیستم را برگشت میدهد.
GmtTime: زمان جاری سیستم را براساس زمان جاری GMT بیان میکند.
TickCount: مدت زمانی سپری شده از روشن بودن سیستم براساس میلی ثانیه را برگشت میدهد.
6. Audio: از این شئ برای پخش صوت دلخواه و همچنین صوتهای پیش فرض ویندوز میتوان استفاده کرد. این شئ فقط دارای 3 متد است:
Play: این متد دارای 4 سربارگذاری بوده و با آن میتوان یک فایل صوتی استاندارد را پخش نمود. برای این متد میتوان اطلاعات مسیر ذخیره سازی فایل را ارسال کرد و یا اطلاعات باینری موسیقی را ارسال نمود و یک Stream حاوی موسیقی ارسال نمود. همچنین نحوه پخش شدن را میتوان تنظیم کرد. میتوان کاری کرد که تا اتمام آهنگ فعالیتی صورت نگیرد و یا اینکه موسیقی در پس زمینه اجرا شود و کاربر بتواند به تعامل با برنامه ادامه دهد.
PlaySystemSound: از این متد برای پخش یکی از صداهای پیش فرض در ویندوز استفاده میکنیم. این متد دارای یک پارامتر است و برای مقداردهی آن از لیست پیشنهادی که باز میشود میتوانید استفاده کنید و یا اینکه یکی از اعضای Media.SystemSounds را ارسال کنید. به عنوان مثال Media.SystemSounds.Beep باعث پخش صدای بوقی از سیستم میشود.
Stop: پخش موسیقی را کنسل میکند.
7. FileSystem: این شئ حاوی متدهای فراوانی برای مدیریت فایلها و پوشهها میباشد. به علت سادگی و همخوانی نام متدها با عملی که انجام میدهند از ذکر آنها خودداری میکنیم. در این فایل چندین خصوصیت کاربردی به منظور یافتم مسیر جاری اجرای برنامه و ... نیز گنجانده شده است. مثلا My.Computer.FileSystem.CurrentDirectory مسیر جاری اجرای برنامه را برمیگرداند. و یا از شئ Drives در این شئ برای مدیریت درایوهای کامپیوتر استفاده میشود. همچنین خصوصیت تحت عنوان SpecialDirectories در این شئ وجود دارد که آدرس پوشههای مهم سیستم مانند Desktop، ProgramFiles، Windows، Temp، Programs و ... را برگشت میدهد.
8. Network: این شئ حاوی متدها و خصوصیاتی برای کنترل شبکه میباشدو با متدهای موجود در این شئ میتوانید اقدام به دانلود و ... نیز بکنید.
9. Port: حاوی اطلاعات راجع به پورتهای سیستم و همچنین تعامل با آنها.
10. ClipBoard: حاوی متدهایی برای کنترل و دستکاری کلیپ بورد سیستم. مثلا با متد ContainsText() میتوان پی برد که اگر گزینه Paste در برنامه فشار داده شود آیا متن در حافظه وجود دارد یا خیر؟ متدهای این کلاس به صورت خلاصه عبارتند از:
()Clear: پاک کردن حافظه کلیپبورد.
ContainsText()، ContainsAudio و متدهایی که با Contains آغاز میشوند: بررسی اینکه شئ موجود در حافظه از نوع مد نظر می باشد یا نه؟
متدهای Get: از این متدها برای دریافت اطلاعات موجود در حافظه متناسب با نوع متد برگشت میدهد
متدهای Set: میتوان حافظه را از درون برنامه در حال اجرا ست نمود.
11. Info: این شئ حاوی اطلاعاتی کلی در مورد سیستم است. اطلاعاتی از قبیل نام کامل سیستم عامل، میزان کل حافظه Ram و حافظه مجازی، میزان در دسترس این حافظهها، نوع سیستم عامل و ورژن سیستم عامل و ... . به عنوان مثال (MsgBox(My.Computer.Info.OSFullName نام کامل سیستم عامل را نمایش میدهد
12. Registery: حاوی متدهایی برای کار با رجیستری میباشد. از متدها و اشیاء درونی این شئ برای دستکاری قسمتهای مختلف Registery میتوان استفاده کرد.
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
تولید اعداد تصادفی در بازه خاص :
Public Command As String
Public Permission As String
Public DB1 As Database
Public RS1 As Recordset
Public SL As String 'Select Lesson
Public Cl As String 'Code of Collegian
Public asd As String
Option Explicit
'//===============================================
'//This function create Random number in special range
'//Count ==> count of number that must created
'//Min ==> Minimume of number that can be created
'//Max ==> Maximume of number that can be created
'//Result() ==> A byref array for put result in it and return to user
Public Function Random_X(ByVal Count As Long, ByVal Min As Long, ByVal Max As Long, ByRef Result() As Long, ByVal Sort_Array As Boolean) As Boolean
Dim i As Long
Dim Top_Array As Long
Dim Rand_Num As Long
Randomize '//Randomize Timer
'//============================
'//First check that count in range (MAX-MIN)
If Count > (Max - Min) Then
Random_X = False
Exit Function
Else
Random_X = True
End If
'//============================
Top_Array = 0
ReDim Result(Count - 1) '//Redim Empty Array and Fit it to Count
For i = LBound(Result) To UBound(Result)
Repeat:
Rand_Num = Rnd() * Max
Rand_Num = Rand_Num + Max '//Go Number larger than max
Do While (Rand_Num < Min Or Rand_Num > Max)
Rand_Num = Rand_Num - (Max - Min) '// IF Rand number is out of range , come it in range
Loop
If In_Array_X(Result, Rand_Num, i) = False Then '//IF Not exist then push it into array
Result(i) = Rand_Num
Else
GoTo Repeat
End If
Next
If Sort_Array = True Then Sort Result '//If Sort =True then Sort result array
End Function
'//=======================================
'//This function get a byref array and a num
'//Check the num exist in array
Public Function In_Array_X(ByRef Arr_Name() As Long, ByVal Num As Long, ByVal Top_Arr As Long) As Boolean
Dim i As Long
In_Array_X = False
If Top_Arr > UBound(Arr_Name) Then Top_Arr = UBound(Arr_Name)
For i = LBound(Arr_Name) To Top_Arr
If Arr_Name(i) = Num Then
In_Array_X = True
Exit For
End If
Next
End Function
'//=======================================
'//This Function get a byref array and sort it
Public Sub Sort(ByRef Sort_Arr() As Long)
Dim i As Long, j As Long
Dim Temp As Long
For i = UBound(Sort_Arr) - 1 To LBound(Sort_Arr) Step -1
For j = 0 To i Step 1
If Sort_Arr(j) > Sort_Arr(j + 1) Then
Temp = Sort_Arr(j)
Sort_Arr(j) = Sort_Arr(j + 1)
Sort_Arr(j + 1) = Temp
End If
Next
Next
End Sub
طرز استفاده از تابع :
Dim IfSuccess As Boolean
Dim Result() As Long
IfSuccess = Random_X(1, 100, 1000, Result, True)
Text1.Text = Result(0
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
با این کد می تونید یک فایل رو در شبکه با استفاده از وینسوک ارسال کنید :
Public Sub SendData(ByVal sFile As String, ByVal sSaveAs As String, ByVal tcpSend As Winsock)
On Error GoTo ErrHandler
Dim sSend As String, sBuf As String
Dim ifreefile As Integer
Dim lRead As Long, lLen As Long, lThisRead As Long, lLastRead As Long
Dim strData As String
tcpSend.GetData(strData)
ifreefile = FreeFile
' Open file for binary access:
Open sFile For Binary Access Read As #ifreefile
lLen = LOF(ifreefile)
' Loop through the file, loading it up in chunks of 64k:
Do While lRead < lLen
lThisRead = 65536
If lThisRead + lRead > lLen Then
lThisRead = lLen - lRead
End If
If Not lThisRead = lLastRead Then
sBuf = Space$(lThisRead)
End If
Get #ifreefile, , sBuf
lRead = lRead + lThisRead
sSend = sSend & sBuf
sBuf = Space$(0)
Loop
lTotal = lLen
Close(ifreefile)
bSendingFile = True
'// Send the file notification
tcpSend.SendData("FILE" & sSaveAs)
DoEvents()
'// Send the file
tcpServer.SendData(sSend)
DoEvents()
'// Finished
tcpSend.SendData("FILEEND")
bSendingFile = False
MMControl1.FileName = "FileDone.wav"
MMControl1.Command = "Open"
MMControl1.Command = "Play"
Exit Sub
ErrHandler:
MsgBox "Err " & Err & " : " & Error
End Sub
Private Sub tcpServer_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
Dim ifreefile
' DoEvents
tcpServer.GetData(strData)
If Right$(strData, 7) = "FILEEND" Then
bFileArriving = False
lblProgress = "Saving File to " & App.Path & "\" & sFile
sArriving = sArriving & Left$(strData, Len(strData) - 7)
ifreefile = FreeFile
MMControl1.FileName = "File.wav"
MMControl1.Command = "Open"
MMControl1.Command = "Play"
Open sFile For Binary Access Write As #ifreefile
Put #ifreefile, 1, sArriving
Close #ifreefile
ShellExecute 0, vbNullString, App.Path & "\" & sFile,
vbNullString, vbNullString, vbNormalFocus
lblProgress = "Complete"
ElseIf Left$(strData, 4) = "FILE" Then
bFileArriving = True
sFile = Right$(strData, Len(strData) - 4)
ElseIf bFileArriving Then
lblProgress = "Receiving " & bytesTotal & " bytes for " & sFile & ""
>from " & tcpServer.RemoteHostIP
sArriving = sArriving & strData
MMControl1.FileName = "FileDone.wav"
MMControl1.Command = "Open"
MMControl1.Command = "Play"
End If
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
با این آموزش شما میتونید یه سری اطلاعات رو یه جای خاص از رجیستری ذخیره کنید که مثلا برای ثبت تنظیمات کاربر میتونید مورد استفاده قرار بدید. به نظر من خیلی کاربردی هست :
ذخیره اطلاعات :
FontName=GetSetting(My.Application.Info.AssemblyNa me, "Appearance", "Font","")
ColorName=GetSetting(My.Application.Info.AssemblyN ame, "Appearance", "Color","")
بازیابی اطلاعات :
FontName=GetSetting(My.Application.Info.AssemblyNa me, "Appearance", "Font","")
ColorName=GetSetting(My.Application.Info.AssemblyN ame, "Appearance", "Color","")
مکان ذخیره :
HKEY_CURRENT_USER\Software\VB and VBA Program Settings
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
انجام اعمال متداول در رجیستری خیلی جالبه :
Imports Microsoft.Win32
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
' // Create SubKey
Registry.LocalMachine.CreateSubKey("Software\Sinpi n", RegistryKeyPermissionCheck.ReadWriteSubTree)
'//Create Key and Set Value
Dim reg As RegistryKey = Registry.LocalMachine.OpenSubKey("Software\Sinpin" , True)
reg.SetValue("DWord", "1", RegistryValueKind.DWord)
reg.SetValue("ExpandString", "1", RegistryValueKind.ExpandString)
reg.SetValue("QWord", "1", RegistryValueKind.QWord)
reg.SetValue("String", "1", RegistryValueKind.String)
reg.SetValue("Unknown", "1", RegistryValueKind.Unknown)
'// Delete Key
reg.DeleteValue("DWOrd")
'// Delete SubKey
Registry.LocalMachine.DeleteSubKey("Software\Sinpi n")
'// Read Key Value
Dim val As String = reg.GetValue("QWord").ToString()
'// Retrieve All Keys
For Each s As String In reg.GetValueNames()
MessageBox.Show(s)
Next
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
روش تغییر پسورد پایگاه داده Access از طریق VB :
این بار قرار است روشی رو به شما عزیزان آموزش بدم که با استفاده از آن می توانید کلمه عبوری را که روی پایگاه داده Access خودتان قرار داده اید از طریق کد نویسی در ویژوال بیسیک تغییر دهید . برای انجام این عمل باید مراحل زیر را انجام دهید .
1. ابتدا یک پروژه را در VB باز کنید . سپس از منوی Project گزینه References را انتخاب کنید تا دیالوگی نمایش داده شود . از لیستی که مشاهده می کنید گزینه ( Microsoft DAO 3.51 Object library ) را علامت بزنید . البته این در صورتی است که پایگاه داده شما پایین تر از فرمت Office 2003 باشد . ( مثلا Office 2000 ) . در غیر این صورت باید گزینه ( MicroSoft DAO 3.6 Object Library )علامت بزنید . تا احیانا با خطایی مواجه نشوید . ( نسخه 3.6 میتواند بهترین انتخاب باشد ).
2. سپس مثلا یک دکمه روی فرم خود گذاشته و نام آن را به Cmd_PassChange و عنوان آن را به PassChange تغییر دهید . حال کدهای زیر را داخل آن بنویسید یا کپی کنید :
Dim db As DAO.Database
("Set db = DBEngine.OpenDatabase(App.Path & "\Test.mdb", True, False, ";pwd=media
"db.NewPassword "media", "ali
db.Close
در این مثال ابتدا ما یک متغیر ( db ) را از نوع کتابخانه DAO تعریف می کنیم . در دستور Set کردن پایگاه داده Access توجه داشته باشید که چون پایگاه داده ما از قبل دارای کلمه عبور است ، ما مجبوریم برای ورود به آن از کلمه عبور ( در این مثال media ) استفاده کنیم . همچنین دقت داشته باشید که در این دستور حتما باید مقدار ورودی Option ( مقدار دوم که تعیین می کند ما به تنظیمات پایگاه داده دسترسی داشته باشیم یا نه) مقدار True باشد . درغیر این صورت از تغییر کلمه عبور جلوگیری خواهد شد . در دستور سوم هم که مشاهدی می کنید ، اولین پارامتر ورودی کلمه عبور قبلی و دومین پارامتر ورودی کلمه عبور جدید شما خواهد بود . خط آخر هم در اصطلاح برای بستن پایگاه داده به کار می رود .
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
اعمال مشخصه RightToLeft به کنترلهایی که فاقد این مشخصه اند :
در این روش شما میتونید به هر کنترلی این مشخصه رو اعمال کنید، حتی کنترلهایی که فاقد این مشخصه هستند مثل DirListBox به صورت از راست به چپ در میان. درضمن اگه با فرمتون اینکارو بکنید میبینید که واقعاً به صورت از راست به چپ درمیاد یعنی دکمه Close، Minimize و Maximize از سمت راست فرم به سمت چپ فرم انتقال پیدا میکنن.
یک پروژه جدید باز کنید و یک DirListBox به فرمتون اضافه کنید و کد زیر رو تو قسمت جنرال فرمتون کپی کنید :
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Sub Form_Load()
SetWindowLong Me.hWnd, -20, GetWindowLong(Me.hWnd, -20) Or &H400000
SetWindowLong Dir1.hWnd, -20, GetWindowLong(Dir1.hWnd, -20) Or &H400000
End Sub
حالا برنامه رو اجرا کنید و شاهد تغییراتی که در حالت معمولی غیر ممکن بودن باشید.
این کد رو اگه خواستین تغییر بدین فقط یه شرط داره اونم اینه که کنترلی که میخواین تغییرات روش اعمال بشه باید خاصیت hWnd رو داشته باشه.
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
تنظیم ساعت سیستم با ویژوال بیسیک :
یه تایمر و فرمتون بذارین و اینتروال اون رو روی 1000 تنظیم کنید و کد زیررو توی قسمت جنرال فرمتون قرار بدین
Dim TimeStop
Private Sub Form_Load()
TimeStop = Time
End Sub
Private Sub Timer1_Timer()
Time = TimeStop
End Sub
توی این کد وقتی فرم اجرا میشه زمان وارد TimeStop میشه بعدش توسط تایمر زمان به TimeStop تنظیم میشه که به عبارتی زمان رو نگه میداره
حالا میخوایم زمان رو تنظیم کنیم:
یهCommand رو فرمتون بذارین بعد از این کد استفاده کنید
Private Sub Command1_Click()
Dim H, Min, Sec, AMorPM
H = InputBox("Type Hour...")
Min = InputBox("Type Minute...")
Sec = InputBox("Type Second...")
AMorPM = InputBox("AM time or PM time")
Time = H & ":" & Min & ":" & Sec & AMorPM
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
ثبت تنظیمات و اطّلاعات برنامه در رجیستری :
خب اوّل یک مثال میزنم و بعد میرم سره آموزش تا بهتر یاد بگیرید.
یک پروژه جدید باز کنید و یک Command Button و یک TextBox بذارید تو فرمتون و کد زیر رو تو قسمت جنرال فرمتون کپی کنید :
Private Sub Command1_Click()
SaveSetting App.Title, "Setting", "Value", Text1.Text
End Sub
Private Sub Form_Load()
Text1.Text = GetSetting(App.Title, "Setting", "Value", "Hello")
End Sub
برنامه رو اجرا کنید و هر چی دلتون میخواد تو TextBox وارد کنید و بعد کلید Command1 رو بزنید و از برنامه خارج بشید. حالا اگه دوباره برنامه رو اجرا کنید میبینید متنی که دفعه قبل وارد کرده بودید سره جاشه و پاک نشده.
به نظرم جالبه
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
تريگرها درSQL Server در ويژوال بيسيك6 :
تريگر نوع خاصي از روال ذخيره شده است و در هنگام تغيير داده اي كه براي حفاظت از آن طراحي شده است فعال مي گردد. تريگرها با جلوگيري از تغييرات غير معتبر يا ناسازگار در داده ها به حفظ يكپارچگي داده اي كمك مي كنند. فرض كنيد دو جدول customer و orders در اختيار داريد بنابراين مي توانيد تريگري ايجاد كنيد كه با ايجاد هر سفارش جديد، اعتبار شماره مشتري آن را كنترل كند. همچنين مي توانيد تريگري ديگري ايجاد كنيد كه در صورت حذف يك مشتري جدول orders را كنترل كرده و در صورت وجود سفارش براي آن مشتري فرآيند حذف مشتري را متوقف سازد.
تريگرها مي توانند قواعد كاري پيچيده تري را نسبت به قيود اعمال كنند. براي مثال يك تريگر insert مي تواند در هنگام درج ركورد جديد به سفارشات فعال شود و وضعيت پرداخت مشتري را بررسي و نوع پرداخت مناسب وي را تعيين كند.
تريگرها پارامتر ندارند و صريحا فعال نمي شوند و براي فعال سازي آنها تغييرات داده اي لازم است.
تريگرها را مي توان تا 32 سطح تودرتو تعريف كرد. اين تريگرها به شكل زير عمل مي كنند:
براي مثال تريگر جدول orders يك ورودي به جدول حسابهاي دريافتي اضافه مي كند و اين ورودي به نوبه خود تريگر ديگري را براي بررسي وضعيت مشتري فعال مي نمايد. يك تريگر به روز رساني جدول را انجام مي ده و همين امر تريگر ديگري را فعال مي كند.
بطور پيش فرض تمامي تريگرها (UPDATE,DELETE,INSERT)پس از تغييرات داده اي فعال مي شوند و به تريگر AFTER معروف مي باشند. در ويرايش هاي قبلي SQL Server تنها اين نوع تريگر موجود بوده است. در SQL Server 2000 نوع ديگري به نام INSTEAD OF معرفي شده است كه بجاي تغييرات داده اي موردنظر فعال مي شود.
از نقطه نظر كارائي، تريگرها سربار زيادي ندارند. بيشتر زمان اجراي يك تريگر براي ارجاع به ساير جدول بكار مي رود. اين ارجاع در صورت وجود جداول در حافظه سريع و در صورت نيار به خواندن از ديسك كمي كندتر خواهد بود.
تريگرها بخشي از يك تراكنش (transaction) محسوب مي شوند. اگر تريگر يا هر بخشي از تراكنش با شكست مواجه شود كل تراكنش عقبگرد مي شود.
درك جدول Deleted و Inserted
تريگرها از دو جدول inserted و deleted استفاده مي كنند. اين جداول ساختار مشابهي با جدول پايه يا جدول trigger كه تريگر در آن ايجاد مي شود دارند. اين دو جدول در حافظه RAMقرار مي گيرند و جداول منطقي هستند . اگر ركورد جديدي را به جدول پايه اضافه كنيد اين ركورد هم در جدول پايه و هم در جدول inserted ثبت مي شود. وجود مقادير در دسترس در جدول insertedبه شما امكان مي دهد كه نيازي به ايجاد متغير براي نگهداري اطلاعات نداشته باشيد و به اطلاعات دلخواه دسترسي بيابيد. هنگام حذف يك ركورد، ركورد حذف شده در جدول deleted قرار مي گيرد. به روز رساني نيز يك حذف و درج متوالي است. اگر ركوردي را به روز رساني كنيد، ركورد اصلي در جدول deleted و ركورد تغيير يافته در جدول پايه و جدول inserted ذخيره مي شود.
نكته : شما نمي توايند محتواي جداول inserted و Deleted را ببينيد.
اما براي اينكار مي توانيد با استفاده از تريگري محتواي اين جداول را ببينيد.كه در قسمتهاي بعدي شرح داده ميشود.
ايجاد تريگرها با دستور CREATE TRIGGER
نگارش ايجاد تريگرها به شرح زير است :
CREATE TRIGGER [owner.]trigger_name
ON [owner.]table_name | view_name
{FOR..AFTER | INSTEAD OF] {INSERT | UPDATE | DELETE}
[WITH ENCRYPTION]
AS sql.statements
يك جدول مي تواند هر تعداد تريگر از انواع DELETE, UPDATE ,INNSERT داشته باشد. هر عمل را مي توان در يك يا چند تريگر ذخيره كرد. اگر عملي در چند تريگر ذخيره شود بايد نام تريگرها منحصر بفرد و يكتا باشد. براي مثال مي توانيد تريگري به نام trInsupAuthors را بر روي جدول authors براي عمل حذف بر روي همين جدول ايجاد كنيد. براي تغيير تريگر كافيست از محيط enterprise روي جدول موردنظرراست كليك كرده گرينه ي Manage Trigger را بزنيد و از ليست كشويي تريگر موردنظر خود را انتخاب كرده و آنرا ويرايش نماييد. و از محيط كوئري آناليز هم توسط دستور ALTER TRIGGER تريگر را ويرايش كنيد يا ابتدا آنرا حذف نموده و دوباره ايجاد كنيد.
توجه : تغيير تريگر با دستور ALTER TRIGGER، سبب جايگزيني كامل تريگر قديم با تريگر جديد مي شود. با حذف يك جدول، تريگرها موجود آن نيز به شكل خودكار حذف مي شوند.
قوانين حاكم بر تريگرها:
· تريگر را نميتوان براي جداول موقت ايجاد كرد اما ميتواند به ديدها و يا جداول موقت ارجاع داشته باشد.
· تريگر مجموعه جواب (resultest) باز نميگرداند بنابراين هنگام استفاده از دستورات select احتياط كنيد. بكارگيري عبارت if exists به عنوان بخشي از دستور select در كد تريگر متداول است.
· تريگر براي حفظ يكپارچگي دادهاي، ارجاعي و كپسوله كردن قوانين كاري بكار ميرود.
· بكارگيري گزينه with encryption سبب ميشود تريگرها در جدول syscomments به شكل رمز شده نگهداري شوند.
· دستورات writetext تريگرها را فعال نميكنند. اين دستورات براي تغييرات دادهاي متني (text) و تصوير (image) بكار ميرود و در فايل گزارش تراكنشها ثبت نميشود.
· دستورات SQL زير را نميتوان در تريگرها بكار برد: همه انواع دستورات CREATE، همه دستورات DROP و دستورات ALTER TABLE, ALTER DATABASE ,TRUNCATE TABLE, GRANT, TRANSACTION, LOAD DATABASE, ROCONFIGURE REVOKE, STATISTICS, UPDATE STATISTICS , SELECT INFO, و كليه دستورات DISK
· دستورات عقبگرد شده تراكنشها در تريگرها مي تواند نتايج غير منتظرهاي را در برنامه ها ايجاد كند.
تريگرهاي Insert و UpdateوDelete
حال به يك نمونه تريگر براي دستورات INSERT و UPDATE جدول توجه كنيد:
CREATE TRIGGER trAddAuther
ON authors
FOR INSERT, UPDATE
AS raiserror (“%d rows have been modified”, 0,1, @@rowcount)
RETURN
CREATE TRIGGER trDelAuthors
ON authors
FOR DELETE AS
raiserror(“%d rows are going to be deleted from this table!”,0 , 1 , @@rowcount)
توجه كنيد كه پيام را در صورتي مشاهده مي كنيد كه عمل حذف را در محيط كوئري آناليز انجام دهيد.
تريگري براي ديدن محتواي جداولinserted و Deleted
CREATE TRIGGER tr24 ON Teacher
FOR DELETE ,update,insert
AS
select * into del from deleted
select * into insl from inserted
نام تريگر بالا tr24 است. كه بر روي جدول teacher ساخته شده است. خط دوم يعني وقتي عمليات اضافه يا حذف يا ويرايش بر روي جدول teacher اتفاق افتاد اين تريگر فراخواني شود..خط چهارم ركوردهاي موجود در جدول Deleted را در جدول del مي ريزد و خط پنج هم محتواي جدولinserted را در جدولins مي ريزد.
توجه كنيد كه جدولهايinsو del نبايد وجود داشته باشند وگرنه پيام خطا ميدهد.
اعمال يكپارچگي دادهاي با تريگرها
تريگرها براي اعمال يكپارچگي دادهاي در پايگاه داده بكار ميروند. در گذشته يكپارچگي ارجاعي صرفا از طريق تريگرها تامين ميشد. در ويرايشهاي اخير SQL Server اينكار را ميتوان با قيد يكپارچگي ارجاعي انجام داد اما تريگرها كماكان براي كپسوله كردن قواعد كاري و تغييرات پلهاي پايگاه داده مفيدند. يك تغيير پلهاي ميتواند با تريگر ايجاد شود. فرض كنيد يك فروشگاه ديگر فعاليت نميكند. شما ميتوانيد تريگري ايجاد كنيد كه ابتدا اين فروشگاه را از جدول stores حذف كند و سپس كليه فروشهاي مربوط به آن را از جدول sales حذف نمايد
اعمال يكپارچگي ارجاعي
تريگرها براي اعمال يكپارچگي ارجاعي نيز بكار ميروند. اين كار هدف اصلي آنها در پايگاه داده است. بخصوص براي حذفها و به روز رساني پلهاي مفيدند. تريگرها در پايان تغييرات دادهاي كنترل ميشوند در حاليكه قيود در ابتدا كنترل ميشوند. اگر قيدي نقض شود. هيچ تريگري فعال نميشود. تريگر زير يكپارچگي دادهاي را اعمال ميكند. از طريق اين تريگر مطمئن ميشويم كه در صورت درج يك ركورد جديد در جدول Sales حتما كد فروشگاه معتبر آن در جدول stores وجود دارد.
CRETAE TRIGGER trInsUpdSales
On tblSales
FOR INSERT, UPDATE AS
IF(SELECT COINT(*) FROM tblStores , inserted
WHERE tblStores.stor_id = inserted.stor_id) =0
BEGIN
PRINT ‘The stor_id you have entered does not exist’
PRINT ‘in the stores table’
ROLLBACK TRANSACTION
END
اين تريگر براي هر دستور مجزاي INSERT يا UPDATE بر روي جدول tblSales بخوبي كار ميكند. اما اگر دستور SELECT INTO را اجرا كنيد، تريگر ممكن است كاملا درست فعال نشود. وقتي با چندين سطر سروكار داريد بايد مطمئن شويد تعداد سطرهاي درج شده stor_id با تعداد فروشهايي كه اضافه كردهايد برابر باشد. حال تريگر را به شكل زير تغيير ميدهيم:
DROP TRIGGER trInsUpdSales
GO
CRETAE TRIGGER trInsUpdSales
On tblSales
FOR INSERT, UPDATE AS
DECLARE @rc int
SELECT @rc = @@rowcount
IF(SELECT COINT(*) FROM tblStores , inserted
WHERE tblStores.stor_id = inserted.stor_id) =0
BEGIN
PRINT ‘The stor_id you have entered does not exist’
PRINT ‘in the stores table’
ROLLBACK TRANSACTION
END
IF(SELECT COINT(*) FROM tblStores , inserted
WHERE tblStores.stor_id = inserted.stor_id) <>@rc
BEGIN
PRINT ‘Not all sales have a valid stor_id’
PRINT ‘in the stores table’
ROLLBACK t TRANSACTION
END
بكار گيري تريگرهاي INSTEAD OF
هنگام استفاده از تريگرهاي INSTEAD OF كد اصلي ايجاد تغييرات در جدول اجرا نمي شود بلكه كد تريگر اجرا ميشود. براي مثال شما ميتوانيد تريگري را براي جدول authors ايجاد كنيد كه به كاربران اطلاع دهد مولفين را نميتوان حذف كرد. اين كار با تريگر معمول FOR،AFTER نيز قابل انجام است. اما مستلزم آن است كه تغييرات واقعي در ابتدا اعمال شوند سپس در كد تريگر عقبگرد شوند. اگر كد تريگر INSTEAD OF را بكار بريد، عمل به روز رساني انجام نميشود و طبيعي است اين تريگر كاراتر است. به مثال زير توجه كنيد.
USE pubs
GO
CREATE TRIGGER trlO_DelAuthors
ON authors INSTEAD OF DELETE AS
PRINT ‘you can not delete authors from the authors table!’
براي تست تريگر سعي كند مولفي با نام خانوادگي white را حذف كنيد:
USE pubes
GO
DELETE authors WHERE au_lname = ‘white’
جمع آوري اطلاعات تريگرها
با اجراي روال ذخيره شده sp_helptext ميتوانيد متن دستور تريگر را مشاهده كنيد. البته تريگرهاي رمز شده ركوردي در جدول Syscomments ندارند. در حالت كلي نبايد هيچ شيئي را رمزنگاري كنيد. مگر آنكه واقعا مجبور باشيد. هنگام ارتقا پايگاه داده كليه اشياء رمزنگاري شده بايد حذف و مجددا ايجاد شوند. اما اشياء رمزنشده بطور خودكار به ويرايش جديد ارتقاء داده ميشوند.
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
تشخیص ادمین بودن کاربر جاری در ویندوز
اگه زمانی خواستید این موضوع رو بفهمید کافیه که از تابع API ی که در shell32 تعریف شده استفاده کنید. صورت کلی این تابع چنین است:
Private Declare Function IsUserAnAdmin Lib "shell32" () As Long
تحت ویندوز 2000 ممکنه که شما خطای با عنوان Can't find DLL entry point دریافت کنید که بهتر است که معرفی تابع را بدین گونه انجام دهید:
Private Declare Function IsUserAnAdmin Lib "shell32" Alias "#680" () As Long
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
فیلتر کردن بعضی از کلید های صفحه کلید :
Private Sub Form_KeyPress(KeyAscii As Integer)
Dim svalid As String
svalid = "0123456789"
If InStr(svalid, Chr(KeyAscii)) = 0 Then
KeyAscii = 0
MsgBox "Not valid Keys.please Press 0-9 keys"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
MsgBox "The form cannot be close.farzad dh."
Dim leftI As Long
Dim rightI As Long
leftI = Form1.Left + 1000
rightI = Form1.Top + 1000
Dim a As New Form1
a.Width = Me.Width
a.Height = Me.Height
a.Left = leftI
a.Top = rightI
a.Show
End Sub
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
ساختن جدول در بانک اطلاعاتی :
از منوی project گزینه refrences رو انتخاب کنید - بعد اونجا گزینه Microsoft ActiveX Data Objects 2.0 library پيدا کنيدو تيک بزنيد - Adodc مورد نظرتون رو هم با دیتابیس set کنید - بعد :
Dim db_file As String
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim NumRec As Integer
Set conn = New ADODB.Connection
conn.ConnectionString = Adodc1.ConnectionString
conn.Open
On Error Resume Next
conn.Execute "DROP TABLE Jadid"
On Error GoTo 0
conn.Execute "CREATE TABLE Jadid(" & "One INTEGER NOT NULL," & "Two VARCHAR(40) NOT NULL," & "Three VARCHAR(40) NOT NULL)"
conn.Execute "INSERT INTO Jadid VALUES (1,'4','7')"
conn.Execute "INSERT INTO Jadid VALUES (2,'5','8')"
conn.Execute "INSERT INTO Jadid VALUES (3,'6','9')"
Set rs = conn.Execute("SELECT COUNT (*) FROM Jadid")
NumRec = rs.Fields(0)
conn.Close
MsgBox "Created ... "
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
نحوه تولید DLL با ویژوال بیسیک
بعنوان یک زبان برنامهنویسی با توسعه سریع، ویژوال بیسیک نظر خیلی از برنامهنویسان را از جهت سادگی به خود معطوف کرد. برنامهنویسی با ویژوال بیسیک در کمترین زمان صورت میگیرد حال آنکه در مقابل زبانهایی چون C و ++C اغلب اوقات به روزها کار مفید نیاز است.
اما بیشترین انتقادی که برنامهنویسان از ویژوال بیسیک دارند در این است که قادر به تولید کتابخانههای پویا (DLL) نیست. حقیقتا این نظر مورد قبول است که نمیتوان این نوع فایلها را در کنار فایلهای اجرایی(Exe) یا ActiveX Exe تولید کرد.
در این مقاله ما قصد داریم که نگاه دقیقی به نحوه تولید فایلهای اجرایی در ویژوال بیسیک یندازیم و بعد با طی مراحل سادهای موفق به ایجاد فایلهای DLL بشویم تا از زیر بار این انتقاد نیز رهایی یابیم.
قبلا به این موضوع اشاره شد که فایهای DLL آن دست از برنامههایی هستند که یکبار نوشته میشوند و در پروژههای بعدی بکرات میتواند از آنها استفاده برد. چیزی که هسته ویندور را تشکیل میدهد اینگونه فایلها هستند. علاوه بر آن تکنیکهایی وجود دارد که شما را قادر میسازد تا برنامههایی بنویسید که قادرند خود را بروز برسانند و یا خود ترمیم باشند. بهتر از آن اینکه برنامهای بنویسید که با الحاق اینگونه فایلها بدان قدرت و امکانات جدید بدان افزود. همانند نرمافزارهای رایج از جمله Winamp.
کتابخانههای پویای قابل اتصال (DLL) چه هستند؟
یک DLL مجموعهای از توابع و پروسههایی است که میتواند از برنامه یا DLLهای نظیر خود فراخوانده شود.
استفاده از اینگونه کتابخانههای دو مزیت اصلی دارد:
1- امکان به اشتراک گذاری از کد را فراهم میسازند. یک DLL میتواند مورد استفاده خیلی از برنامههای قرار گیرد. بعنوان مثال کتابخانه Win32 API نمونهای از این سری فایلها است. بعلاوه از زمانی که پروسههای گوناگون قادر به فراخوانی یک DLL واحد هستند امکان به اشتراک گذاری کدها و روتینها فراهم آمده است. یک فایل DLL تنها یکبار به درون حافظه لود میشود و بارها توسط پروسههای گوناگونی مورد استفاده قرار میگیرد و این یعنی مدیریت حافظه بهتر.
2- مزیت دیگر امکان نوشتن برنامهها بصورت اجزای منفصل است که این اجزا خود قابل تعویض با نگارشهای جدیدتر جهت توسعه نرمافزار خواهند بود بدون اینکه خطی از کد برنامه اصلی دگرگون شود.
با این توصیف فایلهای کتابخانهای درونی که در پروژههای مورد استفاده قرار میگیرد در صورت تغییر نیاز هست تا پروژه اصلی دوباره کمپایل شود تا بتوان با آن ارتباط بر قرار کرد. اما در DLL ها چون بصورت پویا و قابل انعطاف نوشته شدهاند این اتصال در بیرون از بدنه اصلی و درست در زمان فراخوانی آن قبیل از متدها و توابع شکل میگیرد و این خود تفاوت آشکار از مزیت این گونه از فایلها میباشد.همچنین یک فایل DLL میتواند حاوی توابعی باشد که فقط مورد استفاده خود هست و از درون به آن دسترسی نخواهیم داشت و آندسته از تابعی را که نیاز هست معرفی میکنیم تا از بیرون بدان دسترسی داشته باشیم. در این مرحله نیاز به معرفی در فایلهای Def هست که در پروژههای C و C++ مورد استفاده قرار میگیرد.
و اما ساختار DLL
فایلهای DLL حاوی یک مدخل شروع انتخابی (optional entry point) و پایانی هستند که در زمانی که توسط برنامههای دیگر به درون حافظه لود یا آنلود میشوند قابل اجرا است. ویندوز این پروسه را در زمانی که یک برنامه DLLها را بدرون حافظه لود یا آنلود میکند اجرا میکند.
این دو نوع پروسه به DLL این امکان را میدهد که یک سری از مقدمات را پیش از استفاده مهیا کند یا بعد از استفاده پاکسازی نماید. در ویژال بیسیک این تابع بدین گونه تعریف میشود:
Public Function DllMain(hinstDLL As Long, fdwReason As Long , lpwReserved As Long) As Boolean
که پارامترهای آن بدین قرارند:
hInstDLL که حاوی یک مقدار یکتا بعنوان دستگیره فایل DLL است.
fdwReason مشخص کننده دلیل فراخوانی این پروسه توسط سیستمعامل است که یکی از چهار مقدار زیر را به خود منتصب میکند:
DLL_PROCESS_ATTACH (1): یک پروسه در حال لود DLL به دورن حافظه است. هر پیشنیاز باید در اینجا شکل گیرد.
DLL_THREAD_ATTACH (2): یک ریسمان (Thread) برای این DLL در حال تولید است. هر پیشنیاز برای ایجاد ریسمان در این مرحله میتواند شکل بگیرد.
DLL_THREAD_DETACH (3) ریسمان در حال پایان یافتن است. به منظور پاکسازی DLL از حافظه.
DLL_PROCESS_DETACH (0) فایل DLL در حال خروح از حافظه است. بمنظور پاکسازی سایر کارها توسط برنامهنویس امکان انجام در این مرحله فراهم آمده است.
lpvReserved: حاوی مقدار اضافی در استفاده از DLL_PROCESS_ATTACH یا DLL_PROCESS_DETACH میباشد.
مقدار برگشتی تابع DllMain در هنگام صدا زدن بصورت DLL_PROCESS_ATTACH مقدار TRUE را باید به خود بگیرد.
در تلاش برای تولید و توسعه یک DLL نمونه قصد این را داریم که یک کتابخانه ریاضی تشکیل دهیم. کد زیر در ماژولی بنام MathLib.Bas قرار میگیرد:
Option Explicit
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Function DllMain(hInst As Long, fdwReason As Long, lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
End Function
Public Function Increment(var As Integer) As Integer
If Not IsNumeric(var) Then Err.Raise 5
Increment = var + 1
End Function
Public Function Decrement(var As Integer) As Integer
If Not IsNumeric(var) Then Err.Raise 5
Decrement = var - 1
End Function
Public Function Square(var As Long) As Long
If Not IsNumeric(var) Then Err.Raise 5
Square = var ^ 2
End Function
به درخواست یکی از دوستان انجمن
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
به نظر شما از چه دستوری استفاده کنیم که يک کلمه را توی يک فيلد بانک اطلاعاتي جستجو کنم نه اينکه اون کلمه اول نوشته باشه . اين کلمه ممکنه وسط هم نوشته شده باشه :
برای کاری که می خوای انجام بدی باید از دستورات SQL استفاده کنی.
اگر از کامپونت ADO استفاده می کنی دستور جستجوش به این شرحه :
Ado1.RecordSource= "Select * From [your table] Where [your field] Like ('%متن مورد نظر برای جستجو%')"
ولی اگر از کامپونت Data استفاده می کنی دستورش اینطوری می شه :
Data1.RecordSource= "Select * From [your table] Where [your field] Like ('*متن مورد نظر برای جستجو*')"
مثال : مثلا من یک Table با نام Table1 و یک فیلد به نام Address دارم و می خوام تمام آدرسهایی که توشون ( شیراز) داره پیدا کنم ، حالا این کلمه می خواد هرجایی از فیلد باشه :
Ado1.CommandType = adCmdText
Ado1.RecordSource= "Select * From Table1 Where Address Like ('%شیراز%')"
Ado1.Refresh
این آموزش واقعاً کاربردیه
-
نقل قول: آموزش ویژوال بیسیک پیشرفته
چیزی که از دستم بر میومد. امیدوارم خوشتون اومده باشه.
موفق باشید.
-
نقل قول: یه سری آموزش های فوق العاده جالب برای دوستان عزیز
سلام خسته نباشین
وافعا مطالبتون مفیده.ففط اگه میشه یکم توضیح بدین
میشه یکم دیگه راجب شماره گیری با مودم بگین
ممنون