You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32程序窗口句柄未正确存储问题:原因何在?

问题分析与解决

你的代码核心问题是对象副本与原始对象的分离:

  • 在UiObjects构造函数中,你将Canvas和Output成员的副本存入了Objects向量,而非引用或指针。
  • 在WM_CREATE消息处理中,你遍历向量创建窗口后,仅更新了向量内副本的hObjectWnd字段,但MyObjects.Output这个独立成员的hObjectWnd始终是初始的NULL。
  • 因此点击Canvas时,IsWindow(MyObjects.Output.hObjectWnd)检测的是未初始化的NULL,自然返回false。

解决方法一:用向量统一管理UI对象(推荐)

去掉单独的Canvas和Output成员,直接通过向量存储所有UI对象,通过标识或索引访问:

  1. 修改UiObjects定义,给Object添加标识字段:
static class UiObjects
{
public:
    enum ObjectClass { Custom };

    struct Object {
        LPWSTR lpClassName;
        LPWSTR lpWindowName;
        DWORD dwStyle;
        LONG x;
        LONG y;
        LONG nWidth;
        LONG nHeigth;
        HMENU hMenu;
        HWND hObjectWnd;
        ObjectClass objectType;
        COLORREF color;
        enum ObjectId { CanvasId, OutputId } id; // 添加标识字段
    };

    std::vector<Object> Objects;

    UiObjects();
} MyObjects;
  1. 更新构造函数,直接向向量添加对象:
UiObjects::UiObjects() {
    Objects.push_back({
        L"myVirtualSandbox Canvas Class",
        L"Canvas",
        WS_VISIBLE | WS_CHILD | WS_BORDER,
        CANVAS_HOR_OFFSET,
        CANVAS_VER_OFFSET,
        CANVAS_WIDTH,
        CANVAS_HEIGTH,
        NULL,
        NULL,
        ObjectClass::Custom,
        0,
        Object::CanvasId
    });

    Objects.push_back({
        L"EDIT",
        L"Output",
        WS_VISIBLE | WS_CHILD | WS_BORDER,
        CANVAS_HOR_OFFSET,
        CANVAS_VER_OFFSET + CANVAS_HEIGTH + OUTPUT_VER_OFFSET,
        CANVAS_WIDTH,
        OUTPUT_HEIGTH,
        NULL,
        NULL,
        ObjectClass::Custom,
        0,
        Object::OutputId
    });
}
  1. 在canvasWndProc中通过标识查找Output窗口:
case WM_LBUTTONDOWN:
{
    POINT point = { };
    point.x = GET_X_LPARAM(lParam);
    point.y = GET_Y_LPARAM(lParam);

    System::Diagnostics::Debug::WriteLine("Clicked in Canvas.");

    HWND hOutputWnd = NULL;
    for (auto& obj : MyObjects.Objects) {
        if (obj.id == UiObjects::Object::OutputId) {
            hOutputWnd = obj.hObjectWnd;
            break;
        }
    }

    if (IsWindow(hOutputWnd))
    {
        SendMessage(hOutputWnd, WM_SETTEXT, NULL, (LPARAM)L"Test.");
    }
    else {
        System::Diagnostics::Debug::WriteLine("Is not..");
    }
    break;
}

解决方法二:让向量存储对象指针

保持Canvas和Output成员,修改向量为存储指针,确保修改的是原始对象:

  1. 修改UiObjects的向量类型:
static class UiObjects
{
public:
    enum ObjectClass { Custom };

    struct Object {
        LPWSTR lpClassName;
        LPWSTR lpWindowName;
        DWORD dwStyle;
        LONG x;
        LONG y;
        LONG nWidth;
        LONG nHeigth;
        HMENU hMenu;
        HWND hObjectWnd;
        ObjectClass objectType;
        COLORREF color;
    };

    Object Canvas, Output;
    std::vector<Object*> Objects; // 修改为指针向量

    UiObjects();
} MyObjects;
  1. 更新构造函数,存入原始对象的指针:
UiObjects::UiObjects() {
    Canvas = {
        L"myVirtualSandbox Canvas Class",
        L"Canvas",
        WS_VISIBLE | WS_CHILD | WS_BORDER,
        CANVAS_HOR_OFFSET,
        CANVAS_VER_OFFSET,
        CANVAS_WIDTH,
        CANVAS_HEIGTH,
        NULL,
        NULL,
        ObjectClass::Custom,
        0
    };
    Objects.push_back(&Canvas); // 存储原始对象指针

    Output = {
        L"EDIT",
        L"Output",
        WS_VISIBLE | WS_CHILD | WS_BORDER,
        CANVAS_HOR_OFFSET,
        CANVAS_VER_OFFSET + CANVAS_HEIGTH + OUTPUT_VER_OFFSET,
        CANVAS_WIDTH,
        OUTPUT_HEIGTH,
        NULL,
        NULL,
        ObjectClass::Custom,
        0
    };
    Objects.push_back(&Output); // 存储原始对象指针
}
  1. 修改WM_CREATE中的循环逻辑:
for (int i = 0; i < MyObjects.Objects.size(); i++) {
    UiObjects::Object* obj = MyObjects.Objects[i]; // 通过指针访问对象

    HWND hObjectWnd = CreateWindow(
        obj->lpClassName,
        obj->lpWindowName,
        obj->dwStyle,
        obj->x,
        obj->y,
        obj->nWidth,
        obj->nHeigth,
        hWnd,
        obj->hMenu,
        hInstance,
        NULL
    );

    obj->hObjectWnd = hObjectWnd; // 修改原始对象的窗口句柄
}

此方法下你原来的canvasWndProc代码无需修改,MyObjects.Output.hObjectWnd会被正确赋值,IsWindow检测即可通过。

内容的提问来源于stack exchange,提问作者thielo06

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:09:50