【问题标题】:Why SetWindowLongPtr always returns zero when processing WM_CREATE message?为什么 SetWindowLongPtr 在处理 WM_CREATE 消息时总是返回零?
【发布时间】:2023-02-24 06:37:57
【问题描述】:

我是 win32 编程的新手,我在 WM_CREATE 消息处理的代码块中使用 SetWindowLongPtr,但它总是返回零。该程序相当简单,有什么我遗漏的吗?

#include <stdio.h>
#include <windows.h>

#ifdef _WIN64
#define SET_WINDOW_LONG_PTR SetWindowLongPtr
#else
#define SET_WINDOW_LONG_PTR SetWindowLong
#endif

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int main(int argc, char *argv[]) {
  HINSTANCE hInstance = GetModuleHandle(NULL);

  WNDCLASS wc = {0};
  wc.lpfnWndProc = WndProc;
  wc.hInstance = hInstance;
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.lpszClassName = L"MyWindowClass";
  wc.cbClsExtra = sizeof(LONG_PTR);

  if (!RegisterClass(&wc)) {
    // Handle error...
  }

  HWND hWnd = CreateWindow(L"MyWindowClass", L"My Window", WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                           CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

  if (!hWnd) {
    // Handle error...
  }

  ShowWindow(hWnd, SW_SHOWNORMAL);

  MSG msg = {0};
  while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
                         LPARAM lParam) {
  switch (message) {
    case WM_CREATE:
      LONG_PTR MYDATA = (LONG_PTR)malloc(sizeof(int));
      int result = SetWindowLongPtr(hWnd, GWLP_USERDATA, MYDATA);
      // int result = SetWindowLongPtr (hWnd, DWLP_USER, MYDATA);   //this won't work either 
      // result is zero
      break;

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

构建命令:

gcc main.c -o test.exe -mwindows -lcomctl32

到目前为止我尝试过的事情:

  1. 使用DWLP_USER代替GWLP_USERDATA
  2. 使用特定于平台的SET_WINDOW_LONG_PTR宏而不是SetWindowLongPtr

    它仍然返回零。

    更新:按照@wohlstad的建议,我先用SetLastError(0)然后用GetLastError得到错误,GetLastError返回零,似乎使用SetWindowLongPtr没有错,虽然官方文档的某些部分似乎是有点混乱:

    如果函数失败,返回值为零

【问题讨论】:

    标签: c user-interface winapi win32gui


    【解决方案1】:

    来自SetWindowLongPtr documentation

    返回值

    类型:LONG_PTR

    如果函数成功,返回值为的先前值 指定的偏移量.

    如果函数失败,则返回值为零。得到扩展错误 信息,请调用 GetLastError。

    如果先前的值为零并且函数成功,则返回 值为零,但函数不清除最后一个错误 信息。决定成败,清除最后一个错误 通过使用 0 调用 SetLastError 获取信息,然后调用 设置窗口长指针.函数失败将由返回值指示 零和非零的 GetLastError 结果。

    (重点是我的)

    因此,0 的返回值不一定表示错误。为了执行正确的错误检查,您需要在调用SetWindowLongPtr()之前调用SetLastError(0),然后检查GetLastError()是否仍然返回0(无错误)。

    SetLastError(0);
    LONG_PTR result = SetWindowLongPtr(hWnd, GWLP_USERDATA, MYDATA);
    if ((result == 0) && (GetLastError() != 0)) {
        // error setting data
    }
    

    【讨论】:

    • “并检查GetLastError是否仍然在它之后返回0(无错误)。”- 这还不够。您还必须验证 SetWindowLongPtr 确实返回了 0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    相关资源
    最近更新 更多