• 文章
  • Borland C++ 5.02 列印預覽程式碼
釋出
2014年1月23日 (最後更新:2014年6月16日)

Borland C++ 5.02 列印預覽視窗程式碼

評分:4.2/5 (41票)
*****
引言

多年來,我一直使用 Borland C++ 5.02 版本為本地小型企業編碼 應用程式開發 專案。它是一個非常健壯的 軟體 平臺,而這些 定製軟體 專案的基石就是“列印預覽”功能。在這裡,我將展示一個支票登記對賬的示例,該示例利用了我的 開發人員技能 來建立一個“列印預覽”功能。

宣告所需的 C++ 類

首先需要宣告列印預覽視窗所需的類。“TPrevWindow”類是從 OWL(物件視窗庫)中的“TWindow”基類派生的。它包含了頁面導航和列印的成員函式。該類中的響應表將定義的點陣圖影像常量與其對應的成員函式關聯起來。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

// this is the class declaration for the “TPrevWindow” class, which
// contains member functions for scrolling forwards and backwards
// through print preview pages as well as the printing function itself.
// also, each of these member functions are associated with bitmaps as
// seen here under the response table. lastly, there is a “TPrinter”
// object, “Printer”, that is used throughout the code.
//
// class TPrevWindow
// ~~~~~ ~~~~~~~~~~~
class TPrevWindow : public TWindow {
  public:
    TPrevWindow(TWindow* parent = 0);
    void PrnNext();
    void PrnPrevious();
    void PrnImage();
    void Paint(TDC& dc, bool erase, TRect& rect);
  private:
    TPrinter* Printer;
  DECLARE_RESPONSE_TABLE(TPrevWindow);
};
DEFINE_RESPONSE_TABLE1(TPrevWindow, TWindow)
  EV_COMMAND(IDB_BITMAP1, PrnNext),
  EV_COMMAND(IDB_BITMAP2, PrnPrevious),
  EV_COMMAND(IDB_BITMAP3, PrnImage),
END_RESPONSE_TABLE;


接下來,我們需要宣告“TDialog”基類的對話方塊類“TBalEndDlg”,它將負責接受使用者輸入、提取資料等,為即將進行的列印預覽操作做準備。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

// this class contains controls for accepting user input as well
// as “TButtonGadget” and “TButtonGadgetEnabler” objects to be
// utilized for constructing the print preview window near the
// end of processing.
//
// class TBalEndDlg
// ~~~~~ ~~~~~~~~~~~~
class TBalEndDlg : public TDialog {
  public:
    TBalEndDlg(TWindow* parent, TResId resId, TBalEndStruct& transfer);
    TEdit *Edit1,*Edit2;

    LRESULT WMChar(WPARAM, LPARAM);

  protected:
    void    CmOk();

  private:
    TButtonGadget* G1;
    TButtonGadget* G2;
    TButtonGadgetEnabler* Ge1;
    TButtonGadgetEnabler* Ge2;
    void    SetupWindow();
    char    StartingAmt[MAXSELL];
    char    EndDate[MAXDAT];

  DECLARE_RESPONSE_TABLE(TBalEndDlg);
};

DEFINE_RESPONSE_TABLE1(TBalEndDlg, TDialog)
  EV_COMMAND(IDOK, CmOk),
  EV_MESSAGE(WM_CHAR, WMChar),
END_RESPONSE_TABLE;


接下來,設定列印預覽

這是從用於主程式視窗的“TTestWindow”類執行“TBalEndDlg”對話方塊的命令。用於建立使用者輸入螢幕的資源是“IDD_STATEMENTBAL”。主視窗類“TTestWindow”中用於構造輸入控制元件傳輸機制的指令是“TBalEndStruct BalEndStruct;”。物件“BalEndStruct”在下面呼叫執行“TBalEndDlg”對話方塊時指定。

1
2
3
4
5
6
7
8
9
10
11

void
TTestWindow::Reconciliation()
{

 if (TBalEndDlg(this, IDD_STATEMENTBAL, BalEndStruct).Execute() == IDOK) {

 }

}


下面是“IDD_STATEMENTBAL”對話方塊資源編碼的樣子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

IDD_STATEMENTBAL DIALOG 15, 20, 205, 65
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Reconciliation Entry Screen"
FONT 8, "MS Sans Serif"
{
 CONTROL "Register Starting Balance: ", 962, "static", SS_LEFT | WS_CHILD, 30 10, 130, 12
 CONTROL "Register Ending Date: ", 963, "static", SS_LEFT | WS_CHILD, 30 25, 130, 12
 EDITTEXT IDC_STARTINGBAL, 113, 10, 55, 12, ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD, 0
 EDITTEXT IDC_ENDDATE, 103, 25, 55, 12, ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD, 0
 DEFPUSHBUTTON "&OK", IDOK, 70, 45, 30, 19, 0, 0
 PUSHBUTTON "&Cancel", IDCANCEL, 100, 45, 30, 19, 0, 0
}


這是執行時輸入螢幕的樣子。




接下來的這段 C++ 程式碼將在“TBalEndDlg”對話方塊呼叫發生後執行。它將開始為列印預覽過程做準備,首先接受一個起始餘額和結束日期。這些將用於隨後的資料提取過程,該過程在上述對話方塊資源中的“OK”按鈕被點選後進行。完成此操作後,它將根據每頁 50 行計算頁數。然後,它將從“TDecoratedFrame”基類構造一個“frame_d”物件。它將初始化各種設定,包括嵌入了成員函式按鈕的控制元件欄。它還將設定列印預覽視窗的尺寸,並根據為列印預覽操作計算的總頁數啟用和停用導航按鈕。您還會注意到我在檔案輸入/輸出操作中使用了定義的常量。這些常量用於設定檔案流中讀取和寫入與 程式設計 配合使用的二進位制固定長度資料檔案的偏移量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510

// instantiate the “TBalEndDlg” dialog class.
//
TBalEndDlg::TBalEndDlg(TWindow* parent, TResId resid,
  TBalEndStruct& transfer)
:
  TDialog(parent, resid)
{
  Edit1 = new TEdAmt_(this, IDC_ENDBAL, sizeof(transfer.StartingAmt));
  Edit2 = new TEdate(this, IDC_ENDDATE, sizeof(transfer.EndDate));

  TransferBuffer = (void far*)&transfer;
}

