CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Jan 2001
    Posts
    165

    BitBlt and 2 monitors

    I'm not sure if this is related to BitBlt or not but I am using a library of functions that allows me to do screen capturing from my application.

    My application captures the client area of its own main form. This works fine when I am running this on a system with just one video card and monitor, but this program normally runs on a system with 2 video cards and 2 monitors (on the secondary monitor). When I try to do the screen capture it comes out as just a blur of colors.

    Here is the function that I use to capture the screen:
    #If Win32 then
    public Function CaptureWindow(byval hWndSrc as Long, _
    byval Client as Boolean, byval LeftSrc as Long, _
    byval TopSrc as Long, byval WidthSrc as Long, _
    byval HeightSrc as Long, optional RasterOp) as Picture

    Dim hDCMemory as Long
    Dim hBmp as Long
    Dim hBmpPrev as Long
    Dim r as Long
    Dim hDCSrc as Long
    Dim hPal as Long
    Dim hPalPrev as Long
    Dim RasterCapsScrn as Long
    Dim HasPaletteScrn as Long
    Dim PaletteSizeScrn as Long
    #ElseIf Win16 then
    public Function CaptureWindow(byval hWndSrc as Integer, _
    byval Client as Boolean, byval LeftSrc as Integer, _
    byval TopSrc as Integer, byval WidthSrc as Long, _
    byval HeightSrc as Long, optional RasterOp) as Picture

    Dim hDCMemory as Integer
    Dim hBmp as Integer
    Dim hBmpPrev as Integer
    Dim r as Integer
    Dim hDCSrc as Integer
    Dim hPal as Integer
    Dim hPalPrev as Integer
    Dim RasterCapsScrn as Integer
    Dim HasPaletteScrn as Integer
    Dim PaletteSizeScrn as Integer
    #End If
    Dim LogPal as LOGPALETTE
    Dim lRasterOp as Long

    If IsMissing(RasterOp) then
    lRasterOp = vbSrcCopy
    else
    lRasterOp = RasterOp
    End If

    ' Depending on the value of Client get the proper device context.
    If Client then
    hDCSrc = GetDC(hWndSrc) ' get device context for client area.
    else
    hDCSrc = GetWindowDC(hWndSrc) ' get device context for entire
    ' window.
    End If

    ' Create a memory device context for the copy process.
    hDCMemory = CreateCompatibleDC(hDCSrc)
    ' Create a bitmap and place it in the memory DC.
    hBmp = CreateCompatibleBitmap(hDCSrc, WidthSrc, HeightSrc)
    hBmpPrev = SelectObject(hDCMemory, hBmp)

    ' get screen properties.
    RasterCapsScrn = GetDeviceCaps(hDCSrc, RASTERCAPS) ' Raster
    ' capabilities.
    HasPaletteScrn = RasterCapsScrn And RC_PALETTE ' Palette
    ' support.
    PaletteSizeScrn = GetDeviceCaps(hDCSrc, SIZEPALETTE) ' Size of
    ' palette.

    ' If the screen has a palette make a copy and realize it.
    If HasPaletteScrn And (PaletteSizeScrn = 256) then
    ' Create a copy of the system palette.
    LogPal.palVersion = &H300
    LogPal.palNumEntries = 256
    r = GetSystemPaletteEntries(hDCSrc, 0, 256, _
    LogPal.palPalEntry(0))
    hPal = CreatePalette(LogPal)
    ' Select the new palette into the memory DC and realize it.
    hPalPrev = SelectPalette(hDCMemory, hPal, 0)
    r = RealizePalette(hDCMemory)
    End If

    ' Copy the on-screen image into the memory DC.
    r = BitBlt(hDCMemory, 0, 0, WidthSrc, HeightSrc, hDCSrc, _
    LeftSrc, TopSrc, lRasterOp)

    ' Remove the new copy of the on-screen image.
    hBmp = SelectObject(hDCMemory, hBmpPrev)

    ' If the screen has a palette get back the palette that was
    ' selected in previously.
    If HasPaletteScrn And (PaletteSizeScrn = 256) then
    hPal = SelectPalette(hDCMemory, hPalPrev, 0)
    End If

    ' Release the device context resources back to the system.
    r = DeleteDC(hDCMemory)
    r = ReleaseDC(hWndSrc, hDCSrc)

    ' Call CreateBitmapPicture to create a picture object from the
    ' bitmap and palette handles. then return the resulting picture
    ' object.
    set CaptureWindow = CreateBitmapPicture(hBmp, hPal)
    End Function


    I call this function in this manner:
    set frmMain.pictScreen.Picture = CaptureWindow(frmMain.hWnd, true, _
    (frmMain.Left + 45) / Screen.TwipsPerPixelX, (frmMain.Top + 25) / Screen.TwipsPerPixelY, _
    (frmMain.Width - 130) / Screen.TwipsPerPixelX, (frmMain.Height - 300) / Screen.TwipsPerPixelY)


    I cannot figure out why this works with one video card but not 2. Please help.

    -K


  2. #2
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: BitBlt and 2 monitors

    Do not know if this may help but:
    #If Win32 then
    should be resolved at compiling time. That means: value is decided when building exe (or compiling from ide). So, if you compile and then switch monitor, you should try to get the wrong one. If this is true, if you first switch monitor then compile, it should work for that monitor. If you build it on the Pc with 1 card only and then install it and run on the other, it should work only for a card compatible with your...
    Let me know if theory matches practice.

    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, Bruno Paris and all the other wonderful people who made and make Codeguru a great place. Come back soon, you Gurus.
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  3. #3
    Join Date
    Jan 2001
    Posts
    165

    Re: BitBlt and 2 monitors

    I believe that you are right in what you say Cesare however I found out that in this case that was not the problem. I still am not sure how to force this function to read the write video memory (if that is indeed how it captures the video) but for a work around I set my screen capture function to move the form to the other monitor, capture the screen, then move back to where it was and this works fine. By the way I tested this on my own system under the VB IDE and this worked but the previous way still did not work.

    -K


  4. #4
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: How did you do it?

    >>a work around I set my screen capture
    function to move the form to the other monitor, capture the screen,
    then move back to where it was and this works fine...

    How did you manage to move your app to the other monitor and then to come back?

    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, Bruno Paris and all the other wonderful people who made and make Codeguru a great place. Come back soon, you Gurus.
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  5. #5
    Join Date
    Jan 2001
    Posts
    165

    Re: How did you do it?

    Grin, you want me to give you all my secrets? Well that is what I love to do--Open Source all the way!

    'First move the form to the primary display
    If lLeft <> 0 Or lTop <> 0 then
    frmMain.WindowState = vbNormal 'Must not be minimized or maximized when moving
    frmMain.Hide

    frmMain.ScaleLeft = 0 'Primary display is
    frmMain.ScaleTop = 0 'always 0,0

    frmMain.Left = Screen.TwipsPerPixelX * frmMain.ScaleLeft
    frmMain.Top = Screen.TwipsPerPixelY * frmMain.ScaleTop

    frmMain.Show
    frmMain.WindowState = vbMaximized
    DoEvents
    End If

    'Here I capture the screen

    'then move the form back to the 2nd display
    If lLeft <> 0 Or lTop <> 0 then
    frmMain.WindowState = vbNormal
    frmMain.Hide

    frmMain.ScaleLeft = lLeft
    frmMain.ScaleTop = lTop

    frmMain.Left = Screen.TwipsPerPixelX * frmMain.ScaleLeft
    frmMain.Top = Screen.TwipsPerPixelY * frmMain.ScaleTop

    frmMain.Show
    frmMain.WindowState = vbMaximized
    End If



    Here lLeft and lTop are the left and top coordinates of the form at startup. These are global variables that I set using a class file that I found on M$ to bring back the top and left coordinates of all the displays set up. I only wrote this to use 2 monitors so the first display that does not have coordinates of 0,0 (primary display) it will use for the 2nd monitor.

    -K


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured