I do a wrapper for Window and want to call window methods from WndProc.
For this I pass 'this' pointer to CreateWindwEx function.
In WndProc I assign hWnd field of Window class and store it by SetWindowLongPtr
But when I try to read it by GetWindowLong I get broken instance of the window (all the fields have undefined values), however I can call w->foo()
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NCCREATE:
{
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
Window* self = static_cast<Window*>(lpcs->lpCreateParams);
// self->m_hInst and self->m_szWindowClass are set properly
// lets set hWnd
self->m_hWnd = hWnd;
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
return true;
}
case WM_COMMAND:
{
Window* w = reinterpret_cast<Window*>(GetWindowLong(hWnd, GWLP_USERDATA));
// got all the windows fields broken, though 'w' pointer itself is valid
w->foo();
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
Window* w = reinterpret_cast<Window*>(GetWindowLong(hWnd, GWLP_USERDATA));
w->foo();
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void foo()
{
//auto d = m_hInst;
auto s = m_hWnd;
}
My fault!
GetWindowLongPtr should be used instead of GetWindowLong
Related
I need to convert the standard cursor to my own when it is outside the working surface of the program screen. Initially, the cursor is standard on the screen, when I leave the window - my own, as it should be. I return it back - again the standard one. But when I go out the window again, it no longer changes to mine. That is, it works only once. Where is the mistake?
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
TRACKMOUSEEVENT tme;
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static BOOL bMouseInside;
switch (message)
{
case WM_CREATE:
{
RECT rt;
POINT pt = { 0, 0 };
GetClientRect(hWnd, &rt);
ClientToScreen(hWnd, &pt);
OffsetRect(&rt, pt.x, pt.y);
GetCursorPos(&pt);
bMouseInside = PtInRect(&rt, pt);
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER;
tme.hwndTrack = hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_MOUSEMOVE: {
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);
if (!bMouseInside)
{
SetSystemCursor(def_arrow_cur, 32512);
DestroyCursor(def_arrow_cur);
bMouseInside = TRUE;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
}
break;
case WM_MOUSELEAVE:
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);
if (bMouseInside)
{
SetSystemCursor(my_cur, 32512);
DestroyCursor(my_cur);
bMouseInside = FALSE;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The native and standard cursors are created like this:
HCURSOR def_arrow_cur = CopyCursor(LoadCursor(0, IDC_ARROW));
HCURSOR my_cur = LoadCursorFromFile(TEXT("my.cur"));
From documentation:
Remarks
The DestroyCursor function destroys a nonshared cursor. Do not use this function to destroy a shared cursor. A shared cursor is valid as
long as the module from which it was loaded remains in memory. The
following functions obtain a shared cursor:
LoadCursor
LoadCursorFromFile
LoadImage (if you use the LR_SHARED flag)
CopyImage (if you use the LR_COPYRETURNORG flag and the hImage parameter is a shared cursor)
And still you do that.
According to this website, any drawing operation performed on the HDC returned by BeginPaint will immediately display on the screen. However, the number printed by the following code only updates when the window is resized:
int counter = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
std::string s = std::to_string(counter).c_str();
TextOutA(hdc, 0, 0, s.c_str(), s.length());
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
counter++;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Even when continuously sending WM_PAINT to the window with
RedrawWindow(hwndMain, 0, 0, RDW_INTERNALPAINT);
after EndPaint, the number only updates when the window is resized. How can I get the number to update without manually resizing the window?
Calling RedrawWindow with different flags solved the problem.
Specifically RedrawWindow(hWnd, 0, 0, RDW_FRAME | RDW_INVALIDATE); after counter++;
I'm new to windows in c++ and i can't figure out how to display a image in my window?
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//Display an image here.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
I have a .png file on my desktop with the file path of Desktop\Dirt.png. i want to display this on my window at the location of 0,0. I don't know how to do this so any help will be nice. Also a function for this would be helpful.
Here is how I create my scrollbar:
CreateWindowEx(NULL, L"SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | scrollPos, x, y, width, height, parent, (HMENU)155, GetModuleHandle(NULL), NULL);
How could I restore my id (155) to know which control I will operate?
Here is how I tried:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
int id;
SCROLLBARINFO si;
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (message)
{
case WM_USER:
break;
case WM_USER + 1:
break;
case CONNECT_TO_SERVER:
break;
case WM_VSCROLL:
id = GetDlgCtrlID(hWnd);
//id isn't my 155 id, it is some kind of random number
//wmId isn't my 155 id
break;
case WM_COMMAND:
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I need to regain this id to choose which one of my controls should react inside my own grid.
id = GetDlgCtrlID(hWnd);
That's not correct, hWnd is the handle to your main window, not the scrollbar control. Also beware that WM_VSCROLL can be sent both by your main window and the scrollbar. The lParam argument tells you where it came from. Fix:
case WM_VSCROLL:
if (lParam != 0) {
int id = GetDlgCtrlID((HWND)lParam);
// etc..
}
break;
I want to disable keyboard when my program Run, means that no one can use alt+F4 etc. How I can make it possible using c in window OS.
Handle WM_SYSKEYUP , WM_SYSKEYDOWN and return 0
Here's the WndProc to handle these messages
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Pressing alt + f4 sends WM_CLOSE message.
You should properly handled this message.