// let’s get the Winform screen set up.
void
TBalEndDlg::SetupWindow()
{
  // declare variables for this function.
  long int  datecomponent,monthvar,dayvar,yearvar;
  int          a,t,b;
  char       var[3],Date_[MAXDAT];
  struct     dosdate_t d;
  ldiv_t     n;

  TDialog::SetupWindow();

  // clear out the starting amount field.
  Edit1->Clear();

  // grab today’s date and assign it to the ending date input. 
  _dos_getdate(&d);
  monthvar = d.month;
  dayvar = d.day;
  yearvar = d.year;

  // take the current date components month, day and year and
  // convert to chars to be stored in the char array “Date_”.	
  for(a=0; a<MAXDAT; a++) Date_[a] = 32;
	  Date_[2] = 47;
	  Date_[5] = 47;
	  t=0;
		  do {

			  if(t == 0) datecomponent = monthvar;
			  if(t == 1) datecomponent = dayvar;
			  if(t == 2) {
			  datecomponent = yearvar;
				  // y2k adjustment.	
				  if (datecomponent < 2000 )
				  datecomponent = datecomponent - 1900;
				  else
				  datecomponent = datecomponent - 2000;
				      }

  var[0] = 48;
  var[1] = 48;
  var[2] = 32;
  b=1;
  do {
  n=ldiv(datecomponent,10L);
  datecomponent =n.quot;
		if(n.rem==0) var[b] = 48;
	  	if(n.rem==1) var[b] = 49;
		if(n.rem==2) var[b] = 50;
		if(n.rem==3) var[b] = 51;
		if(n.rem==4) var[b] = 52;
		if(n.rem==5) var[b] = 53;
		if(n.rem==6) var[b] = 54;
  		if(n.rem==7) var[b] = 55;
	  	if(n.rem==8) var[b] = 56;
		if(n.rem==9) var[b] = 57;
  b--;
  } while(datecomponent > 0);

  if(t==0) for(a=0; a<2; a++) Date_[a] = var[a];
  if(t==1) for(a=0; a<2; a++) Date_[3+a] = var[a];
  if(t==2) for(a=0; a<2; a++) Date_[6+a] = var[a];

  t++;
  } while(t < 3);
  Date_[MAXDAT-1] = 0;
  Edit2->SetText(Date_);

  for(a=0; a<MAXDAT-1; a++) Horddatexz[a] = Date_[a];

  Datedispz = 0;

}

