public int Print(int charFrom, int charTo, PrintPageEventArgs e) { //Calculate the area to render and print RECT rectToPrint; rectToPrint.Top = (int)(e.MarginBounds.Top * anInch); rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch); rectToPrint.Left = (int)(e.MarginBounds.Left * anInch); rectToPrint.Right = (int)(e.MarginBounds.Right * anInch); //Calculate the size of the page RECT rectPage; rectPage.Top = (int)(e.PageBounds.Top * anInch); rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch); rectPage.Left = (int)(e.PageBounds.Left * anInch); rectPage.Right = (int)(e.PageBounds.Right * anInch); IntPtr hdc = e.Graphics.GetHdc(); FORMATRANGE fmtRange; fmtRange.chrg.cpMax = charTo; //Indicate character from to character to fmtRange.chrg.cpMin = charFrom; fmtRange.hdc = hdc; //Use the same DC for measuring and rendering fmtRange.hdcTarget = hdc; //Point at printer hDC fmtRange.rc = rectToPrint; //Indicate the area on page to print fmtRange.rcPage = rectPage; //Indicate size of page IntPtr res = IntPtr.Zero; IntPtr wparam = IntPtr.Zero; wparam = new IntPtr(1); //Get the pointer to the FORMATRANGE structure in memory IntPtr lparam = IntPtr.Zero; lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange)); Marshal.StructureToPtr(fmtRange, lparam, false); //Send the rendered data for printing res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam); //Free the block of memory allocated Marshal.FreeCoTaskMem(lparam); //Release the device context handle obtained by a previous call e.Graphics.ReleaseHdc(hdc); //Return last + 1 character printer return res.ToInt32(); }
http://blog.csdn.net/zgke/archive/2008/11/06/3236058.aspx
但是现在问题是。不能直接打印出来,要把这个内容,存成一张图片。
我现在就是想要这张图,请问该如何做转换呢?
{
SaveFileDialog myDlg = new SaveFileDialog();
myDlg.Title = "另存为";
myDlg.OverwritePrompt = true;
myDlg.Filter = "BMP文件 (*.bmp) | *.bmp|" +
"Gif文件 (*.gif) | *.gif|" +
"JPEG文件 (*.jpg) | *.jpg|" +
"PNG文件 (*.png) | *.png";
myDlg.ShowHelp = true; if (myDlg.ShowDialog() == DialogResult.OK)
{
string fileName = myDlg.FileName;
string strfileEx = fileName.Remove(0, fileName.Length - 3);
switch (strfileEx)
{
case "bmp":
curBitmap.Save(fileName, ImageFormat.Bmp);
break; case "jpg":
curBitmap.Save(fileName, ImageFormat.Jpeg);
break; case "gif":
curBitmap.Save(fileName, ImageFormat.Gif);
break; case "tif":
curBitmap.Save(fileName, ImageFormat.Tiff);
break; case "png":
curBitmap.Save(fileName, ImageFormat.Png);
break; default:
break;
}
} }
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "图片文件|*.jpg|所有文件|*.*";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
Clipboard.SetDataObject(Image.FromFile(openFileDialog1.FileName), false);
richTextBox1.Paste();
}
}
这一句之后知道Hdc被release之前。是无法操作 e.Graphics对象的。所以还是存不到图。
不知道你的代码里curBitmap是从哪里来的。谢谢你的回复。
richtextbox控件有一个成员方法,叫做:DrawToBitmap……然后你把导出来的图片存起来就好了……还有什么需要?
为什么我的C#中richtextbox控件没有这么个成员呢?
我说的是winform下的richtextbox
如果你是WPF下的RICHTEXTBOX的话,根本就不用处理,你去查看一下flowdocument就可以了。
谢谢。
GetImage取出来的是null;
rtb.Update(); // Ensure RTB fully painted
Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
using (Graphics gr = Graphics.FromImage(bmp)) {
gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
}
return bmp;
}那就试试这个吧。这个看得懂吧……那个 gr 很好用。
有一个很perfect的方法,不过怕你看不懂,呵呵,没有,其实挺简单的,想要么?
但是还有问题,如果这个rtb的内容不止一页,就是由滚动条的时候,滚动条下边的内容就不能在图上显示。to Harvey_He
没找到PageInfo,我在打印的事件里吧graphic取到了转存后的图片是一片漆黑
太晕了。
肯定是我的方法不对。
[DllImport("USER32.dll")]
private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
private const int WM_USER = 0x400;
private const int EM_FORMATRANGE = WM_USER + 57;// 再是所需要的结构体的定义:
[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
// 望文生义吧[StructLayout(LayoutKind.Sequential)]
private struct CHARRANGE {
public int cpMin;
public int cpMax;
}[StructLayout(LayoutKind.Sequential)]
private struct FORMATRANGE {
public IntPtr hdc;
public IntPtr hdcTarget;
public RECT rc;
public RECT rcPage;
public CHARRANGE chrg;
}
// 将RTB上的内容格式化后画出来public static Bitmap RtbToBitmap(RichTextBox rtb)
{
return RtbToBitmap(rtb,rtb.ClientRectangle.Width,rtb.ClientRectangle.Height);
}public Bitmap RtbToBitmap(RichTextBox rtb, int width, int height)
{
Bitmap bmp = new Bitmap(width, height);
using (Graphics gr = Graphics.FromImage(bmp))
{
System.IntPtr hDC = gr.GetHdc(); // 屏幕做为画源
FORMATRANGE fmtRange;
RECT rect;
int fromAPI;
rect.Top = 0; rect.Left = 0;
rect.Bottom = (int)(bmp.Height + (bmp.Height * (bmp.HorizontalResolution / 100)) * inch);
rect.Right = (int)(bmp.Width + (bmp.Width * (bmp.VerticalResolution / 100)) * inch);
fmtRange.chrg.cpMin = 0;
fmtRange.chrg.cpMax = -1;
fmtRange.hdc = hDC;
fmtRange.hdcTarget = hDC;
fmtRange.rc = rect;
fmtRange.rcPage = rect;
int wParam = 1;
System.IntPtr lParam = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
System.Runtime.InteropServices.Marshal.StructureToPtr(fmtRange, lParam, false);
fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, lParam);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(lParam);
fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, new IntPtr(0));
gr.ReleaseHdc(hDC);
} return bmp;
}
好吧,那还有一个更好的方法。你会格式化“绘画”文本吗?对于纯文本的内容的话,那么你就把所有的文本都缓存起来,然后建一个适当大的图,用Graphic.DrawText去往上面画!至于该做多大的图,你可以自己设定画上去的文字的大小和行间距,这一切都是由你来调整。我做过一个打印程序,就是这么干的。你这不是绘图,是打印文本。或者说,如果你问大家,该如何把RTB中的内容“打印”出来的话……
你上边发的那段代码
inch这个变量没有,我用10替换了它。
存出来还是黑色的。
这个inch是什么呢?你说的画文本的方式是不行的。因为rtb理由可能是图文混排的内容。谢谢
10嘛……差点……图文混排可就难了。除非你记录下来所有图片的位置,以及与文本的相对位置,打印的时候,到什么地方,就打印什么内容,graphic类里面有对应的方法。打印就是这么的,别无它法。我认为你这个问题,就是RICHTEXT打印。
其实打印,网上就有源码。但是我要的是存成图片。
你可以打印成图片啊……将 Graphic的源设为你要保存的image就行了。
在绘图之前加上: for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
bmp.SetPixel(i, j, Color.White);
}
}将整个图先画成白色,然后再绘制richtextbox的内容。不过这种做法,仍然只能绘制 控件内的可见内容,对于不可见内容的绘制,请使用我在32楼提的方法。首先你要记录排版,然后将文本和图片定位“打印”到图片上。
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "图片文件|*.jpg|所有文件|*.*";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
Clipboard.SetDataObject(Image.FromFile(openFileDialog1.FileName), false);
richTextBox1.Paste();
}
}
{
//Calculate the area to render and print
RECT rectToPrint;
rectToPrint.Top = (int)(e.MarginBounds.Top * anInch);
rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch);
rectToPrint.Left = (int)(e.MarginBounds.Left * anInch);
rectToPrint.Right = (int)(e.MarginBounds.Right * anInch); //Calculate the size of the page
RECT rectPage;
rectPage.Top = (int)(e.PageBounds.Top * anInch);
rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch);
rectPage.Left = (int)(e.PageBounds.Left * anInch);
rectPage.Right = (int)(e.PageBounds.Right * anInch); IntPtr hdc = e.Graphics.GetHdc(); FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = charTo; //Indicate character from to character to
fmtRange.chrg.cpMin = charFrom;
fmtRange.hdc = hdc; //Use the same DC for measuring and rendering
fmtRange.hdcTarget = hdc; //Point at printer hDC
fmtRange.rc = rectToPrint; //Indicate the area on page to print
fmtRange.rcPage = rectPage; //Indicate size of page IntPtr res = IntPtr.Zero; IntPtr wparam = IntPtr.Zero;
wparam = new IntPtr(1); //Get the pointer to the FORMATRANGE structure in memory
IntPtr lparam = IntPtr.Zero;
lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lparam, false); //Send the rendered data for printing
res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam); //Free the block of memory allocated
Marshal.FreeCoTaskMem(lparam);
//Release the device context handle obtained by a previous call e.Graphics.ReleaseHdc(hdc);
//Return last + 1 character printer
return res.ToInt32();
}