窗口消息处理函数以某种方式改变了应保持不变的 int 变量的值

问题描述 投票:0回答:1

在我的 Window_manager.c 文件中,我无处手动编辑

*wm->actStkSize
的值(!?),但是在
DispatchMessage(&msg);
函数中调用
RunMessageLoop
后,值以某种方式从 0 更改为 66,我完全不知道怎么办。

main.c

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WindowManager wm;
    InitWindowManager(&wm);
    printf("from main: %d %d\n", *wm.actBfrSize, *wm.actStkSize);

    if (CreateAndShowWindow(&wm, hInstance, nCmdShow) != 0)
    {
        MessageBox(NULL, L"Failed to create window.", L"Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    int result = RunMessageLoop(&wm);
    CleanupWindowManager(&wm);

    return result;
}

Window_manager.c

#include "window_manager.h"
#include <stdio.h>
#include <windows.h>
#include <windowsx.h>
#include "config.h"
#include "graphics.h"

void InitWindowManager(WindowManager *wm) {
    wm->hwnd = NULL;
    wm->logFile = NULL;

    Document doc;
    Page pg;
    RawPoint** stack = (RawPoint**)malloc(sizeof(RawPoint*));
    RawPoint* buffer = (RawPoint*)malloc(SIZE_OF_BUFFER * sizeof(RawPoint));
    *stack = buffer;

    pg.rawStk = stack;
    pg.rawBfrSize = 0;
    pg.rawStkSize = 0;
    doc.page = &pg;
    wm->document = &doc;
    wm->actBuffer = buffer;
    wm->actPt = buffer;
    wm->actBfrSize = &pg.rawBfrSize;
    wm->actStkSize = &pg.rawStkSize;

    // Initialize penData attributes
    wm->penData.position.x = 0;
    wm->penData.position.y = 0;
    wm->penData.pressure = 0.0f;
    wm->penData.azimuth = 0.0f;
    wm->penData.altitude = 0.0f;
    wm->penData.tiltX = 0.0f;
    wm->penData.tiltY = 0.0f;
    wm->penData.twist = 0.0f;
    wm->penData.touching = FALSE;
    wm->penData.buttonPressed = FALSE;

    wcscpy_s(wm->displayText, MAX_TEXT_LENGTH, L"Pointer Events: None");
    wcscpy_s(wm->logFileName, MAX_TEXT_LENGTH, L"logs/pen_pressure_log.txt");
    // Open the log file for writing
    _wfopen_s(&wm->logFile, wm->logFileName, L"w");
}

int CreateAndShowWindow(WindowManager *wm, HINSTANCE hInstance, int nCmdShow) {
    
    // Register window class
    // Register window class
    WNDCLASSW wc = {}; // Note the use of WNDCLASSW for wide strings
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = L"MyWindowClass"; // Use wide-character string

    if (RegisterClassW(&wc) == 0) {
        // Handle registration failure
        return 1;
    }
    // Create window
    wm->hwnd = CreateWindowExW(0, L"MyWindowClass", L"My Window Title",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        500, 300, NULL, NULL, hInstance, wm);
    HWND hButton = CreateWindowExW(0, L"BUTTON", L"redraw",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        10, 50, 100, 30,
        wm->hwnd, (HMENU)1001, GetModuleHandle(NULL), NULL);
    if (wm->hwnd == NULL) {
        return 1;
    }
    ShowWindow(wm->hwnd, nCmdShow);
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    WindowManager *wm;
    if (uMsg == WM_NCCREATE) {
        // Retrieve the pointer to the WindowManager from the CREATESTRUCT
        CREATESTRUCT *pCreate = (CREATESTRUCT *)lParam;
        wm = (WindowManager *)pCreate->lpCreateParams;
        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wm);
        wm->hwnd = hwnd;
        printf("from ProcIf: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));

        // printf("%s",wm->displayText);
        // printf("if");
    } else {
        wm = (WindowManager *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        // printf("from ProcElse: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    }
    // printf("from Proc: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    // printf("WindowPrc: %i\n", *wm->actStkSize);
    switch (uMsg) {
        case WM_CLOSE: {
            printf("from WM_CLOSE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            DestroyWindow(hwnd);
            break;
        }
        case WM_DESTROY: {
            printf("from WM_DESTROY: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            PostQuitMessage(0);
            break;
        }
        case WM_POINTERDOWN: {
            printf("from WM_POINTERDOWN: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            wm->penData.touching = TRUE; // Pen is down
            break;
        }
        case WM_POINTERUP: {
            printf("from WM_POINTERDOWN: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            wm->penData.touching = FALSE;
            break;
        }
        case WM_POINTERUPDATE: {
            printf("from WM_POINTERUPDATE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            // Handle pointer events
            wm->penData.position.x = GET_X_LPARAM(lParam);
            wm->penData.position.y = GET_Y_LPARAM(lParam);
            ScreenToClient(wm->hwnd, &wm->penData.position);
            wm->actPt->coords.x = wm->penData.position.x;
            wm->actPt->coords.y = wm->penData.position.y;
            wm->actPt->touching = wm->penData.touching;
            wm->actPt->pressure = GET_POINTERID_WPARAM(wParam) / 5551.0f;
            UpdateDisplay(wm);
            InvalidateRect(hwnd, NULL, TRUE); // Request a redraw of the window
            
            (*wm->actBfrSize)++;
            if (*wm->actBfrSize == SIZE_OF_BUFFER) {
                printf("Stoooooooooop!!!");
            }
            else {
                // printf("actStkSize: %i\n", *(wm->actStkSize));
                wm->actPt++;
            }
            break;
        }
        case WM_SIZE: {
            printf("from WM_SIZE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            Do Some Stuff
            break;}
        case WM_PAINT: {
            printf("from WM_PAINT: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            // Do some Stuff
            break;}
        case WM_COMMAND: {
            printf("from WM_COMMAND: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            //Do some Stuff
        }
        default: {
            // printf("from default: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
    }
    return 0;
}

int RunMessageLoop(WindowManager *wm) {
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        printf("from beginLoop: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
        TranslateMessage(&msg);
        printf("from midLoop:   %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
        DispatchMessage(&msg);
        printf("from endLoop:   %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    }
    return (int)msg.wParam;
}

void CleanupWindowManager(WindowManager *wm) {
    // Close the log file if it's open
    if (wm->logFile != NULL) {
        fclose(wm->logFile);
    }
}

这是输出:

from main: 0 0
from ProcIf: 0 0
from WM_SIZE: 0 0
from beginLoop: 0 0
from midLoop:   0 0
from endLoop:   0 66
from beginLoop: 0 66
from midLoop:   0 66
from endLoop:   0 66

调用

wm->hwnd
时传递
GetMessageW
不会改变任何内容。

c windows window message-handlers
1个回答
0
投票

doc
pg
的局部变量在函数返回后通过指针访问。到那时变量的生命周期已经到期,导致
未定义的行为
要解决此问题,可以将

InitWindowManager

wm->document
指向动态分配的内存,如下所示:
wm->document->page

© www.soinside.com 2019 - 2024. All rights reserved.