// after the operator clicks the “OK” button, grab the Winform
// screen inputs and commence the data extraction process.
void
TBalEndDlg::CmOk()
{
  // declare variables for this function.
  int          a,PickVar,CountVar_,KountVar,fileinfo,f,r,date_compare,b,ff;
  long int   fileoffset, sizeofdatafile,accum,accum2,startbal,convert_to_number[MAXSELL],endbal, enddate_month;
  long int   enddate_day, enddate_year, transdate_month, transdate_day, transdate_year;
  char       kh,ch,dh,eh,transaction_date[MAXDAT],ExtractedAmt[MAXSELL];
  ldiv_t     n;
  streambuf  *inn = cin.rdbuf();

  // set the cursor to a hourglass.
  SetCursor(0, IDC_WAIT);


  for(a=0; a<MAXSELL; a++) StartingAmt[a] = 32;
  for(a=0; a<MAXDAT; a++) EndDate[a] = 32;

  // grab data from the Winform screen controls.
  GetDlgItemText(IDC_STARTINGBAL, StartingAmt, MAXSELL);
  GetDlgItemText(IDC_ENDDATE, EndDate, MAXDAT);


	          // format the retrieved starting amount so it is right justified.
		  for(a=0; a<MAXSELL; a++) {
			  if(StartingAmt[a] < 46 || StartingAmt[a] > 57) StartingAmt[a] = 32;
		  }
			  r=0;
			  do {
				  if(StartingAmt[9] < 48 || StartingAmt[9] > 57) {
					  for(f=9; f>0; f--) StartingAmt[f] = StartingAmt[f-1];
					  StartingAmt[0] = 32;
			  	  }
			  r++;
			  } while(r < 10);


  // parse the retrieved ending date into month, day and year numerical
  // components for further processing.
  a=0;
  do {

	  if(a==0) b = 0;
	  if(a==1) b = 3;
	  if(a==2) b = 6;

  for(ff=0; ff<2; ff++) {
  convert_to_number[ff] = 0;
  if(EndDate[b+ff] == 48) convert_to_number[ff] = 0;
  if(EndDate[b+ff] == 49) convert_to_number[ff] = 1;
  if(EndDate[b+ff] == 50) convert_to_number[ff] = 2;
  if(EndDate[b+ff] == 51) convert_to_number[ff] = 3;
  if(EndDate[b+ff] == 52) convert_to_number[ff] = 4;
  if(EndDate[b+ff] == 53) convert_to_number[ff] = 5;
  if(EndDate[b+ff] == 54) convert_to_number[ff] = 6;
  if(EndDate[b+ff] == 55) convert_to_number[ff] = 7;
  if(EndDate[b+ff] == 56) convert_to_number[ff] = 8;
  if(EndDate[b+ff] == 57) convert_to_number[ff] = 9;
  }
  if(a == 0) enddate_month = (convert_to_number[0] * 10) + (convert_to_number[1] * 1);
  if(a == 1) enddate_day = (convert_to_number[0] * 10) + (convert_to_number[1] * 1);
  if(a == 2) {
  enddate_year = (convert_to_number[0] * 10) + (convert_to_number[1] * 1);
  // include y2k adjustment.
  if(enddate_year >= 80) enddate_year = enddate_year + 1900;
  if(enddate_year < 80) enddate_year = enddate_year + 2000;
  }

  a++;
  } while(a < 3);

  // convert the starting amount to a numerical value.
  for(a=0; a<MAXSELL; a++) Sellvarq_[a]=StartingAmt[a];
	  for(a=0; a<MAXSELL-1; a++) {
	  hold[a]=0;
	  if(StartingAmt[a] == 48) convert_to_number[a]=0;
	  if(StartingAmt[a] == 49) convert_to_number[a]=1;
	  if(StartingAmt[a] == 50) convert_to_number[a]=2;
	  if(StartingAmt[a] == 51) convert_to_number[a]=3;
	  if(StartingAmt[a] == 52) convert_to_number[a]=4;
	  if(StartingAmt[a] == 53) convert_to_number[a]=5;
  	  if(StartingAmt[a] == 54) convert_to_number[a]=6;
	  if(StartingAmt[a] == 55) convert_to_number[a]=7;
	  if(StartingAmt[a] == 56) convert_to_number[a]=8;
	  if(StartingAmt[a] == 57) convert_to_number[a]=9;
	  }
  startbal = ( (convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) +
  (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1) );

  // now, let’s prepare for data extraction from the check register
  // by purging the last used extracted data file and opening a new 
  // stream to a file of the same name that is set for append record
  // mode. we will also open a stream to the check register fixed width
  // binary data file to read needed data from.
  remove("test_x.txt");

  PickVar = 0;

  fileinfo = open("cbook.txt", ios::in | ios::binary);
  sizeofdatafile = filelength(fileinfo);
  close(fileinfo);

  ifpstream ifile;
  ifile.open("cbook.txt", ios::in | ios::binary);
  inn = ifile.rdbuf();

  ofpstream ofile;
  ofile.open("test_x.txt", ios::ate | ios::app | ios::binary);
  fileoffset = 0;
  do {

// get the first 2 characters of the transaction type designator.
inn -> seekpos(fileoffset+MAXDAT+MAXINVNO+MAXSELL+MAXNOTE2+MAXSELL+MAXSELL+MAXSELL+MAXCCODE+MAXCOMPANY2-9, ios::in);
	kh = ifile.readByte();
	eh = ifile.readByte();
		// get the first character of the transaction cleared designator.
  		inn -> seekpos(fileoffset+CHECKBLEN-5-(MAXANS-1), ios::in);
	   	ch = ifile.readByte();
			// get the first character of the transaction paid designator.
                        inn -> seekpos(fileoffset    +MAXDAT+MAXINVNO+MAXSELL+MAXNOTE2+MAXSELL+MAXSELL+MAXSELL+MAXCCODE+MAXCOMPANY2+MAXSELL+MAXANS-11, ios::in);
			dh = ifile.readByte();

  // parse the check register transaction date into month, day and
  // year numerical components for further processing.
  inn -> seekpos(fileoffset+CHECKBLEN-5-(MAXDAT+MAXANS-2), ios::in);
  for(a=0; a<MAXDAT-1; a++) transaction_date[a] = ifile.readByte();

  a = 0;
  do {

	  if(a == 0) b = 0;
	  if(a == 1) b = 3;
	  if(a == 2) b = 6;

  for(ff=0; ff<2; ff++) {
  convert_to_number[ff] = 0;
  if(transaction_date [b+ff] == 48) convert_to_number[ff] = 0;
  if(transaction_date [b+ff] == 49) convert_to_number[ff] = 1;
  if(transaction_date [b+ff] == 50) convert_to_number[ff] = 2;
  if(transaction_date [b+ff] == 51) convert_to_number[ff] = 3;
  if(transaction_date [b+ff] == 52) convert_to_number[ff] = 4;
  if(transaction_date [b+ff] == 53) convert_to_number[ff] = 5;
  if(transaction_date [b+ff] == 54) convert_to_number[ff] = 6;
  if(transaction_date [b+ff] == 55) convert_to_number[ff] = 7;
  if(transaction_date [b+ff] == 56) convert_to_number[ff] = 8;
  if(transaction_date [b+ff] == 57) convert_to_number[ff] = 9;
  }
  if(a == 0) transdate_month = convert_to_number[0]*10 + convert_to_number[1]*1;
  if(a == 1) transdate_day = convert_to_number[0]*10 + convert_to_number[1]*1;
  if(a == 2) {
  transdate_year = (convert_to_number[0] * 10) + (convert_to_number[1] * 1);
  // include y2k adjustment.
  if(transdate_year >= 80) transdate_year = transdate_year + 1900;
  if(transdate_year < 80) transdate_year = transdate_year + 2000;
  }

  a++;
  } while(a < 3);

  // now, check to see if the check register transaction date is
  // less than or equal to the ending date from the Winform.
  date_compare = 1;
  if(transdate_year < enddate_year) date_compare = 0;

	  if(transdate_year == enddate_year && transdate_month < enddate_month) date_compare = 0;

		  if(transdate_year == enddate_year && transdate_month == enddate_month) {
			  if(transdate_day <= enddate_day) date_compare = 0;
		  }

  // if this transaction is a deposit that has not cleared the bank
  // and has not been paid and the check register transaction date is
  // less than or equal to the inputted ending date, then append a ‘D’ and
  // the check register credit amount to the extracted data file and
  // increment the line counter “PickVar” by 1.
  if ( kh == 'D' && eh == 'E' && ch == 'N' && dh == 'N' && date_compare == 0 ) {
	inn -> seekpos(fileoffset+MAXDAT+MAXINVNO+MAXSELL+MAXNOTE2+MAXSELL+MAXSELL
	+MAXSELL+MAXCCODE+MAXCOMPANY2+MAXSELL+MAXANS+MAXANS-12, ios::in);
			  for(a=0; a<MAXSELL-1; a++) ofile.writeByte(ifile.readByte());
			  ofile.writeByte('D');
			  PickVar++;
  }

  // if this transaction is not a deposit that has not cleared the bank
  // and has not been paid and the check register transaction date is
  // less than or equal to the inputted ending date, then append a ‘W’ and
  // the check register debit amount to the extracted data file and
  // increment the line counter “PickVar” by 1.
  if ( kh != 'D' && eh != 'E' && ch == 'N' && dh == 'N' && date_compare == 0 ) {
  inn -> seekpos(fileoffset+MAXDAT+MAXINVNO+MAXSELL+MAXNOTE2+MAXSELL-5, ios::in);
			  for(a=0; a<MAXSELL-1; a++) ofile.writeByte(ifile.readByte());
			  ofile.writeByte('W');
			  PickVar++;
  }

  // advance to the next fixed width record in the check register.
  fileoffset = fileoffset + CHECKBLEN;

  } while(fileoffset < sizeofdatafile);
  ifile.close();
  ofile.close();

  // initialize the 2 2-dimensional char arrays to prepare for
  // loading the first 50 rows of the extracted check register data.
  for(a=0; a<50; a++) {
  for(f=0; f<MAXSELL-1; f++) Xvault2_[f][a] = 32;
  for(f=0; f<MAXSELL-1; f++) Xvault4_[f][a] = 32;
  }

  // loop around the extracted data file "test_x.txt" to load
  // the first 50 rows of data into 2 2-dimensional char arrays
  // that will later populate the print preview window. also,
  // sum deposits and withdrawals with looping.
  fileinfo = open("test_x.txt", ios::binary);
  sizeofdatafile = filelength(fileinfo);
  close(fileinfo);

  ifile.open("test_x.txt", ios::in | ios::binary);
  inn = ifile.rdbuf();
  CountVar_ = 0;
  KountVar = 0;
  fileoffset = 0;
  accum = 0;
  accum2 = 0;
  do {

  // read the amount from the current file offset and convert
  // this to a numerical amount for further processing.
  inn -> seekpos(fileoffset+MAXSELL-1, ios::in);
  kh = ifile.readByte();
  inn -> seekpos(fileoffset, ios::in);
  for(a=0; a<MAXSELL; a++) ExtractedAmt[a] = ifile.readByte();

  for(a=0; a<MAXSELL; a++) {
	  if(StartingAmt[a] < 46 || StartingAmt[a] > 57) StartingAmt[a] = 32;
  }

  r = 0;
  do {
  		if(StartingAmt[9] < 48 || StartingAmt[9] > 57) {
				for(f=9; f>0; f--) StartingAmt[f] = StartingAmt[f-1];
			   StartingAmt[0] = 32;
	  	}
  r++;
  } while(r < 10);

  for(a=0; a<MAXSELL-1; a++) {
  convert_to_number[a]=0;
  if(StartingAmt[a] == 48) convert_to_number[a] = 0;
  if(StartingAmt[a] == 49) convert_to_number[a] = 1;
  if(StartingAmt[a] == 50) convert_to_number[a] = 2;
  if(StartingAmt[a] == 51) convert_to_number[a] = 3;
  if(StartingAmt[a] == 52) convert_to_number[a] = 4;
  if(StartingAmt[a] == 53) convert_to_number[a] = 5;
  if(StartingAmt[a] == 54) convert_to_number[a] = 6;
  if(StartingAmt[a] == 55) convert_to_number[a] = 7;
  if(StartingAmt[a] == 56) convert_to_number[a] = 8;
  if(StartingAmt[a] == 57) convert_to_number[a] = 9;
  }
  // accumulate for deposit transactions into the variable “accum”.
  if ( kh == 'D' ) accum = accum + ( (convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) +
  (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1) );
  // accumulate for withdrawal transactions into the variable “accum2”.
  if ( kh == 'W' ) accum2 = accum2 + ( (convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) +
  (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1) );
	     // if the transaction is a deposit and all 50 rows of the
             // 2-dimensional char array “Xvault2_” have not been filled,
             // then add the amount to the current slot in the char array
             // “Xvault2_” and then increment the row counter “CountVar_” by 1.
             if ( kh == 'D' && CountVar_ < 50 ) {
		  inn -> seekpos(fileoffset, ios::in);
		      for(r=0; r<MAXSELL-1; r++) Xvault2_[r][CountVar_] = ifile.readByte();
		      CountVar_++;
	     }
	          // if the transaction is a withdrawal and all 50 rows of the
                  // 2-dimensional char array “Xvault4_” have not been filled,
                  // then add the amount to the current slot in the char array
                  // “Xvault4_” and then increment the row counter “KountVar” by 1.
    		  if ( kh == 'W' && KountVar < 50 ) {
			  inn -> seekpos(fileoffset, ios::in);
				  	for(r=0; r<MAXSELL-1; r++) Xvault4_[r][KountVar] = ifile.readByte();
				  	KountVar++;
		  }

  // advance to the next fixed width record in the extracted check book data file.
  fileoffset = fileoffset + MAXSELL;

  } while(fileoffset < sizeofdatafile);
  ifile.close();

  // calculate the ending balance that will appear on the check
  // register reconciliation. this is the starting balance less
  // deposits plus withdrawals.
  endbal = startbal - accum + accum2;

  // take the numerical ending balance amount and convert it to
  // chars to be stored in the char array “totpay”.	
  for(a=0; a<MAXSELL; a++) totpay[a] = 32;
	  if(endbal < 0) {
	  totpay[0] = '-';
	  endbal = -endbal;
	  }
  totpay[9] = 48;
  totpay[8] = 48;
  totpay[7] = 46;
  totpay[6] = 48;
  r=9;
  do {
  n=ldiv(endbal,10L);
  endbal=n.quot;
  if(n.rem==0) totpay[r] = 48;
  if(n.rem==1) totpay[r] = 49;
  if(n.rem==2) totpay[r] = 50;
  if(n.rem==3) totpay[r] = 51;
  if(n.rem==4) totpay[r] = 52;
  if(n.rem==5) totpay[r] = 53;
  if(n.rem==6) totpay[r] = 54;
  if(n.rem==7) totpay[r] = 55;
  if(n.rem==8) totpay[r] = 56;
  if(n.rem==9) totpay[r] = 57;
  r--;
  if(r == 7) r--;
  } while(endbal > 0);

  r=0;
  do {
  r++;
  } while(totpay[r] == 32 && r < MAXSELL-1);
  totpay[r-1] = '$';
  
  // set the cursor to an arrow.
  SetCursor(0, IDC_ARROW);

		// this code will calculate the number of pages in the
		// print preview assuming there are 50 lines per page.
		mPage2 = 0;
		do {
		mPage2++;
		PickVar = PickVar - 50;
		} while( PickVar >= 50 );
			if ( PickVar > 0 ) mPage2++;

// this code snippet will initialize the trappings of a "TDecoratedFrame"
// object, “frame_d”. it will incorporate the “TPrevWindow” class as well
// as the bitmaps associated with each member function of the class into
// the "TDecoratedFrame" object. a control bar object, “ControlBar”, is
// constructed from "TMyControlBar". the buttons for the member functions
// are embedded into this control bar. the dimensions of the "TDecoratedFrame"
// window are set as well as the page count and the file stream offset,
// “fileoffset”. finally, the decorated print preview window is brought to life
// with the directive, “frame_d->Create()”.
TDecoratedFrame* frame_d = new TDecoratedFrame(0, "Reconciliation Preview", new TPrevWindow, false);
hndl = this->GetHandle();
TMyControlBar* ControlBar;
ControlBar = new TMyControlBar(frame_d);
frame_d->Insert(*ControlBar, TDecoratedFrame::Top);
G1 = new TButtonGadget(IDB_BITMAP1, IDB_BITMAP1);
ControlBar->Insert(*G1);
Ge1 = new TButtonGadgetEnabler(frame_d->GetHandle(), G1);
ControlBar->Insert(*new TSeparatorGadget);
G2 = new TButtonGadget(IDB_BITMAP2, IDB_BITMAP2);
ControlBar->Insert(*G2);
Ge2 = new TButtonGadgetEnabler(frame_d->GetHandle(), G2);
ControlBar->Insert(*new TSeparatorGadget);
ControlBar->Insert(*new TButtonGadget(IDB_BITMAP3, IDB_BITMAP3, 0, true));
ControlBar->Insert(*new TSeparatorGadget);
PageCount = 1;
fileoffset = 0;
frame_d->Attr.X = 10;
frame_d->Attr.Y = 10;
frame_d->Attr.W = 630;
frame_d->Attr.H = 440;
	// the page navigation buttons are initially enabled and/or
        // disabled based on the number of pages in the print preview
        // operation for cases where the total number of pages is 1 or
        // there are at least 2 or more pages.
	if ( mPage2 == 1 ) {
	Ge1->Enable(false);
	Ge2->Enable(false);
	}
		if ( mPage2 >= 2 ) {
		Ge1->Enable(true);
		Ge2->Enable(false);
		}
			frame_d->Create();

}

