中國最大的web開發資源網站及技術社區,
前篇說了.net環境下有關打印頁面設置、打印機設置、打印預覽對話框的實現,現在到了我們應用它們的時候了。
我們需要做下面的一些事情:
1、將上篇中寫的程序輸出類型改為類庫并編譯成printerpagesetting.dll;
2、建立c#或vb.net項目,并在項目的引用處添加引用,在彈出的對話框的.net標簽中瀏覽并選擇printerpagesetting.dll;
3、在默認窗口form1上增加一個textbox文本框控件,默認名textbox1(實際項目中建議采用命名及編碼規范,如frmtestprint,txtprint)
4、從工具箱中拖一個mainmenu到窗口form1,創建mainmenu1菜單對象,建立主菜單menufile
5、單擊menufile,在其下方輸入處分別建立menufilepagesetup、menufileprintpreview、menufileprint菜單。我想大家明白這幾個菜單的意義了,這是命名規范最基本的。
準備工作做完了,看看我們怎么使用printerpagesetting輕松完成打印頁面設置、打印機設置、打印預覽對話框。
第一步:在窗口類中申明并實例化printerpagesetting,當然實例化對象可以放在構造函數中。
c#:
private goldprinter.printerpagesetting printerpagesetting = new goldprinter.printerpagesetting();
vb.net:
private printerpagesetting as new goldprinter.printerpagesetting
第二步:寫一個實現打印的具體過程
c#:
private void printdocument_printpage_handler(object o,system.drawing.printing.printpageeventargs e)
{
system.drawing.graphics g = e.graphics;
if (draw(g))
{
e.hasmorepages = true; //要分頁打印
}
else
{
e.hasmorepages = false; //打印結束
}
}
vb.net:
private sub printdocument_printpage(byval sender as object, byval e as system.drawing.printing.printpageeventargs)
dim g as system.drawing.graphics = e.graphics
if me.draw(g) then
e.hasmorepages = true '要分頁打印
else
e.hasmorepages = false '打印結束
end if
end sub
大家可以看到我們是怎么使程序在打印時自動分頁的,就是設置hasmorepages屬性為真就可以了。為了清晰可見,我將真正打印的具體過程獨立出來用draw()實現。
在第二步中我們實現打印的具體過程,在printerpagesetting類中,我們并不知道打印的具體實現,就設計了printpage委托,讓調用者自己實現,然后告訴printerpagesetting是用哪一個方法實現,也就是第三步了。
第三步:打印委托
在窗口空白處雙擊,在form1_load事件中輸入相關語句。當然也可以放在構造函數中,這里為了描述的方便。
c#:
private void form1_load(object sender, system.eventargs e)
{
this.printerpagesetting.printpage += new goldprinter.printpagedelegate(printdocument_printpage_handler);
}
如果你不知上一句是什么意思,就用這一句吧:
this.printerpagesetting.printpagevalue = new goldprinter.printpagedelegate(printdocument_printpage_handler);
意思就是告訴printerpagesetting打印的具體實現過程是printdocument_printpage_handler(第二步)
vb.net:
private sub form1_load(byval sender as system.object, byval e as system.eventargs) handles mybase.load
me.printerpagesetting.printpagevalue = new goldprinter.printpagedelegate(addressof printdocument_printpage)
end sub
大家還可以一試啊,
private withevents printdocument as system.drawing.printing.printdocument '第一步:在申明窗口級變量
me.printdocument = me.printerpagesetting.printdocument '第二步:在此將兩個量聯系起來
將printdocument_printpage(...)加上 handles printdocument.printpage
第四步:顯示頁面設置/打印機設置/打印預覽對話框
分別在幾個菜單上單擊,具體代碼如下:
c#:
private void menufilepagesetup_click(object sender, system.eventargs e)
{
this.printerpagesetting.showpagesetupdialog(); //顯示頁面設置對話框
}
private void menufileprintpreview_click(object sender, system.eventargs e)
{
this.printerpagesetting.showprintpreviewdialog(); //顯示打印預覽對話框
}
private void menufileprint_click(object sender, system.eventargs e)
{
this.printerpagesetting.showprintsetupdialog(); //顯示打印預覽對話框
}
vb.net:
private sub menufilepagesetup_click(byval sender as system.object, byval e as system.eventargs) handles menufilepagesetup.click
me.printerpagesetting.showpagesetupdialog()
end sub
private sub menufileprintpreview_click(byval sender as system.object, byval e as system.eventargs) handles menufileprintpreview.click
me.printerpagesetting.showprintpreviewdialog()
end sub
private sub menufileprint_click(byval sender as system.object, byval e as system.eventargs) handles menufileprint.click
me.printerpagesetting.showprintsetupdialog()
end sub
哈哈,到現在為此,我們做的工作基本完成了,不過不要忘了draw()噢。
c#:
private bool draw(system.drawing.graphics g)
{
g.drawstring("hello world!",new font("宋體",15),brushes.black,new pointf(0,0));
return false;
}
vb.net:
private function draw(byval g as system.drawing.graphics) as boolean
g.drawstring("hello world!", new font("宋體", 15), brushes.black, new pointf(0, 0))
return false
end function
大家可不要笑這個draw()太簡單喲!運行看看,嘿,程序確實能夠完成打印頁面設置、打印機設置、打印預覽對話框的功能,還能設置橫向縱向打印,改變紙張大小等設置呢。
擴展:
當然,既然printdocument_printpage_handler()與printdocument_printpage()組織的清晰且能夠分頁,那我就不讓大家遺憾了。
我現在分別用vb.net和c#實現一個能夠分頁打印的例子,而且上面的工作不白做,僅僅改一下draw()就可以了。
vb.net:
private function draw(byval g as system.drawing.graphics) as boolean
return drawtext(g, me.printerpagesetting.printdocument, me.textbox1.text)
end function
'這段代碼改編自msdn
private function drawtext(byval g as system.drawing.graphics, byval pdoc as system.drawing.printing.printdocument, byval text as string) as boolean
g.drawstring("hello world!", new font("宋體", 15), brushes.black, new pointf(0, 0))
return false
static intcurrentchar as int32
dim font as new font("宋體", 10)
dim intprintareaheight, intprintareawidth as int32
with pdoc.defaultpagesettings
intprintareaheight = .papersize.height - .margins.top - .margins.bottom
intprintareawidth = .papersize.width - .margins.left - .margins.right
end with
' 橫向打印,寬與高交換
if pdoc.defaultpagesettings.landscape then
me.swap(intprintareawidth, intprintareaheight)
end if
'定義打印區域
dim rectprintingarea as new rectanglef(pdoc.defaultpagesettings.margins.left, pdoc.defaultpagesettings.margins.top, intprintareawidth, intprintareaheight)
dim fmt as new stringformat(stringformatflags.linelimit)
dim intlinesfilled, intcharsfitted as int32
g.measurestring(mid(text, intcurrentchar + 1), font, _
new sizef(intprintareawidth, intprintareaheight), fmt, _
intcharsfitted, intlinesfilled)
g.drawstring(mid(text, intcurrentchar + 1), font, _
brushes.black, rectprintingarea, fmt)
intcurrentchar += intcharsfitted
if intcurrentchar < text.length then
return true
else
intcurrentchar = 0
return false
end if
end function
'兩個數的值互換
private sub swap(byref i as int32, byref j as int32)
dim tmp as int32 = i
i = j
j = tmp
end sub
vb.net實現了,那我就換一個面向對象的實現方法吧。
c#:
在c#項目上右鍵選擇添加/添加類,命名為drawtext.cs,這里列出全部內容:
///
/// 在繪圖表面區域內繪制文本
///
public class drawtext
{
private graphics _graphics;
private rectanglef _rectanglef;
private string _text;
private font _font;
private brush _brush;
private stringformat _stringformat;
private int _startchar;
private int _linesfilled;
private int _charsfitted;
#region 字段屬性
public graphics graphics
{
get
{
return _graphics;
}
set
{
_graphics = value;
}
}
public rectanglef rectanglef
{
get
{
return _rectanglef;
}
set
{
_rectanglef = value;
}
}
public string text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public font font
{
get
{
return _font;
}
set
{
if (value != null)
{
_font = value;
}
}
}
public brush brush
{
get
{
return _brush;
}
set
{
if (value != null)
{
_brush = value;
}
}
}
public stringformat stringformat
{
get
{
return _stringformat;
}
set
{
_stringformat = value;
}
}
public int startchar
{
get
{
return _startchar;
}
set
{
_startchar = value;
if (_startchar < 0)
{
_startchar = 0;
}
}
}
public int charsfitted
{
get
{
return _charsfitted;
}
}
public int linesfilled
{
get
{
return _linesfilled;
}
}
#endregion
public drawtext()
{
_text = "";
_font = new font("宋體",10);
_rectanglef = new rectanglef(0,0,0,_font.height);
_brush = brushes.black;
_startchar = 0;
_linesfilled = 0;
_charsfitted = 0;
_stringformat = new stringformat(stringformatflags.linelimit);
}
public drawtext(string text):this()
{
_text = text;
}
public void draw()
{
if (_graphics != null)
{
int intlinesfilled, intcharsfitted;
_graphics.measurestring(_text.substring(_startchar),_font,new sizef(_rectanglef.width, _rectanglef.height),_stringformat,out intcharsfitted,out intlinesfilled);
_graphics.drawstring(_text.substring(_startchar),_font,_brush,_rectanglef,_stringformat);
this._linesfilled = intlinesfilled;
this._charsfitted = intcharsfitted;
}
}
然后將原來的draw()用下面的語句替換掉:
private static int intcurrentcharindex;
private bool draw(system.drawing.graphics g)
{
float width,height;
width = this.printerpagesetting.printdocument.defaultpagesettings.papersize.width - this.printerpagesetting.printdocument.defaultpagesettings.margins.left - this.printerpagesetting.printdocument.defaultpagesettings.margins.right;
height = this.printerpagesetting.printdocument.defaultpagesettings.papersize.height -this.printerpagesetting.printdocument.defaultpagesettings.margins.top - this.printerpagesetting.printdocument.defaultpagesettings.margins.bottom;
//橫向打印,寬與高交換
if (this.printerpagesetting.printdocument.defaultpagesettings.landscape)
{
swap(ref width,ref height);
}
rectanglef recprintarea = new rectanglef(this.printerpagesetting.printdocument.defaultpagesettings.margins.left,this.printerpagesetting.printdocument.defaultpagesettings.margins.top,width,height);
drawtext drawtext = new drawtext(this.textbox1.text);
drawtext.graphics = g;
drawtext.rectanglef = recprintarea;
drawtext.startchar = intcurrentcharindex;
drawtext.draw();
intcurrentcharindex += drawtext.charsfitted;
if (intcurrentcharindex < this.textbox1.text.length)
{
return true;
}
else
{
intcurrentcharindex = 0;
return false;
}
}
//兩個數的值互換
private void swap(ref float i,ref float j)
{
float tmp = i;
i = j;
j = tmp;
}
在vb.net和c#的實現中,都分別寫了一個互換兩個數的值swap()函數,供頁面橫向打印時調用,這里不再敖述。
還需要補充說明的是在上篇:
開源:.net環境下有關打印頁面設置、打印機設置、打印預覽對話框的實現
http://blog.csdn.net/flygoldfish/archive/2004/08/17/77208.aspx
中,我又稍有改動,列表如下:
1、iprinterpagesetting.cs中將printpage改為printpagevalue,增加event printpagedelegate printpage;
2、webprinterpagesetting.cs中將printpage改為printpagevalue,增加public event goldprinter.printpagedelegate printpage;
3、winprinterpagesetting.cs中printpage改為printpagevalue,增加
public event printpagedelegate printpage
{
add
{
_printdocument.printpage += new system.drawing.printing.printpageeventhandler(value);
_printpagevalue = value;
}
remove
{
_printdocument.printpage -= new system.drawing.printing.printpageeventhandler(value);
_printpagevalue = null;
}
}
4、printerpagesetting.cs中printpage改為printpagevalue,增加
public event printpagedelegate printpage
{
add
{
_printerpagesetting.printpage += new printpagedelegate(value);
}
remove
{
_printerpagesetting.printpage -= new printpagedelegate(value);
}
}
5、printerpagesetting.cs中將printerpagesetting的有參構造函數public printerpagesetting(printdocument printdocument)
的_printerpagesetting.printdocument = printdocument;加一個判斷,即
if (printdocument != null)
{
_printerpagesetting.printdocument = printdocument;
}
這樣,系統會提供一個默認的printdocument對象。