/* ** Haaf's Game Engine 1.8 ** Copyright (C) 2003-2007, Relish Games ** hge.relishgames.com ** ** Core system functions ** Upgraded to DirectX9 By Chris Xiong, 2013/08/08 */ #include "hge_impl.h" #define LOWORDINT(n) ((int)((signed short)(LOWORD(n)))) #define HIWORDINT(n) ((int)((signed short)(HIWORD(n)))) static const char* SYSTEM_SRC_FN="hge/system.cpp"; const char *WINDOW_CLASS_NAME = "HGE__WNDCLASS"; LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); int nRef=0; HGE_Impl* pHGE=0; BOOL APIENTRY DllMain(HANDLE, DWORD, LPVOID) { return TRUE; } HGE* CALL hgeCreate(int ver) { if(ver==HGE_VERSION) return (HGE*)HGE_Impl::_Interface_Get(); else return 0; } HGE_Impl* HGE_Impl::_Interface_Get() { if(!pHGE) pHGE=new HGE_Impl(); nRef++; return pHGE; } void CALL HGE_Impl::Release() { nRef--; if(!nRef) { if(pHGE->hwnd) pHGE->System_Shutdown(); Resource_RemoveAllPacks(); delete pHGE; pHGE=0; } } bool CALL HGE_Impl::System_Initiate() { OSVERSIONINFO os_ver; SYSTEMTIME tm; MEMORYSTATUS mem_st; WNDCLASS winclass; int width, height; // Log system info System_Log("%s: HGE Started...",SYSTEM_SRC_FN); System_Log("%s: hge version: %X.%X", SYSTEM_SRC_FN, HGE_VERSION>>8, HGE_VERSION & 0xFF); GetLocalTime(&tm); System_Log("%s: Date: %02d.%02d.%d, %02d:%02d:%02d\n", SYSTEM_SRC_FN, tm.wDay, tm.wMonth, tm.wYear, tm.wHour, tm.wMinute, tm.wSecond); System_Log("%s: Application: %s", SYSTEM_SRC_FN, szWinTitle); os_ver.dwOSVersionInfoSize=sizeof(os_ver); GetVersionEx(&os_ver); System_Log("%s: OS: Windows %ld.%ld.%ld", SYSTEM_SRC_FN, os_ver.dwMajorVersion,os_ver.dwMinorVersion,os_ver.dwBuildNumber); GlobalMemoryStatus(&mem_st); System_Log("%s: Memory: %ldK total, %ldK free\n", SYSTEM_SRC_FN, mem_st.dwTotalPhys/1024L,mem_st.dwAvailPhys/1024L); // Register window class winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hInstance; winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; if(szIcon) winclass.hIcon = LoadIcon(hInstance, szIcon); else winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClass(&winclass)) { _PostError("Can't register window class"); return false; } // Create window width=nScreenWidth + GetSystemMetrics(SM_CXFIXEDFRAME)*2; height=nScreenHeight + GetSystemMetrics(SM_CYFIXEDFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); rectW.left=(GetSystemMetrics(SM_CXSCREEN)-width)/2; rectW.top=(GetSystemMetrics(SM_CYSCREEN)-height)/2; rectW.right=rectW.left+width; rectW.bottom=rectW.top+height; styleW=WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_VISIBLE; //WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX; rectFS.left=0; rectFS.top=0; rectFS.right=nScreenWidth; rectFS.bottom=nScreenHeight; styleFS=WS_POPUP|WS_VISIBLE; //WS_POPUP if(hwndParent) { rectW.left=0; rectW.top=0; rectW.right=nScreenWidth; rectW.bottom=nScreenHeight; styleW=WS_CHILD|WS_VISIBLE; bWindowed=true; } if(bWindowed) hwnd = CreateWindowEx(0, WINDOW_CLASS_NAME, szWinTitle, styleW, rectW.left, rectW.top, rectW.right-rectW.left, rectW.bottom-rectW.top, hwndParent, NULL, hInstance, NULL); else hwnd = CreateWindowEx(WS_EX_TOPMOST, WINDOW_CLASS_NAME, szWinTitle, styleFS, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); if (!hwnd) { _PostError("Can't create window"); return false; } ShowWindow(hwnd, SW_SHOW); // Init subsystems timeBeginPeriod(1); Random_Seed(); //_InitPowerStatus(); _InputInit(); if(!_GfxInit()) { System_Shutdown(); return false; } if(!_SoundInit()) { System_Shutdown(); return false; } System_Log("%s: Init done.\n",SYSTEM_SRC_FN); fTime=0.0f; t0=t0fps=timeGetTime(); dt=cfps=0; nFPS=0; nFPSf=0.0f; Fcnt=0; fUpdateFPSDelay=0.0f; // Show splash #ifdef DEMO bool (*func)(); bool (*rfunc)(); HWND hwndTmp; if(pHGE->bDMO) { Sleep(200); func=(bool(*)())pHGE->System_GetStateFunc(HGE_FRAMEFUNC); rfunc=(bool(*)())pHGE->System_GetStateFunc(HGE_RENDERFUNC); hwndTmp=hwndParent; hwndParent=0; pHGE->System_SetStateFunc(HGE_FRAMEFUNC, DFrame); pHGE->System_SetStateFunc(HGE_RENDERFUNC, 0); DInit(); pHGE->System_Start(); DDone(); hwndParent=hwndTmp; pHGE->System_SetStateFunc(HGE_FRAMEFUNC, func); pHGE->System_SetStateFunc(HGE_RENDERFUNC, rfunc); } #endif // Done return true; } void CALL HGE_Impl::System_Shutdown() { System_Log("\n%s: Closing session..",SYSTEM_SRC_FN); timeEndPeriod(1); if(hSearch) { FindClose(hSearch); hSearch=0; } _ClearQueue(); _SoundDone(); _GfxDone(); //_DonePowerStatus(); if(hwnd) { //ShowWindow(hwnd, SW_HIDE); //SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); //ShowWindow(hwnd, SW_SHOW); DestroyWindow(hwnd); hwnd=0; } if(hInstance) UnregisterClass(WINDOW_CLASS_NAME, hInstance); System_Log("%s: Session ended.",SYSTEM_SRC_FN); } bool CALL HGE_Impl::System_Start() { MSG msg; if(!hwnd) { _PostError("System_Start: System_Initiate wasn't called"); return false; } if(!procFrameFunc) { _PostError("System_Start: No frame function defined"); return false; } bActive=true; // MAIN LOOP for(;;) { // Process window messages if not in "child mode" // (if in "child mode" the parent application will do this for us) if(!hwndParent) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; // TranslateMessage(&msg); DispatchMessage(&msg); continue; } } // Check if mouse is over HGE window for Input_IsMouseOver _UpdateMouse(); // If HGE window is focused or we have the "don't suspend" state - process the main loop if(bActive || bDontSuspend) { // Ensure we have at least 1ms time step // to not confuse user's code with 0 do { dt=timeGetTime() - t0; } while(dt < 1); // If we reached the time for the next frame // or we just run in unlimited FPS mode, then // do the stuff if(dt >= nFixedDelta) { // fDeltaTime = time step in seconds returned by Timer_GetDelta fDeltaTime=dt/1000.0f; // Cap too large time steps usually caused by lost focus to avoid jerks if(fDeltaTime > 0.2f) { fDeltaTime = nFixedDelta ? nFixedDelta/1000.0f : 0.01f; } // Update time counter returned Timer_GetTime fTime += fDeltaTime; // Store current time for the next frame // and count FPS t0=timeGetTime(); if(t0-t0fps <= 1000) cfps++; else { nFPS=cfps; cfps=0; t0fps=t0; _UpdatePowerStatus(); } ++Fcnt;fUpdateFPSDelay+=fDeltaTime; if(fUpdateFPSDelay>1) { nFPSf=Fcnt/fUpdateFPSDelay; fUpdateFPSDelay=0.0f; Fcnt=0; } // Do user's stuff if(procFrameFunc()) break; if(procRenderFunc) procRenderFunc(); // If if "child mode" - return after processing single frame if(hwndParent) break; // Clean up input events that were generated by // WindowProc and weren't handled by user's code for (int i=1;i<=255;++i) keylast[i]=Input_GetKeyState(i); _ClearQueue(); // If we use VSYNC - we could afford a little // sleep to lower CPU usage // if(!bWindowed && nHGEFPS==HGEFPS_VSYNC) Sleep(1); } // If we have a fixed frame rate and the time // for the next frame isn't too close, sleep a bit else { if(nFixedDelta && dt+3 < nFixedDelta) Sleep(1); } } // If main loop is suspended - just sleep a bit // (though not too much to allow instant window // redraw if requested by OS) else Sleep(1); } _ClearQueue(); bActive=false; return true; } void CALL HGE_Impl::System_SetStateBool(hgeBoolState state, bool value) { switch(state) { case HGE_WINDOWED: if(VertArray || hwndParent) break; if(pD3DDevice && bWindowed != value) { if(d3dppW.BackBufferFormat==D3DFMT_UNKNOWN || d3dppFS.BackBufferFormat==D3DFMT_UNKNOWN) break; if(bWindowed) GetWindowRect(hwnd, &rectW); bWindowed=value; if(bWindowed) d3dpp=&d3dppW; else d3dpp=&d3dppFS; if(_format_id(d3dpp->BackBufferFormat) < 4) nScreenBPP=16; else nScreenBPP=32; _GfxRestore(); _AdjustWindow(); } else bWindowed=value; break; case HGE_ZBUFFER: if(!pD3DDevice) bZBuffer=value; break; case HGE_TEXTUREFILTER: bTextureFilter=value; if(pD3DDevice) { _render_batch(); if(bTextureFilter) { pD3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); pD3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); } else { pD3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT); pD3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT); } } break; case HGE_USESOUND: if(bUseSound!=value) { bUseSound=value; if(bUseSound && hwnd) _SoundInit(); if(!bUseSound && hwnd) _SoundDone(); } break; case HGE_HIDEMOUSE: bHideMouse=value; break; case HGE_DONTSUSPEND: bDontSuspend=value; break; #ifdef DEMO case HGE_SHOWSPLASH: bDMO=value; break; #endif } } void CALL HGE_Impl::System_SetStateFunc(hgeFuncState state, hgeCallback value) { switch(state) { case HGE_FRAMEFUNC: procFrameFunc=value; break; case HGE_RENDERFUNC: procRenderFunc=value; break; case HGE_FOCUSLOSTFUNC: procFocusLostFunc=value; break; case HGE_FOCUSGAINFUNC: procFocusGainFunc=value; break; case HGE_GFXRESTOREFUNC: procGfxRestoreFunc=value; break; case HGE_EXITFUNC: procExitFunc=value; break; } } void CALL HGE_Impl::System_SetStateHwnd(hgeHwndState state, HWND value) { switch(state) { case HGE_HWNDPARENT: if(!hwnd) hwndParent=value; break; } } void CALL HGE_Impl::System_SetStateInt(hgeIntState state, int value) { switch(state) { case HGE_SCREENWIDTH: if(!pD3DDevice) nScreenWidth=value; break; case HGE_SCREENHEIGHT: if(!pD3DDevice) nScreenHeight=value; break; case HGE_SCREENBPP: if(!pD3DDevice) nScreenBPP=value; break; case HGE_SAMPLERATE: if(!hOpenAL) nSampleRate=value; break; case HGE_FXVOLUME: nFXVolume=value; _SetFXVolume(nFXVolume); break; case HGE_MUSVOLUME: nMusVolume=value; _SetMusVolume(nMusVolume); break; case HGE_STREAMVOLUME: nStreamVolume=value; _SetStreamVolume(nStreamVolume); break; case HGE_FPS: if(VertArray) break; if(pD3DDevice) { if((nHGEFPS>=0 && value <0) || (nHGEFPS<0 && value>=0)) { if(value==HGEFPS_VSYNC) { d3dppW.SwapEffect = D3DSWAPEFFECT_COPY; d3dppW.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dppFS.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { d3dppW.SwapEffect = D3DSWAPEFFECT_COPY; d3dppFS.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } //if(procFocusLostFunc) procFocusLostFunc(); _GfxRestore(); //if(procFocusGainFunc) procFocusGainFunc(); } } nHGEFPS=value; if(nHGEFPS>0) nFixedDelta=int(1000.0f/value); else nFixedDelta=0; break; } } void CALL HGE_Impl::System_SetStateString(hgeStringState state, const char *value) { FILE *hf; switch(state) { case HGE_ICON: szIcon=value; if(pHGE->hwnd) SetClassLong(pHGE->hwnd, GCL_HICON, (LONG)LoadIcon(pHGE->hInstance, szIcon)); break; case HGE_TITLE: strcpy(szWinTitle,value); if(pHGE->hwnd) SetWindowText(pHGE->hwnd, szWinTitle); break; case HGE_INIFILE: if(value) strcpy(szIniFile,Resource_MakePath(value)); else szIniFile[0]=0; break; case HGE_LOGFILE: if(value) { strcpy(szLogFile,Resource_MakePath(value)); hf=fopen(szLogFile, "w"); if(!hf) szLogFile[0]=0; else fclose(hf); } else szLogFile[0]=0; break; } } bool CALL HGE_Impl::System_GetStateBool(hgeBoolState state) { switch(state) { case HGE_WINDOWED: return bWindowed; case HGE_ZBUFFER: return bZBuffer; case HGE_TEXTUREFILTER: return bTextureFilter; case HGE_USESOUND: return bUseSound; case HGE_DONTSUSPEND: return bDontSuspend; case HGE_HIDEMOUSE: return bHideMouse; #ifdef DEMO case HGE_SHOWSPLASH: return bDMO; #endif } return false; } hgeCallback CALL HGE_Impl::System_GetStateFunc(hgeFuncState state) { switch(state) { case HGE_FRAMEFUNC: return procFrameFunc; case HGE_RENDERFUNC: return procRenderFunc; case HGE_FOCUSLOSTFUNC: return procFocusLostFunc; case HGE_FOCUSGAINFUNC: return procFocusGainFunc; case HGE_EXITFUNC: return procExitFunc; } return NULL; } HWND CALL HGE_Impl::System_GetStateHwnd(hgeHwndState state) { switch(state) { case HGE_HWND: return hwnd; case HGE_HWNDPARENT: return hwndParent; } return 0; } int CALL HGE_Impl::System_GetStateInt(hgeIntState state) { switch(state) { case HGE_SCREENWIDTH: return nScreenWidth; case HGE_SCREENHEIGHT: return nScreenHeight; case HGE_SCREENBPP: return nScreenBPP; case HGE_SAMPLERATE: return nSampleRate; case HGE_FXVOLUME: return nFXVolume; case HGE_MUSVOLUME: return nMusVolume; case HGE_STREAMVOLUME: return nStreamVolume; case HGE_FPS: return nHGEFPS; case HGE_POWERSTATUS: return nPowerStatus; } return 0; } const char* CALL HGE_Impl::System_GetStateString(hgeStringState state) { switch(state) { case HGE_ICON: return szIcon; case HGE_TITLE: return szWinTitle; case HGE_INIFILE: if(szIniFile[0]) return szIniFile; else return 0; case HGE_LOGFILE: if(szLogFile[0]) return szLogFile; else return 0; } return NULL; } const char* CALL HGE_Impl::System_GetErrorMessage() { return szError; } void CALL HGE_Impl::System_Log(const char *szFormat, ...) { FILE *hf = NULL; va_list ap; if(!szLogFile[0]) return; hf = fopen(szLogFile, "a"); if(!hf) return; va_start(ap, szFormat); vfprintf(hf, szFormat, ap); va_end(ap); va_start(ap, szFormat); vfprintf(stderr, szFormat, ap); va_end(ap); fprintf(hf, "\n"); fprintf(stderr, "\n"); fclose(hf); } bool CALL HGE_Impl::System_Launch(const char *url) { if((DWORD)ShellExecute(pHGE->hwnd, NULL, url, NULL, NULL, SW_SHOWMAXIMIZED)>32) return true; else return false; } void CALL HGE_Impl::System_Snapshot(const char *filename) { LPDIRECT3DSURFACE9 pSurf; char *shotname, tempname[_MAX_PATH]; int i; if(!filename) { i=0; shotname=Resource_EnumFiles("shot???.bmp"); while(shotname) { i++; shotname=Resource_EnumFiles(); } sprintf(tempname, "shot%03d.bmp", i); filename=Resource_MakePath(tempname); } if(pD3DDevice) { pD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurf); D3DXSaveSurfaceToFile(filename, D3DXIFF_BMP, pSurf, NULL, NULL); pSurf->Release(); } } //////// Implementation //////// HGE_Impl::HGE_Impl() { hInstance=GetModuleHandle(0); hwnd=0; bActive=false; szError[0]=0; pD3D=0; pD3DDevice=0; d3dpp=0; pTargets=0; pCurTarget=0; pScreenSurf=0; pScreenDepth=0; pVB=0; pIB=0; VertArray=0; textures=0; hOpenAL=0; bSilent=false; streams=0; hSearch=0; res=0; queue=0; Char=VKey=Zpos=0; Xpos=Ypos=0.0f; bMouseOver=false; bCaptured=false; nHGEFPS=HGEFPS_UNLIMITED; fTime=0.0f; fUpdateFPSDelay=0.0f; fDeltaTime=0.0f; nFPS=0; nFPSf=0.0f; Fcnt=0; procFrameFunc=0; procRenderFunc=0; procFocusLostFunc=0; procFocusGainFunc=0; procGfxRestoreFunc=0; procExitFunc=0; szIcon=0; strcpy(szWinTitle,"HGE"); nScreenWidth=800; nScreenHeight=600; nScreenBPP=32; bWindowed=false; bZBuffer=false; bTextureFilter=true; szLogFile[0]=0; szIniFile[0]=0; bUseSound=true; nSampleRate=44100; nFXVolume=100; nMusVolume=100; nStreamVolume=100; nFixedDelta=0; bHideMouse=true; bDontSuspend=false; hwndParent=0; nPowerStatus=HGEPWR_UNSUPPORTED; hKrnl32 = NULL; lpfnGetSystemPowerStatus = NULL; #ifdef DEMO bDMO=true; #endif GetModuleFileName(GetModuleHandle(NULL), szAppPath, sizeof(szAppPath)); int i; for(i=strlen(szAppPath)-1; i>0; i--) if(szAppPath[i]=='\\') break; szAppPath[i+1]=0; } void HGE_Impl::_PostError(const char *error) { System_Log(error); strcpy(szError,error); } void HGE_Impl::_FocusChange(bool bAct) { bActive=bAct; if(bActive) { if(procFocusGainFunc) procFocusGainFunc(); } else { if(procFocusLostFunc) procFocusLostFunc(); } } LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { bool bActivating; switch(msg) { case WM_CREATE: return FALSE; case WM_PAINT: if(pHGE->pD3D && pHGE->procRenderFunc && pHGE->bWindowed) pHGE->procRenderFunc(); break; case WM_DESTROY: PostQuitMessage(0); return FALSE; /* case WM_ACTIVATEAPP: bActivating = (wparam == TRUE); if(pHGE->pD3D && pHGE->bActive != bActivating) pHGE->_FocusChange(bActivating); return FALSE; */ case WM_ACTIVATE: // tricky: we should catch WA_ACTIVE and WA_CLICKACTIVE, // but only if HIWORD(wParam) (fMinimized) == FALSE (0) bActivating = (LOWORD(wparam) != WA_INACTIVE) && (HIWORD(wparam) == 0); if(pHGE->pD3D && pHGE->bActive != bActivating) pHGE->_FocusChange(bActivating); return FALSE; case WM_SETCURSOR: if(pHGE->bActive && LOWORD(lparam)==HTCLIENT && pHGE->bHideMouse) SetCursor(NULL); else SetCursor(LoadCursor(NULL, IDC_ARROW)); return FALSE; case WM_SYSKEYDOWN: if(wparam == VK_F4) { if(pHGE->procExitFunc && !pHGE->procExitFunc()) return FALSE; return DefWindowProc(hwnd, msg, wparam, lparam); } else if(wparam == VK_RETURN) { pHGE->System_SetState(HGE_WINDOWED, !pHGE->System_GetState(HGE_WINDOWED)); return FALSE; } else { pHGE->_BuildEvent(INPUT_KEYDOWN, wparam, HIWORD(lparam) & 0xFF, (lparam & 0x40000000) ? HGEINP_REPEAT:0, -1, -1); return FALSE; } case WM_KEYDOWN: pHGE->_BuildEvent(INPUT_KEYDOWN, wparam, HIWORD(lparam) & 0xFF, (lparam & 0x40000000) ? HGEINP_REPEAT:0, -1, -1); return FALSE; case WM_SYSKEYUP: pHGE->_BuildEvent(INPUT_KEYUP, wparam, HIWORD(lparam) & 0xFF, 0, -1, -1); return FALSE; case WM_KEYUP: pHGE->_BuildEvent(INPUT_KEYUP, wparam, HIWORD(lparam) & 0xFF, 0, -1, -1); return FALSE; case WM_LBUTTONDOWN: SetFocus(hwnd); pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_LBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_MBUTTONDOWN: SetFocus(hwnd); pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_MBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_RBUTTONDOWN: SetFocus(hwnd); pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_RBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_LBUTTONDBLCLK: pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_LBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_MBUTTONDBLCLK: pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_MBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_RBUTTONDBLCLK: pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_RBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_LBUTTONUP: pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_LBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_MBUTTONUP: pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_MBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_RBUTTONUP: pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_RBUTTON, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_MOUSEMOVE: pHGE->_BuildEvent(INPUT_MOUSEMOVE, 0, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case 0x020A: // WM_MOUSEWHEEL, GET_WHEEL_DELTA_WPARAM(wparam); pHGE->_BuildEvent(INPUT_MOUSEWHEEL, short(HIWORD(wparam))/120, 0, 0, LOWORDINT(lparam), HIWORDINT(lparam)); return FALSE; case WM_SIZE: if(pHGE->pD3D && wparam==SIZE_RESTORED) pHGE->_Resize(LOWORD(lparam), HIWORD(lparam)); //return FALSE; break; case WM_SYSCOMMAND: if(wparam==SC_CLOSE) { if(pHGE->procExitFunc && !pHGE->procExitFunc()) return FALSE; pHGE->bActive=false; return DefWindowProc(hwnd, msg, wparam, lparam); } break; } return DefWindowProc(hwnd, msg, wparam, lparam); }