OpenGL窗口内容使用BitBlt没有复制出窗口的图像,是一个黑屏,大家帮忙看看啊!

CloneCenter 2006-11-07 11:43:23
使用OpenGL画出的窗口,窗口内包含了一个2D的图片,还有3D的物体,表面有2D的贴图,现在希望将整个窗口内的内容复制到BitMap中。从网上找了一下代码,运行没有问题,可是结果保存的图片文件是一个黑屏,没有任何内容。

使用Alt-PrintScreen键,内容都能够复制到剪贴板上,自己的代码怎么就不行呢!

附代码如下:
' 将当前窗口内的内容复制到 Bitmap 中。
Public Function CopyFormBitmap()

Dim dDC As System.IntPtr, bm As New Bitmap(form.Width, form.Height)
Dim g As Graphics = Graphics.FromImage(bm)
dDC = g.GetHdc
If BitBlt(dDC, 0, 0, form.Width, form.Height, hDC, 0, 0, SRCCOPY) Then
bm.Save("d:\temp\window.jpeg", ImageFormat.Jpeg)
End If
g.ReleaseHdc(dDC)
End Function

大家帮我看看,有没有什么办法解决,谢谢!
...全文
628 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
CloneCenter 2006-11-09
  • 打赏
  • 举报
回复
谢谢楼上的解答,不过问题仍然存在!
附上我的BitBlt函数定义:
Public Declare Function BitBlt Lib "gdi32.dll" Alias "BitBlt" (ByVal hDCDest As IntPtr, ByVal XDest As Integer, ByVal YDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hDCSrc As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As Integer) As Boolean
sx_lxh 2006-11-09
  • 打赏
  • 举报
回复
试试: SendMessage(hwd, WM_PRINT, hdc, DrawingOptions.PRF_CLIENT + DrawingOptions.PRF_ERASEBKGND + DrawingOptions.PRF_OWNED + DrawingOptions.PRF_CHILDREN)
另外:检查bitblt的声明函数
sx_lxh 2006-11-09
  • 打赏
  • 举报
回复
这个在我这儿可以,没有标题栏:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim bmp As New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
Dim gr As Graphics = Graphics.FromImage(bmp)
Dim hdc = gr.GetHdc()
SendMessage(Me.Handle, WM_PRINT, hdc, DrawingOptions.PRF_CLIENT + DrawingOptions.PRF_ERASEBKGND + DrawingOptions.PRF_OWNED + DrawingOptions.PRF_CHILDREN)
gr.ReleaseHdc(hdc)
bmp.Save("c:\02.bmp")
gr = Nothing
End Sub
sx_lxh 2006-11-09
  • 打赏
  • 举报
回复
也有标题栏!
CloneCenter 2006-11-09
  • 打赏
  • 举报
回复
-_-!

感谢龙子的帮助,自己还要多学习啊!问题解决了,不过图片效果貌似有点问题,先不管了。

这个是我修改后的一个代码,替代了上面的 CopyFromBitmap 函数。

Public Sub DragonBitmap()
Dim hHandle As IntPtr = form.Handle
Dim hBitmap As IntPtr = CreateCompatibleBitmap(hDC, form.Width, form.Height)
Dim hdcSrc As IntPtr = GetWindowDC(hHandle)
Dim hdcDest As IntPtr = CreateCompatibleDC(hdcSrc)
SelectObject(hdcDest, hBitmap)
BitBlt(hdcDest, 0, 0, form.Width, form.Height, hdcSrc, 0, 0, SRCCOPY)
Dim image As Bitmap = image.FromHbitmap(hBitmap)
image.Save("d:\temp\window_l.jpeg", ImageFormat.Jpeg)
ReleaseDC(hHandle, hdcSrc)
DeleteDC(hdcDest)
DeleteObject(hBitmap)
End Sub
lexchou 2006-11-09
  • 打赏
  • 举报
回复
Public Const SRCCOPY As Integer = 13369376

Public Declare Function BitBlt Lib "GDI32.dll" (ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean

Public Declare Function CreateCompatibleBitmap Lib "GDI32.dll" (ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr

Public Declare Function CreateCompatibleDC Lib "GDI32.dll" (ByVal hdc As IntPtr) As IntPtr

Public Declare Function DeleteDC Lib "GDI32.dll" (ByVal hdc As IntPtr) As Boolean

Public Declare Function DeleteObject Lib "GDI32.dll" (ByVal hObject As IntPtr) As Boolean

Public Declare Function SelectObject Lib "GDI32.dll" (ByVal hdc As IntPtr, ByVal hgdiobj As IntPtr) As Integer

Public Declare Function GetDesktopWindow Lib "User32.dll" () As IntPtr

Public Declare Function GetWindowDC Lib "User32.dll" (ByVal hWnd As IntPtr) As IntPtr

Public Declare Function ReleaseDC Lib "User32.dll" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer

Private Sub btn_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim hHandle As IntPtr = Handle
Dim hBitmap As IntPtr = CreateCompatibleBitmap(hdcSrc, Width, Height)
Dim hdcSrc As IntPtr = GetWindowDC(hHandle)
Dim hdcDest As IntPtr = CreateCompatibleDC(hdcSrc)
SelectObject(hdcDest, hBitmap)
BitBlt(hdcDest, 0, 0, Width, Height, hdcSrc, 0, 0, SRCCOPY)
Dim image As Bitmap = Image.FromHbitmap(hBitmap)
image.Save("d:\\window.jpeg", ImageFormat.Jpeg)
ReleaseDC(hHandle, hdcSrc)
DeleteDC(hdcDest)
DeleteObject(hBitmap)
End Sub

找个地方翻译了一下
lexchou 2006-11-09
  • 打赏
  • 举报
回复
IntPtr hHandle = Handle;
IntPtr hdcSrc = GetWindowDC(hHandle),
hdcDest = CreateCompatibleDC(hdcSrc),
hBitmap = CreateCompatibleBitmap(hdcSrc,
Width, Height);
SelectObject(hdcDest, hBitmap);
BitBlt(hdcDest, 0, 0, Width,
Height,
hdcSrc, 0, 0, SRCCOPY);
Bitmap image = Image.FromHbitmap(hBitmap);
image.Save("d:\\window.jpeg", ImageFormat.Jpeg);

ReleaseDC(hHandle, hdcSrc);
DeleteDC(hdcDest);
DeleteObject(hBitmap);
CloneCenter 2006-11-09
  • 打赏
  • 举报
回复
函数调用该成下面这个样子了,结构还是错误的。
BitBlt(dDC.ToInt32, 0, 0, form.Width, form.Height, hDC.ToInt32, 0, 0, SRCCOPY)
CloneCenter 2006-11-09
  • 打赏
  • 举报
回复
hDestDC 和 hSrcDC 修改成 Int32 之后,我的hdc怎么传给他?一个是IntPtr一个是Int32,怎么转换?
sx_lxh 2006-11-09
  • 打赏
  • 举报
回复
试试:
Private Declare Function BitBlt Lib "gdi32.dll" (ByVal hDestDC As Int32, ByVal x As Int32, ByVal y As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal hSrcDC As Int32, ByVal xSrc As Int32, ByVal ySrc As Int32, ByVal dwRop As Int32) As Int32
shengli_liao 2006-11-08
  • 打赏
  • 举报
回复
xuexi...
CloneCenter 2006-11-08
  • 打赏
  • 举报
回复
这个是Tao自带的帮助中的关于 GetDC 的说明:

The GetDC function retrieves a handle to a display device context (DC) for the client area of a specified window or for the entire screen. You can use the returned handle in subsequent GDI functions to draw in the DC.

The GetDCEx function is an extension to GetDC, which gives an application more control over how and whether clipping occurs in the client area.

public static IntPtr GetDC(
IntPtr windowHandle
);
Parameters
windowHandle
Handle to the window whose DC is to be retrieved. If this value is null, GetDC retrieves the DC for the entire screen.

Windows 98/Me, Windows 2000/XP: To get the DC for a specific display monitor, use the EnumDisplayMonitors and CreateDC functions.

Return Value

If the function succeeds, the return value is a handle to the DC for the specified window's client area.

If the function fails, the return value is null.

Windows NT/2000/XP: To get extended error information, call GetLastWin32Error.


Remarks
The GetDC function retrieves a common, class, or private DC depending on the class style of the specified window. For class and private DCs, GetDC leaves the previously assigned attributes unchanged. However, for common DCs, GetDC assigns default attributes to the DC each time it is retrieved. For example, the default font is System, which is a bitmap font. Because of this, the handle for a common DC returned by GetDC does not tell you what font, color, or brush was used when the window was drawn. To determine the font, call GetTextFace.

Note that the handle to the DC can only be used by a single thread at any one time.

After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC. The number of DCs is limited only by available memory.

Windows 95/98/Me: There are only 5 common DCs available per thread, thus failure to release a DC can prevent other applications from accessing one.

CloneCenter 2006-11-08
  • 打赏
  • 举报
回复
hdc通过OpenGl的一个.net类库Tao里面的一个函数获得的,和上面我说的一样,但是这个函数是如何实现的,我还不清楚,可能还要查一下。用Bitblt获取图象这个方法应该是没有问题的吧?
Knight94 2006-11-08
  • 打赏
  • 举报
回复
call api?
CloneCenter 2006-11-08
  • 打赏
  • 举报
回复
hDC = Tao.Platform.Windows.User.GetDC(form.Handle) ' Attempt To Get A Device Context

谢谢楼上的大侠!
Knight94 2006-11-08
  • 打赏
  • 举报
回复
hDC怎么获得的
CloneCenter 2006-11-08
  • 打赏
  • 举报
回复
楼上的办法也不行啊,和我的方法的唯一区别是,我的代码得到的是黑屏,您的代码得到的是灰色窗口,WindowBackColor颜色的。
leq_82 2006-11-08
  • 打赏
  • 举报
回复
JF
ssrwf 2006-11-08
  • 打赏
  • 举报
回复
学习!!!!
ccrun.com 2006-11-07
  • 打赏
  • 举报
回复
友情up
加载更多回复(8)

16,555

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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