// // WndProc // Handles the main message loop's events/messages //----------------------------------------------------------------------------- LRESULT CALLBACK CPUTWindowWin::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CPUTEventHandledCode handledCode = CPUT_EVENT_UNHANDLED; LRESULT res; static bool sizing = false; switch (message) { case WM_COMMAND: { int wmId, wmEvent; wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // handle any menu item events here // see reference code in file history for examples } break; case WM_KEYDOWN: // WM_KEYDOWN: gives you EVERY key - including shifts/etc { CPUTKeyState state = CPUT_KEY_DOWN; CPUTKey key = ConvertVirtualKeyToCPUTKey(wParam); if (KEY_NONE != key) { for (const auto &callBack : mKeyboardEventCallbacks) { handledCode = callBack(key, state); } } } break; case WM_KEYUP: { CPUTKeyState state = CPUT_KEY_UP; CPUTKey key = ConvertVirtualKeyToCPUTKey(wParam); if (KEY_NONE != key) { for (const auto &callBack : mKeyboardEventCallbacks) { handledCode = callBack(key, state); } } } break; case WM_CHAR: { CPUTKeyState state = CPUT_KEY_DOWN; CPUTKey key = ConvertCharacterToCPUTKey(wParam); if (KEY_NONE != key) { for (const auto &callBack : mKeyboardEventCallbacks) { handledCode = callBack(key, state); } } } break; case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: // handle double-click events break; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: { CPUTMouseState state = ConvertMouseState(wParam); short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); for (const auto &callBack : mMouseEventCallbacks) { handledCode = callBack(xPos, yPos, 0, state, CPUT_EVENT_DOWN); } } break; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: { CPUTMouseState state = ConvertMouseState(wParam); short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); for (const auto &callBack : mMouseEventCallbacks) { handledCode = callBack(xPos, yPos, 0, state, CPUT_EVENT_UP); } } break; case WM_MOUSEMOVE: { CPUTMouseState state = ConvertMouseState(wParam); short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); for (const auto &callBack : mMouseEventCallbacks) { handledCode = callBack(xPos, yPos, 0, state, CPUT_EVENT_MOVE); } } break; case WM_MOUSEWHEEL: { // get mouse position short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); // get wheel delta int wheel = GET_WHEEL_DELTA_WPARAM(wParam); // one 'click' for (const auto &callBack : mMouseEventCallbacks) { handledCode = callBack(xPos, yPos, wheel, CPUT_MOUSE_WHEEL, CPUT_EVENT_WHEEL); } } return 0; break; case WM_PAINT: PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_SIZING: sizing = true; break; case WM_MOVING: case WM_ERASEBKGND: // overriding this to do nothing avoids flicker and // the expense of re-creating tons of gfx contexts as it resizes break; //case WM_ACTIVATE: // check for maximize/minimize // break; case WM_SIZE: int width, height; height = HIWORD(lParam); width = LOWORD(lParam); RECT windowRect; if(0==GetClientRect(hWnd, &windowRect)) // this gets the client area inside the window frame *excluding* frames/menu bar/etc break; width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; // if we have shrunk to 0 width/height - do not pass on this kind of resize - leads to // various render target resizing warnings if(0==width || 0==height) { break; } { if (!sizing) { // maximize/minimize effect if ((SIZE_MAXIMIZED == wParam)) { // resize for new max/min size for (const auto &callBack : mResizeEventCallbacks) { callBack(width, height); } mbMaxMinFullScreen = true; } else if (SIZE_RESTORED == wParam) { if (true == mbMaxMinFullScreen) { for (const auto &callBack : mResizeEventCallbacks) { callBack(width, height); } mbMaxMinFullScreen = false; } else { for (const auto &callBack : mResizeEventCallbacks) { callBack(width, height); } } } } else { for (const auto &callBack : mResizeEventCallbacks) { callBack(width, height); } } } break; case WM_EXITSIZEMOVE: sizing = false; // update the system's size and make callback { RECT windowRect; if(0==GetClientRect(hWnd, &windowRect)) // this gets the client area inside the window frame *excluding* frames/menu bar/etc break; width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; // if we have shrunk to 0 width/height - do not pass on this kind of resize - leads to // various render target resizing warnings if(0==width || 0==height) { break; } for (const auto &callBack : mResizeEventCallbacks) { callBack(width, height); } } break; case WM_DESTROY: // time to shut down the system PostQuitMessage(0); break; default: // we don't handle it - pass it on thru to parent res = DefWindowProc(hWnd, message, wParam, lParam); return res; } // translate handled code if(CPUT_EVENT_HANDLED == handledCode) { return 1; } return 0; }
// // WndProc // Handles the main message loop's events/messages //----------------------------------------------------------------------------- LRESULT CALLBACK CPUTWindowWin::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CPUTEventHandledCode handledCode = CPUT_EVENT_UNHANDLED; LRESULT res; switch (message) { case WM_COMMAND: int wmId, wmEvent; wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // handle any menu item events here // see reference code in file history for examples break; case WM_KEYDOWN: if(mCPUT) { CPUTKey key = ConvertSpecialKeyCode(wParam, lParam); if(KEY_NONE!=key) { handledCode = mCPUT->CPUTHandleKeyboardEvent( key ); } } break; case WM_CHAR: // WM_KEYDOWN: gives you EVERY key - including shifts/etc if(mCPUT) { CPUTKey key = ConvertKeyCode(wParam, lParam); if(KEY_NONE!=key) { handledCode = mCPUT->CPUTHandleKeyboardEvent( key ); } } break; case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: // handle double-click events break; case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MOUSEMOVE: if(mCPUT) { CPUTMouseState state = ConvertMouseState(wParam); short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); handledCode = mCPUT->CPUTHandleMouseEvent(xPos, yPos, 0, state); } break; case WM_MOUSEWHEEL: if(mCPUT) { // get mouse position short xPos = LOWORD(lParam); short yPos = HIWORD(lParam); // get wheel delta int wheel = GET_WHEEL_DELTA_WPARAM(wParam); // one 'click' handledCode = mCPUT->CPUTHandleMouseEvent(xPos, yPos, wheel, CPUT_MOUSE_WHEEL); } return 0; break; case WM_PAINT: PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_SIZING: case WM_MOVING: case WM_ERASEBKGND: // overriding this to do nothing avoids flicker and // the expense of re-creating tons of gfx contexts as it resizes break; //case WM_ACTIVATE: // check for maximize/minimize // break; case WM_SIZE: int width, height; height = HIWORD(lParam); width = LOWORD(lParam); RECT windowRect; if(0==GetClientRect(hWnd, &windowRect)) // this gets the client area inside the window frame *excluding* frames/menu bar/etc break; width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; if(mCPUT) { // maximize/minimize effect if( (SIZE_MAXIMIZED == wParam) || (SIZE_MINIMIZED==wParam) ) { // resize for new max/min size mCPUT->ResizeWindow(width,height); mbMaxMinFullScreen = true; } else if(SIZE_RESTORED == wParam) { if(true == mbMaxMinFullScreen) { // resize for new max/min size mCPUT->ResizeWindow(width,height); mbMaxMinFullScreen = false; } else { // do a stretch-blit while actively sizing by just rendering to un-resized back buffer mCPUT->ResizeWindowSoft(width, height); } } } break; case WM_EXITSIZEMOVE: // update the system's size and make callback if(mCPUT) { RECT windowRect; if(0==GetClientRect(hWnd, &windowRect)) // this gets the client area inside the window frame *excluding* frames/menu bar/etc break; width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; mCPUT->ResizeWindow(width,height); } break; case WM_DESTROY: // time to shut down the system PostQuitMessage(0); break; default: // we don't handle it - pass it on thru to parent res = DefWindowProc(hWnd, message, wParam, lParam); return res; } // translate handled code if(CPUT_EVENT_HANDLED == handledCode) { return 1; } return 0; }
// Main message pump //----------------------------------------------------------------------------- int CPUTWindowX::StartMessageLoop() { bool fRunning = true; XEvent event; while (fRunning) { if (XPending(pDisplay) > 0) { XNextEvent((pDisplay), &event); switch(event.type) { case KeyPress: if(mCPUT) { CPUTKey key = ConvertKeyCode(&event.xkey); CPUTKeyState state = CPUT_KEY_DOWN; if(key != KEY_NONE) { CPUTEventHandledCode handledCode; handledCode = mCPUT->CPUTHandleKeyboardEvent( key, state ); } } break; case KeyRelease: if(mCPUT) { CPUTKey key = ConvertKeyCode(&event.xkey); CPUTKeyState state = CPUT_KEY_UP; if(key != KEY_NONE) { CPUTEventHandledCode handledCode; handledCode = mCPUT->CPUTHandleKeyboardEvent( key, state ); } } break; case CreateNotify: break; case DestroyNotify: fRunning = false; break; case ClientMessage: if (event.xclient.data.l[0] == wmDeleteMessage) { fRunning = false; } break; case ButtonPress: if (mCPUT) { CPUTEventHandledCode handledCode; CPUTMouseState state = ConvertMouseState(&event.xbutton); short xPos = event.xbutton.x; short yPos = event.xbutton.y; handledCode = mCPUT->CPUTHandleMouseEvent(xPos, yPos, 0, state); } break; case ButtonRelease: if (mCPUT) { CPUTEventHandledCode handledCode; CPUTMouseState state = ConvertMouseState(&event.xbutton); state = CPUT_MOUSE_NONE; short xPos = event.xbutton.x; short yPos = event.xbutton.y; handledCode = mCPUT->CPUTHandleMouseEvent(xPos, yPos, 0, state); } break; case MotionNotify: if (mCPUT) { CPUTMouseState state = CPUT_MOUSE_NONE; CPUTEventHandledCode handledCode; // CPUTMouseState state = ConvertMouseState(&event.xbutton); if (event.xbutton.state & Button1Mask) { state = (CPUTMouseState) (state | static_cast<int>(CPUT_MOUSE_LEFT_DOWN)); } if (event.xbutton.state & Button2Mask) { state = (CPUTMouseState) (state | static_cast<int>(CPUT_MOUSE_RIGHT_DOWN)); } short xPos = event.xbutton.x; short yPos = event.xbutton.y; handledCode = mCPUT->CPUTHandleMouseEvent(xPos, yPos, 0, state); } break; default: break; } } else { mCPUT->InnerExecutionLoop(); } } // XDestroyWindow and XCloseDisplay as the next two commands immediately following your event loop, with an exit(0) af /* // // Message pump // MSG msg = { 0 }; bool fRunning = true; while(fRunning) { // PeekMessage() is a passthru on no events // so it allows us to render while no events are present if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { if (msg.message == WM_QUIT) { PostQuitMessage(0); fRunning = false; } TranslateMessage( &msg ); DispatchMessage( &msg ); } else { // trigger render and other calls mCPUT->InnerExecutionLoop(); } } // // Drain out the rest of the message queue. // while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } if (UnregisterClass(mAppTitle.c_str(), mhInst) == 0) { HandleWin32Error(); } // // Set the window handle to NULL to indicate window shutdown is complete // mhWnd = NULL; // return code mAppClosedReturnCode = (int) msg.wParam; return mAppClosedReturnCode; * */ return 0; }