Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   C++ Warum wird Fensterinhalt nicht neu gezeichnet? (https://www.delphipraxis.net/204851-warum-wird-fensterinhalt-nicht-neu-gezeichnet.html)

delphifan2004 6. Jul 2020 21:25

Warum wird Fensterinhalt nicht neu gezeichnet?
 
Hallo,

ich beschäftige mich gerade etwas mit C++, zu Delphi gibt es ja neben dem Pascal Compiler auch den C++ Compiler und da habe ich aus dem Buch "Programming Windows" fifth Edition von Charles Petzold das folgende Programm von Seite 44 abgetippt:

Delphi-Quellcode:
#include <windows.h>
#include <winuser.h>
#include <stdarg.h>
#include <tchar.h>
#include <stdio.h>

int cxscreen, cyscreen;

int CDECL MessageBoxPrintf(TCHAR *szCaption, TCHAR *szFormat, ...);

/*  Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;              /* This is the handle for our window */
    MSG messages;           /* Here messages to the application are saved */
    WNDCLASSEX wincl;       /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;     /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                /* No menu */
    wincl.cbClsExtra = 0;                     /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                     /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                  /* Extended possibilites for variation */
           szClassName,        /* Classname */
           "Windows App",      /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,      /* Windows decides the position */
           CW_USEDEFAULT,      /* where the window ends up on the screen */
           544,                /* The programs width */
           375,                /* and height in pixels */
           HWND_DESKTOP,       /* The window is a child-window to desktop */
           NULL,               /* No menu */
           hThisInstance,      /* Program Instance handler */
           NULL                /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   HDC        hdc;
   PAINTSTRUCT ps;
   RECT       rect;

    switch (message)                 /* handle the messages */
    {
        case WM_PAINT:
            /*
            cxscreen = GetSystemMetrics(SM_CXSCREEN);
            cyscreen = GetSystemMetrics(SM_CYSCREEN);
            MessageBoxPrintf(TEXT("Scrnsize"),
                             TEXT("The screen is %1 pixels wide by %2 pixels height!"),
                             cxscreen,cyscreen);
                             */
            //InValidateRect(hwnd, NULL, TRUE);
            RedrawWindow(hwnd, NULL, NULL, RDW_INTERNALPAINT);

            hdc = BeginPaint(hwnd, &ps);

            GetClientRect(hwnd, &rect);

            //RedrawWindow(hwnd,NULL,NULL,RDW_INTERNALPAINT);
            DrawText(hdc, TEXT("Hello Windows!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

            EndPaint(hwnd,&ps);

            break;

        case WM_DESTROY:
            PostQuitMessage (0);      /* send a WM_QUIT to the message queue */
            break;
        default:                     /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

int CDECL MessageBoxPrintf(TCHAR *szCaption, TCHAR *szFormat, ...)
{
    TCHAR szBuffer[1024];
    va_list pArgList;

    // The va_start macro, defined in stdarg.h is usually equivalent to:
    // pArgList = (char *) &szFormat + sizeof(szFormat)

    va_start(pArgList, szFormat);

    // the last argument to _vsnprintf points to the arguments
        _vsntprintf( szBuffer, sizeof(szBuffer)/sizeof(TCHAR),szFormat,pArgList);

    // the va_end macro just zeroes out pArglist for no good reason

    va_end(pArgList);

    return MessageBox(NULL, szBuffer, szCaption, 0);
}
Wenn ich nun das Fenster derart verkleinere, dass der Text "Hello Windows" nicht mehr zu sehen ist und anschließend das Fenster wieder auf seine ursprüngliche Ausdehnung vergrößere, wird der Text nicht neu gezeichnet, der Hintergrund bleibt leer. Ich will aber den Text neu zeichnen lassen. Wenn ich das Fenster in der Breite ändere, wird der Text auch nicht neu zentriert, obwohl ich in der DrawText Funktion die Flags DT_CENTER | DT_VCENTER gesetzt habe.

Wie erreiche ich das korrekte Neuzeichnen des Textes im Fenster bei Breiten und Größenänderung?

hoika 6. Jul 2020 21:42

AW: Warum wird Fensterinhalt nicht neu gezeichnet?
 
Hallo,
ein Masochist ;)

Du musst WM_RESIZE mit reinbringen in deine WindowProcedure.
Es müsste ein UpdateWindow(hwnd) schon reichen oder ein InvalidateRect,
um das WM_PAINT "aufzurufen" und damit das Neuzeichnen anzuwerfen.

https://docs.microsoft.com/en-us/win...r-updatewindow

https://docs.microsoft.com/en-us/win...he-client-area

TurboMagic 6. Jul 2020 21:47

AW: Warum wird Fensterinhalt nicht neu gezeichnet?
 
I glaube es liegt daran, dass du den Code in der Window Proc auskommentiert hast.
Wenn du was auf den Canvas einer Form zeichnest oder ähnliches, dann weiß Windows
nicht was du da mal gezeichnet hattest.

Wenn es verdeckt war und dann wieder aufgedeckt wurde, dann musst du es neu zeichnen.
Windows schickt daher eine wm_paint Nachricht an das Fenster, welches sich neu zeichnen
soll.

Das wird in dem Buch (besitze das auch) aber auch irgendwo erklärt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz