( تعداد نمایش : 1553 )

آشنایی با BitBlt در ویژوال بیسیک

هدف از این مبحث آموزشی ، آشنایی با تابع BitBlt و برخی دیگر از توابع کتابخانه Win32 GDI برای انجام برخی عملیات گرافیکی مثل double buffering و خواندن sprite از فایل است .
نکته : sprite به کاراکترهای متحرکی گفته می شود که در بازیها وجود دارد .
اولین چیزی که به آن نیاز دارید ایجاد یک فرم است . خاصیت ScaleMode آنرا برابر ۳-Pixel قرار دهید . پیشنهاد می کنم که همیشه در هنگام استفاده از فرم بهمراه API از pixel برای scalemode استفاده کنید .
سپس سایز فرم را به اندازه ای افزایش دهید تا ScaleWidth برابر ۳۲۰ و ScaleHeight برابر ۲۵۶ شود . توجه کنید که خاصیت 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 را در فرم حرکت دهیم :
۱ – یک فایل bmp با ابعاد ۳۲×۳۲ بسازید و با نام sprite1.bmp در دایرکتوری پروژه ذخیره کنید .
۲ – یک دکمه در فرم قرار دهید و نام آنرا cmdTest بگذارید .
۳ – دکمه را در گوشه بالایی فرم و در سمت راست قرار دهید .
۴ – کد زیر را برای 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
اگر ۱۵ میلی ثانیه گذشته بود فریم بعدی شروع شود’
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

دیدگاه خود را بیان کنید.

باید وارد سایت شده باشید برای دیدگاه دادن