api (三)文本字符输出 (转)

在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接口(GDI)进行的,Windows的三大核心组件之一的GDI32.dll封装了所有的文本和图像输出。

  • GDI基本知识

Windows下要绘图和输出文本,都是通过GDI(Graphics Device Interface,图形设备接口)完成的,GDI是windows在绘制图文时的设备上下文环境,包括画笔、画刷、字体、位图等多种与绘制有关的对象。设备环境(DC)在绘制中起至关重要的作用。几乎所有的绘制(包括图形和文本)都与设备环境相关,注意“环境”的意义,就跟我们在画布上绘画和写字一样,绘制时的画布是哪个,用的什么笔,什么颜色,填充整个画布时用的什么刷子等等,这就是我们的绘制时的环境,而Windows绘图的DC设备上下文就是一样的道理。设备环境句柄(HDC)就是用来描述DC的句柄,可以说,只要有了这个句柄,就具备了在窗口上输出图形和文本的条件。你获得了窗口客户区的HDC,就可以在窗口客户区上画;你获得了窗口的非客户区HDC,就可以在它上面画;你获得了桌面HDC,就可以直接在桌面上画……

获取设备环境句柄的方法有两种:一是处理WM_PAINT消息时,通过BeginPaint函数返回。另外一种就是通过GetDC、GetWindowDC的API函数获取。

  • 通过WM_PAINT消息获取DC

Windows在检测到需要重新绘制或者刷新窗口时,会主动要求处理WM_PAINT消息。比如在如下情况下就会主动求处理:

  1. 用户移动一个窗口,导致原来被盖住的部分窗口显示出来。
  2. 用户调整窗口的大小,并且窗口风格类型设置为CS_HREDRAW和CS_VREDRAW。
  3. 程序调用ScrollWindow或者ScrollDC函数滚动客户区。
  4. 程序调用InvalidateRect或者InvalidateRgn函数,该函数显示生产一条WM_PAINT消息。

我们可以在该消息中完成图文绘制,该消息的处理具有特定的格式,必须在实际绘制前调用BeginPaint,在绘制完成后调用EndPaint函数,也就是说我们需要把所有绘制的功能都放到这两个函数之间,并且HDC也只能在这之间使用,不能保存起来在其它地方使用。使用WM_PAINT有一个好处,就是windows会自己计算哪些区域需要更新,也就是说只有真正变化的地方才会更新,这样更新的代价会降低到最小。

  • 通过API函数获取HDC

我们还可以通过GetDC、GetWindowDC函数来获取HDC,但是要注意,通过这个来获取的HDC,可以保存起来在其它时候使用,但是要记住一旦窗口有更新,必须想办法重新绘制,否则就会消失了。最后在使用完毕后需要调用ReleaseDC来释放,否则会造成资源泄露。

  • 创建特定字体

我们平时最常见的文本输出是不需要自己创建字体的,因为常见的对象都有系统预定义好的。如果想输出点特殊(非系统预定义的)字体,就需要我们创建并自动选入设备环境。创建字体主要有CreateFont和CreateFontIndirect,这两个函数的参数都很多,基本一样,具体用法看后面的实例。

  • 实现文本绘制

有了上面的基础,我们就可以通过Windows的API来完成文本输出了,常用的文本输出函数有TextOut、DrawText、DrawTextExt、ExtTextOut等,这些函数基本都有相似的参数,比如hdc,坐标位置,字符串。下面TextOut、DrawText、ExtTextOut为例来说明如何在Windows窗口中如何输出文本,其它请查看MSDN的用法。

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

#include <windows.h>

#include <tchar.h>

static TCHAR szAppName[] = TEXT("Textout");

static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

HWND     hWnd;

MSG      msg;

WNDCLASS wndclass;

wndclass.style         = CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc   = WndProc;

wndclass.cbClsExtra    = 0;

wndclass.cbWndExtra    = 0;

