How to make a mouse cursor to point to a window? - c++

Is there a way to automatically/by default set the mouse cursor to point inside a newly created window (using for e.g. the CreateWindow function)? I know that for keyboard input there is a SetFocus() function, but haven't found a similar function for a mouse.

As #IInspectable said, the following is the code implementation.
LRESULT CALLBACK WndProcNOP(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
RECT rcClient;
GetWindowRect(hwnd, &rcClient);
int x = rcClient.left + (rcClient.right - rcClient.left) / 2;
int y = rcClient.top + (rcClient.bottom - rcClient.top) / 2;
SetCursorPos(x, y);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
return 0;
}

Related

How to change textout() when it's already drawn?

I'm trying to move static TCHAR greeting[] = _T("123"); by using arrows, but it doesn't move at all. MessageBox is used as a confirmation of getting keyboard input.
void move(HWND hWnd, WPARAM wParam, LPARAM lParam, unsigned int *x, unsigned int * y) {
RECT rt;
if (wParam == VK_LEFT) {
GetClientRect(hWnd, &rt);
x = x - 5;
InvalidateRect(hWnd, &rt, FALSE);
MessageBox(hWnd, LPCSTR("123"), LPCSTR("123"), MB_OK);
}
if (wParam == VK_DOWN) {
GetClientRect(hWnd, &rt);
y = y - 5;
InvalidateRect(hWnd, &rt, FALSE);
}
if (wParam == VK_UP) {
GetClientRect(hWnd, &rt);
y = y + 5;
InvalidateRect(hWnd, &rt, FALSE);
}
if (wParam == VK_RIGHT) {
GetClientRect(hWnd, &rt);
x = x + 5;
InvalidateRect(hWnd, &rt, FALSE);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
static TCHAR greeting[] = _T("123");
unsigned int x = 50;
unsigned int y = 50;
switch (message)
{
case WM_PAINT: {
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc,
x, y,
greeting, 3);
EndPaint(hWnd, &ps);
break;
}
case WM_KEYDOWN:
move(hWnd, wParam, lParam, &x, &y);
break;
case WM_DESTROY: {
PostQuitMessage(0);
break;
default: {
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
}
return 0;
}
}
Can somebody explain, what is wrong here? I'm still trying to learn about <Windows.h> so pls don't try to make the code much more complicated.
The x and y variables you are using to draw the text with are local to WndProc and are always reset to the initial values whenever a new message is received. You need to move their declarations outside of WndProc() (or at least make them static) so that their values can persist between messages. You can then update their values in your WM_KEYDOWN handler, and use their current values to draw the text in your WM_PAINT handler.
Also, your move() function is updating the pointers that are pointing at the x and y variables, it is not updating the values of the x and y variables themselves.
Try this instead:
void move(HWND hWnd, WPARAM wParam, LPARAM lParam, unsigned int *x, unsigned int * y) {
switch (wParam) {
case VK_LEFT:
*x -= 5;
InvalidateRect(hWnd, NULL, FALSE);
break;
case VK_DOWN:
*y -= 5;
InvalidateRect(hWnd, NULL, FALSE);
break;
case VK_UP:
*y += 5;
InvalidateRect(hWnd, NULL, FALSE);
break;
case VK_RIGHT:
*x += 5;
InvalidateRect(hWnd, NULL, FALSE);
break;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
static TCHAR greeting[] = _T("123");
static unsigned int x = 50;
static unsigned int y = 50;
switch (message) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
TextOut(hdc,
x, y,
greeting, 3);
EndPaint(hWnd, &ps);
break;
}
case WM_KEYDOWN:
move(hWnd, wParam, lParam, &x, &y);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
While #Remy Lebeau's answer is right, I don't think I'd write the move function quite the way he has. I'd pass x and y by reference instead of using pointers, and I'd consolidate more of the code together. Oh, and since it doesn't use lParam, we might as well not pass it at all:
void move(HWND hWnd, WPARAM wParam, unsigned int &x, unsigned int & y) {
switch (wParam) {
case VK_LEFT:
x -= 5;
break;
case VK_DOWN:
y -= 5;
break;
case VK_UP:
y += 5;
break;
case VK_RIGHT:
x += 5;
break;
default: return;
}
InvalidateRect(hWnd, NULL, FALSE);
}
Also note, however that this has a little bit of a problem. Passing FALSE as the last parameter to InvalidateRect means it doesn't erase the background. If you move your string around much, you're probably going to end up with artifacts of the movement--fragments of the string showing up in both the previous and the current location.
One easy way to fix that is change the final parameter to TRUE. To make that a bit more efficient, you can calculate the rectangle covering the old and new locations of the string, and invalidate only that much. Alternatively, invalidate the old rectangle with TRUE and the new rectangle with FALSE, and Windows will figure things out from there.
Another possibility (slightly more work, but under the right circumstances it can pay off) is to create an off-screen bitmap containing both your message and a border in the background color that's large enough to cover up the message in its previous location. Then when you move it around, you just blit that bitmap to the screen.
That obviously only works if your background is a solid, uniform color though.

In win32 api using c++ i want to track double click and triple click and so on

LRESULT handleDoubleClicks(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, POINT ptLastClickPos, DWORD dwLastClickTime)
{
DWORD dwClickTime = GetMessageTime();
POINT ptClickPos = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
switch(message)
{
case WM_LBUTTONDOWN:
if (dwLastClickTime + GetDoubleClickTime() > dwClickTime
&& abs(ptLastClickPos.x - ptClickPos.x) < GetSystemMetrics(SM_CXDOUBLECLK)
&& abs(ptLastClickPos.y - ptClickPos.y) < GetSystemMetrics(SM_CYDOUBLECLK))
{
MessageBox(hWnd, TEXT("Double click"), TEXT("I appear when double clicked"), MB_OKCANCEL);
}
else
{
dwLastClickTime = dwClickTime;
ptLastClickPos = ptClickPos;
wchar_t waCoord[20];
wsprintf(waCoord, _T("(%i,%i)"), ptLastClickPos.x, ptLastClickPos.y);
MessageBox(hWnd, waCoord, _T("Left mouse button click"), MB_OK);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
This is function i have made to handle double click:
This function is called when windows recieve WM_LBUTTONDOWN it will take the time of the message and coordinate of the click and will transfer it to the function here i want the fuction to recieve another message WM_LBUTTONDOWN and determine the time of the message and compare with the previous click time and the co ordinates to identify if it is a double click.
But this is not working .May be I am Wrong with the approach I am newbie Pls help me to solve this problem.
case WM_LBUTTONDOWN:
{
dwLastClickTime= GetMessageTime();
// SetTimer(hWnd,0,GetDoubleClickTime(),0);
ptLastClickPos.x = LOWORD(lParam);
ptLastClickPos.y = HIWORD(lParam);
handleDoubleClicks(hWnd, message, wParam, lParam, ptLastClickPos, dwLastClickTime);
}
You could use SetTimer, after one click, not immediately judge it as a click, but start the timer, check whether there is another click within the timer range, if there is, it is judged as double-click, if not, and the previous time is determined as a single click.
#define TIMER_ID 10
static int click_count = 0;
static POINT point = { 0 };
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_TIMER:
{
KillTimer(hWnd, TIMER_ID);
if (click_count == 1)
{
wchar_t waCoord[20];
wsprintf(waCoord, _T("(%i,%i)"), point.x, point.y);
MessageBox(hWnd, waCoord, _T("Left mouse button click"), MB_OK);
}
else if(click_count == 2)
{
MessageBox(hWnd, TEXT("Double click"), TEXT("I appear when double clicked"), MB_OKCANCEL);
}
else if (click_count == 3)
{
MessageBox(hWnd, TEXT("Triple click"), TEXT("I appear when triple clicked"), MB_OKCANCEL);
}
click_count = 0;
return 0;
}
break;
case WM_LBUTTONDOWN:
{
if (click_count == 0)
{
SetTimer(hWnd, TIMER_ID, GetDoubleClickTime(), NULL);
}
click_count++;
return 0;
}
break;
case WM_PAINT:
{
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;
}
And make sure your window doesn't have CS_DBLCLKS style. Otherwise, the second WM_LBUTTONDOWN message that would normally be generated becomes a WM_LBUTTONDBLCLK message, according to the document: Double Clicks

Create resizable window with fixed top coordinate

I'd like to implemented a window that its top coordinate is always X (for simplicity let's say 0). Meaning, the window's top side is fixed on 0 which is the top of the screen.
I've already implemented the window, set its position using SetWindowPos but I'm struggling maintaining its top coordinate value.
You can create a window with no caption bar, for example
CreateWindow(className, title, WS_THICKFRAME | WS_POPUP, ...)
Then override WM_NCHITTEST to change the requests for moving the window up and down.
If window has caption bar, for example:
CreateWindow(className, title, WS_OVERLAPPEDWINDOW, ...)
Then add override for WM_WINDOWPOSCHANGING as well:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_NCHITTEST:
{
LRESULT lresult = DefWindowProc(hwnd, msg, wParam, lParam);
switch (lresult)
{
case HTTOP: lresult = HTCLIENT; break;
case HTTOPLEFT: lresult = HTLEFT; break;
case HTTOPRIGHT: lresult = HTRIGHT; break;
}
return lresult;
}
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS* wndpos = (WINDOWPOS*)lParam;
wndpos->y = 100;//choose a fixed position
break;
}
...
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

Saving coordinates of 2 mouse clicks and the drawing line between them c++

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ HDC hdc;
int count=1; int xs,ys,xe,ye;
switch (message)
{
case WM_LBUTTONDOWN
hdc=GetDC(hwnd);
if(count%2!=1){
xs=GET_X_LPARAM(lParam);
ys=GET_Y_LPARAM(lParam);}
else{
xe=GET_X_LPARAM(lParam);
ye=GET_Y_LPARAM(lParam);
drawline(hdc,xs,ys,xe,ye);
}
ReleaseDC(hwnd,hdc);
count++;
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
I've tried , but there's something wrong with this code.
Use
if(count%2 == 1)
insted of
if(count%2 != 1)
Might work then.

ComboBox Subclassing Listbox

I am trying to Subclass the Listbox and the Edit Control of a Combobox for some customasing reasons. Below is the code work . Subclassing for Edit Control is working perfect but Listbox is not getting the messeage of MouseDown.
void Subclass(HWND hComboBox)
{
HWND hEdit=FindWindowEx(hComboBox, NULL, WC_EDIT, NULL);
HWND hCombo=FindWindowEx(hComboBox, NULL, WC_LISTBOX, NULL);
SetProp(hEdit, TEXT("Wprc"), (HANDLE)GetWindowLongPtr(hEdit, GWL_WNDPROC));
SubclassWindow(hEdit, ComboBox_Proc);
SetProp(hCombo, TEXT("Wprc1"), (HANDLE)GetWindowLongPtr(hCombo, GWL_WNDPROC));
SubclassWindow(hCombo, ComboBox_Proc1);
}
static LRESULT CALLBACK ComboBox_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CHAR:
break;
case WM_KEYDOWN:
break;
case WM_DESTROY:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (DWORD)GetProp(hwnd, TEXT("Wprc")));
RemoveProp(hwnd, TEXT("Wprc"));
break;
default:
return CallWindowProc((WNDPROC)GetProp(hwnd, TEXT("Wprc")), hwnd, msg, wParam, lParam);
}
return FALSE;
}
static LRESULT CALLBACK ComboBox_Proc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
//PROBLEM IS HERE
break;
case WM_DESTROY:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (DWORD)GetProp(hwnd, TEXT("Wprc1")));
RemoveProp(hwnd, TEXT("Wprc1"));
break;
default:
return CallWindowProc((WNDPROC)GetProp(hwnd, TEXT("Wprc1")), hwnd, msg, wParam, lParam);
}
return FALSE;
}
The ListBox part of a ComboBox is of type COMBOLBOX (with L).
The ComboLBox window is not a child of the ComboBox window.
The only way I found to subclass the COMBOLBOX control is as follows.
Windows sends the WM_CTLCOLORLISTBOX message to the COMBOBOX (no L) before the listbox is drawn. The lParam of this message contains the handle of the listbox.
case WM_CTLCOLORLISTBOX:
{
if ( !hSubclassedListBox )
{
hSubclassedListBox = (HWND)lParam;
SubclassWindow(hSubclassedListBox , MyLBProc);
}
}
Alsoo see this link for more information
For those who are using Visual Studio with WINVER set to 0500 or higher (Windows XP or later), you can use the GetComboBoxInfo function (passing the handle to the ComboBox), which will return (in a COMBOBOXINFO structure) the handles to both the Edit box and the ComboLBox (ListBox). The handles can then be used to get the CWnd-derived objects they represent.