Bitblt导致无法用API绘图
去掉Bitblt那句代码,就能画出圆,加上却画不出。我已经用GetDC获得了窗体的场景,为什么复制场景后画不出图了,请问这是什么原因?
Option Explicit
Private Declare Function GetDC& Lib "user32" (ByVal hwnd As Long)
Private Declare Function Ellipse& Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long)
Private Declare Function ReleaseDC& Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long)
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
Private Sub Command1_Click()
Dim PicDC As Long
Form1.AutoRedraw = True
'BitBlt hdc, 0, 0, 1000, 1000, Picture1.hdc, 0, 0, vbSrcCopy
PicDC = GetDC(hwnd) '获取设备场景句柄
Ellipse PicDC, 0, 0, 100, 100 '画空心圆
ReleaseDC hwnd, PicDC '释放设备场景
End Sub
没人知道? 应该是你的两个DC不是兼容的DC,你可以使用CreateCompatibleDC,创建一个和Me.hdc相兼容的DC再使用BitBlt
您好,我不明白您的意思,我知道当AutoRedraw=True的时候,Form1.hdc与GetDC(Form1.hwnd)得到的不是同一个hdc。但GetDC(Form1.hwnd)不就是显示出来的设备场景么?
当没用Bitblt的时候,是可以在这个场景中画图的,但是用了之后,到底哪里发生变化了,怎么就画不了了,Bitblt不只是复制设备场景内容而已么? BitBlt的参数中有两个DC,一个源DC,一个目标DC,这两个DC必须是“相兼容”的。
您好,在AutoRedraw=True的情况下,使用Bitblt后,用Form1.Refresh是可以看到复制的场景的,我的疑问是为什么用API画圆就失效了呢?用API画圆本身就没有什么兼容不兼容的问题啊
您好,在AutoRedraw=True的情况下,使用Bitblt后,用Form1.Refresh是可以看到复制的场景的,我的疑问是为什么用API画圆就失效了呢?用API画圆本身就没有什么兼容不兼容的问题啊
Form1.hDC和Picture1.hDC应该是兼容的吧?要不Form1.Refresh也刷新不了啊。 看看这个例子:
'Example Name:Draw On Screen
'This Project needs
'- two timers, interval=100
'- a button
'in general section
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetActiveWindow Lib "user32" () As Long
Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function Ellipse Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Sub Form_Load()
Timer1.Interval = 100
Timer1.Enabled = True
Timer2.Interval = 100
Timer2.Enabled = True
Command1.Caption = "Draw Text"
End Sub
'This will draw an Ellipse on the active window
Sub Timer1_Timer()
Dim Position As POINTAPI
'Get the cursor position
GetCursorPos Position
'Draw the Ellipse on the Screen's DC
Ellipse GetWindowDC(0), Position.x - 5, Position.y - 5, Position.x + 5, Position.y + 5
End Sub
Sub Command1_Click()
'KPD-Team 1998
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim intCount As Integer, strString As String
strString = "Cool, text on screen !"
For intCount = 0 To 30
'Draw the text on the screen
TextOut GetWindowDC(0), intCount * 20, intCount * 20, strString, Len(strString)
Next intCount
End Sub
Private Sub Timer2_Timer()
'Draw the text to the active window
TextOut GetWindowDC(GetActiveWindow), 50, 50, "This is a form", 14
End Sub
谢谢,运行了一下这个例子。但是还是无法解释Bitblt如何导致绘制不上椭圆的问题。我主要的疑问是为什么Bitblt会导致绘制不上这种情况。 不是BitBlt不能绘制,而是Ellipse绘制了,但没有显示出来而已,你可以单步执行,看看Ellipse函数的返回值是否是非0,如果是非0,那么执行成功。
您好,GetDC得到的不是当前显示的设备场景么?既然画在当前显示的场景上,应该立即输出才对啊? Option Explicit
Private Declare Function GetDC& Lib "user32" (ByVal hwnd As Long)
Private Declare Function Ellipse& Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long)
Private Declare Function ReleaseDC& Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long)
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
Private Sub Command1_Click()
Dim PicDC As Long
Form1.AutoRedraw = True
BitBlt hdc, 0, 0, 1000, 1000, Picture1.hdc, 0, 0, vbSrcCopy
' PicDC = GetDC(hwnd) '获取设备场景句柄
Ellipse hdc, 0, 0, 100, 100 '画空心圆
' ReleaseDC hwnd, PicDC'释放设备场景
Refresh
End Sub
红色的语句可以同时去除,不需要getdc
你使用了别的dc,使用刷新也没有效果,但应该可以去掉设置autoredraw=false可立即显示
您好,我知道怎么让椭圆显示,我现在只是对出现的情况感到疑惑,因为从头到尾我用GetDC得到的场景都是不变的,我只是用了一句Bitblt向另一个hDC复制了一次,就无法显示出我绘制的椭圆了。下面的代码对此进行了测试。
Option Explicit
Private Declare Function GetDC& Lib "user32" (ByVal hwnd As Long)
Private Declare Function Ellipse& Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long)
Private Declare Function ReleaseDC& Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long)
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
Private Sub Command1_Click()
Dim PicDC As Long
Form1.AutoRedraw = True
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
Debug.Print "hdc="; hdc
BitBlt hdc, 0, 0, 100, 100, Picture1.hdc, 0, 0, vbSrcCopy
Debug.Print "hdc="; hdc
PicDC = GetDC(hwnd) '获取设备场景句柄
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
Dim r As Long
r = Ellipse(PicDC, 100, 100, 200, 200) '画空心圆
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
ReleaseDC hwnd, PicDC '释放设备场景
End Sub
Private Sub Picture1_Click()
Dim PicDC As Long
Form1.AutoRedraw = False
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
Debug.Print "hdc="; hdc
BitBlt hdc, 0, 0, 100, 100, Picture1.hdc, 0, 0, vbSrcCopy
Debug.Print "hdc="; hdc
PicDC = GetDC(hwnd) '获取设备场景句柄
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
Dim r As Long
r = Ellipse(PicDC, 100, 100, 200, 200) '画空心圆
Debug.Print "GetDC(hwnd)="; GetDC(hwnd)
ReleaseDC hwnd, PicDC '释放设备场景
End Sub
从Debug返回的结果来看,这两个过程GetDC都是同一个设备场景,只是因为第一个过程AutoRedraw=True,第二个过程AutoRedraw=False就出现不同的输出效果。
就是说
A)当 AutoRedraw = False 时 Form1.hDC = GetDC(Form1.hWnd)
无论 API 绘图还是 VB 绘图,都是向同一个设备输出,所见即所得。
B)当 AutoRedraw = True 时 Form1.hDC <> GetDC(Form1.hWnd)
Form1.hDC 其实是 VB 创建的缓冲设备,VB 会在必要的时候将 hDC 上内容复制到真正的显示设备 GetDC(Form1.hWnd) 上,所以直接在 GetDC(Form1.hWnd) 上的绘图就可能被覆盖。
您好,经过测试,在Autoredraw=true时,执行过Bitblt后,如果不刷新,并不显示复制的内容,也就应该不会覆盖GetDC得到的场景,即便不覆盖也不能显示绘制的内容。我清楚hDC和GetDC的区别,但是这并不能解释这个现象。显然大家并没有认真分析这短短的几行代码。
求破解 你已经糊涂了!
Private Sub Command1_Click()
Form1.AutoRedraw = True '有显示和缓冲两个设备
BitBlt hdc, 0, 0, 100, 100, Picture1.hdc, 0, 0, vbSrcCopy '向缓冲设备绘图
End Sub
没有经过刷新,缓冲设备的内容没有复制到显示设备上,怎么可能看得到?
补充:VB , API