如何更新窗口内的文本?

时间:2015-03-27 22:30:39

标签: c windows

我正在尝试创建我的第一个GUI应用程序。我只想显示一个文本(可能是一个数字),然后在循环中更改/更新它。我找到了一些基本的例子来创建和显示一个窗口,有一些文本,但我如何更新文本? 有人能告诉我一个简单的例子吗?一个很好的例子就是显示时间。

提前致谢!

更新: 这是我的代码。这没什么特别的,我只是从MSDN上做了一个例子。

#include <windows.h>  
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

static TCHAR szWindowClass[] = _T( "win32app" );
static TCHAR szTitle[] = _T( "Win32 Guided Tour Application" );

HINSTANCE hInst;

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

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_APPLICATION ) );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_APPLICATION ) );

if ( !RegisterClassEx( &wcex ) )
{
    MessageBox( NULL, _T( "Call to RegisterClassEx failed!" ), _T( "Win32 Guided Tour" ), NULL );

    return 1;
}

hInst = hInstance; // Store instance handle in our global variable

HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL );

if ( !hWnd )
{
    MessageBox( NULL, _T( "Call to CreateWindow failed!" ), _T( "Win32 Guided Tour" ), NULL );

    return 1;
}

ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );

HDC hdc;
PAINTSTRUCT ps;
// Main message loop:
MSG msg;
char test[ 100 ] = { 0 };
int i = 0;
while ( GetMessage( &msg, NULL, 0, 0 ) )
{
    i++;
    hdc = BeginPaint( hWnd, &ps );
    sprintf(test, "%d", i);
    TextOutA( hdc, 5, 5, test, strlen( test ) );

    EndPaint( hWnd, &ps );
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}

return ( int )msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
 {
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T( "Hello, World!" );

switch ( message )
{
    case WM_PAINT:
        hdc = BeginPaint( hWnd, &ps );

        TextOut( hdc, 5, 5, greeting, _tcslen( greeting ) );

        EndPaint( hWnd, &ps );
        break;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    default:
        return DefWindowProc( hWnd, message, wParam, lParam );
        break;
}

return 0;
}

3 个答案:

答案 0 :(得分:1)

1) Do not do the drawing in your loop.
2) Only draw in WM_PAINT
3) Create a variable that contains what you want to draw
4) If you want to redraw your window, call InvalidateRect(hWnd, NULL, NULL) and it will post a WM_PAINT message to your window proc.
5) I'd suggest creating a timer that redraws maybe once every 5 seconds. Ideally, you would redraw when something changes the state of your data.  If you redraw every time through your message loop, it's going to continuously redraw and be very unresponsive.

答案 1 :(得分:1)

此示例显示如何在窗口的中心打印一个数字,并在窗口的客户区域的任何位置使用鼠标左键按下时增加和更新。

#include <windows.h>
#include <cstdio>

LRESULT __stdcall wndProc(HWND, UINT, WPARAM, LPARAM);

void register_window_class(HINSTANCE hInstance)
{
    WNDCLASSEX wndclass;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    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(COLOR_BTNFACE + 1);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = "wndclass";
    wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&wndclass);
}

HWND create_window(HINSTANCE hInstance)
{
    HWND hwnd = CreateWindowEx(
        WS_EX_OVERLAPPEDWINDOW,
        "wndclass",
        "My first window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        800,
        600,
        NULL,
        NULL,
        hInstance,
        NULL);

    return hwnd;
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int iCmdShow)
{
    try{
        register_window_class(hInstance);
        HWND hwnd = create_window(hInstance);
        ShowWindow(hwnd, SW_SHOWNORMAL);

        MSG msg;
        while(GetMessage(&msg, NULL, 0, 0)){
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return EXIT_SUCCESS;
    }
    catch(...){
        return EXIT_FAILURE;
    }
}

LRESULT __stdcall wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    RECT rect;
    PAINTSTRUCT ps;

    static int iCount = 0;
    static char buffer[256];

    switch(msg){

        case WM_LBUTTONDOWN:
            ++iCount;
            snprintf(buffer, 256, "%d", iCount);
            InvalidateRect(hwnd, NULL, true);
            return 0;

        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);

            GetClientRect(hwnd, &rect);
            SetTextAlign(hdc, TA_CENTER);
            TextOut(hdc, rect.right / 2, rect.bottom / 2, buffer, strlen(buffer));

            EndPaint(hwnd, &ps);
            return 0;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

因此,当您使用鼠标左键单击时,会显示消息

WM_LBUTTONDOWN

由Windows发送到您的窗口过程。只要发生这种情况,就会增加静态int,将其写入char缓冲区。最后,电话

InvalidateRect(hwnd, NULL, true);

使窗口的整个客户区无效。这意味着将调用WM_PAINT,因为客户区的一部分是无效的。此外,设置为true的最后一个参数确保在

hdc = BeginPaint(hwnd, &ps);

执行后,客户区的无效部分将使用窗口类中指定的背景画笔绘制。这有效地删除了任何先前的窗口内容,以便

TextOut(hdc, rect.right / 2, rect.right / 2, buffer);

有一个干净的区域可供写作。

构建程序是一个好习惯,以便累积所有信息,以便在WM_PAINT中完成重新绘制(基本上引用Charles Petzold的Win32圣经“编程Windows”)。

答案 2 :(得分:-1)

你需要在BeginPaint / EndPaint调用之间的消息循环中的WM_PAINT处理程序中完成所有绘图,否则它将被覆盖。

这是一个显示时间的示例。我使用一个计时器使生成WM_PAINT消息的窗口无效,但如果你愿意,可以采用不同的方式。

#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HINSTANCE hInst;
HWND hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    switch(message)
    {
        case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            SYSTEMTIME time;
            GetLocalTime(&time);
            wchar_t timeString[30] = {};
            GetTimeFormatEx(nullptr, 0, &time, nullptr, timeString, 30);
            RECT clientRect;
            GetClientRect(hWnd, &clientRect);
            DrawText(hdc, timeString, -1, &clientRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            EndPaint(hWnd, &ps);
        }
        break;
        case WM_TIMER:
            InvalidateRect(hWnd, nullptr, false);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"TestClass";
    wcex.hIconSm = NULL;
    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance;
    RECT sz = {0, 0, 128, 64};
    AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
    hWnd = CreateWindow(L"TestClass", L"Test Window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
        NULL, NULL, hInstance, NULL);
    if(!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MyRegisterClass(hInstance);
    if(!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    SetTimer(hWnd, 1, 1000, nullptr);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}