【专业技术】Win32 SDK编程:我们如何输出文本

在使用Win32编程时,我们常常需要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接口(GDI)进行的,Windows的三大组件之一的GDI32.dll封装了所有的文本和图像输出函数。你也许会说直接用printf不就可以了吗?不错,这个确实是可以输出文本,但是这个智能用于console下的文本输出,而不能用于直接在窗口上面。要在窗口上输出文本,以下的函数都可以实现:

DrawText、DrawTextExt、ExtTextOut以及TextOut,这些函数基本都有相似的参数,比如hdc,坐标位置,字符串。下面以最常用的TextOut为例来说明如何在Windows窗口中如何输出文本,其他请查看MSDN的用法。TextOut的函数原型如下:

BOOL TextOut( HDC hdc, // handle to DC

intnXStart, // x-coordinate ofstarting position

intnYStart, // y-coordinate ofstarting position

LPCTSTRlpString, // character string

intcbString // number of characters

);

参数说明:

Hdc,设备上下文句柄,所有的窗口都会有这个句柄,最后的文本将在上面输出。

nXStart,字符串输出的开始横坐标。

nYStart,字符串输出的开始纵坐标。

lpString,要输出的字符串。

cbString,要输出的字符数目,注意是字符数而不是字节数。

在windows窗口上输出有两种方式来获取设备上下文句柄,一种是在处理WM_PAINT消息时通过BeginPaint函数获取,另外一种就是通过主动获取上下文句柄函数GetDC或者GetWindowDC,这种可以在任何时候进行输出,但是一旦窗口有更新,必须想办法重新绘制,否则就会消失了。而通过WM_PAINT绘制的文本会在窗口有更新时自动调用,因此不用担心什么时候需要重绘的问题,Windows会在以下的情况下受到WM_PAINT消息:

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

使用WM_PAINT还有一个好处,就是windows会自己计算哪些区域需要更新,也就是说只有真正变化的地方才会更新,这样更新的代价会降低到最小。

下面的实例中,我们用了这两种方式获取设备上下文句柄来输出文本:

#include <windows.h>

staticTCHAR szAppName[] = TEXT("HelloWin32");

staticLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

intWINAPI 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 programrequires Windows NT!"), szAppName, MB_ICONERROR);

return 0;

}

//创建主窗体

hWnd = CreateWindow(szAppName, //window class name

TEXT("TextOut demo"), // window caption

WS_OVERLAPPEDWINDOW, // window style

CW_USEDEFAULT, //initial x position

CW_USEDEFAULT, //initial y position

400, // initialx 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;

}

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

{

HDC hDC;

PAINTSTRUCTps;

static int cxClient,cyClient;

switch (message)

{

case WM_CREATE:

return 0;

case WM_SIZE:

cxClient= LOWORD(lParam);

cyClient= HIWORD(lParam);

return 0;

case WM_PAINT:

hDC= BeginPaint(hWnd, &ps);

//使用BeginPaint函数返回的句柄

TextOut(hDC,50, 50, TEXT("Hello, World!"),13);

EndPaint(hWnd,&ps);

return 0;

case WM_LBUTTONDOWN:

{

//点击鼠标左键后也执行文本输出

HDChDC = GetDC(hWnd);

//设置文本颜色

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

//设置文本背景颜色

SetBkColor(hDC,RGB(0xFF, 0, 0));

//使用GetDC函数返回的句柄

TextOut(hDC,50, 100, TEXT("This is a test!"),15);

}

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0 ;

}

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

}

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

然后我们用鼠标改变窗口大小后,可以看见直接用GetDC获取设备上下文句柄画出来的文本消失了,而在处理WM_PAINT消息时通过BeginPaint函数获取设备上下文画出来的文本依然存在。

至于用DrawText、DrawTextExt、ExtTextOut这几个函数输出文本大同小异,前面两个都增加了矩形的限制。详细用法请自己参考MSDN,通过本例,您应该学会如何输出文本了。

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-05-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏西枫里博客

Python学习笔记四(条件和循环)

写在开头:今天催更小伙伴们,突然发现自己的python学习笔记竟然一个月没更了,按照每月总更8篇计算,每月应更2篇左右的python学习笔记,也不知是杂文更的太...

471
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day5 Java中的运算符

  运算符,顾名思义就是用于运算的符号,比如最简单的+-*/,这些运算符可以用来进行数学运算,举个最简单的栗子:   已知长方形的长为3cm,高为4cm,求长方...

1877
来自专栏点滴积累

geotrellis使用(十一)实现空间数据库栅格化以及根据属性字段进行赋值

Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 安装空...

3457
来自专栏野路子程序员

Thinkphp修改一句代码,使得foreach标签支持对象,增加变量[数组对象]混合解析法!

2758
来自专栏mySoul

node工具模块

因为计算机读取的时候是从低电位进行读取,计算的时候也是从低位进行计算(人类也是这样)这样的效率一般会比较高。

994
来自专栏数据小魔方

左手用R右手Python系列之——字符串格式化进阶

关于R语言字符串格式化之前无论是专题还是案例教程中均有所涉及,今日这一篇之所以重提是因为又找到了一个很好用的字符串格式化包。 这个包的语法源于Python风格,...

28112
来自专栏技术专栏

慕课网Flask高级编程实战-11.Python与Flask的结合应用

视图函数接受用户填写的email账号,如果不存在应该跳转到404界面,这个逻辑flask-sqlalchemy为我们提供了良好的封装,不需要手动去处理,只需要调...

1203
来自专栏数说工作室

【SAS Says】基础篇:SAS宏初步

特别说明:本节【SAS Says】基础篇:SAS宏初步,用的是数说君学习《The little SAS book》时的中文笔记,我们认为这是打基础的最好选择。 ...

2824
来自专栏Golang语言社区

Go语言的 10 个实用技术--转

十条有用的 Go 技术   这里是我过去几年中编写的大量 Go 代码的经验总结而来的自己的最佳实践。我相信它们具有弹性的。这里的弹性是指:   某个应用需要适配...

3417
来自专栏Golang语言社区

十条有用的 Golang语言 技术

十条有用的 Go 技术 这里是我过去几年中编写的大量 Go 代码的经验总结而来的自己的最佳实践。我相信它们具有弹性的。这里的弹性是指: 某个应用需要适配一个灵...

3496

扫码关注云+社区