用VC6.0编写Win32程序加载文本文件

时间:2022-10-03 05:03:42

文章结构说明:

  1. 本文是要说明什么
  2. 关键代码解释和说明
  3. 上机实践的工程源码和提示

一、文章概要

  在VC6.0编译环境用C加载显示多行的文本文件。主要是参考:http://www.bccn.net/Article/kfyy/cjj/jszl/200412/430.html

  重点主要是windows中字体结构信息的学习,以及如何计算字符的宽度高度,如何排列加载的字符和文字完成多行显示。原理也很简单,得到当前设备的字符高度,第一行的起点在(0,0),第二行就是(0,字符高度),第三行就是(0,字符高度*2)等等。然后调用函数在这些位置显示字符即可。

二、代码说明

 这里解释下WM_CREATE消息处理函数的代码:

1         case WM_CREATE:
2             hdc = GetDC(hWnd);//从OS借用设备
3             GetTextMetrics(hdc, &tm);//获取显示设备上下文
4             xChar = tm.tmAveCharWidth;//设备的字符平均宽度
5             yChar = tm.tmHeight + tm.tmExternalLeading;//设备的字符高度
6             ReleaseDC(hWnd, hdc);//释放设备
7             break;

 

GetDC()函数的MSDN(VC6.0版)解释如下:

The GetDC function retrieves a handle to a display device context (DC) for the client area of a specified window or for the entire screen. You can use the returned handle in subsequent GDI functions to draw in the DC. 

即返回一个显示设备上下文句柄。

 

GetTextMetrics()函数MSDN:

The GetTextMetrics function fills the specified buffer with the metrics for the currently selected font. 

即从第一个参数——hdc显示设备上下文——中获得的一种字体有关的基本信息填入到第二个参数——tm描述字体信息的结构类型TEXTMETRIC变量中去。

 

TEXTMETRIC结构:

结构类型TEXTMETRIC描述了与一种字体有关的基本信息,它的各域所给出的字体大小以逻辑单位表示(关于逻辑单位的介绍参见下一章)。该结构类型包含有许多域,图2-2给出了与字体垂直尺寸有关的五个域的定义。

用VC6.0编写Win32程序加载文本文件
图2-1 TEXTMETRIC结构类型中定义垂直尺寸字体的域


  tmInternalLeading的值是允许在一个字符上加上重音号的空隙量,tmExternalLeading的值是字体的设计者推荐的空隙量,在显示多行文本时程序员可以拒绝使用这个空隙量。
  在TEXTMETRIC结构类型中,有两个域用来定义字符的宽度:tmAveCharWidth表示字体字符的平均宽度,tmMaxCharWidth表示字体最宽的字符的宽度。Windows中使用两种类型的字体,一类是固定宽度的字体,固定宽度的字体的每个字符的宽度是一样的,这样tmAveCharWidth和tmMaxCharWidth两值相等;另一类是可变宽度的字体,对于这类字体,每个字符占用的宽度不一样。例如, 字符“w”和“i”的宽度就不同,使用可变宽度的字体可以绘制紧凑的文本。
  可以使用函数GetTextExtent计算出一个特定的文本行的宽度和高度,使用函数GetTextMetrics可以得到字符的有关尺寸

接着是WM_PAINT的代码:

 1         case WM_PAINT:
 2 //            hdc = BeginPaint(hWnd, &ps);
 3 //            RECT rt;
 4 //            GetClientRect(hWnd, &rect);
 5 //            DrawText(hdc, "xxxx", -1, &rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
 6 //            EndPaint(hWnd, &ps);
 7 //            break;
 8 
 9             hdc = BeginPaint(hWnd, &ps);
10             line =0;
11             if((fp=fopen("e:\\xxx.txt","r"))!= NULL)  //此处文件地址要自己修改
12             {
13                 while(!feof(fp)) {
14                     int i = 0;
15                     char ch;
16                     while((ch = fgetc(fp)) != '\n' && ch != EOF)    //换行则调用TextOut显示
17                         szBuffer[i++] = (char)ch;
18                     TextOut(hdc, xChar, line*yChar, szBuffer, i);   //xChar是每行前面留出xChar宽度的空白,line*yChar是计算该行的纵坐标
19                     line++;                                         //很有趣的是,可以尝试把xChar换成0,把line*yChar换成0看看效果,会发生覆盖
20                 }
21                 fclose(fp);
22             }
23             EndPaint(hWnd, &ps);
24             break;

 

 

三、工程说明

  首先新建一个Hello World的win32 application,然后在主要的cpp中做如下修改:

  1. 加入两个头文件:

    #include <windows.h>
    #include <stdio.h>

  2. 修改WndProc函数:

    WndProc函数中需要加入WM_CREATE消息处理并修改自动生成的WM_PAINT消息处理。

 

 附:WndProc函数代码,记得要加上两个头文件。

 

 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 2 {
 3     int wmId, wmEvent;
 4     PAINTSTRUCT ps;
 5     HDC hdc;
 6     TCHAR szHello[MAX_LOADSTRING];
 7     LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
 8 
 9 //声明一些要用到的变量
10     int line;
11     TEXTMETRIC tm;
12     static int xChar, yChar;
13     char szBuffer[256];
14     FILE *fp;
15 
16     switch (message) 
17     {
18         case WM_COMMAND:
19             wmId    = LOWORD(wParam); 
20             wmEvent = HIWORD(wParam); 
21             // Parse the menu selections:
22             switch (wmId)
23             {
24                 case IDM_ABOUT:
25                    DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
26                    break;
27                 case IDM_EXIT:
28                    DestroyWindow(hWnd);
29                    break;
30                 default:
31                    return DefWindowProc(hWnd, message, wParam, lParam);
32             }
33             break;
34 
35 //加入创建窗口的消息处理
36         case WM_CREATE:
37             hdc = GetDC(hWnd);//从OS借用设备
38             GetTextMetrics(hdc, &tm);//获取显示设备上下文
39             xChar = tm.tmAveCharWidth;//设备的字符平均宽度
40             yChar = tm.tmHeight + tm.tmExternalLeading;//设备的字符高度
41             ReleaseDC(hWnd, hdc);//释放设备
42             break;
43 
44 //修改自动生成的绘图消息处理
45         case WM_PAINT:
46 //            hdc = BeginPaint(hWnd, &ps);
47 //            RECT rt;
48 //            GetClientRect(hWnd, &rect);
49 //            DrawText(hdc, "xxxx", -1, &rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
50 //            EndPaint(hWnd, &ps);
51 //            break;
52 
53             hdc = BeginPaint(hWnd, &ps);
54             line =0;
55             if((fp=fopen("e:\\xxx.txt","r"))!= NULL)  //此处文件地址要自己修改
56             {
57                 while(!feof(fp)) {
58                     int i = 0;
59                     char ch;
60                     while((ch = fgetc(fp)) != '\n' && ch != EOF)    //如果该行结束则立即调用TextOut显示该行
61                         szBuffer[i++] = (char)ch;
62                     TextOut(hdc, xChar, line*yChar, szBuffer, i);   //xChar是每行前面留出xChar宽度的空白,line*yChar是计算该行的纵坐标
63                     line++;                                         //很有趣的是,可以尝试把xChar换成0,把line*yChar换成0看看效果
64                 }
65                 fclose(fp);
66             }
67             EndPaint(hWnd, &ps);
68             break;
69         case WM_DESTROY:
70             PostQuitMessage(0);
71             break;
72         default:
73             return DefWindowProc(hWnd, message, wParam, lParam);
74    }
75    return 0;
76 }

 

PS:不知道,上面链接的网站的内容是哪本书上的,如果有读者知道,希望留言告知一下哈,谢啦。本人邮箱:huanqing2010@gmail.com