eMousePos DockingCont::isInRect(HWND hwnd, int x, int y) { RECT rc; eMousePos ret = posOutside; ::GetWindowRect(hwnd, &rc); ScreenRectToClientRect(hwnd, &rc); if (_isTopCaption == TRUE) { if ((x > rc.left) && (x < rc.right-HIGH_CAPTION) && (y > rc.top) && (y < rc.bottom)) { ret = posCaption; } else if ((x > rc.right-(12+CLOSEBTN_POS_LEFT)) && (x < (rc.right-CLOSEBTN_POS_LEFT)) && (y > (rc.top+CLOSEBTN_POS_TOP)) && (y < (rc.bottom-CLOSEBTN_POS_TOP))) { ret = posClose; } } else { if ((x > rc.left) && (x < rc.right) && (y > rc.top+HIGH_CAPTION) && (y < rc.bottom)) { ret = posCaption; } else if ((x > rc.left+CLOSEBTN_POS_LEFT) && (x < rc.right-CLOSEBTN_POS_LEFT) && (y > (rc.top+CLOSEBTN_POS_TOP)) && (y < (rc.top+(12+CLOSEBTN_POS_LEFT)))) { ret = posClose; } } return ret; }
static void OnSize(HWND hDlg, LPARAM lParam) { TWindowData * pData = GetDialogData(hDlg); HWND hTabCtrl = GetDlgItem(hDlg, IDC_TAB); HWND hButton = GetDlgItem(hDlg, IDC_EXIT); RECT rect; int nHeight = HIWORD(lParam); int nWidth = LOWORD(lParam); int x, y, cx, cy; // Sanity check for zero size if(pData != NULL && nWidth != 0 && nHeight != 0) { // If the dialog hasn't done the initial resize, // we have to remember the relative sizes of the tab control // and the exit button if(!pData->bInitialResizeDone) { // Save the relative position of the tab control GetWindowRect(hTabCtrl, &rect); ScreenRectToClientRect(hDlg, &rect); pData->nTabInnerTop = rect.top; pData->nTabInnerLeft = rect.left; pData->nTabInnerRight = pData->nTabInnerTop; pData->nTabInnerBottom = pData->nTabInnerTop; // Save position of the "Exit" button GetWindowRect(hButton, &rect); pData->nButtonInnerRight = pData->nTabInnerRight + (rect.right - rect.left); pData->nButtonInnerBottom = pData->nTabInnerBottom + (rect.bottom - rect.top); // Update the inner bottom margin of the tab cobtrol pData->nTabInnerBottom = pData->nButtonInnerBottom + 8; pData->bInitialResizeDone = true; } // Resize the tab control cx = nWidth - (pData->nTabInnerLeft + pData->nTabInnerRight); cy = nHeight - (pData->nTabInnerTop + pData->nTabInnerBottom); TabCtrl_Resize(hTabCtrl, pData->nTabInnerLeft, pData->nTabInnerTop, cx, cy); // Move the Exit button x = nWidth - pData->nButtonInnerRight; y = nHeight - pData->nButtonInnerBottom; SetWindowPos(hButton, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } }
static void ArrangeDialogButton(HWND hDlg, RECT & ClientRect, UINT nIDButton, int nDeltaY) { HWND hWndChild = GetDlgItem(hDlg, nIDButton); RECT rect; int y; if(hWndChild != NULL) { // Retrieve the child rect of the button GetWindowRect(hWndChild, &rect); ScreenRectToClientRect(hDlg, &rect); // Move the control y = (ClientRect.bottom - ClientRect.top) + nDeltaY - (ClientRect.bottom - rect.top); SetWindowPos(hWndChild, NULL, rect.left, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } }
// // Process function of caption bar // LRESULT DockingCont::runProcCaption(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { static ToolTip toolTip; switch (Message) { case WM_LBUTTONDOWN: { _isMouseDown = TRUE; if (isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)) == posClose) { _isMouseClose = TRUE; _isMouseOver = TRUE; // start hooking hWndServer = _hCaption; winVer ver = (NppParameters::getInstance())->getWinVersion(); hookMouse = ::SetWindowsHookEx(ver >= WV_W2K?WH_MOUSE_LL:WH_MOUSE, (HOOKPROC)hookProcMouse, _hInst, 0); if (!hookMouse) { DWORD dwError = ::GetLastError(); TCHAR str[128]; ::wsprintf(str, TEXT("GetLastError() returned %lu"), dwError); ::MessageBox(NULL, str, TEXT("SetWindowsHookEx(MOUSE) failed"), MB_OK | MB_ICONERROR); } ::RedrawWindow(hwnd, NULL, NULL, TRUE); } focusClient(); return TRUE; } case WM_LBUTTONUP: { _isMouseDown = FALSE; if (_isMouseClose == TRUE) { // end hooking ::UnhookWindowsHookEx(hookMouse); if (_isMouseOver == TRUE) { doClose(); } _isMouseClose = FALSE; _isMouseOver = FALSE; } focusClient(); return TRUE; } case WM_LBUTTONDBLCLK: { if (isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)) == posCaption) ::SendMessage(_hParent, DMM_FLOATALL, 0, (LPARAM)this); focusClient(); return TRUE; } case WM_MOUSEMOVE: { POINT pt = {0}; // get correct cursor position ::GetCursorPos(&pt); ::ScreenToClient(_hCaption, &pt); if (_isMouseDown == TRUE) { if (_isMouseClose == FALSE) { // keep sure that button is still down and within caption if ((wParam == MK_LBUTTON) && (isInRect(hwnd, pt.x, pt.y) == posCaption)) { _dragFromTab = FALSE; NotifyParent(DMM_MOVE); _isMouseDown = FALSE; } else { _isMouseDown = FALSE; } } else { BOOL isMouseOver = _isMouseOver; _isMouseOver = (isInRect(hwnd, pt.x, pt.y) == posClose ? TRUE : FALSE); // if state is changed draw new if (_isMouseOver != isMouseOver) { ::SetFocus(NULL); ::RedrawWindow(hwnd, NULL, NULL, TRUE); } } } else if (_bCapTTHover == FALSE) { _hoverMPos = isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)); if ((_bCaptionTT == TRUE) || (_hoverMPos == posClose)) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = hwnd; tme.dwFlags = TME_LEAVE | TME_HOVER; tme.dwHoverTime = 1000; _bCapTTHover = _TrackMouseEvent(&tme); } } else if ((_bCapTTHover == TRUE) && (_hoverMPos != isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)))) { toolTip.destroy(); _bCapTTHover = FALSE; } return TRUE; } case WM_MOUSEHOVER: { RECT rc = {0}; POINT pt = {0}; // get mouse position ::GetCursorPos(&pt); toolTip.init(_hInst, hwnd); if (_hoverMPos == posCaption) { toolTip.Show(rc, _pszCaption.c_str(), pt.x, pt.y + 20); } else { toolTip.Show(rc, TEXT("Close"), pt.x, pt.y + 20); } return TRUE; } case WM_MOUSELEAVE: { toolTip.destroy(); _bCapTTHover = FALSE; return TRUE; } case WM_SIZE: { ::GetWindowRect(hwnd, &_rcCaption); ScreenRectToClientRect(hwnd, &_rcCaption); break; } case WM_SETTEXT: { ::RedrawWindow(hwnd, NULL, NULL, TRUE); return TRUE; } default: break; } return ::CallWindowProc(_hDefaultCaptionProc, hwnd, Message, wParam, lParam); }
// Arranging the dialog layout for empty dialogs, where the controls need to be created static void CreateDialogLayout_Empty(TFlagDialogData * pData) { TFlagInfo * pFlags; HWND hWndGroup = GetDlgItem(pData->hDlg, IDC_GROUPBOX); HWND hWndFirst = GetDlgItem(pData->hDlg, IDC_CHILD_MUSTER); HWND hWndChild = hWndFirst; RECT DialogRect; // Rectangle of the dialog (screen-relative) RECT ParentRect; // Rectangle of the dialog's parent (screen-relative) RECT ClientRect; // Rectangle of the dialog client area (screen-relative) RECT GroupRect; // Rectangle of the group box RECT CheckBoxRect; // Rectangle of the checkbox DWORD dwFlags = pData->dwFlags; int nChecked = BST_UNCHECKED; int x, y, cx, cy; // Get the size of the parent if(pData->hWndParent != NULL) GetWindowRect(pData->hWndParent, &ParentRect); else SystemParametersInfo(SPI_GETWORKAREA, 0, &ParentRect, FALSE); // Set the dialog title SetWindowTextRc(pData->hDlg, pData->nIDTitle); // Get the size of the dialog and the "master" settings GetWindowRect(pData->hDlg, &DialogRect); GetClientRect(pData->hDlg, &ClientRect); pData->hFont = (HFONT)SendMessage(hWndChild, WM_GETFONT, 0, 0); // Get the position of the groupbox and the child muster GetWindowRect(hWndGroup, &GroupRect); ScreenRectToClientRect(pData->hDlg, &GroupRect); GetWindowRect(hWndChild, &CheckBoxRect); ScreenRectToClientRect(pData->hDlg, &CheckBoxRect); // Get the settings of the "master" checkbox pData->dwExStyle = GetWindowLong(hWndChild, GWL_EXSTYLE); pData->dwStyle = GetWindowLong(hWndChild, GWL_STYLE) & ~(WS_TABSTOP | WS_GROUP); // Create all switch items for(pFlags = pData->pFlags; pFlags->szFlagText != NULL; pFlags++) { // Create the (next) switch item hWndChild = CreateSwitchItem(pData, pFlags, CheckBoxRect, hWndChild); nChecked = BST_UNCHECKED; // Check/uncheck the box if(pFlags->dwValue != FLAG_SEPARATOR) { // Do we have radio buttons? if(pData->IsValueDialog) { if(dwFlags == pFlags->dwValue) { nChecked = BST_CHECKED; dwFlags = 0; } } else { if((dwFlags & pFlags->dwMask) == pFlags->dwValue) { nChecked = BST_CHECKED; dwFlags = dwFlags & ~pFlags->dwValue; } } // Check or uncheck the button Button_SetCheck(hWndChild, nChecked); } // The next control will be created dynamically, 6 dialog units lower hWndChild = NULL; } // If there is at least one flag unused, we need to create an extra button if(dwFlags != 0) { LoadString(g_hInst, IDS_CUSTOM_VALUE, pData->szCustomValue, _maxchars(pData->szCustomValue)); pData->ExtraFlag.dwValue = dwFlags; pData->ExtraFlag.dwMask = 0xFFFFFFFF; pData->ExtraFlag.szFlagText = pData->szCustomValue; hWndChild = CreateSwitchItem(pData, &pData->ExtraFlag, CheckBoxRect, hWndChild); Button_SetCheck(hWndChild, BST_CHECKED); } // Resize the group box so it covers all buttons cx = (GroupRect.right - GroupRect.left); cy = (GroupRect.bottom - GroupRect.top) + pData->nDeltaY; SetWindowPos(hWndGroup, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); // Move the buttons ArrangeDialogButton(pData->hDlg, ClientRect, IDC_SELECT_ALL, pData->nDeltaY); ArrangeDialogButton(pData->hDlg, ClientRect, IDC_CLEAR_ALL, pData->nDeltaY); ArrangeDialogButton(pData->hDlg, ClientRect, IDOK, pData->nDeltaY); // Resize and center the dialog cx = (DialogRect.right - DialogRect.left); cy = (DialogRect.bottom - DialogRect.top) + pData->nDeltaY; x = ParentRect.left + ((ParentRect.right - ParentRect.left) - cx) / 2; y = ParentRect.top + ((ParentRect.bottom - ParentRect.top) - cy) / 2; SetWindowPos(pData->hDlg, NULL, x, y, cx, cy, SWP_NOZORDER | SWP_NOACTIVATE); }