// // PSDLG.CPP // Page Sorter Dialog // // Copyright Microsoft 1998- // // PRECOMP #include "precomp.h" static const DWORD s_helpIds[] = { IDC_PS_THUMBNAILS, IDH_CONF_PAGESORT_MAIN, IDC_PS_GOTO, IDH_CONF_PAGESORT_GOTO, IDC_PS_DELETE, IDH_CONF_PAGESORT_DEL, IDC_PS_INSERT_BEFORE, IDH_CONF_PAGESORT_BEFORE, IDC_PS_INSERT_AFTER, IDH_CONF_PAGESORT_AFTER, 0,0 }; // // PageSortDlgProc() // Dialog message handler for the page sort dialog. We have to set the // real LRESULT return value in some cases. // INT_PTR PageSortDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { BOOL fHandled = FALSE; PAGESORT * pps = (PAGESORT *)::GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_DROPFILES: g_pMain->OnDropFiles((HDROP)wParam); fHandled = TRUE; break; case WM_INITDIALOG: OnInitDialog(hwnd, (PAGESORT *)lParam); fHandled = TRUE; break; case WM_MEASUREITEM: OnMeasureItem(hwnd, (UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); fHandled = TRUE; break; case WM_DRAWITEM: OnDrawItem(hwnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam); fHandled = TRUE; break; case WM_DELETEITEM: OnDeleteItem(hwnd, (UINT)wParam, (LPDELETEITEMSTRUCT)lParam); fHandled = TRUE; break; case WM_LBTRACKPOINT: // This gets sent to us from the listbox; see if the user is dragging OnStartDragDrop(pps, (UINT)wParam, LOWORD(lParam), HIWORD(lParam)); fHandled = TRUE; break; case WM_MOUSEMOVE: WhileDragging(pps, LOWORD(lParam), HIWORD(lParam)); fHandled = TRUE; break; case WM_LBUTTONUP: case WM_CAPTURECHANGED: // If we're dragging, complete the drag/drop OnEndDragDrop(pps, (message == WM_LBUTTONUP), (short)LOWORD(lParam), (short)HIWORD(lParam)); fHandled = TRUE; break; case WM_PALETTECHANGED: // Repaint the thumbnail list ::InvalidateRect(::GetDlgItem(hwnd, IDC_PS_THUMBNAILS), NULL, TRUE); fHandled = TRUE; break; case WM_COMMAND: OnCommand(pps, GET_WM_COMMAND_ID(wParam, lParam), GET_WM_COMMAND_CMD(wParam, lParam), GET_WM_COMMAND_HWND(wParam, lParam)); fHandled = TRUE; break; case WM_SETCURSOR: fHandled = OnSetCursor(pps, (HWND)wParam, LOWORD(lParam), HIWORD(lParam)); break; case WM_CONTEXTMENU: DoHelpWhatsThis(wParam, s_helpIds); fHandled = TRUE; break; case WM_HELP: DoHelp(lParam, s_helpIds); fHandled = TRUE; break; // // Private PageSortDlg messages // case WM_PS_ENABLEPAGEOPS: ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); pps->fPageOpsAllowed = (wParam != 0); EnableButtons(pps); fHandled = TRUE; break; case WM_PS_LOCKCHANGE: ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); EnableButtons(pps); fHandled = TRUE; break; case WM_PS_PAGECLEARIND: ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); OnPageClearInd(pps, (WB_PAGE_HANDLE)wParam); fHandled = TRUE; break; case WM_PS_PAGEDELIND: ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); OnPageDeleteInd(pps, (WB_PAGE_HANDLE)wParam); fHandled = TRUE; break; case WM_PS_PAGEORDERUPD: ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); OnPageOrderUpdated(pps); fHandled = TRUE; break; } return(fHandled); } // // OnInitDialog() // WM_INITDIALOG handler // void OnInitDialog(HWND hwnd, PAGESORT * pps) { int nCount; RECT rc; RECT rcWindow; HWND hwndList; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnInitDialog"); ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); // Save this away ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pps); // Get our listbox pps->hwnd = hwnd; // Also put our HWND in WbMainWindow ASSERT(g_pMain); g_pMain->m_hwndPageSortDlg = hwnd; // // Get the drag/drop cursors we use // pps->hCursorDrag = ::LoadCursor(g_hInstance, MAKEINTRESOURCE(DRAGPAGECURSOR)); pps->hCursorNoDrop = ::LoadCursor(NULL, IDC_NO); pps->hCursorNormal = ::LoadCursor(NULL, IDC_ARROW); pps->hCursorCurrent = pps->hCursorNormal; // Convert the cur page to a page number pps->iCurPageNo = (int) g_pwbCore->WBP_PageNumberFromHandle((WB_PAGE_HANDLE)pps->hCurPage); // // Insert items, with empty data (we render thumbnail bitmap the first // time we draw ite). // hwndList = ::GetDlgItem(hwnd, IDC_PS_THUMBNAILS); nCount = g_pwbCore->WBP_ContentsCountPages(); // LB_SETCOUNT doesn't work on NT 4.0; must use add string while (nCount > 0) { ::SendMessage(hwndList, LB_ADDSTRING, 0, 0); nCount--; } ASSERT(::SendMessage(hwndList, LB_GETCOUNT, 0, 0) == (LRESULT)g_pwbCore->WBP_ContentsCountPages()); // Select the current page ::SendMessage(hwndList, LB_SETCURSEL, pps->iCurPageNo - 1, 0); // // Set the original button page op state // EnableButtons(pps); // // We can receive dropped files // DragAcceptFiles(hwnd, TRUE); } // // OnMeasureItem() // void OnMeasureItem(HWND hwnd, UINT id, LPMEASUREITEMSTRUCT lpmis) { RECT rcClient; ASSERT(id == IDC_PS_THUMBNAILS); ASSERT(!IsBadReadPtr(lpmis, sizeof(MEASUREITEMSTRUCT))); // // We want the slots to be square, although the page is wider than it // is high. // ::GetClientRect(::GetDlgItem(hwnd, id), &rcClient); rcClient.bottom -= rcClient.top; lpmis->itemWidth = rcClient.bottom; lpmis->itemHeight = rcClient.bottom; } // // OnDeleteItem() // We need to delete the bitmap for the item, if there is one // void OnDeleteItem(HWND hwnd, UINT id, LPDELETEITEMSTRUCT lpdis) { HBITMAP hbmp; ASSERT(id == IDC_PS_THUMBNAILS); ASSERT(!IsBadReadPtr(lpdis, sizeof(DELETEITEMSTRUCT))); hbmp = (HBITMAP)lpdis->itemData; if (hbmp != NULL) { ASSERT(GetObjectType(hbmp) == OBJ_BITMAP); ::DeleteBitmap(hbmp); } } // // OnDrawItem() // Draws the thumbnail. If there isn't a cached bitmap, we create one for // the page. The page number is the same as the item index + 1. // void OnDrawItem(HWND hwnd, UINT id, LPDRAWITEMSTRUCT lpdi) { HWND hwndList; WB_PAGE_HANDLE hPage; HPALETTE hPalette; HPALETTE hOldPalette1 = NULL; HPALETTE hOldPalette2 = NULL; HBITMAP hBitmap = NULL; HBITMAP hOldBitmap = NULL; HDC hdcMem = NULL; HBRUSH hbr; HPEN hpen; TCHAR szPageNum[8]; COLORREF clrOld; int nMode; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnDrawItem"); ASSERT(id == IDC_PS_THUMBNAILS); ASSERT(!IsBadReadPtr(lpdi, sizeof(DRAWITEMSTRUCT))); hwndList = ::GetDlgItem(hwnd, id); // // Is this within the proper range? // if (lpdi->itemID == -1) { WARNING_OUT(("OnDrawItem: bogus item id")); goto Done; } if (g_pwbCore->WBP_PageHandleFromNumber(lpdi->itemID+1, &hPage) != 0) { ERROR_OUT(("OnDrawItem: can't get page handle")); goto Done; } // // Account for the horizontal scroll bar; to get around whacky listbox // sizing bugs, we needed to fake the height out by including the scroll // bar in the item height. // lpdi->rcItem.bottom -= ::GetSystemMetrics(SM_CYHSCROLL); hdcMem = ::CreateCompatibleDC(lpdi->hDC); if (!hdcMem) { ERROR_OUT(("OnDrawItem: can't create compatible dc")); goto Done; } // // Realize our palette into the DC // hPalette = PG_GetPalette(); if (hPalette != NULL) { hOldPalette1 = ::SelectPalette(lpdi->hDC, hPalette, FALSE); ::RealizePalette(lpdi->hDC); hOldPalette2 = ::SelectPalette(hdcMem, hPalette, FALSE); } // // Do we have the image for this page created yet? If not, create it // now. // hBitmap = (HBITMAP)lpdi->itemData; if (hBitmap == NULL) { hBitmap = ::CreateCompatibleBitmap(lpdi->hDC, RENDERED_WIDTH+2, RENDERED_HEIGHT+2); if (!hBitmap) { ERROR_OUT(("OnDrawItem: can't create compatible bitmap")); goto Done; } } hOldBitmap = SelectBitmap(hdcMem, hBitmap); if ((HBITMAP)lpdi->itemData == NULL) { // // Fill the bitmap with the background color, framed so it looks // like a page. // hbr = SelectBrush(hdcMem, ::GetSysColorBrush(COLOR_WINDOW)); ::Rectangle(hdcMem, 0, 0, RENDERED_WIDTH+2, RENDERED_HEIGHT+2); SelectBrush(hdcMem, hbr); // // Render the page // ::SaveDC(hdcMem); // Set the attributes to compress the whole page into a // thumbnail at the relevant position for the cache index. ::SetMapMode(hdcMem, MM_ANISOTROPIC); ::SetWindowExtEx(hdcMem, DRAW_WIDTH, DRAW_HEIGHT, NULL); ::SetViewportOrgEx(hdcMem, 1, 1, NULL); ::SetViewportExtEx(hdcMem, RENDERED_WIDTH, RENDERED_HEIGHT, NULL); // Draw the page into the cache bitmap ::SetStretchBltMode(hdcMem, STRETCH_DELETESCANS); PG_Draw(hPage, hdcMem, TRUE); // Restore the DC atrributes ::RestoreDC(hdcMem, -1); // Set the item data ::SendMessage(hwndList, LB_SETITEMDATA, lpdi->itemID, (LPARAM)hBitmap); } // // Fill the background with the selection or window color depending // on the state. // if (lpdi->itemState & ODS_SELECTED) ::FillRect(lpdi->hDC, &lpdi->rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT)); else ::FillRect(lpdi->hDC, &lpdi->rcItem, ::GetSysColorBrush(COLOR_WINDOW)); if (lpdi->itemState & ODS_FOCUS) ::DrawFocusRect(lpdi->hDC, &lpdi->rcItem); // // Blt the page bitmap to the listbox item, centering it horizontally // and vertically. // ::BitBlt(lpdi->hDC, (lpdi->rcItem.left + lpdi->rcItem.right - (RENDERED_WIDTH + 2)) / 2, (lpdi->rcItem.top + lpdi->rcItem.bottom - (RENDERED_HEIGHT + 2)) / 2, RENDERED_WIDTH + 2, RENDERED_HEIGHT + 2, hdcMem, 0, 0, SRCCOPY); // // Draw number of page centered // wsprintf(szPageNum, "%d", lpdi->itemID+1); clrOld = ::SetTextColor(lpdi->hDC, ::GetSysColor(COLOR_GRAYTEXT)); nMode = ::SetBkMode(lpdi->hDC, TRANSPARENT); ::DrawText(lpdi->hDC, szPageNum, lstrlen(szPageNum), &lpdi->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE); ::SetBkMode(lpdi->hDC, nMode); ::SetTextColor(lpdi->hDC, clrOld); Done: if (hOldBitmap) { SelectBitmap(hdcMem, hOldBitmap); } if (hOldPalette2) { ::SelectPalette(hdcMem, hOldPalette2, FALSE); } if (hOldPalette1) { ::SelectPalette(lpdi->hDC, hOldPalette1, FALSE); } if (hdcMem) { ::DeleteDC(hdcMem); } } // // OnSetCursor // If the set is for us, handles the WM_SETCURSOR message and returns TRUE // that we handled it, and TRUE via the window LRESULT. // BOOL OnSetCursor(PAGESORT * pps, HWND hwnd, UINT uiHit, UINT msg) { // Check that this message is for the main window if (hwnd == pps->hwnd) { // If the cursor is now in the client area, set the cursor if (uiHit == HTCLIENT) { ::SetCursor(pps->hCursorCurrent); } else { // Restore the cursor to the standard arrow ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); } ::SetWindowLongPtr(pps->hwnd, DWLP_MSGRESULT, TRUE); return(TRUE); } else { return(FALSE); } } // // OnCommand() // void OnCommand(PAGESORT * pps, UINT id, UINT cmd, HWND hwndCtl) { switch (id) { case IDC_PS_INSERT_BEFORE: if (cmd == BN_CLICKED) { InsertPage(pps, INSERT_BEFORE); } break; case IDC_PS_INSERT_AFTER: if (cmd == BN_CLICKED) { InsertPage(pps, INSERT_AFTER); } break; case IDC_PS_GOTO: if (cmd == BN_CLICKED) { pps->iCurPageNo = (int)::SendDlgItemMessage(pps->hwnd, IDC_PS_THUMBNAILS, LB_GETCURSEL, 0, 0) + 1; OnCommand(pps, IDOK, BN_CLICKED, NULL); } break; case IDC_PS_DELETE: if (cmd == BN_CLICKED) { OnDelete(pps); } break; case IDC_PS_THUMBNAILS: switch (cmd) { case LBN_DBLCLK: OnCommand(pps, IDC_PS_GOTO, BN_CLICKED, NULL); break; } break; case IDOK: case IDCANCEL: if (cmd == BN_CLICKED) { // Clear out WbMainWindow ASSERT(g_pMain); g_pMain->m_hwndPageSortDlg = NULL; // Get the current page pps->hCurPage = PG_GetPageNumber(pps->iCurPageNo); ::EndDialog(pps->hwnd, id); } break; } } // // EnableButtons // Enable (or disable) the dialog buttons appropriately // // void EnableButtons(PAGESORT * pps) { MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::EnableButtons"); ASSERT(!IsBadWritePtr(pps, sizeof(PAGESORT))); // If another user currently has a lock on the contents, disable the // delete and insert buttons. BOOL bLocked = WB_Locked(); UINT uiCountPages = (UINT)::SendDlgItemMessage(pps->hwnd, IDC_PS_THUMBNAILS, LB_GETCOUNT, 0, 0); ::EnableWindow(::GetDlgItem(pps->hwnd, IDC_PS_DELETE), (!bLocked && (uiCountPages > 1) && pps->fPageOpsAllowed)); ::EnableWindow(::GetDlgItem(pps->hwnd, IDC_PS_INSERT_BEFORE), (!bLocked && (uiCountPages < WB_MAX_PAGES) && pps->fPageOpsAllowed)); ::EnableWindow(::GetDlgItem(pps->hwnd, IDC_PS_INSERT_AFTER), (!bLocked && (uiCountPages < WB_MAX_PAGES) && pps->fPageOpsAllowed)); } // // OnDelete // The user has clicked the Delete button // // void OnDelete(PAGESORT * pps) { int iResult; BOOL bWasPosted; HWND hwndList; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnDelete"); if (!pps->fPageOpsAllowed) return; // Display a message box with the relevant question if (g_pMain->UsersMightLoseData( &bWasPosted, pps->hwnd ) ) // bug NM4db:418 return; hwndList = ::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS); if( bWasPosted ) iResult = IDYES; else iResult = ::Message(pps->hwnd, IDS_DELETE_PAGE, IDS_DELETE_PAGE_MESSAGE, MB_YESNO | MB_ICONQUESTION ); // If the user wants to continue with the delete if (iResult == IDYES) { UINT uiRet; int iSel = (int)::SendMessage(hwndList, LB_GETCURSEL, 0, 0); // Get a pointer to the current page WB_PAGE_HANDLE hPage = PG_GetPageNumber(iSel + 1); ASSERT(::SendMessage(hwndList, LB_GETCOUNT, 0, 0) > 1); // Ensure that we have the Page Order lock. if (!g_pMain->GetLock(WB_LOCK_TYPE_CONTENTS, SW_HIDE)) { DefaultExceptionHandler(WBFE_RC_WB, WB_RC_LOCKED); return; } // Delete the page. We do not update the thumbnails yet - this // is done when the page deleted event is received. uiRet = g_pwbCore->WBP_PageDelete(hPage); if (uiRet != 0) { DefaultExceptionHandler(WBFE_RC_WB, uiRet); return; } // Show that the pages have been manipulated pps->fChanged = TRUE; } } // // // InsertPage // Insert a new (blank) page into the Whiteboard // // void InsertPage(PAGESORT * pps, UINT uiBeforeAfter) { int iSel; MLZ_EntryOut(ZONE_FUNCTION, "InsertPage"); if (!pps->fPageOpsAllowed) return; // Ensure that we have the Page Order lock. if (!g_pMain->GetLock(WB_LOCK_TYPE_CONTENTS, SW_HIDE)) return; iSel = (int)::SendDlgItemMessage(pps->hwnd, IDC_PS_THUMBNAILS, LB_GETCURSEL, 0, 0); // Add the new page to the list (throws an exception on failure) WB_PAGE_HANDLE hRefPage = PG_GetPageNumber(iSel + 1); UINT uiRet; WB_PAGE_HANDLE hPage; if (uiBeforeAfter == INSERT_BEFORE) { uiRet = g_pwbCore->WBP_PageAddBefore(hRefPage, &hPage); } else { uiRet = g_pwbCore->WBP_PageAddAfter(hRefPage, &hPage); } if (uiRet != 0) { DefaultExceptionHandler(WBFE_RC_WB, uiRet); return; } // Show that the contents have been changed by the dialog pps->fChanged = TRUE; // We'll get notified in a bit when the page order has changed. } // // OnPageClearInd() // Notification passed on AFTER page has been cleared // void OnPageClearInd(PAGESORT * pps, WB_PAGE_HANDLE hPage) { HWND hwndList; int iPageNo; RECT rcItem; HBITMAP hbmp; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnPageClearInd"); hwndList = ::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS); iPageNo = g_pwbCore->WBP_PageNumberFromHandle(hPage) - 1; // Is it in the right range? if ((iPageNo < 0) || (iPageNo >= ::SendMessage(hwndList, LB_GETCOUNT, 0, 0))) { ERROR_OUT(("Bogus page number %d", iPageNo)); return; } // Clear the item's data hbmp = (HBITMAP)::SendMessage(hwndList, LB_SETITEMDATA, iPageNo, 0); if (hbmp) ::DeleteBitmap(hbmp); // Repaint the rect if (::SendMessage(hwndList, LB_GETITEMRECT, iPageNo, (LPARAM)&rcItem)) { ::InvalidateRect(hwndList, &rcItem, TRUE); ::UpdateWindow(hwndList); } } // // OnPageDeleteInd() // Notification passed on BEFORE page has been deleted // void OnPageDeleteInd(PAGESORT * pps, WB_PAGE_HANDLE hPage) { HWND hwndList; int iPageNo; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnPageDeleteInd"); hwndList = ::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS); iPageNo = g_pwbCore->WBP_PageNumberFromHandle(hPage) - 1; // // If this isn't in the range we know about, we don't care // if ((iPageNo < 0) || (iPageNo >= ::SendMessage(hwndList, LB_GETCOUNT, 0, 0))) { ERROR_OUT(("Bogus page number %d", iPageNo)); return; } // // Delete this item from the list // ::SendMessage(hwndList, LB_DELETESTRING, iPageNo, 0); EnableButtons(pps); } // // OnPageOrderUpdated() // void OnPageOrderUpdated(PAGESORT * pps) { HWND hwndList; int nCount; int iCurSel; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::OnPageOrderUpdated"); hwndList = ::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS); // Remember the old selection iCurSel = (int)::SendMessage(hwndList, LB_GETCURSEL, 0, 0); // This is too complicated. We're just going to wipe out all the items // and their bitmaps ::SendMessage(hwndList, WM_SETREDRAW, FALSE, 0); ::SendMessage(hwndList, LB_RESETCONTENT, 0, 0); nCount = g_pwbCore->WBP_ContentsCountPages(); // // Adjust the current, and selected indeces // if (pps->iCurPageNo > nCount) { pps->iCurPageNo = nCount; } // Put back the same selected item if (iCurSel >= nCount) { iCurSel = nCount - 1; } // LB_SETCOUNT doesn't work on NT 4.0; must use add string while (nCount > 0) { ::SendMessage(hwndList, LB_ADDSTRING, 0, 0); nCount--; } ASSERT(::SendMessage(hwndList, LB_GETCOUNT, 0, 0) == (LRESULT)g_pwbCore->WBP_ContentsCountPages()); ::SendMessage(hwndList, LB_SETCURSEL, iCurSel, 0); ::SendMessage(hwndList, WM_SETREDRAW, TRUE, 0); ::InvalidateRect(hwndList, NULL, TRUE); ::UpdateWindow(hwndList); EnableButtons(pps); } // // OnStartDragDrop() // This checks if the user is trying to drag & drop pages around to // change the order via direct manipulation. We get a WM_LBTRACKPOINT // message when someone clicks in the listbox. We then see if they are // dragging; if so, we tell the listbox to ignore the mouse click, and we // ourselves capture the mouse moves. // void OnStartDragDrop(PAGESORT * pps, UINT iItem, int x, int y) { POINT pt; // // If no page order stuff is currently allowed, return // if (!pps->fPageOpsAllowed || WB_Locked()) { WARNING_OUT(("No direct manipulation of page order allowed")); return; } pt.x = x; pt.y = y; if (!DragDetect(pps->hwnd, pt)) { // If the mouse is no longer down, fake a button up to the listbox // because DragDetect() just swallowed it if (::GetKeyState(VK_LBUTTON) >= 0) { ::PostMessage(::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS), WM_LBUTTONUP, MK_LBUTTON, MAKELONG(x, y)); } return; } // We are dragging pps->fDragging = TRUE; pps->iPageDragging = iItem + 1; pps->hCursorCurrent = pps->hCursorDrag; ::SetCursor(pps->hCursorCurrent); ::SetCapture(pps->hwnd); // Tell the listbox to ignore the mouse-we're handling it // and blow off a double-click. ::SetWindowLongPtr(pps->hwnd, DWLP_MSGRESULT, 2); } // // WhileDragging() // void WhileDragging(PAGESORT * pps, int x, int y) { POINT pt; RECT rc; if (!pps->fDragging) return; pps->hCursorCurrent = pps->hCursorNoDrop; if (pps->fPageOpsAllowed && !WB_Locked()) { // // Is this over the listbox client? // ::GetClientRect(::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS), &rc); ::MapWindowPoints(::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS), pps->hwnd, (LPPOINT)&rc, 2); pt.x = x; pt.y = y; if (::PtInRect(&rc, pt)) { pps->hCursorCurrent = pps->hCursorDrag; } } ::SetCursor(pps->hCursorCurrent); } // // OnEndDragDrop // void OnEndDragDrop(PAGESORT * pps, BOOL fComplete, int x, int y) { POINT pt; RECT rc; int iItem; if (!pps->fDragging) return; // // Do this first; releasing capture will send a WM_CAPTURECHANGED // message. // pps->fDragging = FALSE; pps->hCursorCurrent = pps->hCursorNormal; ::SetCursor(pps->hCursorCurrent); // Release capture if (::GetCapture() == pps->hwnd) { ::ReleaseCapture(); } if (fComplete && pps->fPageOpsAllowed && !WB_Locked()) { HWND hwndList; POINT pt; // // Is this over the listbox client? // hwndList = ::GetDlgItem(pps->hwnd, IDC_PS_THUMBNAILS); ::GetClientRect(hwndList, &rc); ::MapWindowPoints(hwndList, pps->hwnd, (LPPOINT)&rc, 2); pt.x = x; pt.y = y; if (::PtInRect(&rc, pt)) { // // If there is no item at this point, use the last one // ::MapWindowPoints(pps->hwnd, hwndList, &pt, 1); iItem = (int)::SendMessage(hwndList, LB_ITEMFROMPOINT, 0, MAKELONG(pt.x, pt.y)); if (iItem == -1) iItem = (int)::SendMessage(hwndList, LB_GETCOUNT, 0, 0) - 1; if (g_pMain->GetLock(WB_LOCK_TYPE_CONTENTS, SW_HIDE)) { // Move the page MovePage(pps, pps->iPageDragging, iItem+1); } } } pps->iPageDragging = 0; } // // // Function: MovePage // // Purpose: Move a page in the core // // void MovePage(PAGESORT * pps, int iOldPageNo, int iNewPageNo) { int iCountPages; MLZ_EntryOut(ZONE_FUNCTION, "PageSortDlgProc::MovePage"); ASSERT(iNewPageNo > 0); ASSERT(iOldPageNo > 0); if (!pps->fPageOpsAllowed) return; // If the new page number is bigger than the number of pages, assume // that the last page is meant. iCountPages = (int)::SendDlgItemMessage(pps->hwnd, IDC_PS_THUMBNAILS, LB_GETCOUNT, 0, 0); if (iNewPageNo > iCountPages) { iNewPageNo = iCountPages; } // If no change will result, do nothing if ( (iNewPageNo != iOldPageNo) && (iNewPageNo != (iOldPageNo + 1))) { // If we are moving a page up the list we use move after to allow // the moving of a page to be the last page. If we are moving a page // down the list we use move before so that we can move a page to // be the first page. // it down. We check here which is meant. // Assume that we want to move the page up the list BOOL bMoveAfter = FALSE; if (iOldPageNo < iNewPageNo) { bMoveAfter = TRUE; iNewPageNo -= 1; } // Only do the move if we have requested to move the page to a new place if (iOldPageNo != iNewPageNo) { // get lock if (!g_pMain->GetLock(WB_LOCK_TYPE_CONTENTS, SW_HIDE)) return; UINT uiRet; WB_PAGE_HANDLE hOldPage = PG_GetPageNumber((UINT) iOldPageNo); WB_PAGE_HANDLE hNewPage = PG_GetPageNumber((UINT) iNewPageNo); // Move the page if (bMoveAfter) { uiRet = g_pwbCore->WBP_PageMove(hNewPage, hOldPage, PAGE_AFTER); } else { uiRet = g_pwbCore->WBP_PageMove(hNewPage, hOldPage, PAGE_BEFORE); } if (uiRet != 0) { DefaultExceptionHandler(WBFE_RC_WB, uiRet); return; } // Show that the pages have been manipulated pps->fChanged = TRUE; } } }