In WinMain, I place a pointer to the structure in the window's pocket (setwindowlong), and in it I get this pointer. And I cannot understand why it is impossible to fill in arrays of this structure through a pointer — the program crashes - 121-122 lines.

#include <windows.h> #include <time.h> #define Ellipsee 1 #define Rectanglee 2 #define SIZEX 4000 #define SIZEY 4000 #define RADIUS 25 #define COUNT 1000 LRESULT CALLBACK windowprocessforwindow(HWND handleforwindow, UINT message, WPARAM wParam, LPARAM lParam); struct FigurePP { int flag; int X[COUNT]; int Y[COUNT]; }; void czCreateMenu(HWND handleforwindow1) { HMENU MainMenu = CreateMenu(); HMENU hPopupMenu = CreatePopupMenu(); AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu, "&Фигура"); { AppendMenu(hPopupMenu, MF_STRING, Ellipsee, "Круг"); AppendMenu(hPopupMenu, MF_SEPARATOR, 1000, ""); AppendMenu(hPopupMenu, MF_STRING, Rectanglee, "Прямоугольник"); SetMenu(handleforwindow1, MainMenu); CheckMenuItem(hPopupMenu, Ellipsee, MF_CHECKED); EnableMenuItem(hPopupMenu, Ellipsee, MF_DISABLED | MF_GRAYED | MF_CHECKED); } } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd) { WNDCLASSEX windowclassforwindow1 = { 0 }; windowclassforwindow1.cbSize = sizeof(WNDCLASSEX); windowclassforwindow1.hbrBackground = (HBRUSH)COLOR_WINDOW; windowclassforwindow1.hInstance = hInst; windowclassforwindow1.hCursor = LoadCursor(NULL, IDC_ARROW); windowclassforwindow1.lpfnWndProc = (WNDPROC)windowprocessforwindow; windowclassforwindow1.lpszClassName = "windowclass 1"; windowclassforwindow1.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClassEx(&windowclassforwindow1)) { MessageBox(NULL, "Window class creation failed", "Window Class Failed", MB_ICONERROR); } HWND handleforwindow = CreateWindowEx(NULL, windowclassforwindow1.lpszClassName, "Parent Window", WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, 350, 250, 640, 480, NULL, NULL, hInst, NULL ); if (!handleforwindow) { MessageBox(NULL, "Window creation failed", "Window Creation Failed", MB_ICONERROR); } FigurePP figure; figure.flag = Ellipsee; SetWindowLong(handleforwindow, GWL_USERDATA, (LONG_PTR)&figure); ShowWindow(handleforwindow, nShowCmd); czCreateMenu(handleforwindow); MSG msg = { 0 }; while (GetMessage(&msg, NULL, 0, 0) != 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK windowprocessforwindow(HWND handleforwindow, UINT uMsg, WPARAM wParam, LPARAM lParam) { //static int X[COUNT]; //static int Y[COUNT]; FigurePP* p = (FigurePP*)GetWindowLong(handleforwindow, GWL_USERDATA); switch (uMsg) { case WM_CREATE: { srand((unsigned)time(NULL)); for (int i = 0; i < COUNT; i++) { p->X[i] = (int)(100 * rand() % SIZEX); p->Y[i] = (int)(100 * rand() % SIZEY); } return 0; } case WM_SIZE: { static RECT rect = { 0L }; GetClientRect(handleforwindow, &rect); SCROLLINFO sinfoo1; sinfoo1.cbSize = sizeof(SCROLLINFO); sinfoo1.fMask = SIF_RANGE | SIF_PAGE; sinfoo1.nMin = 0; sinfoo1.nMax = SIZEX - rect.right; sinfoo1.nPage = HIWORD(lParam); SetScrollInfo(handleforwindow, SB_HORZ, &sinfoo1, TRUE); SCROLLINFO sinfoo2; sinfoo2.cbSize = sizeof(SCROLLINFO); sinfoo2.fMask = SIF_RANGE | SIF_PAGE; sinfoo2.nMin = 0; sinfoo2.nMax = SIZEY - rect.bottom; sinfoo2.nPage = HIWORD(lParam); SetScrollInfo(handleforwindow, SB_VERT, &sinfoo2, TRUE); InvalidateRect(handleforwindow, NULL, true); break; } case WM_PAINT: { int i; SCROLLINFO hscroll = { 0 }, vscroll = { 0 }; hscroll.cbSize = sizeof(SCROLLINFO); hscroll.fMask = SIF_POS; GetScrollInfo(handleforwindow, SB_HORZ, &hscroll); vscroll.cbSize = sizeof(SCROLLINFO); vscroll.fMask = SIF_POS; GetScrollInfo(handleforwindow, SB_VERT, &vscroll); RECT scRect, Rect; PAINTSTRUCT Paint; GetClientRect(handleforwindow, &Rect); HDC hdc = BeginPaint(handleforwindow, &Paint); HBRUSH NewBrush1 = CreateSolidBrush(RGB(255, 255, 0)); HBRUSH NewBrush2 = CreateSolidBrush(RGB(0, 255, 255)); HGDIOBJ OldBrush = SelectObject(hdc, NewBrush1); switch (p->flag) { case (Ellipsee): { for (i = 0; i < COUNT; i++) { scRect.right = p->X[i] + RADIUS; scRect.left = p->X[i] - RADIUS; scRect.top = p->Y[i] - RADIUS; scRect.bottom = p->Y[i] + RADIUS; SelectObject(hdc, OldBrush); if (i % 2 == 0) { SelectObject(hdc, NewBrush1); } else { SelectObject(hdc, NewBrush2); } if ((p->X[i] < Paint.rcPaint.right + 25 + hscroll.nPos && p->Y[i] > vscroll.nPos - 25) && (p->X[i] > hscroll.nPos - 25 && p->Y[i] < Paint.rcPaint.bottom + vscroll.nPos + 25)) { Ellipse(hdc, p->X[i] - RADIUS - hscroll.nPos, p->Y[i] - RADIUS - vscroll.nPos, p->X[i] + RADIUS - hscroll.nPos, p->Y[i] + RADIUS - vscroll.nPos); } } break; } case (Rectanglee): { for (i = 0; i < COUNT; i++) { scRect.right = p->X[i] + RADIUS; scRect.left = p->X[i] - RADIUS; scRect.top = p->Y[i] - RADIUS; scRect.bottom = p->Y[i] + RADIUS; SelectObject(hdc, OldBrush); if (i % 2 == 0) { SelectObject(hdc, NewBrush1); } else { SelectObject(hdc, NewBrush2); } if ((p->X[i] < Paint.rcPaint.right + 25 + hscroll.nPos && p->Y[i] > vscroll.nPos - 25) && (p->X[i] > hscroll.nPos - 25 && p->Y[i] < Paint.rcPaint.bottom + vscroll.nPos + 25)) { Rectangle(hdc, p->X[i] - RADIUS - hscroll.nPos, p->Y[i] - RADIUS - vscroll.nPos, p->X[i] + RADIUS - hscroll.nPos, p->Y[i] + RADIUS - vscroll.nPos); } } break; } } SelectObject(hdc, OldBrush); DeleteObject(NewBrush1); DeleteObject(NewBrush2); EndPaint(handleforwindow, &Paint); return 0; } case WM_HSCROLL: { SCROLLINFO hscr; hscr.cbSize = sizeof(SCROLLINFO); hscr.fMask = SIF_ALL; GetScrollInfo(handleforwindow, SB_HORZ, &hscr); int min = hscr.nMin; int max = hscr.nMax; int ncurPos = hscr.nPos; int fpos = ncurPos; RECT rect; GetClientRect(handleforwindow, &rect); switch (LOWORD(wParam)) { case SB_THUMBTRACK: { ncurPos = HIWORD(wParam); break; } case SB_LINERIGHT: { if (ncurPos < max - 200) ncurPos += 200; break; } case SB_PAGERIGHT: { if (ncurPos < max - 200) { ncurPos += 200; } else ncurPos = max; break; } case SB_LINELEFT: { if (ncurPos >(min + 200)) { ncurPos -= 200; } else { ncurPos = min; } break; } case SB_PAGELEFT: { if (ncurPos > min + 200) { ncurPos -= 200; } else ncurPos = min; break; } } if (fpos != ncurPos) { SetScrollPos(handleforwindow, SB_HORZ, ncurPos, TRUE); ScrollWindow(handleforwindow, (fpos - ncurPos), 0, NULL, NULL); if (fpos - ncurPos < 0) { rect.left = rect.right + (fpos - ncurPos); InvalidateRect(handleforwindow, &rect, FALSE); } else { rect.right = rect.left + (fpos - ncurPos); InvalidateRect(handleforwindow, &rect, FALSE); } } break; } case WM_VSCROLL: { SCROLLINFO vscr; vscr.cbSize = sizeof(SCROLLINFO); vscr.fMask = SIF_ALL; GetScrollInfo(handleforwindow, SB_VERT, &vscr); int min = vscr.nMin; int max = vscr.nMax; int ncurPos = vscr.nPos; int fpos = ncurPos; RECT rect; GetClientRect(handleforwindow, &rect); switch (LOWORD(wParam)) { case SB_THUMBTRACK: { ncurPos = vscr.nTrackPos; break; } case SB_LINEUP: { if (ncurPos > min + 200) ncurPos -= 200; else ncurPos = min; break; } case SB_LINEDOWN: { if (ncurPos < max - 200) { ncurPos += 200; } else { ncurPos = max; } break; } case SB_PAGEUP: { if (ncurPos > min) { ncurPos -= 400; } else ncurPos = min; } case SB_PAGEDOWN: { if (ncurPos < (max - 200)) { ncurPos += 200; } else { ncurPos = max; } } } if (fpos != ncurPos) { SetScrollPos(handleforwindow, SB_VERT, ncurPos, TRUE); ScrollWindow(handleforwindow, 0, (fpos - ncurPos), NULL, NULL); if (fpos - ncurPos < 0) { rect.bottom = rect.top - (fpos - ncurPos); InvalidateRect(handleforwindow, &rect, true); } else { rect.top = rect.bottom - (fpos - ncurPos); InvalidateRect(handleforwindow, &rect, true); } } break; } case WM_DESTROY: { PostQuitMessage(0); return 0; } case WM_COMMAND: { HMENU hMenuBar = GetMenu(handleforwindow); switch (LOWORD(wParam)) { case Ellipsee: { CheckMenuItem(GetSubMenu(hMenuBar, 0), Ellipsee, MF_CHECKED); EnableMenuItem(GetSubMenu(hMenuBar, 0), Ellipsee, MF_CHECKED | MF_DISABLED | MF_GRAYED); CheckMenuItem(GetSubMenu(hMenuBar, 0), Rectanglee, MF_UNCHECKED); EnableMenuItem(GetSubMenu(hMenuBar, 0), Rectanglee, MF_CHECKED); p->flag = Ellipsee; InvalidateRect(handleforwindow, NULL, true); break; } case Rectanglee: { CheckMenuItem(GetSubMenu(hMenuBar, 0), Ellipsee, MF_UNCHECKED); EnableMenuItem(GetSubMenu(hMenuBar, 0), Ellipsee, MF_CHECKED); CheckMenuItem(GetSubMenu(hMenuBar, 0), Rectanglee, MF_CHECKED); EnableMenuItem(GetSubMenu(hMenuBar, 0), Rectanglee, MF_CHECKED | MF_DISABLED | MF_GRAYED); p->flag = Rectanglee; InvalidateRect(handleforwindow, NULL, true); break; } } } } return DefWindowProc(handleforwindow, uMsg, wParam, lParam); } 
  • WM_CREATE does not fill arrays through a pointer. - Alexander
  • I would venture to suggest that WM_CREATE is processed BEFORE a call to SetWindowLong - Vladimir Martyanov
  • Well, logically, as I thought, after the function CreateWindow in the pocket is already a pointer, and in WM_CREATE it is already possible to fill arrays. - Alexander
  • By what logic should the code written below be executed before the code written above? - Vladimir Martyanov
  • so in the function callback we get this pointer - FigurePP * p and then wm_create goes like - Alexander

