如题, 我另外写了一个贴图的程序, 里面在Form_load 事件里用了D0...loop循环, 还有GetTickCount 的时间控制, 发现不用Form_paint.但是如果不循环, 就画不上图, 这是为什么呢? 下面是我写的程序, BlitIt 放在Form_load 就不画图了。有没用办法不用循环, 也不用Form_Paint? ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Dim DX7 As New DirectX7
Dim DD As DirectDraw7Dim DDPrimSurf As DirectDrawSurface7
Dim DDBuffer As DirectDrawSurface7Dim ddsdPrimSurf As DDSURFACEDESC2
Dim ddsdBuffer As DDSURFACEDESC2
Dim ddclipper As DirectDrawClipperConst ScreenHeight = 1200
Const ScreenWidth = 2400Dim ddrval As Long
Dim r1 As RECT
Dim r2 As RECT
Private Sub Form_Load()Set DD = DX7.DirectDrawCreate("")DD.SetCooperativeLevel Form1.hWnd, DDSCL_NORMALddsdPrimSurf.lFlags = DDSD_CAPS
ddsdPrimSurf.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
Set DDPrimSurf = DD.CreateSurface(ddsdPrimSurf)ddsdBuffer.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
ddsdBuffer.lHeight = ScreenHeight
ddsdBuffer.lWidth = ScreenWidth
Set DDBuffer = DD.CreateSurface(ddsdBuffer)Dim DestRect As RECT'Set up a rectangle as big as the screen
With DestRect
.Bottom = ScreenHeight
.Left = 0
.Right = ScreenWidth
.Top = 0
End With
Set ddclipper = DD.CreateClipper(0)
ddclipper.SetHWnd Form1.hWnd
DDPrimSurf.SetClipper ddclipperDo
DoEvents
DDBuffer.BltColorFill DestRect, 0
Call BlitIt
Loop
End SubSub BlitIt()DX7.GetWindowRect Me.hWnd, r1'r2.Bottom = ddsdBuffer.lHeight
'r2.Right = ddsdBuffer.lWidthr2.Bottom = Form1.ScaleHeight
r2.Right = Form1.ScaleWidthddrval = DDPrimSurf.blt(r1, DDBuffer, r2, DDBLT_WAIT)End SubPrivate Sub Form_Paint()
'Call BlitIt
End Sub
Option Explicit
Dim DX7 As New DirectX7
Dim DD As DirectDraw7Dim DDPrimSurf As DirectDrawSurface7
Dim DDBuffer As DirectDrawSurface7Dim ddsdPrimSurf As DDSURFACEDESC2
Dim ddsdBuffer As DDSURFACEDESC2
Dim ddclipper As DirectDrawClipperConst ScreenHeight = 1200
Const ScreenWidth = 2400Dim ddrval As Long
Dim r1 As RECT
Dim r2 As RECT
Private Sub Form_Load()Set DD = DX7.DirectDrawCreate("")DD.SetCooperativeLevel Form1.hWnd, DDSCL_NORMALddsdPrimSurf.lFlags = DDSD_CAPS
ddsdPrimSurf.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
Set DDPrimSurf = DD.CreateSurface(ddsdPrimSurf)ddsdBuffer.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
ddsdBuffer.lHeight = ScreenHeight
ddsdBuffer.lWidth = ScreenWidth
Set DDBuffer = DD.CreateSurface(ddsdBuffer)Dim DestRect As RECT'Set up a rectangle as big as the screen
With DestRect
.Bottom = ScreenHeight
.Left = 0
.Right = ScreenWidth
.Top = 0
End With
Set ddclipper = DD.CreateClipper(0)
ddclipper.SetHWnd Form1.hWnd
DDPrimSurf.SetClipper ddclipperDo
DoEvents
DDBuffer.BltColorFill DestRect, 0
Call BlitIt
Loop
End SubSub BlitIt()DX7.GetWindowRect Me.hWnd, r1'r2.Bottom = ddsdBuffer.lHeight
'r2.Right = ddsdBuffer.lWidthr2.Bottom = Form1.ScaleHeight
r2.Right = Form1.ScaleWidthddrval = DDPrimSurf.blt(r1, DDBuffer, r2, DDBLT_WAIT)End SubPrivate Sub Form_Paint()
'Call BlitIt
End Sub
Print "你能看见吗?"
Me.Show
Print "现在看见了吧?"
End Sub
说的更直白点就是:你代码中DDraw绘制最终是直接绘制到屏幕上去的,而不是你的窗体上面。
而屏幕上的内容可能被任何东西更改,比如GDI可能在上面绘制其它东西,从而导致你用DX绘制的东西被覆盖掉。
但是Windows在局部覆盖一个对象或者让一个对象重新显示的时候会向其发送WM_PAINT事件,因此截获这个事件(在VB中就是Paint事件了)便可以及时更新你的绘制。总结:
1、如果你打算采用DDraw往主表面上绘制,那么循环或Paint事件中的绘制代码是少不了的。
2、如果你实在不想在那些事件中写东西,那么你可以改用GDI来往窗体上绘制东西,并将窗体的AutoRedraw属性设置为True。(其实背后还是系统帮你在接收WM_PAINT消息的时候绘制了的,只不过是你自己表面上不用写代码了)