// the page navigation buttons are enabled and disabled based on the number
// of pages in the print preview and also at what page number in the preview
// operation is currently being viewed. the variable “PageCount” holds the
// number of the currently displayed page in the preview screen. this member
// function, "TBalEndDlg::WMChar(WPARAM cmd, LPARAM cmd2)", will be sent to
// the handle of the decorated print preview window to use the current page
// number as well as the total number of pages in the print preview operation
// to update which navigation buttons on the decorated window are enabled
// and/or disabled.
LRESULT
TBalEndDlg::WMChar(WPARAM cmd, LPARAM cmd2)
{

 if ( mPage2 >= 2 && PageCount < mPage2 && PageCount > 1 ) {
 Ge1->Enable(true);
 Ge2->Enable(true);
 }

 	if ( mPage2 >= 2 && PageCount == mPage2 ) {
Ge1->Enable(false);
Ge2->Enable(true);
}

 if ( mPage2 >= 2 && PageCount == 1 ) {
 Ge1->Enable(true);
 Ge2->Enable(false);
 }

}


為螢幕上的列印預覽編寫程式碼

下面是“TPrevWindow”類中的“Paint(TDC& dc, bool erase, TRect& rect)”成員元件下的程式碼,它將在資料提取處理完成後出現的裝飾視窗框架中繪製列印預覽資訊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

