Print
Mailing Labels - Database - CDataBase
Get
Business Card / Label
Print Component
C++
Source Codes
VC++
Tool:
Visual
C++ and SQL generator for ODBC Database, with
source code sample
VC++ MFC Project Setting, Unicode,
MBCS,_MBCS
or
_UNICODE,
wWinMainCRTStartup
VC++
Article
Draw Rotate / slant
text strings
SetWorldTransform
VC++
MFC Example: CTreeCtrl,
Create Tree Control
VC++
Sample:
ExtSelectClipRgn
or
IntersectClipRect,
ExcludeClipRect and
OffsetClipRgn or GetMetaRgn with InvalidateRect
Free Codes with
BITMAPINFOHEADER
and CreateDIBSection
Visual C++ MFC
Class Wizard
MFC
Source Code:
WindowFromPoint and GetDlgItem or ScreenToClient
Add
Skin to your
Visual C++ MFC
application,
download source codes
Open Souce VC++ Code and MFC Code Site,
VC++ FAQ Site and Tutorial Site
Hosting
WPF
Content in an
VC++ MFC
Application
GDI+
Example:
Draw
Curve ActiveX Control
GraphicsPath and Graphics
AfxGetStaticModuleState
and LoadLibrary of GetProcAddress and FreeLibrary
MFC ARTICLE with LOAD DLL
MFC
Library:
Drawing Spline
application with OpenGL with sample Source Code
MFC
visualisation software:
Create and draw Thumbnail View
with CWinApp and
CDocTemplate and CMultiDocTemplate
VC++
Sample:
Multiple Views layout of
RepositionBars and DeferWindowPos with
RecalcLayout and UpdateAllViews
VC++
Example:
splitter control in dialog UpdateWindow
GetWindowRect GetDlgItem
VC++
Example:
Display GIF-animatE using GDI+ with BMP,
JPEG, PNG, TIFF, EMF, WMF, DrawImage
VC++ Example
Capture Print Screen to
Clipboard including
dropdown menu,
SetWindowsHookEx
and
UnhookWindowsHookEx,
with
RegisterWindowMessage
UML
Diagram Component / Drawing C++ Source Code Solution
from ucancode,
it will save you 50% - 80% time for building any UML based application.
This article will explain how to print mailing labels using an ODBC
database, OnPrint, and OnDraw. I
used VC++ version 5 with service
patch 2 installed, but it should work with any version of VC++.
To get my mailing labels printed
I first used Crystal Reports. While this worked, I was not happy
with the output of the label. There was too much seperation between
fields, and trying to get them to look right was going to be a major
programming project in itself.
In starting to do my own labels, I
needed a font other than the default one. So, first was to add two
variables in the CView header file:
CFont cfSmall;
CFont *pOldFont;
Next, in the OnDraw function I
needed to know where to print each label. The first label starts
about a half inch down from the top and a quarter of an inch over to
the right. Time for some more variables. This time they are local to
On Draw:
int xstart,ystart;
int labelheight,labelwidth;
The TWIPS mapping mode give
dimensions in inches. According to the help for CDC::SetMapMode:
"Each logical unit is converted 1/20 of a point. (Because a
point is 1/72 inch, a twip is 1/1440 inch.) Positive x is to the
right; positive y is up."
Therefore, I coded:
xstart = 1440 / 4;
ystart = 1440 / 2;
labelheight = 1440;
labelwidth = 1440 * 2.5;
OnDraw receives a pointer the the
CDC. One of the functions is IsPrinting(). I put a check in my
function and coded the following:
if(pDC->IsPrinting())
{
if(m_nCurPage == 0l)
m_pSet->MoveFirst();
else
m_pSet->SetAbsolutePosition((long)((m_nCurPage * 30)+1l)));
iOldMode = pDC->SetMapMode(MM_TWIPS);
cfSmall.CreateFont(200,0,0,0,
FW_NORMAL,FALSE,FALSE,
ANSI_CHARSET,OUT_TT_PRECIS,0,
PROOF_QUALITY,DEFAULT_PITCH,FF_DONTCARE,"Arial");
pOldFont = pDC->SelectObject(&cfSmall);
GetClientRect(&r);
s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
textsize = pDC->GetTextExtent(s);
lx = r.left + xstart;
ly = r.top - ystart;
for(a = 0;a < 10;a++)
{
for(b = 0;b < 3;b++)
{
x = lx;
y = ly;
if(!m_pSet->IsEOF())
{
m_pSet->m_FirstName.TrimRight();
m_pSet->m_LastName.TrimRight();
csOut = m_pSet->m_FirstName;
csOut += " ";
csOut += m_pSet->m_LastName;
pDC->TextOut(x,y,csOut);
y -= textsize.cy;
m_pSet->m_FirstAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_FirstAddr);
y -= textsize.cy;
m_pSet->m_SecondAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_SecondAddr);
y -= textsize.cy;
m_pSet->m_City.TrimRight();
m_pSet->m_State.TrimRight();
m_pSet->m_ZipCode.TrimRight();
csOut = m_pSet->m_City;
csOut += ", ";
csOut += m_pSet->m_State;
csOut += " ";
csOut += m_pSet->m_ZipCode;
pDC->TextOut(x,y,csOut);
m_pSet->MoveNext();
}
lx += labelwidth;
}
ly -= labelheight;
lx = r.left + xstart;
}
pDC->SelectObject(pOldFont);
cfSmall.DeleteObject();
pDC->SetMapMode(iOldMode);
}
The whole view file and header is
included. I tried putting a while (!m_pSet->IsEof()) as a part of
the controlling loop, then doing the counting for each label. This
didn't work because pages will be printed one on top of the other.
The key to keeping up with where in the database
you are, and where to start printing
is current page. The print engine in MFC starts counting current
pages at 1, so in your OnPrint override you have this:
m_nCurPage = pInfo->m_nCurPage;
m_nCurPage -= 1;
OnDraw(pDC);
CView::OnPrint(pDC, pInfo);
m_nCurPage is part of your CView,
subtract one, then each time your on draw gets called you multiply
by 30. Why 30? 3 labels accross, 10 down. Adjust if you only have
two accross.
You will also have to determine how
many pages you have to print. This gets done in OnPreparePrinting():
LONG lNumRecs;
int iNumPages;
int iExtra;
lNumRecs = m_pSet->GetRecordCount();
iNumPages = (int)(lNumRecs / 30l);
iExtra = (int)(lNumRecs % 30l);
if(iExtra > 0)
iNumPages++;
pInfo->SetMaxPage(iNumPages);
return DoPreparePrinting(pInfo);
You get the number of records in
your dataset, divide that number by the number of labels per sheet.
Because there might be more labels left over than can print on a
sheet, you do a mod on the number records. This will tell you if
there are any remaining on a partial sheet, if so, add one to the
page count. Then set your page count by callint SetMaxPage().
The y is always decremented using
the TWIPS map mode because the bottom of the page is 0. For each
page, you have to reinitialize the font and map mode--the printer
will not remember those things between pages, that's why you delete
your objects and reinitialize them each time your OnDraw is called.
That's about it. You've got print
preview, and printing for your
labels.
The CView .cpp file:
// mlabelView.cpp : implementation of the CMlabelView class
//
#include "stdafx.h"
#include "mlabel.h"
#include "MlistSet.h"
#include "mlabelDoc.h"
#include "mlabelView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////
// CMlabelView
IMPLEMENT_DYNCREATE(CMlabelView, CView)
BEGIN_MESSAGE_MAP(CMlabelView, CView)
//{{AFX_MSG_MAP(CMlabelView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////
// CMlabelView construction/destruction
CMlabelView::CMlabelView()
{
// TODO: add construction code here
m_pSet = NULL;
}
CMlabelView::~CMlabelView()
{
}
BOOL CMlabelView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
////////////////////////////////////////////////////////////////////////////
/
// CMlabelView drawing
void CMlabelView::OnDraw(CDC* pDC)
{
CMlabelDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int xstart,ystart;
int lx,ly;
int x,y;
int a,b;
int labelheight,labelwidth;
RECT r;
CSize textsize;
xstart = 1440 / 4;
ystart = 1440 / 2;
labelheight = 1440;
labelwidth = 1440 * 2.5;
CString csOut;
CString s;
if(pDC->IsPrinting())
{
if(m_nCurPage == 0l)
m_pSet->MoveFirst();
else
m_pSet->SetAbsolutePosition((long)((m_nCurPage * 30)+1l));
iOldMode = pDC->SetMapMode(MM_TWIPS);
cfSmall.CreateFont(200,0,0,0,
FW_NORMAL,FALSE,FALSE,
ANSI_CHARSET,OUT_TT_PRECIS,0,
PROOF_QUALITY,DEFAULT_PITCH,FF_DONTCARE,"Arial");
pOldFont = pDC->SelectObject(&cfSmall);
GetClientRect(&r);
s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
textsize = pDC->GetTextExtent(s);
lx = r.left + xstart;
ly = r.top - ystart;
for(a = 0;a < 10;a++)
{
for(b = 0;b < 3;b++)
{
x = lx;
y = ly;
if(!m_pSet->IsEOF())
{
m_pSet->m_FirstName.TrimRight();
m_pSet->m_LastName.TrimRight();
csOut = m_pSet->m_FirstName;
csOut += " ";
csOut += m_pSet->m_LastName;
pDC->TextOut(x,y,csOut);
y -= textsize.cy;
m_pSet->m_FirstAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_FirstAddr);
y -= textsize.cy;
m_pSet->m_SecondAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_SecondAddr);
y -= textsize.cy;
m_pSet->m_City.TrimRight();
m_pSet->m_State.TrimRight();
m_pSet->m_ZipCode.TrimRight();
csOut = m_pSet->m_City;
csOut += ", ";
csOut += m_pSet->m_State;
csOut += " ";
csOut += m_pSet->m_ZipCode;
pDC->TextOut(x,y,csOut);
m_pSet->MoveNext();
}
lx += labelwidth;
}
ly -= labelheight;
lx = r.left + xstart;
}
pDC->SelectObject(pOldFont);
cfSmall.DeleteObject();
pDC->SetMapMode(iOldMode);
}
else
{
iOldMode = pDC->SetMapMode(MM_TWIPS);
cfSmall.CreateFont(200,0,0,0,
FW_NORMAL,FALSE,FALSE,
ANSI_CHARSET,OUT_TT_PRECIS,0,
PROOF_QUALITY,DEFAULT_PITCH,FF_DONTCARE,"Arial");
pOldFont = pDC->SelectObject(&cfSmall);
GetClientRect(&r);
s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
textsize = pDC->GetTextExtent(s);
lx = r.left + xstart;
ly = r.top - ystart;
m_pSet->MoveFirst();
while(!m_pSet->IsEOF())
{
for(b = 0;b < 3;b++)
{
x = lx;
y = ly;
if(!m_pSet->IsEOF())
{
m_pSet->m_FirstName.TrimRight();
m_pSet->m_LastName.TrimRight();
csOut = m_pSet->m_FirstName;
csOut += " ";
csOut += m_pSet->m_LastName;
pDC->TextOut(x,y,csOut);
y -= textsize.cy;
m_pSet->m_FirstAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_FirstAddr);
y -= textsize.cy;
m_pSet->m_SecondAddr.TrimRight();
pDC->TextOut(x,y,m_pSet->m_SecondAddr);
y -= textsize.cy;
m_pSet->m_City.TrimRight();
m_pSet->m_State.TrimRight();
m_pSet->m_ZipCode.TrimRight();
csOut = m_pSet->m_City;
csOut += ", ";
csOut += m_pSet->m_State;
csOut += " ";
csOut += m_pSet->m_ZipCode;
pDC->TextOut(x,y,csOut);
m_pSet->MoveNext();
}
lx += labelwidth;
}
ly -= labelheight;
lx = r.left + xstart;
}
pDC->SelectObject(pOldFont);
cfSmall.DeleteObject();
pDC->SetMapMode(iOldMode);
}
// TODO: add draw code for native data here
}
////////////////////////////////////////////////////////////////////////////
/
// CMlabelView printing
BOOL CMlabelView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
LONG lNumRecs;
int iNumPages;
int iExtra;
lNumRecs = m_pSet->GetRecordCount();
iNumPages = (int)(lNumRecs / 30l);
iExtra = (int)(lNumRecs % 30l);
if(iExtra > 0)
iNumPages++;
pInfo->SetMaxPage(iNumPages);
return DoPreparePrinting(pInfo);
}
void CMlabelView::OnBeginPrinting(CDC*
News:
1 UCanCode Advance E-XD++
CAD Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2024 is released!
2
UCanCode Advance E-XD++
HMI & SCADA Source Code Solution for C/C++, .NET V2024 is released!
3
UCanCode
Advance E-XD++ GIS SVG Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2024 is released! |