C++ - Change vertical pitch of your mouse - c++

The Idea
I was wondering if it's possible to change the pitch of your mouse over the entire screen. To give an example: If you draw a perfect circle with your physical mouse on your table, your screen would draw an oval (with: width > height).
This could be useful if you e.g. used to have a customizable mouse that supported individual m_pitch settings but recently broke down and you can't afford a new one. You could use this program to virtualize those individual settings.
So I went to work and concocted this small program:
#include <windows.h>
#include <iostream>
#include <math.h>
using namespace std;
HHOOK hMouseHook;
bool prev_initialized = false;
bool real_input = true;
MOUSEHOOKSTRUCT prevMouseStruct;
double ratio = 0.5; //cursor should pitch 0.5x as fast as it normally would
double rest = 0;
LRESULT CALLBACK mouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{
MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
if (pMouseStruct != NULL){
if(wParam == WM_MOUSEMOVE)
{
printf("Mouse position X = %d Mouse Position Y = %d\n", pMouseStruct->pt.x,pMouseStruct->pt.y);
if(prev_initialized && real_input){
int y_diff = prevMouseStruct.pt.y - pMouseStruct->pt.y;
if(y_diff != 0){
double ratiod_diff = ((double)y_diff) * ratio;
int rounded_diff = (int)round(ratiod_diff);
int newY = prevMouseStruct.pt.y - rounded_diff;
rest += ratiod_diff - rounded_diff;
if(rest > 1){
--rest;
++newY;
}else if(rest < -1){
++rest;
--newY;
}
real_input = false;
pMouseStruct->pt.y = newY;
SetCursorPos(pMouseStruct->pt.x, pMouseStruct->pt.y);
printf("New- Mouse position X = %d Mouse Position Y = %d\n", pMouseStruct->pt.x,newY);
}
}else if(!real_input){
real_input = true;
} else{
prevMouseStruct = *pMouseStruct;
prev_initialized = true;
}
}
}
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
int main()
{
HINSTANCE hInstance = GetModuleHandle(NULL);
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, hInstance, NULL);
MSG message;
while (GetMessage(&message,NULL,0,0)) {
TranslateMessage( &message );
DispatchMessage( &message );
}
UnhookWindowsHookEx(hMouseHook);
return 0;
}
How?
This program registers all mousemovement-events on the screen and remembers 2 coordinates:
The previous mouse location; e.g.: POINT(100, 100)
The current mouse location; e.g.: POINT(120,150) -> the mouse moved 20px to the right and 50px down
Then, I calculate where I want the cursor to be with the ratio (and some other fancy precision stuff). E.g.: the cursor moves 50px down and the ratio is 0.5 -> the mouse only goes 25px down.
Lastly, I call SetMousePos() with the new y-value to move the cursor to my desired location. (Note: I also try to make sure that this function does not call mouseProc() again by using the boolean real_input as a flag).
The problem
I am running into the following problem: the cursor is not staying at its new y-position. After calling the setMousePos()-function, the mouse shifts to its new position for a split second and then instantly reverts back to its former position. This leaves a makeshift 'afterimage' of the mouse. In this GIF, I move the cursor from the top to the bottom. You can see that it leaves it's after-image that grows larger in distance when you move further away from your starting-position (the starting-position is the position of your mouse when the console opens).
Any feedback would be MUCH appreciated!

Related

Windows API: Guess the next caret position