wndclass.hInstance     = hInstance;

wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);

wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);

wndclass.lpszMenuName  = NULL;

wndclass.lpszClassName = szAppName;

if (!RegisterClass(&wndclass))

{

MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);

return 0;

}

hWnd = CreateWindow(szAppName,            // window class name

szAppName,           // window caption

WS_OVERLAPPEDWINDOW, // window style

CW_USEDEFAULT,       // initial x position

CW_USEDEFAULT,       // initial y position

400,                 // initial x size

300,                 // initial y size

NULL,                // parent window handle

NULL,                // window menu handle

hInstance,           // program instance handle

NULL);               // creation parameters

ShowWindow(hWnd, iCmdShow);

UpdateWindow(hWnd);

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

HDC         hDC;

PAINTSTRUCT ps;

switch (message)

{

case WM_CREATE:

return 0;

case WM_PAINT:

{

RECT rect = {10, 30, 100, 50};

TCHAR str[] = TEXT("English and 中文");

hDC = BeginPaint(hWnd, &ps);

TextOut(hDC, 10, 10, str, _tcslen(str));

SetTextColor(hDC, RGB(255,0,0));

DrawText(hDC, str, -1, &rect, DT_LEFT|DT_VCENTER);

SetTextColor(hDC, RGB(0,255,0));

INT dx[] = {8,8,8,8,16,8,8,8,16,8,8,8,10};

ExtTextOut(hDC, 10, 50, 0, &rect, str, _tcslen(str), dx);

SetTextColor(hDC, RGB(0,0,255));

rect.right = 110;

rect.top = 70;

rect.bottom = 82;

ExtTextOut(hDC, 10, rect.top, ETO_CLIPPED, &rect, str, _tcslen(str), dx);

HFONT hFont = CreateFont(96,         // nHeight, 所创建字体的字符高度

0,           // nWidth,       字体的字符平均宽度

200,          // nEscapement,  字符输出方向与水平向右的方向所成角度,以0.1度为单位

0,             // nOrientation, 字符与基线的角度,以0.1度为单位

FW_BOLD,        // nWeight,      字符颜色的深浅度

TRUE,            // bItalic,      斜体属性标志(FALSE:正常字体,TRUE:斜体)

FALSE,            // bUnderline,   下划线属性标志(FALSE:无下划线,TRUE:有下划线)

FALSE,             // cStrikeOut,   删除线属性标志(FALSE:无删除线,TRUE:有删除线)

ANSI_CHARSET,       // nCharSet,        字符集标识0:ANSI字符集,1:系统缺省字符集

OUT_DEFAULT_PRECIS,  // nOutPrecision,   输出精度

CLIP_DEFAULT_PRECIS, // nClipPrecision,  剪切精度

DEFAULT_QUALITY,      // nQuality,        输出品质

DEFAULT_PITCH|FF_SWISS, // nPitchAndFamily, 字符间距

TEXT("Arial"));          // lpszFacename,    现有系统TrueType字体名称

HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);

SetBkMode(hDC, TRANSPARENT);

SetTextColor(hDC, RGB(0x00, 0xFF, 0xFF));

TextOut(hDC, 0, 150, TEXT("创建Font"), 6);

DeleteObject(hFont);

EndPaint(hWnd, &ps);

}

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0 ;

}

return DefWindowProc (hWnd, message, wParam, lParam);

}

程序运行,点击鼠标左键后效果如下:

程序中的DrawText、ExtTextOut能设置文本输出的矩形范围,超出部分是看不见的,从运行结果我们也可以看出有两行显示不全,就是由于设置的显示范围小的缘故。

另外ExtTextOut函数还可以设置字符的间距,运行结果的第三行就是这种自己设置间距不一样的结果。

本程序还用CreateFont函数创建了一个斜体、右上排列的文本串。通过上例,我们把常用的文本输出作为实例展示给大家,只要好好对照实例代码,在结合MSDN的说明,再加上本系列的第一篇的Windows编程基本框架,一定可以掌握好Windows编程的基本文本输出。

