1. مهمان گرامی، جهت ارسال پست، دانلود و سایر امکانات ویژه کاربران عضو، ثبت نام کنید.
    بستن اطلاعیه

یه سری آموزش های فوق العاده جالب برای دوستان عزیز

شروع موضوع توسط hector2141 ‏10/9/12 در انجمن Visual Basic

  1. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    موضوع : ايجاد صدای سه بعدی توسط DirectSound3D



    تاکنون با چگونگي پخش افکتهاي صوتي و موسيقي پس زمينه توسط DirectXAudiuo آشنا شديد . اين مطالب براي کاربردهاي ساده مناسبند اما اينکه فقط ما صداي استريو داشته باشيم کافي نيست و در کاربردهاب حرفه اي بايستي از صداهاي کاملاً سه بعدي استفاده کنيم .
    با استفاده از افکتهاي صوتي سه بعدي مي توانيم صدا را در تمام جهتها براي کاربر شبيه سازي کنيم اما با همه مزاياي صداي سه بعدي ، دو اشکال براي آن وجود دارد : اول اينکه پخش صداي سه بعدي پيچيده تر از پخش صداي عادي است و تنها کارت هاي سخت افزاري جديد بطور کاملاً واقعي از آن پشتيباني مي کنند و دوم اينکه صداي سه بعدي با 4 بلندگو يا بيشتر حاصل مي شود – کيفيت حالت 2 بلندگو بد نيست اما در مقايسه با حالت 4 بلندگو ، بسيار کيفيت صداي سه بعدي پايين است .

    برپاسازي DirectSound3D

    برپاسازي صداي سه بعدي چندان پيچيده نيست اما هر بافر صوتي که براي يک صداي سه بعدي مي سازيد ، يک overhead را به سيستم تان اضافه مي کند . همچنين برخي درايورها هستند که تنها اجازه ايجاد تعداد محدودي بافر سه بعدي را در يک لحظه مي دهند و نيز اغلب درايورها تعداد بافرهاي سه بعدي که مي توان در يک لحظه پخش کرد را محدود مي کنند ( معمولاً 8 تا 16 بافر ) .
    اولين قدم در استفاده از صداي سه بعدي تعريف متغيرها و اشيا زير است :

    Dim DSBuffer As DirectSoundSecondaryBuffer8
    Dim DSBuffer3D As DirectSound3DBuffer8
    Dim DSBListener As DirectSound3DListener8

    تنها دو شي آخر براي شما جديد هستند . شي DirectSound3dBuffer8 يک ارائه سه بعدي از بافرهاي عادي است . ما همچنان از DirectSoundSecondaryBuffer8 براي نگهداري داده صوتي استفاده مي کنيم و از DirectSound3Dbuffer8 براي نگهداري پارامترهاي سه بعدي و تنظيمات سه بعدي استفاده مي کنيم . شي DirectSound3Dlistener8 نيز يک listener است و براي تنظيم کردن سرعت و جهت صدا و برخي پارامترهاي ديگر استفاده مي شود .
    مرحله دوم ، ساخت بافر صوتي است . اين کار در دو بخش انجام مي شود . اول ما يک بافر صوتي نرمال مي سازيم و سپس يک واسط بافر صوتي سه بعدي را از آن بدست مي آوريم :

    If Not (DSBuffer Is Nothing) Then DSBuffer.Stop
    Set DSBuffer = Nothing
    DSBDesc.lFlags = DSBCAPS_CTRL3D Or DSBCAPS_CTRLVOLUME
    Set DSBuffer = DS.CreateSoundBufferFromFile(App.Path & "\blip.wav", DSBDesc)x
    If DSBDesc.fxFormat.nChannels > 1 Then
    MsgBox "You can only use mono (1 channel) sounds with DirectSound3D"x
    End If
    If optLow.Value Then DSBDesc.guid3DAlgorithm = GUID_DS3DALG_NO_VIRTUALIZATION
    If optMedium.Value Then DSBDesc.guid3DAlgorithm = GUID_DS3DALG_HRTF_LIGHT
    If optHigh.Value Then DSBDesc.guid3DAlgorithm = GUID_DS3DALG_HRTF_FULL
    Set DSBuffer = DS.CreateSoundBufferFromFile(App.Path & "\blip.wav", DSBDesc)x
    Set DSBuffer3D = DSBuffer.GetDirectSound3DBuffer()x

    سه نکته است که بايد به آن دقت شود :
    1 – اضافه کردن DSBCAPS_CTRL3D بسيار مهم است . شما اگر اين پارامتر را بکار نبريد ، قادر نخواهيد بود که واسط سه بعدي را بدست آوريد .
    2 – ما بايستي تنها از افکتهاي صوتي Mono ( تک کاناله ) استفاده کنيم زيرا افکت صوتي استريو در صداي سه بعدي معنا ندارد زيرا صدا از يک نقطه در فضاي سه بعدي مي آيد .
    3 – سطح الگوريتم سه بعدي – که در پارامتر DSBDesc.guid3Dalgorhthm آمده . حالت NO VIRTULIZATION تنها از CPU استفاده مي کند و روي تمام سيستم ها کار مي کند اما افکتها مينيمم هستند . حالت HRTF LIGHT هم از CPU و هم سخت افزار کارت صوتي استفاده مي کند و کيفيت بهتري را نسبت به خالت اول ارائه مي دهد . حالت HRTF FULL بهترين حالت است اما در صورتي درست کار مي کند که يک سخت افزار سه بعدي داشته باشيد .
    آخرين پارامتري که بايد تنظيم کنيم شي listener است :

    DSBDesc_2.lFlags = DSBCAPS_CTRL3D Or DSBCAPS_PRIMARYBUFFER
    Set DSBPrimary = DS.CreatePrimarySoundBuffer(DSBDesc_2) x
    Set DSBListener = DSBPrimary.GetDirectSound3Dlistener
    DSBListener.SetOrientation 0#, 0#, 1#, 0#, 1#, 0#, DS3D_IMMEDIATE

    تا اينجا صداي سه بعدي ما آماده است و مي توانيم برخي پخش بافر را مشابه درسهاي قبلي شروع کنيد .
    پارامترهاي اختياري :

    چند پارامتر وجود دارد که مي توان آنها را تغيير داد :
    1 – Volume : عدد 0 بيشترين ميزان صدا و عدد 3000 - کمترين ميزان صدا را دارد :

    If DSBuffer Is Nothing Then Exit Sub
    DSBuffer.SetVolume scrlVolume.Value

    2 – Position : تنظيم محل listener :

    DSBuffer3D.SetPosition Src_X, 0, Src_Y, DS3D_IMMEDIATE
    DSBListener.SetPosition Src_X, 0, Src_Y, DS3D_IMMEDIATE

    3 – Velocity : تنظيم سرعت و جهت منبع صدا :

    DSBuffer3D.SetVelocity X, Y, Z, DS3D_IMMEDIATE
    DSBListener.SetVelocity X, Y, Z, DS3D_IMMEDIATE

    4 – Dppler Effect : انحراف صدا از مسيري که مي پيمايد انحراف سرعت حرکت صدا :

    DSBListener.SetDopplerFactor CSng(scrlDoppler.Value), DS3D_IMMEDIATE

    5 – Rolloff Effect : rolloff چگونگي تضعيف صدا با تغيير فاصله است .

    DSBListener.SetRolloffFactor CSng(scrlRolloff.Value), DS3D_IMMEDIATE

    6 – Distance : ماکزيمم فاصله اي که يک صدا مي تواند شنيده شود :

    DSBuffer3D.SetMaxDistance 250, DS3D_IMMEDIATE
    DSBuffer3D.SetMinDistance 0.01, DS3D_IMMEDIATE

     
  2. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    رجيستري چيست ؟
    سيستم عامل ويندوز تنظيمات سخت افزاري و نرم افزاري خود را بطور مرکزي در يک بانک اطلاعاتي با ساختار سلسله مراتبي ذخيره مي کند که رجيستري نام دارد . رجيستري جايگزيني براي بسياري از فايلهاي پيکربندي INI ، SYS و COM است که در نسخه هاي اوليه ويندوز موجود بود . رجيستري ، سيستم عامل را با مهيا کردن اطلاعات موردنيز براي اجراي برنامه ها و load شدن component ها ، کنترل مي کند .
    رجيستري شامل انواع مختلفي از اطلاعات مي باشد مثل :
    - اطلاعات سخت افزارهاي نصب شده روي سيستم
    - اطلاعات درايورهاي نصب شده روي سيستم
    - اطلاعات برنامه هاي نصب شده روي سيستم
    - اطلاعات پروتکلهاي شبکه اي مورد استفاده در سيستم
    ساختار رجيستري شامل چندين مجموعه رکورد است که داده هاي اين رکوردها توسط بسياري از برنامه ها و اجزاي سيستم عامل خوانده و يا نوشته مي شود .
    اجزاي رجيستري
    اجزاي تشکيل دهنده رجيستري عبارتند از :
    1 – subtree : Subtree ها همانند folder هاي موجود در ريشه يک درايو هارد هستند . رجستری ويندوز داراي پنج subtree مي باشد :
    - HKEY_LOCAL_MACHINE : شامل تمام داده هاي پيکربندي براي کامپيوتر مي باشد و شامل 5 key است :Hardware ، SAM ، Security ، Software و System
    - HKEY_USERS : شامل داده هاي مربوط به تنظيمات سيستم عامل براي هر user است مثل تنظيمات desktop و محيط ويندوز
    - HKEY_CURRENT_USER : شامل داده هاي کاربر فعلي سيستم
    - HKEY_CLASSES_ROOT : شامل اطلاعات پيکربندي نرم افزار است مثل داده هاي OLE و داده هاي کلاسهاي متناظر با فايل
    - HKEY_CURRENT_CONFIG : شامل اطلاعات مورد نياز براي تنظيمات داريورهاي سخت افزاري و غيره
    2 – Key : key ها همانند folder ها و subfolder هاي روي هارد هستند . هر key متناظر با object هاي نرم افزاري يا سخت افزاري مي باشد . subkey ها key هايي هستند که درون يکسري key قراردارند .
    3 – Entry : هر key داراي يک يا چند entry است . هر entry داراي سه بخش مي باشد :
    - نام Name
    - نوع داده اي Data Type : مقدار هر entry يکي از انواع داده هاي زير است :
    REG_DWORD ، REG_SZ ، REG_EXPAND_SZ ، REG_BINARY ،
    REG_MULTI_SZ ، REG_FULL_RESOURCE_DESCRIPTOT
    - مقدار Value
    نکته 1 : براي مشاهده رجيستري و اعمال تغييرات در آن ( لطفاً اگر هيچ تجربه اي در تنظيم کردن رجيستري نداريد اطلاعات آنرا تغيير ندهيد ) ، مي توانيد از برنامه regedit.exe و يا regedt32.exe موجود در ويندوز استفاده کنيد . براي اينکار کافيست نام برنامه را در کادر Run وارد کنيد .
    ---------------------

    براي کار با رجيستري در ويژوال بيسيک کلاس Registery.bas را مطابق مطالب زير ايجاد کرده و در پروژه هاي خود از آن استفاده کنيد :

    1 - تعريف ثابتهاي مورد نياز : براي نوشتن اين کلاس نياز به تعريف چهار دسته ثابت داريم :

    - ثابتهاي مربوط به تعريف data type هاي entry هاي رجيستري :
    Global Const REG_SZ As Long = 1
    Global Const REG_DWORD As Long = 4

    - ثابتهاي مربوط به تعريف key هاي رجيستري
    Global Const HKEY_CLASSES_ROOT = &H80000000
    Global Const HKEY_CURRENT_USER = &H80000001
    Global Const HKEY_LOCAL_MACHINE = &H80000002
    Global Const HKEY_USERS = &H80000003

    - ثابتهاي مربوط به خطاهاي کار با رجيستري
    Global Const ERROR_NONE = 0
    Global Const ERROR_BADDB = 1
    Global Const ERROR_BADKEY = 2
    Global Const ERROR_CANTOPEN = 3
    Global Const ERROR_CANTREAD = 4
    Global Const ERROR_CANTWRITE = 5
    Global Const ERROR_OUTOFMEMORY = 6
    Global Const ERROR_INVALID_PARAMETER = 7
    Global Const ERROR_ACCESS_DENIED = 8
    Global Const ERROR_INVALID_PARAMETERS = 87
    Global Const ERROR_NO_MORE_ITEMS = 259

    - ثابتهاي متفرقه
    Global Const KEY_ALL_ACCESS = &H3F
    Global Const REG_OPTION_NON_VOLATILE = 0

    2 - Declare کردن Api هاي مورد نياز : براي کار با رجيستري از توابع کتابخانه Advapi32.dll استفاده مي کنيم . اين توابع عبارتند از :

    - تابع RegCloseKey : آزاد کردن handle مربوط به يک key
    Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long

    - تابع RegCreateKeyEx : ساخت يک key در رجيستري ( اگر key قبلاً وجود داشته باشد ، اين تابع آنرا باز مي کند ) :
    Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDisposition As Long) As Long

    - تابع RegOpenKeyEx : باز کردن يک key
    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

    - تابع RegQueryValueExLong : استخراج type و data ي يک نام متناظر با يک key باز شده
    Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long

    Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Long, lpcbData As Long) As Long

    Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long

    - تابع RegSetValueEx : ذخيره يک مقدار در فيلد value يک کليد باز
    Declare Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As String, ByVal cbData As Long) As Long

    Declare Function RegSetValueExLong Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, ByVal cbData As Long) As Long

    - تابع RegDeleteKey : پاک کردن يک کليد و کليه اطلاعات مرتبط با آن
    Private Declare Function RegDeleteKey& Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String)

    - تابع RegDeleteValue : حذف مقدار يک key
    Private Declare Function RegDeleteValue& Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String)

    3 - توابع کمکي : براي نوشتن توابع اصلي کار با رجيستري نياز به نوشتن توابع کمکي زير است :

    - تابع SetValueEx : با توجه به نوع داده يک کليد ، مقدار موجود در آنرا در يک متغير ذخيره مي کند :
    Public Function SetValueEx(ByVal hKey As Long, sValueName As String, lType As Long, vValue As Variant) As Long
    Dim lValue As Long
    Dim sValue As String
    Select Case lType
    Case REG_SZ ' type of value is string
    sValue = vValue
    SetValueEx = RegSetValueExString(hKey, sValueName, 0&, lType, sValue, Len(sValue))x
    Case REG_DWORD ' type of value is Double word
    lValue = vValue
    SetValueEx = RegSetValueExLong(hKey, sValueName, 0&, lType, lValue, 4)x
    End Select
    End Function

    - تابع QueryValueEx : سايز و نوع داده اي يک داده را که بايد خوانده شود مشخص مي کند .
    Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
    Dim cch As Long
    Dim lrc As Long
    Dim lType As Long
    Dim lValue As Long
    Dim sValue As String
    lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch)x
    Select Case lType
    ' For strings
    Case REG_SZ:
    sValue = String(cch, 0)x
    lrc = RegQueryValueExString(lhKey, szValueName, 0&, lType, sValue, cch)x
    If lrc = ERROR_NONE Then
    vValue = Left$(sValue, cch)x
    Else
    vValue = Empty
    End If
    ' For DWORDS
    Case REG_DWORD:
    lrc = RegQueryValueExLong(lhKey, szValueName, 0&, lType, lValue, cch)x
    If lrc = ERROR_NONE Then vValue = lValue
    Case Else
    'all other data types not supported
    lrc = -1
    End Select
    QueryValueExExit:
    QueryValueEx = lrc
    Exit Function
    QueryValueExError:
    Resume QueryValueExExit
    End Function

    4 - توابع اصلي : توابع مربوط به پاک کردن يک کليد از رجيستري ، ساخت يک کليد جديد در رجيستري و مقداردهي به يک کليد :

    - تابع DeleteKey : اين تابع يک کليد از رجيستري را حذف مي کند . داراي دو پارامتر ورودي است :
    Location که يکي از مقادير HKEY_CLASSES_ROOT ، HKEY_CURRENT_USER
    ، HKEY_LOCAL_MACHINE و يا HKEY_USERS است .
    KeyName که نام کليدي است که بايد از رجيستري حذف شود . اين کليد ممکنست شامل subkey هايي نيز باشد مثلاً Key1\SubKey1
    Public Function DeleteKey(lPredefinedKey As Long, sKeyName As String)x
    Dim lRetVal As Long
    lRetVal = RegDeleteKey(lPredefinedKey, sKeyName)x
    DeleteKey = lRetVal ' return function value
    End Function

    - تابع DeleteValue : اين تابع يک entry را از کليد حذف مي کند . داراي سه پارامتر ورودي است : Location ، KeyName و ValueName که نام آن value را مشخص مي کند .
    Public Function DeleteValue(lPredefinedKey As Long, sKeyName As String, sValueName As String)x
    Dim lRetVal As Long
    Dim hKey As Long
    lRetVal = RegOpenKeyEx(lPredefinedKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)x
    lRetVal = RegDeleteValue(hKey, sValueName)x
    RegCloseKey (hKey)x
    DeleteValue = lRetVal
    End Function

    - تابع CreateNewKey : اين تابع يک کليد جديد ايجاد مي کند . داراي دو پارامتر ورودي است : Location و KeyName
    Public Function CreateNewKey(lPredefinedKey As Long, sNewKeyName As String)x
    Dim hNewKey As Long
    Dim lRetVal As Long
    lRetVal = RegCreateKeyEx(lPredefinedKey, sNewKeyName, 0&, vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0&, hNewKey, lRetVal)x
    RegCloseKey (hNewKey)x
    CreateNewKey = lRetVal
    End Function

    - تابع SetKeyValue : اين تابع پارامتر data يک entry را تنظيم مي کند . داراي 5 پارامتر ورودي است : Location ، KeyName ، ValueName ، ValueSetting و ValueType
    Public Function SetKeyValue(lPredefinedKey As Long, sKeyName As String, sValueName As String, vValueSetting As Variant, lValueType As Long)x
    Dim lRetVal As Long
    Dim hKey As Long
    lRetVal = RegOpenKeyEx(lPredefinedKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)x
    lRetVal = SetValueEx(hKey, sValueName, lValueType, vValueSetting)x
    RegCloseKey (hKey)x
    SetKeyValue = lRetVal
    End Function

    - تابع QueryValue : اين تابع فيلد داده يک entry را برمي گرداند . داراي سه پارامتر ورودي است : Location ، KeyName و ValueName
    Public Function QueryValue(lPredefinedKey As Long, sKeyName As String, sValueName As String)x
    Dim lRetVal As Long
    Dim hKey As Long
    Dim vValue As Variant
    lRetVal = RegOpenKeyEx(lPredefinedKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)x
    lRetVal = QueryValueEx(hKey, sValueName, vValue)x
    QueryValue = vValue
    RegCloseKey (hKey)x
    End Function

    --------------------------
    ساخت يک انتصاب فايل يا File Association به يک برنامه

    در اين درس می خواهم با استفاده از کلاسی که در درس قبل معرفی شد تابعی بسازيم که توسط آن بتوانيم فايلهای با پسوندی مشخص را به يک برنامه اختصاص دهيم . بعبارت ديگر تابعی بنويسيم که اطلاعات لازم برای باز شدن فايلهايی با پسوند xxx را توسط برنامه MyApp.exe در رجيستری ثبت کند .

    Public Sub CreateAssociation(sExtension As String, sApplication As String, sAppPath As String)x
    Dim sPath, sAppExe As String
    CreateNewKey "." & sExtension, HKEY_CLASSES_ROOT
    SetKeyValue HKEY_CLASSES_ROOT, "." & sExtension, "", sApplication & ".Document", REG_SZ
    CreateNewKey sApplication & ".Document\shell\open\command", HKEY_CLASSES_ROOT
    SetKeyValue HKEY_CLASSES_ROOT, sApplication & ".Document", "", sApplication & " Document", REG_SZ
    sPath = sAppPath & " %1"x
    sAppExe = sApplication & ".exe"x
    SetKeyValue HKEY_CLASSES_ROOT, sApplication& ".Document\shell\open\command", "", sPath, REG_SZ
    CreateNewKey "Software\Microsoft\Windows\CurrentVersion\Explore r\FileExts\." & sExtension, HKEY_CURRENT_USER
    SetKeyValue HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explore r\FileExts\." & sExtension, "Application", sAppExe, REG_SZ
    CreateNewKey "Applications\" & sAppExe & "\shell\open\command", HKEY_CLASSES_ROOT
    SetKeyValue HKEY_CLASSES_ROOT, "Applications\" & sAppExe & "\shell\open\command", "", sPath, REG_SZ
    End Sub

    کاربرد اين تابع بصورت زير است :
    CreateAssociation("xxx","MyApp","c:\MyApp.exe")x

    اجرا شدن يک برنامه در هنگام راه اندازی سيستم

    فرض کنيد می خواهيم برنامه ای بنويسيم که هر بار در هنگام راه اندازي سيستم بطور خودكار اجرا شود. البته نمي خواهم در startup ويندوز ديده شود .
    براي اين كار بايد برنامه موردنظر را در StartUp رجيستري قرار دهيم . به اين ترتيب كه در يكي از كليدهاي زير يك مقدار رشته اي جديد(String Value) ايجاد کنيم و آدرس برنامه را در آن وارد كنيم :
    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Curre ntVersion\Run
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Curr entVersion\Run

    براي مثال اگه اسم برنامه مورد نظر MyApp و مسيرش C:\Windows\MyApp.exe است بايد بصورت زير عمل کرد :
    SetKeyValue HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run ", "MyApp", "C:\MyApp.exe", REG_SZ


    نکته : البته دو تا راه ديگر برای اينکار وجود دارد که برخی تروجان ها هم از اين روشها استفاده می کنند تا روی سيستم باقی بمانند :
    يكي استفاده از win.ini و نوشتن نام فايل جلوي = run و ديگري استفاده از system.ini و نوشتن نام برنامه جلوي خط explorer.exe .

     
  3. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    آشنايي با Windows API : واژه API مخفف Application Programming Interface مي باشد . API هاي ويندوز مجموعه اي از توابع از پيش آماده موجود در سيستم عامل هستند که شما مي توانيد آنها را در برنامه هاي خود فراخواني کنيد . اين توابع در چندين کتابخانه DLL ويندوز ذخيره شده اند . براي دسترسي به اين توابع در ويژوال بيسيک ابتدا بايد آنها را برنامه خود declare کنيد . براي مثال :

    Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long

    همانطور که مي بينيد مثال فوق يک Declare از تابع sndPlaySound مي باشد که اين تابع در کتابخانه Winmm.dll موجود است . کلمه Alias نشان مي دهد که اين تابع نام ديگري در dll دارد . ساير بخشها مربوط به تعريف پارامترهاي تابع مي باشند که در مورد مثال فوق ، اين تابع دو پارامتر ورودي و يک خروجي از نوع Long دارد .
    پس از Delare کردن API در برنامه مي توانيد از آن استفاده نمائيد .

    ۲ - پخش فايلهاي Wav : تابعي که براي پخش فايلهاي Wav استفاده مي شود تابع sndPlaySound است که در بالا با آن آشنا شديد . پارامتر lpzSoundName نام و مسير فايل Wavو پارامتر uFlags چگونگي پخش فايل را مشخص مي کند . مقادير ممکن اين پارامتر عبارتند از :
    - SND_ASYNC : اجازه مي دهد طوري فايل Wav پخش شود که آنرا بتوان وقفه داد . بعبارت ديگر قادر خواهيد بود فايل Wav تان را هر زمان که بخواهيد پخش کنيد و مطمئن باشيد که حتماً شنيده مي شود .
    - SND_LOOP : فايل Wav را بطور ممتد پخش مي کند .
    - SND_NODEFAULT : اگر فايل Wav پيدا نشود صداي ديگري پخش نخواهد شد ( مثلاً برخي صداهاي default ويندوز )
    - SND_SYNC : در طول پخش فايل Wav کنترل به برنامه داده نمي شود . اين پارامتر در زمانيکه مي خواهيد فايل Wav اي را در پس زمينه برنامه تان پخش کنيد مناسب نمي باشد .
    - SND_NOSTOP : اگر فايل Wav اي قبلاً در حال پخش باشد ، فايل Wav شما آنرا دچار وقفه نمي کند . از اين پارامتر زماني استفاده مي شود که بخواهيم فايل Wav مان هيچوقت در وسط کار قطع نشود .
    اگر بخواهيد از بيش از يکي از اين پارامترها استفاده کنيد توسط Or آنها را ترکيب نمائيد مثال :

    sndPlaySound App.path & "\ding.wav", SND_ASYNC or SND_LOOP


    نکته : براي استفاده از توابع صوتي پيچيده تر بايستي از DirectSound که يکي از اجزاي DirectX مي باشد استفاده کنيد . در مورد DirectSound بعداً صحبت خواهم کرد .

    ۳ - ساخت يک تايمر با دقت بالا : شايد تا بحال از کنترل تايمر موجود در نوار ابزار ويژوال بيسيک استفاده کرده باشيد . اين تايمر داراي دقت حدود ۵۵ ميلي ثانيه است . براي دستيابي به زمانهاي با دقت بالاتر اين کنترل مفيد نخواهد بود .
    تابع GetTickCount يک API موجود در کتابخانه Kernel32.dll است . اين تابع طول زماني را که سيستم شروع به کار کرده است را برحسب ميلي ثانيه برمي گرداند :

    Private Declare Function GetTickCount Lib "kernel32" () As Long
    براي بررسي طي شدن يک مدت زماني خاص شما ابتدا بايد مقدار اين تابع را در يک متغير کمکي مثل TempTime قرار دهيد سپس در يک حلقه Do-Loop بايد اختلاف زمان GetTickCount جديد و زمان TempTime را با مقدار زماني که مي خواهيد سپري شود مقايسه کنيد :

    TempTime = GetTickCount()x
    Do While DesiredTime < GetTickCount() - TempTime
    Do some things'
    Loop

    توسط کد بالا مي توان يک عمليات خاص را براي يک مدت زماني مشخص اجرا کرد .
    کد زير نشان مي دهد که چگونه مي توان دستورات خاصي را در فواصل زماني خاص اجرار کرد :

    ExitFunction = False
    TempTime = GetTickCount()x
    Do While not(ExitFunction)x
    If DesiredTime < GetTickCount() - TempTime then
    Reset the temporary variable'
    TempTime = GetTickCount()x
    Do some things'
    End If
    Loop

    همچنين از تابع GetTickCount مي توان براي benchmark برنامه ها استفاده کرد . بعبارت ديگر مي توان زمان اجراي يکسري دستورات خاص را بدست آورد .
     
  4. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    مطالبی در مورد کنترل WINSOCK
    کنترل WinSock نسبت به تمام کنترلهاي اينترنت در سطح پايينتري قرار دارد . اين کنترل امکان ايجاد سرويسهاي شبکه اي مبتني بر پروتکلهاي TCP و UDP را مهيا مي کند . بعبارت ديگر توسط اين کنترل مي توان برنامه هاي کاربردي Client/Server ( سرويس گيرنده / سرويس دهنده ) ايجاد و با استفاده از پروتکل TCP و يا UDP بين آنها ارتباط برقرار نمود .
    با تنظيم خصوصيات و فراخواني متدهاي اين کنترل مي توانيد به راحتي به يک کامپيوتر راه دور متصل شويد و داده ها را در هر دو جهت جابجا نمائيد . نمونه کاربرهايي که مي توان با اين کنترل ايجاد نمود :
    Client-server chat ، Mail client ، Mail server ، Proxy Server ، Network Game ، Port Scanner ، پياده سازي الگوريتم هاي موازي و …
    مباني TCP :
    پروتکل کنترل اينترنت ( Transfer Control Protocol ) اجازه مي دهد يک اتصال ( Connection ) را از طريق سوکت ( socket ) به يک کامپيوتر راه دور ( Remote Computer ) ساخته و استفاده کنيد . با استفاده از اين اتصال ، هر دو کامپيوتر مي توانند داده ها را بين خودشان انتقال دهند . برقراري ارتباط از طريق TCP همانند صحبت کردن با تلفن است که بايد حتماً اتصالي بين دو کامپيوتر صورت گيرد تا بتوانند با هم ارتباط برقرار کنند .
    اگر يک برنامه Client مي سازيد بايستي بدانيد که نام يا آدرس IP کامپيوتر Server چيست ( Remote Host IP ) و همچنين از طريق چه پورتي مي توانيد به آن متصل شويد ( Remote Port ) . حال بايستي به آن پورت Connect کنيد .
    همچنين اگر يک برنامه Server مي سازيد بايستي پورتي را که روي آن به درخواستها گوش مي دهيد مشخص کنيد ( LocalPort ) و سپس به پورت گوش دهيد ( Listen ) .
    زمانيکه يک کامپيوتر Client تقاضاي يک اتصال را مي دهد Server اين درخواست را Accept مي کند .
    زمانيکه يک اتصال ساخته مي شود ، هر دو کامپيوتر مي توانند داده را فرستاده و دريافت کنند .
    مباني UDP :
    پروتکل ديتاگرام کاربر ( User Datagram Protocol ) پروتکلي بدون اتصال ( Connectionless ) است . برخلاف TCP ، کامپيوترها نياز به برپا کردن يک اتصال ندارند بنابراين يک برنامه مي تواند يک client و يا يک server باشد . برقراري ارتباط در UDP شبيه ارسال نامه از طريق پست است .
    براي انتقال داده توسط UDP ابتدا بايد Local Port کامپيوتر Client تنظيم گردد . کامپيوتر Server تنها بايستي RemoteHost را برابر آدرس کامپيوتر Client قرار دهد و همچنين Remote Port را همان Local Port کامپيوتر Client قرار دهد . سپس دو کامپيوتر مي توانند داده ها را بين خود جابجا کنند .
    استفاده از کنترل WinSock :
    1 – انتخاب پروتکل: در زمان استفاده از کنترل WinSock اولين کاري که بايد انجام دهيد انتخاب يکي از پروتکلهاي TCP يا UDP است . طبيعت برنامه اي که شما مي سازيد نوع پروتکلي را که بايد استفاده کنيد مشخص مي کند . چند سوال زير به شما کمک مي کند که پروتکل مورد نيازتان را انتخاب کنيد :
    - آيا برنامه شما در زمانيکه داده فرستاده مي شود يا دريافت مي شود نياز به اطلاعاتي از طرف Server يا Client دارد ؟ اگر چنين است بايستي يک اتصال TCP قبل از ارسال يا دريافت داده ايجاد شود .
    - آيا داده بسيار بزرگ است ( مثل تصوير يا فايلهاي صوتي ) ؟ زمانيکه يک اتصال TCP ساخته مي شود پروتکل TCP اتصال را باقي نگه مي دارد و درستي ارسال داده تضمين شده است . اين اتصال در هر حال به منابع محاسباتي بيشتري نياز دارد و بنابراين پرهزينه تر است .
    - آيا داده متناوب ارسال مي شود يا در يک نشست ( Session ) ارسال خواهد شد ؟ براي مثال اگر شما يک برنامه مي سازيد که کامپترهاي مشخصي را در يک زمان خاص از انجام شدن عملياتي مطلع مي کند پروتکل UDP مناسب تر است . پروتکل UDP همچنين براي ارسال مقادير کوچک داده اي مناست تر مي باشد .
    2 – تنظيم پروتکل : براي تنظيم پروتکلي که مي خواهيد در برنامه تان از آن استفاده کنيد در زمان طراحي برنامه خاصيت Protocol کنترل WinSock را برابر sckTCPProtocol و يا sckUDPProtocol قرار دهيد . همچنين مي توانيد پروتکل خود را توسط کد زير تنظيم کنيد :

    WinSock.Protocol=sckTCPProtocol
    3 – مشخص کردن نام کامپيوتان : براي اتصال به کامپيوتر راه دور بايستي آدرس IP و يا نام کامپوتر را بدانيد .
    نام کامپيوتر در Control Panel/Network/Identification موجود است . در صورتيکه مي خواهيد دو برنامه Client و Server خود را روي يک کامپيوتر تست کنيد از آدرس IP 127.0.0.1 براي هر دو استفاده کنيد اما اگر دو برنامه را روي دو کامپيوتر مجزا در شبکه قرار داده ايد با اجراي دستور ipconfig در DOS Prompt مي توانيد آدرس IP کامپيوتر ها را بدست آوريد .
    4 – ايجاد اتصال TCP : در زمان ساخت برنامه اي که از پروتکل TCP استفاده مي کند ابتدا بايد تصميم بگيريد که اين برنامه Client است يا Server . براي ساخت يک برنامه Server بايستي روي يک پورت خاص Listen کنيد . زمانيکه Client تقاضاي يک اتصال را مي دهد ، برنامه Server مي تواند آنرا Accept کند و بنابراين اتصال کامل شده است . حال Client و Server مي توانند با هم ارتباط داشته باشند .
    مراحل زير ساخت يک سرور چت ساده بر مبناي TCP را نشان مي دهد :
    - از منوي Project گزينه Components را انتخاب کنيد و در ليست Component ها مورد Microsoft WinSock 6.0 را انتخاب کنيد .
    - يک کنترل WinSock در فرم خود قرار دهيد و نام آنرا tcpserver بگذاريد
    - دو textbox با نامهاي txtSendData و txtReceiveData و نيز يک دکمه در فرم قرار دهيد .
    - کد زير را در رويداد Form_Load بنويسيد :

    Tcpserver.LocalPort=1000
    tcpserver.Listen

    - زمانيکه درخواستي از طرف Client مي آيد رويداد ConnectionRequest اجرا مي شود . در اين رويداد ابتدا بايد چک کنيد که حالت کنترل بسته باشد . اگر چنين نيست اتصال را قبل از پذيرفتن اتصال جديد ببنديد . سپس تقاضا را بر اساس پارامتر requestID مي پذيريم :

    Private Sub tcpserver_ConnectionRequest(ByVal requestID As Long)
    If tcpserver.State <> sckClosed Then tcpserver.Close
    tcpserver.Accept requestID
    End Sub

    - حال اتصال بين Client و Server برقرار شده است . کد زير را براي event مربوط به کليک دکمه Send بنويسيد :

    Tcpserver.SendData txtSendData.text
    - اگر داده اي از طرف Client بيايد رويداد DataArrival اجرا مي شود . کد زير را براي اين رويداد بنويسيد :

    Private Sub tcpserver_DataArrival(ByVal bytesTotal As Long)
    Dim strData As String
    tcpserver.GetData strData
    txtReceiveData.Text = strData
    End Sub

    - کد زير را براي رويداد Form_Unload بنويسيد :

    Tcpserver.Close
    مراحل ساخت يک TCP Client بصورت زير است :
    - يک کنترل WinSock در فرم قرار دهيد و نام آنرا tcpclient بگذاريد .
    - دو textbox با نامهاي txtsend و txtreceive و نيز يک دکمه با نام sendدر فرم قرار دهيد .
    - يک دکمه با نام connect در فرم قرار دهيد .
    - کد زير را براي متد Form_Load بنويسيد :

    tcpclient.RemoteHost=”yourservername”x
    tcpclient.RemotePort=1000

    - کد زير را براي رويداد کليک شدن دکمه connect بنويسيد :

    tcpclient.Connect
    - کد زير را براي رويداد کليک شدن دکمه send بنويسيد :

    tctclient.SendData txtsend.Text
    - کد زير را براي رويداد DataArrival بنويسيد :

    Private Sub tcpclient_DataArrival(ByVal bytesTotal As Long)
    Dim strData As String
    tcpclient.GetData strData
    txtreceive.Text = strData
    End Sub

    - کد زير را باري رويداد Form_Unload بنويسيد :

    Tcpclient.Close
    کدهاي فوق يک سيستم Client-Server ساده را نشان مي دهد . فايل exe هر دو برنامه را بسازيد و آنها را اجرا کنيد تا بتوانيد سيستم خود را تست کنيد .
    5 – پذيرفتن بيش از يک تقاضاي اتصال : Server اي که در بالا ساخته شد تنها مي تواند تقاضاي يک اتصال را بپذيرد . با استفاده از ايجاد يک آرايه از کنترل WinSock مي توان چندين تقاضاي اتصال را پذيرفت . براي اينکار کافي است يک کپي ( instance ) از کنترل بسازيم ( با تنظيم خاصيت Index ) و متد Accept را براي instance جديد بکار ببريم . فرض کنيد يک کنترل WinSock با نام sckServer در فرم داريم که خاصيت Index آنرا صفر قرار داده ايم . همچنين يک متغير intMax از نوع Long تعريف مي کنيم که تعداد اتصالات همزمان به Server را نگه مي دارد . در event مربوط به Form_Load کد زير را بنويسيد :

    intMax=0
    sckServer(0).LocalPort=1000
    sckServer(0).Listen

    هر بار که تقاضاي يک اتصال مي رسد کد ابتدا تست مي کند که مقدار Index چقدر است . اگر مقدار Index صفر باشد متغير intMax يکي افزايش مي يابد و از intMax براي ساخت يک instance جديد از کنترل استفاده مي شود . حال از اين instance براي پذيرفتن تقاضاي اتصال استفاده مي گردد . براي اينکار کد زير را براي رويداد ConnectionRequest بنويسيد :

    Private Sub sckServer_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    If Index = 0 Then
    intmax = intmax + 1
    Load sckServer(intmax)x
    sckServer(intmax).LocalPort = 0
    sckServer(Index).Accept requestID
    End If
    End Sub
    6 – ايجاد اتصال UDP : ساخت يک برنامه UDP ساده تر از برنامه هاي TCP است زيرا پروتکل UDP به اتصال نياز ندارد . در برنامه TCP بالا يک کنترل WinSock بايستي حتماً Listen مي کرد و يک کنترل ديگر يک اتصال را توسط متد Connect ايجاد نمود . در عوض پروتکل UDP نيازي به اتصال ندارد . براي ارسال داده بين دو کنترل WinSock سه مرحله بايستي انجام شود :
    - پارامتر RemoteHost برابر نام کامپيوتر مقابل است .
    - پارامتر RemotePort برابر پارامتر LocalPort کامپيوتر مقابل
    - استفاده از متد Bind براي مشخص کردن LocalPort
    چون هر دو کامپيوتر از نظر ارتباط مساوي هستند ، اين نوع برنامه ها را Peer-to-Peer گويند . براي نمونه از کد زير براي ساخت يک برنامه chat استفاده مي کنيم :
    - يک کنترل WinSock در فرم قرار دهيد و نام آنرا udppeerA بگذاريد .
    - خاصيت Protocol آنرا UDPProtocol قرار دهيد .
    - دو textbox با نامهاي txtsend و txtreceive و نيز يک دکمه در فرم قرار دهيد .
    - کد زير را براي متد Form_Load بنويسيد :

    udppeerA.RemoteHost=”nameofpeerB”x
    udppeerA.RemotePort=1001
    udppeerA.Bind 1002

    - کد زير را براي event مربوط به کليک دکمه بنويسيد :

    udppeerA.SendData txtsend.text
    - کد زير را براي رويداد DataArrival بنويسيد :

    Dim strData as String
    udppeerA.GetData strData
    txtreceive.Text=strData

    براي ساخت UDP peerB مشابه مراحل بالا عمل کنيد فقط خاصيت RemoteHost آنرا نام کامپيوتر PeerA و خاصيت RemotePort آنرا 1002 و خاصيت Bind آنرا 1001 قرار دهيد .
    -------------------

    بررسی خواص کنترل WinSock :
    ByteReceived : مقدار داده دريافت شده ( موجود در بافر receive ) را نشان مي دهد . توسط متد GetData مي توان اين داده را دريافت نمود .
    LocalHostName : نام ماشين محلي را نشان مي دهد . اين پارامتر فقط خواندني است .
    LocalIP : آدرس IP ماشين محلي را بصورت يک string برمي گرداند . اين پارامتر فقط خواندني است .
    LocalPort : براي خواندن و يا تنظيم شماره پورت محلي بکار مي رود .
    Protocol : براي خواندن و يا تنظيم پروتوکل مورد استفاده توسط کنترل WinSock بکار مي رود .
    RemoteHost : براي خواندن و يا تنظيم نام يا آدرس IP ماشين راه دور بکار مي رود .
    RemoteHostIP : آدرس IP ماشين راه دور را برمي گرداند :
    ۱- براي برنامه هاي Client بعد از زمانيکه يک اتصال توسط متد Connect پذيرفته شد ، اين خاصيت حاوي آدرس IP ماشين راه دور است .
    ۲ - براي برنامه Server ، بعد از آمدن يک Connection Request اين خاصيت شامل آدرس IP ماشين راه دور است .
    ۳ - در زمان استفاده از پروتکل UDP بعد از اينکه رويداد Data Arrival رخ داد اين خاصيت حاوي آدرس IP ماشيني است که داده را فرستاده .
    RemotePort : براي خواندن و يا تنظيم شماره پورت ماشين راه دوري که مي خواهيد به آن متصل شويد بکار مي رود .
    SocketHandle : مقداري را برمي گرداند که مرتبط با سوکتي است که کنترل WinSock را مديريت مي کند و براي ارتباط با لايه WinSock بکار مي رود . اين پارامتر فقط خواندني است و تنها براي ارسال به API هاي WinSock طراحي شده است .
    State : وضعيت کنترل WinSock را نشان مي دهد . وضعيتهاي ممکن براي State عبارتند از :
    ۱ - sckClosed : اتصال بسته است .
    ۲ - sckOpen : اتصال باز است .
    ۳ - sckListening : حالت گوش دادن به پورت
    4 - sckConnectionPending : معلق شدن اتصال
    ۵ - sckResolvingHost : تصميم گيري در مورد ميزبان
    ۶ - sckHostResolved : در مورد ميزبان تصميم گيري شد .
    ۷ - sckConnecting : حالت برقراري ارتباط
    ۸ - sckConnected : ارتباط برقرار شد .
    ۹ - sckClosing : حالت قطع اتصال
    ۱۰ - sckError : حالت خطا

    بررسی متدهای کنترل WinSock :
    متد Accept : تنها براي برنامه هاي TCP Server بکار مي رود . اين متد براي پذيرفتن يک اتصال در زمان مديريت رويداد ConnectionRequest استفاده مي شود .
    متد Bind : اين پارامتر LocalPort و LocalIP يک اتصال را مشخص مي کند .
    متد Close : براي بستن يک اتصال TCP و يا بستن يک listening socket بکار مي رود .
    متد GetData : بلوک جاري داده دريافت شده را گرفته و آنرا در متغيري از نوع Variant ذخيره مي کند . شکل کلي اين متد بصورت زير است :

    WinSock.GetData data[,type][,maxlen]x
    که data داده دريافتي است . اگر داده کافي موجود نباشد data برابر empty خواهد بود .
    type نوع داده دريافتي است که مي تواند مقادير زير باشد :
    vbByte - vbInteger - vbLong - vbSingle - vbDouble - vbDate - vbBoolean - vbError - vbString - vbArray+vbByte
    maxlen حداکثر سايز را در زمان دريافت يک byte Array و يا يک string مشخص مي کند .
    متد Getdata در رويداد Data Arrival استفاده مي شود که اين رويداد يک پارامتر با نام TotalBytes دارد . اگر maxlen اي که شما تعيين کرده ايد کمتر از TotalBytes باشد پيغام هشدار شماره ۱۰۰۴۰ دريافت مي کنيد بدين معني که بايتهاي باقيمانده گم خواهند شد .
    متد Listen : يک سوکت مي سازد و آنرا در حالت Listen قرار مي دهد . اين متد تنها در اتصالات TCP بکار ميرود .
    متد PeekData : مشابه GetData است با اين تفاوت که داده را از صف ورودي حذف نمي کند . اين متد تنها براي اتصالات TCP بکار مي رود .
    متد SendData : براي ارسال داده به کامپيوتر راه دور بکار مي رود .
    بررسي event هاي کنترل WinSock :
    رويداد Close : زماني رخ مي دهد که کامپيوتر راه دور اتصال را ببندد .
    رويداد Connect : بعد از اينکه يک اتصال به Server ايجاد شد روي مي دهد . شکل کلي آن بصورت زير است :

    Private Sub WinSock_Connect(ErrorOccurred As Boolean)x
    که پارامتر ErrorOccurred دو مقدار دارد : اگر True باشد يعني اتصال Fail شده است و اگر False باشد يعني اتصال با موفقيت انجام شده است .
    با رويداد Connect مي توانيد error هايي که در زمان فرايند باز کردن اتصال برگردانده شده را چک کنيد .
    رويداد ConnectionRequest : زماني رخ مي دهد که يک کامپيوتر راه دور تقاضاي يک اتصال را بدهد . اين رويداد فقط براي برنامه هاي TCP Server بکار مي رود .
    رويداد DataArrival : زماني رخ مي دهد که داده جديدي بيايد .
    رويداد Error : زماني رخ مي دهد که يک خطا در فرايند ارتباط رخ دهد ( مثلاً Failed to Connect و يا Failed to Send ) . شکل کلي آن بصورت زير است :

    Private WinSock_Error(number as Integer,description as String,scode as Long,source as String,helpfile as String,helpcontext as Long,canceldisplay as Boolean)x

    number شماره کد خطا است .
    description توضيحي در مورد خطا است .
    source توصيف منبع خطا
    canceldisplay : مشخص مي کند آيا پيغام خطاي پيش فرض نشان داده شود يا نه
    رويداد SendComplete : زماني رخ مي دهد که يک عمل Send تکميل شده باشد .
    رويداد SendProgress : زماني رخ مي دهد که کنترل شروع به ارسال داده نمايد . شکل کلي آن بصورت زير است :

    WinSock_SendProgress (bytesSent As Long, bytesRemaining As Long)x

    که bytesSent تعداد بايتهاي ارسال شده و bytesRemaining تعداد بايتهاي باقيمانده است .
     
  5. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    رویداد ها در ویژوال بیسیک
    براي هر عملي که ميخواهيم کاربر در برنامه ما انجام دهد مي بايست در هر رويداد کد خاصي را بنويسيم تا نسبت به رفتار خاصي پاسخگو باشيم اين رويدادها تعيين ميکنند که برنامه ما نسبت به چه اعمالي حساس باشد کليک کردن يا فشردن دکمه اي خاص.
    عمل کليک : تو مثالهاي قبلي وقتي رو Command1 کليک ميکرديم يه عملي انجام ميشد چون ما تو رويداد کليک Command1 اون کدمون رو نوشتيم حالا اگه بخواهيم رويدادهاي ديگه اي هم هستن مثلا KeyDown ويا MouseMove و ... همه اينها بسته به نوعشون در مقابل رفتار کاربر عمل بخصوصي رو انجام ميدن حالا چند تا کد مينويسيم که با رويدادهاي مختلف آشنا بشيم :
    MouseMove:زماني که ماوس رو باتن حرکت کنه Caption باتن عوض ميشه.
    Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "Mosee Move !"End Sub​
    MouseDown: اگر دکمه فشار داده شود (هنوز دستمان روي دکمه ماوس است دکمه بالا نيامده)
    Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "Mosee Down !"End Sub​
    MouseUp : دکمه ماوس فشار داده شده و به سمت بالا رها مي شود بعد از عمل MouseDown
    Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "Mosee Up !"End Sub​
    رويدادهاي KeyDown وKeyPress وKeyUp هم مثل همين ها هستند تنها تفاوت چون نياز به يک دستور شرطي دارند(با يک دستور شرطي مشخص ميکنيم اگر کليد فشرده شده مثلا Ctrl بود چه عملي انجام شود) بعدا که دستورات شرطي رسيديم ميگم .DragDrop و DragOver هم همچنين.+
    ولي حالا ميخواهيم يه برنامه ساده بنويسيم که از کنترل Label استفاده مي شه . يه کنترل ليبل از سمت چپ انتخاب کنين و بندازين تو صفحه فرمتون ! برنامه ما اين کار رو ميکنه -[وقتي ماوس رو ليیل ميره رنگ اون عوض ميشه و Bold هم ميشه مثل همين لينک ها و وقتي هم ماوس رو از روش برمي داريم به حالت اول بر ميگرده ]- خب اول براي رويداد MouseMove اينها رو مينويسيم:
    Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Label1.ForeColor = &HFF& Label1.FontBold = TrueEnd Sub​
    و در رويداد Form_MouseMove هم اينها رو مينويسيم(همين ها رو کپي و پيست کنين)
    Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Label1.ForeColor = &H80000007 Label1.FontBold = FalseEnd Sub​
    حالا برنامه رو اجرا کنين ماوس رو روي ليبل بذارين و از روش بردارين
     
  6. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    آشنایی با BITBIT
    هدف از اين مبحث آموزشي ، آشنايي با تابع BitBlt و برخي ديگر از توابع کتابخانه Win32 GDI براي انجام برخي عمليات گرافيکي مثل double buffering و خواندن sprite از فايل است .
    نکته : sprite به کاراکترهاي متحرکي گفته مي شود که در بازيها وجود دارد .
    اولين چيزي که به آن نياز داريد ايجاد يک فرم است . خاصيت ScaleMode آنرا برابر 3-Pixel قرار دهيد . پيشنهاد مي کنم که هميشه در هنگام استفاده از فرم بهمراه API از pixel براي scalemode استفاده کنيد .
    سپس سايز فرم را به اندازه اي افزايش دهيد تا ScaleWidth برابر 320 و ScaleHeight برابر 256 شود . توجه کنيد که خاصيت HasDC فرم را True قرار دهيد . همچنين از خاصيت AutoRedraw براي فرم استفاده نمي کنيم زيرا مي خواهيم از Double Buffering استفاده کنيم که بسيار سريعتر و کارامدتر مي باشد .
    مرحله بعدي declare کردن API هايي است که به آنها نياز داريم :
    'blitting
    Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
    'code timer
    Private Declare Function GetTickCount Lib "kernel32" () As Long
    'creating buffers / loading sprites
    Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    'loading sprites
    Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
    'cleanup
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

    سوال : DC چيست ؟ DC و يا بعبارت ديگر Device Context ، hDC يک عدد است که به يک آدرس در حافظه اشاره مي کند که داده اي در آن ذخيره شده است . در هنگام استفاده از BitBlt براي اشاره کردن به آدرسي که داده گرافيکي در آنجا ذخيره شده ، استفاده مي شود .
    در مرحله بعدي نياز به ذخيره آدرسهاي DC داريم که مي سازيم . آدرسهاي DC مقادير Long هستند همچنين آنها را بصورت Public تعريف مي کنيم :
    'our Buffer's DC
    Public myBackBuffer As Long
    Public myBufferBMP As Long
    'The DC of our sprite/graphic
    Public mySprite As Long
    'coordinates of our sprite/graphic on the screen
    Public SpriteX As Long
    Public SpriteY As Long

    حال بايد تابعي بسازيم که تصاوير گرافيکي درون حافظه load کند . نکته مهمي که بايد به آن توجه کنيد اينست که يک device context خودش به تنهايي هيچ داده گرافيکي ندارد و بايستي يک bitmap موجود باشد تا درون آن load شود براي مثال يک فايل bmp يا يک bitmap خالي که از آن بعنوان back buffer استفاده مي کنيد .
    تابعي که خواهيم نوشت يک device context منطبق با صفحه مي سازد سپس فايلهاي گرافيکي مورد نظر را درون device context قرار مي دهد :
    Public Function LoadGraphicDC(sFileName As String) As Long
    'temp variable to hold our DC address
    Dim LoadGraphicDCTEMP As Long
    'create the DC address compatible with
    'the DC of the screen
    LoadGraphicDCTEMP = CreateCompatibleDC(GetDC(0))
    'load the graphic file into the DC...
    SelectObject LoadGraphicDCTEMP, LoadPicture(sFileName)
    'return the address of the file
    LoadGraphicDC = LoadGraphicDCTEMP
    End Function

    سوال : double-buffering چيست ؟ زمانيکه يک محيط گرافيکي مي سازيد تا درون آن چيزي را ترسيم کنيد ، شما sprite ها / گرافيکها / متن را درون حافظه blit مي کنيد ( offscrean ) سپس نتيجه نهايي را روي صفحه blit مي کنيد . اين عمل از لرزش تصوير يا flickering جلوگيري مي کند ( زماني رخ مي دهد که چندين sprite مستقيماً روي صفحه blit شوند ) و بسيار سريعتر از AutoRedraw است .
    قبل از اينکه مثالي براي اين تابع ذکر کنم تابع BitBlt را توضيح خواهم داد :
    BitBlt تابعي از کتابخانه dll “gdi32” است . اين تابع يک انتقال bit-block از داده هاي مرتبط به يک مستطيل از پيکسلها به يک device context مقصد انجام مي دهد . بعبارت ديگر داده هاي گرافيکي را از محيط گرافيکي ( يک bitmap ) به محيط گرافيکي ديگري ( screen يا يک form ) کپي مي کند . فرم کلي اين تابع بصورت زير است :
    Declare Function BitBlt Lib "gdi32" Alias "BitBlt" _
    (ByVal hDestDC As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long, _
    ByVal hSrcDC As Long, _
    ByVal xSrc As Long, _
    ByVal ySrc As Long, _
    ByVal dwRop As Long) As Long

    اولين خط بيان مي کند که ما بوسيله gdi32 DLL به تابع BitBlt دسترسي خواهيم داشت . خطوط ديگر پارامترهايي هستند که اين تابع مي گيرد :
    hDestDC : hDC مربوط به محيط مقصد ( اگر مي خواهيد مقصد يک فرم باشد از form.hDC استفاده کنيد و يا اينکه آدرس يک backbuffer را که ساخته ايد بدهيد )
    x : مختصات افقي محلي که مي خواهيد گرافيک شما ظاهر شود .
    y : مختصات عمدي محلي که مي خواهيد گرافيک شما ظاهر شود .
    nWidth : عرض گرافيک شما
    nHeight : ارتفاع گرافيک شما
    hSrcDC : hDC مربوط به محيط مبدا
    xSrc : افست x . 0 زماني استفاده مي شود که بخواهيد از سمت چپترين گوشه گرافيک مبدا عمل blit را انجام دهيد .
    ySrc : افست y
    dwRop : مد draw اي که در زمان blitting گرافيکتان مي خواهيد استفاده کنيد ( Raster Operations يا ROP ) . اين پارامتر مقادير زير را مي تواند بگيرد :
    - vbSrcCopy : داده تصوير مبدا را مستقيماً در مقصد کپي مي کند .
    - vbSrcPaint : داده هاي تصاوير مبدا و مقصد را با هم OR مي کند ( pseudo-alphablending effect )
    - vbSrcAnd : داده هاي تصاوير مبدا و مقصد را با هم AND مي کند ( pseudo-gamma effect )
    - vbSrcInvert : داده هاي تصاوير مبدا و مقصد را با هم XOR مي کند
    - vbSrcErase : ابتدا داده تصوير مقصد را invert مي کند سپس آنرا با داده تصوير مبدا AND مي کند .
    - vbDstInvert : داده تصوير مقصد را invert مي کند و داده تصوير مبدا را در نظر نمي گيرد .
    - vbNotSrcCopy : داده تصوير مبدا را invert مي کند و آنرا مستقيماً در مقصد کپي مي کند .
    - vbNotSrcErase : داده تصاوير مبدا و مقصد را OR کرده و نتيجه را invert مي کند .

    مثالي از کاربرد BitBlt :
    BitBlt Form1.hDC, PlayerX, PlayerY, 48, 48, picPlayer.hDC, 0, 0, vbSrcCopy

    حال مي خواهيم از BitBlt در يک حلقه استفاده کنيم تا يک image را در فرم حرکت دهيم :
    1 – يک فايل bmp با ابعاد 32x32 بسازيد و با نام sprite1.bmp در دايرکتوري پروژه ذخيره کنيد .
    2 – يک دکمه در فرم قرار دهيد و نام آنرا cmdTest بگذاريد .
    3 – دکمه را در گوشه بالايي فرم و در سمت راست قرار دهيد .
    4 – کد زير را براي event مربوط به کليک شدن دکمه بنويسيد :
    'Timer variables...
    Dim T1 As Long, T2 As Long
    ساخت DC براي backbuffer’
    myBackBuffer = CreateCompatibleDC(GetDC(0))
    ساخت يک سطح bitmap براي DC’
    myBufferBMP = CreateCompatibleBitmap(GetDC(0), 320, 256)
    load کردن سطح bitmap خالي درون buffer’
    SelectObject myBackBuffer, myBufferBMP
    قبل از blit کردن درون بافر بايد آنرا با black پر کنيم’
    BitBlt myBackBuffer, 0, 0, 320, 256, 0, 0, 0, vbWhiteness
    load کردن split توسط تابعي که در بالا نوشتيم’
    mySprite = LoadGraphicDC(App.Path & "\sprite1.bmp")
    cmdTest.Enabled = False
    == شروع حلقه اصلي ==’
    خواندن tickcount جاري’
    T2 = GetTickCount
    Do
    DoEvents
    T1 = GetTickCount
    اگر 15 ميلي ثانيه گذشته بود فريم بعدي شروع شود’
    If (T1 - T2) >= 15 Then
    پاک کردن محل قبلي sprite بوسيله پر کردن آنجا با black ‘
    BitBlt myBackBuffer, SpriteX - 1, SpriteY - 1,32, 32, 0, 0, 0, vbBlackness
    Blit کردن sprite درون back buffer’
    BitBlt myBackBuffer, SpriteX, SpriteY, 32, 32,mySprite, 0, 0, vbSrcPaint
    Blit کردن backbuffer روي فرم’
    BitBlt Me.hdc, 0, 0, 320, 256, myBackBuffer,0, 0, vbSrcCopy
    حرکت دادن sprite روي صفحه’
    SpriteX = SpriteX + 1
    SpriteY = SpriteY + 1
    'update timer
    T2 = GetTickCount
    End If
    Loop Until SpriteX = 320
    سپس بايد يک cleanup code بنويسيد تا حافظه هاي را که براي نگهداري تصاوير گرافيکي و buffer ها استفاده کرده ايد آزاد کنيد :
    Private Sub Form_Unload(Cancel As Integer)
    DeleteObject myBufferBMP
    DeleteDC myBackBuffer
    DeleteDC mySprite
    End
    End Sub

     
  7. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    ايجاد کلاسی برای کار با فايلهای XML
    برای قرار دادن پارامترهای اتصال به بانک اطلاعاتی از فايل XML استفاده خواهيم نمود . بنابراين ابتدا بايستی کلاسی برای کار با فايلهای XML بنويسيم . توجه داشته باشيد که کلاسی که در اين بخش معرفی می شود کلاسی ساده می باشد که فقط با آن می توان مقدار يک ند Node وجود در فايل xml را خواند . در صورت نياز ، می توانيد خودتان متدهای ديگری را به آن اضافه کنيد . برای اين منظور نکاتی را در انتهای همين بخش آورده ام .
    XML يک زبان نشانه ای توسعه پذير ( eXtensible Markup Language ) است که در سال 1998 توسط کنسرسيوم وب جهانی W3C ايجاد شد . XML واقعاً يک زبان نيست بلکه يک متا-زبان است و برای توصيف ساير زبانها بکار می رود . داده ها در فايلهای XML براحتی قابل تعريف و استفاده هستند .
    مثالی از يک فايل XML :


    <user>
    <name>ali</name>
    <id>12</id>
    </user>


    کار با فايلهای XML در وی بی :
    برای کار با فايلهای xml در ويژوال بيسيک بايستی ابتدا از بخش References مورد Microsoft XML 3.0 را انتخاب کنيد . سپس يک Class Modules به پروژه تان اضافه کنيد و نام آنرا XMLReader بگذاريد . در اين کلاس ابتدا يک متغير از نوع شی xml برای کار با فايلهای xml تعريف می کنيم :

    Private xml

    سپس متدی برای مقداردهی اوليه شی xml می نويسيم . اين متد دارای يک متغير ورودی است که نام فايل xml مورد نظر می باشد :

    Public Sub Initiate(ByVal filename As String)x
    Set xml = CreateObject("Microsoft.XMLDOM")x
    xml.async = False
    xml.Load (server.MapPath(filename))x
    End Sub

    توجه کنيد که در کد فوق از شی server برای يافتن مسير فيزيکی فايل XML استفاده شده است بنابراين ابتدا بايستی در Class_Initialize اين شی را مطابق مطالب درس دوم مقداردهی کنيد .

    حال بايستی متدی برای خواندن مقدار يک ند از فايل xml بنويسيم . در اين متد توسط يک حلقه for each ندهای فايل را بررسی می کنيم تا ندی را بيابيم که نامش مشابه با متغير ورودی متد است . سپس با استفاده از خاصيت nodeValue می توانيم مقدار آنرا بخوانيم .

    Public Function getvalue(ByVal NName As String) As String
    Dim x
    getvalue = ""x
    For Each x In xml.documentElement.childNodes
    If x.nodeName = NName Then
    getvalue = x.childNodes(0).nodeValue
    Exit For
    End If
    Next
    End Function

    مثالی از کار با کلاس XMLReader :
    همانطور که گفته شد می توانيم پارامترهای اتصال به بانک اطلاعاتی را در فايل XML قرار دهيم و در زمان Initiate کردن ADODB برای اتصال به بانک اطلاعاتی ، آنها را بخوانيم :

    Dim xmlf As New XMLReader
    Call xmlf.Initiate("config.xml")x
    userName = xmlf.getvalue("DataBaseID")x
    Password = xmlf.getvalue("DataBasePassword")x
    database_name = xmlf.getvalue("DataBaseName")x
    server_name = xmlf.getvalue("ServerAddress")x

    ساختار يک فايل نمونه config.xml بصورت زير می باشد :


    <Application>testIt</Application>
    <ServerAddress>192.168.0.1</ServerAddress>
    <DataBaseName>Edatabase</DataBaseName>
    <DataBaseID>Euser</DataBaseID>
    <DataBasePassword>Epass</DataBasePassword>


    ساير نکات برای توسعه کلاس فوق :
    نکات زير شما را در نوشتن کلاسی کاملتر راهنمايي می کنند :

    1 - توجه داشته باشيد که xml.documentElement بعنوان ريشه فايل xml محسوب می شود . بنابراين برای دسترسی به ريشه می توان يک شی ريشه نيز تعريف کرد :

    Dim root
    Set root = xml.documentElement

    2 - در صورتيکه يک فايل xml دارای چندين ند در ريشه اش باشد و هر ند ريشه نيز دارای چندين ند درونی باشد توسط خاصيت root.childNodes.length و با استفاده از يک حلقه for می توان به اين ندها دسترسی داشت . برای مثال فايل زير را درنظر بگيريد :


    <people>
    <user>
    <name>ali</name>
    <id>1</id>
    </user>
    <user>
    <name>reza</name>
    <id>2</id>
    </user>
    </people>


    حلقه زير روش دسترسی را به اين فايل نشنان می دهد :

    For I = 0 TO (root.childNodes.length - 1)x
    Set thisChild = root.childNodes(I)x
    name = thisChild.childNodes(0).Text
    id = thisChild.childNodes(1).Text
    Next

    3 – اضافه کردن ند به فايل : برای اضافه کردن ند از متدهای createNode و appendChild استفاده می شود برای مثال برای اضافه کردن يک user جديد به مثال فوق :

    Set newuser = xml.createNode("element", "people", "")x
    Dim name,id
    Set newname = xml.createNode("element", "name", "")x
    newname.text = yourname
    Set newid = xml.createNode("element", "id", "")x
    newid.text = yourid
    newuser.appendChild(newname)x
    newuser.appendChild(newid)x
    root.appendChild(newuser)x

    در انتها نيز بايستی فايل را ذخيره نمود :

    xml.save(Server.Mappath(filename))x

    4 – حذف يک ند از فايل : برای حذف يک ند از فايل توسط يک حلقه for بايستی ند مورد نظر را يافته و سپس توسط متد removeChild آنرا حذف کنيم :

    found = False
    For I = (root.childNodes.length - 1) TO 0 STEP -1
    Set thisChild = root.childNodes(I)x
    name = thisChild.childNodes(0).Text
    If name = searchname Then
    root.removeChild(thisChild)x
    found = True
    End If
    Next
     
  8. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    آموزش DirectX-Graphic قسمت اول
    DirectX8 ابزاري براي ساخت تصاوير ثابت و متحرک دو بعدي و سه بعدي مي باشد .
    براي کار با
    DirectX8 ابتدا بايستي آنرا روي سيستم خود نصب کنيد . سپس در محيط vb از منوي project گزينه References را انتخاب کنيد . در فرمي که ظاهر مي شود اطمينان حاصل کنيد که گزينه DirectX8 for VB type library فعال باشد .
    براي کار با
    DirectX8 بايستي از تعريف نمودن شي پايه DirectX8 شروع نمود :

    Dim Dx as DirectX8


    شي
    Direct3D8 براي کنترل اشيا‌‌ سه بعدي بکار مي رود :

    Dim D3D as Direct3D8


    شي
    Direct3DDevice8 ، سخت افزار مربوط به رندر تصاوير را مشخص مي کند :

    Dim D3DDevice as Direct3DDevice8


    حال براي شروع کار با
    Direct3D ، تابع ( ) initialise را تعريف مي کنيم . اگر اينکار درست انجام شود تابع ، مقدار true را برمي گرداند :

    public function initialise () as boolean
    DimDispMode as D3DISPLAYMODE


    شي
    D3DISPLAYMODE حالت نمايش را مشخص مي نمايد .

    Dim D3Dwindow as D3DPRESENT_PARAMETERS


    شي فوق مشخص مي کند که
    viewport شما چگونه باشد .
    حال شي اصلي
    DirectX8 را مي سازيم :

    Set Dx=New DirectX8


    سپس شي اصلي ساخت واسط سه بعدي را مي سازيم :

    ()
    set D3D.Dx.Direct3Dcreate


    سپس حالت فعلي نمايش را با دستور زير استخراج مي کنيم :

    D3D.getadapterdisplaymodeD3DADAPTER_DEFAULT,dispmode


    حال دو حالت براي کار با
    DirectX داريم :
    1 -
    windowed mode
    2 -
    fullscrean mode
    1 - براي کار با حالت پنجره اي ابتدا اين موضوع را به
    DirectX اطلاع مي دهيم :

    D3Dwindow.windowed=1


    سپس نوع
    referesh تصوير را مشخص مي کنيم ( در اينجا چند انتخاب وجود دارد که در صورت نياز به اطلاعات بيشتر با من تماس بگيريد . ) :

    D3Dwindow.swapeffect=D3DSWAPEFFECT_COPY_VSYNC


    سپس بايستي فرمت بافر نگهدارنده تصاوير را مشخص کنيم :

    D3Dwindow.backbufferformat=dispmode.format


    2 - براي کار با حالت تمام صفحه ، ابتدا نوع
    refresh را مشخص کرده سپس تعداد بافر هاي تصوير و سرانجام نوع و سايز بافر را مشخص مي نمائيم :

    D3Dwindow.swapeffect=D3DSWAPEFFECT_DISCARD
    D3Dwindow.backbuffercount=1
    D3Dwindow.backbufferformat=dispmode.format
    D3Dwindow.backbufferheight=dispmode.height
    D3Dwindow.backbufferwidth=dispmode.width


    سپس پنجره نمايش مشخص مي گردد :

    D3Dwindow.hdevicewindow=frmMain.hwnd



    @حال بايستی يک
    device ساخته شود که يا از طريق سخت افزار و يا نرم افزار تصاوير را رندر نمايد :

    SetD3DDevice=D3Dcreatedevice(D3DADAPTER_DEFAULT
    ,
    D3DDEVTYPE_HAL,
    frmMain.hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,
    D3Dwindow)x,
    endsub


    درصورتي که کارت گرافيک شما امکانات رندر سخت افزاري تصاوير را ندارد از
    D3DDEVTYPE_REF بجاي D3DDEVTYPE_HAL استفاده کنيد .
    حال بايستي روتين
    render را بنويسيم . البته در اين درس تصويري براي رندر نداريم و تنها چگونگي نوشتن اين روتين را بيان خواهم کرد :
    ۱ - ابتدا بايستي device مربوط به رندر ، قبل از کشيدن تصوير در آن پاک شود :

    D3DDevice.clear 0,byval 0,D3DCLEAR_TARGET,&H0,1#,0


    عدد
    hex اي که در دستور فوق آمده رنگ زمينه صفحه را مشخص مي کند
    ۲ - سپس بايستي تصاوير مورد نظر را رندر کنيم . اينکار توسط دستورات زير انجام مي شود :

    D3DDevice.beginscence
    all rendering calls gobetween these two lines '
    D3DDEvice.endscence


    3 - در پايان بايستي صفحه را
    update کنيد :

    D3DDevice.present byval 0,byval 0,0,byval 0
     
  9. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    آموزش DirectX-Graphic قسمت دوم
    موضوع : بدست آوردن مشخصات و تواناييهاي گرافيکي يک سيستم توسط DirectX-Graphic


    1 - شمارش تعداد آداپتورهاي گرافيکي يک سيستم : فرض کنيد متغير nAdapters متغيري از نوع long باشد . همچنين شي D3DADAPTER_IDENTIFIER8 يک ساختار است که اطلاعات مربوط به آداپتور را نگه مي دارد . در اينصورت روتين enumerateAdapters بصورت زير خواهد بود :


    Dim adapterinfo as D3DADAPTER_IDENTIFIER8
    Private Sub EnumerateAdapters
    Dim i as integer
    nadapters=D3D.Getadaptercount


    براي بدست آوردن جزئيات آداپبورها بصورت زير عمل مي کنيم :


    for i=0 to nadapters-1
    D3D.GetadapterIdentifier i ,0,adapterinfo


    نام اين آداپتور بصورت ليستي از کدهاي اسکي است که بايستي آنها را درون يک string قرار دهيم :


    for j=0 to 511
    name=name & chr$(adapterinfo.description(j)) x
    next j
    name=replace(name,chr$(0)," ") x
    end sub


    بنابراين در متغير name نام آداپتور قرار خواهد گرفت .

    ۲ - مشخص کردن نوع Rendering : فرض کنيد شي D3DCAPS8 توانايي rendering آداپتور را نشان دهد . در اينصورت روتين EnumerateDevices بصورت زير خواهد بود :


    Private EnumerateDevices
    On Local Error resume next
    Dim Caps as D3DCAPS8
    deviceindex=0 'For Example
    D3D.Getdevicecaps deviceindex,D3DDEVTYPE_HAL,caps
    if err.number=D3DERR_NOTAVAILABLE then


    اگر آداپتور امکان رندر سخت افزاري نداشته باشد در اينصورت :


    MsgBox("Reference Rasterizer(REF)") x
    else
    MsgBox("Hardware Acceleration(HAL)+Reference Rasterizer(REF)") x
    end if
    end sub


    3 - شمارش تعداد Mode نمايشي آداپتور :
    فرض کنيد در صورت REF بودن امکان رندر ، متغير r=2 و در غيراينصورت r=1
    باشد . همچنين شي D3DDISPLAYMODE اطلاعات مدهاي نمايشي را در خود
    دارد . همچنين فرض کنيد متغير nModes از نوع longباشد . در اينصورت روتين enumeratedispmodes بصورت زير خواهد بود :


    Private Sub EnumerateDispModes(r as Long,n as Long) x
    Dim i as integer
    Dim mode_tmp as D3DDISPLAYMODE
    deviceindex=0 'For Example
    nModes=D3D.Getadaptermodecount(deviceindex) x
    for i=0 to nModes-1
    D3D.EnumAdapterModes(deviceindex,i,mode_tmp) x


    ابتدا Mode ها را به دو گروه ۱۶ بيتي و ۳۲ بيتي تقسيم مي کنيم :


    if mode_tmp.format=D3DFMT_R8G8B8 or mode_tmp=D3DFMT_X8R8G8B8 or mode_tmp=D3DFMT_A8R8G8B8 then


    حال چک مي کنيم که device قابل پذيرش و معتبر است يا نه :


    if D3D.checkdevicetype(deviceindex,r,mode_tmp.format, mode_tmp.format,Flase)>=0 then
    MsgBox(mode_tmp.width & "X" & mode_tmp.height & "32 Bit
    FMT:" & mode_tmp.format ) x & "
    end if
    else
    if D3D.checkdevicetype(deviceindex,r,mode_tmp.format, mode_tmp.format,Flase)>=0 then
    MsgBox(mode_tmp.width & "X" & mode_tmp.height & "16 Bit
    FMT:" & mode_tmp.format ) x & "
    end if
    end if
    next i


    4 - مشخص کردن توانايي هاي آداپتور گرافيکي : فرض کنيد در صورت REF بودن امکان رندر ، متغير r=2 و در غيراينصورت r=1 باشد :


    Private Sub EnumerateHardware(r as long) x
    Dim caps as D3DCAPS8
    D3D.Getdevicecaps deviceindex,r,caps
    If Caps.MaxActiveLights = -1 Then
    MsgBox "Maximum Active Lights: Unlimited" x
    Else
    MsgBox "Maximum Active Lights: " & Caps.MaxActiveLights
    End If
    MsgBox "Maximum Point Vertex size: " & Caps.MaxPointSize
    MsgBox "Maximum Texture Size: " & Caps.MaxTextureWidth & "X" & Caps.MaxTextureHeight
    MsgBox "Maximum Primatives in one call: " & Caps.MaxPrimitiveCount
    If Caps.TextureCaps And D3DPTEXTURECAPS_SQUAREONLY Then
    MsgBox "Textures must always be square" x
    End If
    If Caps.TextureCaps And D3DPTEXTURECAPS_CUBEMAP Then
    MsgBox "Device Supports Cube Mapping" x
    End If
    If Caps.TextureCaps And D3DPTEXTURECAPS_VOLUMEMAP Then
    MsgBox "Device Supports Volume Mapping" x
    End If
    If Caps.DevCaps And D3DDEVCAPS_PUREDEVICE Then
    MsgBox "Device supports the Pure Device Option" x
    End If
    If Caps.DevCaps And D3DDEVCAPS_HWTRANSFORMANDLIGHT Then
    MsgBox "Device supports hardware transform and lighting" x
    End If
    If Caps.DevCaps And D3DDEVCAPS_HWRASTERIZATION Then
    MsgBox "Device can use Hardware Rasterization" x
    End If
    If Caps.Caps2 And D3DCAPS2_CANCALIBRATEGAMMA Then
    MsgBox "Device can Calibrate Gamma" x
    End If
    If Caps.Caps2 And D3DCAPS2_CANRENDERWINDOWED Then
    MsgBox "Device can Render in Windowed Mode" x
    End If
    If Caps.Caps2 And D3DCAPS2_FULLSCREENGAMMA Then
    MsgBox "Device can calibrate gamma in fullscreen mode" x
    End If
    If Caps.RasterCaps And D3DPRASTERCAPS_FOGRANGE Then
    MsgBox "Device supports range based fog calculations" x
    End If
    If Caps.RasterCaps And D3DPRASTERCAPS_ANISOTROPY Then
    MsgBox "Device supports Anisotropic Filtering" x
    End If
    If Caps.RasterCaps And D3DPRASTERCAPS_ZBUFFERLESSHSR Then
    MsgBox "Device does not require a Z-Buffer/Depth Buffer" x
    End If

     
  10. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,318
    تشکر شده:
    2,702
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : یه سری آموزش های فوق العاده جالب برای دوستان عزیز

    آموزش DirectX-Graphic قسمت سوم
    موضوع : رسم اشکال دو بعدي

    مروري بر object هاي DirectX8
    1 - DirectX8 : اين شي ، شي مرکزي براي directX است و به شما امکان دسترسي به توابع و اشيا DirectX را مي دهد .
    ۲ - Direct3D8 : شي اصلي براي کار با محيط سه بعدي مي باشد . هدف از آن ، ساخت Direct3DDevice8 است و همچنين شامل توابعي براي مشخص کردن توانايي هاي کارت گرافيک است .
    ۳ - Direct3DDevice8 : اين شي مسئول ساخت بافتها textures ، مديريت نورها در يک صحنه ، مديريت مواد materials و همچنين render صحنه است . در واقع اين شي ، قلب نمايشي کار شماست .
    4 - D3DX8 : گر چه هميشه نيازي به استفاده از اين شي نيست ، اما اين شي شامل توابعي براي ساخت برنامه هاي userfriendly تر توسط DirectX است . مثلاً ساخت اشيا سه بعدي ( مثل کره ، مکعب و ... ) ، ساخت بافتها ، ساخت سطوح و غيره
    شروع کار براي رسم اشيا دوبعدي
    ابتدا ثابت FVF را تعريف مي کنيم . اين ثابت توصيف " فرمت قابل انعطاف نقطه flexible-vertex-format " براي يک vertex دو بعدي انتقال يافته و ساده شده مي باشد .
    سپس بايستي يک ساختار براي توصيف اين vertex معرفي کنيم :


    Const FVF = D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR
    Private Type TLVERTEX
    X As Single
    Y As Single
    Z As Single
    rhw As Single
    color As Long
    specular As Long
    tu As Single
    tv As Single
    End Type


    فرض کنيد بخواهيم يک مربع را در صفحه رسم کنيم . براي رسم آن نياز به 4 عدد vertex داريم . بنابراين آرايه TriStrip را از نوع TLVERTEX تعريف ميکنيم :


    Dim TriStrip (0 To 3) As TLVERTEX


    حال به سراغ تابع initialize که در درس ۱ با آن آشنا شديد مي رويم و دستورات زير را به آن اضافه مي کنيم :


    Private Function Initialize as boolean
    .
    .
    .


    ابتدا سيستم سايه زني vertex را طوري تنظيم مي کنيم که از FVF استفاده کند .


    D3DDevice.SetVertexShader FVF


    حال سيستم lighting را براي vertex هاي دو بعدي غير فعال مي کنيم زيرا نيازي به آن نداريم :


    D3DDevice.SetRenderState D3DRS_LIGHTING,false


    حال بايستي تابع initializeGeometry را اجرا کنيم . اين تابع را در ادامه توضيح خواهم داد . اگر نتيجه اين تابع true باشد دراينصورت initialize به درستي انجام شده است :


    if initializeGeometry()=true then initialize=true
    end function


    تابع initializeGeometry در اين درس ، تابعي ساده است که تنها آرايه Vertex ها را مقدار دهي مي کند . براي رسم يک مربع نياز به مقداردهي ۴ vertex در جهت عقربه هاي ساعت داريم ( اين مربع شامل ۲ مثلث است )



    Private Function InitialiseGeometry() As Boolean
    On Error GoTo BOut:
    color = RGB(200, 100, 0)
    TriStrip(0) = CreateTLVertex(100, 100, 0, 1, color, 0, 0, 0)
    TriStrip(1) = CreateTLVertex(300, 100, 0, 1, color, 0, 0, 0)
    TriStrip(2) = CreateTLVertex(100, 300, 0, 1, color, 0, 0, 0)
    TriStrip(3) = CreateTLVertex(300, 300, 0, 1, color, 0, 0, 0)
    InitialiseGeometry = True
    Exit Function
    BOut:
    InitialiseGeometry = False
    End Function


    همانطور که مشاهده مي کنيد براي تعريف vertex از تابع CreateTLVERTEX استفاده شده است . اين تابع صرفاً مقادير ساختار TLVERTEX را مقداردهي مي کند :


    Private Function CreateTLVertex(X As Single, Y As Single, Z As Single, rhw As Single, color As Long, specular As Long, tu As Single, tv As Single) As TLVERTEX


    نکته : ضمن اينکه شما مي توانيد مقادير اعشاري floating point را براي مختصاتهاي x و y و z بکار ببريد ، Direct3D مختصاتها را با گردکردن آنها تخمين مي زند و بنابراين ممکنست باعث ايجاد نتايج ناخواسته شود .


    CreateTLVertex.X = X
    CreateTLVertex.Y = Y
    CreateTLVertex.Z = Z
    CreateTLVertex.rhw = rhw
    CreateTLVertex.color = color
    CreateTLVertex.specular = specular
    CreateTLVertex.tu = tu
    CreateTLVertex.tv = tv
    End Function
    حال بايستي تابع Render را بنويسيم :
    Public Sub Render()
    D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0
    D3DDevice.BeginScene
    D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TriStrip(0), Len(TriStrip(0))x
    D3DDevice.EndScene
    D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
    End Sub


    ساختار اصلي براي اجراي توابع فوق بصورت زير است :

    --Main part--
    Initialize
    Do While yourevent=true
    Render
    DoEvents
    Loop