【专业技术】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 条评论
登录 后参与评论

相关文章

来自专栏数据小魔方

数据透视表多表合并|字段合并

今天要跟大家分享的内容是数据透视表多表合并——字段合并! 因为之前一直都没有琢磨出来怎么使用数据透视表做横向合并(字段合并),总觉得关于表合并绍的不够完整,最近...

5168
来自专栏HTML5学堂

乐视网面试真题,非一般的题目

正文 HTML5学堂:这是一套2014年7月份乐视网的一份面试真题,虽然面试题目还算比较简单,但也很能反应面试者基础知识的掌握程度,特别是面试者对细节方面的处理...

3518
来自专栏JackieZheng

AngularJS入门心得3——HTML的左右手指令

  在《AngularJS入门心得1——directive和controller如何通信》我们提到“AngularJS是为了克服HTML在构建应用上的不足而设计...

1855
来自专栏LEo的网络日志

markdown学习

3538
来自专栏Albert陈凯

Hive Tips Hive使用技巧

http://blog.sina.com.cn/s/blog_6a7df1f1010197d2.html 在Hive中,某些小技巧可以让我们的Job执行得更快,...

2758
来自专栏编程

10个短小却超实用的JavaScript代码段

JavaScript正变得越来越流行,它已经成为前端开发的第一选择,并且利用基于JavaScript语言的NodeJS,我们也可以开发出高性能的后端服务,甚至我...

1768
来自专栏生信宝典

R语言学习 - 热图美化

热图美化 上一期的绘图命令中,最后一行的操作抹去了之前设定的横轴标记的旋转,最后出来的图比较难看。 上次我们是这么写的 p <- p + xlab("samp...

2948
来自专栏社区的朋友们

在共享内存实现 Redis(下)

从实现方式入手,设计了一种综合二者优点的方案:将 Redis 做成数据逻辑分离,数据存放共享内存,进程只负责存储逻辑,同时解决 Redis 长命令卡顿和 for...

2510
来自专栏null的专栏

hive学习笔记——Hive表的创建

初衷:以前看过Hadoop方面的材料,但是一直以来都是与实际应用脱轨,现在有机会接触到真正的Hadoop集群,还是被他的性能所震撼,利用这个机会认真重新学习下...

2813
来自专栏AhDung

【C#】让DataGridView输入中实时更新数据源中的计算列

本文适用Winform开发,且DataGridView的数据源为DataTable/DataView的情况。

792

扫描关注云+社区