static VOID MonSelUpdateMonitorsInfo(IN OUT PMONITORSELWND infoPtr, IN BOOL bRepaint) { RECT rcExtSurface, rcExtDisplay; DWORD Index; /* Recalculate rcExtent */ MonSelUpdateExtent(infoPtr); infoPtr-> CanDisplay = infoPtr->MonitorsCount != 0 && (infoPtr->ClientSize.cx > (2 * (infoPtr->Margin.cx + infoPtr->SelectionFrame.cx))) && (infoPtr->ClientSize.cy > (2 * (infoPtr->Margin.cy + infoPtr->SelectionFrame.cy))); if (infoPtr->CanDisplay) { /* Calculate the rectangle on the control in which may be painted */ rcExtSurface.left = infoPtr->Margin.cx; rcExtSurface.top = infoPtr->Margin.cy; rcExtSurface.right = rcExtSurface.left + infoPtr->ClientSize.cx - (2 * infoPtr->Margin.cx); rcExtSurface.bottom = rcExtSurface.top + infoPtr->ClientSize.cy - (2 * infoPtr->Margin.cy); /* Calculate the rectangle on the control that is actually painted on */ rcExtDisplay.left = rcExtDisplay.top = 0; rcExtDisplay.right = infoPtr->rcExtent.right - infoPtr->rcExtent.left; rcExtDisplay.bottom = infoPtr->rcExtent.bottom - infoPtr->rcExtent.top; ScaleRectSizeFit(&rcExtSurface, &rcExtDisplay); infoPtr->rcOldMonitors = infoPtr->rcMonitors; infoPtr->rcMonitors = rcExtDisplay; /* Now that we know in which area all monitors are located, calculate the monitors selection rectangles on the screen */ for (Index = 0; Index < infoPtr->MonitorsCount; Index++) { MonSelMonInfoToRect(&infoPtr->MonitorInfo[Index], &rcExtDisplay); MonSelScaleRectRelative(&infoPtr->rcExtent, &rcExtDisplay, &infoPtr->rcMonitors, &infoPtr->Monitors[Index].rc); } MonSelResetMonitors(infoPtr); if (bRepaint) MonSelRepaint(infoPtr); } else if (bRepaint) { InvalidateRect(infoPtr->hSelf, NULL, TRUE); } }
static LRESULT CALLBACK MonitorSelWndProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { PMONITORSELWND infoPtr; LRESULT Ret = 0; infoPtr = (PMONITORSELWND)GetWindowLongPtrW(hwnd, 0); if (infoPtr == NULL && uMsg != WM_CREATE) { goto HandleDefaultMessage; } switch (uMsg) { case WM_PAINT: case WM_PRINTCLIENT: { PAINTSTRUCT ps; HDC hDC; if (wParam != 0) { if (!GetUpdateRect(hwnd, &ps.rcPaint, TRUE)) { break; } hDC = (HDC)wParam; } else { hDC = BeginPaint(hwnd, &ps); if (hDC == NULL) { break; } } if (infoPtr->CanDisplay) { MonSelPaint(infoPtr, hDC, &ps.rcPaint); } if (wParam == 0) { EndPaint(hwnd, &ps); } break; } case WM_MOUSEMOVE: { POINT pt; if (!(wParam & MK_LBUTTON)) { MonSelCancelDragging(infoPtr); break; } if (infoPtr->LeftBtnDown) { pt.x = (LONG)LOWORD(lParam); pt.y = (LONG)HIWORD(lParam); MonSelDrag(infoPtr, &pt); } break; } case WM_RBUTTONDOWN: { if (!(infoPtr->ControlExStyle & MSLM_EX_SELECTONRIGHTCLICK)) break; /* Fall through */ } case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: { INT Index; POINT pt; if (!infoPtr->HasFocus) SetFocus(infoPtr->hSelf); pt.x = (LONG)LOWORD(lParam); pt.y = (LONG)HIWORD(lParam); Index = MonSelHitTest(infoPtr, &pt); if (Index >= 0 || (infoPtr->ControlExStyle & MSLM_EX_ALLOWSELECTNONE)) { MonSelSetCurSelMonitor(infoPtr, Index, TRUE); } if (Index >= 0 && (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK)) { infoPtr->LeftBtnDown = TRUE; MonSelInitDragging(infoPtr, (DWORD)Index, &pt); } /* Fall through */ } case WM_MBUTTONDOWN: { if (!infoPtr->HasFocus) SetFocus(hwnd); break; } case WM_RBUTTONUP: { MonSelContextMenu(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); break; } case WM_LBUTTONUP: { MonSelCancelDragging(infoPtr); infoPtr->LeftBtnDown = FALSE; break; } case WM_GETDLGCODE: { INT virtKey; virtKey = (lParam != 0 ? (INT)((LPMSG)lParam)->wParam : 0); switch (virtKey) { case VK_TAB: { /* Change the UI status */ SendMessage(GetAncestor(hwnd, GA_PARENT), WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); break; } } Ret |= DLGC_WANTARROWS; if (infoPtr->ControlExStyle & MSLM_EX_SELECTBYNUMKEY) Ret |= DLGC_WANTCHARS; break; } case WM_SETFOCUS: { infoPtr->HasFocus = TRUE; MonSelRepaintSelected(infoPtr); break; } case WM_KILLFOCUS: { infoPtr->HasFocus = FALSE; MonSelCancelDragging(infoPtr); MonSelRepaintSelected(infoPtr); break; } case WM_UPDATEUISTATE: { DWORD OldUIState; Ret = DefWindowProcW(hwnd, uMsg, wParam, lParam); OldUIState = infoPtr->UIState; switch (LOWORD(wParam)) { case UIS_SET: infoPtr->UIState |= HIWORD(wParam); break; case UIS_CLEAR: infoPtr->UIState &= ~HIWORD(wParam); break; } if (infoPtr->UIState != OldUIState) MonSelRepaintSelected(infoPtr); break; } case WM_SETFONT: { Ret = (LRESULT)MonSelChangeFont(infoPtr, (HFONT)wParam, (BOOL)LOWORD(lParam)); break; } case WM_SIZE: { infoPtr->ClientSize.cx = LOWORD(lParam); infoPtr->ClientSize.cy = HIWORD(lParam); /* Don't let MonSelUpdateMonitorsInfo repaint the control because this won't work properly in case the control was sized down! */ MonSelUpdateMonitorsInfo(infoPtr, FALSE); InvalidateRect(infoPtr->hSelf, NULL, TRUE); break; } case WM_GETFONT: { Ret = (LRESULT)infoPtr->hFont; break; } case WM_ENABLE: { infoPtr->Enabled = ((BOOL)wParam != FALSE); MonSelRepaint(infoPtr); break; } case WM_STYLECHANGED: { if (wParam == GWL_STYLE) { unsigned int OldEnabled = infoPtr->Enabled; infoPtr->Enabled = !(((LPSTYLESTRUCT)lParam)->styleNew & WS_DISABLED); if (OldEnabled != infoPtr->Enabled) MonSelRepaint(infoPtr); } break; } case WM_KEYDOWN: { INT Index; if (infoPtr->ControlExStyle & MSLM_EX_SELECTBYARROWKEY) { switch (wParam) { case VK_UP: case VK_LEFT: { Index = infoPtr->SelectedMonitor; if (infoPtr->MonitorsCount != 0) { if (Index < 0) Index = 0; else if (Index > 0) Index--; } if (Index >= 0) { MonSelSetCurSelMonitor(infoPtr, Index, TRUE); } break; } case VK_DOWN: case VK_RIGHT: { Index = infoPtr->SelectedMonitor; if (infoPtr->MonitorsCount != 0) { if (Index < 0) Index = (INT)infoPtr->MonitorsCount - 1; else if (Index < (INT)infoPtr->MonitorsCount - 1) Index++; } if (infoPtr->SelectedMonitor < (INT)infoPtr->MonitorsCount) { MonSelSetCurSelMonitor(infoPtr, Index, TRUE); } break; } } } break; } case WM_CHAR: { if ((infoPtr->ControlExStyle & MSLM_EX_SELECTBYNUMKEY) && wParam >= '1' && wParam <= '9') { INT Index = (INT)(wParam - '1'); if (Index < (INT)infoPtr->MonitorsCount) { MonSelSetCurSelMonitor(infoPtr, Index, TRUE); } } break; } case MSLM_SETMONITORSINFO: { Ret = MonSelSetMonitorsInfo(infoPtr, (DWORD)wParam, (const MONSL_MONINFO *)lParam); break; } case MSLM_GETMONITORSINFO: { Ret = MonSelGetMonitorsInfo(infoPtr, (DWORD)wParam, (PMONSL_MONINFO)lParam); break; } case MSLM_GETMONITORINFOCOUNT: { Ret = infoPtr->MonitorsCount; break; } case MSLM_HITTEST: { Ret = MonSelHitTest(infoPtr, (const POINT *)wParam); break; } case MSLM_SETCURSEL: { Ret = MonSelSetCurSelMonitor(infoPtr, (INT)wParam, FALSE); break; } case MSLM_GETCURSEL: { Ret = infoPtr->SelectedMonitor; break; } case MSLM_SETMONITORINFO: { Ret = MonSelSetMonitorInfo(infoPtr, (INT)wParam, (const MONSL_MONINFO *)lParam); break; } case MSLM_GETMONITORINFO: { Ret = MonSelGetMonitorInfo(infoPtr, (INT)wParam, (PMONSL_MONINFO)lParam); break; } case MSLM_SETEXSTYLE: { Ret = MonSelSetExtendedStyle(infoPtr, (DWORD)lParam); break; } case MSLM_GETEXSTYLE: { Ret = MonSelGetExtendedStyle(infoPtr); break; } case MSLM_GETMONITORRECT: { Ret = (LRESULT)MonSelGetMonitorRect(infoPtr, (INT)wParam, (PRECT)lParam); break; } case WM_CREATE: { infoPtr = (PMONITORSELWND) HeapAlloc(GetProcessHeap(), 0, sizeof(MONITORSELWND)); if (infoPtr == NULL) { Ret = (LRESULT)-1; break; } ZeroMemory(infoPtr, sizeof(MONITORSELWND)); infoPtr->hSelf = hwnd; infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; infoPtr->Enabled = !(((LPCREATESTRUCTW)lParam)->style & WS_DISABLED); infoPtr->UIState = SendMessage(hwnd, WM_QUERYUISTATE, 0, 0); SetWindowLongPtrW(hwnd, 0, (LONG_PTR)infoPtr); MonSelCreate(infoPtr); break; } case WM_DESTROY: { MonSelDestroy(infoPtr); HeapFree(GetProcessHeap(), 0, infoPtr); SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)NULL); break; } default: { HandleDefaultMessage: Ret = DefWindowProcW(hwnd, uMsg, wParam, lParam); break; } } return Ret; }