如何获取最小化窗口内的颜色点的值?

Sean918 2010-06-08 10:01:06
rt

窗口内容是在不停变化的,不要想着先恢复窗口,再截图到内存,或者最小化前先截屏之类的方法。

所有方法请先验证可行后再回复。

谢谢!

我的实验结果是,最小化以后DC中没有保留位图信息,所以不管取哪个点都是返回的 -1

那么,OS中肯定有地方保留了这个窗口的颜色信息,否则不可能恢复窗口的时候可以重画。

问题是,保存在哪里,如何取到保存的信息?

如果可以根据窗口句柄取到这些信息 那就可以自己创建内存位图来获取颜色了。

解决问题200分送上。
...全文
421 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
橘子皮... 2010-07-30
  • 打赏
  • 举报
回复
哎呀,我觉得大家都没有明白楼主的意思啊
楼主的意思是获得最小化后的任何窗体里某点的颜色数值

不是要获得VB里的,也不是只限制于ie浏览器的,要通用的方法
韧恒 2010-07-30
  • 打赏
  • 举报
回复
我想这个问题是这样的:
用VB的窗体来举例子可能会理解的快一点,我们知道窗口有一个AutoDraw属性,当它为真时,无论窗口是否可见,OS都为其开辟一块内存来保存窗口中的图像,当然,这样会很浪费系统资源,因此,绝大多数窗口的这个属性都是Flase,这样,当窗口最小化时,用来绘制窗口的内存就被释放了。所以,你是不会得到窗口中的图像的。
当窗口恢复时,其实是重绘了整个窗口,重绘窗口的依据是根据程序的当前状态来绘制的。我们可以举一个简单的示例:
第一种,窗口的AutoRedaw为False,如果想保持窗口最小化,或被其他窗口摭挡后再恢复上面的图形,则需要将绘图语句写在Paint事件中。
Private Sub Form_Load()
Me.AutoDraw=False
Me.ScaleMode = vbPixels
End Sub

Private Sub Form_Paint()
Me.Line (10, 10)-(Me.ScaleWidth - 10, Me.ScaleHeight - 10), , B
End Sub


第二种情形,将AutoRedraw设置为True,只需绘制一次图形,无论窗口最小化,或被其他窗口摭挡后再恢复
窗口均可保持上面的图形。因为OS已将其信息保存在内存中,并与之关联。
Private Sub Form_Load()
Me.AutoRedraw = True
Me.ScaleMode = vbPixels

Me.Line (10, 10)-(Me.ScaleWidth - 10, Me.ScaleHeight - 10), , B
End Sub



如果还不理解,请看下面的示例。
赵4老师 2010-07-30
  • 打赏
  • 举报
回复
dim rgb as long
rgb=Form1.Point(x,y)
lwplwp123 2010-07-19
  • 打赏
  • 举报
回复
嘿嘿.留个记号
ldy888 2010-07-10
  • 打赏
  • 举报
回复
晕死,楼主在银河系吗?
这一问一答 一个月。
PctGL 2010-07-10
  • 打赏
  • 举报
回复
还在执迷不悟呢...

你以为你真解决呢......

yimins 2010-07-10
  • 打赏
  • 举报
回复
我也以为这帖沉定了,没想到居然又飘起来了。


致楼主:什么窗口都是一样的,IE窗口的话你用spy++抓到窗体的句柄,然后用API拿到窗体的DC句柄,然后代入我那段代码去试试看。
bcrun 2010-07-09
  • 打赏
  • 举报
回复
楼主你应该可通过webbrowser控件的接口获得那图像吧,就是不少软件提供的那个保存网页到图片的功能使用的.你用"保存网页到图片"大约能搜索到:)
Sean918 2010-07-09
  • 打赏
  • 举报
回复
可能是我没说清楚, 我所谓的窗体不是我们VB自己建的工程里面的form

我的窗体是浏览器

你可以试试 ,最小化IE 的时候 还能不能取到上面 flash 的画面。。。
ldy888 2010-06-10
  • 打赏
  • 举报
回复
'Form1
Private Sub Form_Load()
Form2.Show
Form2.Timer1.Interval = 500
Me.Timer1.Interval = 500
Form2.WindowState = 1
End Sub
Private Sub Timer1_Timer()
Dim p As StdPicture
Set p = Form2.Image
'如何通过 P 取像素点的值,我的懒办法是 Picture1.Picture = p
'然后读取Picture1的像素
Me.Picture = p
End Sub


'Form2
Private Sub Timer1_Timer()
Static i As Integer
Me.BackColor = QBColor(i)
i = i + 1
If i = 16 Then i = 0
End Sub
ldy888 2010-06-10
  • 打赏
  • 举报
回复
窗口内容是在不停变化的,它的图像信息存在Form2.Image 中
然后通过StdPicture 取像素值
Private Sub Timer1_Timer()

Me.Picture = Form2.Image

End Sub
yimins 2010-06-10
  • 打赏
  • 举报
回复
累死人了,原来不知不觉花了一个小时!

强烈建议楼主加分!!!
yimins 2010-06-10
  • 打赏
  • 举报
回复
有结果了,答案是可以的。窗体的图像其实就放在Picture属性里面,不过获取起来的确比较麻烦,需要用到一些GDI相关的方法。答案如下:

首先建立一个工程,创建form1和form2两个窗体,form1上创建一个command1,form2上创建一个timer1。然后分别写入如下代码:

form2中的代码:


Option Explicit
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc 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 GetCurrentObject Lib "gdi32" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long

Private Const Bits As Long = 32 '颜色深度,这里把所有图像都按照32位来处理
Private bi24BitInfo As BITMAPINFO '定义BMP信息
Private Const BI_RGB = 0&
Private Type BITMAPINFOHEADER '40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type

Private Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As RGBQUAD
End Type

Private ColVal() As Byte '用于存放从DIB输入的像素值

Private Sub Command1_Click()
Dim MemDC As Long
MemDC = CreateCompatibleDC(Form2.hdc)

SelectObject MemDC, Form2.Picture.Handle

'BitBlt Me.hdc, 0, 0, 200, 200, MemDC, 0, 0, vbSrcCopy

'将字转换为二进制数组
DibGet MemDC, 1, 1, 200, 200

Dim R As Integer
Dim G As Integer
Dim B As Integer
''''''''''''''''''''''''''''''''''''''''''''''''''
'逐点回显整幅图像
Dim i As Long
Dim j As Long
For i = 0 To 199
For j = 0 To 199
R = ColVal(2, i, 199 - j)
G = ColVal(1, i, 199 - j)
B = ColVal(0, i, 199 - j)
SetPixel Me.hdc, i, j, RGB(R, G, B)
Next j
Next i
''''''''''''''''''''''''''''''''''''''''''''''''''
End Sub

'将DC转换成二进制数据
Private Sub DibGet(ByVal IdSource As Long, XBegin As Long, ByVal YBegin As Long, ByVal XEnd As Long, ByVal YEnd As Long)
Dim iBitmap As Long
Dim iDC As Long
Dim i As Long
Dim w As Long
Dim h As Long

Dim InPutWid As Long
Dim InPutHei As Long

InPutWid = XEnd - XBegin
InPutHei = YEnd - YBegin
w = InPutWid + 1
h = InPutHei + 1

i = (Bits \ 8) - 1
ReDim ColVal(i, InPutWid, InPutHei)
With bi24BitInfo.bmiHeader
.biBitCount = Bits
.biCompression = BI_RGB
.biPlanes = 1
.biSize = Len(bi24BitInfo.bmiHeader)
.biWidth = w
.biHeight = h
End With

iBitmap = GetCurrentObject(IdSource, 7&)
GetDIBits IdSource, iBitmap, 0&, h, ColVal(0, 0, 0), bi24BitInfo, 0&
DeleteObject iBitmap
End Sub


Private Sub Form_Load()
Form2.Show
End Sub



form2中的代码:

Option Explicit

Private Sub Form_Load()
Timer1.Interval = 3000
Timer1.Enabled = True

Me.WindowState = 1
End Sub

Private Sub Timer1_Timer()
Timer1.Enabled = False
Set Me.Picture = LoadPicture("e:\pic\1.jpg") '这里请自行替换成本机上任意一张图片,必须大于200×200像素

Me.Caption = "图像加载完毕,可以开始获取"
End Sub


运行之后就可以尝试按下command1按钮尝试获取form2中的图像,就能见到效果了。
yimins 2010-06-10
  • 打赏
  • 举报
回复
这个好像挺有趣的,回头我试一下。

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