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"
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.
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
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.