I'm currently writing a function to get the current line/column of an EDIT control, and I'm stuck on a problem:
If I use WM_KEYUP to handle the caret position, the coordinates are valid but it can't be updated every "frame" since it waits for the user to release the pressed key
If I use WM_KEYDOWN, GetCaretPos returns the "previous" position of the caret (well, it's an obvious issue since it hasn't moved yet.)
Is there anything I can do to guess the next position of a caret? is it efficient if I just use EM_GETSEL?
LRESULT Edit::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
{
// Get character position from the mouse cursor's position (currently, there's no conversion of the coordinates if the mouse cursor is out of bound)
POINT pntMousePos{ 0 };
pntMousePos.x = GET_X_LPARAM(lParam);
pntMousePos.y = GET_Y_LPARAM(lParam);
LRESULT notifyValue = this->Notify(EM_CHARFROMPOS, 0, MAKELPARAM(pntMousePos.x, pntMousePos.y));
int lineIdx = static_cast<int>(this->Notify<int, LPARAM>(EM_LINEINDEX, -1));
if (lineIdx == NULL) {
DWORD beg, end;
lineIdx = Notify(EM_GETSEL, &beg, &end);
}
m_caretPos.line = HIWORD(notifyValue) + 1;
m_caretPos.column = (LOWORD(notifyValue) - lineIdx) + 1;
// Send a custom message to the main window
SendMessage(GetParent(m_parent) /*The EDIT control is actually a child of a tab control that is itself a child of the main window, ignore this */, CEM_GETLINEINFO, MAKEWPARAM(m_caretPos.line, m_caretPos.column), 0);
}
break;
case WM_KEYDOWN:
{
// Get Character position from the carret's position
// Get text metric (doesn't work so I removed some lines)
TEXTMETRIC tm{0};
HDC hdc = GetDC(m_self);
SelectObject(hdc, this->m_fnt);
GetTextMetricsW(hdc, &tm);
ReleaseDC(m_self, hdc);
POINT caretPos{ 0 };
GetCaretPos(&caretPos);
LRESULT notifyValue = this->Notify(EM_CHARFROMPOS, 0, MAKELPARAM(caretPos.x, caretPos.y));
int lineIdx = static_cast<int>(this->Notify<int, LPARAM>(EM_LINEINDEX, -1));
m_caretPos.line = HIWORD(notifyValue) + 1;
m_caretPos.column = (LOWORD(notifyValue) - lineIdx) + 1;
SendMessage(GetParent(m_parent), CEM_GETLINEINFO, MAKEWPARAM(m_caretPos.line, m_caretPos.column), 0);
}
break;
}
return DefSubclassProc(m_self, msg, wParam, lParam);
}

How to block resizing after a double-click on a dialog window's top or bottom edges in Windows 10?

I'm coding a customized popup window with C++ using Win32. The condition for this popup window is that it can be only resized from the bottom down. The following is the implementation of such restriction:
RECT rcInitialWindowRectangle = {0};
//The dialog has WS_THICKFRAME style
LRESULT CALLBACK DlgWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_INITDIALOG:
{
//Set minimum window size
::GetWindowRect(hDlg, &rcInitialWindowRectangle);
}
break;
case WM_SIZING:
{
//Restrict sizing on all sides but bottom
if(wParam != WMSZ_BOTTOM)
{
RECT* pRcWnd = (RECT*)lParam;
//Preserve all sides but bottom
int b = pRcWnd->bottom;
*pRcWnd = rcInitialWindowRectangle;
pRcWnd->bottom = b;
return TRUE;
}
}
break;
case WM_GETMINMAXINFO:
{
//The following is needed to restrict minimum window size
int w = rcInitialWindowRectangle.right - rcInitialWindowRectangle.left;
if(w != 0)
{
MINMAXINFO* pMMI = (MINMAXINFO*)lParam;
pMMI->ptMinTrackSize.x = w;
pMMI->ptMinTrackSize.y = rcInitialWindowRectangle.bottom - rcInitialWindowRectangle.top;
pMMI->ptMaxTrackSize.x = w;
}
}
break;
case WM_NCHITTEST:
{
//The following is needed to display correct cursor for resizing
POINT pnt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
RECT rcWnd;
::GetWindowRect(hDlg, &rcWnd);
//L, T, R, B
RECT rcBtm = {rcInitialWindowRectangle.left,
rcWnd.bottom - 16, //Some arbitrary border
rcInitialWindowRectangle.right,
rcWnd.bottom};
return ::PtInRect(&rcBtm, pnt) ? HTNOWHERE : HTBORDER;
}
break;
return 0;
}
So this works except one thing. On Windows 10, there's evidently a new feature -- when someone double-clicks on the bottom (or top) edge of a window -- here's an example with Notepad so that you can try:
that window is resized (stretched) to the top and bottom of the screen (akin to maximization, but only vertically.)
So my question is how do I block this double-click resizing? (In my case the top of the popup window should not move.)
PS. My first instinct was to block all double-clicks on the window's edge, but then I thought that maybe there's a less barbaric way to achieve this?
You are already handling WM_NCHITTEST. Handle WM_NCLBUTTONDBLCLK and don't forward to DefWindowProc unless the hit test (in wParam) indicates the lower frame.
here's the workaround that seems to work for me. It is not really about blocking the double-clicks. (Apart from subclassing the WndProc of a dialog box, which I haven't tried, I failed to block that double-click effect in DlgProc alone.) My workaround presented below is to achor the top of the popup window and let it drop down to the bottom of the screen, if the user who double-clicks the bottom border wants similar stuff to happen.
Since this does not answer my original question, I won't mark it as such.
//Add this case statement to my original code
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS* pWP = (WINDOWPOS*)lParam;
if(!(pWP->flags & (SWP_NOMOVE | SWP_NOSIZE)))
{
int w = rcInitialWindowRectangle.right - rcInitialWindowRectangle.left;
if(w > 0)
{
//Anchor the top of the popup window
pWP->x = rcInitialWindowRectangle.left;
pWP->y = rcInitialWindowRectangle.top;
pWP->cx = w;
int h = pWP->cy;
//Make sure that the height fits the screen
POINT pnt = {pWP->x, pWP->y};
MONITORINFO mi = {0};
mi.cbSize = sizeof(mi);
if(::GetMonitorInfo(::MonitorFromPoint(pnt, MONITOR_DEFAULTTONEAREST), &mi))
{
if(pWP->y + h > mi.rcWork.bottom)
{
int nMinDefaultH = rcInitialWindowRectangle.bottom -
rcInitialWindowRectangle.top;
int nAh = mi.rcWork.bottom - y;
if(nAh >= nMinDefaultH)
h = nAh;
else
h = nMinDefaultH;
}
}
pWP->cy = h;
}
}
}
break;

