前言

本来今天还是写关于MySQL系列文章,结果做了一个小程序,就没写。

由于姐姐开的摄影店,时不时就有人来照1/2寸照,拍摄后进行修图美白,然后进行排版,1寸的话排列8张,2寸是4张,然后导出png,进行打印,所以我想的是可以用程序简化后两步骤。

这回没有选择Java写,而是选择上古神器Visual Basic。

操作流程

对于程序操作流程是这样想的:首先要更改注册表,增加对png、jpg图片右键菜单选项,选择寸照打印,这样就会启动我们的程序,然后根据当前尺寸大小,自动排列8张或4张,最后调用默认打印机打印。

里面还要设计一个细节,当白底的时候,为每个照片都加一个白边,其他就不需要了。

绘制图像

VB中绘制图像是个难题,但有了GDI+,一切都变得很简单,首先去网上搜索一个VB GDI+模块进行导入,因为这些函数在VB默认的API浏览器中是搜不到的,自己慢慢写又太麻烦了。

绘制的流程如下:

1. 获取启动参数

首先要拿到图片地址,VB中可以使用command函数获取启动参数,启动参数是右键菜单单机时候传入的,然后判断这个文件是否存在。

Private Sub Verification()
mImagePath = Command
If (Dir(mImagePath) = "") ThenMsgBox "文件不存在"End
End If
End Sub

2.初始化GDI+

下一步是初始化GDI+库,并加载图像, 使用GDI+的时候首先需要通过GdiplusStartup函数初始化才行,但是这个GDI+模块已经做好了初始化的函数,只需要调用即可。

Public Function InitGDIPlusTo(ByRef token As Long, _Optional OnErrShowMsg As Boolean = True, Optional OnErrEndApp As Boolean = True, _Optional ErrMsgText As String = "GDI+ 初始化错误。程序即将关闭。", _Optional ErrMsgStyle As VbMsgBoxStyle = vbCritical, _Optional ErrMsgTitle As String = "初始化错误") As GpStatusIf token <> 0 ThenDebug.Print "InitGDIPlusTo> GdiPlus已被初始化"Exit FunctionEnd IfDim uInput As GdiplusStartupInputDim ret As GpStatusuInput.GdiplusVersion = 1ret = GdiplusStartup(token, uInput)If ret <> Ok ThenIf OnErrShowMsg Then MsgBox ErrMsgText, ErrMsgStyle, ErrMsgTitleIf OnErrEndApp Then EndEnd IfInitGDIPlusTo = ret
End Function
'直接调用
mToken = GDI.InitGDIPlus

然后使用GdipLoadImageFromFile加载,第一个参数是图片地址,但是需要传入字符串地址,所以要通过StrPtr函数转换,第二个是图片返回句柄,加载成功后,hImageRes变量会大于0,(这个传递方式是引用传递。)

Call GDI.GdipLoadImageFromFile(StrPtr(mImagePath), hImageRes)

3.排列图片

加载图像后,获取图像宽度,如果宽度小于400,则可以认为这是1寸照,因为一寸照在2.5cmx3.5cm,分别率在300的情况下,宽高像素是295x413,需要排列8张。(2寸宽大于400)

GDI+绘制的话需要在Graphics对象上绘制,所以就先要创建Graphics对象。

创建Graphics对象有很多办法,其中之一是从Bitmap/Image对象中获取,所以可以先创建一个空的Bitma,,接着通过GdipGetImageGraphicsContext创建与Bitmap对象关联的Graphics对象,后续绘图就可以在这个对象上绘,相当于一块画板。

至于这个大小为什么是1500x1050,其实就是实际承载寸照的纸张大小。因为纸张大小是12.7x8.9,分辨率300.

Dim mBitmap As Long
Dim mBitmapGraphics As Long
//创建空Bitmap
Call GdipCreateBitmapFromScan0(1500, 1050, 0, PixelFormat32bppARGB, ByVal 0, mBitmap)
//获取这个Bitmap关联的Graphics对象
Call GDI.GdipGetImageGraphicsContext(mBitmap, mBitmapGraphics)
//调用DrawBitmap绘图
DrawBitmap mBitmapGraphics, hImageRes, 34, 22

接下来就是绘制,首先获取点0,0位置的颜色值,判断rgb值都大于200,我们则可以认为他是白底,那么我们就需要绘制边框,否则最终不好裁剪。

然后就是根据是1寸还是2寸图片,分别绘制图像就行。