时间: 2024-12-17 10:02:24

api (三)文本字符输出 (转)的相关文章

【Windows编程】系列第三篇:文本字符输出

上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符. 在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接口(GDI)进行的,Windows的三大核心组件之一的GDI32.dll封装了所有的文本和图像输出. GDI基本知识 Windows下要绘图和输出文本,都是通过GDI(Graphics Device Interface,图形设备接口)完成的,GDI是windows在绘制图文时的设备上下文环境,包括画

c语言:先后输出BOY三个字符

先后输出BOY三个字符. 程序: #include<stdio.h> int main() { char   a='B', b = 'O', c = 'Y'; putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; } 结果: BOY 请按任意键继续. . .

c语言:从键盘输入BOY三个字符,然后把它们输出到屏幕。

从键盘输入BOY三个字符,然后把它们输出到屏幕. 程序: #include<stdio.h> int main() { char a,b,c; printf("请输入字符:"); a=getchar();//注意getchar一次只能读入1个字符 b=getchar(); c=getchar(); putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; } 结果: 请输入字符:BOY BOY 请按任意键继续.

输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符。

ASCII码排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符. 输入 第一行输入一个数N,表示有N组测试数据.后面的N行输入多组数据,每组输入数据都是占一行,有三个字符组成,之间无空格. 输出 对于每组输入数据,输出一行,字符中间用一个空格分开. 样例输入 2 qwe asd 样例输出 e q w a d s #include <iostream> using namespace

【c语言】先后输出BOY三个字符

// 先后输出BOY三个字符 #include <stdio.h> int main() { char a = 'B'; char b = 'O'; char c = 'Y'; putchar(a); putchar(b); putchar(c); printf("\n"); return 0; } <img src="http://img.blog.csdn.net/20150423121000488?watermark/2/text/aHR0cDovL2

【c语言】从键盘输入BOY三个字符,然后把它们输出到屏幕

// 从键盘输入BOY三个字符,然后把它们输出到屏幕 #include <stdio.h> int main() { char a,b,c; printf("请输入三个字符:"); a = getchar(); b = getchar(); c = getchar(); putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; } <img src="http://img.blog.csdn.n

ASP.net MVC4 View设置Html代码显示为文本字符问题

问题描述: 在ASP.net MVC4 框架下,在后台ViewBag上设置连接属性 ViewBag.link = "<a href='/'>"+DisplayName+"</a>"; 前台输出时使用 <span>@ViewBag.link</span> 页面上显示的内容变成了 <a href='/'>"+DisplayName+"</a> 没有做成链接. 修改方法: 前台输出

LINUX设备驱动程序笔记(三)字符设备驱动程序

      <一>.主设备号和次设备号        对字符设备的访问时通过文件系统内的设备名称进行的.那些设备名称简单称之为文件系统树的节点,它们通常位于/dev目录.字符设备驱动程序的设备文件可通过ls -l命令输出的第一列中的'c'来识别.块设备同样位于/dev下,由字符'b'标识 crw-rw----  1 root root    253,   0 2013-09-11 20:33 usbmon0 crw-rw----  1 root root    253,   1 2013-09

将键盘按下的字符输出到窗口上

要实现字符的输入,也就是当用户在键盘按下某个字符按键后,要把该字符输出到窗口上,这就需要程序捕获键盘按下消息(WM_CHAR消息):将每次输入的字符都先存储到一个单独的字符串中,每当按下新的字符时,都先将字符加到字符串中,然后再在窗口当前插入符的位置把这个字符串重新输出一次. 1.首先让CTextView类捕获WM_CHAR消息,生成消息响应函数 2.接着为CTextView类添加一个成员变量: CString m_strLine,用来存储单独的字符串 3.在CTextView类的构造函数中将变