Tracking tooltip in CScrollView?

In a standard C++/MFC MDI doc/view project, I want to implement a tracking tooltip in the view (the tabbed view windows which generally occupy most of the main frame window). So, in class MyAppView, I have a member CToolTipCtrl tooltip. Function MyAppView::OnInitialUpdate() contains the initialization
BOOL ok0 = tooltip.Create(this, TTS_ALWAYSTIP);
CRect clientRect; GetClientRect(&clientRect);
BOOL ok2 = tooltip.AddTool(this, LPSTR_TEXTCALLBACK, &clientRect, 1234/*tool ID*/);
tooltip.Activate(TRUE);
to make the entire client area of the view be the "tool". The message map contains an entry
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)
and the function OnNeedToolTipText is defined as
BOOL MyAppView::OnNeedToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
UNREFERENCED_PARAMETER(id);
NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(nID == 1234)
{
// Come here when text is needed for tracking tooltip
}
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %d"), nID);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}
*pResult = 0;
return bRet;
}
What happens is that only placing the mouse on the menu items (File, Edit, View, Window, Help) causes the code to enter OnNeedToolTipText, with an ID of 0-5. Moving the mouse into the client area (the view) does nothing.
How can I get the tooltip to appear in the client area of the view only?
Visual Studio 2017; C++; 64-bit Windows 7
In order to solve the problem you need to do the following:
BOOL CMyAppView::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
if (m_pToolTip->GetSafeHwnd () != NULL)
{
m_pToolTip->RelayEvent(pMsg);
}
break;
}
return CScrollView::PreTranslateMessage(pMsg);
}
If you want a tracking tooltip in a view, these are the steps to follow:
Create tooltip and add the tool.
void CToolTipDemoView::OnInitialUpdate()
{
// ...
m_toolTip.Create(this, TTS_ALWAYSTIP | TTS_NOANIMATE);
m_toolTip.AddTool(this, _T("Doesn't matter"));
}
Handle WM_MOUSEMOVE message. First, call _TrackMouseEvent in order to further receive WM_MOUSELEAVE and activate the tooltip. Second, update the tooltip text, and show it at mouse pointer coordinates.
void CToolTipDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTrackingMouseLeave)
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
::_TrackMouseEvent(&tme);
m_toolTip.Activate(TRUE);
m_bTrackingMouseLeave = TRUE;
}
if (m_pointLastMousePos != point)
{
CString strText;
strText.Format(_T("x = %d y = %d"), point.x, point.y);
m_toolTip.UpdateTipText(strText, this);
m_toolTip.Popup();
m_pointLastMousePos = point;
}
CScrollView::OnMouseMove(nFlags, point);
}
Handle WM_MOUSELEAVE and deactivate the tooltip.
void CCToolTipDemoView::OnMouseLeave()
{
m_bTrackingMouseLeave = FALSE;
// mouse pointer leaves the window so deactivate the tooltip
m_toolTip.Activate(FALSE);
CScrollView::OnMouseLeave();
}
Notes:
there is no more necessary to handle TTN_NEEDTEXT.
also, there is no more necessary to override PreTranslateMessage
So I went back to see what I could be missing. I wrote this stuff over 10 years ago. I had also overridden a CWnd member
virtual INT_PTR OnToolHitTest( CPoint point, TOOLINFO* pTI ) const;
With:
INT_PTR HERichView::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
pTI->hwnd = m_hWnd;
pTI->uId = point.x + ( point.y << 16 );
CRect rect;
GetClientRect( rect );
pTI->rect= rect;
pTI->lpszText= LPSTR_TEXTCALLBACK;
return pTI->uId;
}
And I checked, it won't work without this. So your:
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTip )
Should get called if you add the above. And only EnableToolTips( ); Should be needed.
I have not succeeded in getting the tracking tooltip to work within MFC. The closest I have come is
In message map: ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)
In OnInitialUpdate: BOOL ok1 = EnableTrackingToolTips(TRUE);
In override of virtual function OnToolHitTest:
pTI->hwnd = m_hWnd;
pTI->uId = (UINT_PTR)m_hWnd;
pTI->uFlags = TTF_IDISHWND | TTF_ALWAYSTIP | TTF_TRACK | TTF_NOTBUTTON | TTF_ABSOLUTE | TTF_SUBCLASS;
pTI->lpszText = LPSTR_TEXTCALLBACK;
return pTI->uId;
In OnNeedToolTipText:
NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
CURSORINFO ci; ci.cbSize = sizeof(CURSORINFO); // get something interesting to display
GetCursorInfo(&ci);
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %lld at (%d, %d)"), nID, ci.ptScreenPos.x, ci.ptScreenPos.y);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}
*pResult = 0;
return bRet;
This produces the following peculiar behavior. When I start the app and move the mouse cursor into the client area of the CScrollView, a tooltip appears right next to the cursor.
If I move the mouse carefully (smoothly) the tooltip tracks properly. After a while, though, it disappears, and no further mouse motions, including leaving the CScrollView window and returning, make it re-appear.
I think what is happening is that when the mouse cursor moves over the tooltip window, the tooltip is turned off, permanently. This disappearance does not seem to be time-related (e g, due to auto-pop); if the mouse is left untouched, the tooltip remains indefinitely.

