INT WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, INT) { gInstance = Instance; INITCOMMONCONTROLSEX icc; // Initialise common controls. icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icc); // Initialize menu bar and set the check boxes' initial state gMainMenu = LoadMenu(Instance, "mainMenu"); CheckMenuItem(gMainMenu, IDM_DISPLAYVIDEO, MF_BYCOMMAND | MF_CHECKED); const char* mainClassName = "KinectBoard"; gKinectON = LoadIcon(Instance, "kinect1-ON"); gKinectOFF = LoadIcon(Instance, "kinect2-OFF"); HBRUSH mainBrush = CreateSolidBrush(RGB(0, 0, 0)); // Define a class for our main window WNDCLASSEX WindowClass; ZeroMemory(&WindowClass, sizeof(WNDCLASSEX)); WindowClass.cbSize = sizeof(WNDCLASSEX); WindowClass.style = 0; WindowClass.lpfnWndProc = &MainProc; WindowClass.cbClsExtra = 0; WindowClass.cbWndExtra = 0; WindowClass.hInstance = Instance; WindowClass.hIcon = gKinectOFF; WindowClass.hCursor = LoadCursor(nullptr, IDC_ARROW); WindowClass.hbrBackground = mainBrush; WindowClass.lpszMenuName = "mainMenu"; WindowClass.lpszClassName = mainClassName; WindowClass.hIconSm = gKinectOFF; RegisterClassEx(&WindowClass); MSG Message; HACCEL hAccel; /* ===== Make two windows to display ===== */ // Set the size, but not the position RECT winSize = {0, 0, static_cast<int>(ImageVars::width), static_cast<int>(ImageVars::height)}; AdjustWindowRect( &winSize, WS_SYSMENU | WS_CAPTION | WS_VISIBLE | WS_MINIMIZEBOX | WS_CLIPCHILDREN, TRUE); // window has menu // Create a new window to be used for the lifetime of the application gDisplayWindow = CreateWindowEx(0, mainClassName, "KinectBoard", WS_SYSMENU | WS_CAPTION | WS_VISIBLE | WS_MINIMIZEBOX | WS_CLIPCHILDREN, (GetSystemMetrics(SM_CXSCREEN) - (winSize.right - winSize.left)) / 2, (GetSystemMetrics(SM_CYSCREEN) - (winSize.bottom - winSize.top)) / 2, winSize.right - winSize.left, // returns image width (resized as window) winSize.bottom - winSize.top, // returns image height (resized as window) nullptr, gMainMenu, Instance, nullptr); /* ======================================= */ // Load keyboard accelerators hAccel = LoadAccelerators(gInstance, "KeyAccel"); gProjectorKnt.setScreenRect(gCurrentMonitor.dim); // Make window receive video stream events and image from Kinect instance gProjectorKnt.registerVideoWindow(gDisplayWindow); gProjectorKnt.startVideoStream(); gProjectorKnt.startDepthStream(); gProjectorKnt.enableColor(Processing::Red); gProjectorKnt.enableColor(Processing::Blue); while (GetMessage(&Message, nullptr, 0, 0) > 0) { if (!TranslateAccelerator(gDisplayWindow, // Handle to receiving window hAccel, // Handle to active accelerator table &Message)) // Message data { // If a message was waiting in the message queue, process it TranslateMessage(&Message); DispatchMessage(&Message); } } DestroyIcon(gKinectON); DestroyIcon(gKinectOFF); UnregisterClass(mainClassName, Instance); UnregisterClass("monitorButton", Instance); TestScreen::unregisterClass(); return Message.wParam; }
LRESULT CALLBACK MainProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { HWND recalibButton = CreateWindowEx(0, "BUTTON", "Recalibrate", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 9, ImageVars::height - 9 - 28, 100, 28, handle, reinterpret_cast<HMENU>(IDC_RECALIBRATE_BUTTON), gInstance, nullptr); SendMessage(recalibButton, WM_SETFONT, reinterpret_cast<WPARAM>(GetStockObject(DEFAULT_GUI_FONT)), MAKELPARAM(FALSE, 0)); HWND toggleStreamButton = CreateWindowEx(0, "BUTTON", "Start", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, ImageVars::width - 9 - 100, ImageVars::height - 9 - 28, 100, 28, handle, reinterpret_cast<HMENU>(IDC_STREAMTOGGLE_BUTTON), gInstance, nullptr); SendMessage(toggleStreamButton, WM_SETFONT, reinterpret_cast<WPARAM>(GetStockObject(DEFAULT_GUI_FONT)), MAKELPARAM(FALSE, 0)); break; } case WM_COMMAND: { int wmId = LOWORD(wParam); switch (wmId) { case IDC_RECALIBRATE_BUTTON: { // If there is no Kinect connected, don't bother trying to retrieve images if (gProjectorKnt.isVideoStreamRunning()) { TestScreen testWin(gInstance, false); testWin.create(gCurrentMonitor.dim); testWin.setColor(Processing::Red); testWin.display(); // Give Kinect time to get image w/ test pattern in it std::this_thread::sleep_for(std::chrono::milliseconds(750)); gProjectorKnt.setCalibImage(Processing::Red); testWin.setColor(Processing::Blue); testWin.display(); // Give Kinect time to get image w/ test pattern in it std::this_thread::sleep_for(std::chrono::milliseconds(750)); gProjectorKnt.setCalibImage(Processing::Blue); gProjectorKnt.calibrate(); } break; } case IDC_STREAMTOGGLE_BUTTON: { // If button was pressed from video display window if (handle == gProjectorKnt.getRegisteredVideoWindow()) { if (gProjectorKnt.isVideoStreamRunning()) { gProjectorKnt.stopVideoStream(); } else { gProjectorKnt.startVideoStream(); } } // If button was pressed from depth image display window else if (handle == gProjectorKnt.getRegisteredDepthWindow()) { if (gProjectorKnt.isDepthStreamRunning()) { gProjectorKnt.stopDepthStream(); } else { gProjectorKnt.startDepthStream(); } } break; } case IDM_STARTTRACK: { gProjectorKnt.setMouseTracking(true); MessageBox(handle, "Mouse tracking has been enabled", "Mouse Tracking", MB_ICONINFORMATION | MB_OK); break; } case IDM_STOPTRACK: { gProjectorKnt.setMouseTracking(false); MessageBox(handle, "Mouse tracking has been disabled", "Mouse Tracking", MB_ICONINFORMATION | MB_OK); break; } case IDM_DISPLAYVIDEO: { // Check "Display Video" and uncheck "Display Depth" CheckMenuItem(gMainMenu, IDM_DISPLAYVIDEO, MF_BYCOMMAND | MF_CHECKED); CheckMenuItem(gMainMenu, IDM_DISPLAYDEPTH, MF_BYCOMMAND | MF_UNCHECKED); // Stop depth stream from displaying and switch to video stream gProjectorKnt.registerVideoWindow(gDisplayWindow); gProjectorKnt.unregisterDepthWindow(); /* Change button text to correctly represent status of stream * displayed */ char windowText[16]; if (gProjectorKnt.isVideoStreamRunning()) { // Change Start/Stop button text to "Stop" EnumChildWindows(handle, StartStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); } else { // Change Start/Stop button text to "Start" EnumChildWindows(handle, StopStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); } break; } case IDM_DISPLAYDEPTH: { // Uncheck "Display Video" and check "Display Depth" CheckMenuItem(gMainMenu, IDM_DISPLAYVIDEO, MF_BYCOMMAND | MF_UNCHECKED); CheckMenuItem(gMainMenu, IDM_DISPLAYDEPTH, MF_BYCOMMAND | MF_CHECKED); // Stop video stream from displaying and switch to depth stream gProjectorKnt.unregisterVideoWindow(); gProjectorKnt.registerDepthWindow(gDisplayWindow); /* Change button text to correctly represent status of stream * displayed */ char windowText[16]; if (gProjectorKnt.isDepthStreamRunning()) { // Change Start/Stop button text to "Stop" EnumChildWindows(handle, StartStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); } else { // Change Start/Stop button text to "Start" EnumChildWindows(handle, StopStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); } break; } case IDM_CHANGEMONITOR: { DialogBox(gInstance, MAKEINTRESOURCE(IDD_MONITORBOX), handle, MonitorCbk); break; } case IDM_HELP: { HINSTANCE status = ShellExecute(handle, "open", "help.html", nullptr, "help", SW_SHOWNORMAL); if (reinterpret_cast<int>(status) <= 32) { std::string errorMsg = "Could not open help file\nError: "; MessageBox(handle, (errorMsg + to_string(status)).c_str(), "Error", MB_ICONERROR | MB_OK); } // TODO: Finish writing HTML help page break; } case IDM_ABOUT: { DialogBox(gInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), handle, AboutCbk); break; } } break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(handle, &ps); // If we're painting the video display window if (handle == gProjectorKnt.getRegisteredVideoWindow()) { gProjectorKnt.displayVideo(gDisplayWindow, 0, 0, hdc); } // If we're painting the depth image display window else if (handle == gProjectorKnt.getRegisteredDepthWindow()) { gProjectorKnt.displayDepth(gDisplayWindow, 0, 0, hdc); } EndPaint(handle, &ps); break; } case WM_DESTROY: { // If the display window is being closed, exit the application if (handle == gDisplayWindow) { PostQuitMessage(0); } break; } case WM_KINECT_VIDEOSTART: { // Change video window icon to green because the stream started PostMessage(handle, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(gKinectON)); PostMessage(handle, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(gKinectON)); // Change Start/Stop button text to "Stop" char windowText[16]; EnumChildWindows(handle, StartStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); break; } case WM_KINECT_VIDEOSTOP: { // Change video window icon to red because the stream stopped PostMessage(handle, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(gKinectOFF)); PostMessage(handle, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(gKinectOFF)); // Change Start/Stop button text to "Start" char windowText[16]; EnumChildWindows(handle, StopStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); break; } case WM_KINECT_DEPTHSTART: { // Change depth window icon to green because the stream started PostMessage(handle, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(gKinectON)); PostMessage(handle, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(gKinectON)); // Change Start/Stop button text to "Stop" char windowText[16]; EnumChildWindows(handle, StartStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); break; } case WM_KINECT_DEPTHSTOP: { // Change depth window icon to red because the stream stopped PostMessage(handle, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(gKinectOFF)); PostMessage(handle, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(gKinectOFF)); // Change Start/Stop button text to "Start" char windowText[16]; EnumChildWindows(handle, StopStreamChildCbk, reinterpret_cast<LPARAM>(windowText)); break; } default: { return DefWindowProc(handle, message, wParam, lParam); } } return 0; }