void
TPrevWindow::Paint(TDC& dc, bool erase, TRect& rect)
{
  // declare variables for this function.
  long int   datecomponent,monthvar,dayvar,yearvar, pagevar;
  int          exta,a,b,f,r,t,ext1,ext2,ext3,ext4,ext44,MarkVar1,MarkVar2,ext5,ext6,ext7;
  float       linecounter;
  char       var[3],Date_[MAXDAT],var2[5];
  char       Idate[MAXDAT],Ino[MAXINVNO],Inamt[MAXSELL],Idescr[MAXNOTE2],Icomp[MAXCOMPANY2];
  char       Indescr[MAXNOTE2],Indisc[MAXSELL],Inpay[MAXSELL],Idr[MAXSELL],Ie_desc[MAXNOTE];
  char       Ivalue[MAXSELL2],Icr[MAXSELL],Ibal[MAXSELL],Ivend[MAXCOMPANY2],Icode[MAXCCODE];
  char       Ipd[MAXDAT],Iinv[MAXDAT],Icrx[13],Ibalx[13],Idrx[13];
  struct     dosdate_t d;
  ldiv_t      n;
  TSize     extent;


  // take the current page number of the print preview and
  // convert to chars to be stored in the char array “var2”.	
  Pagevar = PageCount;
  for(a=0; a<5; a++) var2[a] = 32;
  var2[4] = 48;
  b=4;
  do {
  n = ldiv(pagevar,10L);
  pagevar = n.quot;
  if(n.rem==0) var2[b] = 48;
  if(n.rem==1) var2[b] = 49;
  if(n.rem==2) var2[b] = 50;
  if(n.rem==3) var2[b] = 51;
  if(n.rem==4) var2[b] = 52;
  if(n.rem==5) var2[b] = 53;
  if(n.rem==6) var2[b] = 54;
  if(n.rem==7) var2[b] = 55;
  if(n.rem==8) var2[b] = 56;
  if(n.rem==9) var2[b] = 57;
  b--;
  } while(pagevar > 0);
  var2[5]=0;


  // take the current date components month, day and year and
  // convert to chars to be stored in the char array “Date_”.	
  _dos_getdate(&d);
  monthvar = d.month;
  dayvar = d.day;
  yearvar = d.year;

  // take the current date components month, day and year and
  // convert to chars to be stored in the char array “Date_”.	
  for(a=0; a<MAXDAT; a++) Date_[a] = 32;
	  Date_[2] = 47;
	  Date_[5] = 47;
	  t=0;
		  do {

			  if(t == 0) datecomponent = monthvar;
			  if(t == 1) datecomponent = dayvar;
			  if(t == 2) {
			  datecomponent = yearvar;
				  // y2k adjustment.	
				  if (datecomponent < 2000 )
				  datecomponent = datecomponent - 1900;
				  else
				  datecomponent = datecomponent - 2000;
				      }

  var[0] = 48;
  var[1] = 48;
  var[2] = 32;
  b=1;
  do {
  n=ldiv(datecomponent,10L);
  datecomponent =n.quot;
		if(n.rem==0) var[b] = 48;
	  	if(n.rem==1) var[b] = 49;
		if(n.rem==2) var[b] = 50;
		if(n.rem==3) var[b] = 51;
		if(n.rem==4) var[b] = 52;
		if(n.rem==5) var[b] = 53;
		if(n.rem==6) var[b] = 54;
  		if(n.rem==7) var[b] = 55;
	  	if(n.rem==8) var[b] = 56;
		if(n.rem==9) var[b] = 57;
  b--;
  } while(datecomponent > 0);

  if(t==0) for(a=0; a<2; a++) Date_[a] = var[a];
  if(t==1) for(a=0; a<2; a++) Date_[3+a] = var[a];
  if(t==2) for(a=0; a<2; a++) Date_[6+a] = var[a];

  t++;
  } while(t < 3);
  Date_[MAXDAT-1] = 0;


  // set the print preview to scale 100 logical units per
  // inch of screen width. set the mapping mode to “MM_LOENGLISH”
  // and save the current device context.
  const UnitsPerInch = 100;
  dc.SaveDC();
  dc.SetMapMode(MM_LOENGLISH);
  int x1 = 0;
  int y1 = 0;

  // using a bold "Times New Roman" font, paint the heading
  // and column labels of the print preview.
  TFont fontBold2("Times New Roman", 20, 8, 0, 0, FW_BOLD);

  dc.SelectObject(fontBold2);

  dc.TextOut(x1 + ( 0.40 * UnitsPerInch ), y1 - ( 0.20 * UnitsPerInch ), "Page:", 5);

  extent = dc.GetTextExtent("Page:", 5);
  ext1 = extent.cx;

  dc.TextOut(x1 + ( 0.40 * UnitsPerInch ), y1 - ( 0.40 * UnitsPerInch ), "Date:", 5);

  extent = dc.GetTextExtent("Date:", 5);
  ext2 = extent.cx;

  dc.TextOut(x1 + ( 5.65 * UnitsPerInch ), y1 - ( 0.20 * UnitsPerInch ), "Acme Company", 12);
  dc.TextOut(x1 + ( 5.65 * UnitsPerInch ), y1 - ( 0.40 * UnitsPerInch ), "123 Acme Blvd.", 14);
  dc.TextOut(x1 + ( 5.65 * UnitsPerInch ), y1 - ( 0.60 * UnitsPerInch ), "Anywhere, Anystate 44444", 24);

  dc.TextOut(x1 + ( 2.55 * UnitsPerInch ), y1 - ( 0.85 * UnitsPerInch ), "Reconciliation", 14);

  dc.TextOut(x1 + ( 0.15 * UnitsPerInch ), y1 - ( 1.15 * UnitsPerInch ), "Starting Balance", 16);
  dc.TextOut(x1 + ( 1.75 * UnitsPerInch ), y1 - ( 1.15 * UnitsPerInch ), "Deposits", 8);
  dc.TextOut(x1 + ( 3.00 * UnitsPerInch ), y1 - ( 1.15 * UnitsPerInch ), "Checks/Withdrawals", 18);
  dc.TextOut(x1 + ( 6.00 * UnitsPerInch ), y1 - ( 1.15 * UnitsPerInch ), "Ending Balance", 14);

  // using a normal "Times New Roman" font, paint the extracted
  // check register data previously stored in the 2 2-dimensional
  // char arrays “Xvault2_” and “Xvault4_”.
  TFont fontNorm2("Courier", 20, 8, 0, 0, FW_NORMAL);

  dc.SelectObject(fontNorm2);

  linecounter = 1.35;
  f = 0;
  MarkVar1 = 0;
  MarkVar2 = 0;
  do {

	  for(r=0; r<MAXSELL-1; r++) Idr[r] = Xvault2_[r][f];
		  for(r=0; r<MAXSELL-1; r++) Icr[r] = Xvault4_[r][f];

			  for(r=0; r<MAXSELL; r++) {
				  if(Sellvarq_[r] < 33 || Sellvarq_[r] > 126) Sellvarq_[r] = 32;
					  if(Idr[r] < 33 || Idr[r] > 126) Idr[r] = 32;
						  if(Icr[r] < 33 || Icr[r] > 126) Icr[r] = 32;
							  if(totpay[r] < 33 || totpay[r] > 126) totpay[r] = 32;
			  }

  Sellvarq_[MAXSELL-1] = 0;
  Idr[MAXSELL-1] = 0;
  Icr[MAXSELL-1] = 0;
  totpay[MAXSELL-1] = 0;

  	if ( PageCount == 1 && MarkVar1 == 0 ) {
dc.TextOut(x1 + ( 0.15 * UnitsPerInch ), y1 - ( rr * UnitsPerInch ), Sellvarq_, MAXSELL-1);
	MarkVar1 = 1;
	}
  	dc.TextOut(x1 + ( 1.75 * UnitsPerInch ), y1 - ( rr * UnitsPerInch ), Idr, MAXSELL-1);
	dc.TextOut(x1 + ( 3.00 * UnitsPerInch ), y1 - ( rr * UnitsPerInch ), Icr, MAXSELL-1);
  		if ( PageCount == mPage2 && MarkVar2 == 0 && Xvault4_[MAXSELL-2][f+1] == 32 ) {
dc.TextOut(x1 + ( 6.00 * UnitsPerInch ), y1 - ( rr * UnitsPerInch ), totpay, MAXSELL-1);
		MarkVar2 = 1;
		}
  		linecounter = linecounter + 0.20;
  		f++;

  } while(f < 50);

  var2[5] = 0;
	  dc.TextOut(x1 + ( 0.46 * UnitsPerInch ) + ext1, y1 - ( 0.20 * UnitsPerInch ), var2, 5);
		  Date_[MAXDAT-1] = 0;
dc.TextOut(x1 + ( 0.46 * UnitsPerInch ) + ext2, y1 - ( 0.40 * UnitsPerInch ), Date_,    MAXDAT-1);

dc.RestoreObjects();
}

