word 打开多个文档进行打印,获取每个文档的打印份数dmCopies 不正确

songhongzhu_518 2012-05-25 09:54:44
用的是office2003,获取打印份数dmCopiecs有一个BUG,已经安网上说的修改过了(http://support.microsoft.com/kb/919736/zh-cn)安了sp3, 添加了注册表,也可以取到打印份数;在word里面HOOK了打印,取打印份数,单个文档打印时取dmCopiecs是对的,但是打开多个文档对文档进行打印时,某些情况取到的值就不对了。各种情况如下:

1.打开两个文档A,B
打印文档A,设置打印份数为1
打印文档B,设置打印份数为5
关闭文档A,关闭文档B
取到的打印份数分别为 :文档A dmCopiecs = 1, 文档B dmCopiecs = 5
这种情况取到的值是对的

2. 打开两个文档A,B
打印文档A,设置打印份数为5
打印文档B,设置打印份数为1
关闭文档A,关闭文档B
取到的打印份数分别为 :文档A dmCopiecs = 5, 文档B dmCopiecs = 5
这种情况取到的值是错的

3. 打开文档A,B
打印文档A,设置打印份数为3,
打印文档B,设置打印份数为2
关闭文档A打印文档B,设置打印份数为2
关闭文档A,关闭文档B
取到的打印份数分别为 :文档A dmCopiecs = 3, 文档B dmCopiecs = 2
这种情况取到的值是对的

4.
打开文档A,打印文档A,设置打印份数为5
关闭文档A
打开文档B,打印文档B,设置打印份数为1
关闭文档B
取到的打印份数分别为 :文档A dmCopiecs = 5, 文档B dmCopiecs = 1
这种情况取到的值是对的

什么原因造成这样的问题,应该怎么解决?
...全文
834 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
jhx2013 2013-08-13
  • 打赏
  • 举报
回复
你好啊。请问这个问题,你解决了吗,我也是断断续续的做了好久,和你遇到的情况一样,还没解决。Please Help me, Thank u.
赵4老师 2012-07-03
  • 打赏
  • 举报
回复
实在不行恐怕得用ReadProcessMemory了。
赵4老师 2012-07-03
  • 打赏
  • 举报
回复
实在不行恐怕得用ReadProcessMemory了。
推荐使用WinHex软件查看文件或内存中的原始字节内容。
songhongzhu_518 2012-07-03
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

请问楼上,如果选择的打印机是虚拟打印机,这些Windows API还会被调用,还能HOOK到吗?
[/Quote]
应该是可以,我只是在word里hook了StartDocPrinter,EndDocPrinter,如果选择的虚拟打印机,也会hook到
蒋晟 2012-06-03
  • 打赏
  • 举报
回复
虚拟打印机不属于Windows,没有通用API……
Tomcat4 2012-05-31
  • 打赏
  • 举报
回复
请问楼上,如果选择的打印机是虚拟打印机,这些Windows API还会被调用,还能HOOK到吗?
songhongzhu_518 2012-05-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
微软没有提供虚拟打印机的文件API……虚拟打印机只需要实现打印接口,其他行为是否实现,是否为这些行为提供接口则取决于驱动的作者,打印驱动的文件对话框行为是没有标准化的接口的。你看看是不是把这部分功能自己实现,让用户选择份数之后写个打印到PDF、PS或者XPS的功能,之后再调用系统的打印功能把结果打出来,这样你可以在打印之前就知道用户选择的打印份数。
[/Quote]
太感谢您看到了我的留言,这个问题可能有点绕跑题了,我做了一个word的插件程序,在程序里我hook了StartDocPrinter,EndDocPrinter,在这两个地方我都EnumJobs枚举打印作业取JOB_INFO_2结构就中的pDevMode成员中的dmCopies。如果我打印一次关闭一个word这样取到dmCopies都是正确了,但是如果在word不关闭的情况下多次打印,就可能出现问题,我不知道我叙述的是否清楚,在网上找过相关的资料,实际上我遇到了和下面说的相同的问题,不知道解决办法,现在就卡在这个问题上了

http://social.msdn.microsoft.com/Forums/fi-FI/worddev/thread/9b6ab313-c100-4791-97f8-6ddf03e404f9
蒋晟 2012-05-26
  • 打赏
  • 举报
回复
微软没有提供虚拟打印机的文件API……虚拟打印机只需要实现打印接口,其他行为是否实现,是否为这些行为提供接口则取决于驱动的作者,打印驱动的文件对话框行为是没有标准化的接口的。你看看是不是把这部分功能自己实现,让用户选择份数之后写个打印到PDF、PS或者XPS的功能,之后再调用系统的打印功能把结果打出来,这样你可以在打印之前就知道用户选择的打印份数。
赵4老师 2012-05-25
  • 打赏
  • 举报
回复
Copies 属性
返回或设置一个 Long 值,表明要打印的份数。可读写。

Printer.Copies

示例
下面的示例为当前项目中的第一个窗体设置各种打印机设置。

With Forms(0).Printer

.TopMargin = 1440
.BottomMargin = 1440
.LeftMargin = 1440
.RightMargin = 1440

.ColumnSpacing = 360
.RowSpacing = 360

.ColorMode = acPRCMColor
.DataOnly = False
.DefaultSize = False
.ItemSizeHeight = 2880
.ItemSizeWidth = 2880
.ItemLayout = acPRVerticalColumnLayout
.ItemsAcross = 6

.Copies = 1
.Orientation = acPRORLandscape
.Duplex = acPRDPVertical
.PaperBin = acPRBNAuto
.PaperSize = acPRPSLetter
.PrintQuality = acPRPQMedium

End With

songhongzhu_518 2012-05-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
内置对话框参数列表
参阅特性您可能需要对 Microsoft Word 中的许多内置对话框的选项进行设置。若要设置或返回与 Word 对话框相关的属性,可使用等效的 Visual Basic 属性和方法。例如,如果需要打印文档,可使用 Word Visual Basic for Applications 的 PrintOut 方法。下列代码使用“打印”对话框中的默认设置打印当前文档。但是,如果不……
[/Quote]
使用Dialogs(wdDialogFilePrint)调用打印对话框取值,这个我也试过,要想取到正确的NumCopies值,只能是拦截word的DocumentBeforePrint 事件,在这个事件里自己弹出Dialogs(wdDialogFilePrint),show()显示执行打印,那么在这儿是可以取到NumCopies的正确值的,但是如果使用虚拟打印,一般会在打印对话框出来选择确定后,还会有一个它自己的对话框,一般可以能是“文件另存为”对话框,这个对话框如果不选择确定,那么它是不会打印的,而这个虚拟打印机自己的对话框是选择的确定还是取消,只有确定我才要取打印份数,而我根本没有办法知道用户选择的是确定还是取消。
基本上用VBA取打印份数不满足我的要求,所以我才要用HOOK API的方法,而且枚举打印机的作业任务,但是在WORD里按照我所描述的方法操作,就出现在了DEVMODE结构中dmCopiecs数据的不正确。
赵4老师 2012-05-25
  • 打赏
  • 举报
回复
内置对话框参数列表
参阅特性您可能需要对 Microsoft Word 中的许多内置对话框的选项进行设置。若要设置或返回与 Word 对话框相关的属性,可使用等效的 Visual Basic 属性和方法。例如,如果需要打印文档,可使用 Word Visual Basic for Applications 的 PrintOut 方法。下列代码使用“打印”对话框中的默认设置打印当前文档。但是,如果不希望使用“打印”对话框中的默认设置,可以使用与 PrintOut 方法相关的参数。

Sub PrintCurrentDocument()
ThisDocument.PrintOut
End Sub
虽然推荐您使用 VBA 关键字获取或设置对话框选项的值,但许多内置的 Word 对话框也具有可用于设置或获取对话框值的参数。详细信息,请参阅显示内置 Word 对话框。

WdWordDialog 常量 参数列表
wdDialogFilePrint Background、AppendPrFile、Range、PrToFileName、From、To、Type、NumCopies、Pages、Order、PrintToFile、Collate、FileName、Printer、OutputPrinter、DuplexPrint、PrintZoomColumn、PrintZoomRow、PrintZoomPaperWidth、PrintZoomPaperHeight 和 ZoomPaper
赵4老师 2012-05-25
  • 打赏
  • 举报
回复
在Word2003中开始记录宏,手动完成所需功能,结束记录宏,按Alt+F11键,查看刚才记录的宏对应的VBA代码。
Sub Macro2()
'
' Macro2 Macro
' 宏在 2012-05-25 由 Zhao4Zhong1@163.com 录制
'
Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
wdPrintDocumentContent, Copies:=2, Pages:="", PageType:=wdPrintAllPages, _
ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
End Sub
songhongzhu_518 2012-05-25
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

“VC通过COM调用VBA对象”和“用VBA调用VBA对象”两者有本质区别吗?

1.在VC中新建一控制台程序,选支持MFC(当然,你也可以不选择支持MFC的,不过会很麻烦)
2.按CTRL+W调出MFC ClassWizard,Add Class->From a type library,选择你的word的类型库
(例如我的是word2003,安装在e盘,我的路径是"e:\edit……
[/Quote]

我对com和VBA的研究并不是很深,所在说的不一定对,我个人觉得区别不大,我也确实是导入word相关的库通过com方式操作WORD,但是我要拦截word打印的某些信息,我曾经考虑过用word的打印事件(DocumentBeforePrint 事件)结论是不行,只通word提供的接口无法实现我要的功能,您之前提供给我的VBA代码,在word里是不能执行的,word中没有“form”对象,这个对象是Access里的(office产品中是否支持该对象我不清楚)
赵4老师 2012-05-25
  • 打赏
  • 举报
回复
“VC通过COM调用VBA对象”和“用VBA调用VBA对象”两者有本质区别吗?

1.在VC中新建一控制台程序,选支持MFC(当然,你也可以不选择支持MFC的,不过会很麻烦)
2.按CTRL+W调出MFC ClassWizard,Add Class->From a type library,选择你的word的类型库
(例如我的是word2003,安装在e盘,我的路径是"e:\edittools\microsoft office\office11\msword.olb"),
选择完毕后,在弹出的窗口中选择要让classwizard生成的包装类,在本例中要用到
_Application,
Documents,
_Document,
Range
这四个类,选中他们后按OK
3.进入你的main函数所在的cpp文件,加入头文件引用
#include "msword.h" //引用刚才classwizard生成的idispatch包装类
4.加入代码
// console_word.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "console_word.h"
#include "msword.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;

// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
printf(_T("Fatal Error: MFC initialization failed!\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
if (CoInitialize(NULL) != S_OK)
{
AfxMessageBox("初始化COM支持库失败!");
return -1;
}

_Application wordApp;
Documents docs;
_Document doc;
Range aRange;
COleVariant vTrue((short)TRUE), vFalse((short)FALSE), vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
CString txt;

wordApp.CreateDispatch("Word.Application",NULL);
wordApp.SetVisible(FALSE);
docs=wordApp.GetDocuments();
doc=docs.Open(COleVariant("c:\\new\\测试.doc"),vFalse,vTrue,vFalse,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt);
aRange=doc.Range(vOpt,vOpt);
txt=aRange.GetText();
AfxMessageBox(txt);//这里GetText得到的就是word文件的纯文本了,你可以将其写到txt文件中
printf("[%s]\n",txt.GetBuffer(txt.GetLength()));//里面的换行不是\r\n而是\r,所以需要输出重定向到文本文件看结果。
aRange.ReleaseDispatch();
doc.Close(vOpt,vOpt,vOpt);
doc.ReleaseDispatch();
docs.ReleaseDispatch();
wordApp.Quit(vOpt,vOpt,vOpt);
wordApp.ReleaseDispatch();

CoUninitialize();
}

return nRetCode;
}


songhongzhu_518 2012-05-25
  • 打赏
  • 举报
回复
我是用VC写的,想拦截WORD文档打印时的打印份数,我已经可以取到打印份数了,但是在word不关闭的情况下,多次打印时就会取出数据就是错误的。

我在第一个打印作业设置打印1份,第二次2份,第三次1份。

我从DEVMODE的得到信息:

第一作业 dmCopiecs = 1,第二个作业 dmCopiecs = 2,第三的作作业 dmCopiecs = 2。

只要在word不关闭的情况下,多次打印,如果设置打印份数为1,那么取出的DEVMODE中的dmCopiecs (打印份数)就是不对的,其值总是我上一次打印作业设置的份数。

我用的系统是XPsp3, word2003(sp3), 这个问题,只有当我从高至1设置打印份数时就会出现,但如果我将它设置从5到3取到的dmCopiecs 值就是正确的,就不会出现这种情况。

不知道我这么说的明不明白,有没有其他人遇到过这个问题,求解决办法
songhongzhu_518 2012-05-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

Copies 属性
返回或设置一个 Long 值,表明要打印的份数。可读写。

Printer.Copies

示例
下面的示例为当前项目中的第一个窗体设置各种打印机设置。

With Forms(0).Printer

.TopMargin = 1440
.BottomMargin = 1440
.LeftMargin = 1440
.……
[/Quote]
谢谢你的帮助,你这个应该是VB的代码吧,这个对我没有什么用处,我是用VC写的

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