تبلیغات :
آکوستیک ، فوم شانه تخم مرغی، صداگیر ماینر ، یونولیت
دستگاه جوجه کشی حرفه ای
فروش آنلاین لباس کودک
خرید فالوور ایرانی
خرید فالوور اینستاگرام
خرید ممبر تلگرام

[ + افزودن آگهی متنی جدید ]




صفحه 9 از 30 اولاول ... 567891011121319 ... آخرآخر
نمايش نتايج 81 به 90 از 299

نام تاپيک: آموزش گام به گام ویژوال بیسیک6.0

  1. #81
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    حال بايد در يک حلقه با استفاده از تابع twen پيکسلهاي CubeVertices را update کنيم :


    Private Sub UpdateAnimation()x
    Dim I As Integer
    به روز کردن پارامترهاي زمان و جهت'
    If AnimTweenDir = True Then
    AnimTweenFactor = AnimTweenFactor + (((GetTickCount() - LastTimeTweened) / 1000)*1#)
    LastTimeTweened = GetTickCount
    If AnimTweenFactor >= 1# Then
    AnimTweenFactor = 1#
    AnimTweenDir = False
    End If
    Else
    AnimTweenFactor = AnimTweenFactor - (((GetTickCount() - LastTimeTweened) / 1000)*1#)
    LastTimeTweened = GetTickCount
    If AnimTweenFactor <= 0# Then
    AnimTweenFactor = 0#
    AnimTweenDir = True
    End If
    End If
    به روز کردن اطلاعات vertex ها '
    For I = 0 To 7
    CubeVertices(I) = TweenVertices(CubeVerticesSource(I), CubeVerticesDest(I), AnimTweenFactor)x
    Next I
    به روز کردن بافر vertex’
    If D3DVertexBuffer8SetData(VBuffer, 0, Len(CubeVertices(0)) * 8, 0, CubeVertices(0)) = D3DERR_INVALIDCALL Then GoTo Error:
    Exit Sub
    Error:
    Debug.Print “Error occured whilst updating the animation…”x
    End Sub


    زمان پايه انيميشن توسط عبارت زير تنظيم مي شود :
    (((GetTickCount() - LastTimeTweened) / 1000) * 1#)
    همانطور که مي دانيد دو نوع انيميشن وجود دارد : انيميشن بر مبناي frame و انيميشن بر مبناي زمان . در انيميشن بر مبناي frame شماره فريم با يک مقدار ثابت در زمان افزايش مي يابد اما اگر اينکار باعث مي شود کيفيت انيميشن در کامپيوترهاي با سرعت متفاوت تغيير کند . بنابراين انيميشن را بر مبناي زمان توليد کرده ايم . انيميشن هاي بر مبناي زمان بجاي " 1 فريم در هر سيکل " ، " 30 فريم در هر ثانيه " هستند .

    2 – روش دوم از توابع کتابخانه D3DX براي انجام عمل tweening استفاده مي کند و بنابراين بهبودي در سرعت انيميشن نسبت به روش بالا حاصل مي شود . با استفاده از کتابخانه D3DX مي توانيم عمل درون يابي خطي را براي تمام اجزا اصلي يک vertex انجام دهيم . ليست زير توابعي را براي اينکار نشان مي دهد :
    - تابع D3DXVec3Lerp : انجام درون يابي براي موقعيت و نرمال :


    D3DXVec3Lerp( VOut as D3DVECTOR, V1 as D3DVECTOR, V2 as D3DVECTOR, S as Single)x
    - VOut = The result of the interpolation
    - V1 = The source coordinates
    - V2 = The destination coordinates
    - S = The interpolation amount - between, but not limited to, 0.0 - 1.0 scale; where 0 is the source and 1 is the destination


    - تابع D3DXColorLerp : انجام درون يابي براي رنگهاي vertex :


    D3DXColorLerp( COut as D3DCOLORVALUE, C1 as D3DCOLORVALUE, C2 as D3DCOLORVALUE, S as Single)x
    - COut = The resulting colour
    - C1 = The source colour
    - C2 = The destination colour
    - S = The interpolant,

    on a 0.0 to 1.0 scale
    - تابع D3DXVec2Lerp : انجام درون يابي براي مختصاتهاي دوبعدي :


    - VOut = The result of this interpolation
    - V1 = The source coordinates
    - V2 = The destination coordinates
    - S = The interpolant on a 0.0 to 1.0 scale

    - تابع D3DXVec3Hermite : توليد يک مسير منحني که از دو نقطه کنترل عبور مي کند :


    D3DXVec3Hermite( VOut as D3DVECTOR, V1 as D3DVECTOR, T1 as D3DVECTOR, V2 as D3DVECTOR, T2 as D3DVECTOR, S as Single)x
    - VOut = The Result
    - V1 = The Source Coordinate
    - T1 = The Tangent at the Source coordinate, this is the direction and speed the line will leave the source point.
    - V2 = The Destination Coordinate
    - T2 = The Tangent at the Destination coordinate, this is the direction and speed the line will enter the destination point.
    - S = The Interpolant Value

    براي اينکه بتوانيم از کتابخانه D3DX استفاده کنيم بايد توصيف vertex هايمان را تغيير دهيم و بايستي يکسري مقادير ARGB اضافي را به ساختار vertex اضافه کنيم :


    Private Type LITVERTEX
    X As Single
    Y As Single
    Z As Single
    color As Long
    specular As Long
    tu As Single
    tv As Single
    ColorEx As D3DCOLORVALUE
    End Type


    حال تابع tween را بصورت زير مي نويسيم :


    Private Function TweenVertices(Source As LITVERTEX, Dest As LITVERTEX, TweenAmount As Single) As LITVERTEX
    Dim vResult As D3DVECTOR
    Dim vResult2 As D3DVECTOR2
    Tween کردن موقعيت vertex ها ‘
    D3DXVec3Lerp vResult, MakeVector(Source.X, Source.Y, Source.Z), MakeVector(Dest.X, Dest.Y, Dest.Z), TweenAmount
    TweenVertices.X = vResult.X
    TweenVertices.Y = vResult.Y
    TweenVertices.Z = vResult.Z
    Tween کردن اطلاعات texture ’
    D3DXVec2Lerp vResult2, MakeVector2D(Source.tu, Source.tv), MakeVector2D(Dest.tu, Dest.tv), TweenAmount
    TweenVertices.tu = vResult2.X
    TweenVertices.tv = vResult2.Y
    Tween کردن اطلاعات رنگ ‘
    D3DXColorLerp TweenVertices.ColorEx, Source.ColorEx, Dest.ColorEx, TweenAmount
    With TweenVertices.ColorEx
    TweenVertices.color = RGB(.B * 255, .G * 255, .R * 255)x
    End With
    End Function

    نکته اي که بايد به آن توجه کنيد اينست که در تابع فوق براي اشاره به vertex ، يک بردار ساخته شده است ( توسط تابع MakeVector ) .

    3 – روش سوم پر استفاده ترين روش انيميشن سازي است . اگر شما انيميشن هاي پيچيده با تعداد زيادي شي در آن داشته باشيد و اگر بخواهيد تغييرات اشيا را در هر فريم ذخيره کنيد ، به حجم بالايي از منابع ذخيره سازي نياز است . بجاي آن ما با استفاده از يکسري فريم کليدي ، فريمهاي مياني را پيش بيني مي کنيم .
    براي انجام درون يابي فريم کليدي ، بايستي مقدار vertex را در هر فريم کليدي بدانيم و نيز بدانيم هر فريم کليدي در چه زماني ظاهر مي شود . بنابراين بايد براي هر انيميشن چند فايل را بعنوان فريم کليدي ذخيره کنيم .
    در اين درس ما داده هاي کليدي انيميشن را از يکسري فايل load مي کنيم بنابراين تمام ثابتهاي زمان keyframe درون برنامه قرار داده مي شود ( شما مي توانيد خودتان يک ماژول بنويسيد که انيميشن هاي عمومي تر را نيز مديريت کند . اين ماژول بايد قادر باشد که يک فرمت استاندارد فايل را import کند ، اشيا و texture هاي مربوطه را load نمايد و سپس خودش ساخت انيميشن را بطور اتوماتيک انجام دهد و برنامه اصلي فقط روتين render و يا update را فراخواني کند ) . پس از جمع آوري اطلاعات فريم هاي کليدي ، بايد در هر زمان محاسبه کنيم که چه مدتي از شروع انيميشن گذشته است و بنابراين انيميشن در چه موقعيتي قرار دارد . سپس محاسبه مي کنيم که فريم کليدي قبلي و فريم کليدي بعدي چيست همچنين حساب مي کنيم در چه فاصله زماني از ايندو قرار داريم . سرانجام يک درون يابي نرمال را انجام مي دهيم تا اطلاعات فريم جاري بدست آيد و اين اطلاعات را درون يک شي Mesh مي گذاريم و آنرا رندر مي کنيم .
    در درسهاي قبلي در مورد load کردن اشيا از يک فايل X صحبت کردم اما در مورد چگونگي گرفتن اطلاعات vertex از يک شي Mesh صحبت نشد . کتابخانه D3DX براي اينکار دو تابع دارد :
    - تابع D3DXMeshVertexBuffer8GetData : اطلاعات يک شي D3DXMesh را گرفته و در يک آرايه از D3DVERTEX ذخيره مي کند :


    D3DXMeshVertexBuffer8GetData( D3DXMeshobj As Unknown, Offset As Long, Size As Long, Flags As Long, Data As Any) As Long
    - D3DXMeshobj As Unknown = A D3DXMESH object that you want to extract the data from.
    - Offset As Long = How far into the vertex buffer we want to start reading, 0 is the beginning
    - Size As Long = Size of the vertex buffer, this will be Len(D3DVERTEX) * Mesh.GetNumVertices
    - Flags As Long = A combination of the CONST_D3DLOCKFLAGS, leave as 0.
    - Data As Any = The first element in the array that you want the data to be read into, should be an array of D3DVERTEX vertices
    - Return Code As Long = Returns D3D_OK for success, or either of D3DERR_INVALIDCALL or E_INVALIDARG for an error


    - تابع D3DXMeshVertexBuffer8SetData : اطلاعات يک بافر vertex را در يک شي D3DXMesh قرار مي دهد :


    D3DXMeshVertexBuffer8SetData( D3DXMeshobj As Unknown, Offset As Long, Size As Long, Flags As Long, Data As Any) As Long
    - D3DXMeshobj As Unknown = The D3DXMESH object that defines where you want the data to be placed
    - Offset As Long = How far into the Destination vertex buffer you want to place the data
    - Size As Long = The Size of the buffer in bytes, this will be Len(D3DVERTEX) * Mesh.GetNumVertices
    - Flags As Long = A Combination of the CONST_D3DLOCKFLAGS, leave as 0
    - Data As Any = The first element in the array of data you want placed in the mesh's vertex buffer
    - Return Code As Long = D3D_OK for success or D3DERR_INVALIDCALL or E_INVALIDARG for failure


    عمليات انجام انيميشن فريم کليدي بصورت زير است :
    - load کردن اشيا از فايلهاي X به درون شي D3DXMesh
    - استخراج اطلاعات vertex از اين شي
    - انجام درون يابي بين فريمهاي کليدي
    - قرار دادن اطلاعات vertex هاي درون يابي در يک شي D3DXMesh
    فرض مي کنيم که انيميشن ما هميشه از زمان صفر تا زمان n باشد – برحيب ميلي ثانيه – بنابراين مي توانيم از GetTickCount براي توابع زماني خود استفاده کنيم . همچنين يک ساختار را براي هر فريم کليدي بصورت زير تعريف مي کنيم :


    Private Type KeyFrame
    شي load شده از يک فايل’ Mesh As D3DXMesh
    آرايه material براي هر شي’ MatList() As D3DMATERIAL8
    آرايه Texture’ TexList() As Direct3DTexture8
    تعداد material ها و texture هايي که استفاده مي کنيم’ nMaterials As Long
    داده هاي vertex براي اين فريم کليدي’ VertexList() As D3DVERTEX
    موقعيت اين فريم کليدي در انيميشن’ TimeIndex As Long
    End Type


    حال بايد تابعي بنويسيم که اطلاعات را از يک فايل X استخراج کرده و درون فريم کليدي قرار دهد :


    Private Function CreateKeyFrameFromFile(Filename As String, TexturePrefix As String, Time As Long) As KeyFrame
    نام فايل X براي شي سه بعدي: Filename ’
    پوشه اي که اطلاعات texture اين شي در آن قرار دارد : TexturePrefix ’
    انديس زمان براي اين فريم کليدي : Time '
    Dim I As Long
    Dim XBuffer As D3DXBuffer
    Dim TextureFile As String
    Dim hResult As Long
    'خواندن اطلاعات از فايل ورودي به حافظه
    Set CreateKeyFrameFromFile.Mesh = D3DX.LoadMeshFromX(Filename, D3DXMESH_MANAGED, D3DDevice, Nothing, XBuffer, CreateKeyFrameFromFile.nMaterials)x
    توليد material ها و texture ها ‘
    ReDim CreateKeyFrameFromFile.MatList(CreateKeyFrameFromF ile.nMaterials) As D3DMATERIAL8
    ReDim CreateKeyFrameFromFile.TexList(CreateKeyFrameFromF ile.nMaterials) As Direct3DTexture8
    For I = 0 To CreateKeyFrameFromFile.nMaterials - 1
    D3DX.BufferGetMaterial XBuffer, I, CreateKeyFrameFromFile.MatList(I)x
    CreateKeyFrameFromFile.MatList(I).Ambient = CreateKeyFrameFromFile.MatList (I).diffuse
    TextureFile = D3DX.BufferGetTextureName(XBuffer, I)x
    If TextureFile <> "" Then
    Set CreateKeyFrameFromFile.TexList(I) = D3DX.CreateTextureFromFileEx(D3DDevice, TexturePrefix & TextureFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
    D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0)x
    End If
    Next I
    استخراج داده هاي vertex’
    ReDim CreateKeyFrameFromFile.VertexList(CreateKeyFrameFr omFile.Mesh.GetNumVertices) As D3DVERTEX
    hResult = D3DXMeshVertexBuffer8GetData(CreateKeyFrameFromFil e.Mesh, 0, Len(CreateKeyFrameFromFile.VertexList(0)) * reateKeyFrameFromFile.Mesh.GetNumVertices, 0, CreateKeyFrameFromFile.VertexList(0))
    CreateKeyFrameFromFile.TimeIndex = Time
    End Function


    در تابع Initialize خطوط زير را براي ساخت فريم هاي کليدي اضافه مي کنيم :


    nKeyFrames = 4
    kfAnimLength = 2500
    AnimLastStartAt = GetTickCount()x
    ReDim kfAnim(nKeyFrames - 1) As KeyFrame
    kfAnim(0) = CreateKeyFrameFromFile(App.Path & "\frame0.x", App.Path & "\", 0)x
    kfAnim(1) = CreateKeyFrameFromFile(App.Path & "\frame1.x", App.Path & "\", kfAnimLength * (1 / 3))x
    kfAnim(2) = CreateKeyFrameFromFile(App.Path & "\frame2.x", App.Path & "\", kfAnimLength * (2 / 3))x
    kfAnim(3) = CreateKeyFrameFromFile(App.Path & "\frame3.x", App.Path & "\", kfAnimLength)x
    kfCurrent = CreateKeyFrameFromFile(App.Path & "\frame0.x", App.Path & "\", 0)


    دقت کنيد که از يک انديس زمان براي ساخت فريم هاي کليدي استفاده شده است .
    حال بايد کدي براي نمايش دادن انيميشن بنويسيم . ابتدا بايد به روشي تغييرات فريمها را کنترل کنيم :


    For I = 0 To nKeyFrames - 2
    If CurrentTimeIndex >= kfAnim(I).TimeIndex Then
    PrevFrame = I
    NextFrame = I + 1
    End If
    Next I


    سپس بايد با توجه به زمان index دو فريم کليدي و زمان جاري ، پارامتر درون يابي را محاسبه کنيم :


    sTime = kfAnim(PrevFrame).TimeIndex
    eTime = kfAnim(NextFrame).TimeIndex
    cTime = CurrentTimeIndex
    eTime = eTime - sTime
    cTime = cTime - sTime
    sTime = sTime - sTime
    InterpolateAmount = cTime / eTime


    سپس بايد بر اساس اين پارامتر عمل درون يابي را روي داده هاي vertex انجام دهيم :


    For I = 0 To kfCurrent.Mesh.GetNumVertices
    'درون يابي مختصاتها
    D3DXVec3Lerp vTemp3D, MakeVector(kfAnim(PrevFrame).VertexList(I).X, kfAnim(PrevFrame).VertexList(I).Y, _
    kfAnim(PrevFrame).VertexList(I).Z), MakeVector(kfAnim(NextFrame).VertexList(I).X, kfAnim(NextFrame).VertexList(I).Y, _
    kfAnim(NextFrame).VertexList(I).Z), InterpolateAmount
    kfCurrent.VertexList(I).X = vTemp3D.X
    kfCurrent.VertexList(I).Y = vTemp3D.Y
    kfCurrent.VertexList(I).Z = vTemp3D.Z

    'درون يابي نرمالها
    D3DXVec3Lerp vTemp3D, MakeVector(kfAnim(PrevFrame).VertexList(I).nx, kfAnim(PrevFrame).VertexList(I).ny, _
    kfAnim(PrevFrame).VertexList(I).nz), MakeVector(kfAnim(NextFrame).VertexList(I).nx, kfAnim(NextFrame).VertexList(I).ny, _
    kfAnim(NextFrame).VertexList(I).nz), InterpolateAmount
    kfCurrent.VertexList(I).nx = vTemp3D.X
    kfCurrent.VertexList(I).ny = vTemp3D.Y
    kfCurrent.VertexList(I).nz = vTemp3D.Z

    'درون يابي اطلاعات بافت
    D3DXVec2Lerp vTemp2D, MakeVector2D(kfAnim(PrevFrame).VertexList(I).tu, kfAnim(PrevFrame).VertexList(I).tv), _
    MakeVector2D(kfAnim(NextFrame).VertexList(I).tu, kfAnim(NextFrame).VertexList(I).tv), InterpolateAmount
    kfCurrent.VertexList(I).tu = vTemp2D.X
    kfCurrent.VertexList(I).tv = vTemp2D.Y
    Next I


    حال بايد داده توليد شده را به فرمت Mesh برگردانيم :


    hResult = D3DXMeshVertexBuffer8SetData(kfCurrent.Mesh, 0, Len(kfCurrent.VertexList(0)) * kfCurrent.Mesh.GetNumVertices, 0, kfCurrent.VertexList(0))x


    با استفاده از روش فوق مي توانيد هر تعداد فريم کليدي را به انيميشنتان اضافه کنيد . اشکالي که روش فوق دارد اينست که اطلاعات texture براي تمام فريمهاي کليدي جداگانه ذخيره شده است در حاليکه texture در تمام فريمها ثابت است . در درسهاي بعدي از روشي بنام texture pooling استفاده مي کنيم تا تنها يک کپي از texture ها نگهداري کنيم .

  2. #82
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    API هاي ويندوز و طرز استفاده آنها در وی بی
    امروز قصد دارم در مورد API هاي ويندوز و چگونگي استفاده از آنها در ويژوال بيسيک بطور خلاصه توضيح دهم و همچنين دو مثال پراستفاده را نيز در اين زمينه بيان کنم که عبارتند از چگونگي پخش فايلهاي Wav و ساخت يک تايمر با دقت بالا :

    ۱ - آشنايي با 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 برنامه ها استفاده کرد . بعبارت ديگر مي توان زمان اجراي يکسري دستورات خاص را بدست آورد .

  3. #83
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    کار با رجيستری در ويژوال بيسيک - قسمت 1و2و3و4
    رجيستري چيست ؟
    سيستم عامل ويندوز تنظيمات سخت افزاري و نرم افزاري خود را بطور مرکزي در يک بانک اطلاعاتي با ساختار سلسله مراتبي ذخيره مي کند که رجيستري نام دارد . رجيستري جايگزيني براي بسياري از فايلهاي پيکربندي 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 .

  4. #84
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    آموزش DirectXAudio - بخش 1و2و3و4
    موضوع : پخش افکتهاي صوتی در برنامه هاي مالتي مديا

    مقدمه : در سلسله مباحث DirectXAudio شما تکنيکهاي لازم براي اضافه کردن موزيک و افکتهاي صوتي سريع و ديناميک را به بازيها و برنامه هاي مالتي مديا خواهيد آموخت . DirectXAudio جايگزيني براي بخشهاي DirectSound ، DirectSound3D و DirectMusic موجود در DirectX 7 مي باشد و داراي امکانات بهتر و سريعتری بوده و برنامه نويسي آن نيز ساده تر است .
    در اولين درس از DirectXAudio چگونگي پخش افکتهاي صوتي را در برنامه هايتان خواهيد آموخت .

    Initial کردن DirectSound :
    DirectSound اولين مبحثي است که آنرا توضيح خواهم داد . گرچه DirectXAudio يک نام عمومي براي امکانات صوتي DirectX8 مي باشد اما بين Sound و Music تفاوت وجود دارد .
    DirectSound با پخش افکتهاي صوتي ارتباط دارد . DirectSound همانند Direct3D از يکسري device سخت افزاري و نرم افزاري استفاده مي کند و افکتهاي صوتي در يکسري بافر ذخيره مي شوند .
    اولين قدم براي برپاسازي DirectSound ، اضافه کردن کتابخانه DirectX8 به پروژه تان مي باشد . قدم بعدي تعريف متغيرها و object هاي موردنياز است . براي استفاده از DirectSound به متغيرهاي زير نياز داريم :

    Private DX As DirectX8
    Private DS As DirectSound8
    Private DSBuffer As DirectSoundSecondaryBuffer8
    Private DSEnum As DirectSoundEnum8
    Private bLoaded As Boolean


    DirectX شي کنترل کننده مرکزي است . DirectSound8 واسط مراقب براي تمام interface هاي پخش صدا است . DirectSoundSecondaryBuffer8 داده audio واقعي را براي پخش ذخيره مي کند . DirectSoundEnum8 اجازه مي دهد که اطلاعاتي را در مورد device هاي سخت افزاري/نرم افزاري استخراج کنيد و متغير bLoaded يک flag وضعيت مي باشد .
    حال در برنامه بايد ليست تمام device هاي در دسترس را مشخص کنيم . ( اين امر کاملاً امکان پذير است که يک کامپيوتر بيش از يک device براي DirectSound داشته باشد ) :

    Private Sub Form_Load()x
    bLoaded = False
    Dim I As Long
    Set DX = New DirectX8
    Set DSEnum = DX.GetDSEnum
    For I = 1 To DSEnum.GetCount
    MsgBox(DSEnum.GetDescription(I))x
    Next I
    End Sub


    فرض کنيم که يکي از device هاي شناخته شده را انتخاب کرديم . حال بايستي device را واقعاً برپا کنيم :

    If bLoaded Then
    Set DSBuffer = Nothing
    Set DS = Nothing
    Set DX = Nothing
    End If
    Dim DSBDesc As DSBUFFERDESC
    Set DX = New DirectX8
    Set DS = DX.DirectSoundCreate(DSEnum.GetGuid(devicenumber)) x
    DS.SetCooperativeLevel frmMain.hWnd, DSSCL_NORMAL


    متغير devicenumber شماره device اي است که شما مي خواهيد با آن کار کنيد . DSBDesc فايل صوتي شما را توصيف مي کند .
    --------------------------------

    موضوع : پخش افکتهاي صوتی در برنامه هاي مالتي مديا

    ساخت بافر و play کردن آن : تاکنون ما توانستيم DirectSound را initial کنيم . همانطور که می دانيد در تمام component های DirectX داده ها در يکسری بافر ذخيره می شوند . در مورد DirectSound نيز ما يک بافر با نام DirectSoundSecondaryBuffer8 می سازيم و داده های صوتی را در آن قرار می دهيم . برخی پارامتر ها هستند که بايد برای بافر تنظيم شوند مثل : stereo يا mono بودن بافر ، ۸ بيتی يا ۱۶ بيتی بودن بافر ، فرکانس صوتی ( 22khz ، 44khz و غيره ) . اگر اين پارامترها را مشخص نکنيم DirectSound از اطلاعات فايل صوتی استفاده می کند .
    در يک کاربرد ساده ، ما تنها يک بافر صوتی از يک فايل ايجاد می کنيم اما امکان ايجاد چندين بافر بطور همزمان و نيز پخش چندين صدا بطور همزمان نيز وجود دارد :


    DSBDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME
    Set DSBuffer = DS.CreateSoundBufferFromFile(App.Path & "\Sample.wav", DSBDesc)x
    MsgBox "SOUND BUFFER CREATED:"x
    MsgBox "Buffer Size: " & DSBDesc.lBufferBytes & "bytes (" & Round(DSBDesc.lBufferBytes / 1024, 3) & "kb)"x
    MsgBox "Buffer Channel Count:" & DSBDesc.fxFormat.nChannelsIIf(DSBDesc.fxFormat.nCh annels = 1, " (Mono)", " (Stereo)")x
    MsgBox "Buffer Bits per channel: " & DSBDesc.fxFormat.nBitsPerSample & " bits"x


    در بالا يک بافر صوتی ايجاد شده و اطلاعات صدا از فايل به بافر load شده است .
    حال بايستی داده صوتی موجود در بافر را play کنيم :
    دستور لازم برای Play کردن بافر بصورت loop :


    DSBuffer.Play DSBPLAY_LOOPING


    دستور لازم برای Play کردن بافر بدون loop :


    DSBuffer.Play DSBPLAY_DEFAULT


    دستورات لازم برای Stop کردن بافر :


    DSBuffer.Stop
    DSBuffer.SetCurrentPosition 0


    دستور لازم برای Pause کردن بافر :


    DSBuffer.Stop


    تنظيم خصوصيات بافر : سه خصوصيت وجود دارد که در مورد بافر تنظيم می شود pannig ، volume و frequency
    محدوده مقادير pannig بين اعداد زير است :
    DSBPAN_LEFT = -10,000
    DSBPAN_CENTER = 0
    DSBPAN_RIGHT = 10,000
    توسط متد SetPan می توان pannig بافر را تنظيم کرد :


    DSBuffer.SetPan yourValue


    DirectSound صدا را تقويت نمی کند بلکه آنرا تضعيف می نمايد بنابراين ماکزيمم volume عبارت است از volume ای که فايل صوتی با آن ضبط شده است . بعبارت ديگر محدود مقادير volume بين اعداد زير است :
    DSBVOLUME_MAX = 0
    DSBVOLUME_MIN = -10000
    توسط متد SetVolume می توان volume بافر را تنظيم کرد :


    DSBuffer.SetVolume yourValue


    محدود فرکانسی DirectSound عبارت است از :
    DSBFREQUENCY_MIN = 100 (hz)x
    DSBFREQUENCY_MAX = 100000 (hz) = 100khz x
    توسط متد SetFrequency می توان فرکانس بافر را تنظيم کرد :


    DSBuffer.SetFrequency yourValue


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

    موضوع : پخش موزيک توسط DirectMusic

    مقدمه :

    در اولين درس از آموزش DirectXAudio با چگونگي پخش افکتهاي صوتي آشنا شديد . اکنون اين توانايي را داريد که يک engine ساده صوتي بنويسيد . در اين بخش مباني پخش موزيک را فرا خواهيد گرفت . پس از اين درس شما مي توانيد يک ماژوال براي پخش موزيکهاي پس زمينه و افکتهاي صوتي براي برنامه هايتان ايجاد کنيد .

    Initil کردن DirectMusic8 :

    قبل از هر کار بايستي ماژول DirectMusic8 را مقداردهي اوليه کنيد . اينکار بصورت زير انجام مي شود :


    Option ExplicitImplements DirectXEvent8
    Private oDX As DirectX8
    Private oDMPerf As DirectMusicPerformance8
    Private oDMLoader As DirectMusicLoader8
    Private oDMSeg As DirectMusicSegment8

    Dim dmParams As DMUS_AUDIOPARAMS
    Set oDX = New DirectX8
    Set oDMPerf = oDX.DirectMusicPerformanceCreate
    Set oDMLoader = oDX.DirectMusicLoaderCreate
    oDMPerf.InitAudio frmMain.hWnd, DMUS_AUDIOF_ALL, dmParams, Nothing, DMUS_APATH_DYNAMIC_STEREO, 128
    oDMPerf.SetMasterAutoDownload True


    شي DirectMusicLoader8 کمک مي کند تا موزيک درون بافر load شود .
    شي DirectMusicSegment8 مموزيکي را که بايد پخش شود ذخيره مي کند .
    کد فوق کافي است يکبار زمانيکه برنامه آغاز مي شود ، اجرا گردد .
    اکنون ما يک واسط مقدار دهي شده از DirectMusic داريم اما قبل از اينکه موزيک را Load کرده و پخش کنيم چگونگي terminate کردن DirectMusic را در زير مي بينيد :


    If ObjPtr(oDMSeg)Then Set oDMSeg = Nothing
    If ObjPtr(oDMLoader)Then Set oDMLoader = Nothing
    If Not (oDMPerf Is Nothing) Then
    oDMPerf.CloseDown
    Set oDMPerf = Nothing
    End If
    If ObjPtr(oDX) Then Set oDX = Nothing



    پيغامها :

    در برخي از component هاي DirectX8 مثل Input , Sound , Music و Play برنامه شما بايستي يک سيستم messaging را برپا کند تا DirectX زمان وقوع برخي رخدادهاي خاص را بشما گزارش دهد . اين مطلب بخصوص زمانيکه يک موزيک را پخش مي کنيد مفيد است براي مثال مي تواند زمان خاتمه يافتن موزيک را به شما اطلاع دهد و آنگاه شما مي توانيد قطعه موزيک بعدي را پخش کنيد .
    پيغامها توسط يک سيستم callback انجام مي شوند . کد زير را در تابع InitDMusic تان پس از initial کردن DirectMusic8 قرار دهيد :


    oDMPerf.AddNotificationType DMUS_NOTIFY_ON_SEGMENT
    hEvent = oDX.CreateEvent(Me)x
    oDMPerf.SetNotificationHandle hEvent


    اولين سطر به DirectMusic مي گويد چه نوع پيغامهايي را مي خواهيد به برنامه تان بفرستد . چندين نوع پيغام وجود دارد :
    DMUS_NOTIFY_ON_SEGMENT = اطلاعات موزيک فعلي ( شروع پخش ، پايان پخش و غيره )
    DMUS_NOTIFY_ON_CHORD = اطلاعات تغيير chord موزيک
    DMUS_NOTIFY_ON_COMMAND = زمانيکه يک event فرماني صدا زده شود .
    DMUS_NOTIFY_ON_MEASUREANDBEAT = اطلاعات beat/measure مربوط به موزيک فعلي
    DMUS_NOTIFY_ON_PERFORMANCE = که event مربوط به سطح performance می باشد .
    DMUS_NOTIFY_ON_RECOMPOSE = که recomposition event می باشد .
    آخرين بخش از پيغام دهي ، تابع اصلي آن مي باشد . همانطور که در بخش Initial کردن DirectMusic ديديد يک توصيف بصورت Implements DirectXEvent8 داشتيم . بخش اصلي تابع callback مربوط به DirectXEvent8 ، شامل يک select case است که بين پيغامهاي مختلف سوئيچ می کند :


    Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long)x
    If eventid = hEvent Then
    Dim dmMSG As DMUS_NOTIFICATION_PMSG
    If Not oDMPerf.GetNotificationPMSG(dmMSG) Then
    Else
    Select Case dmMSG.lNotificationOption
    Case DMUS_NOTIFICATION_SEGABORT
    Case DMUS_NOTIFICATION_SEGALMOSTEND
    Case DMUS_NOTIFICATION_SEGEND
    Case DMUS_NOTIFICATION_SEGLOOP
    Case DMUS_NOTIFICATION_SEGSTART
    Case Else
    End Select
    End If
    End If
    End Sub



    پخش موزيک / متوقف کردن موزيک :

    براي پخش يک موزيک ابتدا بايستي آنرا load کنيد . اينکار توسط کد زير انجام مي شود :


    oDMLoader.SetSearchDirectory App.Path & "\"x
    Set oDMSeg = oDMLoader.LoadSegment(App.Path & FILENAME)oDMSeg.SetStandardMidiFile


    DirectMusic تنها چهار نوع فرمت صوتي را مي پذيرد : WAV ، MID ، RMI و SEG .
    براي پخش فايلهاي MP3 بايستي از DirectXShow استفاده کنيد که آنرا در درسهاي بعدي خواهيد ديد .
    اکنون که داده هاي فايل صوتي درون بافر load شد مي توانيد آنرا پخش کنيد :


    oDMSeg.SetRepeats 0
    oDMPerf.PlaySegmentEx oDMSeg, DMUS_SEGF_DEFAULT, 0


    تعداد پخش شدن فايل را با متد SetRepets تنظيم کنيد . اگر اين مقدار صفر باشد ، آهنگ تنها يکبار پخش مي شود و اگر 1- باشد بطور ممتد پخش خواهد شد .
    براي متوقف کردن موزيک از کد زير استفاده کنيد :


    oDMPerf.StopEx oDMSeg, 0, DMUS_SEGF_DEFAULT


    براي تنظيم ميزان صدا از متد SetMasterVolume استقاده کنيد :


    oDMPerf.SetMasterVolume yourvalue


    رنج صدا بين 20+ دسی بل تا 200- دسي بل است .
    براي تنظيم Tempo از متد SetMasterTempo استفاده کنيد :


    oDMPerf.SetMasterTempo yourvalue/ 100


    بطور نرمال tempo برابر 1 مي باشد . عدد 2 سرعت را دو برابر مي کند و عدد 0 موزيک را قطع مي کند .
    -------------------------------

    موضوع : ايجاد صدای سه بعدی توسط 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

  5. #85
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    آشنايي با کتابخانه Windows Packet Capture - بخش 1,2,3,4
    مقدمه :

    برای آشنايي با مبانی شبکه های TCP/IP به بحث مروری بر TCP/IP مراجعه کنيد .

    معرفی :

    کتابخانه WinPcap يک معماری برای استخراج Packet های TCP/IP و آناليز شبکه در محيطهای ۳۲ بيتی ويندوز می باشد . اين کتابخانه شامل سه بخش است :

    ۱ - يک ----- Packet در سطح هسته سيستم عامل ( Kernel )

    ۲ - يک کتابخانه dll سطح پايين ( low-level ) با نام packet.dll

    ۳ - يک کتابخانه مستقل از سيستم عامل و سطح بالا ( high-level ) با نام wpcap.dll

    ----- packet يک درايور دستگاه ( device driver ) است که به ويندوزهای ۹۵ ، ۹۸ ، ME ، NT و ۲۰۰۰ قابليت استخراج و capture کردن و نيز ارسال داده خام ( raw data ) از يک کارت شبکه را می دهد . همچنين اين امکان را دارد که packet های capture شده را در يک بافر ذخيره کند و يا آنها را ----- نمايد .
    packet.dll يک API است که بمنظور دسترسی مستقيم به عملکرد درايور packet استفاده می شود . بنابراين packet.dll يک واسط برنامه نويسی مستقل از سیستم عامل های مايکروسافت را مهيا می کند .
    Wpcap.dll مجموعه ای از ابزارهای سطح بالای اصلی برای capture را مهيا می کند که اين توابع با کتابخانه libpcap ( کتابخانه capture در سيستم عامل UNIX ) سازگار می باشند . اين توابع اجازه capture کردن packet ها را با روشی مستقل از سخت افزار شبکه و مستقل از سيستم عامل مهيا می کنند .

    دريافت کتابخانه WinPcap :

    نسخه WinPcap 2.2 :
    برای دريافت برنامه auto-installer ( شامل درايور و DLL های مربوطه ) برای سيستم هایWindows 95/98/ME/NT/2000 به آدرس زير مراجعه کنيد :
    WinPcap auto-installer (driver +DLLs)
    برای دريافت بسته توسعه دهنده اين کتابخانه که شامل برنامه های نمونه ايجاد شده توسط packet capture driver و packet.dll و libpcap است ، به آدرس زير مراجعه کنيد :
    Developer's pack
    برای دريافت source code کتابخانه WinPcap به آدرس زير مراجعه کنيد :
    WinPcap source code

    =================

    پاسخ به سوالاتی در مورد کتابخانه WinPcap :

    ۱ - WinPcap چگونه روی سيستم نصب می شود ؟
    در صورت اجرای فايل نصب ، فايل درايور و Dll های مربوطه در دايرکتوری سيستم شما کپی می شوند . همچنين در Control Panel بخش Add/Remove Program می توانيد عبارت WinPcap را مشاهده کنيد .

    ۲ - آيا WinPcap 2.2 آخرين نسخه WinPcap است ؟
    خير . آخرين نسخه WinPcap نسخه ۲.۳ می باشد که از آدرس زير قابل دريافت است :
    Support Windows 95/98/ME/NT/2000/XP
    WinPcap auto-installer:driver +DLLs
    Developer's pack
    WinPcap source code
    همچنين WinPcap 3.0 Alpha 4 را می توانيد از آدرس زير دريافت کنيد :
    WinPcap auto-installer:driver +DLLs

    ۳ - چگونه می توان فهميد که WinPcap در حال اجرا روی يک کامپيوتر Win2k/XP است ؟
    در بخش Run دستور msinfo32 را وارد کنيد . سپس در بخش Software Environment و سپس بخش System Drivers بايستی عبارت NPF را ببينيد .

    ۴ - برنامه های بر مبنای WinPcap ( مثل Windump که بعداً در مورد آن صحبت خواهم کرد ) بدرستی اجرا نمی شوند . آيا اشکال از WinPcap است ؟
    برنامه Windump را نصب کنيد . دستور windump -D ليست آداپتورهای مجاز را گزارش می دهد و همچنين نشان می دهد که آيا WinPcap قادر به شناسايی درست سخت افزار شما بوده است يا نه . اگر Windump درست کار کند ، اشکال از برنامه شماست نه از WinPcap .

    ۵ - آيا می توان از WinPcap در اتصالات PPP (‌ اتصالات مودمی ) استفاده کرد ؟
    در ويندوز ۹۵ بخاطر باگی که در NDIS است WinPcap گاهی اوقات اتصال PPP را reset می کند . در ويندوزهای ۹۸ و ME اين مشکل وجود ندارد اما گاهی اوقات قادر به ارسال packet نيست . در ويندوزهای NT/2k/XP نيز برخی مشکلات در فرايند binding وجود دارد که مانع از درست کار کردن درايور پروتکل روی آداپتور WAN می شود . اين مشکل بخاطر درايور PPP با نام ndiswan است که يک واسط استاندارد را برای capture کردن مهيا نمی کند .

    ۶ - Security در WinPcap چگونه است ؟
    مدل Security اين برنامه ضعيف است و نويسندگان اين برنامه درحال کار روی آن هستند .

    ۷ - آيا از WinPcap می توان در محيطهای برنامه نويسی Borland استفاده کرد ؟
    برای اينکه بتوان از امکانات WinPcap در C++ Builder استفاده کرد بايستی توسط برنامه COFF2OMF.EXE که در دايرکتوری Borland وجود دارد ، کتابخانه های Packet.lib و wpcap.lib که بر اساس استانداردهای مايکروسافت ( استاندارد COFF ) هستند را به استاندارد OMF تبديل کنيد مثال : COFF2OMF input.lib output.lib

    ۸ - آيا می توان از WinPcap در ويژوال بيسيک استفاده کرد ؟
    بطور مستقيم نمی توان از اين کتابخانه در VB استفاده کرد . شرکت BeeSync يک کنترل ActiveX با نام PacketX ايجاد کرده که بوسيله آن می توان از تواناييهای WinPcap در ويژوال بيسک يا هر محيط ديگری که Microsoft ActiveX technology را پشتيبانی کند استفاده کرد .

    بحث در مورد اين ActiveX موضوع بخش بعدی اين سلسه مقالات می باشد .

    ۹ - آيا WinPcap می تواند با فايروال کار می کند ؟
    ممکنست گاهی اوقات کار نکند .

    ۱۰ - آيا می توان از WinPcap در جاوا استفاده کرد ؟
    WinPcap بطور مستقيم از جاوا پشتيبانی نمی کند اما در اين آدرس می توانيد يک Java wrapper را برای اينکار دريافت کنيد .

    ۱۱ - آيا WinPcap از device های loopback پشتيبانی می کند ؟
    خير و علت آن بخاطر محدوديتهای ويندوز است .

    ۱۲ - WinPcap از چه سخت افزارهايي پشتيبانی می کند ؟
    NPF device driver طوری توسعه يافته که بتواند با آداپتورهای اترنت درست کار کند اما نمی تواند بدرستی با آداپتورهای PPP WAN ( مودمها ) کار کند . همچنين نبايستی با کارتهای FDDI, ARCNET, ATM و Token Ring مشکلی داشته باشد اما اين امر بطور قطعی تائيد شده نيست . با آداپتورهای Wireless نيز نمی تواند درست کار کند و در بهترين حالت قادرست يک Ethernet emulation را ببيند .

    ۱۳ - آيا می توان توسط WinPcap ، بسته های اطلاعاتی ورودی را Drop کرد ؟
    خير فقط می توان بسته ها را capture کرد .

    ۱۴ - آيا می توان توسط امکانات WinPcap يک Firewall ساخت ؟
    همانطور که در بالا گقته شد WinPcap قابليت Drop کردن بسته ها را ندارد و تواناييهای Filtering در WinPcap تنها روی بسته های sniff شده است . برای جلوگيری کردن از ورود يک بسته به پشته TCP/IP بايستی خودتان يک درايور ميانی ايجاد کنيد .

    ۱۵ - چگونه می توان کاری کرد که WinPcap بطور اتوماتيک در زمان بوت سيستم فعال گردد ؟
    مقدار کليد زير را در رجيستری از 0x3 به 0x2 تغيير دهيد . اين کار فقط در ويندوزهای NTx جواب می دهد :
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Servic es\NPF\Start

    ۱۶ - آيا با کامپايل مجدد سورس WinPcap نتيجه درستی حاصل می شود ؟
    بله اما ابتدا بايستی Service Pack 5 برنامه Microsoft Visual Studio را از سايت مايکروسافت دريافت و آنرا نصب کنيد .

    ۱۷ - آيا درايورهای ديگری بجز WinPcap برای کار با packet های TCP/IPوجود دارد ؟
    بله . برای مثال برنامه Zx Sniffer يک کتابخانه capture کردن packet دارد که مشابه WinPcap است .

    ۱۸ - آيا Document ها و Tutorial های کاملی برای کار با Packet Driver API و Packet.dll و wpcap.dll در ويژوال سی وجود دارد ؟
    بله . برای اينکار می توانيد از مطالب زير استفاده کنيد :
    How to use wpcap.dll
    wpcap specific extensions
    Packet Driver API. How to use the low level capture library
    Instructions and examples of how to write and compile a capture application using libpcap calls or packet driver's (PACKET.DLL) calls
    Compiling WinPcap
    ========================

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

    مقدمه :

    برنامه WinDump نسخه تحت ويندوز برنامه مشهور TcpDump می باشد که در سيستم عامل UNIX وجود دارد . اين برنامه يکی از بهترين ابزارهای Network Sniffer/Analyzer می باشد .
    WinDump کاملاً با TcpDump سازگار می باشد و می توان از آن برای مانيتور کردن ترافيک شبکه بر اساس قوانين مختلف و پيچيده ای که قابل تنظيم هستند ، استفاده کرد .
    WinDump روی سيستم عاملهای 95/98/ME و نيز NT/2000/XP قابل استفاده می باشد .
    WinDump از کتابخانه libpcap موجود در WinPcap استفاده می کند .

    دريافت برنامه :

    برای دريافت نسخه 3.6.2 به آدرس زير مراجعه کنيد :
    WinDump.exe
    WinDump source code
    نکته : قبل از اجرای اين برنامه بايستی برنامه 2.3 WinPcap را روی سيستم خود نصب کنيد .
    برای دريافت نسخه 3.8 alpha به آدرس زير مراجعه کنيد :
    WinDump.exe
    WinDump source code
    نکته : قبل از اجرای اين برنامه بايستی برنامه 3.0 WinPcap را روی سيستم خود نصب کنيد .

    پاسخ به سوالاتی در مورد برنامه WinDump :

    ۱ - چگونه می توان با استفاده از WinDump ليست آداپتورهای شبکه را بدست آورد ؟
    با اجرای دستور WinDump –D
    توسط دستور WinDump –i adaptername می توان WinDump را روی آداپتور خاصی اجرا کرد .

    ۲ - آيا می توان از WinDump روی اتصالات PPP ( اتصالات مودمی ) استفاده کرد ؟
    WinDump از همان device هايي پشتيبانی می کند که WinPcap می کند . به بخش قبل مراجعه کنيد .

    ۳ - چگونه می توان اطلاعاتی در مورد TcpDump بدست آورد ؟
    به آدرس زير مراجعه کنيد :
    [ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ]

    ۴ - با وجود نصب آخرين نسخه برنامه WinDump ، چرا اين برنامه قادر به capture کردن همه packet ها نيست ؟
    توسط سوئيچ B می توانيد سايز بافر درايور را افزايش دهيد برای مثال دستور Windump –B 5000 سايز بافر را ۵ مگابايت می کند . سايز بافر برنامه در حالت عادی 1 مگابايت است .

    ۵ - آيا می توان چندين WinDump را روی يک ماشين اجرا کرد ؟
    بله

    ۶ - چرا WinDump در زمان capture کردن برای مدتی hang می کند ؟
    علت آن فراخوانی تابع gethostbyaddr در برنامه می باشد که برای استخراج host name ها بکار می رود . می توان توسط سوئيچ n- از name resolution جلوگيری کرد .

    ۷ - آيا اطلاعات کاملی در مورد برنامه WinDump وجود دارد ؟
    به آدرس زير مراجعه کنيد :
    WinDump Manual

    ==========================

    مقدمه

    PacketX مجموعه ای از کلاسهای اکتيو ايکس است که امکانات WinPcap را در ويژوال بيسيک و هر زبان برنامه نويسی ديگری که از تکنولوژی Microsoft ActiveX پشتيبانی کند مهيا می کند .
    بطور خلاصه PacketX از WinPcap برای capture کردن و ----- کردن packet های شبکه استفاده می کند . علاوه بر capture استاندارد ، شما می توانيد از PacketX برای گردآوری اطلاعات ترافيک شبکه و ارسال raw packet استفاده کنيد .

    دريافت PacketX

    برای دريافت نسخه 1.3 اين کتابخانه به آدرس زير مراجعه کنيد :
    PacketX 1.3 Download
    قبل از استفاده از PacketX بايستی WinPcap 2.3 را که آدرس آن در بخش قبل گفته شد دريافت و نصب نمائيد .

    استفاده از PacketX

    با يک مثال ساده سعی می کنم روش استفاده از اين کتابخانه را به شما آموزش دهم .
    پس از نصب PacketX وارد محيط ويژوال بيسيک شده و از منوی Project مورد Components را انتخاب کنيد .
    سپس مورد PacketX Type Library را انتخاب کنيد تا به ToolBar اضافه شود .

    اين ActiveX را در فرمتان قرار دهيد و سپس در قسمت properties آن روی Custom کليک نموده و نوع آداپتور را مشخص نمائيد .
    پس از انتخاب آداپتور با کليک روی دکمه Edit می توانيد اطلاعاتی از قبيل مد کاری و ساير بافر و نوع -------- را مشخص نمائيد .
    نام اين شی را نيز PacketX1 می گذاريم .
    در فرمتان دو دکمه به نامهای Start و Stop قرار دهيد . همچنين يک listBox با نام IPList در فرمتان قرار دهيد .
    در کد مربوط به Form_load عبارت زير را بنويسيد :


    PacketX1.Adapter.BPFilter = "port 80"x


    عبارت فوق مشخص می کند که می خواهيم packet های پورت 80 را capture کنيم .
    کد زير را برای event مربوط به کليک شدن دکمه Start بنويسيد :


    PacketX1.start


    کد زير را برای متد OnPacket مربوط به PacketX1 بنويسيد :


    Private Sub PacketX1_OnPacket(ByVal pPacket As PACKETXLibCtl.IPktXPacket)x
    IPList.AddItem (pPacket.DestIpAddress)x
    End Sub


    کد فوق آدرس IP مقصد packet ها را به يک ليست اضافه می کند . شما می توانيد اطلاعات ديگری از قبيل داده موجود در packet ، سايز داده ، آدرس مبدا ، تاريخ ارسال داده و غيره را استخراج کنيد .
    کد زير را برای event مربوط به کليک شدن دکمه Stop بنويسيد :


    PacketX1.stop



    برای اينکه بتوانيد در يک مدت خاص وضعيت دريافت و ارسال packet را بدست آوريد بايد ابتدا توسط دستور زير مد آداپتور را در حالت Statistic قرار دهيد :


    PacketX1.Adapter.Mode=PktXModeStatistics
    PacketX1.Adapter.ReadTimeout=2000 '// 2 sec


    سپس PacketX1 را start نموده و توسط متد OnStatistics اطلاعات مربوطه را استخراج کنيد .

    اطلاعات بيشتر

    برای مشاهده اطلاعات کامل در مورد ساختار PacketX و ماژولهای آن به آدرس زير مراجعه کنيد :
    PacketX Documentation

  6. #86
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    آموزش DirectX Input - بخش 1,2,3
    گرفتن اطلاعات ورودی از کيبرد - ۱

    مقدمه

    Direct Input 8 همانطور که از نامش مشخص است به شما اجازه می دهد که بتوانيد برنامه هايي بنويسيد که توسط هر نوع دستگاه ورودی کنترل شود .
    Direct Input 8 دارای چندين مزيت نسبت به استفاده از کنترلهای ورودی خود ويژوال بيسيک دارد – کنترلهايي مثل Form_KeyUp, Form_KeyDown, Form_MouseMove - و همچنين قابليت کنترل بيشتری نسبت به توابع استاندارد Win32 از قبيل GetCursorPos, GetKeyState دارد .
    Direct Input 8 سريعتر ، کاراتر و قدرتمند تر بوده و برای ساخت بازيها طراحی شده بنابراين باعث کندی برنامه ها نخواهد شد .

    چگونگی کار با Direct Input 8 برای گرفتن ورودی از کيبرد

    دو روش برای استفاده از کيبرد در DirectX8 وجود دارد : روش polling و روش event-based که هر دو دارای مزايا و معايبی هستند .
    بطور کلی در اغلب طراحيها از روش event-based استفاده می شود زيرا کار با آن راحت تر اسن . در اين روش هر پيغام فرستاده شده ازطرف دستگاه ورودی log می شود و برنامه نيازی به هيچگونه پردازشی بمنظور منتظر ماندن برای يک پيغام از طرف ورودی ندارد ، بنابر اين کاراتر است . در روش polling کنترل کمی دقيقتر و راحتر است .
    اگر در مورد برنامه نويسی بر مبنای polling و بر مبنای event اطلاعات کافی نداريد می توانيد از منابع موجود در سايتهايي چون Gamasutra و GameDev استفاده کنيد .

    روش Polling

    مراحل اين روش عبارتند از :

    1 – تعريفات Declerations : يک فرم ايجاد کرده و يک TextBox به نام txtOutput با خصوصيات Multiline ، Locked و Vertical Scroll Bar در آن قرار دهيد . کدهای زير را در بخش کدنويسی اين فرم بنويسيد :

    Private Const UsePollingMethod As Boolean = True
    Private Const UseEventMethod As Boolean = False
    ‘نکته مهم اينست که تنها يکی از دو ثابت فوق بايستی True باشد .
    Private bRunning As Boolean
    ‘اين متغير برای polling استفاده می شود
    Private DX As DirectX8
    Private DI As DirectInput8
    ‘تعريف شی اصلی DirectX و شی DirectInput
    Private DIDevice As DirectInputDevice8
    Private DIState As DIKEYBOARDSTATE
    ‘اين دو شی برای دسترسی به دستگاه ورودی ( کيبرد ) استفاده می شوند
    Private KeyState(0 To 255) As Boolean
    ‘آرايه ای برای تشخيص فشرده شدن کليد
    Private Const BufferSize As Long = 10
    ‘ سايز بافر نگهدارنده event ها . در روش event-based اين مقدار برابر يک و در روش polling برابر 10 تا 20 است ( بسته به سرعت حلقه بازی )
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)x
    ‘ تابع Sleep برای متوقف کردن حلقه polling در صورت بالا بودن نرخ ورودی



    2- مقدار دهی اوليه Initialisation : اين بخش سه مرحله دارد :
    در مرحله اول اشيا و Device ها ساخته می شوند .
    در مرحله دوم تنظيمات مربوط به Device انجام می شود .
    در مرحله سوم به Device می گوئيم که می خواهيم شروع به استفاده از آن کنيم .

    در Form_Load کدهای زير را بنويسيد :

    Me.Show
    Dim I As Long
    Dim DevProp As DIPROPLONG
    Dim DevInfo As DirectInputDeviceInstance8
    Dim pBuffer(0 To BufferSize) As DIDEVICEOBJECTDATA
    If UsePollingMethod And UseEventMethod Then
    MsgBox "You must select only one of the constants before running"x
    Unload Me
    End
    End If

    If UsePollingMethod Then txtOutput.Text = "Using Polling Method" & vbCrLf
    If UseEventMethod Then txtOutput.Text = "Using Event Based Method" & vbCrLf

    ‘مقداردهی اوليه روش انتخاب شده
    Set DX = New DirectX8
    Set DI = DX.DirectInputCreate
    Set DIDevice = DI.CreateDevice("GUID_SysKeyboard")x

    DIDevice.SetCommonDataFormat DIFORMAT_KEYBOARD
    DIDevice.SetCooperativeLevel frmMain.hWnd, DISCL_BACKGROUND Or ISCL_NONEXCLUSIVE

    ‘برپاسازی بافر
    DevProp.lHow = DIPH_DEVICE
    DevProp.lData = BufferSize
    DIDevice.SetProperty DIPROP_BUFFERSIZE, DevProp

    ‘ به دايرکت ايکس می گوئيم که می خواهيم از دستگاه ورودی استفاده کنيم
    DIDevice.Acquire

    ‘استخراج اطلاعاتی در مورد دستگاه ورودی
    Set DevInfo = DIDevice.GetDeviceInfo()x
    txtOutput.Text = txtOutput.Text & "Product Name: " & DevInfo.GetProductName & vbCrLf
    txtOutput.Text = txtOutput.Text & "Device Type: " & DevInfo.GetDevType & vbCrLf
    txtOutput.Text = txtOutput.Text & "GUID: " & DevInfo.GetGuidInstance & vbCrLf


    ‘در صورتی که بخواهيم به برنامه خاتمه بدهيم کدهای زير را می نويسيم
    DIDevice.Unacquire
    Set DIDevice = Nothing
    Set DI = Nothing
    Set DX = Nothing
    Unload Me
    End



    3 – گرفتن ورودی از کيبرد : در اين بخش فرض کنيد بخواهيم يک بازی را در يک حلقه Do-Loop شبيه سازی کنيم . در اين حلقه هر بار فشرده شدن کليدهای کيبرد را چک می کنيم :

    If Not Err.Number Then bRunning = True

    Do While bRunning

    ‘دريافت اطلاعات شامل خواندن وضعيت کيبرد ، خواندن اطلاعات بافر و سپس خطا
    DIDevice.GetDeviceStateKeyboard DIState
    DIDevice.GetDeviceData pBuffer, DIGDD_DEFAULT
    If Err.Number = DI_BUFFEROVERFLOW Then
    Msgbox(“BUFFER OVERFLOW (Compensating)...")x
    GoTo ENDOFLOOP:
    End If
    ‘بررسی فشرده شدن کليدها
    For I = 0 To 255
    If DIState.Key(I) = 128 And (Not KeyState(I) = True) Then
    txtOutput.Text = txtOutput.Text & "{ DOWN } " & KeyNames(CInt(I))& vbCrLf
    txtOutput.SelStart = Len(txtOutput.Text)x
    KeyState(I) = True
    End If
    Next I

    ‘بررسی رها شدن کليد
    For I = 0 To BufferSize
    If KeyState(pBuffer(I).lOfs) = True And pBuffer(I).lData = 0 Then
    KeyState(pBuffer(I).lOfs) = False
    txtOutput.Text = txtOutput.Text & "{ UP } " & KeyNames(CInt(pBuffer(I).lOfs)) & vbCrLf
    txtOutput.SelStart = Len(txtOutput.Text)x
    End If
    Next I

    Sleep (50)x
    DoEvents
    ENDOFLOOP:
    Loop


    در کد فوق يک تابع KeyName وجود دارد که نام کليد فشارداده شده را بر می گرداند . بخشی از اين تابع را در زير می بينيد :


    Function KeyNames(iNum As Integer) As String

    Dim aKeys(0 To 255) As String

    aKeys(1) = "DIK_ESCAPE"
    aKeys(2) = "DIK_1 On main keyboard"x
    aKeys(3) = "DIK_2 On main keyboard"x
    aKeys(4) = "DIK_3 On main keyboard"x
    aKeys(5) = "DIK_4 On main keyboard"x
    aKeys(6) = "DIK_5 On main keyboard"x
    aKeys(7) = "DIK_6 On main keyboard"x
    aKeys(8) = "DIK_7 On main keyboard"x
    aKeys(9) = "DIK_8 On main keyboard"x
    aKeys(10) = "DIK_9 On main keyboard"x
    aKeys(11) = "DIK_0 On main keyboard"x
    aKeys(12) = "DIK_MINUS On main keyboard"x
    aKeys(13) = "DIK_EQUALS On main keyboard"x
    aKeys(14) = "DIK_BACK BACKSPACE"x
    aKeys(15) = "DIK_TAB"x
    aKeys(16) = "DIK_Q"x
    aKeys(17) = "DIK_W"x
    aKeys(18) = "DIK_E"x
    aKeys(19) = "DIK_R"x
    aKeys(20) = "DIK_T"x
    .
    .
    .
    KeyNames = aKeys(iNum)x

    End Function

  7. #87
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    موضوع : کنترل کيبرد با روش Event-Based

    مقداردهی اوليه و مفاهيم اصلی در روش Event-Based مشابه روش Polling است و تنها بايستی ساختار بخش جمع آوری داده و حلقه پردازشی را تغيير دهيم . مراحل کار با روش Event-Based بصورت زير می باشد :

    ۱ - تعاريف و مقداردهی اوليه : در بخش تعاريف دو تعريف جديد بصورت زير داريم :


    Dim hEvent As Long
    Implements DirectXEvent8


    hEvent يک پارامتر هندل برای يک می باشد .
    نکته : زمانی که کليدی فشرده يا رها می شود ، DirectX اين امر با فراخوانی تابعی به اسم DirectXEvent8_DXCallback به برنامه شما اطلاع می دهد . ( اين نوع توابع را Call Back Function گويند ) . اين تابع به برنامه شما می گويد که يک رويداد اتفق افتاده است و بايستی بافرها را چک کند .

    تنها تغييری که در بخش مقداردهی اوليه نياز است ، برپاسازی يک event می باشد :


    If UseEventMethod Then
    hEvent = DX.CreateEvent(frmMain)x
    DIDevice.SetEventNotification hEvent
    End If


    در انتهای برنامه نيز کد زير را برای از بين بردن event اضافه کنيد :


    If hEvent <> 0 Then DX.DestroyEvent hEvent



    ۲ - استفاده از event : برای اين بخش کدهايي را در داخل تابع DirectXEvent8_DXCallback می نويسيم :


    Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long)x
    'متغيرهای موردنياز
    Dim I As Long
    Dim pBuffer(0 To BufferSize) As DIDEVICEOBJECTDATA
    If eventid = hEvent Then
    If DIDevice Is Nothing Then Exit Sub
    'درصورت رخ دادن event داده را از کيبرد می گيريم
    DIDevice.GetDeviceStateKeyboard DIState
    DIDevice.GetDeviceData pBuffer, DIGDD_DEFAULT
    'چک کردن تمام کليدها برای اينکه متوجه شويم چه اتفاقی افتاده است
    For I = 0 To 255
    'عدد ۱۲۸ نشان دهنده key_down event است .
    If DIState.Key(I) = 128 Then
    If pBuffer(0).lData = 128 Then
    txtOutput.Text = txtOutput.Text & "{ DOWN } " & KeyNames(CInt(I)) & vbCrLf
    End If
    End If
    'کد فوق برای بررسی فشرده شدن يک کليد بود . کد زير رها شدن کليد را بررسی می کند
    If (pBuffer(0).lData = 0 And pBuffer(0).lOfs = I) Then
    txtOutput.Text = txtOutput.Text & "{ UP }" & KeyNames(CInt(I)) & vbCrLf
    End If

    txtOutput.SelStart = Len(txtOutput.Text)x
    Next I
    End If
    End Sub

  8. #88
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    موضوع : کنترل ماوس با DirectX Input

    مقدمه :

    برای استفاده از ماوس در برنامه های مالتی مديا و بازيها همانند کی برد می توانيم از امکانات دايرکت ايکس استفاده کنيم . روش کنترل ماوس توسط DirectX Input بسيار ساده بوده و مشابه کنترل کيبرد می باشد بنابراين درصورتی که دو درس گذشته را نخوانده اين پيشنهاد می کنم ابتدا آنها را مطالعه کنيد .

    برپاسازی Device :

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


    Private Const mSpeed As Single = 2
    Private Const BufferSize As Long = 10
    Private mPosition As Point

    س
    mSpeed مقدار سرعت حرکت کرسر ماوس را مشخص می کند .
    BufferSize سايز بافر DI می باشد .
    mPosition موقعيت جاری کرسر ماوس را نشان می دهد .

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


    Set DIDevice = DI.CreateDevice("guid_SysMouse")x
    Call DIDevice.SetCommonDataFormat(DIFORMAT_MOUSE)x
    Call DIDevice.SetCooperativeLevel(frmMain.hWnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE)x


    تفاوت عمده کدهای فوق با کدهای مقداردهی اوليه در بخش کی برد آنست که cooperativelevel تغيير کرده است . در اينجا گفته شده که ما می خواهيم از ماوس بصورت انحصاری در برنامه استفاده کنيم . اين حالت برای برنامه های window-base مناسب نيست و بهترست از آن در بازيهايي که بصورت full screan هستند استفاده کنيد .

    خواندن ورودی از ماوس :

    در اين بخش می توانيد هم از روش polling و هم event-based استفاده کنيد . نکته مهمی که در اينجا وجود دارد آنست که Direct Input فقط حرکت داده شدن ماوس و کليک شدن يک دکمه را به شما اطلاع می دهد و برای تشخيص حالتهای double click و single click خودتان بايستی کد بنويسيد برای مثال اگر فاصله زمانی بين دو کليک کمتر از ۴۰ ميلی ثانيه باشد آنگاه اين يک double click بوده است .
    کد زير حرکت داده شدن ماوس و کليک يکی از سه دکمه آنرا اطلاع می دهد :


    Dim DevData(1 To BufferSize) As DIDEVICEOBJECTDATA
    Dim nEvents As Long
    Dim I As Long
    nEvents = DIDevice.GetDeviceData(DevData, DIGDD_DEFAULT)x
    For I = 1 To nEvents
    Select Case DevData(I).lOfs
    Case DIMOFS_X
    mPosition.x = mPosition.x + (DevData(I).lData * mSpeed)x
    If mPosition.x < 0 Then mPosition.x = 0
    If mPosition.x > frmMain.ScaleWidth Then mPosition.x = frmMain.ScaleWidth
    imgCursor.Top = mPosition.y
    imgCursor.Left = mPosition.x
    lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
    Case DIMOFS_Y
    mPosition.y = mPosition.y + (DevData(I).lData * mSpeed)x
    If mPosition.y < 0 Then mPosition.y = 0
    If mPosition.y > frmMain.ScaleHeight Then mPosition.y = frmMain.ScaleHeight
    imgCursor.Top = mPosition.y
    imgCursor.Left = mPosition.x
    lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
    Case DIMOFS_BUTTON0
    label(2).Caption = "Button 0 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON1
    label(3).Caption = "Button 1 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON2
    label(4).Caption = "Button 2 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON3
    label(5).Caption = "Button 3 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    End Select
    Next I


    برای استفاده از کد فوق در روش Polling ، بايستی آنرا در يک حلقه Do while-Loop قرار دهيد .
    برای استفاده از کد فوق در روش Event-Based ، بايستی آنرا درون روتين DirectXEvent8_DXCallback قرار دهيد

  9. #89
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    TAPI در ويژوال بيسيک - درس 1و 2و 3و 4و 5و 6و 7
    TAPI در ويژوال بيسيک - درس 1و 2و 3و 4و 5و 6و 7
    TAPI چيست ؟

    TAPI يا Telephony API يک کتابخانه استاندارد برای کار با مودم و نوشتن برنامه های تلفنی می باشد . برای نمونه می توان از برنامه های Phone Dialer ( شماره گير تلفن ) ، برنامه شبکه سازی تلفنی ( Dialup Networking ) ، برنامه تشخيص پالس مودم برای ضبط اطلاعات وارد شده از طرف کاربران و کاربردهای ديگر در اين زمينه نام برد . اين کتابخانه به شما کمک کمک می کند تا بدون درگير شدن با برنامه نويسی سخت افزار مودم و درايور آن بطور مستقيم بتوانيد برنامه های کاربردیي در اين زمينه بنويسيد .
    مروری بر Microsoft Telephony :

    Telephony امکان مجتمع سازی کامپيوترها با دستگاههای ارتباطی و شبکه ها را فراهم نموده است . معمولاً دستگاه ارتباطی يک مودم و خط ارتباطی نيز شبکه PSTN ( شبکه عمومی تلفن سوئيچينگ ) می باشد . برخی از کاربردهای Telephony عبارتند از :

    ۱ - کنفرانسهای مالتی مديا بصورت Multicast
    ۲ - VoIP
    ۳ - مرکز پاسخ گويي اتوماتيک
    ۴ - تماس تلفنی از طريق کامپيوتر روی شبکه PSTN

    دياگرام زير معماری Microsoft Telephony را نشان می دهد :
    برنامه های TAPI :

    برای نوشتن برنامه های کاربردی با استفاده از TAPI بايستی ابتدا در مورد سطح سرويسی که می خواهيم ارائه دهيم تصميم گيری کنيم . برای مثال برای نوشتن يک برنامه شماره گير تلفن نياز به استفاده کامل از TAPI نيست و می توان از قابليتهای خود ويندوز در اين زمينه استفاده کرد ( Assisted Telephony ) . در بخشهای بعدی در مورد سطوح مختلف سرويس در TAPI بيشتر صحبت خواهم کرد .
    دومين مطلبی که بايد مورد توجه قرار داد اينست که می خواهيم از TAPI 2.x استفاده کنيم يا از TAPI 3.x . تفاوت ايندو آنست که TAPI ورژن ۲ يک API برمبنای C است در حاليکه ورژن ۳ آن بر مبنای تکنولوژی COM می باشد . در بخشهای بعدی مطالب بيشتری در مورد تفاوتهای اين دو نسخه بيان خواهم کرد .
    بخشهای اصلی يک برنامه کامل TAPI عبارتند از :

    ۱ - TAPI Initialization : شامل load کردن TAPI dll ، اتصال به TAPI Server ، مذاکره در مورد ورژن TAPI و برپاسازی سيستم اطلاع رسانی event می باشد .

    ۲ - Session Control : مقداردهی اوليه ، دريافت و کنترل تماسها

    ۳ - Device Control : دريافت و تنظيم اطلاعات دستگاه

    ۴ - Media Control : تشخيص و يا توليد تونها و ارقام ، کنترل stream

    ۵ - TAPI Shutdown : آزاد سازی منابع
    مقداردهی اوليه TAPI :

    عملکرد درست اجزای TAPI نياز به برپاسازی محيط ارتباطی روی کامپيوتر مورد نظر دارد . مراحل اين امر عبارتند از :

    ۱ - نصب TAPI : زمانيکه سخت افزار و يا نرم افزار برای اولين بار به کامپيوتر اضافه می شود انجام می گيرد . جزئيات کار به سيستم عامل و نرم افزار بستگی دارد .

    ۲ - مقداردهی ابتدائی : ساخت اشيا و مسيرهای ارتباطی

    ۳ - مذاکره در مورد ورژن TAPI : برای اطمينان از اينکه اجزای TAPI قادر به تبادل داده ها باشند .

    ۴ - استخراج اطلاعات منابع : بدست آوردن اطلاعاتی در مورد دستگاهی که می توان از آن در برنامه TAPI مورد نظرمان استفاده نمود .

    ۵ - Event notification : برپاسازی سيستم اطلاع رسانی event
    مقداردهی اوليه TAPI در ويژوال بيسيک :

    از منوی Project گزينه References را انتخاب کرده و از ليست مربوطه مورد Microsoft TAPI 3.0 Type Library را انتخاب کنيد .
    حال وارد بخش کد نويسی فرمتان شويد و متغير objTAPI را بصورت زير تعريف کنيد :

    Dim objTapi As TAPI


    سپس در بخش مربوط به Form Load شی objTAPI را بصورت زير ايجاد می کنيم :

    Set objTapi = New TAPI


    همانطور که در بخشهای قبلی گفته شد ، قبل از فراخوانی هر تابع TAPI ابتدا بايستی آنرا مقداردهی اوليه کنيم . برای مقداردهی اوليه کردن شی TAPI عبارت زير را بنويسيد :

    Call objTapi.Initialize


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

    نکته : در کد زير عمل error checking انجام نگرفته است و برای استفاده از کد زير در برنامه های واقعی بايستی بخش بررسی خطا را به آن اضافه کنيد .
    ۱ - تعريف يک شی آدرس و يک شی مجموعه آدرس :

    Dim gobjAddress As ITAddress
    Dim objCollAddresses As ITCollection


    ۲ - تنظيم شی objCollAddress بعنوان يک مجموعه آدرس از شی objTapi :

    Set objCollAddresses = objTapi.Addresses


    ۳ - پيدا کردن آدرسی که بتواند از واسط مورد نظر ما پشتيبانی کند :

    bFound = False
    For indexAddr = 1 To objCollAddresses.Count
    Set objCrtAddress = objCollAddresses.Item(indexAddr)x
    Set objMediaSupport = objCrtAddress
    Set objAddressCapabilities = objCrtAddress

    If objMediaSupport.QueryMediaType( nSelectedType ) x
    bFound = True
    End If

    Set objAddressCapabilities = Nothing
    Set objMediaSupport = Nothing
    Set objCrtAddress = Nothing

    If bFound = True Then Exit For
    Next indexAddr



    در صورتيکه آدرس مورد نظزر پيدا شود برنامه از حلقه خارج شده و gobjAddress يک آدرس قابل استفاده خواهد بود :

    Set gobjAddress = objcollAddresses.Item(indexAddr)x


    انجام Event Handling در TAPI :

    کد زير شامل يک event handler ساده برای TAPI ، رجيستر کردن واسط event ، تنظيم ----- event و رجيستر کردن تمام فراخوانيهای دادن اخطار است . هدف اصلی از اين کد اينست که مطمئن شويم بخشی از TAPI که event ها را دريافت می کند پردازشی را قبل از انتقال به بخشهای ديگر انجام دهد .

    تعاريفها :

    Dim WithEvents gobjTapiWithEvents As TAPI
    Attribute gobjTapiWithEvents.VB_VarHelpID = -1
    Dim glRegistrationToken As Long



    Const TAPI3_CALL_EVENTS =TE_CALLMEDIA Or
    TE_CALLNOTIFICATION Or TE_CALLSTATE



    تنظيم eventfilter بصورتيکه تمام event های تعريف شده برای TAPI را بپذيرد :

    objTapi.EventFilter = TAPI3_CALL_EVENTS


    رجيستر کردن event ها :

    Set gobjTapiWithEvents = objTapi
    Dim fOwner As Boolean, fMonitor As Boolean
    Dim lMediaTypes As Long, lCallbackInstance As Long

    fOwner = True
    fOwner = True
    fMonitor = False
    lMediaTypes = TAPIMEDIATYPE_AUDIO
    lCallbackInstance = 1

    glRegistrationToken = gobjTapi.RegisterCallNotifications(gobjAddress,fMo nitor,
    fOwner,lMediaTypes,lCallbackInstance)x


    انتخاب يک ترمينال :

    + قبل از اينکه يک ترمينال را برای برقراری ارتباط انتخاب کنيد بايستی TAPI Initialization و عمل انتخاب آدرس را انجام داده باشيد .

    ابتدا يک متغير از نوع ITBasicCallControl ( واسط کنترل تماس ) تعريف می کنيم :

    Dim objCallControl As ITBasicCallControl
    Set objCallControl = gobjReceivedCallInfo


    سپس يک متغير از نوع ITTerminalSupport ( کوئری از شی آدرس ) تعريف می کنيم :

    Dim objTerminalSupport As ITTerminalSupport
    Set objTerminalSupport = gobjAddress


    سپس متغير ترمينال را تعريف کرده و توسط شی objTerminalSupport يک ترمينال را برای آن استخراج می کنيم :

    Dim objTerminal As ITTerminal
    Set objTerminal = objTerminalSupport.GetDefaultStaticTerminal(lMedia Type, dir)x


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

    Set objTerminalSupport = Nothing


    سپس نياز به تعريف شی objStreamControl برای کنترل ترمينال است :

    Dim objStreamControl As ITStreamControl
    Set objStreamControl = objCallControl


    در صورتيکه اين شی ايجاد شود ، به ازای استريم های موجود در ITCollection امکان ايجاد ترمينال در يک حلقه for بررسی می شود و ترمينال مناسب انتخاب می گردد :

    If Not (objStreamControl Is Nothing) Then
    Dim objITCollStreams As ITCollection

    Set objITCollStreams = objStreamControl.Streams

    Dim nIndex As Long, objCrtStream As ITStream

    For nIndex = 1 To objITCollStreams.Count
    Set objCrtStream = objITCollStreams.Item(nIndex)x
    If objCrtStream.MediaType = lMediaType Then
    If objCrtStream.Direction = dir Then
    Call objCrtStream.SelectTerminal(objTerminal)x
    End If
    End If
    Set objCrtStream = Nothing
    Next nIndex

    Set objITCollStreams = Nothing
    Set objStreamControl = Nothing
    End If



    ايجاد يک تماس ( Make a Call ) :
    + قبل از اين بخش بايستی مراحل TAPI Initialization و عمل انتخاب آدرس انجام شده باشد .
    اين بخش برای ايجاد يک شی تماس ، بررسی و مشخص کردن استريمی که با اين تماس در ارتباط است ، انتخاب و ايجاد ترمينالهای مناسب و کامل کردن ارتباط استفاده می شود .
    قبل TAPI Initialization و عمل انتخاب آدرس و انتخاب ترمينال انجام شده باشد .
    در ابتدا با استفاده از متد CreateCall يک شی تماس ساخته می شود :

    Set gobjCall = gobjOrigAddress.CreateCall(strDestAddress, nSelectedType,lMediaTypes)x


    سپس در اينجا بايستی کدی که در بخش اول اين درس برای انتخاب ترمينال نوشته شد آورده شود :

    }
    Select Terminal Code
    {


    سپس بايستی دستور Connect اجرا شود :

    gobjCall.Connect (False)x


    False بدين معناست که ارتباط بصورت آسنکرون برقرار می شود .
    دريافت يک تماس :

    کد زير برای يافتن و يا ايجاد يک ترمينال مناسب برای دريافت يک تماس بکار می رود . بايستی توجه داشته باشيد که قبل از اجرای کد زير بايستی مراحل مقداردهی اوليه ، انتخاب يک آدرس و رجيسر کردن event ها را انجام دهيد . همچنين در کد زير بايستی مرحله انتخاب ترمينال را نيز انجام دهيد . توجه داشته باشيد که در کد زير متغير pEvent يک اشاره گر برای واسط ITCallNotificationEvent است که توسط TAPI به event Handler داده می شود :

    If TapiEvent = TE_CALLNOTIFICATION Then
    Dim objCallNotificationEvent As ITCallNotificationEvent
    Set objCallNotificationEvent = pEvent
    Dim gobjReceivedCallInfo As ITCallInfo
    Set gobjReceivedCallInfo = objCallNotificationEvent.Call
    Dim objCallControl As ITBasicCallControl
    Set objCallControl = gobjReceivedCallInfo
    objCallControl.Answer
    End If




    + بخاطر طولانی شدن اين سری مطالب و نيز تخصصی بودن آن که باعث می شود مخاطبين کمتری داشته باشد بحث TAPI را به همين جا خاتمه می دهم . اما برای دوستان علاقمند که بخواهند مطالب بيشتری در اين زمينه آموخته و نيز مثالهای عملی از نوشتن برنامه های TAPI را در اختيار داشته باشند لينکهای زير را معرفی می کنم :
    آموزش TAPI در سايت MSDN
    سوالات مختلف در مورد TAPI
    سوالات مختلف در مورد TAPI
    Active Call Center
    يک کنترل ActiveX برای استفاده از TAPI
    نمونه ای از يک برنامه کامل TAPI در ويژوال بيسيک
    TAPI در ويژوال بيسيک
    کتابی در مورد برنامه نويسی TAPI در ويژوال بيسيک

  10. #90
    آخر فروم باز تکنیک برتر's Avatar
    تاريخ عضويت
    Sep 2005
    پست ها
    1,705

    پيش فرض

    موضوع : کنترل ماوس با DirectX Input

    مقدمه :

    برای استفاده از ماوس در برنامه های مالتی مديا و بازيها همانند کی برد می توانيم از امکانات دايرکت ايکس استفاده کنيم . روش کنترل ماوس توسط DirectX Input بسيار ساده بوده و مشابه کنترل کيبرد می باشد بنابراين درصورتی که دو درس گذشته را نخوانده اين پيشنهاد می کنم ابتدا آنها را مطالعه کنيد .

    برپاسازی Device :

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

    Private Const mSpeed As Single = 2
    Private Const BufferSize As Long = 10
    Private mPosition As Point


    mSpeed مقدار سرعت حرکت کرسر ماوس را مشخص می کند .
    BufferSize سايز بافر DI می باشد .
    mPosition موقعيت جاری کرسر ماوس را نشان می دهد .

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


    Set DIDevice = DI.CreateDevice("guid_SysMouse")x
    Call DIDevice.SetCommonDataFormat(DIFORMAT_MOUSE)x
    Call DIDevice.SetCooperativeLevel(frmMain.hWnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE)x


    تفاوت عمده کدهای فوق با کدهای مقداردهی اوليه در بخش کی برد آنست که cooperativelevel تغيير کرده است . در اينجا گفته شده که ما می خواهيم از ماوس بصورت انحصاری در برنامه استفاده کنيم . اين حالت برای برنامه های window-base مناسب نيست و بهترست از آن در بازيهايي که بصورت full screan هستند استفاده کنيد .

    خواندن ورودی از ماوس :

    در اين بخش می توانيد هم از روش polling و هم event-based استفاده کنيد . نکته مهمی که در اينجا وجود دارد آنست که Direct Input فقط حرکت داده شدن ماوس و کليک شدن يک دکمه را به شما اطلاع می دهد و برای تشخيص حالتهای double click و single click خودتان بايستی کد بنويسيد برای مثال اگر فاصله زمانی بين دو کليک کمتر از ۴۰ ميلی ثانيه باشد آنگاه اين يک double click بوده است .
    کد زير حرکت داده شدن ماوس و کليک يکی از سه دکمه آنرا اطلاع می دهد :


    Dim DevData(1 To BufferSize) As DIDEVICEOBJECTDATA
    Dim nEvents As Long
    Dim I As Long
    nEvents = DIDevice.GetDeviceData(DevData, DIGDD_DEFAULT)x
    For I = 1 To nEvents
    Select Case DevData(I).lOfs
    Case DIMOFS_X
    mPosition.x = mPosition.x + (DevData(I).lData * mSpeed)x
    If mPosition.x < 0 Then mPosition.x = 0
    If mPosition.x > frmMain.ScaleWidth Then mPosition.x = frmMain.ScaleWidth
    imgCursor.Top = mPosition.y
    imgCursor.Left = mPosition.x
    lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
    Case DIMOFS_Y
    mPosition.y = mPosition.y + (DevData(I).lData * mSpeed)x
    If mPosition.y < 0 Then mPosition.y = 0
    If mPosition.y > frmMain.ScaleHeight Then mPosition.y = frmMain.ScaleHeight
    imgCursor.Top = mPosition.y
    imgCursor.Left = mPosition.x
    lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
    Case DIMOFS_BUTTON0
    label(2).Caption = "Button 0 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON1
    label(3).Caption = "Button 1 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON2
    label(4).Caption = "Button 2 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    Case DIMOFS_BUTTON3
    label(5).Caption = "Button 3 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
    End Select
    Next I


    برای استفاده از کد فوق در روش Polling ، بايستی آنرا در يک حلقه Do while-Loop قرار دهيد .
    برای استفاده از کد فوق در روش Event-Based ، بايستی آنرا درون روتين DirectXEvent8_DXCallback قرار دهيد

Thread Information

Users Browsing this Thread

هم اکنون 1 کاربر در حال مشاهده این تاپیک میباشد. (0 کاربر عضو شده و 1 مهمان)

User Tag List

قوانين ايجاد تاپيک در انجمن

  • شما نمی توانید تاپیک ایحاد کنید
  • شما نمی توانید پاسخی ارسال کنید
  • شما نمی توانید فایل پیوست کنید
  • شما نمی توانید پاسخ خود را ویرایش کنید
  •