win32_winproc.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:19k
- /* Copyright (c) Nate Robins, 1997, 2001. */
- /* portions Copyright (c) Mark Kilgard, 1997, 1998. */
- /*
- This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
- implied. This program is -not- in the public domain.
- */
- #include "glutint.h"
- #if defined(__CYGWIN32__)
- typedef MINMAXINFO* LPMINMAXINFO;
- #else
- #include <sys/timeb.h>
- #endif
- #ifdef _WIN32
- #include <assert.h>
- #include <crtdbg.h>
- #include <windowsx.h>
- #include <mmsystem.h> /* Win32 Multimedia API header. */
- #endif
- extern unsigned __glutMenuButton;
- extern GLUTidleCB __glutIdleFunc;
- extern GLUTtimer *__glutTimerList;
- extern void handleTimeouts(void);
- extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
- static HMENU __glutHMenu;
- static int __glutOnCreate( HWND hwnd, LPCREATESTRUCT createStruct )
- {
- return TRUE;
- }
- static void __glutOnClose( HWND hwnd )
- {
- if ( __glutExitFunc )
- {
- __glutExitFunc( 0 );
- }
-
- DestroyWindow( hwnd );
- }
- static void __glutOnDestroy( HWND hwnd )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- if ( window->ctx )
- {
- wglMakeCurrent( NULL, NULL );
- wglDeleteContext( window->ctx );
- }
- }
- }
- static void __glutOnPaint( HWND hwnd )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
-
- PAINTSTRUCT ps;
- BeginPaint( hwnd, &ps );
- EndPaint( hwnd, &ps );
-
- if ( window )
- {
- if ( window->win == hwnd )
- {
- __glutPostRedisplay(window, GLUT_REPAIR_WORK);
- }
- }
- }
- static void __glutOnSize( HWND hwnd, UINT state, int width, int height )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- if ( window->width != width || window->height != height )
- {
- window->width = width;
- window->height = height;
-
- __glutSetWindow( window );
-
- /* Do not execute OpenGL out of sequence with respect to the
- SetWindowPos request! */
- GdiFlush();
-
- window->reshape( width, height );
- window->forceReshape = FALSE;
-
- /* A reshape should be considered like posting a repair request. */
- __glutPostRedisplay( window, GLUT_REPAIR_WORK );
- }
- }
- }
- static void updateWindowState( GLUTwindow *window, int visState )
- {
- GLUTwindow* child;
-
- /* XXX shownState and visState are the same in Win32. */
- window->shownState = visState;
- if ( visState != window->visState )
- {
- if ( window->windowStatus )
- {
- window->visState = visState;
- __glutSetWindow( window );
- window->windowStatus( visState );
- }
- }
- /* Since Win32 only sends an activate for the toplevel window,
- update the visibility for all the child windows. */
- child = window->children;
- while ( child )
- {
- updateWindowState( child, visState );
- child = child->siblings;
- }
- }
- static void __glutOnActivate( HWND hwnd, UINT state, HWND hWndPrev, BOOL minimized )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- int visState = ! minimized;
- updateWindowState( window, visState );
- }
-
- /* Just in case there is a palette, make sure we re-select it if the
- window is being activated. */
- if ( state != WA_INACTIVE )
- {
- PostMessage( hwnd, WM_PALETTECHANGED, 0, 0 );
- }
- }
- static void __glutOnSetFocus( HWND hwnd, HWND hwndOldFocus )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- window->entryState = WM_SETFOCUS;
- if ( window->entry )
- {
- __glutSetWindow( window );
- window->entry( GLUT_ENTERED );
- /* XXX Generation of fake passive notify? See how much
- work the X11 code does to support fake passive notify
- callbacks. */
- }
-
- if ( window->joystick && __glutCurrentWindow )
- {
- if ( __glutCurrentWindow->joyPollInterval > 0 )
- {
- /* Because Win32 will only let one window capture the
- joystick at a time, we must capture it when we get the
- focus and release it when we lose the focus. */
- MMRESULT result = joySetCapture( __glutCurrentWindow->win, JOYSTICKID1, 0, TRUE );
- if ( result == JOYERR_NOERROR )
- {
- joySetThreshold( JOYSTICKID1, __glutCurrentWindow->joyPollInterval );
- }
- }
- }
- }
- }
- static void __glutOnKillFocus( HWND hwnd, HWND hwndNewFocus )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- window->entryState = WM_KILLFOCUS;
- if ( window->entry )
- {
- __glutSetWindow( window );
- window->entry( GLUT_LEFT );
- }
-
- if ( window->joystick && __glutCurrentWindow )
- {
- if ( __glutCurrentWindow->joyPollInterval > 0 )
- {
- joyReleaseCapture( JOYSTICKID1 );
- }
- }
- }
- }
- static void __glutOnGetMinMaxInfo( HWND hwnd, LPMINMAXINFO mmi )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- RECT r;
-
- /* set it to as small as possible, although it doesn't seem to allow
- the decorations to be munged. */
- r.top = 0;
- r.left = 0;
- r.bottom = 1;
- r.right = 1;
-
- /* get window coordinates from the client coordinates. */
- AdjustWindowRect( &r, GetWindowLong( hwnd, GWL_STYLE ), FALSE );
- mmi->ptMinTrackSize.x = r.right - r.left;
- mmi->ptMinTrackSize.y = r.bottom - r.top;
- mmi->ptMaxTrackSize.x = __glutScreenWidth;
- mmi->ptMaxTrackSize.y = __glutScreenHeight;
- }
- }
- static GLUTwindow* getWindowUnderCursor( HWND hwndParent, GLUTwindow* windowParent )
- {
- /* It seems that some messages are sent to the parent window only. Since
- GLUT wants to send information to the "current" window, descend the
- heirarchy until the window with the cursor in it is found. */
-
- assert( windowParent );
-
- if ( windowParent->children )
- {
- HWND hwndChild;
-
- POINT p;
- GetCursorPos( &p );
- ScreenToClient( hwndParent, &p );
-
- hwndChild = ChildWindowFromPoint( hwndParent, p );
- if ( hwndChild && hwndChild != hwndParent )
- {
- GLUTwindow* windowChild = __glutGetWindow( hwndChild );
- if ( windowChild )
- {
- windowParent = getWindowUnderCursor( hwndChild, windowChild );
- }
- }
- }
-
- return windowParent;
- }
- static unsigned int getModifierMask( void )
- {
- unsigned int mask = 0;
-
- if ( ( GetKeyState( VK_SHIFT ) & 0xFF00 ) )
- {
- mask |= ShiftMask;
- }
- if ( ( GetKeyState( VK_CONTROL ) & 0xFF00 ) )
- {
- mask |= ControlMask;
- }
- if ( ( GetKeyState( VK_MENU ) & 0xFF00 ) )
- {
- mask |= Mod1Mask;
- }
-
- return mask;
- }
- static int vkToSpecial( UINT vk )
- {
- switch ( vk )
- {
- case VK_F1: return -GLUT_KEY_F1;
- case VK_F2: return -GLUT_KEY_F2;
- case VK_F3: return -GLUT_KEY_F3;
- case VK_F4: return -GLUT_KEY_F4;
- case VK_F5: return -GLUT_KEY_F5;
- case VK_F6: return -GLUT_KEY_F6;
- case VK_F7: return -GLUT_KEY_F7;
- case VK_F8: return -GLUT_KEY_F8;
- case VK_F9: return -GLUT_KEY_F9;
- case VK_F10: return -GLUT_KEY_F10;
- case VK_F11: return -GLUT_KEY_F11;
- case VK_F12: return -GLUT_KEY_F12;
- case VK_LEFT: return -GLUT_KEY_LEFT;
- case VK_UP: return -GLUT_KEY_UP;
- case VK_RIGHT: return -GLUT_KEY_RIGHT;
- case VK_DOWN: return -GLUT_KEY_DOWN;
- case VK_PRIOR: return -GLUT_KEY_PAGE_UP;
- case VK_NEXT: return -GLUT_KEY_PAGE_DOWN;
- case VK_HOME: return -GLUT_KEY_HOME;
- case VK_END: return -GLUT_KEY_END;
- case VK_INSERT: return -GLUT_KEY_INSERT;
- default: return 0;
- }
- }
- static int getKey( UINT vk )
- {
- BYTE keyState[ 256 ];
- WORD c[ 2 ];
-
- GetKeyboardState( keyState );
-
- if ( ToAscii( vk, 0, keyState, c, 0 ) == 1 )
- {
- return c[ 0 ];
- }
- else
- {
- if ( vk == VK_DELETE )
- {
- return 127; /* 127 = DEL in ascii */
- }
- else
- {
- return vkToSpecial( vk );
- }
- }
- }
- static void __glutOnKey( HWND hwnd, UINT vk, BOOL down, int repeats, UINT flags )
- {
- int key;
- POINT point;
-
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- window = getWindowUnderCursor( hwnd, window );
-
- /* If we are ignoring auto repeated key strokes for the window,
- and this keystroke is an autorepeat generated one, bail. */
- if ( down )
- {
- BOOL autorepeat = ( ( flags >> 14 ) & 0x1 ) == 1;
-
- if ( window->ignoreKeyRepeat && autorepeat )
- {
- return;
- }
- }
-
- GetCursorPos( &point );
- ScreenToClient( window->win, &point );
-
- __glutModifierMask = getModifierMask();
-
- key = getKey( vk );
- if ( key < 0 )
- {
- /* special */
-
- if ( down )
- {
- if ( window->special )
- {
- __glutSetWindow( window );
- window->special( -key, point.x, point.y );
- }
- }
- else
- {
- if ( window->specialUp )
- {
- __glutSetWindow( window );
- window->specialUp( -key, point.x, point.y );
- }
- }
- }
- else if ( key > 0 )
- {
- /* ascii */
-
- if ( down )
- {
- if ( window->keyboard )
- {
- __glutSetWindow( window );
- window->keyboard( ( unsigned char )key, point.x, point.y );
- }
- }
- else
- {
- if ( window->keyboardUp )
- {
- __glutSetWindow( window );
- window->keyboardUp( ( unsigned char )key, point.x, point.y );
- }
- }
- }
-
- __glutModifierMask = ( unsigned int )~0;
- }
- }
- static void __glutOnButtonDn( HWND hwnd, int x, int y, int button )
- {
- GLUTmenu* menu;
- GLUTwindow* window = __glutGetWindow( hwnd );
-
- // !!! - look at this more closely sometime
- // !!! - look at this more closely sometime
- // !!! - look at this more closely sometime
-
- /* finish the menu if we get a button down message (user must have
- cancelled the menu). */
- if ( __glutMappedMenu )
- {
- POINT point;
-
- /* TODO: take this out once the menu on middle mouse stuff works
- properly. */
- if (button == GLUT_MIDDLE_BUTTON)
- return;
- GetCursorPos(&point);
- ScreenToClient(hwnd, &point);
- __glutItemSelected = NULL;
- __glutFinishMenu(hwnd, point.x, point.y);
- return;
- }
-
- // !!!
- // !!!
- // !!!
-
- /* Set the capture so we can get mouse events outside the window. */
- SetCapture( hwnd );
-
- if ( window )
- {
- menu = __glutGetMenuByNum( window->menu[ button ] );
- if ( menu )
- {
- POINT point;
- point.x = x; point.y = y;
- ClientToScreen(window->win, &point);
- __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
- button == GLUT_LEFT_BUTTON ? TPM_LEFTBUTTON :
- 0x0001;
- __glutStartMenu(menu, window, point.x, point.y, x, y);
- }
- else if ( window->mouse )
- {
- __glutModifierMask = getModifierMask();
-
- __glutSetWindow( window );
- window->mouse( button, GLUT_DOWN, x, y );
-
- __glutModifierMask = ( unsigned int )~0;
- }
- }
- }
- static void __glutOnButtonUp( HWND hwnd, int x, int y, int button )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
-
- // !!! - look at this more closely sometime
- // !!! - look at this more closely sometime
- // !!! - look at this more closely sometime
-
- /* Bail out if we're processing a menu. */
- if (__glutMappedMenu) {
- POINT point;
- GetCursorPos(&point);
- ScreenToClient(hwnd, &point);
- /* if we're getting the middle button up signal, then something
- on the menu was selected. */
- if (button == GLUT_MIDDLE_BUTTON) {
- return;
-
- /* For some reason, the code below always returns -1 even
- though the point IS IN THE ITEM! Therefore, just bail out if
- we get a middle mouse up. The user must select using the
- left mouse button. Stupid Win32. */
- #if 0
- int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
- if (item != -1)
- __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
- else
- __glutItemSelected = NULL;
- __glutFinishMenu(hwnd, point.x, point.y);
- #endif
- } else {
- __glutItemSelected = NULL;
- __glutFinishMenu(hwnd, point.x, point.y);
- }
- return;
- }
-
- // !!!
- // !!!
- // !!!
-
- /* Release the mouse capture. */
- ReleaseCapture();
-
- if ( window )
- {
- if ( window->mouse )
- {
- __glutModifierMask = getModifierMask();
-
- __glutSetWindow( window );
- window->mouse( button, GLUT_UP, x, y );
-
- __glutModifierMask = ( unsigned int )~0;
- }
- }
- }
- static void __glutOnLButtonDn( HWND hwnd, BOOL doubleClick, int x, int y, UINT flags )
- {
- __glutOnButtonDn( hwnd, x, y, GLUT_LEFT_BUTTON );
- }
- static void __glutOnRButtonDn( HWND hwnd, BOOL doubleClick, int x, int y, UINT flags )
- {
- __glutOnButtonDn( hwnd, x, y, GLUT_RIGHT_BUTTON );
- }
- static void __glutOnMButtonDn( HWND hwnd, BOOL doubleClick, int x, int y, UINT flags )
- {
- __glutOnButtonDn( hwnd, x, y, GLUT_MIDDLE_BUTTON );
- }
- static void __glutOnLButtonUp( HWND hwnd, int x, int y, UINT flags )
- {
- __glutOnButtonUp( hwnd, x, y, GLUT_LEFT_BUTTON );
- }
- static void __glutOnRButtonUp( HWND hwnd, int x, int y, UINT flags )
- {
- __glutOnButtonUp( hwnd, x, y, GLUT_RIGHT_BUTTON );
- }
- static void __glutOnMButtonUp( HWND hwnd, int x, int y, UINT flags )
- {
- __glutOnButtonUp( hwnd, x, y, GLUT_MIDDLE_BUTTON );
- }
- static void __glutOnMouseMove( HWND hwnd, int x, int y, UINT flags )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
-
- if ( __glutMappedMenu )
- {
- return;
- }
-
- if ( window )
- {
- BOOL down = ( flags & MK_LBUTTON ) || ( flags & MK_RBUTTON ) || ( flags & MK_MBUTTON );
-
- if ( window->motion && down )
- {
- __glutSetWindow( window );
- window->motion( x, y );
- }
- if ( window->passive && ! down )
- {
- __glutSetWindow( window );
- window->passive( x, y );
- }
- }
- }
- static BOOL __glutOnEnterMenuLoop( HWND hwnd )
- {
- /* KLUDGE: create a timer that fires every 100 ms when we start a
- menu so that we can still process the idle & timer events (that
- way, the timers will fire during a menu pick and so will the
- idle func. */
- SetTimer( hwnd, 'MENU', 1, NULL );
-
- return FALSE;
- }
- static BOOL __glutOnExitMenuLoop( HWND hwnd )
- {
- /* nuke the above created timer...we don't need it anymore, since
- the menu is gone now. */
- KillTimer( hwnd, 'MENU' );
-
- return FALSE;
- }
- static void __glutOnMenuSelect( HWND hwnd, HMENU hmenu, int item, HMENU hmenuPopup, UINT flags )
- {
- if ( hmenu != 0 )
- {
- __glutHMenu = hmenu;
- }
- }
- static void __glutOnCommand( HWND hwnd, int id, HWND hwndCtl, UINT codeNotify )
- {
- if ( __glutMappedMenu )
- {
- POINT point;
- #if 0
- if ( GetSubMenu( __glutHMenu, id ) )
- {
- __glutItemSelected = NULL;
- }
- else
- #endif
- {
- __glutItemSelected = __glutGetUniqueMenuItem( __glutMappedMenu, id );
- }
-
- GetCursorPos( &point );
- ScreenToClient( hwnd, &point );
-
- __glutFinishMenu( hwnd, point.x, point.y );
- }
- }
- static void __glutOnTimer( HWND hwnd, UINT id )
- {
- /* only worry about the idle function and the timeouts, since
- these are the only events we expect to process during
- processing of a menu. */
- /* we no longer process the idle functions (as outlined in the
- README), since drawing can't be done until the menu has
- finished...it's pretty lame when the animation goes on, but
- doesn't update, so you get this weird jerkiness. */
- #if 0
- if ( __glutIdleFunc )
- {
- __glutIdleFunc();
- }
- #endif
- if ( __glutTimerList )
- {
- handleTimeouts();
- }
- }
- static BOOL __glutOnSetCursor( HWND hwnd, HWND hWndCursor, UINT codeHitTest, UINT msg )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window )
- {
- __glutSetCursor( window );
- }
-
- return FALSE;
- }
- static BOOL __glutOnPalette( HWND hwnd )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window && window->colormap )
- {
- UnrealizeObject( window->colormap->cmap );
- SelectPalette( window->hdc, window->colormap->cmap, FALSE );
- RealizePalette( window->hdc );
-
- return TRUE;
- }
-
- return FALSE;
- }
- static BOOL __glutOnJoystick( HWND hwnd )
- {
- GLUTwindow* window = __glutGetWindow( hwnd );
- if ( window->joystick )
- {
- JOYINFOEX jix;
- int x, y, z;
-
- /* Because WIN32 only supports messages for X, Y, and Z
- translations, we must poll for the rest */
- jix.dwSize = sizeof( jix );
- jix.dwFlags = JOY_RETURNALL;
- joyGetPosEx( JOYSTICKID1, &jix );
-
- #define SCALE( v ) ( ( int )( ( v - 32767 ) / 32.768 ) )
-
- /* Convert to integer for scaling. */
- x = jix.dwXpos;
- y = jix.dwYpos;
- z = jix.dwZpos;
- window->joystick( jix.dwButtons, SCALE( x ), SCALE( y ), SCALE( z ) );
-
- return TRUE;
- }
-
- return FALSE;
- }
- LONG WINAPI __glutWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
- {
- switch ( msg )
- {
- case WM_CREATE: return HANDLE_WM_CREATE ( hwnd, wparam, lparam, __glutOnCreate );
- case WM_CLOSE: return HANDLE_WM_CLOSE ( hwnd, wparam, lparam, __glutOnClose );
- case WM_DESTROY: return HANDLE_WM_DESTROY ( hwnd, wparam, lparam, __glutOnDestroy );
- case WM_PAINT: return HANDLE_WM_PAINT ( hwnd, wparam, lparam, __glutOnPaint );
- case WM_SIZE: return HANDLE_WM_SIZE ( hwnd, wparam, lparam, __glutOnSize );
- case WM_ACTIVATE: return HANDLE_WM_ACTIVATE ( hwnd, wparam, lparam, __glutOnActivate );
- case WM_SETFOCUS: return HANDLE_WM_SETFOCUS ( hwnd, wparam, lparam, __glutOnSetFocus );
- case WM_KILLFOCUS: return HANDLE_WM_KILLFOCUS ( hwnd, wparam, lparam, __glutOnKillFocus );
- case WM_GETMINMAXINFO: return HANDLE_WM_GETMINMAXINFO ( hwnd, wparam, lparam, __glutOnGetMinMaxInfo );
- case WM_KEYDOWN: return HANDLE_WM_KEYDOWN ( hwnd, wparam, lparam, __glutOnKey );
- case WM_KEYUP: return HANDLE_WM_KEYUP ( hwnd, wparam, lparam, __glutOnKey );
- case WM_SYSKEYDOWN: return HANDLE_WM_KEYDOWN ( hwnd, wparam, lparam, __glutOnKey );
- case WM_SYSKEYUP: return HANDLE_WM_KEYUP ( hwnd, wparam, lparam, __glutOnKey );
- case WM_LBUTTONDOWN: return HANDLE_WM_LBUTTONDOWN ( hwnd, wparam, lparam, __glutOnLButtonDn );
- case WM_RBUTTONDOWN: return HANDLE_WM_RBUTTONDOWN ( hwnd, wparam, lparam, __glutOnRButtonDn );
- case WM_MBUTTONDOWN: return HANDLE_WM_MBUTTONDOWN ( hwnd, wparam, lparam, __glutOnMButtonDn );
- case WM_LBUTTONUP: return HANDLE_WM_LBUTTONUP ( hwnd, wparam, lparam, __glutOnLButtonUp );
- case WM_RBUTTONUP: return HANDLE_WM_RBUTTONUP ( hwnd, wparam, lparam, __glutOnRButtonUp );
- case WM_MBUTTONUP: return HANDLE_WM_MBUTTONUP ( hwnd, wparam, lparam, __glutOnMButtonUp );
- case WM_MOUSEMOVE: return HANDLE_WM_MOUSEMOVE ( hwnd, wparam, lparam, __glutOnMouseMove );
- case WM_ENTERMENULOOP: return __glutOnEnterMenuLoop( hwnd );
- case WM_EXITMENULOOP: return __glutOnExitMenuLoop( hwnd );
- case WM_COMMAND: return HANDLE_WM_COMMAND ( hwnd, wparam, lparam, __glutOnCommand );
- case WM_TIMER: return HANDLE_WM_TIMER ( hwnd, wparam, lparam, __glutOnTimer );
-
- case WM_SETCURSOR:
- if ( LOWORD( lparam ) != HTCLIENT )
- {
- /* Let the default window proc handle cursors outside the client area */
- break;
- }
- else
- {
- return HANDLE_WM_SETCURSOR( hwnd, wparam, lparam, __glutOnSetCursor );
- }
-
- case WM_PALETTECHANGED:
- if ( ( HWND )wparam == hwnd )
- {
- /* Don't respond to the message that we sent! */
- break;
- }
- /* Fall through to WM_QUERYNEWPALETTE */
-
- case WM_QUERYNEWPALETTE:
- return __glutOnPalette( hwnd );
-
- case MM_JOY1MOVE:
- case MM_JOY1ZMOVE:
- case MM_JOY1BUTTONDOWN:
- case MM_JOY1BUTTONUP:
- return __glutOnJoystick( hwnd );
-
- default:
- break;
- }
-
- return DefWindowProc( hwnd, msg, wparam, lparam );
- }