Пример #1
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;
    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;
}