How to get (true) mouse displacement with windows

I'm wondering how to get true mouse displacement with windows.
For example, I could save the position of a previous mouse position, and request the new position, and subtract the latter from the previous. But this would not give me true mouse displacement.
Imagine the previous cursor position would be the maximum x coordinate of your screen resolution, and the user is moving his mouse to the right. Is there still a way to capture the true mouse displacement then?
Thanks
Although it might be possible to actually read sensor data (after all the mouse itself only reports movement, not location), I'm not aware of how this could be done. I think at the very low levels of windows, that displacement information gets translated into cursor position on the screen and from then on, you will always be limited by your screen resolution.
In whatever you are trying to do, is the mouse cursor still visible?
A little while ago, I wrote a WPF numeric edit box control that mimicked the way those controls work in Expression Blend. The ones where you can drag the mouse from the edit box itself and it'll change the value. I ran into exactly same issue that you found and my solution was to hide the mouse cursor, detect displacement on every tick and reset the cursor to the center of the screen. Then when the user lets go of the button to stop dragging, I would put the cursor back to where I found it before the drag. This worked out really well and Expression Blend also behaves this way in hiding the cursor.
As far as I know DirectX has its own APIs to interact with peripherals, that is recommended for game developers. You should look into it - try for example DirectX 8 and the Mouse, more detailed documentation you can find on MSDN.
The most reliable way is to use window hooks. Here is a minimalist sample using C(++)
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){
MSLLHOOKSTRUCT* hookStruct = (MSLLHOOKSTRUCT*)lParam;
int ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int x = hookStruct->pt.x * ScreenWidth / 65536);
int y = hookStruct->pt.y * ScreenHeight / 65536);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
HHOOK LowLevelMouseProcHook = NULL;
void hook_window_procedure()
{
if (LowLevelMouseProcHook == NULL)
LowLevelMouseProcHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LowLevelMouseProc, (HINSTANCE)NULL, NULL);
}
void unhook_window_procedure()
{
if (LowLevelMouseProcHook != NULL)
UnhookWindowsHookEx(LowLevelMouseProcHook);
}
You can hook the mouse calling hook_window_procedure(); and unhook it by calling unhook_window_procedure();
You will receive calls to void LowLevelMouseProc(...) whenever the mouse moves. lParam contains a pointer to MSLLHOOKSTRUCT and you find all needed mouse information in its structs. Most interesting here is POINT pt; that is in relative screen coordinates assuming 1/65536th of the screen. Transform them to real pixels by multiplying with int ScreenWidth or int ScreenHeight and dividing by 65536
If you struggle being clamped by the screen borders, you can make a workaround setting the mouse back to the center of your window each call. This is often seen in older games. If you are not forced to use only the Windows API, I would try using Direct Input.
Another way would be to evaluate WM_INPUT directly in your WindowProc for example. This reads data directly from the Human Interface Device (HID) stack and should have raw Mouse-Data in it. Here is a link to the MS-Documentation
The method on windows is as such:
// you can #include <hidusage.h> for these defines
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
then in message loop:
case WM_INPUT:
{
UINT dwSize = sizeof(RAWINPUT);
static BYTE lpb[sizeof(RAWINPUT)];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
}
break;
}
Installing hooks will trigger sensitive antiviruses.
MSDN doc to refer
This sort of displacement ? : http://en.wikipedia.org/wiki/Differential_calculus
Try pitch/yaw : How could simply calling Pitch() and Yaw() cause the camera to eventually Roll()?
FPS style : http://cboard.cprogramming.com/game-programming/94944-mouse-input-aiming-fps-style-using-glut.html
and this : Jittering when moving mouse
pseudo code:
int mouseX, mouseY;
int oldMouseX, oldMouseY;
while(game_is_Running)
{
oldMouseX = mouseX;
oldMouseY = mouseY;
mouseX = get_new_mouse_from_windows_X();
mouseY = get_new_mouse_from_windows_Y();
if ((mouseX - oldMouseX) > 0)
{
// mouse moved to the right
}
else if ((mouseX - oldMouseX) < 0)
{
// mouse moved to the left
}
if ((mouseY - oldMouseY) < 0)
{
// mouse moved down
}
else if ((mouseY - oldMouseY) > 0)
{
// mouse moved up
}
}
A common method for this (in games):
Every frame of the game, get the position of the mouse and then recenter the mouse in the middle of the window using operating system functions. For every frame other than the first, this should give you an accurate displacement information. The key is to just be re-centering the mouse every frame so it never reaches the blocking outer bounds of the screen.
EDIT: Woops, didn't realize that DXM had already said this.
It is not possible to track physical mouse displacement with the Windows API. However, DirectInput provides features to keep track of it. You can also 'fake' it using only the Windows API, using the neat little trick in the answer of SO user DXM

