├── scripts ├── build 2017.bat ├── build.bat └── genie.lua ├── .gitignore ├── LICENSE ├── Sample.cpp ├── README.md ├── EasyWindow.cpp ├── EasyWindow.h └── EasyWindowWin32.cpp /scripts/build 2017.bat: -------------------------------------------------------------------------------- 1 | build vs2017 2 | pause -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | Intermediate/ 35 | Scripts/vs*/ -------------------------------------------------------------------------------- /scripts/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if not exist "genie.exe" ( 4 | echo Downloading genie... 5 | rem bitsadmin /transfer "genie" "https://github.com/bkaradzic/bx/raw/master/tools/bin/windows/genie.exe" "%~dp0\genie.exe" 6 | powershell [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri "https://github.com/bkaradzic/bx/raw/master/tools/bin/windows/genie.exe" -OutFile '%~dp0\genie.exe' 7 | ) 8 | 9 | IF "%1"=="" ( 10 | echo No argument set 11 | echo Exemple : build.bat vs2015 12 | exit 1 13 | ) 14 | 15 | genie.exe %* 16 | 17 | if errorlevel 1 pause 18 | -------------------------------------------------------------------------------- /scripts/genie.lua: -------------------------------------------------------------------------------- 1 | 2 | solution "EasyWindow" 3 | location (_ACTION) 4 | language "C++" 5 | configurations { "Debug", "Release" } 6 | platforms { "x32", "x64" } 7 | objdir ("../Intermediate/".._ACTION) 8 | flags { "StaticRuntime" } 9 | 10 | project "EasyWindowSample" 11 | uuid "f3501d7f-3f2d-476b-b9e2-d6c629e327da" 12 | kind "ConsoleApp" 13 | targetdir "../Output/" 14 | 15 | files { 16 | "../**.cpp", 17 | "../**.h", 18 | } 19 | 20 | includedirs { 21 | ".." 22 | } 23 | 24 | flags "ExtraWarnings" 25 | 26 | platforms{} 27 | 28 | configuration "Debug" 29 | targetsuffix "_d" 30 | flags { "Symbols" } 31 | 32 | configuration "Release" 33 | targetsuffix "_r" 34 | flags { "Optimize" } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thibault Hennequin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sample.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "EasyWindow.h" 3 | 4 | #include 5 | 6 | void OnSize(const EasyWindow* /*pWindow*/, int iW, int iH) 7 | { 8 | printf("OnSize %d %d\n", iW, iH); 9 | } 10 | 11 | bool OnClose(const EasyWindow* /*pWindow*/) 12 | { 13 | printf("OnClose\n"); 14 | static int s_iCloseCount = 0; 15 | return s_iCloseCount++ < 3; 16 | } 17 | 18 | void OnChar(const EasyWindow* /*pWindow*/, unsigned long iChar) 19 | { 20 | printf("OnChar %c\n", (char)iChar); 21 | } 22 | 23 | void OnKey(const EasyWindow* /*pWindow*/, EasyWindow::EKey eKey, bool bDown) 24 | { 25 | printf("OnKey %s %d %s\n", bDown ? "down" : "up", eKey, EasyWindow::KeyToString(eKey)); 26 | } 27 | 28 | int main() 29 | { 30 | EasyWindow* pWindow = EasyWindow::Create("Test", 640, 480, true, 0, EasyWindow::E_STYLE_NORMAL, EasyWindow::E_FLAG_OWN_DC); 31 | pWindow->OnSize.Set(&OnSize); 32 | pWindow->OnClose.Set(&OnClose); 33 | 34 | pWindow->OnKey.Set(&OnKey); 35 | pWindow->OnChar.Set(&OnChar); 36 | pWindow->Show(); 37 | pWindow->SetCursor(EasyWindow::E_CURSOR_HAND); 38 | 39 | while (pWindow->Update()) 40 | { 41 | if ((pWindow->GetLastEvents() & EasyWindow::E_EVENT_SIZED) != 0) 42 | { 43 | printf("Updated size\n"); 44 | } 45 | } 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyWindow 2 | 3 | EasyWindow is a simple library for creating and managing windows. 4 | 5 | It's usefull for create graphics project. 6 | 7 | __!!!WARNING!!!__ 8 | 9 | Only work on Windows actually (need an Linux and MacOS support) and not stable enough for production. 10 | 11 | ## How to use 12 | Include files in you project: 13 | * EasyWindow.h 14 | * EasyWindow.cpp 15 | * EasyWindowWin32.cpp 16 | 17 | 18 | EasyWindow allow you to create a window in 3 lines 19 | 20 | ``` c++ 21 | #include "EasyWindow.h" 22 | 23 | EasyWindow* pMyWindow = EasyWindow::Create("My window", 640, 480); 24 | while (pMyWindow->Update()); 25 | ``` 26 | 27 | ## How to get some events 28 | 29 | Available events: 30 | * OnSize 31 | * OnMove 32 | * OnMaximize 33 | * OnMinimize 34 | * OnRestore 35 | * OnFocus 36 | * OnClose 37 | * OnMouseButton 38 | * OnMouseMove 39 | * OnMouseWheel 40 | * OnKey 41 | * OnChar 42 | 43 | ### Example 44 | 45 | ``` c++ 46 | #include "EasyWindow.h" 47 | 48 | void MyOnSizeFunction(int iWidth, int iHeight) 49 | { 50 | printf("%d x %d\n", iWidth, iHeight); 51 | } 52 | 53 | void MyOnKeyFunction(EasyWindow::EKey eKey, bool bIsDown) 54 | { 55 | printf("Key '%s' is %s\n", EasyWindow::KeyToString(eKey), bIsDown ? "down" : "up"); 56 | } 57 | 58 | void main() 59 | { 60 | // Create window 61 | EasyWindow* pMyWindow = EasyWindow::Create("My window", 640, 480); 62 | // Set events callback 63 | pMyWindow->OnSize.Set(&MyOnSizeFunction); 64 | pMyWindow->OnKey.Set(&MyOnKeyFunction); 65 | // Update window 66 | while (pMyWindow->Update()); 67 | } 68 | ``` 69 | 70 | ## Use with BGFX 71 | 72 | ```c++ 73 | EasyWindow* pMyWindow = EasyWindow::Create("My window", 640, 480); 74 | 75 | bgfx::PlatformData pd; 76 | memset(&pd, 0, sizeof(pd)); 77 | pd.nwh = pMyWindow->GetHandle(); 78 | bgfx::setPlatformData(pd); 79 | 80 | bool bInit = bgfx::init(bgfx::RendererType::OpenGL); 81 | 82 | bgfx::createFrameBuffer(pMyWindow->GetHandle(), pMyWindow->GetClientWidth(), pMyWindow->GetClientHeight()); 83 | ``` 84 | -------------------------------------------------------------------------------- /EasyWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "EasyWindow.h" 2 | 3 | #include 4 | 5 | #include // toupper 6 | 7 | const char* const c_pKeyTable[] = { 8 | 0, 9 | "Esc", 10 | "Return", 11 | "Tab", 12 | "Space", 13 | "Backspace", 14 | "Up", 15 | "Down", 16 | "Left", 17 | "Right", 18 | "Insert", 19 | "Delete", 20 | "Home", 21 | "End", 22 | "PageUp", 23 | "PageDown", 24 | "Print", 25 | "Plus", 26 | "Minus", 27 | "LeftBracket", 28 | "RightBracket", 29 | "Semicolon", 30 | "Quote", 31 | "Comma", 32 | "Period", 33 | "Slash", 34 | "Backslash", 35 | "Tilde", 36 | "F1", 37 | "F2", 38 | "F3", 39 | "F4", 40 | "F5", 41 | "F6", 42 | "F7", 43 | "F8", 44 | "F9", 45 | "F10", 46 | "F11", 47 | "F12", 48 | "NumPad0", 49 | "NumPad1", 50 | "NumPad2", 51 | "NumPad3", 52 | "NumPad4", 53 | "NumPad5", 54 | "NumPad6", 55 | "NumPad7", 56 | "NumPad8", 57 | "NumPad9", 58 | "0", 59 | "1", 60 | "2", 61 | "3", 62 | "4", 63 | "5", 64 | "6", 65 | "7", 66 | "8", 67 | "9", 68 | "A", 69 | "B", 70 | "C", 71 | "D", 72 | "E", 73 | "F", 74 | "G", 75 | "H", 76 | "I", 77 | "J", 78 | "K", 79 | "L", 80 | "M", 81 | "N", 82 | "O", 83 | "P", 84 | "Q", 85 | "R", 86 | "S", 87 | "T", 88 | "U", 89 | "V", 90 | "W", 91 | "X", 92 | "Y", 93 | "Z", 94 | 95 | // Modifiers 96 | "Alt", 97 | "LeftAlt", 98 | "RightAlt", 99 | "Ctrl", 100 | "LeftCtrl", 101 | "RightCtrl", 102 | "Shift", 103 | "LeftShift", 104 | "RightShift", 105 | "Meta", 106 | "LeftMeta", 107 | "RightMeta" 108 | }; 109 | 110 | const char* EasyWindow::KeyToString(EKey eKey) 111 | { 112 | return c_pKeyTable[eKey]; 113 | } 114 | 115 | int _EasyWindowStricmp(const char* str1, const char* str2) 116 | { 117 | int d; 118 | while ((d = ::toupper(*str2) - ::toupper(*str1)) == 0 && *str1) { str1++; str2++; } 119 | return d; 120 | } 121 | 122 | EasyWindow::EKey EasyWindow::StringToKey(const char* pString) 123 | { 124 | if (pString == 0) 125 | return KEY_NONE; 126 | 127 | for (int i = 1; i < sizeof(c_pKeyTable); ++i) 128 | { 129 | if (_EasyWindowStricmp(pString, c_pKeyTable[i]) == 0) 130 | return (EasyWindow::EKey)i; 131 | } 132 | 133 | return KEY_NONE; 134 | } 135 | 136 | bool EasyWindow::IsModifierKey(EKey eKey) 137 | { 138 | return eKey >= KEY_ALT && eKey <= KEY_RIGHTMETA; 139 | } 140 | 141 | bool EasyWindow::GetExtendedKeys(EKey eKey, EKey* pOutKey1, EKey* pOutKey2) 142 | { 143 | switch (eKey) 144 | { 145 | case KEY_ALT: 146 | if (pOutKey1 != NULL) *pOutKey1 = KEY_LEFTALT; 147 | if (pOutKey2 != NULL) *pOutKey2 = KEY_RIGHTALT; 148 | return true; 149 | case KEY_CTRL: 150 | if (pOutKey1 != NULL) *pOutKey1 = KEY_LEFTCTRL; 151 | if (pOutKey2 != NULL) *pOutKey2 = KEY_RIGHTCTRL; 152 | return true; 153 | case KEY_SHIFT: 154 | if (pOutKey1 != NULL) *pOutKey1 = KEY_LEFTSHIFT; 155 | if (pOutKey2 != NULL) *pOutKey2 = KEY_RIGHTSHIFT; 156 | return true; 157 | case KEY_META: 158 | if (pOutKey1 != NULL) *pOutKey1 = KEY_LEFTMETA; 159 | if (pOutKey2 != NULL) *pOutKey2 = KEY_RIGHTMETA; 160 | return true; 161 | default: 162 | if (pOutKey1 != NULL) *pOutKey1 = KEY_NONE; 163 | if (pOutKey2 != NULL) *pOutKey2 = KEY_NONE; 164 | return false; 165 | } 166 | } 167 | 168 | EasyWindow::EKey EasyWindow::GetOriginalKey(EKey eKey) 169 | { 170 | switch (eKey) 171 | { 172 | case KEY_LEFTALT: 173 | case KEY_RIGHTALT: 174 | return KEY_ALT; 175 | case KEY_LEFTCTRL: 176 | case KEY_RIGHTCTRL: 177 | return KEY_CTRL; 178 | case KEY_LEFTSHIFT: 179 | case KEY_RIGHTSHIFT: 180 | return KEY_SHIFT; 181 | case KEY_LEFTMETA: 182 | case KEY_RIGHTMETA: 183 | return KEY_META; 184 | default: 185 | return KEY_NONE; 186 | } 187 | } -------------------------------------------------------------------------------- /EasyWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef __EASY_WINDOW_H__ 2 | #define __EASY_WINDOW_H__ 3 | 4 | class EasyWindow 5 | { 6 | public: 7 | //Caller 8 | //No arg 9 | template 10 | class Caller 11 | { 12 | public: 13 | virtual ~Caller() {} 14 | virtual R Call(const EasyWindow* pWindow) = 0; 15 | }; 16 | 17 | template 18 | class FunctionCaller : public Caller 19 | { 20 | public: 21 | FunctionCaller(R(*pFunctionPtr)(const EasyWindow*)) 22 | { 23 | m_pFunctionPtr = pFunctionPtr; 24 | } 25 | virtual R Call(const EasyWindow* pWindow) 26 | { 27 | return m_pFunctionPtr(pWindow); 28 | } 29 | R(*m_pFunctionPtr)(const EasyWindow*); 30 | }; 31 | 32 | template 33 | class InstanceCaller : public Caller 34 | { 35 | public: 36 | InstanceCaller(C* pThis, R(C::*pMemberPtr)(const EasyWindow*)) 37 | { 38 | m_pThis = pThis; 39 | m_pMemberPtr = pMemberPtr; 40 | } 41 | virtual R Call(const EasyWindow* pWindow) 42 | { 43 | return (m_pThis->*m_pMemberPtr)(pWindow); 44 | } 45 | R(C::*m_pMemberPtr)(const EasyWindow*); 46 | C* m_pThis; 47 | }; 48 | 49 | //One args 50 | template 51 | class CallerOneArg 52 | { 53 | public: 54 | virtual ~CallerOneArg() {} 55 | virtual R Call(const EasyWindow* pWindow, const T1& oT1) = 0; 56 | }; 57 | 58 | template 59 | class FunctionCallerOneArg : public CallerOneArg 60 | { 61 | public: 62 | FunctionCallerOneArg(R(*pFunctionPtr)(const EasyWindow*, T1)) 63 | { 64 | m_pFunctionPtr = pFunctionPtr; 65 | } 66 | virtual R Call(const EasyWindow* pWindow, const T1& oT1) 67 | { 68 | return m_pFunctionPtr(pWindow, oT1); 69 | } 70 | R(*m_pFunctionPtr)(const EasyWindow*, T1); 71 | }; 72 | 73 | template 74 | class InstanceCallerOneArg : public CallerOneArg 75 | { 76 | public: 77 | InstanceCallerOneArg(C* pThis, R(C::*pMemberPtr)(const EasyWindow*, T1)) 78 | { 79 | m_pThis = pThis; 80 | m_pMemberPtr = pMemberPtr; 81 | m_pMemberPtrConstRef = NULL; 82 | } 83 | InstanceCallerOneArg(C* pThis, R(C::*pMemberPtrConstRef)(const EasyWindow*, const T1&)) 84 | { 85 | m_pThis = pThis; 86 | m_pMemberPtr = NULL; 87 | m_pMemberPtrConstRef = pMemberPtrConstRef; 88 | } 89 | virtual R Call(const EasyWindow* pWindow, const T1& oT1) 90 | { 91 | if (m_pMemberPtr != NULL) 92 | return (m_pThis->*m_pMemberPtr)(pWindow, oT1); 93 | return (m_pThis->*m_pMemberPtrConstRef)(pWindow, oT1); 94 | } 95 | R(C::*m_pMemberPtr)(const EasyWindow*, T1); 96 | R(C::*m_pMemberPtrConstRef)(const EasyWindow*, const T1&); 97 | C* m_pThis; 98 | }; 99 | 100 | //Two args 101 | template 102 | class CallerTwoArg 103 | { 104 | public: 105 | virtual ~CallerTwoArg(){} 106 | virtual R Call(const EasyWindow* pWindow, const T1& oT1, const T2& oT2) = 0; 107 | }; 108 | 109 | template 110 | class FunctionCallerTwoArg : public CallerTwoArg 111 | { 112 | public: 113 | FunctionCallerTwoArg(R(*pFunctionPtr)(const EasyWindow*, T1, T2)) 114 | { 115 | m_pFunctionPtr = pFunctionPtr; 116 | } 117 | virtual R Call(const EasyWindow* pWindow, const T1& oT1, const T2& oT2) 118 | { 119 | return m_pFunctionPtr(pWindow, oT1, oT2); 120 | } 121 | R(*m_pFunctionPtr)(const EasyWindow*, T1, T2); 122 | }; 123 | 124 | template 125 | class InstanceCallerTwoArg : public CallerTwoArg 126 | { 127 | public: 128 | InstanceCallerTwoArg(C* pThis, R(C::*pMemberPtr)(const EasyWindow*, T1, T2)) 129 | { 130 | m_pThis = pThis; 131 | m_pMemberPtr = pMemberPtr; 132 | } 133 | virtual R Call(const EasyWindow* pWindow, const T1& oT1, const T2& oT2) 134 | { 135 | return (m_pThis->*m_pMemberPtr)(pWindow, oT1, oT2); 136 | } 137 | R(C::*m_pMemberPtr)(const EasyWindow*, T1, T2); 138 | C* m_pThis; 139 | }; 140 | 141 | //Callbacks 142 | template 143 | class Callback 144 | { 145 | public: 146 | Callback() 147 | { 148 | m_pCaller = 0; 149 | } 150 | ~Callback() 151 | { 152 | if (0 != m_pCaller) 153 | delete m_pCaller; 154 | } 155 | 156 | bool IsSet() const 157 | { 158 | return m_pCaller != 0; 159 | } 160 | 161 | void Set(R(*pFuncPtr)(const EasyWindow* pWindow)) 162 | { 163 | if (0 != m_pCaller) 164 | delete m_pCaller; 165 | 166 | if (pFuncPtr != 0) 167 | m_pCaller = new FunctionCaller(pFuncPtr); 168 | else 169 | m_pCaller = 0; 170 | } 171 | 172 | template 173 | void Set(C* pThis, R(C::*pMemberPtr)(const EasyWindow*)) 174 | { 175 | if (0 != m_pCaller) 176 | delete m_pCaller; 177 | 178 | if (0 != pThis && 0 != pMemberPtr) 179 | m_pCaller = new InstanceCaller(pThis, pMemberPtr); 180 | else 181 | m_pCaller = 0; 182 | } 183 | 184 | R operator()(const EasyWindow* pWindow) 185 | { 186 | if (0 != m_pCaller) 187 | return m_pCaller->Call(pWindow); 188 | return R(); 189 | } 190 | protected: 191 | Caller* m_pCaller; 192 | }; 193 | 194 | template 195 | class CallbackOneArg 196 | { 197 | public: 198 | CallbackOneArg() 199 | { 200 | m_pCaller = 0; 201 | } 202 | ~CallbackOneArg() 203 | { 204 | if (0 != m_pCaller) 205 | delete m_pCaller; 206 | } 207 | 208 | bool IsSet() const 209 | { 210 | return m_pCaller != 0; 211 | } 212 | 213 | void Set(R(*pFuncPtr)(const EasyWindow*, T1)) 214 | { 215 | if (0 != m_pCaller) 216 | delete m_pCaller; 217 | 218 | if (pFuncPtr != 0) 219 | m_pCaller = new FunctionCallerOneArg(pFuncPtr); 220 | else 221 | m_pCaller = 0; 222 | } 223 | 224 | template 225 | void Set(C* pThis, R(C::*pMemberPtr)(const EasyWindow*, T1)) 226 | { 227 | if (NULL != m_pCaller) 228 | delete m_pCaller; 229 | if (0 != pThis && 0 != pMemberPtr) 230 | m_pCaller = new InstanceCallerOneArg(pThis, pMemberPtr); 231 | else 232 | m_pCaller = 0; 233 | } 234 | 235 | template 236 | void Set(C* pThis, R(C::*pMemberPtrConstRef)(const EasyWindow*, const T1&)) 237 | { 238 | if (NULL != m_pCaller) 239 | delete m_pCaller; 240 | 241 | if (0 != pThis && 0 != pMemberPtrConstRef) 242 | m_pCaller = new InstanceCallerOneArg(pThis, pMemberPtrConstRef); 243 | else 244 | m_pCaller = 0; 245 | } 246 | 247 | R operator()(const EasyWindow* pWindow, const T1& oT1) 248 | { 249 | if (0 != m_pCaller) 250 | return m_pCaller->Call(pWindow, oT1); 251 | return R(); 252 | } 253 | protected: 254 | CallerOneArg* m_pCaller; 255 | }; 256 | 257 | template 258 | class CallbackTwoArg 259 | { 260 | public: 261 | CallbackTwoArg() 262 | { 263 | m_pCaller = 0; 264 | } 265 | ~CallbackTwoArg() 266 | { 267 | if (0 != m_pCaller) 268 | delete m_pCaller; 269 | } 270 | 271 | bool IsSet() const 272 | { 273 | return m_pCaller != 0; 274 | } 275 | 276 | void Set(R(*pFuncPtr)(const EasyWindow*, T1, T2)) 277 | { 278 | if (0 != m_pCaller) 279 | delete m_pCaller; 280 | if (pFuncPtr != 0) 281 | m_pCaller = new FunctionCallerTwoArg(pFuncPtr); 282 | else 283 | m_pCaller = 0; 284 | } 285 | 286 | template 287 | void Set(C* pThis, R(C::*pMemberPtr)(const EasyWindow*, T1, T2)) 288 | { 289 | if (NULL != m_pCaller) 290 | delete m_pCaller; 291 | 292 | if (0 != pThis && 0 != pMemberPtr) 293 | m_pCaller = new InstanceCallerTwoArg(pThis, pMemberPtr); 294 | else 295 | m_pCaller = 0; 296 | } 297 | 298 | R operator()(const EasyWindow* pWindow, const T1& oT1, const T2& oT2) 299 | { 300 | if (0 != m_pCaller) 301 | return m_pCaller->Call(pWindow, oT1, oT2); 302 | return R(); 303 | } 304 | protected: 305 | CallerTwoArg* m_pCaller; 306 | }; 307 | 308 | // Enums and structs 309 | 310 | enum EKey 311 | { 312 | KEY_NONE = 0, 313 | KEY_ESC, 314 | KEY_RETURN, 315 | KEY_TAB, 316 | KEY_SPACE, 317 | KEY_BACKSPACE, 318 | KEY_UP, 319 | KEY_DOWN, 320 | KEY_LEFT, 321 | KEY_RIGHT, 322 | KEY_INSERT, 323 | KEY_DELETE, 324 | KEY_HOME, 325 | KEY_END, 326 | KEY_PAGEUP, 327 | KEY_PAGEDOWN, 328 | KEY_PRINT, 329 | KEY_PLUS, 330 | KEY_MINUS, 331 | KEY_LEFTBRACKET, 332 | KEY_RIGHTBRACKET, 333 | KEY_SEMICOLON, 334 | KEY_QUOTE, 335 | KEY_COMMA, 336 | KEY_PERIOD, 337 | KEY_SLASH, 338 | KEY_BACKSLASH, 339 | KEY_TILDE, 340 | KEY_F1, 341 | KEY_F2, 342 | KEY_F3, 343 | KEY_F4, 344 | KEY_F5, 345 | KEY_F6, 346 | KEY_F7, 347 | KEY_F8, 348 | KEY_F9, 349 | KEY_F10, 350 | KEY_F11, 351 | KEY_F12, 352 | KEY_NUMPAD0, 353 | KEY_NUMPAD1, 354 | KEY_NUMPAD2, 355 | KEY_NUMPAD3, 356 | KEY_NUMPAD4, 357 | KEY_NUMPAD5, 358 | KEY_NUMPAD6, 359 | KEY_NUMPAD7, 360 | KEY_NUMPAD8, 361 | KEY_NUMPAD9, 362 | KEY_0, 363 | KEY_1, 364 | KEY_2, 365 | KEY_3, 366 | KEY_4, 367 | KEY_5, 368 | KEY_6, 369 | KEY_7, 370 | KEY_8, 371 | KEY_9, 372 | KEY_A, 373 | KEY_B, 374 | KEY_C, 375 | KEY_D, 376 | KEY_E, 377 | KEY_F, 378 | KEY_G, 379 | KEY_H, 380 | KEY_I, 381 | KEY_J, 382 | KEY_K, 383 | KEY_L, 384 | KEY_M, 385 | KEY_N, 386 | KEY_O, 387 | KEY_P, 388 | KEY_Q, 389 | KEY_R, 390 | KEY_S, 391 | KEY_T, 392 | KEY_U, 393 | KEY_V, 394 | KEY_W, 395 | KEY_X, 396 | KEY_Y, 397 | KEY_Z, 398 | 399 | // Modifiers 400 | KEY_ALT, 401 | KEY_LEFTALT, 402 | KEY_RIGHTALT, 403 | KEY_CTRL, 404 | KEY_LEFTCTRL, 405 | KEY_RIGHTCTRL, 406 | KEY_SHIFT, 407 | KEY_LEFTSHIFT, 408 | KEY_RIGHTSHIFT, 409 | KEY_META, 410 | KEY_LEFTMETA, 411 | KEY_RIGHTMETA, 412 | }; 413 | 414 | enum EWindowStyle 415 | { 416 | E_STYLE_NORMAL, 417 | E_STYLE_BORDERLESS, 418 | E_STYLE_BORDERLESS_RESIZABLE, 419 | E_STYLE_POPUP, 420 | }; 421 | 422 | enum EWindowFlag 423 | { 424 | E_FLAG_NONE = 0, 425 | E_FLAG_OWN_DC = (1 << 0), 426 | E_FLAG_ACCEPT_FILES_DROP = (1 << 1), 427 | E_FLAG_CATCH_ALT_KEY = (1 << 2), 428 | E_FLAG_ALWAYS_CAPTURE_MOUSE_ON_CLICK = (1 << 3) 429 | }; 430 | typedef int EWindowFlags; 431 | 432 | enum ECursor 433 | { 434 | E_CURSOR_NONE, 435 | E_CURSOR_ARROW, 436 | E_CURSOR_TEXT_INPUT, 437 | E_CURSOR_HAND, 438 | E_CURSOR_RESIZE_NS, 439 | E_CURSOR_RESIZE_EW, 440 | E_CURSOR_RESIZE_NESW, 441 | E_CURSOR_RESIZE_NWSE 442 | }; 443 | 444 | enum EEventFlag 445 | { 446 | E_EVENT_NONE = 0, 447 | E_EVENT_CLOSED = (1 << 0), 448 | E_EVENT_MOVED = (1 << 1), 449 | E_EVENT_SIZED = (1 << 2), 450 | E_EVENT_MAXIMIZED = (1 << 3), 451 | E_EVENT_MINIMIZED = (1 << 4), 452 | E_EVENT_RESTORED = (1 << 5), 453 | E_EVENT_FOCUSED = (1 << 6), 454 | E_EVENT_UNFOCUSED = (1 << 7), 455 | E_EVENT_MOUSE_MOVED = (1 << 8), 456 | E_EVENT_MOUSE_WHEEL = (1 << 9), 457 | E_EVENT_MOUSE_BUTTON_DOWN = (1 << 10), 458 | E_EVENT_MOUSE_BUTTON_UP = (1 << 11), 459 | E_EVENT_KEY_DOWN = (1 << 12), 460 | E_EVENT_KEY_UP = (1 << 13), 461 | E_EVENT_CHAR = (1 << 14), 462 | E_EVENT_FILES_DROPPED = (1 << 15), 463 | E_EVENT_PAINT = (1 << 16) 464 | }; 465 | typedef unsigned long EEventFlags; 466 | 467 | enum EHoveredArea 468 | { 469 | E_HOVEREDAREA_NONE, 470 | E_HOVEREDAREA_MENU, 471 | E_HOVEREDAREA_CAPTION, 472 | E_HOVEREDAREA_MINIMIZE, 473 | E_HOVEREDAREA_MAXIMIZE, 474 | E_HOVEREDAREA_CLOSE 475 | }; 476 | 477 | struct Point 478 | { 479 | int x; 480 | int y; 481 | }; 482 | 483 | struct DropFiles 484 | { 485 | int iCount; 486 | char** pFiles; 487 | Point oPosition; 488 | }; 489 | 490 | // Static functions 491 | 492 | static EasyWindow* Create(const char* pTitle, int iWidth, int iHeight, bool bClientSize, EasyWindow* pParent = 0, EWindowStyle eStyle = E_STYLE_NORMAL, EWindowFlags eFlags = E_FLAG_NONE); 493 | static const char* KeyToString(EKey eKey); 494 | static EKey StringToKey(const char* pString); 495 | static bool IsModifierKey(EKey eKey); 496 | static bool GetExtendedKeys(EKey eKey, EKey* pOutKey1, EKey* pOutKey2); 497 | static EKey GetOriginalKey(EKey eKey); 498 | 499 | // Members 500 | 501 | virtual ~EasyWindow() {}; 502 | 503 | virtual bool Update() = 0; 504 | virtual EEventFlags GetLastEvents() = 0; 505 | 506 | virtual void Show(bool bShow = true) = 0; 507 | 508 | virtual bool IsFocused() const = 0; 509 | virtual void SetFocused() = 0; 510 | 511 | virtual void SetSize(int iWidth, int iHeight, bool bClientSize) = 0; 512 | virtual void SetPosition(int iPosX, int iPosY, bool bClientPos) = 0; 513 | virtual void SetMaximized(bool bMaximized) = 0; 514 | virtual void SetMinimized(bool bMinimized) = 0; 515 | virtual void SetTitle(const char* pTitle) = 0; 516 | virtual void SetAlpha(unsigned char iAlpha) = 0; 517 | virtual void SetCursor(ECursor eCursorStyle) = 0; 518 | 519 | virtual void GetSize(int* iWidth, int* iHeight) const = 0; 520 | virtual void GetClientSize(int* iWidth, int* iHeight) const = 0; 521 | virtual void GetPosition(int* iX, int* iY) const = 0; 522 | virtual void GetClientPosition(int* iX, int* iY) const = 0; 523 | virtual bool IsMaximized() const = 0; 524 | virtual bool IsMinimized() const = 0; 525 | 526 | virtual bool IsKeyCtrlDown() = 0; 527 | virtual bool IsKeyAltDown() = 0; 528 | virtual bool IsKeyShiftDown() = 0; 529 | 530 | virtual void* GetHandle() = 0; 531 | 532 | // Events 533 | 534 | /* int Width, int Height */ 535 | CallbackTwoArg OnSize; 536 | /* int PosX, int PosY */ 537 | CallbackTwoArg OnMove; 538 | Callback OnMaximize; 539 | Callback OnMinimize; 540 | Callback OnRestore; 541 | /* bool HasFocus */ 542 | CallbackOneArg OnFocus; 543 | /* return bool AbortClosing */ 544 | Callback OnClose; 545 | 546 | /* int Button, bool IsDown */ 547 | CallbackTwoArg OnMouseButton; 548 | /* int PosX, int PosY */ 549 | CallbackTwoArg OnMouseMove; 550 | /* int wheel step */ 551 | CallbackOneArg OnMouseWheel; 552 | 553 | /* int Key, bool IsDown */ 554 | CallbackTwoArg OnKey; 555 | /* int Char */ 556 | CallbackOneArg OnChar; 557 | 558 | /* int FileCount, char** Files */ 559 | CallbackOneArg OnDropFiles; 560 | 561 | 562 | CallbackTwoArg BorderlessHoveredArea; 563 | }; 564 | 565 | #endif //__EASY_WINDOW_H__ -------------------------------------------------------------------------------- /EasyWindowWin32.cpp: -------------------------------------------------------------------------------- 1 | 2 | #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) 3 | 4 | #include "EasyWindow.h" 5 | 6 | #include 7 | 8 | #define EW_OVERRIDE override 9 | 10 | class EasyWindowWin32 : public EasyWindow 11 | { 12 | static const char* const c_pClassName; 13 | public: 14 | EasyWindowWin32(const char* pTitle, int iWidth, int iHeight, bool bClientSize, EasyWindow* pParent, EWindowStyle eStyle, EWindowFlags eFlags) 15 | : m_bSizing(false) 16 | , m_iActiveHitMousePosition(HTNOWHERE) 17 | , m_eCursor(EasyWindow::E_CURSOR_ARROW) 18 | { 19 | m_bKeyDownAlt[0] = false; 20 | m_bKeyDownAlt[1] = false; 21 | m_bKeyDownCtrl[0] = false; 22 | m_bKeyDownCtrl[1] = false; 23 | m_bKeyDownShift[0] = false; 24 | m_bKeyDownShift[1] = false; 25 | 26 | m_iLastEvents = 0; 27 | 28 | if (!s_bClassInitialized) 29 | { 30 | s_bClassInitialized = true; 31 | WNDCLASSEX wc; 32 | ZeroMemory(&wc, sizeof(WNDCLASSEX)); 33 | wc.cbSize = sizeof(WNDCLASSEX); 34 | wc.style = CS_HREDRAW | CS_VREDRAW; 35 | wc.lpfnWndProc = (WNDPROC)EasyWindowWin32::Proc; 36 | //wc.hInstance = hInstance; 37 | wc.hInstance = GetModuleHandle(NULL); 38 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); 39 | wc.hbrBackground = (HBRUSH)COLOR_WINDOW; 40 | wc.lpszClassName = c_pClassName; 41 | RegisterClassEx(&wc); 42 | 43 | for (int i = 0; i < c_iMaxKeys; ++i) 44 | s_iTranslateKeys[i] = KEY_NONE; 45 | 46 | s_iTranslateKeys[VK_ESCAPE] = EKey::KEY_ESC; 47 | s_iTranslateKeys[VK_RETURN] = EKey::KEY_RETURN; 48 | s_iTranslateKeys[VK_TAB] = EKey::KEY_TAB; 49 | s_iTranslateKeys[VK_BACK] = EKey::KEY_BACKSPACE; 50 | s_iTranslateKeys[VK_SPACE] = EKey::KEY_SPACE; 51 | s_iTranslateKeys[VK_UP] = EKey::KEY_UP; 52 | s_iTranslateKeys[VK_DOWN] = EKey::KEY_DOWN; 53 | s_iTranslateKeys[VK_LEFT] = EKey::KEY_LEFT; 54 | s_iTranslateKeys[VK_RIGHT] = EKey::KEY_RIGHT; 55 | s_iTranslateKeys[VK_INSERT] = EKey::KEY_INSERT; 56 | s_iTranslateKeys[VK_DELETE] = EKey::KEY_DELETE; 57 | s_iTranslateKeys[VK_HOME] = EKey::KEY_HOME; 58 | s_iTranslateKeys[VK_END] = EKey::KEY_END; 59 | s_iTranslateKeys[VK_PRIOR] = EKey::KEY_PAGEUP; 60 | s_iTranslateKeys[VK_NEXT] = EKey::KEY_PAGEDOWN; 61 | s_iTranslateKeys[VK_SNAPSHOT] = EKey::KEY_PRINT; 62 | s_iTranslateKeys[VK_OEM_PLUS] = EKey::KEY_PLUS; 63 | s_iTranslateKeys[VK_OEM_MINUS] = EKey::KEY_MINUS; 64 | s_iTranslateKeys[VK_OEM_4] = EKey::KEY_LEFTBRACKET; 65 | s_iTranslateKeys[VK_OEM_6] = EKey::KEY_RIGHTBRACKET; 66 | s_iTranslateKeys[VK_OEM_1] = EKey::KEY_SEMICOLON; 67 | s_iTranslateKeys[VK_OEM_7] = EKey::KEY_QUOTE; 68 | s_iTranslateKeys[VK_OEM_COMMA] = EKey::KEY_COMMA; 69 | s_iTranslateKeys[VK_OEM_PERIOD] = EKey::KEY_PERIOD; 70 | s_iTranslateKeys[VK_DECIMAL] = EKey::KEY_PERIOD; 71 | s_iTranslateKeys[VK_OEM_2] = EKey::KEY_SLASH; 72 | s_iTranslateKeys[VK_OEM_5] = EKey::KEY_BACKSLASH; 73 | s_iTranslateKeys[VK_OEM_3] = EKey::KEY_TILDE; 74 | s_iTranslateKeys[VK_F1] = EKey::KEY_F1; 75 | s_iTranslateKeys[VK_F2] = EKey::KEY_F2; 76 | s_iTranslateKeys[VK_F3] = EKey::KEY_F3; 77 | s_iTranslateKeys[VK_F4] = EKey::KEY_F4; 78 | s_iTranslateKeys[VK_F5] = EKey::KEY_F5; 79 | s_iTranslateKeys[VK_F6] = EKey::KEY_F6; 80 | s_iTranslateKeys[VK_F7] = EKey::KEY_F7; 81 | s_iTranslateKeys[VK_F8] = EKey::KEY_F8; 82 | s_iTranslateKeys[VK_F9] = EKey::KEY_F9; 83 | s_iTranslateKeys[VK_F10] = EKey::KEY_F10; 84 | s_iTranslateKeys[VK_F11] = EKey::KEY_F11; 85 | s_iTranslateKeys[VK_F12] = EKey::KEY_F12; 86 | s_iTranslateKeys[VK_NUMPAD0] = EKey::KEY_NUMPAD0; 87 | s_iTranslateKeys[VK_NUMPAD1] = EKey::KEY_NUMPAD1; 88 | s_iTranslateKeys[VK_NUMPAD2] = EKey::KEY_NUMPAD2; 89 | s_iTranslateKeys[VK_NUMPAD3] = EKey::KEY_NUMPAD3; 90 | s_iTranslateKeys[VK_NUMPAD4] = EKey::KEY_NUMPAD4; 91 | s_iTranslateKeys[VK_NUMPAD5] = EKey::KEY_NUMPAD5; 92 | s_iTranslateKeys[VK_NUMPAD6] = EKey::KEY_NUMPAD6; 93 | s_iTranslateKeys[VK_NUMPAD7] = EKey::KEY_NUMPAD7; 94 | s_iTranslateKeys[VK_NUMPAD8] = EKey::KEY_NUMPAD8; 95 | s_iTranslateKeys[VK_NUMPAD9] = EKey::KEY_NUMPAD9; 96 | s_iTranslateKeys['0'] = EKey::KEY_0; 97 | s_iTranslateKeys['1'] = EKey::KEY_1; 98 | s_iTranslateKeys['2'] = EKey::KEY_2; 99 | s_iTranslateKeys['3'] = EKey::KEY_3; 100 | s_iTranslateKeys['4'] = EKey::KEY_4; 101 | s_iTranslateKeys['5'] = EKey::KEY_5; 102 | s_iTranslateKeys['6'] = EKey::KEY_6; 103 | s_iTranslateKeys['7'] = EKey::KEY_7; 104 | s_iTranslateKeys['8'] = EKey::KEY_8; 105 | s_iTranslateKeys['9'] = EKey::KEY_9; 106 | s_iTranslateKeys['A'] = EKey::KEY_A; 107 | s_iTranslateKeys['B'] = EKey::KEY_B; 108 | s_iTranslateKeys['C'] = EKey::KEY_C; 109 | s_iTranslateKeys['D'] = EKey::KEY_D; 110 | s_iTranslateKeys['E'] = EKey::KEY_E; 111 | s_iTranslateKeys['F'] = EKey::KEY_F; 112 | s_iTranslateKeys['G'] = EKey::KEY_G; 113 | s_iTranslateKeys['H'] = EKey::KEY_H; 114 | s_iTranslateKeys['I'] = EKey::KEY_I; 115 | s_iTranslateKeys['J'] = EKey::KEY_J; 116 | s_iTranslateKeys['K'] = EKey::KEY_K; 117 | s_iTranslateKeys['L'] = EKey::KEY_L; 118 | s_iTranslateKeys['M'] = EKey::KEY_M; 119 | s_iTranslateKeys['N'] = EKey::KEY_N; 120 | s_iTranslateKeys['O'] = EKey::KEY_O; 121 | s_iTranslateKeys['P'] = EKey::KEY_P; 122 | s_iTranslateKeys['Q'] = EKey::KEY_Q; 123 | s_iTranslateKeys['R'] = EKey::KEY_R; 124 | s_iTranslateKeys['S'] = EKey::KEY_S; 125 | s_iTranslateKeys['T'] = EKey::KEY_T; 126 | s_iTranslateKeys['U'] = EKey::KEY_U; 127 | s_iTranslateKeys['V'] = EKey::KEY_V; 128 | s_iTranslateKeys['W'] = EKey::KEY_W; 129 | s_iTranslateKeys['X'] = EKey::KEY_X; 130 | s_iTranslateKeys['Y'] = EKey::KEY_Y; 131 | s_iTranslateKeys['Z'] = EKey::KEY_Z; 132 | 133 | s_iTranslateKeys[VK_LMENU] = EKey::KEY_LEFTALT; 134 | s_iTranslateKeys[VK_RMENU] = EKey::KEY_RIGHTALT; 135 | s_iTranslateKeys[VK_LCONTROL] = EKey::KEY_LEFTCTRL; 136 | s_iTranslateKeys[VK_RCONTROL] = EKey::KEY_RIGHTCTRL; 137 | s_iTranslateKeys[VK_LSHIFT] = EKey::KEY_LEFTSHIFT; 138 | s_iTranslateKeys[VK_RSHIFT] = EKey::KEY_RIGHTSHIFT; 139 | s_iTranslateKeys[VK_LWIN] = EKey::KEY_LEFTMETA; 140 | s_iTranslateKeys[VK_RWIN] = EKey::KEY_RIGHTMETA; 141 | } 142 | 143 | DWORD iWindowStyle = WS_OVERLAPPEDWINDOW; // E_NORMAL 144 | DWORD iWindowExStyle = 0; 145 | 146 | if (eStyle == E_STYLE_BORDERLESS) 147 | { 148 | iWindowStyle = WS_OVERLAPPED | WS_SYSMENU; 149 | } 150 | else if (eStyle == E_STYLE_BORDERLESS_RESIZABLE) 151 | { 152 | iWindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; 153 | } 154 | else if (eStyle == E_STYLE_POPUP) 155 | { 156 | iWindowStyle = WS_POPUP; 157 | } 158 | 159 | if ((eFlags & E_FLAG_OWN_DC) != 0) 160 | { 161 | iWindowStyle |= CS_OWNDC; 162 | } 163 | 164 | if ((eFlags & E_FLAG_ACCEPT_FILES_DROP) != 0) 165 | { 166 | iWindowExStyle |= WS_EX_ACCEPTFILES; 167 | } 168 | 169 | m_bBorderless = eStyle == E_STYLE_BORDERLESS || eStyle == E_STYLE_BORDERLESS_RESIZABLE; 170 | m_bManualSizing = eStyle == E_STYLE_BORDERLESS_RESIZABLE; 171 | 172 | m_bCatchAlt = (eFlags & E_FLAG_CATCH_ALT_KEY) != 0; 173 | 174 | m_bCaptureMouseOnClick = ( eFlags & E_FLAG_ALWAYS_CAPTURE_MOUSE_ON_CLICK ) != 0; 175 | 176 | RECT wr = { 0, 0, iWidth, iHeight }; 177 | if (bClientSize) 178 | { 179 | AdjustWindowRect(&wr, iWindowStyle, FALSE); 180 | } 181 | 182 | m_pHandle = CreateWindowEx( 183 | iWindowExStyle, 184 | "EasyWindowWin32", 185 | pTitle != NULL ? pTitle : "", 186 | iWindowStyle, 187 | CW_USEDEFAULT, 188 | CW_USEDEFAULT, 189 | wr.right - wr.left, 190 | wr.bottom - wr.top, 191 | pParent != NULL ? ((EasyWindowWin32*)pParent)->m_pHandle : NULL, 192 | NULL, 193 | GetModuleHandle(NULL), 194 | NULL); 195 | 196 | if (m_bManualSizing) 197 | { 198 | SetRectEmpty(&m_oBorderThickness); 199 | if (iWindowStyle & WS_THICKFRAME) 200 | { 201 | AdjustWindowRectEx(&m_oBorderThickness, iWindowStyle & ~WS_CAPTION, FALSE, NULL); 202 | m_oBorderThickness.left *= -1; 203 | m_oBorderThickness.top *= -1; 204 | 205 | m_oBorderThickness.left += 1; 206 | m_oBorderThickness.top += 1; 207 | m_oBorderThickness.right += 1; 208 | m_oBorderThickness.bottom += 1; 209 | } 210 | else if (iWindowStyle & WS_BORDER) 211 | { 212 | SetRect(&m_oBorderThickness, 1, 1, 1, 1); 213 | } 214 | } 215 | 216 | SetWindowLongPtr(m_pHandle, GWLP_USERDATA, (LONG_PTR)this); 217 | 218 | SetWindowPos(m_pHandle, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 219 | } 220 | 221 | virtual ~EasyWindowWin32() 222 | { 223 | if (m_pHandle != NULL) 224 | { 225 | SetWindowLongPtr(m_pHandle, GWLP_USERDATA, (LONG_PTR)NULL); 226 | 227 | bool bIsActive = GetActiveWindow() == m_pHandle; 228 | HWND hOwner = GetWindow(m_pHandle, GW_OWNER); 229 | 230 | DestroyWindow(m_pHandle); 231 | 232 | if (bIsActive && hOwner != NULL) 233 | { 234 | // HACK : Force active window because on destroy the owner window can be moved in background 235 | SetActiveWindow(hOwner); 236 | } 237 | } 238 | } 239 | 240 | virtual bool Update() EW_OVERRIDE 241 | { 242 | if (IsWindow(m_pHandle) == FALSE) 243 | return false; 244 | 245 | MSG oMsg; 246 | int iCount = 0; 247 | m_iLastEvents = 0; 248 | while (iCount < 10 && PeekMessage(&oMsg, m_pHandle, 0, 0, PM_NOREMOVE)) // Max 10 messages 249 | { 250 | if (GetMessage(&oMsg, m_pHandle, 0, 0)) 251 | { 252 | TranslateMessage(&oMsg); 253 | DispatchMessage(&oMsg); 254 | if (m_bSizing) 255 | break; 256 | } 257 | ++iCount; 258 | } 259 | return true; 260 | } 261 | 262 | virtual EEventFlags GetLastEvents() EW_OVERRIDE 263 | { 264 | return m_iLastEvents; 265 | } 266 | 267 | virtual void Show(bool bShow) EW_OVERRIDE 268 | { 269 | ShowWindow(m_pHandle, bShow ? SW_SHOW : SW_HIDE); 270 | } 271 | 272 | virtual bool IsFocused() const EW_OVERRIDE 273 | { 274 | return GetForegroundWindow() == m_pHandle; 275 | } 276 | 277 | virtual void SetFocused() EW_OVERRIDE 278 | { 279 | SetForegroundWindow(m_pHandle); 280 | } 281 | 282 | virtual void SetSize(int iWidth, int iHeight, bool bClientSize) EW_OVERRIDE 283 | { 284 | RECT oRect = { 0, 0, iWidth, iHeight }; 285 | if (bClientSize && m_bBorderless == false) 286 | { 287 | DWORD iWindowStyle = GetWindowLong(m_pHandle, GWL_STYLE); 288 | AdjustWindowRect(&oRect, iWindowStyle, FALSE); 289 | } 290 | 291 | SetWindowPos(m_pHandle, NULL, 0, 0, oRect.right - oRect.left, oRect.bottom - oRect.top, SWP_NOMOVE); 292 | } 293 | 294 | virtual void SetPosition(int iPosX, int iPosY, bool bClientPos) EW_OVERRIDE 295 | { 296 | RECT oRect = { iPosX, iPosY, 0, 0 }; 297 | if (bClientPos) 298 | { 299 | POINT oPoint = { 0, 0 }; 300 | ClientToScreen( m_pHandle, &oPoint ); 301 | 302 | RECT oWinRect; 303 | GetWindowRect(m_pHandle, &oWinRect); 304 | 305 | oRect.left += oPoint.x - oWinRect.left; 306 | oRect.top += oPoint.y - oWinRect.top; 307 | } 308 | SetWindowPos(m_pHandle, NULL, oRect.left, oRect.top, 0, 0, SWP_NOSIZE); 309 | } 310 | 311 | virtual void SetMaximized(bool bMaximized) EW_OVERRIDE 312 | { 313 | if (bMaximized) 314 | ShowWindow(m_pHandle, SW_MAXIMIZE); 315 | else 316 | ShowWindow(m_pHandle, SW_RESTORE); 317 | } 318 | 319 | virtual void SetMinimized(bool bMinimized) EW_OVERRIDE 320 | { 321 | if (bMinimized) 322 | ShowWindow(m_pHandle, SW_MINIMIZE); 323 | else if(IsIconic(m_pHandle)) 324 | ShowWindow(m_pHandle, SW_RESTORE); 325 | } 326 | 327 | virtual void SetTitle(const char* pTitle) EW_OVERRIDE 328 | { 329 | SetWindowText(m_pHandle, pTitle); 330 | } 331 | 332 | virtual void SetAlpha(unsigned char iAlpha) EW_OVERRIDE 333 | { 334 | if (iAlpha < 255) 335 | { 336 | SetWindowLong(m_pHandle, GWL_EXSTYLE, GetWindowLong(m_pHandle, GWL_EXSTYLE) | WS_EX_LAYERED); 337 | } 338 | else 339 | { 340 | SetWindowLong(m_pHandle, GWL_EXSTYLE, GetWindowLong(m_pHandle, GWL_EXSTYLE) & ~WS_EX_LAYERED); 341 | } 342 | SetLayeredWindowAttributes(m_pHandle, RGB(0, 0, 0), iAlpha, LWA_ALPHA); 343 | } 344 | 345 | virtual void SetCursor(ECursor eCursor) EW_OVERRIDE 346 | { 347 | m_eCursor = eCursor; 348 | } 349 | 350 | virtual void GetSize(int* iWidth, int* iHeight) const EW_OVERRIDE 351 | { 352 | RECT oRect; 353 | GetWindowRect(m_pHandle, &oRect); 354 | *iWidth = (int)(oRect.right - oRect.left); 355 | *iHeight = (int)(oRect.bottom - oRect.top); 356 | } 357 | 358 | virtual void GetClientSize(int* iWidth, int* iHeight) const EW_OVERRIDE 359 | { 360 | RECT oRect; 361 | GetClientRect(m_pHandle, &oRect); 362 | *iWidth = (int)(oRect.right - oRect.left); 363 | *iHeight = (int)(oRect.bottom - oRect.top); 364 | } 365 | 366 | virtual void GetPosition(int* iX, int* iY) const EW_OVERRIDE 367 | { 368 | RECT oRectClient; 369 | GetWindowRect(m_pHandle, &oRectClient); 370 | *iX = (int)oRectClient.left; 371 | *iY = (int)oRectClient.top; 372 | } 373 | 374 | virtual void GetClientPosition(int* iX, int* iY) const EW_OVERRIDE 375 | { 376 | RECT oRectClient; 377 | GetClientRect(m_pHandle, &oRectClient); 378 | ClientToScreen(m_pHandle, reinterpret_cast(&oRectClient.left)); // convert top-left 379 | *iX = (int)oRectClient.left; 380 | *iY = (int)oRectClient.top; 381 | } 382 | 383 | virtual bool IsMaximized() const EW_OVERRIDE 384 | { 385 | return IsZoomed(m_pHandle) == TRUE; 386 | } 387 | 388 | virtual bool IsMinimized() const EW_OVERRIDE 389 | { 390 | return IsIconic(m_pHandle) == TRUE; 391 | } 392 | 393 | virtual bool IsKeyCtrlDown() EW_OVERRIDE 394 | { 395 | return (GetKeyState(VK_CONTROL) & 0x8000) != 0; 396 | } 397 | 398 | virtual bool IsKeyAltDown() EW_OVERRIDE 399 | { 400 | return (GetKeyState(VK_MENU) & 0x8000) != 0; 401 | } 402 | 403 | virtual bool IsKeyShiftDown() EW_OVERRIDE 404 | { 405 | return (GetKeyState(VK_SHIFT) & 0x8000) != 0; 406 | } 407 | 408 | virtual void* GetHandle() EW_OVERRIDE 409 | { 410 | return (void*)m_pHandle; 411 | } 412 | protected: 413 | HWND m_pHandle; 414 | bool m_bBorderless; 415 | bool m_bManualSizing; 416 | RECT m_oBorderThickness; 417 | bool m_bSizing; 418 | WPARAM m_iActiveHitMousePosition; 419 | LONG_PTR m_iSizingMode; 420 | ECursor m_eCursor; 421 | bool m_bCatchAlt; 422 | bool m_bKeyDownAlt[2]; 423 | bool m_bKeyDownCtrl[2]; 424 | bool m_bKeyDownShift[2]; 425 | bool m_bCaptureMouseOnClick; 426 | EEventFlags m_iLastEvents; 427 | static bool s_bClassInitialized; 428 | static const int c_iMaxKeys = 256; 429 | static EKey s_iTranslateKeys[c_iMaxKeys]; 430 | 431 | static LRESULT CALLBACK Proc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) 432 | { 433 | EasyWindowWin32* pThis = (EasyWindowWin32*)GetWindowLongPtr(hWnd, GWLP_USERDATA); 434 | 435 | if (pThis != NULL) 436 | { 437 | switch (iMsg) 438 | { 439 | case WM_ERASEBKGND: 440 | return 1; 441 | break; 442 | case WM_PAINT: 443 | { 444 | pThis->m_iLastEvents |= E_EVENT_PAINT; 445 | PAINTSTRUCT ps; 446 | BeginPaint( hWnd, &ps ); 447 | EndPaint( hWnd, &ps ); 448 | return 1; 449 | break; 450 | } 451 | case WM_NCPAINT: 452 | //return 0; 453 | break; 454 | case WM_SIZE: 455 | pThis->m_iLastEvents |= E_EVENT_SIZED; 456 | pThis->OnSize(pThis, LOWORD(lParam), HIWORD(lParam)); 457 | break; 458 | case WM_MOVE: 459 | pThis->m_iLastEvents |= E_EVENT_MOVED; 460 | pThis->OnMove(pThis, LOWORD(lParam), HIWORD(lParam)); 461 | break; 462 | case WM_SETFOCUS: 463 | pThis->m_iLastEvents |= E_EVENT_FOCUSED; 464 | pThis->OnFocus(pThis, true); 465 | break; 466 | case WM_KILLFOCUS: 467 | pThis->m_iLastEvents |= E_EVENT_UNFOCUSED; 468 | pThis->OnFocus(pThis, false); 469 | break; 470 | case WM_CLOSE: 471 | pThis->m_iLastEvents |= E_EVENT_CLOSED; 472 | if (pThis->OnClose(pThis)) 473 | return 1; 474 | break; 475 | case WM_LBUTTONDOWN: 476 | if (!pThis->m_bSizing) 477 | { 478 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_DOWN; 479 | if (pThis->m_bCaptureMouseOnClick) 480 | SetCapture(hWnd); 481 | pThis->OnMouseButton(pThis, 0, true); 482 | } 483 | break; 484 | case WM_LBUTTONUP: 485 | if (pThis->m_bSizing) 486 | { 487 | ReleaseCapture(); 488 | pThis->m_bSizing = false; 489 | } 490 | else 491 | { 492 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_UP; 493 | if (pThis->m_bCaptureMouseOnClick) 494 | ReleaseCapture(); 495 | pThis->OnMouseButton(pThis, 0, false); 496 | } 497 | break; 498 | case WM_RBUTTONDOWN: 499 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_DOWN; 500 | pThis->OnMouseButton(pThis, 1, true); 501 | break; 502 | case WM_RBUTTONUP: 503 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_UP; 504 | pThis->OnMouseButton(pThis, 1, false); 505 | break; 506 | case WM_MBUTTONDOWN: 507 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_DOWN; 508 | pThis->OnMouseButton(pThis, 2, true); 509 | break; 510 | case WM_MBUTTONUP: 511 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_UP; 512 | pThis->OnMouseButton(pThis, 2, false); 513 | break; 514 | case WM_XBUTTONDOWN: 515 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_DOWN; 516 | pThis->OnMouseButton(pThis, 2 + GET_XBUTTON_WPARAM(wParam), true); 517 | break; 518 | case WM_XBUTTONUP: 519 | pThis->m_iLastEvents |= E_EVENT_MOUSE_BUTTON_UP; 520 | pThis->OnMouseButton(pThis, 2 + GET_XBUTTON_WPARAM(wParam), false); 521 | break; 522 | case WM_MOUSEMOVE: 523 | case WM_NCMOUSEMOVE: 524 | { 525 | /*if (!m_bMouseTracking) 526 | { 527 | TRACKMOUSEEVENT tme; 528 | tme.cbSize = sizeof(TRACKMOUSEEVENT); 529 | tme.dwFlags = TME_LEAVE; 530 | tme.hwndTrack = m_hWnd; 531 | if (TrackMouseEvent(&tme)) 532 | { 533 | m_bMouseTracking = true; 534 | } 535 | }*/ 536 | 537 | POINT oCursorPos; 538 | GetCursorPos(&oCursorPos); 539 | 540 | if (pThis->m_bSizing) 541 | { 542 | RECT oRect; 543 | GetWindowRect(pThis->m_pHandle, &oRect); 544 | switch (pThis->m_iSizingMode) 545 | { 546 | case HTLEFT: 547 | oRect.left = oCursorPos.x; 548 | break; 549 | case HTTOPLEFT: 550 | oRect.top = oCursorPos.y; 551 | oRect.left = oCursorPos.x; 552 | break; 553 | case HTBOTTOMLEFT: 554 | oRect.bottom = oCursorPos.y; 555 | oRect.left = oCursorPos.x; 556 | break; 557 | case HTRIGHT: 558 | oRect.right = oCursorPos.x; 559 | break; 560 | case HTTOPRIGHT: 561 | oRect.top = oCursorPos.y; 562 | oRect.right = oCursorPos.x; 563 | break; 564 | case HTBOTTOMRIGHT: 565 | oRect.bottom = oCursorPos.y; 566 | oRect.right = oCursorPos.x; 567 | break; 568 | case HTTOP: 569 | oRect.top = oCursorPos.y; 570 | break; 571 | case HTBOTTOM: 572 | oRect.bottom = oCursorPos.y; 573 | break; 574 | } 575 | SetWindowPos(pThis->m_pHandle, NULL, oRect.left, oRect.top, oRect.right - oRect.left, oRect.bottom - oRect.top, 0); 576 | } 577 | else 578 | { 579 | pThis->m_iLastEvents |= E_EVENT_MOUSE_MOVED; 580 | POINT oTopLeft = { 0, 0 }; 581 | ClientToScreen(pThis->m_pHandle, &oTopLeft); // Convert top-left client position to screen position 582 | pThis->OnMouseMove(pThis, oCursorPos.x - oTopLeft.x, oCursorPos.y - oTopLeft.y); 583 | } 584 | break; 585 | } 586 | case WM_MOUSEWHEEL: 587 | pThis->m_iLastEvents |= E_EVENT_MOUSE_WHEEL; 588 | pThis->OnMouseWheel(pThis, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); 589 | break; 590 | case WM_SYSKEYDOWN: 591 | case WM_SYSKEYUP: 592 | if (pThis->m_bCatchAlt == false) 593 | break; 594 | case WM_KEYDOWN: 595 | case WM_KEYUP: 596 | { 597 | bool bDown = (iMsg == WM_SYSKEYDOWN) || (iMsg == WM_KEYDOWN); 598 | if (wParam >= 0 && wParam < c_iMaxKeys && (bDown == false || (HIWORD(lParam) & KF_REPEAT) == 0)) 599 | { 600 | pThis->m_iLastEvents |= bDown ? E_EVENT_KEY_DOWN : E_EVENT_KEY_UP; 601 | 602 | EKey eKey = (EKey)s_iTranslateKeys[wParam]; 603 | 604 | if (wParam == VK_SHIFT) 605 | { 606 | if (bDown && pThis->m_bKeyDownShift[0] != bDown && pThis->m_bKeyDownShift[1] != bDown) 607 | pThis->OnKey(pThis, KEY_SHIFT, bDown); 608 | 609 | UINT iScancode = (lParam & 0x00ff0000) >> 16; 610 | UINT iNewVK = MapVirtualKey(iScancode, MAPVK_VSC_TO_VK_EX); 611 | eKey = (EKey)s_iTranslateKeys[iNewVK]; 612 | 613 | pThis->m_bKeyDownShift[(int)(eKey == KEY_RIGHTSHIFT)] = bDown; 614 | 615 | if (!bDown && pThis->m_bKeyDownShift[0] == bDown && pThis->m_bKeyDownShift[1] == bDown) 616 | pThis->OnKey(pThis, KEY_SHIFT, bDown); 617 | } 618 | else if (wParam == VK_CONTROL) 619 | { 620 | if (bDown && pThis->m_bKeyDownCtrl[0] != bDown && pThis->m_bKeyDownCtrl[1] != bDown) 621 | pThis->OnKey(pThis, KEY_CTRL, bDown); 622 | 623 | bool bExtended = (HIWORD(lParam) & KF_EXTENDED) != 0; 624 | eKey = bExtended ? KEY_RIGHTCTRL : KEY_LEFTCTRL; 625 | 626 | pThis->m_bKeyDownCtrl[(int)(eKey == KEY_RIGHTCTRL)] = bDown; 627 | 628 | if (!bDown && pThis->m_bKeyDownCtrl[0] == bDown && pThis->m_bKeyDownCtrl[1] == bDown) 629 | pThis->OnKey(pThis, KEY_CTRL, bDown); 630 | } 631 | else if (wParam == VK_MENU) 632 | { 633 | if (bDown && pThis->m_bKeyDownAlt[0] != bDown && pThis->m_bKeyDownAlt[1] != bDown) 634 | pThis->OnKey(pThis, KEY_ALT, bDown); 635 | 636 | bool bExtended = (HIWORD(lParam) & KF_EXTENDED) != 0; 637 | eKey = bExtended ? KEY_RIGHTALT : KEY_LEFTALT; 638 | 639 | pThis->m_bKeyDownAlt[(int)(eKey == KEY_RIGHTALT)] = bDown; 640 | 641 | if (!bDown && pThis->m_bKeyDownAlt[0] == bDown && pThis->m_bKeyDownAlt[1] == bDown) 642 | pThis->OnKey(pThis, KEY_ALT, bDown); 643 | } 644 | 645 | pThis->OnKey(pThis, eKey, bDown); 646 | } 647 | return 1; 648 | break; 649 | } 650 | case WM_CHAR: 651 | pThis->m_iLastEvents |= E_EVENT_CHAR; 652 | pThis->OnChar(pThis, (unsigned long)wParam); 653 | break; 654 | 655 | case WM_NCCALCSIZE: 656 | if (pThis->m_bManualSizing && wParam == TRUE && lParam != NULL) 657 | { 658 | NCCALCSIZE_PARAMS* pSizeParams = (NCCALCSIZE_PARAMS*)lParam; 659 | if (pSizeParams != NULL && IsZoomed(hWnd)) 660 | { 661 | pSizeParams->rgrc[0].left += pThis->m_oBorderThickness.left; 662 | pSizeParams->rgrc[0].top += pThis->m_oBorderThickness.top; 663 | pSizeParams->rgrc[0].right -= pThis->m_oBorderThickness.right; 664 | pSizeParams->rgrc[0].bottom -= pThis->m_oBorderThickness.bottom; 665 | } 666 | return 0; 667 | } 668 | break; 669 | case WM_NCHITTEST: 670 | if (pThis->m_bBorderless && pThis->BorderlessHoveredArea.IsSet()) 671 | { 672 | switch (pThis->BorderlessHoveredArea(pThis, (signed short)lParam, (signed short)(lParam >> 16))) 673 | { 674 | case E_HOVEREDAREA_MENU: 675 | return HTMENU; 676 | case E_HOVEREDAREA_CAPTION: 677 | return HTCAPTION; 678 | case E_HOVEREDAREA_MINIMIZE: 679 | return HTMINBUTTON; 680 | case E_HOVEREDAREA_MAXIMIZE: 681 | return HTMAXBUTTON; 682 | case E_HOVEREDAREA_CLOSE: 683 | return HTCLOSE; 684 | case E_HOVEREDAREA_NONE: 685 | break; 686 | } 687 | } 688 | 689 | if (pThis->m_bManualSizing) 690 | { 691 | RECT oWindowRect; 692 | const RECT& oBorder = pThis->m_oBorderThickness; 693 | 694 | GetWindowRect(pThis->m_pHandle, &oWindowRect); 695 | 696 | // Cast DWORD to short to recover signed value 697 | int iAbsoluteX = (short)LOWORD(lParam); 698 | int iAbsoluteY = (short)HIWORD(lParam); 699 | int iX = iAbsoluteX - oWindowRect.left; 700 | int iY = iAbsoluteY - oWindowRect.top; 701 | 702 | if (iX < oBorder.left && iY < oBorder.top) 703 | return HTTOPLEFT; 704 | else if (iX > oWindowRect.right - oWindowRect.left - oBorder.right && iY < oBorder.top) 705 | return HTTOPRIGHT; 706 | else if (iX > oWindowRect.right - oWindowRect.left - oBorder.right && iY > oWindowRect.bottom - oWindowRect.top - oBorder.bottom) 707 | return HTBOTTOMRIGHT; 708 | else if (iX < oBorder.left && iY > oWindowRect.bottom - oWindowRect.top - oBorder.bottom) 709 | return HTBOTTOMLEFT; 710 | else if (iX < oBorder.left) 711 | return HTLEFT; 712 | else if (iY < oBorder.top) 713 | return HTTOP; 714 | else if (iX > oWindowRect.right - oWindowRect.left - oBorder.right) 715 | return HTRIGHT; 716 | else if (iY > oWindowRect.bottom - oWindowRect.top - oBorder.bottom) 717 | return HTBOTTOM; 718 | else 719 | return HTCLIENT; 720 | } 721 | break; 722 | case WM_NCLBUTTONDOWN: 723 | if (pThis->m_bManualSizing) 724 | { 725 | switch (wParam) 726 | { 727 | case HTLEFT: 728 | case HTTOPLEFT: 729 | case HTBOTTOMLEFT: 730 | case HTRIGHT: 731 | case HTTOPRIGHT: 732 | case HTBOTTOMRIGHT: 733 | case HTTOP: 734 | case HTBOTTOM: 735 | SetCapture(hWnd); 736 | pThis->m_bSizing = true; 737 | pThis->m_iSizingMode = wParam; 738 | return 0; 739 | } 740 | } 741 | 742 | pThis->m_iActiveHitMousePosition = wParam; 743 | 744 | if (pThis->m_bBorderless && (wParam == HTMINBUTTON || wParam == HTMAXBUTTON || wParam == HTCLOSE)) 745 | { 746 | // Skip deafult system behaviour to skip buttons drawing in bordeless mode 747 | return 0; 748 | } 749 | break; 750 | case WM_NCLBUTTONUP: 751 | { 752 | if (pThis->m_bSizing) 753 | { 754 | ReleaseCapture(); 755 | pThis->m_bSizing = false; 756 | } 757 | 758 | WPARAM iActiveHitMousePotition = pThis->m_iActiveHitMousePosition; 759 | pThis->m_iActiveHitMousePosition = HTNOWHERE; 760 | 761 | // Self manage buttons 762 | if (iActiveHitMousePotition == wParam) 763 | { 764 | if (wParam == HTMINBUTTON) 765 | { 766 | ShowWindow(hWnd, SW_MINIMIZE); 767 | return 0; 768 | } 769 | else if (wParam == HTMAXBUTTON) 770 | { 771 | WINDOWPLACEMENT oWindowPlacement; 772 | GetWindowPlacement(hWnd, &oWindowPlacement); 773 | ShowWindow(hWnd, oWindowPlacement.showCmd == SW_MAXIMIZE ? SW_RESTORE : SW_MAXIMIZE); 774 | return 0; 775 | } 776 | else if (wParam == HTCLOSE) 777 | { 778 | SendMessage(hWnd, WM_CLOSE, 0, 0); 779 | return 0; 780 | } 781 | } 782 | break; 783 | } 784 | case WM_SETCURSOR: 785 | if (LOWORD(lParam) == HTCLIENT) // Inside window 786 | { 787 | switch (pThis->m_eCursor) 788 | { 789 | case E_CURSOR_NONE: 790 | ::SetCursor(NULL); 791 | break; 792 | case E_CURSOR_ARROW: 793 | ::SetCursor(LoadCursor(NULL, IDC_ARROW)); 794 | break; 795 | case E_CURSOR_TEXT_INPUT: // When hovering over InputText, etc. 796 | ::SetCursor(LoadCursor(NULL, IDC_IBEAM)); 797 | break; 798 | case E_CURSOR_HAND: // Unused 799 | ::SetCursor(LoadCursor(NULL, IDC_HAND)); 800 | break; 801 | case E_CURSOR_RESIZE_NS: // Unused 802 | ::SetCursor(LoadCursor(NULL, IDC_SIZENS)); 803 | break; 804 | case E_CURSOR_RESIZE_EW: // When hovering over a column 805 | ::SetCursor(LoadCursor(NULL, IDC_SIZEWE)); 806 | break; 807 | case E_CURSOR_RESIZE_NESW: // Unused 808 | ::SetCursor(LoadCursor(NULL, IDC_SIZENESW)); 809 | break; 810 | case E_CURSOR_RESIZE_NWSE: // When hovering over the bottom-right corner of a window 811 | ::SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); 812 | break; 813 | } 814 | return 1; 815 | } 816 | break; 817 | case WM_DROPFILES: 818 | { 819 | pThis->m_iLastEvents |= E_EVENT_FILES_DROPPED; 820 | HDROP hDrop = (HDROP)wParam; 821 | 822 | int iFileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); 823 | char** pFiles = (char**)malloc(sizeof(char**) * iFileCount); 824 | for (int i = 0; i < iFileCount; ++i) 825 | { 826 | pFiles[i] = (char*)malloc(sizeof(char) * MAX_PATH); 827 | DragQueryFile(hDrop, i, pFiles[i], MAX_PATH); 828 | } 829 | 830 | POINT oDropPoint; 831 | DragQueryPoint(hDrop, &oDropPoint); 832 | 833 | DragFinish(hDrop); 834 | 835 | DropFiles oFiles; 836 | oFiles.iCount = iFileCount; 837 | oFiles.pFiles = pFiles; 838 | oFiles.oPosition.x = oDropPoint.x; 839 | oFiles.oPosition.y = oDropPoint.y; 840 | 841 | pThis->OnDropFiles(pThis, oFiles); 842 | 843 | for (int i = 0; i < iFileCount; ++i) 844 | { 845 | free(pFiles[i]); 846 | } 847 | free(pFiles); 848 | 849 | return 1; 850 | } 851 | } 852 | } 853 | return DefWindowProc(hWnd, iMsg, wParam, lParam); 854 | } 855 | }; 856 | 857 | const char* const EasyWindowWin32::c_pClassName = "EasyWindowWin32"; 858 | 859 | bool EasyWindowWin32::s_bClassInitialized = false; 860 | EasyWindowWin32::EKey EasyWindowWin32::s_iTranslateKeys[c_iMaxKeys]; 861 | 862 | EasyWindow* EasyWindow::Create(const char* pTitle, int iWidth, int iHeight, bool bClientSize, EasyWindow* pParent, EWindowStyle eStyle, EWindowFlags eFlags) 863 | { 864 | return new EasyWindowWin32(pTitle, iWidth, iHeight, bClientSize, pParent, eStyle, eFlags); 865 | } 866 | 867 | #endif //_WIN32 || _WIN64 || _MSC_VER 868 | --------------------------------------------------------------------------------