// Process Window Message Callbacks static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get The Window Context GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA)); switch (uMsg) // Evaluate Window Message { case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } return 0; case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong(hWnd, GWL_USERDATA, (LONG)(window)); } return 0; // Return case WM_CLOSE: // Closing The Window TerminateApplication(window); // Terminate The Application return 0; // Return case WM_SIZE: // Size Action Has Taken Place switch (wParam) // Evaluate Size Action { case SIZE_MINIMIZED: // Was Window Minimized? window->isVisible = FALSE; // Set isVisible To False return 0; // Return case SIZE_MAXIMIZED: // Was Window Maximized? window->isVisible = TRUE; // Set isVisible To True ReshapeGL(LOWORD(lParam), HIWORD(lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return case SIZE_RESTORED: // Was Window Restored? window->isVisible = TRUE; // Set isVisible To True ReshapeGL(LOWORD(lParam), HIWORD(lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return } break; // Break } return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }
/** 创建windows窗口 */ bool GLWindow::Create(const char * window_title,const char * class_name,bool fullscreen, HINSTANCE h_instance, LPVOID lpParam) { m_IsFullScreen = fullscreen; int nX=0; int nY=0; PIXELFORMATDESCRIPTOR pfd = /**< 设置像素描述结构 */ { sizeof(PIXELFORMATDESCRIPTOR), /**< 像素描述结构的大小 */ 1, /**< 版本号 */ PFD_DRAW_TO_WINDOW | /**< 缓存区的输出显示在一个窗口中 */ PFD_SUPPORT_OPENGL | /**< 缓存区支持OpenGL绘图 */ PFD_STEREO | /**< 颜色缓存区是立体缓存 */ PFD_DOUBLEBUFFER, /**< 颜色缓存区是双缓存 */ PFD_TYPE_RGBA, /**< 使用RGBA颜色格式 */ m_BitsPerPixel, /**< 颜色缓存区中颜色值所占的位深 */ 0, 0, 0, 0, 0, 0, /**< 使用默认的颜色设置 */ 0, /**< 无Alpha缓存 */ 0, /**< 颜色缓存区中alpha成分的移位计数 */ 0, /**< 无累计缓存区 */ 0, 0, 0, 0, /**< 累计缓存区无移位 */ 32, /**< 32位深度缓存 */ 0, /**< 无蒙版缓存 */ 0, /**< 无辅助缓存区 */ PFD_MAIN_PLANE, /**< 必须为PFD_MAIN_PLANE,设置为主绘图层 */ 0, /**< 表示OpenGL实现所支持的上层或下层平面的数量 */ 0, 0, 0 /**< 过时,已不再使用 */ }; DWORD windowStyle = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX; /**< 定义我们窗口类型,使用常规设定,去掉最大化按钮,并不能改变窗体大小 */ DWORD windowExtendedStyle = WS_EX_APPWINDOW; if (m_IsFullScreen == true) /**< 如果为全屏模式,尝试转化为全屏模式 */ { if (ChangeScreenSetting() == false) { /**< 全屏模式转换失败,弹出对话框提示,并尝试窗口模式 */ MessageBox(HWND_DESKTOP, "模式转换失败.\n在窗口模式下运行.", "Error", MB_OK | MB_ICONEXCLAMATION); m_IsFullScreen = false; /**< 设置为窗口模式 */ } else /**< 如果为窗口模式 */ { ShowCursor(false); /**< 隐藏鼠标 */ windowStyle = WS_POPUP; /**< 设置窗口模式为顶层窗口 */ windowExtendedStyle |= WS_EX_TOPMOST; } } /// 调整我们窗口的大小,使其客户区的大小为我们设置的大小 RECT windowRect = {GetPosX(), GetPosY(), GetPosX() + GetWidth(), GetPosY() + GetHeight()}; if (m_IsFullScreen == false) /**< 在窗口模式下使用 */ { windowExtendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; /**< 使窗口具有3D外观 */ int wid = GetSystemMetrics(SM_CXSCREEN); /**< 获取当前屏幕宽 */ int hei = GetSystemMetrics(SM_CYSCREEN); /**< 获取当前屏幕高 */ nX = (wid - GetWidth()) / 2; /**< 计算窗口居中用 */ nY = (hei - GetHeight()) / 2; /// 调整我们窗口的大小,使其客户区的大小为我们设置的大小 AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle); /// 判断窗口的左上角是否隐藏在桌面外 if (windowRect.left < 0) /**< 如果窗口X坐标为负,移动坐标到0处,并调整窗口的位置 */ { windowRect.right -= windowRect.left; windowRect.left = 0; } if (windowRect.top < 0) /**< 如果窗口Y坐标为负,移动坐标到0处,并调整窗口的位置 */ { windowRect.bottom -= windowRect.top; windowRect.top = 0; } } /// 创建窗口 m_hWnd = CreateWindowEx(windowExtendedStyle, /**< 窗口的扩展风格 */ class_name, /**< 窗口的类名 */ window_title, /**< 窗口标题 */ windowStyle, /**< 窗口的风格 */ nX,nY, /**< 窗口的左上角位置 */ windowRect.right - windowRect.left, /**< 窗口的宽度 */ windowRect.bottom - windowRect.top, /**< 窗口的高度 */ HWND_DESKTOP, /**< 窗口的父窗口为桌面 */ 0, /**< 无菜单 */ h_instance, /**< 传入窗口的实例句柄 */ lpParam); /**< 传入程序类参数 */ while (m_hWnd != 0) /**< 窗口是否创建成功 */ { m_hDC = GetDC(m_hWnd); /**< 返回窗口的设备描述表 */ if (m_hDC == 0) /**< 如果为空 */ { /**< 失败 */ break; } GLuint PixelFormat = ChoosePixelFormat(m_hDC, &pfd); /**< 查找一个兼容的像素格式 */ if (PixelFormat == 0) /**< 如果没找到 */ { /**< 失败 */ break; } if (SetPixelFormat(m_hDC, PixelFormat, &pfd) == false) /**< 设置像素格式 */ { /**< 失败 */ break; } m_hRC = wglCreateContext(m_hDC); /**< 创建OpenGL的渲染描述表 */ if (m_hRC == 0) /**< 如果为空 */ { /**< 失败 */ break; } if (wglMakeCurrent(m_hDC, m_hRC) == false) /**< 设置当前的OpenGL的渲染对象为当前的窗口 */ { /**< 失败 */ break; } ShowWindow(m_hWnd, SW_NORMAL); /**< 显示窗口 */ ReshapeGL(); /**< 告诉OpenGL调整窗口大小 */ return true; /**< 成功返回 */ } Destroy(); /**< 释放资源 */ return false; /**< 返回失败 */ }
BOOL CreateWindowGL (GL_Window* window) // This Code Creates Our OpenGL Window { DWORD windowStyle = WS_OVERLAPPEDWINDOW; // Define Our Window Style DWORD windowExtendedStyle = WS_EX_APPWINDOW; // Define The Window's Extended Style //Hide windows' mouse cursor //ShowCursor(FALSE); PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be { sizeof (PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format window->init.bitsPerPixel, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; RECT windowRect = {0, 0, window->init.width, window->init.height}; // Define Our Window Coordinates GLuint PixelFormat; // Will Hold The Selected Pixel Format if (window->init.isFullScreen == TRUE) // Fullscreen Requested, Try Changing Video Modes { if (ChangeScreenResolution (window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE) { // Fullscreen Mode Failed. Run In Windowed Mode Instead MessageBox (HWND_DESKTOP, "Mode Switch Failed.\nRunning In Windowed Mode.", "Error", MB_OK | MB_ICONEXCLAMATION); window->init.isFullScreen = FALSE; // Set isFullscreen To False (Windowed Mode) } else // Otherwise (If Fullscreen Mode Was Successful) { windowStyle = WS_POPUP; // Set The WindowStyle To WS_POPUP (Popup Window) windowExtendedStyle |= WS_EX_TOPMOST; // Set The Extended Window Style To WS_EX_TOPMOST } // (Top Window Covering Everything Else) } else // If Fullscreen Was Not Selected { // Adjust Window, Account For Window Borders AdjustWindowRectEx (&windowRect, windowStyle, 0, windowExtendedStyle); } // Create The OpenGL Window window->hWnd = CreateWindowEx (windowExtendedStyle, // Extended Style window->init.application->className, // Class Name window->init.title, // Window Title windowStyle, // Window Style 0, 0, // Window X,Y Position windowRect.right - windowRect.left, // Window Width windowRect.bottom - windowRect.top, // Window Height HWND_DESKTOP, // Desktop Is Window's Parent 0, // No Menu window->init.application->hInstance, // Pass The Window Instance window); if (window->hWnd == 0) // Was Window Creation A Success? { return FALSE; // If Not Return False } window->hDC = GetDC (window->hWnd); // Grab A Device Context For This Window if (window->hDC == 0) // Did We Get A Device Context? { // Failed DestroyWindow (window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } PixelFormat = ChoosePixelFormat (window->hDC, &pfd); // Find A Compatible Pixel Format if (PixelFormat == 0) // Did We Find A Compatible Format? { // Failed ReleaseDC (window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow (window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } if (SetPixelFormat (window->hDC, PixelFormat, &pfd) == FALSE) // Try To Set The Pixel Format { // Failed ReleaseDC (window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow (window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } window->hRC = wglCreateContext (window->hDC); // Try To Get A Rendering Context if (window->hRC == 0) // Did We Get A Rendering Context? { // Failed ReleaseDC (window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow (window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } // Make The Rendering Context Our Current Rendering Context if (wglMakeCurrent (window->hDC, window->hRC) == FALSE) { // Failed wglDeleteContext (window->hRC); // Delete The Rendering Context window->hRC = 0; // Zero The Rendering Context ReleaseDC (window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow (window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } ShowWindow (window->hWnd, SW_NORMAL); // Make The Window Visible window->isVisible = TRUE; // Set isVisible To True ReshapeGL (window->init.width, window->init.height); // Reshape Our GL Window ZeroMemory (window->keys, sizeof (Keys)); // Clear All Keys window->lastTickCount = GetTickCount (); // Get Tick Count return TRUE; // Window Creating Was A Success // Initialization Will Be Done In WM_CREATE }
// Process Window Message Callbacks LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get The Window Context GL_Window* window = (GL_Window*)(GetWindowLong (hWnd, GWL_USERDATA)); static UINT mouseHold = 0; switch (uMsg) // Evaluate Window Message { case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } return 0; // Return case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(window)); } return 0; // Return case WM_CLOSE: // Closing The Window TerminateApplication(window); // Terminate The Application return 0; // Return case WM_SIZE: // Size Action Has Taken Place switch (wParam) // Evaluate Size Action { case SIZE_MINIMIZED: // Was Window Minimized? window->isVisible = FALSE; // Set isVisible To False return 0; // Return case SIZE_MAXIMIZED: // Was Window Maximized? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return case SIZE_RESTORED: // Was Window Restored? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return } break; // Break case WM_KEYDOWN: // Update Keyboard Buffers For Keys Pressed if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { window->keys->keyDown [wParam] = TRUE; // Set The Selected Key (wParam) To True //if a key is pressed send it to Selection Selection ( wParam ); return 0; // Return } break; // Break case WM_KEYUP: // Update Keyboard Buffers For Keys Released if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { window->keys->keyDown [wParam] = FALSE; // Set The Selected Key (wParam) To False return 0; // Return } break; // Break case WM_TOGGLEFULLSCREEN: // Toggle FullScreen Mode On/Off g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage (hWnd, WM_QUIT, 0, 0); break; // Break case WM_LBUTTONDOWN : case WM_RBUTTONDOWN : case WM_MBUTTONDOWN : { mouse_x = LOWORD(lParam); mouse_y = HIWORD(lParam); mouseHold = uMsg; //hold down the mouse button Selection ( uMsg ); } break; case WM_LBUTTONUP : case WM_RBUTTONUP : case WM_MBUTTONUP : mouseHold = 0; //button released break; case WM_MOUSEMOVE: { mouse_x = LOWORD(lParam); mouse_y = HIWORD(lParam); if ( mouseHold ) Selection ( mouseHold ); } break; } return DefWindowProc (hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }
LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get The Window Context GL_Window* window = (GL_Window*)(GetWindowLong (hWnd, GWL_USERDATA)); switch (uMsg) // Evaluate Window Message { case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } return 0; // Return case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(window)); } return 0; // Return case WM_CLOSE: // Closing The Window TerminateApplication(window); // Terminate The Application return 0; // Return case WM_SIZE: // Size Action Has Taken Place switch (wParam) // Evaluate Size Action { case SIZE_MINIMIZED: // Was Window Minimized? window->isVisible = FALSE; // Set isVisible To False return 0; // Return case SIZE_MAXIMIZED: // Was Window Maximized? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return case SIZE_RESTORED: // Was Window Restored? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return } break; // Break case WM_KEYDOWN: // Update Keyboard Buffers For Keys Pressed if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { //if(wParam != 70){ window->keys->keyDown [wParam] = TRUE; // Set The Selected Key (wParam) To True return 0; // Return //} /*else{ LPPOINT lpPoint = new POINT; GetCursorPos(lpPoint); createSearchMenu(lpPoint,hWnd); }*/ } break; // Break case WM_KEYUP: // Update Keyboard Buffers For Keys Released if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { window->keys->keyDown [wParam] = FALSE; // Set The Selected Key (wParam) To False return 0; // Return } break; // Break case WM_MOUSEMOVE: { int x = (lParam << 16) >> 16; int y = lParam >> 16; if (ldown) // Левая кнопка { ry = (GLfloat)(y - my); //Изменение угола поворота rx = (GLfloat)(x - mx); mx=x; my=y; //rx/= 10; //ry/= 10; //ry = 0; //ry = 0; //ry = 1; if(rx) { ort1 = Vector3D::RotateVector1AroundVector2(ort1,Vector3D(0,1,0),rx); ort2 = Vector3D::RotateVector1AroundVector2(ort2,Vector3D(0,1,0),rx); ort3 = Vector3D::RotateVector1AroundVector2(ort3,Vector3D(0,1,0),rx); } if(ry) { ort1 = Vector3D::RotateVector1AroundVector2(ort1,Vector3D(1,0,0),ry); ort2 = Vector3D::RotateVector1AroundVector2(ort2,Vector3D(1,0,0),ry); ort3 = Vector3D::RotateVector1AroundVector2(ort3,Vector3D(1,0,0),ry); } //if((rx==0)&&(ry==0)) // worm->UpdateSelection(); //glutPostRedisplay(); //Перерисовать экран } if (rdown) //Правая { /*tx+=0.05f*(x-mx); //Перемещение вдоль активной плоскости if (tt) tz+=0.05f*(y-my); else ty+=0.05f*(my-y); mx=x; my=y;*/ ry = (GLfloat)(y - my); rx = (GLfloat)(x - mx); mx=x; my=y; vcenter += Vector3D(rx,-ry,0)*scale/50; /* if(rx) { ort1 = Vector3D::RotateVector1AroundVector2(ort1,Vector3D(0,1,0),rx); ort2 = Vector3D::RotateVector1AroundVector2(ort2,Vector3D(0,1,0),rx); ort3 = Vector3D::RotateVector1AroundVector2(ort3,Vector3D(0,1,0),rx); //vbeg = Vector3D::RotateVector1AroundVector2(vbeg,Vector3D(0,1,0),rx); //vend = Vector3D::RotateVector1AroundVector2(vend,Vector3D(0,1,0),rx); } if(ry) { ort1 = Vector3D::RotateVector1AroundVector2(ort1,Vector3D(1,0,0),ry); ort2 = Vector3D::RotateVector1AroundVector2(ort2,Vector3D(1,0,0),ry); ort3 = Vector3D::RotateVector1AroundVector2(ort3,Vector3D(1,0,0),ry); //vbeg = Vector3D::RotateVector1AroundVector2(vbeg,Vector3D(1,0,0),ry); //vend = Vector3D::RotateVector1AroundVector2(vend,Vector3D(1,0,0),ry); }*/ //glutPostRedisplay(); } } break; case WM_LBUTTONUP: { ldown = false; /*mx = (lParam << 16) >> 16; my = lParam >> 16;*/ } break; case WM_LBUTTONDOWN: { ldown = true; //установить флаг mx = (lParam << 16) >> 16; my = lParam >> 16; //CheckSelection(); calc_select_line(mx,my,vbeg,vend); CNeuron * cn = worm->UpdateSelection(); //Block with contextMenu /*if(cn != NULL) { LPPOINT lpPoint = new POINT; GetCursorPos(lpPoint); createMenus(lpPoint,hWnd,cn); ldown = false; } else { }*/ } break; case WM_RBUTTONUP: { rdown = false; /*mx = (lParam << 16) >> 16; my = lParam >> 16;*/ } break; case WM_RBUTTONDOWN: { rdown = true; //установить флаг mx = (lParam << 16) >> 16; my = lParam >> 16; } break; case WM_MOUSEWHEEL: { if((short)HIWORD(wParam)>0) scale*=1.05f;//"down" else scale/=1.05f;//"up" /* if(wParam == -7864320) scale*=1.1f;//"down" if(wParam == 7864320) scale/=1.1f;//"up"*/ } break; case WM_TOGGLEFULLSCREEN: // Toggle FullScreen Mode On/Off g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage (hWnd, WM_QUIT, 0, 0); break; // Break } return DefWindowProc (hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }
int main( int argc, char *argv[] ) { XEvent event; GL_Window window; Keys keys; KeySym key; struct timeval tv, tickCount; window.keys = &keys; window.init.title = "Lesson 48: NeHe & Terence J. Grant's ArcBall Rotation Tutorial"; window.init.width = 640; window.init.height = 480; window.init.depth = 32; window.init.isFullScreen = true; g_createFullScreen = window.init.isFullScreen; if( CreateWindowGL (&window) == false ) { exit(1); } initGL(&window, &keys); while( !done ) { while( XPending( window.init.dpy ) > 0 ) { XNextEvent( window.init.dpy, &event ); switch( event.type ) { case Expose: if( event.xexpose.count != 0 ) break; Draw(); break; case ConfigureNotify: if( (event.xconfigure.width != window.init.width) || (event.xconfigure.height != window.init.height) ) { window.init.width = event.xconfigure.width; window.init.height = event.xconfigure.height; ReshapeGL( window.init.width, window.init.height ); } break; case ButtonPress: switch( event.xbutton.button ) { case 1: isClicked = true; break; case 3: isRClicked = true; break; } break; case ButtonRelease: switch( event.xbutton.button ) { case 1: isClicked = false; break; case 3: isRClicked = false; break; } break; case MotionNotify: MousePt.s.X = event.xmotion.x; MousePt.s.Y = event.xmotion.y; break; case KeyPress: key = XLookupKeysym( &event.xkey, 0 ); if( key == XK_Escape ) done = true; else if( key == XK_F1 ) { DestroyWindowGL( &window ); window.init.isFullScreen = !window.init.isFullScreen; CreateWindowGL( &window ); initGL(&window, &keys); } else { window.keys->keyDown[key] = true; } break; case KeyRelease: key = XLookupKeysym( &event.xkey, 0 ); window.keys->keyDown[key] = false; break; case ClientMessage: if( *XGetAtomName( window.init.dpy, event.xclient.message_type) == *"WM_PROTOCOLS" ) { done = true; } default: break; } } gettimeofday( &tv, NULL ); tickCount.tv_sec = tv.tv_sec - window.lastTickCount.tv_sec; tickCount.tv_usec = tv.tv_usec - window.lastTickCount.tv_usec; Update(tickCount.tv_usec / 1000 + tickCount.tv_sec * 1000 ); window.lastTickCount = tickCount; Draw(); if( window.init.doubleBuffered ) glXSwapBuffers( window.init.dpy, window.init.win ); } Deinitialize (); DestroyWindowGL (&window); }
void initGL( GL_Window *window, Keys *keys ) { Initialize( window, keys ); ReshapeGL( window->init.width, window->init.height ); }
BOOL WindowFrame::CreateWindowGL (GL_Window* window) { DWORD windowStyle = WS_OVERLAPPEDWINDOW; // 设置窗口类型为一般的弹出式窗口 DWORD windowExtendedStyle = WS_EX_APPWINDOW; // 设置窗口的扩展属性 PIXELFORMATDESCRIPTOR pfd = // pfd 告诉窗口我们所希望的东东,即窗口使用的像素格式 { sizeof (PIXELFORMATDESCRIPTOR), // 上述格式描述符的大小 1, // 版本号 PFD_DRAW_TO_WINDOW | // 格式支持窗口 PFD_SUPPORT_OPENGL | // 格式必须支持OpenGL PFD_DOUBLEBUFFER, // 必须支持双缓冲 PFD_TYPE_RGBA, // 申请 RGBA 格式 window->init.bitsPerPixel, // 选定色彩深度 0, 0, 0, 0, 0, 0, // 忽略的色彩位 0, // 无Alpha缓存 0, // 忽略Shift Bit 0, // 无累加缓存 0, 0, 0, 0, // 忽略聚集位 16, // 16位 Z-缓存 (深度缓存) 0, // 无蒙板缓存 0, // 无辅助缓存 PFD_MAIN_PLANE, // 主绘图层 0, // 不使用重叠层 0, 0, 0 // 忽略层遮罩 }; RECT windowRect = {0, 0, window->init.width, window->init.height}; // 记录窗口的大小 GLuint PixelFormat; // 将保存的像素格式 if (window->isFullScreen == TRUE) // 如果为全屏模式 { if (ChangeScreenResolution (window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE) { MessageBox (HWND_DESKTOP, "模式切换失败\n在窗口模式下运行", "错误", MB_OK | MB_ICONEXCLAMATION); window->isFullScreen = FALSE; // 设置isFullscreen为False } else { ShowCursor(FALSE); // 不显示光标 windowStyle = WS_POPUP; // 设置窗口模式为弹出式窗口 windowExtendedStyle |= WS_EX_TOPMOST; // 设置窗口的扩展模式为最顶层窗口 } } else // 如果不为全屏模式 { AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle); //调整窗口大小,以容纳边框等窗口部件 } window->hWnd = CreateWindowEx(windowExtendedStyle, // 扩展窗体风格 window->init.application->className, // 类名字 window->init.title, // 窗口标题 windowStyle, // 必须的窗体风格属性 0, 0, // 窗口位置 windowRect.right - windowRect.left, // 计算调整好的窗口宽度 windowRect.bottom - windowRect.top, // 计算调整好的窗口高度 HWND_DESKTOP, // 无父窗口 0, // 无菜单 window->init.application->hInstance, // 实例 window); // 向window的WM_CREATE传递window结构 if (window->hWnd == 0) // 窗口创建是否成功 { return FALSE; // 不成功则返回 } window->hDC = GetDC (window->hWnd); // 返回设备描述表 if (window->hDC == 0) // 是否成功获得设备描述表 { DestroyWindow (window->hWnd); // 删除窗口 window->hWnd = 0; // 设置窗口句柄为0 return FALSE; // 返回失败 } PixelFormat = ChoosePixelFormat (window->hDC, &pfd); // 选择一种相容的像素格式 if (PixelFormat == 0) // 是否获得相容的像素格式 { ReleaseDC (window->hWnd, window->hDC); // 释放设备描述表 window->hDC = 0; // 设置窗口设备描述表为0 DestroyWindow (window->hWnd); // 删除窗口 window->hWnd = 0; // 设置窗口句柄为0 return FALSE; // 返回错误 } if (SetPixelFormat (window->hDC, PixelFormat, &pfd) == FALSE) // 设置像素格式 { ReleaseDC (window->hWnd, window->hDC); // 释放设备描述表 window->hDC = 0; // 设置窗口设备描述表为0 DestroyWindow (window->hWnd); // 删除窗口 window->hWnd = 0; // 设置窗口句柄为0 return FALSE; // 返回错误 } window->hRC = wglCreateContext (window->hDC); // 设置OpenGL渲染描述表 if (window->hRC == 0) // 如果没有成功创建 { ReleaseDC (window->hWnd, window->hDC); // 释放设备描述表 window->hDC = 0; // 设置窗口设备描述表为0 DestroyWindow (window->hWnd); // 删除窗口 window->hWnd = 0; // 设置窗口句柄为0 return FALSE; // 返回错误 } if (wglMakeCurrent (window->hDC, window->hRC) == FALSE) // 设置RC为当前的OpenGL的渲染描述表 { wglDeleteContext (window->hRC); // 删除当前的OpenGL渲染描述表 window->hRC = 0; // 释放设备描述表 ReleaseDC (window->hWnd, window->hDC); // 设置窗口设备描述表为0 window->hDC = 0; // 删除窗口 DestroyWindow (window->hWnd); // 设置窗口句柄为0 window->hWnd = 0; // 返回错误 return FALSE; } ShowWindow (window->hWnd, SW_NORMAL); // 显示窗口 window->isVisible = TRUE; // 设置窗口为可见 ReshapeGL (window->init.width, window->init.height); // 根据窗口大小,调整OpenGL对应的窗口大小 ZeroMemory (window->keys, sizeof (Keys)); // 初始化按键记录表 return TRUE; // 窗口创建完毕,成功返回 }
LRESULT CALLBACK WindowFrame::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // 返回创建信息 GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA)); switch (uMsg) { case WM_SYSCOMMAND: // 捕获系统消息 { switch (wParam) // 检测系统调用 { case SC_SCREENSAVE: // 如果是要运行屏保程序 case SC_MONITORPOWER: // 如果是要关闭显示器 return 0; // 截获上面的消息,不做处理 } break; } return 0; case WM_CREATE: // 窗口创建 { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // 获得创建的窗口信息 window = (GL_Window*)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(window)); } return 0; case WM_CLOSE: // 关闭窗口 TerminateApplication(window); // 结束程序 return 0; case WM_SIZE: // 改变大小 switch (wParam) { case SIZE_MINIMIZED: // 最小化 window->isVisible = FALSE; // 如果是,设窗口不可见 return 0; case SIZE_MAXIMIZED: // 最大化 window->isVisible = TRUE; // 设置窗口可见 ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // 更改OpenGL窗口的大小 return 0; case SIZE_RESTORED: // 创口是否被重新载入了 window->isVisible = TRUE; // 设置窗口可见 ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // 更改OpenGL窗口的大小 return 0; } break; case WM_KEYDOWN: // 更新按键控制 if ((wParam >= 0) && (wParam <= 255)) // 如果为键盘支持的256个字符 { window->keys->keyDown [wParam] = TRUE; // 记录那个字符被按下 return 0; } break; case WM_KEYUP: // 更新按键控制 if ((wParam >= 0) && (wParam <= 255)) { window->keys->keyDown [wParam] = FALSE; // 记录那个字符被释放 return 0; } break; case WM_TOGGLEFULLSCREEN: // 切换全拼/窗口模式 window->isFullScreen = (window->isFullScreen == TRUE)? FALSE : TRUE; PostMessage(hWnd, WM_QUIT, 0, 0); break; case WM_LBUTTONDOWN: { window->mouse.x = LOWORD(lParam); window->mouse.y = HIWORD(lParam); } break; case WM_MOUSEMOVE: { window->mouse.x = LOWORD(lParam); window->mouse.y = HIWORD(lParam); } break; } return DefWindowProc (hWnd, uMsg, wParam, lParam); }
static BOOL CreateWindowGL(GL_Window* window, int colorDepth) { PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format colorDepth, 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; if (window->hWnd == 0) // Was Window Creation A Success? { return FALSE; // If Not Return False } window->hDC = GetDC(window->hWnd); // Grab A Device Context For This Window if (window->hDC == 0) // Did We Get A Device Context? { // Failed DestroyWindow(window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } GLuint PixelFormat; // Will Hold The Selected Pixel Format PixelFormat = ChoosePixelFormat(window->hDC, &pfd); // Find A Compatible Pixel Format if (PixelFormat == 0) // Did We Find A Compatible Format? { // Failed ReleaseDC(window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow(window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } if (SetPixelFormat(window->hDC, PixelFormat, &pfd) == FALSE) // Try To Set The Pixel Format { // Failed ReleaseDC(window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow(window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } window->hRC = wglCreateContext(window->hDC); // Try To Get A Rendering Context if (window->hRC == 0) // Did We Get A Rendering Context? { // Failed ReleaseDC(window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow(window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } // Make The Rendering Context Our Current Rendering Context if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) { // Failed wglDeleteContext(window->hRC); // Delete The Rendering Context window->hRC = 0; // Zero The Rendering Context ReleaseDC(window->hWnd, window->hDC); // Release Our Device Context window->hDC = 0; // Zero The Device Context DestroyWindow(window->hWnd); // Destroy The Window window->hWnd = 0; // Zero The Window Handle return FALSE; // Return False } ShowWindow(window->hWnd, SW_NORMAL); // Make The Window Visible window->isVisible = TRUE; // Set isVisible To True ReshapeGL(window->init.width, window->init.height); // Reshape Our GL Window window->lastTickCount = GetTickCount(); // Get Tick Count return TRUE; // Window Creating Was A Success // Initialization Will Be Done In WM_CREATE }
// Process Window Message Callbacks LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { DWORD tickCount; // Holds Current Tick Count __int64 timer; // Used For The Tick Counter // Get The Window Context GL_Window* window = (GL_Window*)(GetWindowLong (hWnd, GWL_USERDATA)); switch (uMsg) // Evaluate Window Message { case WM_ERASEBKGND: // Check To See If Windows Is Trying To Erase The Background return 0; // Return 0 (Prevents Flickering While Resizing) case WM_PAINT: // Window Needs Updating { if (window->hrTimer) // Are We Using High Resolution Timer { QueryPerformanceCounter((LARGE_INTEGER *) &timer); // Grab Current Value In Performance Counter tickCount = (DWORD) timer; // Store It In Tick Count } else // Otherwise We Grab Ticks The Old Fashioned Way tickCount = GetTickCount (); // Get The Tick Count // Call Update With The New Counter Value Update ((tickCount - window->lastTickCount) * window->timerResolution * 1000.0f); window->lastTickCount = tickCount; // Set Last Count To Current Count Draw (); // Draw Our Scene SwapBuffers (window->hDC); // Swap Buffers (Double Buffering) } return 0; // Return case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } return 0; // Return case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(window)); } return 0; // Return case WM_CLOSE: // Closing The Window TerminateApplication(window); // Terminate The Application return 0; // Return case WM_SIZE: // Size Action Has Taken Place switch (wParam) // Evaluate Size Action { case SIZE_MINIMIZED: // Was Window Minimized? window->isVisible = FALSE; // Set isVisible To False return 0; // Return case SIZE_MAXIMIZED: // Was Window Maximized? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return case SIZE_RESTORED: // Was Window Restored? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return } break; // Break case WM_KEYDOWN: // Update Keyboard Buffers For Keys Pressed if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { window->keys->keyDown [wParam] = TRUE; // Set The Selected Key (wParam) To True return 0; // Return } break; // Break case WM_KEYUP: // Update Keyboard Buffers For Keys Released if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { window->keys->keyDown [wParam] = FALSE; // Set The Selected Key (wParam) To False return 0; // Return } break; // Break case WM_TOGGLEFULLSCREEN: // Toggle FullScreen Mode On/Off g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage (hWnd, WM_QUIT, 0, 0); break; // Break } return DefWindowProc (hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }
// Process Window Message Callbacks LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get The Window Context gl_window_t *win = (gl_window_t *)(GetWindowLong (hWnd, GWL_USERDATA)); //printf("hwnd=%d uMsg=%d\n", hWnd, uMsg); switch (uMsg) { case WM_ERASEBKGND: // Check To See If Windows Is Trying To Erase The Background return 0; // Return 0 (Prevents Flickering While Resizing A Window) case WM_PAINT: // Window Needs Updating { //PAINTSTRUCT ps; //BeginPaint(win->hWnd, &ps); // uncomment this to repaint window on size/move event, maybe add win->sizemoveevent = TRUE, // so it will not interfer with main loop if (win->win32_wndproconly) { WindowUpdate(win); WindowDraw(win); } // I've read that opengl should be drawn in WM_PAINT, but that just caused problems (unfocused window e.g. just would not update at all) //EndPaint(win->hWnd, &ps); return 0; } case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Call DefWindowProc() } case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer win = (gl_window_t *)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(win)); return 0; } case WM_CLOSE: WindowTerminate(win); return 0; case WM_SIZE: // Size Action Has Taken Place //printf("WM_SIZE\n"); switch (wParam) { case SIZE_MINIMIZED: // Was Window Minimized? win->isVisible = FALSE; // Set isVisible To False return 0; case SIZE_MAXIMIZED: // Was Window Maximized? win->isVisible = TRUE; // Set isVisible To True WindowMakeCurrent(win); ReshapeGL (win, LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; case SIZE_RESTORED: // Was Window Restored? win->isVisible = TRUE; // Set isVisible To True WindowMakeCurrent(win); ReshapeGL (win, LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; } break; case WM_KEYDOWN: // Update Keyboard Buffers For Keys Pressed if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { win->keys.keyDown [wParam] = TRUE; // Set The Selected Key (wParam) To True return 0; // Return } break; case WM_KEYUP: // Update Keyboard Buffers For Keys Released if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { win->keys.keyDown [wParam] = FALSE; // Set The Selected Key (wParam) To False return 0; // Return } break; case WM_TOGGLEFULLSCREEN: // Toggle FullScreen Mode On/Off //win->toggleFullscreen = TRUE; PostMessage (hWnd, WM_QUIT, 0, 0); break; } return DefWindowProc (hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }
//static bool gwenhandled = false; // Process Window Message Callbacks LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get The Window Context GL_Window* window = (GL_Window*)(GetWindowLong (hWnd, GWL_USERDATA)); switch (uMsg) // Evaluate Window Message { case WM_PAINT: ValidateRect(hWnd,NULL); //Needed to avoid new WM_PAINT messages return 0; case WM_DESTROY: //gameShouldQuit = true; PostQuitMessage(0); //iexit(-1); return 0; case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } return 0; // Return case WM_CREATE: // Window Creation { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store Window Structure Pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong (hWnd, GWL_USERDATA, (LONG)(window)); } return 0; // Return case WM_CLOSE: // Closing The Window TerminateApplication(window); // Terminate The Application return 0; // Return case WM_SIZE: // Size Action Has Taken Place switch (wParam) // Evaluate Size Action { case SIZE_MINIMIZED: // Was Window Minimized? window->isVisible = FALSE; // Set isVisible To False return 0; // Return case SIZE_MAXIMIZED: // Was Window Maximized? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return case SIZE_RESTORED: // Was Window Restored? window->isVisible = TRUE; // Set isVisible To True ReshapeGL (LOWORD (lParam), HIWORD (lParam)); // Reshape Window - LoWord=Width, HiWord=Height return 0; // Return } break; // Break case WM_TOGGLEFULLSCREEN: // Toggle FullScreen Mode On/Off g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage (hWnd, WM_QUIT, 0, 0); break; // Break case WM_LBUTTONDOWN: { int x = (short)LOWORD(lParam); int y = (short)HIWORD(lParam); SetCapture(hWnd); mouseDown = true; MakeMouseDown(); } return 0; case WM_LBUTTONUP: { int x = (short)LOWORD(lParam); int y = (short)HIWORD(lParam); ReleaseCapture(); mouseDown = false; MakeMouseUp(); } case WM_MOUSEMOVE: { int x = (short)LOWORD(lParam); int y = (short)HIWORD(lParam); MakeMousePos(x,y); if (mouseDown) { } } return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: { if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { MakeKeyDown(wParam); /* if (wParam == VK_MENU) { } if (wParam == VK_F1)//NUMPAD8) { RECT r; GetWindowRect(hWnd, &r); SetWindowPos(hWnd, HWND_TOP, r.left, r.top-100, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW); } if (wParam == VK_F2)//NUMPAD2) { RECT r; GetWindowRect(hWnd, &r); SetWindowPos(hWnd, HWND_TOP, r.left, r.top+100, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW); } if (wParam == VK_F3)//NUMPAD4) { RECT r; GetWindowRect(hWnd, &r); SetWindowPos(hWnd, HWND_TOP, r.left-100, r.top, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW); } if (wParam == VK_F4)//NUMPAD6) { RECT r; GetWindowRect(hWnd, &r); SetWindowPos(hWnd, HWND_TOP, r.left+100, r.top, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW); } #if 1 //hack ... simulate interrupts //if (InputManager::kbState.IsKeyDown(Keys::P) && InputManager::lastKbState.IsKeyUp(Keys::P)) if (wParam == VK_F5)//NUMPAD6) { } //if (InputManager::kbState.IsKeyDown(Keys::G) && InputManager::lastKbState.IsKeyUp(Keys::G)) if (wParam == VK_F6)//NUMPAD6) { } #endif*/ } return 0; } case WM_SYSKEYUP: case WM_KEYUP: { if ((wParam >= 0) && (wParam <= 255)) // Is Key (wParam) In A Valid Range? { MakeKeyUp(wParam); // if(wParam == 27) // { // InputManager::BackPressed(); // } if (wParam == VK_MENU) { } return 0; // Return } return 0; } case WM_GETMINMAXINFO: { MINMAXINFO* info = (MINMAXINFO*)lParam; //override default window sizes //allow the window to be bigger than the screen info->ptMaxSize.x = 4000; //should be enough until we get to x8 :)))) info->ptMaxSize.y = 4000; info->ptMaxTrackSize.x = 4000; info->ptMaxTrackSize.y = 4000; info->ptMaxPosition.x = -2000; info->ptMaxPosition.y = -2000; return 0; } break; }; return DefWindowProc (hWnd, uMsg, wParam, lParam); // Pass Unhandled Messages To DefWindowProc }