I'm quite new to win32 programming, and I'm using the SetWindowLongPtr
in the code block of WM_CREATE
message processing, but it always returns zero. The program is rather simple, is there anything I was missing?
#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);
}
Build command:
gcc main.c -o test.exe -mwindows -lcomctl32
Things I've tried so far:
DWLP_USER
instead of GWLP_USERDATA
;SET_WINDOW_LONG_PTR
macro instead of SetWindowLongPtr
;It still returns zero.
Update:
Following the advice of @wohlstad, I use SetLastError(0)
and then GetLastError
to get the error, GetLastError
returns zero, seems that there's nothing wrong with the use of SetWindowLongPtr
, though some part of the official documentation seems a bit confusing:
If the function fails, the return value is zero
From the SetWindowLongPtr
documentation:
Return value
Type: LONG_PTR
If the function succeeds, the return value is the previous value of the specified offset.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
If the previous value is zero and the function succeeds, the return value is zero, but the function does not clear the last error information. To determine success or failure, clear the last error information by calling SetLastError with 0, then call SetWindowLongPtr. Function failure will be indicated by a return value of zero and a GetLastError result that is nonzero.
(emphasis is mine)
Therefore, a return value of 0
does not necessarily indicate an error. In order to perform proper error checking, you need to call SetLastError(0)
before calling SetWindowLongPtr()
, and then check whether GetLastError()
still returns 0
(no-error) afterwards.
SetLastError(0);
LONG_PTR result = SetWindowLongPtr(hWnd, GWLP_USERDATA, MYDATA);
if ((result == 0) && (GetLastError() != 0)) {
// error setting data
}