Quantcast
Channel: VBForums
Viewing all articles
Browse latest Browse all 15429

Drawing bitmap to printer based Enhanced Metafile after latest windows update 03-2021

$
0
0
Oh, this is a very annoying one.
With the latest Windows 10 update (start of 03-2021) MS has screwed up something with printers as I see also a lot of problems with BSOD when printing to certain printers since that update.
But one other problem seems to be with the Device Context.
When I try to BitBlt/StretchBlt a stdPicture based bitmap to an EnhancedMetafile Device Context (EMDC), which was created based on a Printer.hDC, it doesn't render the bitmap anymore. It worked flawlessly before the windows update for over 19 years.
As a test I saved the bitmap image as an EMF file (with photoshop/paintshop/whatever) and then used PlayEnhMetaFile into the EMDC and that still works.
If I create the EMDC for instance based on the Form.hDC the old code still works, so it seems to be a problem with the DeviceContext in relation to being created based on the Printer.hDC.

I have added an example, just start a default Exe project with only Form1 and paste the following into the Code module:
Make sure you have an image "C:\Temp\MyTestBitmap.bmp" (my original test image has a resolution of 876x600) or replace the string in the code with your location (can also be a JPG).
For the sake of simplicity I have hardcoded widths/Heights etc

What the code does is:
-Load the image into a stdPicture object
-Render the image to the Form (so you know the image is properly loaded)
-Set the base DC which is used to create the EnhancedMetaFileDeviceContext (Printer.hDC doesn't render the image (but worked before the windows update), Me.hDC does render the image)
-Create a new EnhancedMetaFileDeviceContext
-Render the image to the EnhancedMetaFileDeviceContext
-Draw an Ellipse so we have something else on the EnhancedMetaFileDeviceContext
-Close the EnhancedMetafileDeviceContext
-Render the EnancedMetaFile on top of the Form
-Save the EnhancedMetafile to a file "C:\Temp\MyMetafile<currenttime:yyyymmdd_HH_MM_SS>.emf"

Code:

Option Explicit

Private Const SRCCOPY As Long = &HCC0020

Private Const MM_ANISOTROPIC  As Long = 8

Private Const OPAQUE      As Long = 2
Private Const TRANSPARENT  As Long = 1

Private Type BITMAP
  bmType        As Long
  bmWidth      As Long
  bmHeight      As Long
  bmWidthBytes  As Long
  bmPlanes      As Integer
  bmBitsPixel  As Integer
  bmBits        As Long
End Type

Private Type RECT
  Left    As Long
  Top    As Long
  Right  As Long
  Bottom  As Long
End Type

Private Declare Function CloseEnhMetaFile Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare Function CopyEnhMetaFile Lib "gdi32.dll" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare Function CreateDC Lib "gdi32.dll" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As Long, lpInitData As Long) As Long
Private Declare Function CreateEnhMetaFile Lib "gdi32.dll" Alias "CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String, lpRect As Any, ByVal lpDescription As String) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare Function DeleteEnhMetaFile Lib "gdi32.dll" (ByVal hemf As Long) As Long
Private Declare Function Ellipse Lib "gdi32.dll" (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 GetGDIObject Lib "gdi32.dll" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function PlayEnhMetaFile Lib "gdi32.dll" (ByVal hDC As Long, ByVal hemf As Long, lpRect As RECT) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function SetBkMode Lib "gdi32.dll" (ByVal hDC As Long, ByVal nBkMode As Long) As Long
Private Declare Function SetMapMode Lib "gdi32.dll" (ByVal hDC As Long, ByVal nMapMode As Long) As Long
Private Declare Function SetViewportExtEx Lib "gdi32.dll" (ByVal hDC As Long, ByVal nX As Long, ByVal nY As Long, lpSize As Any) As Long
Private Declare Function SetWindowExtEx Lib "gdi32.dll" (ByVal hDC As Long, ByVal nX As Long, ByVal nY As Long, lpSize As Any) As Long
Private Declare Function StretchBlt Lib "gdi32.dll" (ByVal hDC 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 nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long

Private Sub pCreateMetaFile()
  Dim bm                    As BITMAP
  Dim hdcBase              As Long
  Dim hdcBitmap            As Long
  Dim hdcMetaFile          As Long
  Dim hMetaFile            As Long
  Dim lPrintableArea_Height As Long
  Dim lPrintableArea_Width  As Long
  Dim lReturn              As Long
  Dim picTest              As StdPicture
  Dim tRect                As RECT
  '--------------------------------------------------------------
  'Get Picture (info)
  Set picTest = LoadPicture("C:\Temp\MyTestBitmap.bmp")
  Call picTest.Render(Me.hDC, 0, 0, Me.ScaleWidth / Screen.TwipsPerPixelX, Me.ScaleHeight / Screen.TwipsPerPixelY, 0, 0, picTest.Width, picTest.Height, ByVal 0&)
  lReturn = GetGDIObject(picTest.Handle, Len(bm), bm)
  '--------------------------------------------------------------
  'Setup Enhanced Metafile
  lPrintableArea_Width = 20989  'Himetric
  lPrintableArea_Height = 29705 'Himetric
  With tRect
    .Left = 0
    .Right = lPrintableArea_Width
    .Top = 0
    .Bottom = lPrintableArea_Height
  End With
  hdcBase = Printer.hDC
  'hdcBase = Me.hDC
  hdcMetaFile = CreateEnhMetaFile(hdcBase, vbNullString, tRect, _
                                  App.EXEName & vbNullChar & "MyExtraTest" & vbNullChar & vbNullChar)
  If hdcMetaFile = 0 Then
    Call MsgBox("No DeviceContext available for Metafile.", vbError)
  Else 'If hdcMetaFile=
    '-------------------------------------------------------
    'Set some Default settings
    lReturn = SetMapMode(hdcMetaFile, MM_ANISOTROPIC)
    lReturn = SetWindowExtEx(hdcMetaFile, _
                            lPrintableArea_Width, lPrintableArea_Height, _
                            ByVal 0&)
    lReturn = SetViewportExtEx(hdcMetaFile, _
                              lPrintableArea_Width, _
                              lPrintableArea_Height, _
                              ByVal 0&)
    lReturn = SetBkMode(hdcMetaFile, TRANSPARENT)
    '--------------------------------------------------------------
    'Draw picture to metafile
    hdcBitmap = CreateCompatibleDC(hdcMetaFile)
    lReturn = SelectObject(hdcBitmap, picTest.Handle)
    lReturn = StretchBlt(hdcMetaFile, 10, 10, 200, 100, _
                        hdcBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY)
    lReturn = DeleteDC(hdcBitmap)
    '--------------------------------------------------------------
    'Draw ellipse
    lReturn = Ellipse(hdcMetaFile, 100, 100, 300, 200)
    '--------------------------------------------------------------
    'Close metafileDC
    hMetaFile = CloseEnhMetaFile(hdcMetaFile)
    '--------------------------------------------------------------
    'Draw to form
    tRect.Left = 0
    tRect.Top = 0
    tRect.Right = Me.ScaleWidth \ 2 'Me.ScaleX(Me.ScaleWidth, vbTwips, vbHimetric)
    tRect.Bottom = Me.ScaleHeight \ 2 ' Me.ScaleX(Me.ScaleHeight, vbTwips, vbHimetric)
    lReturn = PlayEnhMetaFile(Me.hDC, hMetaFile, tRect)
    '--------------------------------------------------------------
    'Save metafile
    lReturn = CopyEnhMetaFile(hMetaFile, "C:\Temp\MyMetafile" & Format(Now, "yyyymmdd_HH_MM_SS") & ".emf")
    If lReturn <> 0 Then Call DeleteEnhMetaFile(lReturn)
  End If
End Sub

I hope someone has found a workaround (without having to resort to not using the Printer.hDC) of rendering the image to the EnhancedMetaFileDeviceContext.
Only workaround I can think of is actually just creating a new EnhancedMetaFileDeviceContext for the image alone, not based on the Printer.hDC and use PlayEnhMetaFile to the EnhancedMetaFileDeviceContext based on the Printer.hDC. But that's not really ideal.

Viewing all articles
Browse latest Browse all 15429

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>