這就是列印預覽螢幕的樣子。




導航和列印按鈕的程式碼來了

下一部分將探討用於“TPrevWindow”類成員函式的程式碼。下面我包含了在操作員單擊列印預覽視窗的“右箭頭”按鈕後導航到下一頁的 C++ 程式碼。如前所述,它會將提取的支票登記二進位制資料檔案“test_x.txt”的檔案偏移量向前移動 50 行支票登記交易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

// this “PrnNext” member function of the “TPrevWindow”
// class will advance to the next page in the print preview window.
void
TPrevWindow::PrnNext()
{
  // declare variables for this function.
  int          fileinfo,a,f,CountVar_,r,KountVar,b;
  long int   sizeofdatafile,fileoffset_local, convert_to_number[13],accum,accum2;
  char       Runbal[MAXSELL],kh;
  streambuf *inn = cin.rdbuf();
  ifpstream ifile;
  ldiv_t      n;

  // if the current page is less than the total number of pages in the print preview 
  // operation, then increment the file stream offset by an amount equivalent to 50 rows
  // of extracted check register data. also, blank out the 2 2-dimensional char arrays
  // used to populate the print preview window.
  if ( PageCount < mPage2 ) {
  PageCount++;
  fileoffset = fileoffset + ( 50 * MAXSELL );
  for(a=0; a<50; a++) {
  for(f=0; f<MAXSELL-1; f++) Xvault2_[f][a] = 32;
  for(f=0; f<MAXSELL-1; f++) Xvault4_[f][a] = 32;
  }

  // get the length of the extracted check register data file and open a file stream to it. also,
  // initialize the variables used before commencing the "do-while" loop.
  fileinfo = open("test_x.txt", ios::binary);
  sizeofdatafile = filelength(fileinfo);
  close(fileinfo);

  ifile.open("test_x.txt", ios::in | ios::binary);
  inn = ifile.rdbuf();
  CountVar_ = 0;
  KountVar = 0;
  fileoffset_local = fileoffset;

  // loop around and fill the 2 2-dimensional char arrays with the next 50 rows of
  // extracted check register data or to the end of the data file, whichever comes first.
  do {

  inn -> seekpos(fileoffset_local+MAXSELL-1, ios::in);
  kh = ifile.readByte();

          // if it is a deposit transaction, then
          // add the amount to the char array, “Xvault2_”
          // and increment the row counter "CountVar_" by 1.
	  if ( kh == 'D' ) {
	  inn -> seekpos(fileoffset_local, ios::in);
		  for(r=0; r<MAXSELL-1; r++) Xvault2_[r][CountVar_] = ifile.readByte();
		  CountVar_++;
	  }

                  // if it is a withdrawal transaction, then
                  // add the amount to the char array, “Xvault4_”
                  // and increment the row counter "KountVar" by 1.
		  if ( kh == 'W' ) {
		  inn -> seekpos(fileoffset_local, ios::in);
			  for(r=0; r<MAXSELL-1; r++) Xvault4_[r][KountVar] = ifile.readByte();
			  KountVar++;
		  }
 // advance to the next fixed width record in the extracted check book data file.
 fileoffset_local = fileoffset_local + MAXSELL;

  } while(CountVar_< 50 && KountVar < 50 && fileoffset_local < sizeofdatafile);
  ifile.close();

  // update the scroller on the print preview window. then fire a message,
  // "WM_CHAR", which is a member function of the "TBalEndDlg" dialog class
  // to the handle of the decorated print preview window to update the left
  // and right navigation keys so they enable and/or disable based on the
  // current page number and the total pages in the print preview operation.
  Scroller->ScrollBy(100, 100);
  Scroller->ScrollBy(-100, -100);
  GetWindowPtr(hndl)->SendMessage(WM_CHAR, 0, 0);

  }

}