get weird cursor position

Ok so I'm working with vectors today yaya!
well im also working with getcursorpos() and i get weird results.
here is the code:
VOID fRegularShot(HDC hdc, HWND hWnd)
{
Graphics graphics(hdc);
Image shot(L"RegularShots.png");
long index=0;
while(index<=(long)pRegularShots.size())
{
index+=2;
int x=pRegularShots.at(index);
int y1=index+1;
int y=pRegularShots.at(y1);
graphics.DrawImage(&shot, x, y);
}
}
///////////////////////////////////////////////////
event
case WM_LBUTTONDOWN:
iRegularShots=0;
POINT pt;
GetCursorPos(&pt);
pRegularShots.insert(pRegularShots.begin()+1, pt.y);
pRegularShots.insert(pRegularShots.begin()+1, pt.x);
InvalidateRect(hWnd, rect, false);
break;
Well basically function fregularshots() get called and use the vector elements which contains the positions of the cursor than draws the image on the cursor positions.
but it doesn't seem to draw it on the cursor positions.
any ideas?
GetCursorPos returns cursor position in screen coordinates. Use ScreenToClient(hWnd, ...) to convert it to window client coordinates.
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
You can work also without GetCursorPos function. When WM_LBUTTONDOWN notification is received, lParam contains window client mouse coordinates: x in low-order word, y in high-order word:
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
Edit:
Let's make this code more simple.
vector<POINT> pRegularShots;
VOID fRegularShot(HDC hdc, HWND hWnd)
{
Graphics graphics(hdc);
Image shot(L"RegularShots.png");
long index=0;
while(index < (long)pRegularShots.size())
{
graphics.DrawImage(&shot, pRegularShots[index].x, pRegularShots[index].y);
++index;
}
}
case WM_LBUTTONDOWN:
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
pRegularShots.push_back(pt);
InvalidateRect(hWnd, rect, false);
break;