📄 win32_winproc.c
字号:
/* Copyright (c) Nate Robins, 1997. *//* 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"#include <sys/timeb.h>#if defined(_WIN32) && !defined(__CYGWIN32__)#include <mmsystem.h> /* Win32 Multimedia API header. */#endifextern unsigned __glutMenuButton;extern GLUTidleCB __glutIdleFunc;extern GLUTtimer *__glutTimerList;extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);static HMENU __glutHMenu;voidupdateWindowState(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; }}LONG WINAPI__glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ POINT point; /* Point structure. */ PAINTSTRUCT ps; /* Paint structure. */ LPMINMAXINFO minmax; /* Minimum/maximum info structure. */ GLUTwindow* window; /* GLUT window associated with message. */ GLUTmenu* menu; /* GLUT menu associated with message. */ int x, y, width, height, key; int button = -1; switch(msg) { case WM_CREATE: return 0; case WM_CLOSE: if (__glutExitFunc) { __glutExitFunc(0); } exit(0); break;#if 0 case WM_DESTROY: /* XXX NVidia's NT OpenGL can have problems closing down its OpenGL internal data structures if we just allow the process to terminate without unbinding and deleting the windows context. Apparently, DirectDraw unloads before OPENGL32.DLL in the close down sequence, but NVidia's NT OpenGL needs DirectDraw to close down its data structures. */ window = __glutGetWindow(hwnd); if (window) { if (window->ctx) { wglMakeCurrent(NULL, NULL); wglDeleteContext(window->ctx); } } return 0;#endif case WM_PAINT: window = __glutGetWindow(hwnd); if (window) { BeginPaint(hwnd, &ps); /* Must have this for some Win32 reason. */ EndPaint(hwnd, &ps); if (window->win == hwnd) { __glutPostRedisplay(window, GLUT_REPAIR_WORK); } else if (window->overlay && window->overlay->win == hwnd) { __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK); } } return 0; case WM_SYSKEYUP: case WM_KEYUP: window = __glutGetWindow(hwnd); if (!window) { break; } /* Win32 is dumb and sends these messages only to the parent window. Therefore, find out if we're in a child window and call the child windows keyboard callback if we are. */ if (window->parent) { GetCursorPos(&point); ScreenToClient(hwnd, &point); hwnd = ChildWindowFromPoint(hwnd, point); window = __glutGetWindow(hwnd); } if (window->specialUp || window->keyboardUp) { GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; switch (wParam) { /* *INDENT-OFF* */ case VK_F1: key = GLUT_KEY_F1; break; case VK_F2: key = GLUT_KEY_F2; break; case VK_F3: key = GLUT_KEY_F3; break; case VK_F4: key = GLUT_KEY_F4; break; case VK_F5: key = GLUT_KEY_F5; break; case VK_F6: key = GLUT_KEY_F6; break; case VK_F7: key = GLUT_KEY_F7; break; case VK_F8: key = GLUT_KEY_F8; break; case VK_F9: key = GLUT_KEY_F9; break; case VK_F10: key = GLUT_KEY_F10; break; case VK_F11: key = GLUT_KEY_F11; break; case VK_F12: key = GLUT_KEY_F12; break; case VK_LEFT: key = GLUT_KEY_LEFT; break; case VK_UP: key = GLUT_KEY_UP; break; case VK_RIGHT: key = GLUT_KEY_RIGHT; break; case VK_DOWN: key = GLUT_KEY_DOWN; break; case VK_PRIOR: key = GLUT_KEY_PAGE_UP; break; case VK_NEXT: key = GLUT_KEY_PAGE_DOWN; break; case VK_HOME: key = GLUT_KEY_HOME; break; case VK_END: key = GLUT_KEY_END; break; case VK_INSERT: key = GLUT_KEY_INSERT; break; case VK_DELETE: /* Delete is an ASCII character. */ if (window->keyboardUp) { window->keyboardUp((unsigned char) 127, point.x, point.y); } return 0; /* *INDENT-ON* */ default: if (window->keyboardUp) { key = MapVirtualKey(wParam, 2); /* Map to ASCII. */ if (isascii(key) && (key != 0)) { /* XXX Attempt to determine modified ASCII character is quite incomplete. Digits, symbols, CapsLock, Ctrl, and numeric keypad are all ignored. Fix this. */ if (!(__glutModifierMask & ShiftMask)) key = tolower(key); window->keyboardUp((unsigned char) key, point.x, point.y); } } __glutModifierMask = (unsigned int) ~0; return 0; } if (window->specialUp) { window->specialUp(key, point.x, point.y); } __glutModifierMask = (unsigned int) ~0; } return 0; case WM_SYSCHAR: case WM_CHAR: window = __glutGetWindow(hwnd); if (!window) { break; } /* Bit 30 of lParam is set if key already held down. If we are ignoring auto repeated key strokes for the window, bail. */ if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) { break; } /* Win32 is dumb and sends these messages only to the parent window. Therefore, find out if we're in a child window and call the child windows keyboard callback if we are. */ if (window->parent) { GetCursorPos(&point); ScreenToClient(hwnd, &point); hwnd = ChildWindowFromPoint(hwnd, point); window = __glutGetWindow(hwnd); } if (window->keyboard) { GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->keyboard((unsigned char)wParam, point.x, point.y); __glutModifierMask = (unsigned int) ~0; } return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: window = __glutGetWindow(hwnd); if (!window) { break; } /* Bit 30 of lParam is set if key already held down. If we are ignoring auto repeated key strokes for the window, bail. */ if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) { break; } /* Win32 is dumb and sends these messages only to the parent window. Therefore, find out if we're in a child window and call the child windows keyboard callback if we are. */ if (window->parent) { GetCursorPos(&point); ScreenToClient(hwnd, &point); hwnd = ChildWindowFromPoint(hwnd, point); window = __glutGetWindow(hwnd); } if (window->special) { switch (wParam) { /* *INDENT-OFF* */ /* function keys */ case VK_F1: key = GLUT_KEY_F1; break; case VK_F2: key = GLUT_KEY_F2; break; case VK_F3: key = GLUT_KEY_F3; break; case VK_F4: key = GLUT_KEY_F4; break; case VK_F5: key = GLUT_KEY_F5; break; case VK_F6: key = GLUT_KEY_F6; break; case VK_F7: key = GLUT_KEY_F7; break; case VK_F8: key = GLUT_KEY_F8; break; case VK_F9: key = GLUT_KEY_F9; break; case VK_F10: key = GLUT_KEY_F10; break; case VK_F11: key = GLUT_KEY_F11; break; case VK_F12: key = GLUT_KEY_F12; break; /* directional keys */ case VK_LEFT: key = GLUT_KEY_LEFT; break; case VK_UP: key = GLUT_KEY_UP; break; case VK_RIGHT: key = GLUT_KEY_RIGHT; break; case VK_DOWN: key = GLUT_KEY_DOWN; break; /* *INDENT-ON* */ case VK_PRIOR: /* VK_PRIOR is Win32's Page Up */ key = GLUT_KEY_PAGE_UP; break; case VK_NEXT: /* VK_NEXT is Win32's Page Down */ key = GLUT_KEY_PAGE_DOWN; break; case VK_HOME: key = GLUT_KEY_HOME; break; case VK_END: key = GLUT_KEY_END; break; case VK_INSERT: key = GLUT_KEY_INSERT; break; case VK_DELETE: goto handleDelete; default: goto defproc; } GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->special(key, point.x, point.y); __glutModifierMask = (unsigned int) ~0; } else if (window->keyboard) { /* Specially handle any keys that match ASCII values but do not generate Windows WM_SYSCHAR or WM_CHAR messages. */ switch (wParam) { case VK_DELETE: handleDelete: /* Delete is an ASCII character. */ GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->keyboard((unsigned char) 127, point.x, point.y); __glutModifierMask = (unsigned int) ~0; return 0; default: /* Let the following WM_SYSCHAR or WM_CHAR message generate the keyboard callback. */ break; } } return 0; case WM_LBUTTONDOWN: button = GLUT_LEFT_BUTTON; case WM_MBUTTONDOWN: if (button < 0) button = GLUT_MIDDLE_BUTTON; case WM_RBUTTONDOWN: if (button < 0) button = GLUT_RIGHT_BUTTON; /* finish the menu if we get a button down message (user must have cancelled the menu). */ if (__glutMappedMenu) { /* TODO: take this out once the menu on middle mouse stuff works properly. */ if (button == GLUT_MIDDLE_BUTTON) return 0; GetCursorPos(&point); ScreenToClient(hwnd, &point); __glutItemSelected = NULL; __glutFinishMenu(hwnd, point.x, point.y); return 0; } /* set the capture so we can get mouse events outside the window */ SetCapture(hwnd); /* Win32 doesn't return the same numbers as X does when the mouse goes beyond the upper or left side of the window. roll the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */ x = LOWORD(lParam); y = HIWORD(lParam); if(x & 1 << 15) x -= (1 << 16); if(y & 1 << 15) y -= (1 << 16); window = __glutGetWindow(hwnd); if (window) { menu = __glutGetMenuByNum(window->menu[button]); if (menu) { point.x = LOWORD(lParam); point.y = HIWORD(lParam); 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) { __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on. */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->mouse(button, GLUT_DOWN, x, y); __glutModifierMask = (unsigned int)~0; } else { /* Stray mouse events. Ignore. */ } } return 0; case WM_LBUTTONUP: button = GLUT_LEFT_BUTTON; case WM_MBUTTONUP: if (button < 0) button = GLUT_MIDDLE_BUTTON; case WM_RBUTTONUP: if (button < 0) button = GLUT_RIGHT_BUTTON; /* Bail out if we're processing a menu. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -