PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/PDFView/PDFView/PrinterUtil.vb

https://gitlab.com/edgardo001/csharp-demos
Visual Basic | 435 lines | 430 code | 5 blank | 0 comment | 0 complexity | d5f54f7cac220818ca83f7b030b9ca06 MD5 | raw file
  1. Imports System.Drawing.Printing
  2. Imports System.Runtime.InteropServices
  3. Imports System.ComponentModel
  4. Imports System.Drawing
  5. Imports System.Windows.Forms
  6. Imports System.IO
  7. Public Class PrinterUtil
  8. Private WithEvents mPrintDocument As PrintDocument
  9. Private mFileName As String
  10. Private mStartPage As Integer
  11. Private mEndPage As Integer
  12. Private mCurrentPage As Integer
  13. Private mPassword As String
  14. Public Shared Function ListAllInstalledPrinters() As List(Of String)
  15. ListAllInstalledPrinters = New List(Of String)
  16. For Each InstalledPrinter As String In _
  17. PrinterSettings.InstalledPrinters
  18. ListAllInstalledPrinters.Add(InstalledPrinter)
  19. Next InstalledPrinter
  20. End Function
  21. Public Shared Function CreateCustomPrintToFilePort() As String
  22. Dim TempString As String = Format(Now, "yyyyMMDDhhmmssfff")
  23. Dim p1 As PrinterInterOp.PORT_INFO_1
  24. p1.pPortName = System.IO.Path.GetTempPath & "\" & TempString & ".prn"
  25. CreateCustomPrintToFilePort = p1.pPortName
  26. PrinterInterOp.AddPortEx(Nothing, 1, p1, "Local Port")
  27. End Function
  28. Public Shared Function CreateNewTempPrinter(ByVal PrinterName As String, ByVal PortName As String, ByVal PrintDriverName As String) As Integer
  29. Dim PrintInterop As New PrinterInterOp
  30. CreateNewTempPrinter = PrintInterop.AddPrinter(PrinterName, PortName, PrintDriverName, "WinPrint")
  31. End Function
  32. Public Shared Sub SendFileToPrinter(ByVal PrinterName As String, ByVal FileName As String)
  33. Dim RP As New RawPrinterHelper
  34. RP.SendFileToPrinter(PrinterName, FileName)
  35. End Sub
  36. Public Shared Sub PrintImageToPrinter(ByRef myFileName As String, ByVal myPrinterSettings As PrinterSettings, Optional ByVal password As String = "")
  37. Dim PrintUtil As New PrinterUtil
  38. PrintUtil.mPrintDocument = New PrintDocument
  39. PrintUtil.mFileName = myFileName
  40. PrintUtil.mPrintDocument.PrinterSettings.PrinterName = myPrinterSettings.PrinterName
  41. Dim StandardPrint As New StandardPrintController
  42. PrintUtil.mPrintDocument.PrintController = StandardPrint
  43. PrintUtil.mPrintDocument.PrinterSettings = myPrinterSettings
  44. PrintUtil.mStartPage = myPrinterSettings.FromPage
  45. PrintUtil.mEndPage = myPrinterSettings.ToPage
  46. PrintUtil.mCurrentPage = PrintUtil.mStartPage
  47. PrintUtil.mPassword = password
  48. Cursor.Current = Cursors.WaitCursor
  49. PrintUtil.mPrintDocument.Print()
  50. PrintUtil = Nothing
  51. GC.Collect()
  52. Cursor.Current = Cursors.Default
  53. End Sub
  54. Public Shared Sub PrintPDFDirectlyToPrinter(ByVal FileName As String)
  55. Dim PD As New PrintDialog
  56. If PD.ShowDialog = DialogResult.OK Then
  57. Dim RP As New RawPrinterHelper
  58. RP.SendFileToPrinter(PD.PrinterSettings.PrinterName, FileName)
  59. End If
  60. End Sub
  61. Public Shared Sub PrintImagesToPrinter(ByVal FileName As String, Optional ByVal password As String = "")
  62. Dim PD As New PrintDialog
  63. Dim PageCount As Integer = PDFView.ImageUtil.GetImageFrameCount(FileName)
  64. PD.AllowPrintToFile = True
  65. PD.AllowSomePages = True
  66. PD.PrinterSettings.FromPage = 1
  67. PD.PrinterSettings.ToPage = PageCount
  68. PD.PrinterSettings.MaximumPage = PageCount
  69. PD.PrinterSettings.MinimumPage = 1
  70. If PD.ShowDialog = DialogResult.OK Then
  71. Dim BeginningPage As Integer = 1
  72. Dim EndingPage As Integer = PageCount
  73. If PD.PrinterSettings.PrintRange = PrintRange.SomePages Then
  74. BeginningPage = PD.PrinterSettings.FromPage
  75. EndingPage = PD.PrinterSettings.ToPage
  76. End If
  77. PrintImageToPrinter(FileName, PD.PrinterSettings, password)
  78. End If
  79. End Sub
  80. Private Sub PrintDocument1_PrintPage(ByVal sender As Object, _
  81. ByVal e As PrintPageEventArgs) Handles mPrintDocument.PrintPage
  82. Dim RenderDPI As Integer = 300 'Set to 600 if this resolution is too low (speed vs. time)
  83. Dim image As System.Drawing.Image = ImageUtil.GetImagePageFromFileForPrint(mFileName, mCurrentPage, RenderDPI, mPassword)
  84. 'Comment out if you do not want Auto-Rotate
  85. If (image.Height > image.Width And e.Graphics.VisibleClipBounds.Width > e.Graphics.VisibleClipBounds.Height) _
  86. Or (image.Width > image.Height And e.Graphics.VisibleClipBounds.Height > e.Graphics.VisibleClipBounds.Width) Then
  87. image.RotateFlip(RotateFlipType.Rotate270FlipNone)
  88. End If
  89. Dim ScalePercentage As Single
  90. Dim XMaxPixels As Integer = (e.Graphics.VisibleClipBounds.Width / 100) * image.HorizontalResolution
  91. Dim YMaxPixels As Integer = (e.Graphics.VisibleClipBounds.Height / 100) * image.VerticalResolution
  92. Dim XFactor As Single = XMaxPixels / image.Width
  93. Dim YFactor As Single = YMaxPixels / image.Height
  94. Dim OptimalDPI As Integer
  95. If YFactor > XFactor Then
  96. ScalePercentage = XFactor
  97. OptimalDPI = RenderDPI * XFactor
  98. Else
  99. ScalePercentage = YFactor
  100. OptimalDPI = RenderDPI * YFactor
  101. End If
  102. If ScalePercentage < 0.75F Then 'Re-render the image to create a smaller print file and save printer processing time
  103. image = ImageUtil.GetImagePageFromFileForPrint(mFileName, mCurrentPage, OptimalDPI, mPassword)
  104. If (image.Height > image.Width And e.Graphics.VisibleClipBounds.Width > e.Graphics.VisibleClipBounds.Height) _
  105. Or (image.Width > image.Height And e.Graphics.VisibleClipBounds.Height > e.Graphics.VisibleClipBounds.Width) Then
  106. image.RotateFlip(RotateFlipType.Rotate270FlipNone)
  107. End If
  108. End If
  109. e.Graphics.ScaleTransform(ScalePercentage, ScalePercentage)
  110. e.Graphics.DrawImage(image, 0, 0)
  111. If mCurrentPage >= mEndPage Then
  112. e.HasMorePages = False
  113. Else
  114. e.HasMorePages = True
  115. End If
  116. image.Dispose()
  117. mCurrentPage += 1
  118. End Sub
  119. End Class
  120. Friend Class PrinterInterOp
  121. Public Structure PORT_INFO_1
  122. Dim pPortName As String
  123. End Structure
  124. Structure PrinterDefaults
  125. Public pDataType As String
  126. Public pDevMode As Int32
  127. Public permissions As Int32
  128. End Structure
  129. Public Function AddPrinter(ByVal psPrinterName As String, ByVal psPortName As String, _
  130. ByVal psDriverName As String, _
  131. ByVal psPrintProcessor As String) As IntPtr
  132. Dim pi2 As New PRINTER_INFO_2
  133. Dim iError As Integer
  134. With pi2
  135. .pPrinterName = psPrinterName
  136. .pPortName = psPortName
  137. .pDriverName = psDriverName
  138. .pPrintProcessor = psPrintProcessor
  139. End With
  140. Dim rtn As Int32
  141. rtn = AddPrinter("", 2, pi2)
  142. If rtn = 0 Then
  143. iError = Marshal.GetLastWin32Error()
  144. Select Case iError
  145. Case 1796
  146. MsgBox("The specified port is unknown")
  147. Exit Select
  148. Case 1797
  149. MsgBox("Printer driver is unknown or not loaded")
  150. Exit Select
  151. Case 1798
  152. MsgBox("The print processor is unknown")
  153. Exit Select
  154. Case 1801
  155. MsgBox("Printer name is invalid")
  156. Exit Select
  157. Case 1802
  158. MsgBox("Printer name already exists")
  159. Exit Select
  160. Case Else
  161. MsgBox("An error occured. Errorcode: " & iError)
  162. Exit Select
  163. End Select
  164. Else
  165. MsgBox("Printer was created successfully")
  166. End If
  167. ClosePrinter(rtn)
  168. Return rtn
  169. End Function
  170. Public Sub RemovePrinter(ByVal PrinterName As String)
  171. Dim hPrinter As IntPtr
  172. Dim PrinterDefs As New PrinterDefaults
  173. With PrinterDefs
  174. .pDevMode = 0&
  175. .permissions = PRINTER_ALL_ACCESS
  176. End With
  177. If OpenPrinter(PrinterName, hPrinter, PrinterDefs) <> 0 Then
  178. If hPrinter <> 0 Then
  179. If DeletePrinter(hPrinter) <> 0 Then
  180. MsgBox("Printer deleted")
  181. Else
  182. MsgBox("Error :" & Err.LastDllError)
  183. End If 'DeletePrinter
  184. End If 'hPrinter
  185. ClosePrinter(hPrinter)
  186. Else
  187. MsgBox("Error :" & Err.LastDllError)
  188. End If 'OpenPrinter
  189. End Sub
  190. Public Declare Function AddPortEx Lib "winspool.drv" Alias "AddPortExA" _
  191. (ByVal pName As String, ByVal pLevel As Integer, _
  192. ByRef lpBuffer As PORT_INFO_1, ByVal pMonitorName As String) As Integer
  193. Public Declare Function DeletePort Lib "winspool.drv" _
  194. (ByVal pName As String, ByVal pLevel As Integer, _
  195. ByVal pMonitorName As String) As Integer
  196. Public Declare Auto Function OpenPrinter Lib "winspool.drv" _
  197. (ByVal pPrinterName As String, _
  198. ByRef phPrinter As IntPtr, _
  199. ByVal pDefault As PrinterDefaults) As Int32
  200. Public Declare Auto Function ResetPrinter Lib "winspool.drv" _
  201. (ByRef phPrinter As IntPtr, _
  202. ByVal pDefault As PrinterDefaults) As Int32
  203. Public Declare Function DeletePrinter Lib "winspool.drv" _
  204. (ByVal hPrinter As IntPtr) As Int32
  205. Public Declare Function ClosePrinter Lib "winspool.drv" _
  206. (ByVal hPrinter As IntPtr) As Int32
  207. Private Declare Function AddPrinter Lib "winspool.drv" _
  208. Alias "AddPrinterA" _
  209. (ByVal pServerName As String, _
  210. ByVal Level As Int32, _
  211. ByVal pPrinter As PRINTER_INFO_2) As Int32
  212. Public Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterW" _
  213. (ByVal hPrinter As IntPtr, ByVal Level As Integer, ByVal pPrinter As IntPtr, _
  214. ByVal cbBuf As Integer, ByRef pcbNeeded As Integer) As Integer
  215. Public Const PRINTER_ACCESS_ADMINISTER As Int32 = &H4
  216. Public Const STANDARD_RIGHTS_REQUIRED As Int32 = &HF0000
  217. Public Const PRINTER_ACCESS_USE As Int32 = &H8
  218. Public Const PRINTER_ALL_ACCESS As Int32 = _
  219. STANDARD_RIGHTS_REQUIRED Or _
  220. PRINTER_ACCESS_USE Or _
  221. PRINTER_ACCESS_ADMINISTER
  222. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto), System.Security.SuppressUnmanagedCodeSecurity()> _
  223. Friend Class PRINTER_INFO_2
  224. <MarshalAs(UnmanagedType.LPStr)> Public pServerName As String
  225. <MarshalAs(UnmanagedType.LPStr)> Public pPrinterName As String
  226. <MarshalAs(UnmanagedType.LPStr)> Public pShareName As String
  227. <MarshalAs(UnmanagedType.LPStr)> Public pPortName As String
  228. <MarshalAs(UnmanagedType.LPStr)> Public pDriverName As String
  229. <MarshalAs(UnmanagedType.LPStr)> Public pComment As String
  230. <MarshalAs(UnmanagedType.LPStr)> Public pLocation As String
  231. <MarshalAs(UnmanagedType.U4)> Public pDevMode As Int32
  232. <MarshalAs(UnmanagedType.LPStr)> Public pSepFile As String
  233. <MarshalAs(UnmanagedType.LPStr)> Public pPrintProcessor As String
  234. <MarshalAs(UnmanagedType.LPStr)> Public pDatatype As String
  235. <MarshalAs(UnmanagedType.LPStr)> Public pParameters As String
  236. <MarshalAs(UnmanagedType.U4)> Public pSecurityDescriptor As Int32
  237. Public Attributes As UInteger
  238. Public Priority As UInteger
  239. Public DefaultPriority As UInteger
  240. Public StartTime As UInteger
  241. Public UntilTime As UInteger
  242. Public Status As UInteger
  243. Public cJobs As UInteger
  244. Public AveragePPM As UInteger
  245. Public Sub New(ByVal hPrinter As IntPtr)
  246. Dim BytesWritten As Int32 = 0
  247. Dim ptBuf As IntPtr
  248. ptBuf = Marshal.AllocHGlobal(1)
  249. Dim PI As New PrinterInterOp
  250. If Not GetPrinter(hPrinter, 2, ptBuf, 1, BytesWritten) Then
  251. If BytesWritten > 0 Then
  252. '\\ Free the buffer allocated
  253. Marshal.FreeHGlobal(ptBuf)
  254. ptBuf = Marshal.AllocHGlobal(BytesWritten)
  255. If GetPrinter(hPrinter, 2, ptBuf, BytesWritten, BytesWritten) Then
  256. Marshal.PtrToStructure(ptBuf, Me)
  257. '\\ Fill any missing members
  258. If pServerName Is Nothing Then
  259. pServerName = ""
  260. End If
  261. Else
  262. Throw New Win32Exception()
  263. End If
  264. '\\ Free this buffer again
  265. Marshal.FreeHGlobal(ptBuf)
  266. Else
  267. Throw New Win32Exception()
  268. End If
  269. Else
  270. Throw New Win32Exception()
  271. End If
  272. End Sub
  273. Public Sub New()
  274. End Sub
  275. End Class
  276. End Class
  277. Friend Class RawPrinterHelper
  278. ' Structure and API declarions:
  279. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  280. Public Class DOCINFOA
  281. <MarshalAs(UnmanagedType.LPStr)> _
  282. Public pDocName As String
  283. <MarshalAs(UnmanagedType.LPStr)> _
  284. Public pOutputFile As String
  285. <MarshalAs(UnmanagedType.LPStr)> _
  286. Public pDataType As String
  287. End Class
  288. <DllImport("winspool.Drv", EntryPoint:="OpenPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  289. Public Shared Function OpenPrinter(<MarshalAs(UnmanagedType.LPStr)> ByVal szPrinter As String, ByRef hPrinter As IntPtr, ByVal pd As IntPtr) As Boolean
  290. End Function
  291. <DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  292. Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
  293. End Function
  294. <DllImport("winspool.Drv", EntryPoint:="StartDocPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  295. Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal level As Int32, <[In](), MarshalAs(UnmanagedType.LPStruct)> ByVal di As DOCINFOA) As Boolean
  296. End Function
  297. <DllImport("winspool.Drv", EntryPoint:="EndDocPrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  298. Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Boolean
  299. End Function
  300. <DllImport("winspool.Drv", EntryPoint:="StartPagePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  301. Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Boolean
  302. End Function
  303. <DllImport("winspool.Drv", EntryPoint:="EndPagePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  304. Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Boolean
  305. End Function
  306. <DllImport("winspool.Drv", EntryPoint:="WritePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  307. Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal pBytes As IntPtr, ByVal dwCount As Int32, ByRef dwWritten As Int32) As Boolean
  308. End Function
  309. ' SendBytesToPrinter()
  310. ' When the function is given a printer name and an unmanaged array
  311. ' of bytes, the function sends those bytes to the print queue.
  312. ' Returns true on success, false on failure.
  313. Public Function SendBytesToPrinter(ByVal szPrinterName As String, ByVal pBytes As IntPtr, ByVal dwCount As Int32) As Boolean
  314. Dim dwError As Int32 = 0, dwWritten As Int32 = 0
  315. Dim hPrinter As New IntPtr(0)
  316. Dim di As New DOCINFOA()
  317. Dim bSuccess As Boolean = False
  318. ' Assume failure unless you specifically succeed.
  319. di.pDocName = "My VB.NET RAW Document"
  320. di.pDataType = "RAW"
  321. ' Open the printer.
  322. If OpenPrinter(szPrinterName.Normalize(), hPrinter, IntPtr.Zero) Then
  323. ' Start a document.
  324. If StartDocPrinter(hPrinter, 1, di) Then
  325. ' Start a page.
  326. If StartPagePrinter(hPrinter) Then
  327. ' Write your bytes.
  328. bSuccess = WritePrinter(hPrinter, pBytes, dwCount, dwWritten)
  329. EndPagePrinter(hPrinter)
  330. End If
  331. EndDocPrinter(hPrinter)
  332. End If
  333. ClosePrinter(hPrinter)
  334. End If
  335. ' If you did not succeed, GetLastError may give more information
  336. ' about why not.
  337. If bSuccess = False Then
  338. dwError = Marshal.GetLastWin32Error()
  339. End If
  340. Return bSuccess
  341. End Function
  342. Public Function SendFileToPrinter(ByVal szPrinterName As String, ByVal szFileName As String) As Boolean
  343. ' Open the file.
  344. Dim fs As New FileStream(szFileName, FileMode.Open)
  345. ' Create a BinaryReader on the file.
  346. Dim br As New BinaryReader(fs)
  347. ' Dim an array of bytes big enough to hold the file's contents.
  348. Dim bytes As [Byte]() = New [Byte](fs.Length - 1) {}
  349. Dim bSuccess As Boolean = False
  350. ' Your unmanaged pointer.
  351. Dim pUnmanagedBytes As New IntPtr(0)
  352. Dim nLength As Integer
  353. nLength = Convert.ToInt32(fs.Length)
  354. ' Read the contents of the file into the array.
  355. bytes = br.ReadBytes(nLength)
  356. ' Allocate some unmanaged memory for those bytes.
  357. pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength)
  358. ' Copy the managed byte array into the unmanaged array.
  359. Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength)
  360. ' Send the unmanaged bytes to the printer.
  361. bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength)
  362. ' Free the unmanaged memory that you allocated earlier.
  363. Marshal.FreeCoTaskMem(pUnmanagedBytes)
  364. fs.Close()
  365. br.Close()
  366. Return bSuccess
  367. End Function
  368. Public Function SendStringToPrinter(ByVal szPrinterName As String, ByVal szString As String) As Boolean
  369. Dim pBytes As IntPtr
  370. Dim dwCount As Int32
  371. ' How many characters are in the string?
  372. dwCount = szString.Length
  373. ' Assume that the printer is expecting ANSI text, and then convert
  374. ' the string to ANSI text.
  375. pBytes = Marshal.StringToCoTaskMemAnsi(szString)
  376. ' Send the converted ANSI string to the printer.
  377. SendBytesToPrinter(szPrinterName, pBytes, dwCount)
  378. Marshal.FreeCoTaskMem(pBytes)
  379. Return True
  380. End Function
  381. End Class