source: trunk/src/user32/winmouse.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 23.3 KB
Line 
1/* $Id: winmouse.cpp,v 1.27 2003-07-28 11:27:50 sandervl Exp $ */
2/*
3 * Win32 mouse functions
4 *
5 * Copyright 1999-2002 Sander van Leeuwen
6 *
7 * Parts based on Wine code (windows\input.c) (TrackMouseEvent)
8 *
9 * Copyright 1993 Bob Amstadt
10 * Copyright 1996 Albrecht Kleine
11 * Copyright 1997 David Faure
12 * Copyright 1998 Morten Welinder
13 * Copyright 1998 Ulrich Weigand
14 *
15 * TODO: SwapMouseButton:
16 * We shouldn't let win32 apps change this for the whole system
17 * better to change mouse button message translation instead
18 *
19 * Project Odin Software License can be found in LICENSE.TXT
20 *
21 */
22
23#include <odin.h>
24#include <odinwrap.h>
25#include <os2sel.h>
26
27#include <os2win.h>
28#include <misc.h>
29#include "win32wbase.h"
30#include <winuser32.h>
31#include <winuser.h>
32#include <commctrl.h>
33#include <debugtools.h>
34#include <win/mouse.h>
35#include "winmouse.h"
36#include "oslibmsg.h"
37#include "oslibres.h"
38#include "pmwindow.h"
39#include "oslibwin.h"
40#include "hook.h"
41
42#include <winkeyboard.h>
43
44#define DBG_LOCALLOG DBG_winmouse
45#include "dbglocal.h"
46
47
48ODINDEBUGCHANNEL(USER32-WINMOUSE)
49
50
51/****************************************************************************
52 * local variables
53 ****************************************************************************/
54
55//******************************************************************************
56//******************************************************************************
57BOOL WIN32API GetCursorPos( PPOINT lpPoint)
58{
59 if (!lpPoint) return FALSE;
60
61 if (OSLibWinQueryPointerPos(lpPoint)) //POINT == POINTL
62 {
63 mapScreenPoint((OSLIBPOINT*)lpPoint);
64 dprintf2(("USER32: GetCursorPos (%d,%d)", lpPoint->x, lpPoint->y));
65 return TRUE;
66 }
67 else return FALSE;
68}
69//******************************************************************************
70//******************************************************************************
71BOOL WIN32API SetCursorPos( int X, int Y)
72{
73 BOOL ret;
74 POINT point;
75 MSLLHOOKSTRUCT hook;
76
77 GetCursorPos(&point);
78 dprintf(("USER32: SetCursorPos (%d,%d)->(%d,%d)", point.x, point.y, X,Y));
79
80 //The current cursor position may not have been passed to the application
81 //just yet. The position change discards any previous events which may
82 //lead to inconsistent mouse behaviour (like in DirectInput).
83 //To fix this, we pass down a mouse move event to any hook handlers.
84 hook.pt.x = point.x;
85 hook.pt.y = point.y;
86 hook.mouseData = 0;
87 hook.flags = 0;
88 hook.time = GetCurrentTime();
89 hook.dwExtraInfo = 0;
90 HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WM_MOUSEMOVE, (LPARAM)&hook);
91
92 ret = OSLibWinSetPointerPos(X, mapScreenY(Y));
93 if(ret == TRUE) {
94 hook.pt.x = X;
95 hook.pt.y = Y;
96 hook.mouseData = 0;
97 //signal to dinput hook that it only needs to modify the last
98 //known position (not treat it as a new event)
99 hook.flags = LLMHF_INJECTED;
100 hook.time = GetCurrentTime();
101 hook.dwExtraInfo = 0;
102
103 HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WM_MOUSEMOVE, (LPARAM)&hook);
104 }
105 return ret;
106}
107//******************************************************************************
108//******************************************************************************
109BOOL WIN32API ClipCursor(const RECT * lpRect)
110{
111 if(lpRect) {
112 dprintf(("USER32: ClipCursor (%d,%d)(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
113 }
114 else dprintf(("USER32: ClipCursor NULL"));
115 return OSLibWinClipCursor(lpRect);
116}
117//******************************************************************************
118//******************************************************************************
119BOOL WIN32API GetClipCursor( LPRECT lpRect)
120{
121 dprintf(("USER32: GetClipCursor %x", lpRect));
122 return OSLibWinGetClipCursor(lpRect);
123}
124//******************************************************************************
125// capture handle "cache"
126static HWND hwndWin32Capture = 0;
127//******************************************************************************
128HWND WIN32API GetCapture()
129{
130 if (0 == hwndWin32Capture)
131 hwndWin32Capture = OS2ToWin32Handle(OSLibWinQueryCapture());
132
133 return hwndWin32Capture;
134}
135//******************************************************************************
136//******************************************************************************
137HWND WIN32API SetCapture(HWND hwnd)
138{
139 HWND hwndPrev = GetCapture();
140 BOOL rc;
141
142 // invalidate capture "cache"
143 hwndWin32Capture = 0;
144
145 if(hwnd == 0)
146 {
147 ReleaseCapture();
148 return hwndPrev;
149 }
150
151 if(hwnd == hwndPrev)
152 {
153 dprintf(("USER32: SetCapture %x; already set to that window; ignore", hwnd));
154 //TODO: NT4 SP6 sends this message even now
155//////// SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
156 return hwndPrev;
157 }
158
159 if(hwndPrev != NULL)
160 {
161 //SvL: WinSetCapture returns an error if mouse is already captured
162 OSLibWinSetCapture(0);
163 }
164
165 rc = OSLibWinSetCapture(Win32ToOS2Handle(hwnd));
166 dprintf(("USER32: SetCapture %x (prev %x) returned %d", hwnd, hwndPrev, rc));
167 if(hwndPrev)
168 {
169 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
170 }
171 return hwndPrev;
172}
173//******************************************************************************
174//******************************************************************************
175BOOL WIN32API ReleaseCapture()
176{
177 HWND hwndPrev;
178 BOOL ret;
179
180 hwndPrev = GetCapture();
181
182 // invalidate capture "cache"
183 hwndWin32Capture = 0;
184
185 ret = OSLibWinSetCapture(0);
186 if(hwndPrev)
187 {
188 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, 0L);
189 }
190 return ret;
191}
192//******************************************************************************
193//******************************************************************************
194UINT WIN32API GetDoubleClickTime()
195{
196 UINT result = OSLibWinQuerySysValue(SVOS_DBLCLKTIME);
197 if(result == 0)
198 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
199
200 return result;
201}
202//******************************************************************************
203//******************************************************************************
204BOOL WIN32API SetDoubleClickTime(UINT uInterval)
205{
206 BOOL ret = TRUE;
207
208 ret = OSLibWinSetSysValue(SVOS_DBLCLKTIME, uInterval);
209 if(ret == FALSE )
210 {
211 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
212 }
213 return (ret);
214}
215//******************************************************************************
216//TODO: we shouldn't let win32 apps change this for the whole system
217// better to change mouse button message translation instead
218BOOL OPEN32API __SwapMouseButton(BOOL swapFlag);
219
220inline BOOL _SwapMouseButton(BOOL swapFlag)
221{
222 BOOL yyrc;
223 USHORT sel = RestoreOS2FS();
224
225 yyrc = __SwapMouseButton(swapFlag);
226 SetFS(sel);
227
228 return yyrc;
229}
230
231//******************************************************************************
232BOOL WIN32API SwapMouseButton(BOOL fSwap)
233{
234 return _SwapMouseButton(fSwap);
235}
236
237/*****************************************************************************
238 * Name : VOID WIN32API mouse_event
239 * Purpose : The mouse_event function synthesizes mouse motion and button clicks.
240 * Parameters: DWORD dwFlags flags specifying various motion/click variants
241 * DWORD dx horizontal mouse position or position change
242 * DWORD dy vertical mouse position or position change
243 * DWORD cButtons unused, reserved for future use, set to zero
244 * DWORD dwExtraInfo 32 bits of application-defined information
245 * Variables :
246 * Result :
247 * Remark :
248 * Status : UNTESTED STUB
249 *
250 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
251 *****************************************************************************/
252
253VOID WIN32API mouse_event(DWORD dwFlags, DWORD dx, DWORD dy, DWORD cButtons,
254 DWORD dwExtraInfo)
255{
256 INPUT i;
257
258 i.type = INPUT_MOUSE;
259 i.mi.dx = dx;
260 i.mi.dy = dy;
261 i.mi.mouseData = cButtons; // PH: is this really correct?
262 i.mi.dwFlags = dwFlags;
263 i.mi.dwExtraInfo = dwExtraInfo;
264
265 // forward to more modern API
266 SendInput(1, &i, sizeof(i) );
267}
268
269
270/*****************************************************************************
271 * Name : UINT SendInput
272 * Purpose : The SendInput function synthesizes keystrokes, mouse motions,
273 * and button clicks
274 * Parameters: UINT nInputs // count if input events
275 * LPINPUT pInputs // array of input structures
276 * int chSize // size of structure
277 * Variables :
278 * Result : number of events successfully inserted,
279 * 0 if the input was already blocked by another thread
280 * Remark :
281 * Status : UNTESTED STUB
282 * TODO: call hooks!!
283 *
284 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
285 *****************************************************************************/
286
287UINT WIN32API SendInput(UINT nInputs, LPINPUT pInputs, int chSize)
288{
289 dprintf(("not correctly implemented"));
290
291 // The simulated input is sent to the
292 // foreground thread's message queue.
293 // (WM_KEYUP, WM_KEYDOWN)
294 // After GetMessage or PeekMessage,
295 // TranslateMessage posts an appropriate
296 // WM_CHAR message.
297
298 HWND hwnd = GetForegroundWindow();
299
300 LPINPUT piBase = pInputs;
301 for (int i = 0;
302 i < nInputs;
303 i++,
304 piBase++)
305 {
306 switch(piBase->type)
307 {
308 case INPUT_MOUSE:
309 {
310 PMOUSEINPUT p = (PMOUSEINPUT)&piBase->mi;
311 MSG msg;
312 HWND hwndCapture;
313
314 hwndCapture = GetCapture();
315 if(hwndCapture) hwnd = hwndCapture;
316
317 if(p->dwFlags & MOUSEEVENTF_MOVE)
318 {
319 if(!(p->dwFlags & MOUSEEVENTF_ABSOLUTE)) {
320 POINT pt;
321
322 if(GetCursorPos(&pt) == TRUE) {
323 LONG relx = (LONG)p->dx;
324 LONG rely = (LONG)p->dy;
325
326 p->dx = pt.x + relx;
327 p->dy = pt.y + rely;
328 }
329 else {
330 DebugInt3();
331 return 0;
332 }
333 }
334 SetCursorPos(p->dx, p->dy);
335 OSLibSendWinMessage(hwnd, WM_MOUSEMOVE);
336 }
337
338 if(p->dwFlags & MOUSEEVENTF_LEFTDOWN)
339 {
340 KeySetOverlayKeyState(VK_LBUTTON, KEYOVERLAYSTATE_DOWN);
341 OSLibSendWinMessage(hwnd, WM_LBUTTONDOWN);
342 }
343 if(p->dwFlags & MOUSEEVENTF_LEFTUP)
344 {
345 KeySetOverlayKeyState(VK_LBUTTON, KEYOVERLAYSTATE_DONTCARE);
346 OSLibSendWinMessage(hwnd, WM_LBUTTONUP);
347 }
348 if(p->dwFlags & MOUSEEVENTF_RIGHTDOWN)
349 {
350 KeySetOverlayKeyState(VK_RBUTTON, KEYOVERLAYSTATE_DOWN);
351 OSLibSendWinMessage(hwnd, WM_RBUTTONDOWN);
352 }
353 if(p->dwFlags & MOUSEEVENTF_RIGHTUP)
354 {
355 KeySetOverlayKeyState(VK_RBUTTON, KEYOVERLAYSTATE_DONTCARE);
356 OSLibSendWinMessage(hwnd, WM_RBUTTONUP);
357 }
358 if(p->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
359 {
360 KeySetOverlayKeyState(VK_MBUTTON, KEYOVERLAYSTATE_DOWN);
361 OSLibSendWinMessage(hwnd, WM_MBUTTONDOWN);
362 }
363 if(p->dwFlags & MOUSEEVENTF_MIDDLEUP)
364 {
365 KeySetOverlayKeyState(VK_MBUTTON, KEYOVERLAYSTATE_DONTCARE);
366 OSLibSendWinMessage(hwnd, WM_MBUTTONUP);
367 }
368 if(p->dwFlags & MOUSEEVENTF_WHEEL)
369 {
370 OSLibSendWinMessage(hwnd, WM_MOUSEWHEEL, p->mouseData);
371 }
372 }
373 break;
374
375 // compose a keyboard input message
376 case INPUT_KEYBOARD:
377 {
378 PKEYBDINPUT p = (PKEYBDINPUT)&piBase->ki;
379 MSG msg;
380 BOOL fUnicode = (p->dwFlags & KEYEVENTF_UNICODE) == KEYEVENTF_UNICODE;
381 DWORD extrainfo = GetMessageExtraInfo();
382
383 //TODO: We should really send an OS/2 WM_CHAR message here and let
384 // our existing code handle everything (WM_CHAR generation)
385 // This is a quick and dirty implementation. Not entirely correct.
386
387 // build keyboard message
388 msg.message = (p->dwFlags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
389
390 if (p->dwFlags & KEYEVENTF_SCANCODE)
391 {
392 // keystroke is identified by the scancode
393 if (fUnicode)
394 msg.wParam = MapVirtualKeyW(p->wScan, 1);
395 else
396 msg.wParam = MapVirtualKeyA(p->wScan, 1);
397 }
398 else
399 msg.wParam = p->wVk;
400
401 msg.lParam = 0x0000001 | // repeat count
402 ( (p->wScan & 0xff) << 16); // scan code
403
404 if (p->dwFlags & KEYEVENTF_EXTENDEDKEY)
405 msg.lParam |= (1 << 24);
406
407 // set additional message flags
408 if (msg.message == WM_KEYDOWN)
409 {
410 // @@@PH
411 // bit 30 - previous key state cannot be set, how to determine?
412 }
413 else
414 {
415 // WM_KEYUP -> previous key is always 1, transistion state
416 // always 1
417 msg.lParam |= (1 << 30);
418 msg.lParam |= (1 << 31);
419 }
420
421 msg.time = p->time;
422
423 // @@@PH
424 // unknown: do we have to post or to send the message?
425
426 SetMessageExtraInfo( (LPARAM)p->dwExtraInfo );
427
428 KeySetOverlayKeyState(msg.wParam, (msg.message == WM_KEYDOWN) ? KEYOVERLAYSTATE_DOWN : KEYOVERLAYSTATE_DONTCARE);
429
430 if (fUnicode)
431 SendMessageW(hwnd, msg.message, msg.wParam, msg.lParam);
432 else
433 SendMessageA(hwnd, msg.message, msg.wParam, msg.lParam);
434
435 if(msg.message == WM_KEYDOWN) {
436 char keybstate[256];
437 WORD key = 0;
438
439 GetKeyboardState((LPBYTE)&keybstate[0]);
440 if(ToAscii(p->wVk, p->wScan, (LPBYTE)&keybstate[0], &key, 0) != 0) {
441 SendMessageA(hwnd, WM_CHAR, key, msg.lParam);
442 }
443 }
444
445 //restore extra info
446 SetMessageExtraInfo(extrainfo);
447 break;
448 }
449
450 case INPUT_HARDWARE:
451 {
452 PHARDWAREINPUT p = (PHARDWAREINPUT)&piBase->hi;
453
454 // @@@PH
455 // not supported for the time being
456 }
457 break;
458
459 default:
460 dprintf(("unsupported input packet type %d",
461 piBase->type));
462 break;
463 }
464 }
465
466 return 0;
467}
468
469/*****************************************************************************
470 * Name : BOOL WIN32API DragDetect
471 * Purpose : The DragDetect function captures the mouse and tracks its movement
472 * Parameters: HWND hwnd
473 * POINT pt
474 * Variables :
475 * Result : If the user moved the mouse outside of the drag rectangle while
476 * holding the left button down, the return value is TRUE.
477 * If the user did not move the mouse outside of the drag rectangle
478 * while holding the left button down, the return value is FALSE.
479 * Remark :
480 * Status : UNTESTED STUB
481 *
482 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
483 *****************************************************************************/
484BOOL WIN32API DragDetect(HWND hwnd, POINT pt)
485{
486 dprintf(("not implemented"));
487
488 return (FALSE);
489}
490//******************************************************************************
491//******************************************************************************
492typedef struct __TRACKINGLIST {
493 TRACKMOUSEEVENT tme;
494 POINT pos; /* center of hover rectangle */
495 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
496} _TRACKINGLIST;
497
498#define UINT_PTR UINT
499static _TRACKINGLIST TrackingList[10];
500static int iTrackMax = 0;
501static UINT_PTR timer;
502static const INT iTimerInterval = 50; /* msec for timer interval */
503
504/* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
505/* TrackMouseEventProc and _TrackMouseEvent */
506static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
507 DWORD dwTime)
508{
509 int i = 0;
510 POINT pos;
511 HWND hwnd;
512 INT hoverwidth = 0, hoverheight = 0;
513
514 GetCursorPos(&pos);
515 hwnd = WindowFromPoint(pos);
516
517 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
518 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
519
520 /* loop through tracking events we are processing */
521 while (i < iTrackMax) {
522 /* see if this tracking event is looking for TME_LEAVE and that the */
523 /* mouse has left the window */
524 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
525 (TrackingList[i].tme.hwndTrack != hwnd)) {
526 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
527
528 /* remove the TME_LEAVE flag */
529 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
530 }
531
532 /* see if we are tracking hovering for this hwnd */
533 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
534 /* add the timer interval to the hovering time */
535 TrackingList[i].iHoverTime+=iTimerInterval;
536
537 /* has the cursor moved outside the rectangle centered around pos? */
538 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
539 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
540 {
541 /* record this new position as the current position and reset */
542 /* the iHoverTime variable to 0 */
543 TrackingList[i].pos = pos;
544 TrackingList[i].iHoverTime = 0;
545 }
546
547 /* has the mouse hovered long enough? */
548 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
549 {
550 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
551
552 /* stop tracking mouse hover */
553 TrackingList[i].tme.dwFlags ^= TME_HOVER;
554 }
555 }
556
557 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
558 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
559 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
560 i++;
561 } else { /* remove this entry from the tracking list */
562 TrackingList[i] = TrackingList[--iTrackMax];
563 }
564 }
565
566 /* stop the timer if the tracking list is empty */
567 if(iTrackMax == 0) {
568 KillTimer(0, timer);
569 timer = 0;
570 }
571}
572
573
574/***********************************************************************
575 * TrackMouseEvent [USER32]
576 *
577 * Requests notification of mouse events
578 *
579 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
580 * to the hwnd specified in the ptme structure. After the event message
581 * is posted to the hwnd, the entry in the queue is removed.
582 *
583 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
584 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
585 * immediately and the TME_LEAVE flag being ignored.
586 *
587 * PARAMS
588 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
589 *
590 * RETURNS
591 * Success: non-zero
592 * Failure: zero
593 *
594 */
595
596BOOL WINAPI
597TrackMouseEvent (TRACKMOUSEEVENT *ptme)
598{
599 DWORD flags = 0;
600 int i = 0;
601 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
602 HWND hwnd;
603 POINT pos;
604
605 pos.x = 0;
606 pos.y = 0;
607
608 dprintf(("TrackMouseEvent: %lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime));
609
610 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
611 WARN("wrong TRACKMOUSEEVENT size from app\n");
612 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
613 return FALSE;
614 }
615
616 flags = ptme->dwFlags;
617
618 /* if HOVER_DEFAULT was specified replace this with the systems current value */
619 if(ptme->dwHoverTime == HOVER_DEFAULT)
620 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
621
622 GetCursorPos(&pos);
623 hwnd = WindowFromPoint(pos);
624
625 if ( flags & TME_CANCEL ) {
626 flags &= ~ TME_CANCEL;
627 cancel = 1;
628 }
629
630 if ( flags & TME_HOVER ) {
631 flags &= ~ TME_HOVER;
632 hover = 1;
633 }
634
635 if ( flags & TME_LEAVE ) {
636 flags &= ~ TME_LEAVE;
637 leave = 1;
638 }
639
640 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
641 if ( flags & TME_QUERY ) {
642 flags &= ~ TME_QUERY;
643 query = 1;
644 i = 0;
645
646 /* Find the tracking list entry with the matching hwnd */
647 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
648 i++;
649 }
650
651 /* hwnd found, fill in the ptme struct */
652 if(i < iTrackMax)
653 *ptme = TrackingList[i].tme;
654 else
655 ptme->dwFlags = 0;
656
657 return TRUE; /* return here, TME_QUERY is retrieving information */
658 }
659
660 if ( flags )
661 FIXME("Unknown flag(s) %08lx\n", flags );
662
663 if(cancel) {
664 /* find a matching hwnd if one exists */
665 i = 0;
666
667 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
668 i++;
669 }
670
671 if(i < iTrackMax) {
672 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
673
674 /* if we aren't tracking on hover or leave remove this entry */
675 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
676 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
677 {
678 TrackingList[i] = TrackingList[--iTrackMax];
679
680 if(iTrackMax == 0) {
681 KillTimer(0, timer);
682 timer = 0;
683 }
684 }
685 }
686 } else {
687 /* see if hwndTrack isn't the current window */
688 if(ptme->hwndTrack != hwnd) {
689 if(leave) {
690 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
691 }
692 } else {
693 /* See if this hwnd is already being tracked and update the tracking flags */
694 for(i = 0; i < iTrackMax; i++) {
695 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
696 if(hover) {
697 TrackingList[i].tme.dwFlags |= TME_HOVER;
698 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
699 }
700
701 if(leave)
702 TrackingList[i].tme.dwFlags |= TME_LEAVE;
703
704 /* reset iHoverTime as per winapi specs */
705 TrackingList[i].iHoverTime = 0;
706
707 return TRUE;
708 }
709 }
710
711 /* if the tracking list is full return FALSE */
712 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
713 return FALSE;
714 }
715
716 /* Adding new mouse event to the tracking list */
717 TrackingList[iTrackMax].tme = *ptme;
718
719 /* Initialize HoverInfo variables even if not hover tracking */
720 TrackingList[iTrackMax].iHoverTime = 0;
721 TrackingList[iTrackMax].pos = pos;
722
723 iTrackMax++;
724
725 if (!timer) {
726 timer = SetTimer(0, 0, iTimerInterval, (TIMERPROC)TrackMouseEventProc);
727 }
728 }
729 }
730
731 return TRUE;
732}
733//******************************************************************************
734//******************************************************************************
735ULONG GetMouseKeyState()
736{
737 ULONG keystate = 0;
738
739 if(GetKeyState(VK_LBUTTON) & 0x8000)
740 keystate |= MK_LBUTTON;
741 if(GetKeyState(VK_RBUTTON) & 0x8000)
742 keystate |= MK_RBUTTON;
743 if(GetKeyState(VK_MBUTTON) & 0x8000)
744 keystate |= MK_MBUTTON;
745 if(GetKeyState(VK_SHIFT) & 0x8000)
746 keystate |= MK_SHIFT;
747 if(GetKeyState(VK_CONTROL) & 0x8000)
748 keystate |= MK_CONTROL;
749
750 return keystate;
751}
752//******************************************************************************
753//******************************************************************************
Note: See TracBrowser for help on using the repository browser.