這是操作員單擊列印預覽視窗的“左箭頭”按鈕後導航到上一頁的程式設計。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

// this “PrnPrevious” member function of the “TPrevWindow”
// class will advance to the previous page in the print preview window.
void
TPrevWindow::PrnPrevious()
{
  // declare variables for this function.
  int          fileinfo,a,f,CountVar_,r,KountVar,b;
  long int   sizeofdatafile,fileoffset_local, convert_to_number[13],accum,accum2;
  char       Runbal[MAXSELL],kh;
  streambuf *inn = cin.rdbuf();
  ifpstream ifile;
  ldiv_t      n;

  // if the current page is greater than one, then decrement the file stream offset by
  // an amount equivalent to 50 rows of extracted check register data. also,
  // blank out the 2 2-dimensional char arrays used to populate the print preview  window.
  if ( PageCount > 1 ) {
  PageCount--;
  fileoffset = fileoffset - ( 50 * MAXSELL );
  for(a=0; a<50; a++) {
  for(f=0; f<MAXSELL-1; f++) Xvault2_[f][a] = 32;
  for(f=0; f<MAXSELL-1; f++) Xvault4_[f][a] = 32;
  }

 // get the length of the extracted check register data file and open a file stream to it. also,
 // initialize the variables used before commencing the "do-while" loop.
 fileinfo = open("test_x.txt", ios::binary);
 sizeofdatafile = filelength(fileinfo);
 close(fileinfo);

  ifile.open("test_x.txt", ios::in | ios::binary);
  inn = ifile.rdbuf();
  CountVar_ = 0;
  KountVar = 0;
  fileoffset_local = fileoffset;

  // loop around and fill the 2 2-dimensional char arrays with the next 50 rows of
  // extracted check register data or to the end of the data file, whichever comes first.
  do {

  inn -> seekpos(fileoffset_local+MAXSELL-1, ios::in);
  kh = ifile.readByte();

          // if it is a deposit transaction, then
          // add the amount to the char array, “Xvault2_”
          // and increment the row counter "CountVar_" by 1.
	  if ( kh == 'D' ) {
	  inn -> seekpos(fileoffset_local, ios::in);
		  for(r=0; r<MAXSELL-1; r++) Xvault2_[r][CountVar_] = ifile.readByte();
		  CountVar_++;
	  }

                  // if it is a withdrawal transaction, then
                  // add the amount to the char array, “Xvault4_”
                  // and increment the row counter "KountVar" by 1.
		  if ( kh == 'W' ) {
		  inn -> seekpos(fileoffset_local, ios::in);
			  for(r=0; r<MAXSELL-1; r++) Xvault4_[r][KountVar] = ifile.readByte();
			  KountVar++;
		  }

 // advance to the next fixed width record in the extracted check book data file.
 fileoffset_local = fileoffset_local + MAXSELL;

  } while(CountVar_< 50 && KountVar < 50 && fileoffset_local < sizeofdatafile);
  ifile.close();

  // update the scroller on the print preview window. then fire a message,
  // "WM_CHAR", which is a member function of the "TBalEndDlg" dialog class
  // to the handle of the decorated print preview window to update the left
  // and right navigation keys so they enable and/or disable based on the
  // current page number and the total pages in the print preview operation.
  Scroller->ScrollBy(100, 100);
  Scroller->ScrollBy(-100, -100);
  GetWindowPtr(hndl)->SendMessage(WM_CHAR, 0, 0);

  }

}


下面的程式碼塊在操作員單擊列印預覽視窗的“印表機”按鈕後觸發。它將顯示一個標準的 Windows 印表機對話方塊,用於選擇所需的印表機。操作員還可以指定所需的份數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

// this “PrnImage” member function of the “TPrevWindow” class will display a print dialog on top of the print
// preview screen. it allows the operator to select the desired printer to render print preview output to.
// the operator can also set the number of copies for the print operation via the
// “mData.GetDevMode()->dmCopies” directive. The other parameters of the print dialog could be processed,
// but the customer had no need for this added functionality.
void
TPrevWindow::PrnImage()
{
  // declare variables for this function.
  int          totcopies,numberofcopies,pcounter;

  // set the “Printer” object to null and construct the “mData” object from “TPrintDialog::TData”.
  // then set the “mPageDoc” variable to the number of pages in the print preview operation.
  Printer = 0;
  TPrintDialog::TData mData;
  mPageDoc = mPage2;

	  // upon clicking the “OK” button in the printer dialog screen, proceed with as follows.
	  if ( TPrintDialog(this, mData).Execute() == IDOK ) {

		  // get the number of copies desired from the printer dialog and multiply that by the 
		  // number of pages in the print preview operation.	
		  totcopies = mData.GetDevMode()->dmCopies;
		  mPage2 = mPage2 * totcopies;
		  // if the current print preview page is greater than 1, then scroll back the 
		  // print preview by 1 page until you are viewing the first page of the print preview.		
		  if ( PageCount > 1 ) {
			  do {
			  TPrevWindow::PrnPrevious();
			  } while(PageCount > 1);
		  }

			  // next, intialize a couple of variables and then render the print preview to the selected
			  // printer for the total number of printed copies desired.				
			  fileoffset = 0;
			  pcounter = 0;
			  do {
			  numberofcopies = 0;
				  do {
				  Printer = new TPrinter; 
				  T2Printout   printout("Reconciliation", this);
				  Printer->SetData(&mData);
				  Printer->Print(this, printout, false);
				  Printer = 0;
				  numberofcopies++;
				  } while(numberofcopies < totcopies);
					  if ( PageCount < mPageDoc) TPrevWindow::PrnNext();
			  pcounter++;
			  } while(PageCount <= mPageDoc && pcounter < mPageDoc);

  }

}


這是單擊“列印”按鈕後出現的內容。




將列印預覽渲染到所選印表機的程式碼

單擊列印對話方塊上的“列印”按鈕後,下面的程式碼將輸出渲染到所選印表機。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

// this is the class declaration for the “T2Printout” class, which
// handles the rendering of what appears in the print preview window
// to a selected printer from the printer dialog.
//
// class T2Printout
// ~~~~~ ~~~~~~~~~~~~~
class T2Printout : public TPrintout {
  public:
	 T2Printout(const char* title, TWindow* window);
    
    void GetDialogInfo(int& minPage, int& maxPage, int& selFromPage, int& selToPage);
    void PrintPage(int page, TRect& rect, unsigned flags);
    void SetBanding(bool b) {Banding = b;}
    bool HasPage(int pageNumber) {return pageNumber == 1;}

  protected:
	 TWindow* Window;
	 BOOL     Scale;
};

// instantiate the “T2Printout” class.
T2Printout::T2Printout(const char* title, TWindow* window)
  : TPrintout(title)
{
  Window = window;
  Scale = TRUE;
}

// initialize the default parameters for the minimum and
// the maximum number of pages as well as the selected
// number of pages to print. these range from 1 to the
// number of pages in the print preview. there is no
// additional programming to change these parameters
// in this case.
void
T2Printout::GetDialogInfo(int& minPage, int& maxPage, int& selFromPage, int& selToPage)
{
  minPage = 1;
  maxPage = mPage2;
  selFromPage = 1;
  selToPage = mPage2;
}

// this will render the print preview output onto the selected printer.
void
T2Printout::PrintPage(int page, TRect& rect, unsigned flags)
{
  // scale the DC (device context) to the window so the
  // printout will mirror the print preview window. notice
  // that the mapping mode is calibrated in “LOENGLISH”
  // units. this unit of measure equates 100 logical device
  // units to one inch of screen width.
  //
  // declare variables for this function.
  int    prevMode;
  TSize  oldVExt, oldWExt;

  if (Scale) {
    prevMode = DC->SetMapMode(MM_LOENGLISH);
    TRect windowSize = Window->GetClientRect();
    DC->SetWindowExt(windowSize.Size(), &oldWExt);
    DC->SetViewportExt(PageSize, &oldVExt);
    DC->DPtoLP(rect, 2);
  }

  // call the window to paint itself.
  Window->Paint(*DC, FALSE, rect);

  // restore changes made to the DC (device context).
  if (Scale) {
    DC->SetWindowExt(oldWExt);
    DC->SetViewportExt(oldVExt);
    DC->SetMapMode(prevMode);
  }

}


結論

這段列印預覽程式碼已被證明可以在 Windows ME、XP、Vista 和 7 中可靠執行。如果您使用 Borland C++ 5.02 平臺進行編碼,它將為實現列印預覽操作提供一個不錯的框架。我的一些 最好的 客戶多年來一直使用它。除了我的 程式設計 服務外,請訪問我的網站以瞭解更多關於我的 電腦維修 服務和我的 “修理我的電腦” 技術技巧。