六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

VC5打印字體的控制

[摘要]VC5.0 為Windows 的程序員提供了一個很好的C++ 開發環境,減少了很多編程負擔,但同時也為我們在程序中加入自己的思想增加了難度。本人在一軟件開發中,想控制文字打印時的字體,使字體大小縮小一倍,以節省打印紙。經過一段時間的摸索,終于解決了這一問題,下面分幾步向大家做一介紹。---- 一、...
VC5.0 為Windows 的程序員提供了一個很好的C++ 開發環境,減少了很多編程負擔,但同時也為我們在程序中加入自己的思想增加了難度。本人在一軟件開發中,想控制文字打印時的字體,使字體大小縮小一倍,以節省打印紙。經過一段時間的摸索,終于解決了這一問題,下面分幾步向大家做一介紹。

---- 一、對VC5 自動生成的程序框架進行改進

---- 這里用VC5 自動創建一個例子程序Test,單文檔界面,注意在最后一步修改view 的繼承類為CEditView。

---- 在view 類中,VC5 已經自動創建了三個用于支持打印的函數:OnPreparePrinting,OnBeginPrinting,OnEndPrinting。為了實現我們的功能,需要再繼承以下幾個函數:OnPrepareDC,OnPrint。并將OnPrepareDC 和OnEndPrinting 改為如下實現:


// OnPrepareDC()
void CTestView::OnPrepareDC
(CDC* pDC, CPrintInfo* pInfo)
{
CView::OnPrepareDC(pDC, pInfo);
}

// OnEndPrinting()
void CTestView::OnEndPrinting
(CDC* pDC, CPrintInfo* pInfo)
{
CView::OnEndPrinting(pDC, pInfo);
}
---- 用CView 來替代原來的CEditView,用以避免CEidtView 對打印的控制?刂谱煮w及輸出的功能主要在OnBeginPrinting 和OnPrint 兩個函數來實現。

---- 二、實現OnBeginPrinting 函數

---- 根據VC5 編程機制,在OnBeginPrinting 函數實現打印前的準備工作,包括設置打印字體,根據打印機當前頁面尺寸計算所需頁數等。下面的程序是對打印字體的重新設置和計算所需打印紙頁數。

---- 程序中首先取得打印機的橫向和縱向分辨率,再得到當前打印字體的大小,然后計算出新的字體大小,為默認字體的一半。讀者可以根據需要設定自己的打印字體大小。

---- 接著,取得當前打印紙的寬度和高度,再根據新字體的寬度和高度計算出每行的最大字符數和每頁的最大行數。

---- 由于打印文件中有些行的寬度可能超過每行的最大字符數,所以程序中調用函數RedealTextData() 對打印文件進行重新整理,函數的實現在下面介紹。

---- 最后,程序中計算并設置所需的打印頁數。

OnBeginPrinting()函數實現如下:
//====================================
// OnBeginPrinting
//====================================
void CTestView::OnBeginPrinting(CDC* pDC,
CPrintInfo* pInfo)
{
//設置新的? 字體////////////////

//取打印機的橫方向和縱方向的分辨率
//即每英寸點數
short cxInch = pDC- >GetDeviceCaps(LOGPIXELSX);
short cyInch = pDC- >GetDeviceCaps(LOGPIXELSY);

// 取當前字體大小
CFont *curFont = pDC- >GetCurrentFont();
LOGFONT curLogFont;
LOGFONT newLogFont;

curFont- >GetLogFont( &curLogFont );
long NewFontWidth = curLogFont.lfWidth;
long NewFontHeight = curLogFont.lfHeight;
newLogFont = curLogFont;

//計算新的字體大小--縮小一倍
newLogFont.lfWidth =(long)((float)NewFontWidth/2.0
* ((float)cxInch / 72.0));
newLogFont.lfHeight =(long)((float)NewFontHeight/2.0
* ((float)cyInch / 72.0));

//創建并設置新的字體,保留以前的字體
CFont newFont;
CFont *oldFont;

newFont.CreateFontIndirect(&newLogFont);
oldFont = pDC- >SelectObject(&newFont );
/////////////////////////////////
//根據字體寬度、高度計算
//每行最大字數及每頁最大行數

//取打印紙張高度和寬度
int nPageHeight, nPageWidth;
nPageHeight = pDC- >GetDeviceCaps(VERTRES);
nPageWidth = pDC- >GetDeviceCaps(HORZRES);

TEXTMETRIC TextM;
pDC- >GetTextMetrics(&TextM);
//字體高度
m_LineHeight = (unsigned short)TextM.tmHeight;
//字體平均寬度
m_CharWidth=(unsigned short)
TextM.tmAveCharWidth;

//每行最大字數
m_MaxLineChar = nPageWidth / m_CharWidth - 8;
//每頁最大行數
m_LinesPerPage = nPageHeight/ m_LineHeight;
//根據每行最大字數對文字進行重新調整
RedealTextData();
//////////////////////////////////////
//計算所需打印紙張數目
int nPrintableLineCount = INT_MAX/m_LineHeight;

// m_lines為文件總行數
if (m_lines < nPrintableLineCount)
nPrintableLineCount = m_lines;
unsigned short MaxPage = (nPrintableLineCount
+ m_LinesPerPage - 1)
/ m_LinesPerPage;
//設置所需打印紙張數目
pInfo- >SetMaxPage(MaxPage);
pInfo- >m_nCurPage = 1;

//////////////////////////////////////////
//最后不要忘記將字體還原,這一句是必需的
pDC- >SelectObject(oldFont );
}
---- RedealTextData 函數根據每行最大寬度對文件進行重新調整。主要是計算文件中每行的寬度,如果超過最大寬度則加入換行符(0x0d,0x0a)。函數實現如下:


//=======================================
// RedealTextData
//注:
//pDoc- >buffer為文件緩沖區
//pDoc- >file_length為文件字節長度
//pDoc- >TextLines為文件原行數
//pDoc- >MaxLineLength為文件原最大行字節寬度
//=======================================
void CTextView::RedealTextData()
{
CDocViewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

short LineLengthMax = m_MaxLineChar;
unsigned short lines=0;
unsigned long i,j;

//申請新的緩沖區保存調整后的文件
long size = pDoc- >file_length + pDoc- >TextLines*
(pDoc- >MaxLineLength/m_MaxLineChar+1);
m_newBuffer = new char [size ];
LPSTR newTempPtr = m_newBuffer;
m_file_length =pDoc- >file_length;
//保存文件新的行數
m_lines = 1;
i = 0;
//記錄當前行的寬度
short theLineLength=0;
//記錄當前行中漢字字節數,
//以防止將一半漢字分為兩行
unsigned short halfChinese=0;

while(i < pDoc- >file_length)
{
*newTempPtr++ = pDoc- >buffer[i];

j=i+1;
if( (pDoc- >buffer[i] == 0x0d && pDoc- >buffer[j] == 0x0a))
{
m_lines++;
theLineLength = 0;
}
else
{
//如果是TAB字符,寬度加8
if(pDoc- >buffer[i] == VK_TAB)
theLineLength += 8;
else
{
//大于0xa1的字節為漢字字節
if((unsigned char)pDoc- >buffer[i] >= 0xa1)
halfChinese++;
theLineLength++;
}
//如果行寬大于每行最大寬度,進行特殊處理
if(theLineLength > LineLengthMax)
{
char buff[256];
short m=255;
newTempPtr--;
if((unsigned char )*newTempPtr < 0xa1)
{
//如果當前字符的前一個字符是數字、
//字母或一些特殊的前置符號時,
//指針循環向前取,
//以防止將一個單詞分為兩行。
while((*newTempPtr >=0 && *newTempPtr< =9)
(*newTempPtr >=a && *newTempPtr < = z)
(*newTempPtr >=A && *newTempPtr < = Z)
*newTempPtr == _ *newTempPtr == *
*newTempPtr == ^ *newTempPtr == ~ )
buff[m--] = *newTempPtr--;
}
else //漢字
{
//防止將一個漢字分為兩行。
if(halfChinese%2)
buff[m--] = *newTempPtr--;
}
newTempPtr++;
//加入換行符,分為兩行
*newTempPtr++ = 0x0d;
*newTempPtr++ = 0x0a;
for(short k=m+1; k< 256; k++)
*newTempPtr++ = buff[k];

m_lines++;
theLineLength = 0;
m_file_length += 2;
}
}
i++;
}
}
---- 三、實現OnPrint 函數

---- 在OnPrint 函數中實現真正的文字輸出,主要功能包括設置打印字體大小,計算當前頁號文字輸出位置,以及文字的輸出打印。

---- 程序中首先計算打印區域,文字在這個打印區域內輸出。然后設置新的打印字體。

---- 由于OnPrint 函數是每打印一頁被調用一次,所以需要根據當前打印頁號計算出當前頁的文字在整個文字緩沖區的起始偏移量和終止偏移量。這里程序中調用了函數GetOffset(),此函數在下面介紹。

---- 最后調用Windows 的DrawText() 函數實現文字的輸出。

