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; }
// Message handler for "Change Monitor" box BOOL CALLBACK MonitorCbk(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { RECT windowSize; GetClientRect(hDlg, &windowSize); // Store button box's width and height unsigned int boxWidth = windowSize.right - windowSize.left - 18; unsigned int boxHeight = 89 - 9; // All buttons are scaled to fit within this window HWND buttonBox = CreateWindowEx(0, "STATIC", "", WS_VISIBLE | WS_CHILD, 9, 9, boxWidth, boxHeight, hDlg, reinterpret_cast<HMENU>(NULL), gInstance, nullptr); EnumDisplayMonitors(nullptr, // List all monitors nullptr, // Don't clip area MonitorEnumProc, reinterpret_cast<LPARAM>(&gMonitors) // User data ); /* Find coordinates of box that will fit all current desktop monitors * * Starts within 0 x 0 rectangle and expands it as necessary * * Then creates buttons within based upon that rectangle and matches * them with their corresponding monitor */ RECT desktopDims = {0, 0, 0, 0}; for (auto& monitor : gMonitors) { if (monitor.dim.left < desktopDims.left) { desktopDims.left = monitor.dim.left; } if (monitor.dim.right > desktopDims.right) { desktopDims.right = monitor.dim.right; } if (monitor.dim.top < desktopDims.top) { desktopDims.top = monitor.dim.top; } if (monitor.dim.bottom > desktopDims.bottom) { desktopDims.bottom = monitor.dim.bottom; } } // Store desktop width and height unsigned int desktopWidth = desktopDims.right - desktopDims.left; unsigned int desktopHeight = desktopDims.bottom - desktopDims.top; char buttonText[2]; bool isButtonClicked = false; // Create a button that will represent the monitor in this dialog for (auto& monitor : gMonitors) { isButtonClicked = gCurrentMonitor.dim.left == monitor.dim.left && gCurrentMonitor.dim.right == monitor.dim.right && gCurrentMonitor.dim.top == monitor.dim.top && gCurrentMonitor.dim.bottom == monitor.dim.bottom; if (isButtonClicked) { std::strcpy(buttonText, "*"); } else { std::strcpy(buttonText, " "); } monitor.activeButton = CreateWindowEx(0, "BUTTON", (buttonText + to_string(monitor.dim.right - monitor.dim.left) + " x " + to_string(monitor.dim.bottom - monitor.dim.top) + " ").c_str(), WS_VISIBLE | WS_CHILD, boxWidth * (monitor.dim.left - desktopDims.left) / desktopWidth, boxHeight * (monitor.dim.top - desktopDims.top) / desktopHeight, boxWidth * (monitor.dim.right - monitor.dim.left) / desktopWidth, boxHeight * (monitor.dim.bottom - monitor.dim.top) / desktopHeight, buttonBox, reinterpret_cast<HMENU>(NULL), gInstance, nullptr); if (isButtonClicked) { gCurrentMonitor = monitor; } } return TRUE; } case WM_PARENTNOTIFY: { if (LOWORD(wParam) == WM_LBUTTONDOWN) { /* This message is only received when a button other than OK was * pressed in the dialog window */ /* Convert cursor coordinates from dialog to desktop, * since the button's position is also in desktop coordinates */ POINT cursorPos = {LOWORD(lParam), HIWORD(lParam)}; MapWindowPoints(hDlg, nullptr, &cursorPos, 1); RECT buttonPos; // Change where test pattern will be drawn if button was clicked on for (auto& monitor : gMonitors) { GetWindowRect(monitor.activeButton, &buttonPos); // If cursor is within boundaries of button if (cursorPos.x > buttonPos.left && cursorPos.x < buttonPos.right && cursorPos.y > buttonPos.top && cursorPos.y < buttonPos.bottom) { // Remove asterisk from previous button's text SetWindowText(gCurrentMonitor.activeButton, (" " + to_string(gCurrentMonitor.dim.right - gCurrentMonitor.dim.left) + " x " + to_string(gCurrentMonitor.dim.bottom - gCurrentMonitor.dim.top) + " ").c_str()); // Set new selected button gCurrentMonitor = monitor; // Add asterisk to new button's text SetWindowText(gCurrentMonitor.activeButton, ("*" + to_string(gCurrentMonitor.dim.right - gCurrentMonitor.dim.left) + " x " + to_string(gCurrentMonitor.dim.bottom - gCurrentMonitor.dim.top) + " ").c_str()); } } } break; } case WM_COMMAND: { if (LOWORD(wParam) == IDOK) { for (auto& monitor : gMonitors) { DestroyWindow(monitor.activeButton); } gMonitors.clear(); gCurrentMonitor.activeButton = nullptr; // Give Kinect correct monitor dimensions so mouse is moved to proper position gProjectorKnt.setScreenRect(gCurrentMonitor.dim); EndDialog(hDlg, LOWORD(wParam)); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg , LOWORD(wParam)); } break; } case WM_CLOSE: { EndDialog(hDlg, 0); break; } default: { return FALSE; } } return TRUE; }