1 answer 1

You should use the SetWindowLongPtr and GetWindowLongPtr . When using SetWindowLong and GetWindowLong pointer may be clipped, respectively, its denaming leads to undefined behavior. In addition, after getting the pointer from GetWindowLongPtr it should be checked for equality to zero before it is renamed.

Since the WM_CREATE sent before CreateWindowEx returned, SetWindowLongPtr was not called at that moment, and the GetWindowLongPtr call returns 0. However, LPARAM will contain the value passed as the last parameter to CreateWindowEx . Accordingly, in order for everything to work, you need to pass the necessary pointer to CreateWindowEx , and in the WM_CREATE handler, get it from LPARAM and save it with SetWindowLongPtr for subsequent calls:

 FigurePP figure; figure.flag = Ellipsee; HWND handleforwindow = CreateWindowEx(NULL, windowclassforwindow1.lpszClassName, "Parent Window", WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, 350, 250, 640, 480, NULL, NULL, hInst, reinterpret_cast<LPARAM>(&figure) ); 

...

 LRESULT CALLBACK windowprocessforwindow(HWND handleforwindow, UINT uMsg, WPARAM wParam, LPARAM lParam) { FigurePP * p = reinterpret_cast<FigurePP *> ( GetWindowLongPtr(handleforwindow, GWL_USERDATA) ); assert((nullptr != p) || (WM_CREATE == uMsg)); switch(uMsg) { case WM_CREATE: { p = reinterpret_cast<FigurePP *>(lParam); assert(nullptr != p) SetWindowLongPtr(handleforwindow, GWL_USERDATA, reinterpret_cast<LONG_PTR>(p)); 
  • I tried - the same thing happens. - Alexander
  • @Alexander Also what, at the first call windowprocessforwindow GetWindowLong returns not zero value? - VTT
  • Well, I podebazhil, the index comes the value 0x00000000 <NULL> - Alexander
  • @Alexander Updated the answer. - VTT