Private Sub DrawBitmap(ByVal graphics As Long, ByVal image As Long, ByVal lrSpacing, ByVal tbSpacing As Integer)
Dim mTotalWidth  As Integer, mWidth As Long, mHeight As Long
Dim mDrawBorder As Boolean
Dim mPicCount As IntegerDim offSetX As Integer, offSetY As Integer
Dim mPen As Long, mBackgroundBrush As Long
Call GDI.GdipBitmapGetPixel(image, 0, 0, rgbValue)r = (rgbValue / 2 ^ 16) And &HFF
g = (rgbValue / 2 ^ 8) And &HFF
b = (rgbValue / 2 ^ 0) And &HFFIf r > 200 And g > 200 And b > 200 ThenmDrawBorder = True
End IfCall GDI.GdipGetImageWidth(image, mWidth)
Call GDI.GdipGetImageHeight(image, mHeight)mPicCount = IIf(mWidth < 400, 3, 1)
If mPicCount = 1 Then Call GdipImageRotateFlip(image, Rotate90FlipNone)Call GDI.GdipGetImageWidth(image, mWidth)
Call GDI.GdipGetImageHeight(image, mHeight)mTotalWidth = ((mPicCount + 1) * mWidth) + ((mPicCount + 1) * lrSpacing)
mTotalHeight = (2 * mHeight) + tbSpacing0
offSetX = (1500 - mTotalWidth) / 2
offSetY = (1050 - mTotalHeight) / 2mPen = GDI.NewPen(&H4A323232, 2)
mBackgroundBrush = GDI.NewBrush(&HFFFFFFFF)Call GDI.GdipFillRectangle(graphics, mBackgroundBrush, 0, 0, 1500, 1050)
For i = 0 To mPicCountCall GDI.GdipDrawImageRect(graphics, image, offSetX + (i * mWidth) + (i * lrSpacing), offSetY, mWidth, mHeight)If (mDrawBorder) Then Call GDI.GdipDrawRectangle(graphics, mPen, offSetX + (i * mWidth) + (i * lrSpacing), offSetY, mWidth, mHeight)
Next
For i = 0 To mPicCountCall GDI.GdipDrawImageRect(graphics, image, offSetX + (i * mWidth) + (i * lrSpacing), offSetY + mHeight + tbSpacing, mWidth, mHeight)If (mDrawBorder) Then Call GDI.GdipDrawRectangle(graphics, mPen, offSetX + (i * mWidth) + (i * lrSpacing), offSetY + mHeight + tbSpacing, mWidth, mHeight)
NextEnd Sub

打印

打印花了好长时间,因为以前没做过,倒现在不懂,为什么向打印机DC贴图的时候,宽高为是326,x477。你猜我是怎么来的,看下图:

没错,是试出来的,此时内存中图像大小是1500x1050是没问题的,但是向打印机不能输出1500x1050。

打印的过程中还要旋转一下图像,否则打印出来的是竖着的。

通过CreateDC创建打印机的DC对象,由于GDI+不能向DC中绘制图像,先要使用GdipCreateFromHDC创建与这个DC关联的Graphics对象,接着就可以绘制了。

最重要的是设置纸张大小,但是在这里面要设置成1270x890,都要扩大10倍,鬼知道原因。

Private Sub PrintBitmap(ByVal Bitmap As Long)Dim OutString As StringDim lf As logfontDim temp As StringDim result As LongDim hOldfont As LongDim hPrintDc As LongDim hFont As LongDim di As DOCINFODim dm As DEVMODEdm = GetPrinterProperty("EPSON L805 Series")dm.dmPaperLength = 1270dm.dmPaperWidth = 890Dim mPrintGraphics As Longdi.cbSize = 20di.lpszDocName = "寸照"hPrintDc = CreateDC(Printer.DriverName, Printer.DeviceName, 0, dm)result = StartDoc(hPrintDc, di)result = StartPage(hPrintDc)GDI.GdipCreateFromHDC hPrintDc, mPrintGraphicsCall GdipImageRotateFlip(Bitmap, Rotate90FlipNone)Call GDI.GdipDrawImageRectI(mPrintGraphics, Bitmap, 0, 0, 326, 477)Call EndPage(hPrintDc)Call EndDoc(hPrintDc)Call DeleteDC(hPrintDc)
End Sub

注册表增加右键菜单

我们还要对png\jpg文件增加右键菜单,考虑到程序读写HKEY_CURRENT_USER\下不需要权限,但是找了好几个子项,都不能修改成功。

但是好赖还是找到了,位置如下。

\HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\

比如要增加对jpg文件右键菜单,可以依次创建下面项:

SystemFileAssociations\.jpg\shell\寸照打印\command

"寸照打印"是右击.jpg文件时候会在弹出的菜单中显示,如下:

还要在command下的默认项中要增加程序启动路劲。

F:\寸照\寸照.exe %0

前面就是我们程序所在路径,后面是一个参数表示方式,这个参数会转换成点击的文件路径,传递给我们程序。

但是没有使用程序增加,而是写了个脚本。

Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\.jpg\shell\寸照打印\command]
@="F:\\寸照\\寸照.exe %0"

