C++代码转为C#

东莞寻香苑 2013-08-03 11:52:55
At offset 24 (0x18) after the end of the DEVMODE structure, there is a byte that directly controls this setting.
So, you need only punch the right value into the right place, at the right time. You'll want to make the change to the application-global DEVMODE right before printing. I decided to put it in the easily-accessible OnPreparePrinting function of my View class.

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
PRINTDLG rPD;
BOOL fRet= AfxGetApp()->GetPrinterDeviceDefaults( &rPD );

LPDEVMODE pDM= (LPDEVMODE)::GlobalLock( rPD.hDevMode );

PBYTE pbDriverData= (PBYTE)(((BYTE *)pDM)+(pDM->dmSize));// right after the end

pbDriverData[24]= 2; // set to 4-up (1=2-up, 3=6-up, etc.)

::GlobalUnlock( rPD.hDevMode );

// default handling (as added by the ClassWizard)
return( DoPreparePrinting(pInfo) );
}

主要是这句:
PBYTE pbDriverData= (PBYTE)(((BYTE *)pDM)+(pDM->dmSize));
...全文
374 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jshi123 2013-08-10
  • 打赏
  • 举报
回复
我试了可以的。不过控制每张纸打印页数的参数并不一定是在第24个字节。你可以用下面这段代码看下你的打印机对应得参数的存放位置:

	var dialog = new PrintDialog();
	var hDevMode = dialog.PrinterSettings.GetHdevmode();
	var p = GlobalLock(hDevMode);
	var devmode = (DEVMODE)Marshal.PtrToStructure(p, typeof(DEVMODE));
	Console.WriteLine("Device Name: {0}\ndmSize: {1}\ndmDriverExtra: {2}",
		devmode.dmDeviceName, devmode.dmSize, devmode.dmDriverExtra);
	int len = devmode.dmDriverExtra;
	var buf = new byte[len];
	Marshal.Copy(p+devmode.dmSize, buf, 0, len);
	GlobalUnlock(hDevMode);
	dialog.ShowDialog();
	var hDevMode1 = dialog.PrinterSettings.GetHdevmode();
	var p1 = GlobalLock(hDevMode1);
	var buf2 = new byte[len];
	Marshal.Copy(p1+devmode.dmSize, buf2, 0, len);
	GlobalUnlock(hDevMode1);
	var changed = buf.Select((a, i) => new {i, a, b = buf2[i]}).Where(x => x.a != x.b);
	Console.WriteLine("changed bytes: {0}", changed.Count());
	foreach (var x in changed)
	{
		Console.WriteLine("offset {0}: {1} -> {2}", x.i, x.a, x.b);
	}
弹出打印框后,改一下“每张纸打印页数这个参数”,看看devmode的前后变化。
KJ_Wang 2013-08-10
  • 打赏
  • 举报
回复
网上有个工具,不知道叫什么了,可以的
东莞寻香苑 2013-08-10
  • 打赏
  • 举报
回复
引用 8 楼 jshi123 的回复:

	const int CCHDEVICENAME = 32;

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	public struct DEVMODE
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
		public string dmDeviceName;
		public short dmSpecVersion;
		public short dmDriverVersion;
		public short dmSize;
		public short dmDriverExtra;
		// 其余字段不用省略
	}

	[DllImport("kernel32.dll")]
	public static extern IntPtr GlobalLock(IntPtr handle);

	[DllImport("kernel32.dll")]
	public static extern IntPtr GlobalUnlock(IntPtr handle);

	void Print()
	{
		var dialog = new PrintDialog();
		var hDevMode = dialog.PrinterSettings.GetHdevmode();
		var p = GlobalLock(hDevMode);
		var devmode = (DEVMODE)Marshal.PtrToStructure(p, typeof(DEVMODE));
		p = p + devmode.dmSize + 24;
		Marshal.WriteByte(p, 3);
		GlobalUnlock(hDevMode);
		dialog.PrinterSettings.SetHdevmode(hDevMode);
		Marshal.FreeHGlobal(hDevMode);
		var result = dialog.ShowDialog();
		。。。
	}
这个可以吗? 我的怎么不行呢 郁闷死了
jshi123 2013-08-08
  • 打赏
  • 举报
回复

	const int CCHDEVICENAME = 32;

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	public struct DEVMODE
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
		public string dmDeviceName;
		public short dmSpecVersion;
		public short dmDriverVersion;
		public short dmSize;
		public short dmDriverExtra;
		// 其余字段不用省略
	}

	[DllImport("kernel32.dll")]
	public static extern IntPtr GlobalLock(IntPtr handle);

	[DllImport("kernel32.dll")]
	public static extern IntPtr GlobalUnlock(IntPtr handle);

	void Print()
	{
		var dialog = new PrintDialog();
		var hDevMode = dialog.PrinterSettings.GetHdevmode();
		var p = GlobalLock(hDevMode);
		var devmode = (DEVMODE)Marshal.PtrToStructure(p, typeof(DEVMODE));
		p = p + devmode.dmSize + 24;
		Marshal.WriteByte(p, 3);
		GlobalUnlock(hDevMode);
		dialog.PrinterSettings.SetHdevmode(hDevMode);
		Marshal.FreeHGlobal(hDevMode);
		var result = dialog.ShowDialog();
		。。。
	}
东莞寻香苑 2013-08-07
  • 打赏
  • 举报
回复
非常感谢,但那些功能已经实现. 现在就是被指针这东西搞死了,就是想得到那块内存地址的内容(我处理不了)
FTD_2009 2013-08-05
  • 打赏
  • 举报
回复
网上应该有转换器吧,我是小白求大神讲解
soaringbird 2013-08-05
  • 打赏
  • 举报
回复
BOOL fRet= AfxGetApp()->GetPrinterDeviceDefaults( &rPD );这一行恐怕不好转换为C#的。别的部分代码都是操作指针的,C#的指针跟C++里的几乎是一样的,很好改写。 c#控制打印机,你可以看看这篇,能不能满足你的需求: http://www.codeproject.com/Articles/6899/Changing-printer-settings-using-C
soaringbird 2013-08-03
  • 打赏
  • 举报
回复
unsafe代码,差不多的写法 byte* pbDriverData= (byte*)(((byte *)pDM)+(pDM->dmSize));
soaringbird 2013-08-03
  • 打赏
  • 举报
回复
PBYTE pbDriverData= (PBYTE)(((BYTE *)pDM)+(pDM->dmSize));// 这个是啥意思?GetPrinterDeviceDefaults取到的数据不仅有DEVMODE ?还有pbDriverData? 你到底想要DEVMODE还是pbDriverData?
东莞寻香苑 2013-08-03
  • 打赏
  • 举报
回复
我的意思是 PBYTE pbDriverData= (PBYTE)(((BYTE *)pDM)+(pDM->dmSize));// 得到DEVMODE的那些内容 private const short CCDEVICENAME = 32; private const short CCFORMNAME = 32; [StructLayout(LayoutKind.Sequential)] public struct DEVMODE { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)] public string dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; public short dmSize; public short dmDriverExtra; public int dmFields; public short dmOrientation; public short dmPaperSize; public short dmPaperLength; public short dmPaperWidth; public short dmScale; public short dmCopies; public short dmDefaultSource; public short dmPrintQuality; public short dmColor; public short dmDuplex; public short dmYResolution; public short dmTTOption; public short dmCollate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)] public string dmFormName; public short dmUnusedPadding; public short dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlags; public int dmDisplayFrequency; }

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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