WIN32 C正确使用SetWindowLongPtr和GetWindowLongPtr

时间:2015-09-17 02:50:17

标签: c winapi

是的,这是一项家庭作业,我完全难过了。

所以我制作了一个结构和两个窗口:

typedef struct thingy {
int count;
TCHAR* MSG;
COLORREF colour; };

窗户有:

wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = sizeof(thingy*);
wndclass.cbWndExtra = sizeof(thingy*);

我需要一个窗口显示0,然后使用SetWindowLongPtr和GetWindowLongPtr / SetClassLongPtr和GetClassLongPtr

使用存储在clsextra中的结构显示1

对于FIRST窗口,当然必须将Count初始化为0,但对于第二个窗口则不是,并且我不知道如何执行此操作。只能使用一个WndProc来执行此操作。

static thingy* mythingy = (thingy*)GetWindowLongPtr(hwnd, 0);
char buf[128];
int num = GetClassLongPtr(hwnd, 0);
static boolean set = false;

    case WM_CREATE:
    if (!set) {
        mythingy = (thingy*)malloc(sizeof(thingy));
        mythingy->count = 0;
        mythingy->colour = RGB(0, 0, 0);
        mythingy->MSG = TEXT("Hello Windows!");
        set = true;
    }
    if (lParam != NULL) {
        SetClassLongPtr(hwnd, 0, (LONG)mythingy->count);
    }
    mythingy->count++;
    SetWindowLongPtr(hwnd, 0, (LONG)mythingy);
    return 0;

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

    GetClientRect(hwnd, &rect);

    DrawText(hdc, mythingy->MSG, -1, &rect,
        DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    sprintf_s(buf, "%d", num);
    TextOut(hdc, 0, 0, LPCWSTR(buf), 1);

    EndPaint(hwnd, &ps);
    return 0;

现在两个窗口都显示1,我很难理解为什么它没有做我想要的,因为我无法在谷歌上找到关于如何使用这两个功能的内容或当我需要打电话给他们。

窗口:0x000a0528 count = 0 添加到班级数据

窗口:0x001f099a count = 1 添加到班级数据

从paint方法我得到的数据都是1。

1 个答案:

答案 0 :(得分:3)

A Window Class

  

...是系统用作创建窗口的模板的一组属性。每个窗口都是窗口类的成员。

由于Windows API作为平面C接口公开,因此语言级别没有继承。短语“是”的成员,是通过在该类的窗口实例之间共享类内存来实现的。因此,每次调用GetClassLongPtr都会访问相同的共享内存。

相反,每个窗口都可以保留 cbWndExtra 字节的内存,这些字节归因于特定的窗口实例。该内存对每个窗口都是专用的,可以存储每个窗口的数据。

要实现您的要求,您需要在窗口类的额外内存( cbClsExtra )中存储公共信息(当前窗口数),并保留每窗口数据(索引,消息,窗口实例的额外内存( cbWndExtra )。

对您的代码应用以下更改:

// Total count of windows stored as an integer:
wndclass.cbClsExtra = sizeof(int);

WM_CREATE - 处理程序中,设置每个窗口的数据,增加总计数并将其存储起来:

case WM_CREATE:
{
    int count = (int)GetClassLongPtr(hwnd, 0);
    // Allocate new per-window data object:
    thingy* mythingy = (thingy*)malloc(sizeof(thingy));
    mythingy->count = count;
    mythingy->colour = RGB(0, 0, 0);
    mythingy->MSG = TEXT("Hello Windows!");
    // Store the per-window data:
    SetWindowLongPtr(hwnd, 0, (LONG_PTR)mythingy);
    // Increment total count and store it in the class extra memory:
    ++count;
    SetClassLongPtr(hwnd, 0, (LONG_PTR)count);
}
return DefWindowProc(hwnd, msg, wParam, lParam);

WM_PAINT - 处理程序中,访问每个窗口的数据:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    hdc = BeginPaint(hwnd, &ps);
    RECT rect;
    GetClientRect(hwnd, &rect);
    // Retrieve per-window data:
    thingy* mythingy = (thingy*)GetWindowLongPtr(hwnd, 0);

    DrawText(hdc, mythingy->MSG, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    char buf[128];
    sprintf_s(buf, "%d", mythingy->count);
    TextOutA(hdc, 0, 0, buf, 1);

    EndPaint(hwnd, &ps);
    return 0;
}

注意:为简洁起见,省略了所有错误处理。字符编码问题也未得到解决(charwchar_t)。同样,缺少资源管理。您可能想要在WM_NCDESTROY - 处理程序中释放内存。代码假定,只创建单个窗口类的窗口。