OnPrint()函數實現如下:
//====================================
// OnPrint
//========================================
void CTestView::OnPrint(CDC* pDC,
CPrintInfo* pInfo)
{
//計算打印區域//////////////////
long yTopOfPage =(pInfo- >m_nCurPage -1) *
m_LinesPerPage * m_LineHeight;

//左邊空出兩個字符寬度
pDC- >SetViewportOrg(m_CharWidth * 2,
-yTopOfPage);

int nPageWidth = pDC- >GetDeviceCaps(HORZRES);
CRect rectClip = CRect(0,
yTopOfPage,
nPageWidth,
yTopOfPage + m_LinesPerPage *
m_LineHeight);

/////設置縮小字體///////////////////
//取打印機的橫方向和縱方向的分辨率
//即每英寸點數
short cxInch=pDC- >GetDeviceCaps(LOGPIXELSX);
short cyInch= DC- >GetDeviceCaps(LOGPIXELSY);

//取當前字體大小
CFont *curFont = pDC- >GetCurrentFont();
LOGFONT curLogFont;
LOGFONT newLogFont;

curFont- >GetLogFont( &curLogFont );
long NewFontWidth = curLogFont.lfWidth;
long NewFontHeight = curLogFont.lfHeight;
newLogFont = curLogFont;

//計算新的字體大小--縮小一倍
newLogFont.lfWidth = (long)((float)NewFontWidth/2.0
* ((float)cxInch / 72.0));
newLogFont.lfHeight = (long)((float)NewFontHeight/2.0
* ((float)cyInch / 72.0));

//創建并設置新的字體,保留以前的字體
CFont newFont;
CFont *oldFont;
newFont.CreateFontIndirect(&newLogFont);
oldFont = pDC- >SelectObject(&newFont );

/////文字打印輸出/////////////////
unsigned short CurrentStartLine ,
CurrentEndLine;
long StartPrintOffset,
EndPrintOffset,
PrintSize;
LPSTR tempPtr;
RECT rect1,rect2;
//根據當前打印頁號計算文字起始行
CurrentStartLine=(pInfo- >m_nCurPage-1) * m_LinesPerPage;
//文字終止行
CurrentEndLine = CurrentStartLine+m_LinesPerPage;

if(CurrentEndLine > m_lines)
CurrentEndLine = m_lines;
//計算打印文字的起始位置和終止位置
StartPrintOffset=GetOffset(m_newBuffer,
m_file_length, CurrentStartLine);
EndPrintOffset = GetOffset(m_newBuffer,
m_file_length,CurrentEndLine);

PrintSize = EndPrintOffset - StartPrintOffset;

tempPtr = m_newBuffer + StartPrintOffset;
//文字輸出
pDC- >DrawText(tempPtr, PrintSize,
&rectClip,
DT_NOCLIP DT_NOPREFIX
DT_EXPANDTABS);

//還原舊的打印字體
pDC- >SelectObject(oldFont );
}
---- 程序中的GetOffset 函數是根據給定的行號計算文字的位置,其實現如下:


//========================================
// GetOffset ()
//========================================
long CTestView::GetOffset(LPSTR buffer,
long buffer_length,
unsigned short StartLine)
{
if(StartLine == 0) return 0;

unsigned short lines=0;
long i,j;

i = 0;
while(i < buffer_length)
{
j=i+1;
if( (buffer[i++] == 0x0d && buffer[j] == 0x0a))
{
lines++;
if(lines == StartLine)
return i;
}
}
return buffer_length;
}
---- 以上是本人在編程中的一點心得,歡迎和大家共同交流。


主站蜘蛛池模板: 天天综合天天看夜夜添狠狠玩 | 日日摸夜夜添夜夜添毛片 | 欧美一卡二卡三卡四卡乱码 | 天天狠天天天天透在线 | 日本啊v在线观看 | 欧美在线观看一区 | 色综合久久综合网欧美综合网 | 日本aa大片在线播放免费看 | 一级在线视频 | 中文字幕亚洲第一 | 中文字幕视频免费在线观看 | 日本在线免费观看视频 | 自拍一区在线观看 | 午夜视频在线免费看 | 日本激情视频一区二区三区 | 婷婷丁香花 | 午夜三级理论在线观看视频 | 四虎永久免费在线观看 | 欧美一级大片在线观看 | 小明精品国产一区二区三区 | 亚洲欧洲精品视频 | 日韩国产欧美成人一区二区影院 | 伊人.com| 一二三四手机在线观看视频播放 | 天天天射| 天天色天天色天天色 | 色橹| 色吧综合网 | 亚洲 日本 欧美 日韩精品 | 伊人三级 | 亚洲 欧美 91| 羞羞答答免费人成黄页在线观看国产 | 亚洲码和乱人伦中文一区 | 日本天堂网站 | 日韩视频在线精品视频免费观看 | 日韩一区二区三区不卡视频 | 日本视频免费在线 | 天天躁夜夜躁狠狠躁2021 | 日韩福利在线观看 | 月婷婷色狠狠 | 青草视频在线免费观看 |