使用上古神器帮姐姐完成寸照自动排版/打印相关推荐

  1. copilot 让AI帮你编程(人工智能自动完成)

    copilot 让AI帮你编程(人工智能自动完成) 官方地址 前不久,GitHub和OpenAI联合为程序员们送上了编程神器--GitHub Copilot. 但是,Copilot目前不提供公开使用, ...

  2. dev c++自动排版_再也不头疼文字排版了

    前言 在办公时,我们经常会需要用到Word,经常需要到网上查找一些资料然后整理排版,如果想提高文字排版.整理的效率.那么小编给你推荐Gidot Typesetter 这款非常好用的排版软件. Word ...

  3. python自动排版 html_Python 实现自动完成A4标签排版打印功能

    老婆大人让俺帮她通过Excel生成百人的准考证,她们学校打算来一次高考模拟.由于高考改革,每个学生的考试科目不一样,需要自动生成一下. 我一个程序员平时很少用到Excel,自己也不打算深入研究这个软件 ...

  4. Android Studio自动排版的两种方法

    Android Studio这样的集成开发环境虽然代码自动化程度很高,但是自动化程度高导致人的自主性就下降了,而且总是依赖编辑器的功能也会搞得代码排版很别扭. 最难受的是你在Android Studi ...

  5. VBNet WinForm如何开发一个照片自动排版程序

    想要开发一个照片自动排版程序要熟悉一下几个知识点: System.Drawing.Printing.PrintDocument.Print涉及到的纸张设置是英寸相关,我们常用的长度单位是毫米,那么先需 ...

  6. python标签打印_Python 实现自动完成A4标签排版打印功能

    老婆大人让俺帮她通过Excel生成百人的准考证,她们学校打算来一次高考模拟.由于高考改革,每个学生的考试科目不一样,需要自动生成一下. 我一个程序员平时很少用到Excel,自己也不打算深入研究这个软件 ...

  7. Android Studio自动排版格式化(android排版和xml排版)

    Android Studio自动排版格式化 今天自己想让Android Studio软件自动格式化排版,结果搜了一下,都说是Ctrl + Alt + L 结果不行 后面自已经过网上一些提示和自己探索终 ...

  8. python如何自动缩进_python word 自动排版写码时应该缩进使用 tab 还是空格?

    对于程序员来说,其实Tab和空格远远不只是"立场"问题那么简单. 在不同的编辑器里tab的长度可能不一致,所以在一个编辑器里用tab设置缩进后,在其它编辑器里看可能缩进就乱了.空格 ...

  9. cdrx4自动排版步骤_现在的大学生,都不会论文排版了

    因为排版问题而被论文导师一遍遍打回,听说广大毕业生实在是流干了眼泪.要想留住师生情,一部分排版工作是很有必要边写边做的. 今天,我将以厦门大学的本科毕业论文排版要求为例,给大家送上一份全面的毕业论文排 ...

最新文章

  1. 浅谈图分析商业化的机遇与挑战,你注意到了吗?
  2. 饿了么异地双活数据库实战
  3. dbeaver导出表结构和数据_Oracle 导入导出表空间跟数据表通用操作笔记
  4. invalid signature_php,微信开发JSSDK遇到的问题 config:invalid signature
  5. android手机活跃度,微信Android机型活跃度曝光,这个结果你满意吗?
  6. # 2019-2020.3 《java程序设计》第一周学习总结
  7. PHP动态验证,php-动态更改验证规则
  8. linux系统计算从1加到100之和思路风暴
  9. 10-10-009-简介-常用Message Queue对比
  10. SAP License:一个 SAP 新手的困惑
  11. 用户登录问题python_Python Flask单点登录问题
  12. (六)java版电子商务spring cloud分布式微服务b2b2c社交电商- commonservice-config配置服务搭建...
  13. 数学常用公式及规律、结论(三)
  14. c#自定义可拖动变形控件
  15. anaconda安装pygame失败怎么下载
  16. 通过 Bitmap Font Generator 生成 fnt 与 png 文件供 cocos2d-x 中 LabelBMFont 使用达到以图片表现数字
  17. 内点法解不等式约束的优化问题
  18. PAT题集2019.6.25排名变动
  19. python爬虫中遇到“\xb5”、“xa0”等字符时报错编码错误的处理方式
  20. 列出所有的电影ID,名字和销售总额(以百万美元为单位计算)

热门文章

  1. 音视频开发-音频数据处理流程
  2. 《赋予角色移动时的动画》part02——动画蓝图
  3. 1-(2-甲氧基乙基)-3-乙基咪唑三氟甲基磺酸盐{[C22O1IM][TfO]}离子液体
  4. php几个时间段去除重复,一个时间段内各地区数据和,发现重复地区不相加
  5. SpringCloudAlibaba(一)SpringCloudAlibaba简介
  6. nvidia卸载程序失败_英伟达显卡驱动安装失败怎么办?
  7. pytorch 文档网页离线 HTML and PDF
  8. 计算机学院杨洋,杨洋-地球科学与技术学院
  9. Because we are OIer
  10. spring源码构建时缺失spring-cglib-repack和spring-objenesis-repack的正确处理姿势