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

相关文章

来自专栏hightopo

HTML5的五种客户端离线存储方案

1135
来自专栏macOS 开发学习

Mac开发跬步积累(四):ImageIO解析Gif 图像数据

这里可以看到Gif 是保存了多幅图像的一个图像文件,有了这个基础认识,我们就可以使用代码来解析Gif图像了.

983
来自专栏非典型技术宅

Quartz2D进行渲染1. 渲染模式2. even-odd rule:奇偶填充规则3. nonzero winding number rule:非零绕数规则4. 其他会用到的渲染模式5. 混合模式

1103
来自专栏wym

Windows 下窗口画图---十天教会你俄罗斯方块

接上篇:https://blog.csdn.net/qq_41603898/article/details/80968333

1121
来自专栏kalifaの日々

动态规划真的可以为所欲为的(Leetcode 62/63)

看起来不错的运行效率 62题: 动态规划递推公式: 站在当前方块上可选择的路径数量 = 我正下方那个方块可选择的路径数量 + 我右侧那个方块可选择的路径数量; ...

3556
来自专栏跟着阿笨一起玩NET

WCF自我学习之(一)

本人最近才开始学习WCF服务框架,今天顺便做了一个小小的练手。适合初学者学习,故上传上来,望和大家一起共勉!高手勿进,见笑了。

661
来自专栏章鱼的慢慢技术路

使用Photoshop画一个圆锥体

2165
来自专栏点滴积累

geotrellis使用(九)使用geotrellis进行栅格渲染

目录 前言 图像渲染 总结 参考链接 一、前言        前面几篇文章讲解了如何使用Geotrellis进行数据处理、瓦片生成等,今天主要表一下如何使用Ge...

3385
来自专栏小灰灰

Java 借助ImageMagic实现图片编辑服务

Java 借助ImageMagic实现图片编辑服务 java原生对于图片的编辑处理并没有特别友好,而且问题也有不少,那么作为一个java后端,如果要提供图片的编...

7236
来自专栏游戏杂谈

Unity插件扩展中组件常用的几个方法

最近为美术编写一个Unity编辑器的扩展,主要为了减轻美术在修改预制对象时的机械化操作的繁琐和出错。具体实现的几个功能:

2541

扫码关注云+社区