我有一张带有大图片的图片框:
在此图片框中,使用ExtFloodFill()
API
Private Declare Function ExtFloodFill Lib "GDI32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
启动FloodFill的X和Y坐标位于必须填充的区域中的某个位置,但不在精确的中心,或者对于所有区域具有相同的偏移,并且区域的形状或尺寸。 (这就是我们喜欢FloodFill的原因)
我现在希望用户通过点击它并使用与他们点击的区域相对应的特定操作的坐标来与图片进行交互。
为此我使用_MouseDown()
事件:
Private Sub picfat_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Dim lngIndex As Long
lngIndex = CheckClick(mobjDet, x, y)
If lngIndex > -1 Then
With mobjDet(lngIndex)
.lngStat = 2 - .lngStat
SendCmd "det swico " & CStr(lngIndex) & "=" & CStr(.lngStat), wskDet
End With 'mobjDet(lngIndex)
End If
End Sub
调用CheckClick()
来确定点击所在的区域:
Private Function CheckClick(obj() As FC_DET, sngX As Single, sngY As Single) As Long
Dim lngObj As Long
Dim lngIndex As Long
Dim sngWidth As Single, sngHeight As Single
sngWidth = 15
sngHeight = 15
lngIndex = -1
For lngObj = 0 To UBound(obj)
With obj(lngObj)
If sngWidth > 0 Then
If sngX > .sngX Then
If sngX < .sngX + sngWidth Then
If sngY > .sngY Then
If sngY < .sngY + sngHeight Then
lngIndex = .lngIndex
Exit For
End If
End If
End If
End If
End If
End With 'obj(lngObj)
Next lngObj
CheckClick = lngIndex
End Function
此时我在原始X和Y坐标的右下角使用15x15像素的正方形,如果用户点击这些坐标,它将正常工作。
如果FloodFill的X和Y坐标是小方块的左上角,则15x15方格适用于图片中的较小方块,但情况并非如此,并且您可以看到还有其他形状以及小方块。
我想做的是:
_MouseDown()
事件[编辑]
例如:
mobjDet(6).sngX
和mobjDet(6).sngY
这样我就可以找出用户在图片中点击了哪个区域。
答案 0 :(得分:2)
当我过去做过这样的事情时,最适合我的方法是创建一个UDT数组。每个UDT都拥有调用我的绘制API(如FloodFill)所需的所有信息(例如color
,x1
,x2
,y1
,y2
)。当我不得不渲染我的屏幕时,我只是在我的阵列中循环,画出了我的所有物品。当用户点击我的hdc时,我会再次循环以使用相同的坐标找到匹配的UDT,其中还包含其他信息,如id
等。
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type DrawItem
Id As Long
Name As String
' etc...
tRect As RECT
End Type
Private DrawItems() As DrawItem
此外,由于FloodFill几乎不可能跟踪填充的内容,因此我建议您使用更加笨拙的API(如FillRect)手动绘制图形。 这意味着您将拥有在UDT 中绘制的全部边界(顶部,底部,左侧和右侧),以便您可以查看是否有鼠标点击是在那个矩形内。
这是用于绘制矩形的API。你还需要创建一个&#34;画笔&#34;使用CreateSolidBrush函数。
Private Declare Function FillRect Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
另外,我喜欢将我正在绘制的任何内容的ScaleMode
(例如,PictureBox)从1 - Twip
(无用)更改为3 - Pixel
所以我不会经常拥有乘以或除以15。
希望这有帮助。
最后请注意,如果您真的与FloodFill挂钩,我建议的最好的就是使用......
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
...可以在鼠标点击x和y坐标时返回像素的颜色。然后你可以测试颜色(希望)匹配你需要的颜色。
答案 1 :(得分:1)
使用GDI,您可以使用Regions。这些将要求您在代码中定义区域(或除位图之外的其他结构,可能是点轮廓数组),但允许您:
CreatePolygonRgn()
或CreatePolyPolygonRgn()
FrameRgn()
FillRgn()
PtInRgn()
答案 2 :(得分:1)
感谢LimaNightHawk和Deanna让我知道如何解决这个问题:)
在我的图片框中加载位图后,我在内存中复制了它。 在该副本中,我然后用自己的颜色填充每个重要区域:
Private Sub CopyView()
Dim lngIndex As Long
Dim sngWidth As Single, sngHeight As Single
Dim lngBrush As Long
Dim lngBmp As Long
sngWidth = ScaleWidth
sngHeight = ScaleHeight
lngBrush = CreateSolidBrush(vbYellow)
With picFAT
mlngCopy = CreateCompatibleDC(.hdc)
SelectObject mlngCopy, lngBrush
If mlngCopy <> 0 Then
lngBmp = CreateCompatibleBitmap(.hdc, sngWidth, sngHeight)
If lngBmp <> 0 Then
SelectObject mlngCopy, lngBmp
BitBlt mlngCopy, 0, 0, sngWidth, sngHeight, .hdc, 0, 0, SRCCOPY
For lngIndex = 0 To UBound(mobjDet)
With mobjDet(lngIndex)
lngBrush = CreateSolidBrush(lngIndex + 1)
SelectObject mlngCopy, lngBrush
ExtFloodFill mlngCopy, .sngX, .sngY, GetPixel(mlngCopy, .sngX, .sngY), 1
End With 'mobjDet(lngIndex)
Next lngIndex
End If
End If
End With 'picFAT
DeleteObject lngBrush
End Sub
为了使它非常简单,我使用区域的索引号作为颜色。
然后,我可以通过读取内存副本中该区域的颜色来获取索引:
Private Function FindIndex(sngX As Single, sngY As Single) As Long
Dim lngColor As Long
lngColor = GetPixel(mlngCopy, sngX, sngY)
FindIndex = lngColor - 1
End Function
最后我从MouseDown事件调用上面的内容来使用用户点击的区域的索引:
Private Sub picfat_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Dim lngIndex As Long
lngIndex = FindIndex(x, y)
If lngIndex > -1 Then
If lngIndex <= UBound(mobjDet) Then
With mobjDet(lngIndex)
.lngStat = 2 - .lngStat
SendCmd "det swico " & CStr(.lngIndex) & "=" & CStr(.lngStat), wskDet
End With 'mobjDet(lngIndex)
End If
End If
End Sub
请参阅下面的API声明:
'API
Private Const SRCCOPY = &HCC0020
Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) 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 Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long