4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
17 #include "wine/obj_base.h"
18 #include "wine/obj_clientserver.h"
19 #include "wine/obj_storage.h"
20 #include "wine/obj_moniker.h"
22 /******************************************************************************
23 * These are static/global variables and internal data structures that the
24 * OLE module uses to maintain it's state.
26 typedef struct tagDropTargetNode
29 IDropTarget
* dropTarget
;
30 struct tagDropTargetNode
* prevDropTarget
;
31 struct tagDropTargetNode
* nextDropTarget
;
34 typedef struct tagTrackerWindowInfo
36 IDataObject
* dataObject
;
37 IDropSource
* dropSource
;
44 HWND curDragTargetHWND
;
45 IDropTarget
* curDragTarget
;
49 * This is the lock count on the OLE library. It is controlled by the
50 * OLEInitialize/OLEUninitialize methods.
52 static ULONG OLE_moduleLockCount
= 0;
55 * Name of our registered window class.
57 static const char OLEDD_DRAGTRACKERCLASS
[] = "WineDragDropTracker32";
60 * This is the head of the Drop target container.
62 static DropTargetNode
* targetListHead
= NULL
;
64 /******************************************************************************
65 * These are the prototypes of the utility methods used for OLE Drag n Drop
67 static void OLEDD_Initialize();
68 static void OLEDD_UnInitialize();
69 static void OLEDD_InsertDropTarget(
70 DropTargetNode
* nodeToAdd
);
71 static DropTargetNode
* OLEDD_ExtractDropTarget(
73 static DropTargetNode
* OLEDD_FindDropTarget(
75 static LRESULT WINAPI
OLEDD_DragTrackerWindowProc(
80 static void OLEDD_TrackMouseMove(
81 TrackerWindowInfo
* trackerInfo
,
84 static void OLEDD_TrackStateChange(
85 TrackerWindowInfo
* trackerInfo
,
88 static DWORD
OLEDD_GetButtonState();
91 /******************************************************************************
92 * OleBuildVersion [OLE2.1]
94 DWORD WINAPI
OleBuildVersion(void)
96 TRACE(ole
,"(void)\n");
100 /***********************************************************************
101 * OleInitialize (OLE2.2) (OLE32.108)
103 HRESULT WINAPI
OleInitialize(LPVOID reserved
)
107 TRACE(ole
, "(%p)\n", reserved
);
110 * The first duty of the OleInitialize is to initialize the COM libraries.
112 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
115 * If the CoInitializeEx call failed, the OLE libraries can't be
122 * Then, it has to initialize the OLE specific modules.
126 * Object linking and Embedding
127 * In-place activation
129 if (OLE_moduleLockCount
==0)
132 * Initialize the libraries.
134 TRACE(ole
, "() - Initializing the OLE libraries\n");
143 * Then, we increase the lock count on the OLE module.
145 OLE_moduleLockCount
++;
150 /******************************************************************************
151 * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108]
154 * Is DWORD really the correct return type for this function?
156 DWORD WINAPI
CoGetCurrentProcess(void) {
157 return (DWORD
)PROCESS_Current();
160 /******************************************************************************
161 * OleUninitialize [OLE2.3] [OLE32.131]
163 void WINAPI
OleUninitialize(void)
168 * Decrease the lock count on the OLE module.
170 OLE_moduleLockCount
--;
173 * If we hit the bottom of the lock stack, free the libraries.
175 if (OLE_moduleLockCount
==0)
178 * Actually free the libraries.
180 TRACE(ole
, "() - Freeing the last reference count\n");
185 OLEDD_UnInitialize();
189 * Then, uninitialize the COM libraries.
194 /***********************************************************************
195 * OleFlushClipboard [OLE2.76]
197 HRESULT WINAPI
OleFlushClipboard16(void)
202 /***********************************************************************
203 * OleSetClipboard [OLE32.127]
205 HRESULT WINAPI
OleSetClipboard(LPVOID pDataObj
)
207 FIXME(ole
,"(%p), stub!\n", pDataObj
);
211 /******************************************************************************
212 * CoRegisterMessageFilter32 [OLE32.38]
214 HRESULT WINAPI
CoRegisterMessageFilter(
215 LPMESSAGEFILTER lpMessageFilter
, /* Pointer to interface */
216 LPMESSAGEFILTER
*lplpMessageFilter
/* Indirect pointer to prior instance if non-NULL */
219 if (lplpMessageFilter
) {
220 *lplpMessageFilter
= NULL
;
225 /******************************************************************************
226 * OleInitializeWOW [OLE32.109]
228 HRESULT WINAPI
OleInitializeWOW(DWORD x
) {
229 FIXME(ole
,"(0x%08lx),stub!\n",x
);
233 /***********************************************************************
234 * RegisterDragDrop16 (OLE2.35)
236 HRESULT WINAPI
RegisterDragDrop16(
238 LPDROPTARGET pDropTarget
240 FIXME(ole
,"(0x%04x,%p),stub!\n",hwnd
,pDropTarget
);
244 /***********************************************************************
245 * RegisterDragDrop32 (OLE32.139)
247 HRESULT WINAPI
RegisterDragDrop(
249 LPDROPTARGET pDropTarget
)
251 DropTargetNode
* dropTargetInfo
;
253 TRACE(ole
,"(0x%x,%p)\n", hwnd
, pDropTarget
);
256 * First, check if the window is already registered.
258 dropTargetInfo
= OLEDD_FindDropTarget(hwnd
);
260 if (dropTargetInfo
!=NULL
)
261 return DRAGDROP_E_ALREADYREGISTERED
;
264 * If it's not there, we can add it. We first create a node for it.
266 dropTargetInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode
));
268 if (dropTargetInfo
==NULL
)
269 return E_OUTOFMEMORY
;
271 dropTargetInfo
->hwndTarget
= hwnd
;
272 dropTargetInfo
->prevDropTarget
= NULL
;
273 dropTargetInfo
->nextDropTarget
= NULL
;
276 * Don't forget that this is an interface pointer, need to nail it down since
277 * we keep a copy of it.
279 dropTargetInfo
->dropTarget
= pDropTarget
;
280 IDropTarget_AddRef(dropTargetInfo
->dropTarget
);
282 OLEDD_InsertDropTarget(dropTargetInfo
);
287 /***********************************************************************
288 * RevokeDragDrop16 (OLE2.36)
290 HRESULT WINAPI
RevokeDragDrop16(
293 FIXME(ole
,"(0x%04x),stub!\n",hwnd
);
297 /***********************************************************************
298 * RevokeDragDrop32 (OLE32.141)
300 HRESULT WINAPI
RevokeDragDrop(
303 DropTargetNode
* dropTargetInfo
;
305 TRACE(ole
,"(0x%x)\n", hwnd
);
308 * First, check if the window is already registered.
310 dropTargetInfo
= OLEDD_ExtractDropTarget(hwnd
);
313 * If it ain't in there, it's an error.
315 if (dropTargetInfo
==NULL
)
316 return DRAGDROP_E_NOTREGISTERED
;
319 * If it's in there, clean-up it's used memory and
322 IDropTarget_Release(dropTargetInfo
->dropTarget
);
323 HeapFree(GetProcessHeap(), 0, dropTargetInfo
);
328 /***********************************************************************
329 * OleRegGetUserType (OLE32.122)
331 HRESULT WINAPI
OleRegGetUserType(
334 LPOLESTR
* pszUserType
)
336 FIXME(ole
,",stub!\n");
340 /***********************************************************************
341 * DoDragDrop32 [OLE32.65]
343 HRESULT WINAPI
DoDragDrop (
344 IDataObject
*pDataObject
, /* ptr to the data obj */
345 IDropSource
* pDropSource
, /* ptr to the source obj */
346 DWORD dwOKEffect
, /* effects allowed by the source */
347 DWORD
*pdwEffect
) /* ptr to effects of the source */
349 TrackerWindowInfo trackerInfo
;
350 HWND hwndTrackWindow
;
353 TRACE(ole
,"(DataObject %p, DropSource %p)\n", pDataObject
, pDropSource
);
356 * Setup the drag n drop tracking window.
358 trackerInfo
.dataObject
= pDataObject
;
359 trackerInfo
.dropSource
= pDropSource
;
360 trackerInfo
.dwOKEffect
= dwOKEffect
;
361 trackerInfo
.pdwEffect
= pdwEffect
;
362 trackerInfo
.trackingDone
= FALSE
;
363 trackerInfo
.escPressed
= FALSE
;
364 trackerInfo
.curDragTargetHWND
= 0;
365 trackerInfo
.curDragTarget
= 0;
367 hwndTrackWindow
= CreateWindowA(OLEDD_DRAGTRACKERCLASS
,
370 CW_USEDEFAULT
, CW_USEDEFAULT
,
371 CW_USEDEFAULT
, CW_USEDEFAULT
,
375 (LPVOID
)&trackerInfo
);
377 if (hwndTrackWindow
!=0)
380 * Capture the mouse input
382 SetCapture(hwndTrackWindow
);
385 * Pump messages. All mouse input should go the the capture window.
387 while (!trackerInfo
.trackingDone
&& GetMessageA(&msg
, 0, 0, 0) )
389 if ( (msg
.message
>= WM_KEYFIRST
) &&
390 (msg
.message
<= WM_KEYFIRST
) )
393 * When keyboard messages are sent to windows on this thread, we
394 * want to ignore notify the drop source that the state changed.
395 * in the case of the Escape key, we also notify the drop source
396 * we give it a special meaning.
398 if ( (msg
.message
==WM_KEYDOWN
) &&
399 (msg
.wParam
==VK_ESCAPE
) )
401 trackerInfo
.escPressed
= TRUE
;
405 * Notify the drop source.
407 OLEDD_TrackStateChange(&trackerInfo
,
409 OLEDD_GetButtonState());
414 * Dispatch the messages only when it's not a keyboard message.
416 DispatchMessageA(&msg
);
421 * Destroy the temporary window.
423 DestroyWindow(hwndTrackWindow
);
425 return trackerInfo
.returnValue
;
431 /***********************************************************************
432 * OleQueryLinkFromData32 [OLE32.118]
434 HRESULT WINAPI
OleQueryLinkFromData32(
435 IDataObject
* pSrcDataObject
)
437 FIXME(ole
,"(%p),stub!\n", pSrcDataObject
);
441 /***********************************************************************
442 * OleRegGetMiscStatus32 [OLE32.121]
444 HRESULT WINAPI
OleRegGetMiscStatus32(
449 FIXME(ole
,"(),stub!\n");
450 return REGDB_E_CLASSNOTREG
;
453 /***********************************************************************
454 * OleGetClipboard32 [OLE32.105]
456 HRESULT WINAPI
OleGetClipboard32(
457 IDataObject
** ppDataObj
)
459 FIXME(ole
,"(%p),stub!\n", ppDataObj
);
467 /***********************************************************************
468 * OleCreateMenuDescriptor [OLE32.97]
470 HOLEMENU WINAPI
OleCreateMenuDescriptor(
472 LPOLEMENUGROUPWIDTHS lpMenuWidths
)
474 FIXME(ole
,"(%x,%p),stub!\n", hmenuCombined
, lpMenuWidths
);
479 /***********************************************************************
480 * OleDestroyMenuDescriptor [OLE32.99]
482 void WINAPI
OleDestroyMenuDescriptor(
483 HOLEMENU hmenuDescriptor
)
485 FIXME(ole
,"(%x),stub!\n", (unsigned int)hmenuDescriptor
);
488 /***********************************************************************
489 * OleSetMenuDescriptor [OLE32.129]
491 HRESULT WINAPI
OleSetMenuDescriptor(
492 HOLEMENU hmenuDescriptor
,
494 HWND hwndActiveObject
,
495 LPOLEINPLACEFRAME lpFrame
,
496 LPOLEINPLACEACTIVEOBJECT lpActiveObject
)
498 FIXME(ole
,"(%x, %x, %x, %p, %p),stub!\n",
499 (unsigned int)hmenuDescriptor
,
511 * Initializes the OLE drag and drop data structures.
513 static void OLEDD_Initialize()
517 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
518 wndClass
.style
= CS_GLOBALCLASS
;
519 wndClass
.lpfnWndProc
= (WNDPROC
)OLEDD_DragTrackerWindowProc
;
520 wndClass
.cbClsExtra
= 0;
521 wndClass
.cbWndExtra
= sizeof(TrackerWindowInfo
*);
522 wndClass
.hCursor
= 0;
523 wndClass
.hbrBackground
= 0;
524 wndClass
.lpszClassName
= OLEDD_DRAGTRACKERCLASS
;
526 RegisterClassA (&wndClass
);
530 * OLEDD_UnInitialize()
532 * Releases the OLE drag and drop data structures.
534 static void OLEDD_UnInitialize()
537 * Simply empty the list.
539 while (targetListHead
!=NULL
)
541 RevokeDragDrop(targetListHead
->hwndTarget
);
546 * OLEDD_InsertDropTarget()
548 * Insert the target node in the tree.
550 static void OLEDD_InsertDropTarget(DropTargetNode
* nodeToAdd
)
552 DropTargetNode
* curNode
;
553 DropTargetNode
** parentNodeLink
;
556 * Iterate the tree to find the insertion point.
558 curNode
= targetListHead
;
559 parentNodeLink
= &targetListHead
;
561 while (curNode
!=NULL
)
563 if (nodeToAdd
->hwndTarget
<curNode
->hwndTarget
)
566 * If the node we want to add has a smaller HWND, go left
568 parentNodeLink
= &curNode
->prevDropTarget
;
569 curNode
= curNode
->prevDropTarget
;
571 else if (nodeToAdd
->hwndTarget
>curNode
->hwndTarget
)
574 * If the node we want to add has a larger HWND, go right
576 parentNodeLink
= &curNode
->nextDropTarget
;
577 curNode
= curNode
->nextDropTarget
;
582 * The item was found in the list. It shouldn't have been there
590 * If we get here, we have found a spot for our item. The parentNodeLink
591 * pointer points to the pointer that we have to modify.
592 * The curNode should be NULL. We just have to establish the link and Voila!
594 assert(curNode
==NULL
);
595 assert(parentNodeLink
!=NULL
);
596 assert(*parentNodeLink
==NULL
);
598 *parentNodeLink
=nodeToAdd
;
602 * OLEDD_ExtractDropTarget()
604 * Removes the target node from the tree.
606 static DropTargetNode
* OLEDD_ExtractDropTarget(HWND hwndOfTarget
)
608 DropTargetNode
* curNode
;
609 DropTargetNode
** parentNodeLink
;
612 * Iterate the tree to find the insertion point.
614 curNode
= targetListHead
;
615 parentNodeLink
= &targetListHead
;
617 while (curNode
!=NULL
)
619 if (hwndOfTarget
<curNode
->hwndTarget
)
622 * If the node we want to add has a smaller HWND, go left
624 parentNodeLink
= &curNode
->prevDropTarget
;
625 curNode
= curNode
->prevDropTarget
;
627 else if (hwndOfTarget
>curNode
->hwndTarget
)
630 * If the node we want to add has a larger HWND, go right
632 parentNodeLink
= &curNode
->nextDropTarget
;
633 curNode
= curNode
->nextDropTarget
;
638 * The item was found in the list. Detach it from it's parent and
639 * re-insert it's kids in the tree.
641 assert(parentNodeLink
!=NULL
);
642 assert(*parentNodeLink
==curNode
);
645 * We arbitrately re-attach the left sub-tree to the parent.
647 *parentNodeLink
= curNode
->prevDropTarget
;
650 * And we re-insert the right subtree
652 if (curNode
->nextDropTarget
!=NULL
)
654 OLEDD_InsertDropTarget(curNode
->nextDropTarget
);
658 * The node we found is still a valid node once we complete
659 * the unlinking of the kids.
661 curNode
->nextDropTarget
=NULL
;
662 curNode
->prevDropTarget
=NULL
;
669 * If we get here, the node is not in the tree
675 * OLEDD_FindDropTarget()
677 * Finds information about the drop target.
679 static DropTargetNode
* OLEDD_FindDropTarget(HWND hwndOfTarget
)
681 DropTargetNode
* curNode
;
684 * Iterate the tree to find the HWND value.
686 curNode
= targetListHead
;
688 while (curNode
!=NULL
)
690 if (hwndOfTarget
<curNode
->hwndTarget
)
693 * If the node we want to add has a smaller HWND, go left
695 curNode
= curNode
->prevDropTarget
;
697 else if (hwndOfTarget
>curNode
->hwndTarget
)
700 * If the node we want to add has a larger HWND, go right
702 curNode
= curNode
->nextDropTarget
;
707 * The item was found in the list.
714 * If we get here, the item is not in the list
720 * OLEDD_DragTrackerWindowProc()
722 * This method is the WindowProcedure of the drag n drop tracking
723 * window. During a drag n Drop operation, an invisible window is created
724 * to receive the user input and act upon it. This procedure is in charge
727 static LRESULT WINAPI
OLEDD_DragTrackerWindowProc(
737 LPCREATESTRUCTA createStruct
= (LPCREATESTRUCTA
)lParam
;
739 SetWindowLongA(hwnd
, 0, (LONG
)createStruct
->lpCreateParams
);
746 TrackerWindowInfo
* trackerInfo
= (TrackerWindowInfo
*)GetWindowLongA(hwnd
, 0);
750 * Get the current mouse position in screen coordinates.
752 mousePos
.x
= LOWORD(lParam
);
753 mousePos
.y
= HIWORD(lParam
);
754 ClientToScreen(hwnd
, &mousePos
);
757 * Track the movement of the mouse.
759 OLEDD_TrackMouseMove(trackerInfo
, mousePos
, wParam
);
770 TrackerWindowInfo
* trackerInfo
= (TrackerWindowInfo
*)GetWindowLongA(hwnd
, 0);
774 * Get the current mouse position in screen coordinates.
776 mousePos
.x
= LOWORD(lParam
);
777 mousePos
.y
= HIWORD(lParam
);
778 ClientToScreen(hwnd
, &mousePos
);
781 * Notify everyone that the button state changed
782 * TODO: Check if the "escape" key was pressed.
784 OLEDD_TrackStateChange(trackerInfo
, mousePos
, wParam
);
791 * This is a window proc after all. Let's call the default.
793 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
797 * OLEDD_TrackMouseMove()
799 * This method is invoked while a drag and drop operation is in effect.
800 * it will generate the appropriate callbacks in the drop source
801 * and drop target. It will also provide the expected feedback to
805 * trackerInfo - Pointer to the structure identifying the
806 * drag & drop operation that is currently
808 * mousePos - Current position of the mouse in screen
810 * keyState - Contains the state of the shift keys and the
811 * mouse buttons (MK_LBUTTON and the like)
813 static void OLEDD_TrackMouseMove(
814 TrackerWindowInfo
* trackerInfo
,
818 HWND hwndNewTarget
= 0;
822 * Get the handle of the window under the mouse
824 hwndNewTarget
= WindowFromPoint(mousePos
);
827 * If we are hovering over the same target as before, send the
828 * DragOver notification
830 if ( (trackerInfo
->curDragTarget
!= 0) &&
831 (trackerInfo
->curDragTargetHWND
==hwndNewTarget
) )
833 POINTL mousePosParam
;
836 * The documentation tells me that the coordinate should be in the target
837 * window's coordinate space. However, the tests I made tell me the
838 * coordinates should be in screen coordinates.
840 mousePosParam
.x
= mousePos
.x
;
841 mousePosParam
.y
= mousePos
.y
;
843 IDropTarget_DragOver(trackerInfo
->curDragTarget
,
846 trackerInfo
->pdwEffect
);
850 DropTargetNode
* newDropTargetNode
= 0;
853 * If we changed window, we have to notify our old target and check for
856 if (trackerInfo
->curDragTarget
!=0)
858 IDropTarget_DragLeave(trackerInfo
->curDragTarget
);
862 * Make sure we're hovering over a window.
864 if (hwndNewTarget
!=0)
867 * Find-out if there is a drag target under the mouse
869 newDropTargetNode
= OLEDD_FindDropTarget(hwndNewTarget
);
871 trackerInfo
->curDragTargetHWND
= hwndNewTarget
;
872 trackerInfo
->curDragTarget
= newDropTargetNode
? newDropTargetNode
->dropTarget
: 0;
875 * If there is, notify it that we just dragged-in
877 if (trackerInfo
->curDragTarget
!=0)
879 POINTL mousePosParam
;
882 * The documentation tells me that the coordinate should be in the target
883 * window's coordinate space. However, the tests I made tell me the
884 * coordinates should be in screen coordinates.
886 mousePosParam
.x
= mousePos
.x
;
887 mousePosParam
.y
= mousePos
.y
;
889 IDropTarget_DragEnter(trackerInfo
->curDragTarget
,
890 trackerInfo
->dataObject
,
893 trackerInfo
->pdwEffect
);
899 * The mouse is not over a window so we don't track anything.
901 trackerInfo
->curDragTargetHWND
= 0;
902 trackerInfo
->curDragTarget
= 0;
907 * Now that we have done that, we have to tell the source to give
908 * us feedback on the work being done by the target. If we don't
909 * have a target, simulate no effect.
911 if (trackerInfo
->curDragTarget
==0)
913 *trackerInfo
->pdwEffect
= DROPEFFECT_NONE
;
916 hr
= IDropSource_GiveFeedback(trackerInfo
->dropSource
,
917 *trackerInfo
->pdwEffect
);
920 * When we ask for feedback from the drop source, sometimes it will
921 * do all the necessary work and sometimes it will not handle it
922 * when that's the case, we must display the standard drag and drop
925 if (hr
==DRAGDROP_S_USEDEFAULTCURSORS
)
927 if ( (*trackerInfo
->pdwEffect
& DROPEFFECT_MOVE
) ||
928 (*trackerInfo
->pdwEffect
& DROPEFFECT_COPY
) ||
929 (*trackerInfo
->pdwEffect
& DROPEFFECT_LINK
) )
931 SetCursor(LoadCursorA(0, IDC_SIZEALLA
));
935 SetCursor(LoadCursorA(0, IDC_NOA
));
941 * OLEDD_TrackStateChange()
943 * This method is invoked while a drag and drop operation is in effect.
944 * It is used to notify the drop target/drop source callbacks when
945 * the state of the keyboard or mouse button change.
948 * trackerInfo - Pointer to the structure identifying the
949 * drag & drop operation that is currently
951 * mousePos - Current position of the mouse in screen
953 * keyState - Contains the state of the shift keys and the
954 * mouse buttons (MK_LBUTTON and the like)
956 static void OLEDD_TrackStateChange(
957 TrackerWindowInfo
* trackerInfo
,
962 * Ask the drop source what to do with the operation.
964 trackerInfo
->returnValue
= IDropSource_QueryContinueDrag(
965 trackerInfo
->dropSource
,
966 trackerInfo
->escPressed
,
970 * All the return valued will stop the operation except the S_OK
973 if (trackerInfo
->returnValue
!=S_OK
)
976 * Make sure the message loop in DoDragDrop stops
978 trackerInfo
->trackingDone
= TRUE
;
981 * Release the mouse in case the drop target decides to show a popup
982 * or a menu or something.
987 * If we end-up over a target, drop the object in the target or
988 * inform the target that the operation was cancelled.
990 if (trackerInfo
->curDragTarget
!=0)
992 switch (trackerInfo
->returnValue
)
995 * If the source wants us to complete the operation, we tell
996 * the drop target that we just dropped the object in it.
998 case DRAGDROP_S_DROP
:
1000 POINTL mousePosParam
;
1003 * The documentation tells me that the coordinate should be
1004 * in the target window's coordinate space. However, the tests
1005 * I made tell me the coordinates should be in screen coordinates.
1007 mousePosParam
.x
= mousePos
.x
;
1008 mousePosParam
.y
= mousePos
.y
;
1010 IDropTarget_Drop(trackerInfo
->curDragTarget
,
1011 trackerInfo
->dataObject
,
1014 trackerInfo
->pdwEffect
);
1018 * If the source told us that we should cancel, fool the drop
1019 * target by telling it that the mouse left it's window.
1021 case DRAGDROP_S_CANCEL
:
1022 IDropTarget_DragLeave(trackerInfo
->curDragTarget
);
1030 * OLEDD_GetButtonState()
1032 * This method will use the current state of the keyboard to build
1033 * a button state mask equivalent to the one passed in the
1034 * WM_MOUSEMOVE wParam.
1036 static DWORD
OLEDD_GetButtonState()
1038 BYTE keyboardState
[256];
1041 GetKeyboardState(keyboardState
);
1043 if ( (keyboardState
[VK_SHIFT
] & 0x80) !=0)
1044 keyMask
|= MK_SHIFT
;
1046 if ( (keyboardState
[VK_CONTROL
] & 0x80) !=0)
1047 keyMask
|= MK_CONTROL
;
1049 if ( (keyboardState
[VK_LBUTTON
] & 0x80) !=0)
1050 keyMask
|= MK_LBUTTON
;
1052 if ( (keyboardState
[VK_RBUTTON
] & 0x80) !=0)
1053 keyMask
|= MK_RBUTTON
;
1055 if ( (keyboardState
[VK_MBUTTON
] & 0x80) !=0)
1056 keyMask
|= MK_MBUTTON
;