WIN32 C Properly using SetWindowLongPtr and GetWindowLongPtr
Sophia Terry
Yes this is a homework assignment and I'm completely stumped.
So I've made a struct and two windows:
typedef struct thingy {
int count;
TCHAR* MSG;
COLORREF colour; };The windows have:
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = sizeof(thingy*);
wndclass.cbWndExtra = sizeof(thingy*);I need one window to display 0 and the next to display 1 using this struct stored in the clsextra using SetWindowLongPtr and GetWindowLongPtr/SetClassLongPtr and GetClassLongPtr
Count of course has to be initialized to 0 for the FIRST window but not for the second and I have no idea how to do this. Only one WndProc can be used to do this.
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;Right now both windows display 1 and I'm struggling to see why it isn't doing what I want as I can't find anything on Google about how to use these two functions or when I need to be calling them.
Window: 0x000a0528 count = 0 Add to class data
Window: 0x001f099a count = 1 Add to class data
From the paint method I get the data and both of them are 1.
41 Answer
... is a set of attributes that the system uses as a template to create a window. Every window is a member of a window class.
Since the Windows API is exposed as a flat C interface, there is no inheritance at the language level. The phrase "is a member of" is implemented by sharing the class memory across window instances of that class. Consequently, every call to GetClassLongPtr accesses the same shared memory.
In contrast, each window can reserve cbWndExtra bytes of memory, that are attributed to the specific window instance. This memory is private to each window, and can store per-window data.
To implement your requirements you need to store the common information (current count of windows) in the window class' extra memory (cbClsExtra), and keep the per-window data (index, message, and color) in the window instance's extra memory (cbWndExtra).
Apply the following changes to your code:
// Total count of windows stored as an integer:
wndclass.cbClsExtra = sizeof(int);In the WM_CREATE-handler, set the per-window data, increment the total count, and store it away:
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);In the WM_PAINT-handler, access the per-window data:
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;
}Note: All error handling has been elided for brevity. Character-encoding issues have not really been addressed either (char vs. wchar_t). Likewise, resource management is missing. You'd probably want to deallocate memory in a WM_NCDESTROY-handler. The code assumes, that only windows of a single window class are created.