我正在使用WinAPI创建一个Windows应用程序。在处理窗口的WM_PAINT消息时,我使用TextOut()函数向用户显示更新后的文本。
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, hfDefault);
// display the user data in the window
TextOut(hdc,10,70, "Points: 0", 9);
TextOut(hdc,10,85, "Level: 0", 8);
// ...
EndPaint(hwnd, &ps);
}
break;如何在调用函数后更改TextOut()打印的文本以及决定打印文本长度的最后一个参数?
我找到的关于使用TextOut()的一切都是关于文本字体的。
发布于 2014-02-27 03:24:40
也许是这样的.
// I'll assume hwnd is global
void OnSomeActionToRefreshValues()
{
HDC hdc = ::GetDc(hwnd);
DrawValues(hdc, 88, 99);
ReleaseDC(hdc);
}
void DrawValues(HDC hdc, int points, int level)
{
// Might need a rectangle here to overwrite old text
SelectObject(hdc, hfDefault); // I assume hfDefault is global
TCHAR text[256];
swprintf_s(text, 256, L"Points: %d", points);
TextOut(hdc, 10, 70, text, wcslen(text));
swprintf_s(text, 256, L"Level: %d", level);
TextOut(hdc, 10, 85, text, wcslen(text));
}在你赢的过程中:
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd,&ps);
DrawValues(hdc, 88, 99);
EndPaint(hwnd,&ps);
break;发布于 2021-08-25 17:51:53
为了在处理WM_PAINT消息时更新窗口中显示的文本,您需要为要显示的文本字符串提供一些源。
由于你最初的帖子有点旧,Windows API已经随着Windows的新版本发生了变化,当前版本的Windows 10和Windows 11已经处于测试阶段。
由于Windows XP是用于WinAPI的16位UNICODE,因此人们大多使用wchar_t文本字符。这要求文本字符串常量需要L修饰符,就像在L"wchar_t text"中一样。
使用Visual Studio2019,我组合了一个运行在Windows10上的简单示例。这是一个简单的Windows WinAPI桌面图形用户界面应用程序。我从Visual Studio中的一个新项目开始,让集成开发环境使用wWinMain()、MyRegisterClass()、InitInstance()和WndProc()为Windows Desktop GUI应用程序生成框架。
然后,我修改了生成的源代码以执行以下操作:
在主窗口中提供了四个按钮,允许使用
我选择使用默认字体,所以没有对用于显示文本的字体进行任何修改。如果需要修改字体,则需要添加代码以创建所需的字体,在用于绘制文本的HDC中选择新字体,然后使用TextOut()使用新字体绘制文本。使用该字体后,您需要将其换回,然后将其删除。

第一步是创建一个用于管理按钮和按钮点击的数据区。我选择在InitInstance()中创建按钮。
static struct {
const wchar_t* txt; // pointer to text to display on button face
int iCount; // count of number of times button clicked
HWND hwnd; // button window handle which identifies the button
} myButtons[] = {
{L"Points up", 0, 0},
{L"Points dwn", 0, 0},
{L"Level up", 0, 0},
{L"Level dwn", 0, 0}
};
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
// create the displayed window along with the buttons.
// the buttons are in a single row at the top of the window.
POINT myPoint = { 10, 10 }; // x, y
for (auto &a : myButtons) {
a.hwnd = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
a.txt, // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
myPoint.x, // x position
myPoint.y, // y position
100, // Button width
50, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL); // Pointer not needed.
myPoint.x += 100 + 20; // button width plus a separation distance
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}更新显示窗口的源代码如下。我们有两个函数,一个是按钮单击处理程序,用于确定哪个按钮被单击了;另一个是带有WM_PAINT消息处理程序的WndProc(),用于修改显示的窗口。
// process a button click event and return an indication
// whether the button handle matches one we are managing (1)
// or not managing (0).
int buttonClick(HWND hWnd, HWND hButton)
{
// look through the list of buttons to see if the window handle
// of the button event matches one of our buttons.
for (auto &a : myButtons) {
if (a.hwnd == hButton) {
// this is one of our buttons so we increment button click count.
// then invalidate the window area and update to trigger WM_PAINT message.
a.iCount++;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
return 1; // indicate we processed this event.
}
}
return 0; // indicate we did not process this event
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
int wmCode = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
// not a menu event so see if it is a button click or not.
if (wmCode == BN_CLICKED) {
// if we are managing this button then we skip
// the DefWindowProc() otherwise it is called.
if (buttonClick(hWnd, (HWND)lParam))
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
// create the text strings we are going to display/update
wchar_t myText[2][64];
// following swprintf_s() works because template
// generates the proper call with the additional buffer
// size argument.
swprintf_s(myText[0], L"Points: %d", myButtons[0].iCount - myButtons[1].iCount);
swprintf_s(myText[1], L"Level: %d", myButtons[2].iCount - myButtons[3].iCount);
// get the text metrics of the font we are using to draw the text so
// that we can find out how tall the letters are and can adjust the
// distance for each line of text properly.
TEXTMETRIC myTextMetric = { 0 };
GetTextMetrics(hdc , &myTextMetric);
// we will use a POINT struct for maintaining the point at which
// the text output will start. x coordinate is horizontal position
// and y coordinate is the vertical position.
POINT myPoint = { 10, 150 }; // x, y
int myMargin = 5;
// iterate over the list of strings we are displaying and
// display each one on a separate line.
for (auto &a : myText) {
TextOut(hdc, myPoint.x, myPoint.y, a, wcslen(a));
myPoint.y += myTextMetric.tmHeight + myMargin;
}
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}https://stackoverflow.com/questions/22050749
复制相似问题