Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

winmgrc.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: winmgrc.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains 00007 * 00008 * History: 00009 * 20-Feb-1992 DarrinM Pulled functions from user\server. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 #define CONSOLE_WINDOW_CLASS (L"ConsoleWindowClass") 00016 00017 /***************************************************************************\ 00018 * GetWindowWord (API) 00019 * 00020 * Return a window word. Positive index values return application window words 00021 * while negative index values return system window words. The negative 00022 * indices are published in WINDOWS.H. 00023 * 00024 * History: 00025 * 20-Feb-1992 DarrinM Wrote. 00026 \***************************************************************************/ 00027 00028 WORD GetWindowWord( 00029 HWND hwnd, 00030 int index) 00031 { 00032 PWND pwnd; 00033 00034 pwnd = ValidateHwnd(hwnd); 00035 00036 if (pwnd == NULL) 00037 return 0; 00038 00039 /* 00040 * If it's a dialog window the window data is on the server side 00041 * We just call the "long" routine instead of have two thunks. 00042 * We know there is enough data if its DWLP_USER so we won't fault. 00043 */ 00044 if (TestWF(pwnd, WFDIALOGWINDOW) && (index == DWLP_USER)) { 00045 return (WORD)_GetWindowLong(pwnd, index, FALSE); 00046 } 00047 00048 return _GetWindowWord(pwnd, index); 00049 } 00050 00051 00052 BOOL FChildVisible( 00053 HWND hwnd) 00054 { 00055 PWND pwnd; 00056 00057 pwnd = ValidateHwnd(hwnd); 00058 00059 if (pwnd == NULL) 00060 return 0; 00061 00062 return (_FChildVisible(pwnd)); 00063 } 00064 00065 BOOL WINAPI AdjustWindowRectEx( 00066 LPRECT lpRect, 00067 DWORD dwStyle, 00068 BOOL bMenu, 00069 DWORD dwExStyle) 00070 { 00071 ConnectIfNecessary(); 00072 00073 return _AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); 00074 } 00075 00076 00077 int WINAPI GetClassNameW( 00078 HWND hwnd, 00079 LPWSTR lpClassName, 00080 int nMaxCount) 00081 { 00082 UNICODE_STRING strClassName; 00083 00084 strClassName.MaximumLength = (USHORT)(nMaxCount * sizeof(WCHAR)); 00085 strClassName.Buffer = lpClassName; 00086 return NtUserGetClassName(hwnd, FALSE, &strClassName); 00087 } 00088 00089 00090 HWND GetFocus(VOID) 00091 { 00092 return (HWND)NtUserGetThreadState(UserThreadStateFocusWindow); 00093 } 00094 00095 00096 HWND GetCapture(VOID) 00097 { 00098 /* 00099 * If no captures are currently taking place, just return NULL. 00100 */ 00101 if (gpsi->cCaptures == 0) { 00102 return NULL; 00103 } 00104 return (HWND)NtUserGetThreadState(UserThreadStateCaptureWindow); 00105 } 00106 00107 /***************************************************************************\ 00108 * AnyPopup (API) 00109 * 00110 * 00111 * 00112 * History: 00113 * 12-Nov-1990 DarrinM Ported. 00114 \***************************************************************************/ 00115 00116 BOOL AnyPopup(VOID) 00117 { 00118 PWND pwnd = _GetDesktopWindow(); 00119 00120 for (pwnd = REBASEPWND(pwnd, spwndChild); pwnd; pwnd = REBASEPWND(pwnd, spwndNext)) { 00121 00122 if ((pwnd->spwndOwner != NULL) && TestWF(pwnd, WFVISIBLE)) 00123 return TRUE; 00124 } 00125 00126 return FALSE; 00127 } 00128 00129 /***************************************************************************\ 00130 * GetInputState 00131 * 00132 * 00133 * 00134 * History: 00135 \***************************************************************************/ 00136 00137 BOOL GetInputState(VOID) 00138 { 00139 PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo; 00140 00141 if ((pcti == NULL) || (pcti->fsChangeBits & (QS_MOUSEBUTTON | QS_KEY))) 00142 return (BOOL)NtUserGetThreadState(UserThreadStateInputState); 00143 00144 return FALSE; 00145 } 00146 00147 /***************************************************************************\ 00148 * MapWindowPoints 00149 * 00150 * 00151 * 00152 * History: 00153 \***************************************************************************/ 00154 00155 int MapWindowPoints( 00156 HWND hwndFrom, 00157 HWND hwndTo, 00158 LPPOINT lppt, 00159 UINT cpt) 00160 { 00161 PWND pwndFrom; 00162 PWND pwndTo; 00163 00164 if (hwndFrom != NULL) { 00165 00166 if ((pwndFrom = ValidateHwnd(hwndFrom)) == NULL) 00167 return 0; 00168 00169 } else { 00170 00171 pwndFrom = NULL; 00172 } 00173 00174 if (hwndTo != NULL) { 00175 00176 00177 if ((pwndTo = ValidateHwnd(hwndTo)) == NULL) 00178 return 0; 00179 00180 } else { 00181 00182 pwndTo = NULL; 00183 } 00184 00185 return _MapWindowPoints(pwndFrom, pwndTo, lppt, cpt); 00186 } 00187 00188 /***************************************************************************\ 00189 * GetLastActivePopup 00190 * 00191 * 00192 * 00193 * History: 00194 \***************************************************************************/ 00195 00196 HWND GetLastActivePopup( 00197 HWND hwnd) 00198 { 00199 PWND pwnd = ValidateHwnd(hwnd); 00200 00201 if (pwnd == NULL) 00202 return NULL; 00203 00204 pwnd = _GetLastActivePopup(pwnd); 00205 00206 return HW(pwnd); 00207 } 00208 00209 /**************************************************************************\ 00210 * PtiWindow 00211 * 00212 * Gets the PTHREADINFO of window or NULL if not valid. 00213 * 00214 * 12-Feb-1997 JerrySh Created. 00215 \**************************************************************************/ 00216 00217 PTHREADINFO PtiWindow( 00218 HWND hwnd) 00219 { 00220 PHE phe; 00221 DWORD dw; 00222 WORD uniq; 00223 00224 dw = HMIndexFromHandle(hwnd); 00225 if (dw < gpsi->cHandleEntries) { 00226 phe = &gSharedInfo.aheList[dw]; 00227 if ((phe->bType == TYPE_WINDOW) && !(phe->bFlags & HANDLEF_DESTROY)) { 00228 uniq = HMUniqFromHandle(hwnd); 00229 if ( uniq == phe->wUniq 00230 #if !defined(_WIN64) && !defined(BUILD_WOW6432) 00231 || uniq == 0 00232 || uniq == HMUNIQBITS 00233 #endif 00234 ) { 00235 return phe->pOwner; 00236 } 00237 } 00238 } 00239 UserSetLastError(ERROR_INVALID_WINDOW_HANDLE); 00240 return NULL; 00241 } 00242 00243 /***************************************************************************\ 00244 * GetWindowThreadProcessId 00245 * 00246 * Get's windows process and thread ids. 00247 * 00248 * 24-Jun-1991 ScottLu Created. 00249 \***************************************************************************/ 00250 00251 DWORD GetWindowThreadProcessId( 00252 HWND hwnd, 00253 LPDWORD lpdwProcessId) 00254 { 00255 PTHREADINFO ptiWindow; 00256 DWORD dwThreadId; 00257 00258 if ((ptiWindow = PtiWindow(hwnd)) == NULL) 00259 return 0; 00260 00261 /* 00262 * For non-system threads get the info from the thread info structure 00263 */ 00264 if (ptiWindow == PtiCurrent()) { 00265 00266 if (lpdwProcessId != NULL) 00267 *lpdwProcessId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess); 00268 dwThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread); 00269 00270 } else { 00271 00272 /* 00273 * Make this better later on. 00274 */ 00275 if (lpdwProcessId != NULL) 00276 *lpdwProcessId = HandleToUlong(NtUserQueryWindow(hwnd, WindowProcess)); 00277 dwThreadId = HandleToUlong(NtUserQueryWindow(hwnd, WindowThread)); 00278 } 00279 00280 return dwThreadId; 00281 } 00282 00283 /***************************************************************************\ 00284 * GetScrollPos 00285 * 00286 * Returns the current position of a scroll bar 00287 * 00288 * !!! WARNING a similiar copy of this code is in server\sbapi.c 00289 * 00290 * History: 00291 \***************************************************************************/ 00292 00293 int GetScrollPos( 00294 HWND hwnd, 00295 int code) 00296 { 00297 PWND pwnd; 00298 00299 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00300 return 0; 00301 00302 switch (code) { 00303 case SB_CTL: 00304 return (int)SendMessageWorker(pwnd, SBM_GETPOS, 0, 0, FALSE); 00305 00306 case SB_HORZ: 00307 case SB_VERT: 00308 if (pwnd->pSBInfo != NULL) { 00309 PSBINFO pSBInfo = (PSBINFO)(REBASEALWAYS(pwnd, pSBInfo)); 00310 return (code == SB_VERT) ? pSBInfo->Vert.pos : pSBInfo->Horz.pos; 00311 } else { 00312 RIPERR0(ERROR_NO_SCROLLBARS, RIP_VERBOSE, ""); 00313 } 00314 break; 00315 00316 default: 00317 /* 00318 * Win3.1 validation layer code. 00319 */ 00320 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00321 } 00322 00323 return 0; 00324 } 00325 00326 /***************************************************************************\ 00327 * GetScrollRange 00328 * 00329 * !!! WARNING a similiar copy of this code is in server\sbapi.c 00330 * 00331 * History: 00332 * 16-May-1991 mikeke Changed to return BOOL 00333 \***************************************************************************/ 00334 00335 BOOL GetScrollRange( 00336 HWND hwnd, 00337 int code, 00338 LPINT lpposMin, 00339 LPINT lpposMax) 00340 { 00341 PSBINFO pSBInfo; 00342 PWND pwnd; 00343 00344 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00345 return FALSE; 00346 00347 switch (code) { 00348 case SB_CTL: 00349 SendMessageWorker(pwnd, SBM_GETRANGE, (WPARAM)lpposMin, (LPARAM)lpposMax, FALSE); 00350 return TRUE; 00351 00352 case SB_VERT: 00353 case SB_HORZ: 00354 if (pSBInfo = REBASE(pwnd, pSBInfo)) { 00355 PSBDATA pSBData; 00356 pSBData = (code == SB_VERT) ? &pSBInfo->Vert : &pSBInfo->Horz; 00357 *lpposMin = pSBData->posMin; 00358 *lpposMax = pSBData->posMax; 00359 } else { 00360 RIPERR0(ERROR_NO_SCROLLBARS, RIP_VERBOSE, ""); 00361 *lpposMin = 0; 00362 *lpposMax = 0; 00363 } 00364 00365 return TRUE; 00366 00367 default: 00368 /* 00369 * Win3.1 validation layer code. 00370 */ 00371 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00372 return FALSE; 00373 } 00374 } 00375 00376 /***************************************************************************\ 00377 * GetScrollInfo 00378 * 00379 * !!! WARNING a similiar copy of this code is in server\winmgrc.c 00380 * 00381 \***************************************************************************/ 00382 00383 BOOL GetScrollInfo( 00384 HWND hwnd, 00385 int code, 00386 LPSCROLLINFO lpsi) 00387 { 00388 PWND pwnd; 00389 PSBINFO pSBInfo; 00390 PSBDATA pSBData; 00391 00392 if (lpsi->cbSize != sizeof(SCROLLINFO)) { 00393 00394 if (lpsi->cbSize != sizeof(SCROLLINFO) - 4) { 00395 RIPMSG0(RIP_WARNING, "SCROLLINFO: Invalid cbSize"); 00396 return FALSE; 00397 00398 } else { 00399 RIPMSG0(RIP_WARNING, "SCROLLINFO: Invalid cbSize"); 00400 } 00401 } 00402 00403 if (lpsi->fMask & ~SIF_MASK) { 00404 RIPMSG0(RIP_WARNING, "SCROLLINFO: Invalid fMask"); 00405 return FALSE; 00406 } 00407 00408 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00409 return FALSE; 00410 00411 switch (code) { 00412 case SB_CTL: 00413 SendMessageWorker(pwnd, SBM_GETSCROLLINFO, 0, (LPARAM)lpsi, FALSE); 00414 return TRUE; 00415 00416 case SB_HORZ: 00417 case SB_VERT: 00418 if (pwnd->pSBInfo == NULL) { 00419 RIPERR0(ERROR_NO_SCROLLBARS, RIP_VERBOSE, ""); 00420 return FALSE; 00421 } 00422 00423 /* 00424 * Rebase rgwScroll so probing will work 00425 */ 00426 pSBInfo = (PSBINFO)REBASEALWAYS(pwnd, pSBInfo); 00427 00428 pSBData = (code == SB_VERT) ? &pSBInfo->Vert : &pSBInfo->Horz; 00429 00430 return(NtUserSBGetParms(hwnd, code, pSBData, lpsi)); 00431 00432 default: 00433 /* 00434 * Win3.1 validation layer code. 00435 */ 00436 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00437 return FALSE; 00438 } 00439 } 00440 00441 /****************************************************************************\ 00442 * _GetActiveWindow (API) 00443 * 00444 * 00445 * 23-Oct-1990 MikeHar Ported from Windows. 00446 * 12-Nov-1990 DarrinM Moved from getset.c to here. 00447 \****************************************************************************/ 00448 00449 HWND GetActiveWindow(VOID) 00450 { 00451 return (HWND)NtUserGetThreadState(UserThreadStateActiveWindow); 00452 } 00453 00454 /****************************************************************************\ 00455 * GetCursor 00456 * 00457 * 00458 * History: 00459 \****************************************************************************/ 00460 00461 HCURSOR GetCursor(VOID) 00462 { 00463 return (HCURSOR)NtUserGetThreadState(UserThreadStateCursor); 00464 } 00465 00466 /***************************************************************************\ 00467 * BOOL IsMenu(HMENU); 00468 * 00469 * Verifies that the handle passed in is a menu handle. 00470 * 00471 * Histroy: 00472 * 10-Jul-1992 MikeHar Created. 00473 \***************************************************************************/ 00474 00475 BOOL IsMenu( 00476 HMENU hMenu) 00477 { 00478 if (HMValidateHandle(hMenu, TYPE_MENU)) 00479 return TRUE; 00480 00481 return FALSE; 00482 } 00483 00484 /***************************************************************************\ 00485 * GetAppCompatFlags 00486 * 00487 * Compatibility flags for < Win 3.1 apps running on 3.1 00488 * 00489 * History: 00490 * 01-Apr-1992 ScottLu Created. 00491 * 04-May-1992 DarrinM Moved to USERRTL.DLL. 00492 \***************************************************************************/ 00493 00494 DWORD GetAppCompatFlags( 00495 PTHREADINFO pti) 00496 { 00497 UNREFERENCED_PARAMETER(pti); 00498 00499 ConnectIfNecessary(); 00500 00501 return GetClientInfo()->dwCompatFlags; 00502 } 00503 00504 /***************************************************************************\ 00505 * GetAppCompatFlags2 00506 * 00507 * Compatibility flags for <= wVer apps. Newer apps will get no hacks 00508 * from this DWORD. 00509 * 00510 * History: 00511 * 06-29-98 MCostea Created. 00512 \***************************************************************************/ 00513 00514 DWORD GetAppCompatFlags2( 00515 WORD wVer) 00516 { 00517 ConnectIfNecessary(); 00518 /* 00519 * Newer apps should behave, so they get no hacks 00520 */ 00521 if (wVer < GETAPPVER()) { 00522 return 0; 00523 } 00524 return GetClientInfo()->dwCompatFlags2; 00525 } 00526 00527 /**************************************************************************\ 00528 * IsWindowUnicode 00529 * 00530 * 25-Feb-1992 IanJa Created 00531 \**************************************************************************/ 00532 00533 BOOL IsWindowUnicode( 00534 IN HWND hwnd) 00535 { 00536 PWND pwnd; 00537 00538 00539 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00540 return FALSE; 00541 00542 return !TestWF(pwnd, WFANSIPROC); 00543 } 00544 00545 /**************************************************************************\ 00546 * TestWindowProcess 00547 * 00548 * 14-Nov-1994 JimA Created. 00549 \**************************************************************************/ 00550 00551 BOOL TestWindowProcess( 00552 PWND pwnd) 00553 { 00554 /* 00555 * If the threads are the same, don't bother going to the kernel 00556 * to get the window's process id. 00557 */ 00558 if (GETPTI(pwnd) == PtiCurrent()) { 00559 return TRUE; 00560 } 00561 00562 return (GetWindowProcess(HW(pwnd)) == GETPROCESSID()); 00563 } 00564 00565 /**************************************************************************\ 00566 * IsHungAppWindow 00567 * 00568 * 11-14-94 JimA Created. 00569 \**************************************************************************/ 00570 00571 BOOL IsHungAppWindow( 00572 HWND hwnd) 00573 { 00574 return (NtUserQueryWindow(hwnd, WindowIsHung) != NULL); 00575 } 00576 00577 /***************************************************************************\ 00578 * PtiCurrent 00579 * 00580 * Returns the THREADINFO structure for the current thread. 00581 * LATER: Get DLL_THREAD_ATTACH initialization working right and we won't 00582 * need this connect code. 00583 * 00584 * History: 00585 * 10-28-90 DavidPe Created. 00586 \***************************************************************************/ 00587 00588 PTHREADINFO PtiCurrent(VOID) 00589 { 00590 ConnectIfNecessary(); 00591 return (PTHREADINFO)NtCurrentTebShared()->Win32ThreadInfo; 00592 } 00593 00594 00595 /***************************************************************************\ 00596 * _AdjustWindowRectEx (API) 00597 * 00598 * 00599 * 00600 * History: 00601 * 10-24-90 darrinm Ported from Win 3.0. 00602 \***************************************************************************/ 00603 00604 BOOL _AdjustWindowRectEx( 00605 LPRECT lprc, 00606 LONG style, 00607 BOOL fMenu, 00608 DWORD dwExStyle) 00609 { 00610 // 00611 // Here we add on the appropriate 3D borders for old and new apps. 00612 // 00613 // Rules: 00614 // (1) Do nothing for windows that have 3D border styles. 00615 // (2) If the window has a dlgframe border (has a caption or is a 00616 // a dialog), then add on the window edge style. 00617 // (3) We NEVER add on the CLIENT STYLE. New apps can create 00618 // it if they want. This is because it screws up alignment 00619 // when the app doesn't know about it. 00620 // 00621 00622 if (NeedsWindowEdge(style, dwExStyle, GETAPPVER() >= VER40)) 00623 dwExStyle |= WS_EX_WINDOWEDGE; 00624 else 00625 dwExStyle &= ~WS_EX_WINDOWEDGE; 00626 00627 // 00628 // Space for a menu bar 00629 // 00630 if (fMenu) 00631 lprc->top -= SYSMET(CYMENU); 00632 00633 // 00634 // Space for a caption bar 00635 // 00636 if ((HIWORD(style) & HIWORD(WS_CAPTION)) == HIWORD(WS_CAPTION)) { 00637 lprc->top -= (dwExStyle & WS_EX_TOOLWINDOW) ? SYSMET(CYSMCAPTION) : SYSMET(CYCAPTION); 00638 } 00639 00640 // 00641 // Space for borders (window AND client) 00642 // 00643 { 00644 int cBorders; 00645 00646 // 00647 // Window AND Client borders 00648 // 00649 00650 if (cBorders = GetWindowBorders(style, dwExStyle, TRUE, TRUE)) 00651 InflateRect(lprc, cBorders*SYSMET(CXBORDER), cBorders*SYSMET(CYBORDER)); 00652 } 00653 00654 return TRUE; 00655 } 00656 00657 /***************************************************************************\ 00658 * ShowWindowNoRepaint 00659 \***************************************************************************/ 00660 00661 void ShowWindowNoRepaint(PWND pwnd) 00662 { 00663 HWND hwnd = HWq(pwnd); 00664 PCLS pcls = REBASE(pwnd, pcls); 00665 NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | 00666 SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | 00667 SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_NOACTIVATE | 00668 ((pcls->style & CS_SAVEBITS) ? SWP_CREATESPB : 0)); 00669 } 00670 00671 /***************************************************************************\ 00672 * AnimateBlend 00673 * 00674 * 6-Mar-1997 vadimg created 00675 \***************************************************************************/ 00676 00677 #define ALPHASTART 40 00678 #define ONEFRAME 10 00679 00680 BOOL AnimateBlend(PWND pwnd, HDC hdcScreen, HDC hdcImage, DWORD dwTime, BOOL fHide) 00681 { 00682 HWND hwnd = HWq(pwnd); 00683 SIZE size; 00684 POINT ptSrc = {0, 0}, ptDst; 00685 BLENDFUNCTION blend; 00686 DWORD dwElapsed; 00687 BYTE bAlpha = ALPHASTART; 00688 LARGE_INTEGER liFreq, liStart, liDiff; 00689 LARGE_INTEGER liIter; 00690 DWORD dwIter; 00691 00692 if (QueryPerformanceFrequency(&liFreq) == 0) 00693 return FALSE; 00694 00695 if (SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | 00696 WS_EX_LAYERED) == 0) 00697 return FALSE; 00698 00699 if (fHide) { 00700 /* 00701 * Give up the time slice and sleep just a touch to allow windows 00702 * below invalidated by the SetWindowLong(WS_EX_LAYERED) call to 00703 * repaint enough for the sprite to get good background image. 00704 */ 00705 Sleep(10); 00706 } 00707 00708 ptDst.x = pwnd->rcWindow.left; 00709 ptDst.y = pwnd->rcWindow.top; 00710 size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left; 00711 size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top; 00712 00713 blend.BlendOp = AC_SRC_OVER; 00714 blend.BlendFlags = 0; 00715 blend.AlphaFormat = 0; 00716 blend.SourceConstantAlpha = fHide ? (255 - bAlpha) : bAlpha; 00717 00718 /* 00719 * Copy the initial image with the initial alpha. 00720 */ 00721 NtUserUpdateLayeredWindow(hwnd, NULL, &ptDst, &size, hdcImage, &ptSrc, 0, 00722 &blend, ULW_ALPHA); 00723 00724 if (!fHide) { 00725 ShowWindowNoRepaint(pwnd); 00726 } 00727 00728 /* 00729 * Time and start the animation cycle. 00730 */ 00731 dwElapsed = (dwTime * ALPHASTART + 255) / 255 + 10; 00732 QueryPerformanceCounter(&liStart); 00733 liStart.QuadPart = liStart.QuadPart - dwElapsed * liFreq.QuadPart / 1000; 00734 00735 while (dwElapsed < dwTime) { 00736 00737 if (fHide) { 00738 blend.SourceConstantAlpha = (BYTE)((255 * (dwTime - dwElapsed)) / dwTime); 00739 } else { 00740 blend.SourceConstantAlpha = (BYTE)((255 * dwElapsed) / dwTime); 00741 } 00742 00743 QueryPerformanceCounter(&liIter); 00744 00745 NtUserUpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, 00746 &blend, ULW_ALPHA); 00747 00748 QueryPerformanceCounter(&liDiff); 00749 00750 /* 00751 * Calculate how long in ms the previous frame took. 00752 */ 00753 liIter.QuadPart = liDiff.QuadPart - liIter.QuadPart; 00754 dwIter = (DWORD)((liIter.QuadPart * 1000) / liFreq.QuadPart); 00755 00756 if (dwIter < ONEFRAME) { 00757 Sleep(ONEFRAME - dwIter); 00758 } 00759 00760 liDiff.QuadPart -= liStart.QuadPart; 00761 dwElapsed = (DWORD)((liDiff.QuadPart * 1000) / liFreq.QuadPart); 00762 } 00763 00764 /* 00765 * Hide the window before removing the layered bit to make sure that 00766 * the bits for the window are not left on the screen. 00767 */ 00768 if (fHide) { 00769 NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | 00770 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 00771 } 00772 00773 SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & 00774 ~WS_EX_LAYERED); 00775 00776 if (!fHide) { 00777 BitBlt(hdcScreen, 0, 0, size.cx, size.cy, hdcImage, 0, 0, SRCCOPY | NOMIRRORBITMAP); 00778 } 00779 00780 return TRUE; 00781 } 00782 00783 /***************************************************************************\ 00784 * AnimateWindow (API) 00785 * 00786 * Hide animations are done by updating a la full-drag. Uses window's window 00787 * region to do some of the magic. 00788 * 00789 * We have to put in the CLIPCHILDREN hack to work around a bug with the 00790 * DC cache resetting attributes even if DCX_USESTYLE is not used whe 00791 * the DC cache is invalidated. 00792 * 00793 * History: 00794 * 9-Sep-1996 vadimg created 00795 \***************************************************************************/ 00796 00797 #define AW_HOR (AW_HOR_POSITIVE | AW_HOR_NEGATIVE | AW_CENTER) 00798 #define AW_VER (AW_VER_POSITIVE | AW_VER_NEGATIVE | AW_CENTER) 00799 00800 __inline int AnimInc(int x, int y, int z) 00801 { 00802 return MultDiv(x, y, z); 00803 } 00804 00805 __inline int AnimDec(int x, int y, int z) 00806 { 00807 return x - AnimInc(x, y, z); 00808 } 00809 00810 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags) 00811 { 00812 PTHREADINFO ptiCurrent = PtiCurrent(); 00813 HDC hdc = NULL, hdcMem = NULL; 00814 HRGN hrgnUpdate = NULL, hrgnOld = NULL, hrgnWin; 00815 HBITMAP hbmMem = NULL, hbmOld; 00816 BOOL fHide = dwFlags & AW_HIDE, fRet = FALSE, fSlide = dwFlags & AW_SLIDE; 00817 BOOL fRemoveClipChildren = FALSE; 00818 int x, y, nx, ny, cx, cy, ix, iy, ixLast, iyLast, xLast, yLast, xWin, yWin; 00819 int xReal, yReal, xMem, yMem; 00820 DWORD dwStart, dwElapsed; 00821 RECT rcOld, rcNew, rcWin; 00822 PWND pwnd = ValidateHwnd(hwnd); 00823 UINT uBounds; 00824 RECT rcBounds; 00825 #ifdef USE_MIRRORING 00826 DWORD dwOldlayout = GDI_ERROR; 00827 #endif 00828 00829 if (pwnd == NULL) 00830 return FALSE; 00831 00832 /* 00833 * Nothing to do or the flags didn't validate. Send the jerk to hell. 00834 */ 00835 if ((dwFlags & ~AW_VALID) != 0 || (dwFlags & (AW_HOR_POSITIVE | 00836 AW_HOR_NEGATIVE | AW_CENTER | AW_VER_POSITIVE | 00837 AW_VER_NEGATIVE | AW_BLEND)) == 0) 00838 return FALSE; 00839 00840 if (!(dwFlags & AW_BLEND)) { 00841 if (pwnd->hrgnClip != NULL) { 00842 return FALSE; 00843 } 00844 } 00845 00846 /* 00847 * If already hidden and tring to hide, just bail out of here. 00848 * (or already shown and trying to show...) 00849 */ 00850 if (!IsWindowVisible(hwnd)) { 00851 if (fHide) { 00852 return FALSE; 00853 } 00854 } else { 00855 if (!fHide) { 00856 return FALSE; 00857 } 00858 } 00859 00860 00861 if ((hdc = GetDCEx(hwnd, NULL, DCX_WINDOW | DCX_USESTYLE | 00862 DCX_CACHE)) == NULL) { 00863 return FALSE; 00864 } 00865 00866 if (TestWF(pwnd, WFCLIPCHILDREN)) { 00867 fRemoveClipChildren = TRUE; 00868 ClearWindowState(pwnd, WFCLIPCHILDREN); 00869 } 00870 00871 /* 00872 * Precreate regions used for calculating paint updates. 00873 */ 00874 if (fHide) { 00875 if ((hrgnUpdate = CreateRectRgn(0, 0, 0, 0)) == NULL) { 00876 goto Cleanup; 00877 } 00878 if ((hrgnOld = CreateRectRgn(0, 0, 0, 0)) == NULL) { 00879 goto Cleanup; 00880 } 00881 } 00882 00883 rcWin = pwnd->rcWindow; 00884 cx = rcWin.right - rcWin.left; 00885 cy = rcWin.bottom - rcWin.top; 00886 00887 /* 00888 * Set up the offscreen dc. 00889 */ 00890 if ((hbmMem = CreateCompatibleBitmap(hdc, cx, cy | CCB_NOVIDEOMEMORY)) == NULL) { 00891 goto Cleanup; 00892 } 00893 if ((hdcMem = CreateCompatibleDC(hdc)) == NULL) { 00894 goto Cleanup; 00895 } 00896 #ifdef USE_MIRRORING 00897 /* 00898 * Turn off Mirroring. 00899 */ 00900 dwOldlayout = SetLayout(hdcMem, 0); 00901 #endif 00902 hbmOld = SelectBitmap(hdcMem, hbmMem); 00903 00904 if (!(dwFlags & AW_BLEND)) { 00905 /* 00906 * Set window region to nothing, so that if the window draws during 00907 * callbacks in WM_PRINT, it doesn't happen on screen. 00908 */ 00909 if ((hrgnWin = CreateRectRgn(0, 0, 0, 0)) != NULL) { 00910 SetWindowRgn(hwnd, hrgnWin, FALSE); 00911 } 00912 00913 if (!fHide) { 00914 ShowWindowNoRepaint(pwnd); 00915 } 00916 } 00917 00918 SetBoundsRect(hdcMem, NULL, DCB_RESET | DCB_ENABLE); 00919 00920 /* 00921 * Get the actual image. The windows participating here must implement 00922 * WM_PRINTCLIENT or they will look ugly. 00923 */ 00924 SendMessage(hwnd, WM_PRINT, (WPARAM)hdcMem, PRF_CLIENT | PRF_NONCLIENT | 00925 PRF_CHILDREN | PRF_ERASEBKGND); 00926 00927 /* 00928 * If the window changes size during callbacks, like RAID does with combo 00929 * boxes by resizing them on WM_CTLCOLOR from WM_ERASEBKGND, send WM_PRINT 00930 * again to get the correctly sized image. 00931 */ 00932 if (!EqualRect(&rcWin, &pwnd->rcWindow)) { 00933 rcWin = pwnd->rcWindow; 00934 cx = rcWin.right - rcWin.left; 00935 cy = rcWin.bottom - rcWin.top; 00936 00937 SelectObject(hdcMem, hbmOld); 00938 DeleteObject(hbmMem); 00939 00940 if ((hbmMem = CreateCompatibleBitmap(hdc, cx, cy)) == NULL) { 00941 goto Cleanup; 00942 } 00943 00944 SelectObject(hdcMem, hbmMem); 00945 SendMessage(hwnd, WM_PRINT, (WPARAM)hdcMem, PRF_CLIENT | 00946 PRF_NONCLIENT | PRF_CHILDREN | PRF_ERASEBKGND); 00947 } 00948 00949 /* 00950 * Check to see if the app painted in our DC. If not, do not animate the window 00951 * SetBoundsRect() was called prior to SendMessage(WM_PRINT) for the hdcMem 00952 * and in xxxLBPaint() (to fix bug#83743) 00953 */ 00954 uBounds = GetBoundsRect(hdcMem, &rcBounds, 0); 00955 if ((uBounds & DCB_RESET) && (!(uBounds & DCB_ACCUMULATE))) { 00956 if (fHide) { 00957 NtUserShowWindow(hwnd, SW_HIDE); 00958 } else { 00959 RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | 00960 RDW_ALLCHILDREN); 00961 } 00962 goto Cleanup; 00963 } 00964 00965 if (dwTime == 0) { 00966 dwTime = CMS_QANIMATION; 00967 } 00968 if (dwFlags & AW_BLEND) { 00969 fRet = AnimateBlend(pwnd, hdc, hdcMem, dwTime, fHide); 00970 goto ShowActivate; 00971 } 00972 00973 xWin = rcWin.left; 00974 yWin = rcWin.top; 00975 00976 ix = iy = xLast = yLast = 0; 00977 ixLast = cx; 00978 iyLast = cy; 00979 00980 /* 00981 * Calculate initial coordinates and multiples. x, y are the starting points 00982 * for xReal, yReal calcs, nx, and ny are the directional multiples. 00983 */ 00984 if (dwFlags & AW_CENTER) { 00985 x = cx / 2; 00986 nx = -1; 00987 fSlide = FALSE; 00988 } else if (dwFlags & AW_HOR_POSITIVE) { 00989 x = fHide ? cx : 0; 00990 nx = fHide ? -1 : 0; 00991 } else if (dwFlags & AW_HOR_NEGATIVE) { 00992 x = fHide ? 0 : cx; 00993 nx = fHide ? 0 : -1; 00994 } else { 00995 x = 0; 00996 nx = 0; 00997 ix = cx; 00998 } 00999 01000 if (dwFlags & AW_CENTER) { 01001 y = cy / 2; 01002 ny = -1; 01003 } else if (dwFlags & AW_VER_POSITIVE) { 01004 y = fHide ? cy : 0; 01005 ny = fHide ? -1 : 0; 01006 } else if (dwFlags & AW_VER_NEGATIVE) { 01007 y = fHide ? 0 : cy; 01008 ny = fHide ? 0 : -1; 01009 } else { 01010 y = 0; 01011 ny = 0; 01012 iy = cy; 01013 } 01014 01015 dwStart = GetTickCount(); 01016 01017 while (TRUE) { 01018 01019 dwElapsed = GetTickCount() - dwStart; 01020 01021 if (dwFlags & AW_HOR) { 01022 if (fHide) { 01023 ix = AnimDec(cx, dwElapsed, dwTime); 01024 } else { 01025 ix = AnimInc(cx, dwElapsed, dwTime); 01026 } 01027 } 01028 01029 if (dwFlags & AW_VER) { 01030 if (fHide) { 01031 iy = AnimDec(cy, dwElapsed, dwTime); 01032 } else { 01033 iy = AnimInc(cy, dwElapsed, dwTime); 01034 } 01035 } 01036 01037 /* 01038 * Terminate when we are out of time or we're hiding and either 01039 * dimenion has reached zero (i.e. the window is not visible) or 01040 * we're showing and the window is completely visible. 01041 */ 01042 if (dwElapsed > dwTime || 01043 (fHide && (ix == 0 || iy == 0)) || 01044 (!fHide && (ix == cx && iy == cy))) { 01045 break; 01046 } else if (ixLast == ix && iyLast == iy) { 01047 Sleep(1); 01048 } else { 01049 if (dwFlags & AW_CENTER) { 01050 xReal = x + nx * (ix / 2); 01051 yReal = y + ny * (iy / 2); 01052 } else { 01053 xReal = x + nx * ix; 01054 yReal = y + ny * iy; 01055 } 01056 01057 /* 01058 * Calculate new window area and set as the window rgn. 01059 */ 01060 rcNew.left = xReal; 01061 rcNew.top = yReal; 01062 rcNew.right = rcNew.left + ix; 01063 rcNew.bottom = rcNew.top + iy; 01064 01065 /* 01066 * Change the window region accordingly to the new rect to make 01067 * sure that everything underneath paints properly. If a region 01068 * was selected in before, it will be destroyed in SetWindowRgn. 01069 */ 01070 if ((hrgnWin = CreateRectRgnIndirect(&rcNew)) != NULL) { 01071 SetWindowRgn(hwnd, hrgnWin, FALSE); 01072 } 01073 01074 if (fHide) { 01075 /* 01076 * Calculate the smallest possible update region. 01077 */ 01078 rcOld.left = xLast; 01079 rcOld.top = yLast; 01080 rcOld.right = rcOld.left + ixLast; 01081 rcOld.bottom = rcOld.top + iyLast; 01082 01083 SetRectRgn(hrgnOld, rcOld.left, rcOld.top, rcOld.right, rcOld.bottom); 01084 SetRectRgn(hrgnUpdate, rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); 01085 CombineRgn(hrgnUpdate, hrgnOld, hrgnUpdate, RGN_DIFF); 01086 01087 OffsetRgn(hrgnUpdate, xWin, yWin); 01088 RedrawWindow(NULL, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | 01089 RDW_ALLCHILDREN); 01090 NtUserCallHwndParamLock(hwnd, (ULONG_PTR)hrgnUpdate, SFI_XXXUPDATEWINDOWS); 01091 } 01092 01093 xMem = xReal; 01094 yMem = yReal; 01095 01096 if (fSlide) { 01097 if (dwFlags & AW_HOR_POSITIVE) { 01098 xMem = fHide ? 0: cx - ix; 01099 } else if (dwFlags & AW_HOR_NEGATIVE) { 01100 xMem = fHide ? cx - ix : 0; 01101 } 01102 if (dwFlags & AW_VER_POSITIVE) { 01103 yMem = fHide ? 0 : cy - iy; 01104 } else if (dwFlags & AW_VER_NEGATIVE) { 01105 yMem = fHide ? cy - iy : 0; 01106 } 01107 } 01108 01109 BitBlt(hdc, xReal, yReal, ix, iy, hdcMem, xMem, yMem, SRCCOPY | NOMIRRORBITMAP); 01110 01111 xLast = xReal; 01112 yLast = yReal; 01113 ixLast = ix; 01114 iyLast = iy; 01115 } 01116 } 01117 01118 fRet = TRUE; 01119 01120 /* 01121 * One last update to make sure that everything is repainted properly. 01122 */ 01123 if (fHide) { 01124 if (fRemoveClipChildren) { 01125 SetWindowState(pwnd, WFCLIPCHILDREN); 01126 fRemoveClipChildren = FALSE; 01127 } 01128 NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | 01129 SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | 01130 SWP_NOREDRAW | SWP_HIDEWINDOW | 01131 (dwFlags & AW_ACTIVATE ? 0 : SWP_NOACTIVATE)); 01132 01133 /* 01134 * This way we won't get a flash, which we would if we allowed to draw 01135 * in the call above. 01136 */ 01137 if (ixLast != 0 && iyLast != 0) { 01138 rcWin.left = xLast + xWin; 01139 rcWin.top = yLast + yWin; 01140 rcWin.right = rcWin.left + ixLast; 01141 rcWin.bottom = rcWin.top + iyLast; 01142 SetRectRgn(hrgnUpdate, rcWin.left, rcWin.top, rcWin.right, rcWin.bottom); 01143 RedrawWindow(NULL, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | 01144 RDW_FRAME); 01145 NtUserCallHwndParamLock(hwnd, (ULONG_PTR)hrgnUpdate, SFI_XXXUPDATEWINDOWS); 01146 } 01147 } else { 01148 if (ixLast != cx || iyLast != cy) { 01149 if ((hrgnWin = CreateRectRgn(0, 0, cx, cy)) != NULL) { 01150 SetWindowRgn(hwnd, hrgnWin, FALSE); 01151 } 01152 BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY | NOMIRRORBITMAP); 01153 } 01154 if (fRemoveClipChildren) { 01155 SetWindowState(pwnd, WFCLIPCHILDREN); 01156 fRemoveClipChildren = FALSE; 01157 } 01158 01159 ShowActivate: 01160 if (dwFlags & AW_ACTIVATE) { 01161 NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | 01162 SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); 01163 } 01164 } 01165 01166 Cleanup: 01167 if (fRemoveClipChildren) { 01168 SetWindowState(pwnd, WFCLIPCHILDREN); 01169 } 01170 if (hdcMem != NULL) { 01171 #ifdef USE_MIRRORING 01172 /* 01173 * Restore old layout value. 01174 */ 01175 if (dwOldlayout != GDI_ERROR) 01176 SetLayout(hdcMem, dwOldlayout); 01177 #endif 01178 DeleteDC(hdcMem); 01179 } 01180 if (hbmMem != NULL) { 01181 DeleteObject(hbmMem); 01182 } 01183 if (hdc != NULL) { 01184 ReleaseDC(hwnd, hdc); 01185 } 01186 if (fHide) { 01187 if (hrgnUpdate != NULL) { 01188 DeleteObject(hrgnUpdate); 01189 } 01190 if (hrgnOld != NULL) { 01191 DeleteObject(hrgnOld); 01192 } 01193 } 01194 if (!(dwFlags & AW_BLEND)) { 01195 SetWindowRgn(hwnd, NULL, FALSE); 01196 } 01197 return fRet; 01198 } 01199 01200 /***************************************************************************\ 01201 * SmoothScrollWindowEx 01202 * 01203 * History: 01204 * 24-Sep-1996 vadimg wrote 01205 \***************************************************************************/ 01206 01207 #define MINSCROLL 10 01208 #define MAXSCROLLTIME 200 01209 01210 int SmoothScrollWindowEx(HWND hwnd, int dx, int dy, CONST RECT *prcScroll, 01211 CONST RECT *prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, DWORD dwFlags, 01212 DWORD dwTime) 01213 { 01214 RECT rc, rcT, rcUpdate; 01215 int dxStep, dyStep, dxDone, dyDone, xSrc, ySrc, xDst, yDst, dxBlt, dyBlt; 01216 int nRet = ERROR, nClip; 01217 BOOL fNegX = FALSE, fNegY = FALSE; 01218 HDC hdc, hdcMem = NULL; 01219 HBITMAP hbmMem = NULL, hbmOld; 01220 DWORD dwSleep; 01221 BOOL fCalcSubscroll = FALSE; 01222 PWND pwnd = ValidateHwnd(hwnd); 01223 HRGN hrgnScroll = NULL, hrgnErase = NULL; 01224 MSG msg; 01225 UINT uBounds; 01226 RECT rcBounds; 01227 01228 if (pwnd == NULL) 01229 return ERROR; 01230 /* 01231 * Keep track of the signs so we don't have to mess with abs all the time. 01232 */ 01233 if (dx < 0) { 01234 fNegX = TRUE; 01235 dx = -dx; 01236 } 01237 01238 if (dy < 0) { 01239 fNegY = TRUE; 01240 dy = -dy; 01241 } 01242 01243 /* 01244 * Set up the client rectangle. 01245 */ 01246 if (prcScroll != NULL) { 01247 rc = *prcScroll; 01248 } else { 01249 rc.left = rc.top = 0; 01250 rc.right = pwnd->rcClient.right - pwnd->rcClient.left; 01251 rc.bottom = pwnd->rcClient.bottom - pwnd->rcClient.top; 01252 } 01253 01254 /* 01255 * If they want to scroll less than we can let them, or more than 01256 * one page, or need repainting send them to the API. 01257 */ 01258 if (pwnd->hrgnUpdate != NULL || (dx == 0 && dy == 0) || 01259 (dx != 0 && dx > rc.right) || 01260 (dy != 0 && dy > rc.bottom)) { 01261 return NtUserScrollWindowEx(hwnd, fNegX ? -dx : dx, fNegY ? -dy : dy, 01262 prcScroll, prcClip, hrgnUpdate, prcUpdate, 01263 dwFlags | SW_ERASE | SW_INVALIDATE); 01264 } 01265 01266 if ((hdc = GetDCEx(hwnd, NULL, DCX_USESTYLE | DCX_CACHE)) == NULL) { 01267 return ERROR; 01268 } 01269 01270 /* 01271 * Part of the window may be obscured, which means that more may be 01272 * invisible and may need to be bltted. Take that into account by 01273 * gettting the clip box. 01274 */ 01275 nClip = GetClipBox(hdc, &rcT); 01276 if (nClip == ERROR || nClip == NULLREGION) { 01277 goto Cleanup; 01278 } 01279 01280 /* 01281 * Set up the offscreen dc and send WM_PRINT to get the image. 01282 */ 01283 if ((hbmMem = CreateCompatibleBitmap(hdc, rc.right, rc.bottom)) == NULL) { 01284 goto Cleanup; 01285 } 01286 if ((hdcMem = CreateCompatibleDC(hdc)) == NULL) { 01287 goto Cleanup; 01288 } 01289 hbmOld = SelectBitmap(hdcMem, hbmMem); 01290 01291 SetBoundsRect(hdcMem, NULL, DCB_RESET | DCB_ENABLE); 01292 01293 SendMessage(hwnd, WM_PRINT, (WPARAM)hdcMem, PRF_CLIENT | 01294 PRF_ERASEBKGND | ((dwFlags & SW_SCROLLCHILDREN) ? PRF_CHILDREN : 0)); 01295 01296 /* 01297 * If the client rect changes during the callback, send WM_PRINT 01298 * again to get the correctly sized image. 01299 */ 01300 if (prcScroll == NULL) { 01301 rcT.left = rcT.top = 0; 01302 rcT.right = pwnd->rcClient.right - pwnd->rcClient.left; 01303 rcT.bottom = pwnd->rcClient.bottom - pwnd->rcClient.top; 01304 01305 if (!EqualRect(&rc, &rcT)) { 01306 rc = rcT; 01307 01308 SelectObject(hdcMem, hbmOld); 01309 DeleteObject(hbmMem); 01310 01311 if ((hbmMem = CreateCompatibleBitmap(hdc, rc.right, rc.bottom)) == NULL) { 01312 goto Cleanup; 01313 } 01314 01315 SelectObject(hdcMem, hbmMem); 01316 SendMessage(hwnd, WM_PRINT, (WPARAM)hdcMem, PRF_CLIENT | 01317 PRF_ERASEBKGND | ((dwFlags & SW_SCROLLCHILDREN) ? PRF_CHILDREN : 0)); 01318 } 01319 } 01320 01321 /* 01322 * Check to see if the app painted in our DC. 01323 */ 01324 uBounds = GetBoundsRect(hdcMem, &rcBounds, 0); 01325 if ((uBounds & DCB_RESET) && (!(uBounds & DCB_ACCUMULATE))) { 01326 goto Cleanup; 01327 } 01328 01329 if ((hrgnScroll = CreateRectRgn(0, 0, 0, 0)) == NULL) { 01330 goto Cleanup; 01331 } 01332 if ((hrgnErase = CreateRectRgn(0, 0, 0, 0)) == NULL) { 01333 goto Cleanup; 01334 } 01335 SetRectEmpty(&rcUpdate); 01336 01337 /* 01338 * Start off with MINSCROLL and adjust it based on available time after 01339 * the first iteration. We should consider adding a NOTIMELIMIT flag. 01340 */ 01341 xDst = xSrc = 0; 01342 yDst = ySrc = 0; 01343 01344 dxBlt = rc.right; 01345 dyBlt = rc.bottom; 01346 01347 if (dx == 0) { 01348 dxDone = rc.right; 01349 dxStep = 0; 01350 } else { 01351 dxDone = 0; 01352 dxStep = max(dx / MINSCROLL, 1); 01353 } 01354 01355 if (dy == 0) { 01356 dyDone = rc.bottom; 01357 dyStep = 0; 01358 } else { 01359 dyDone = 0; 01360 dyStep = max(dy / MINSCROLL, 1); 01361 } 01362 01363 if (dwTime == 0) { 01364 dwTime = MAXSCROLLTIME; 01365 } 01366 dwSleep = dwTime / MINSCROLL; 01367 01368 do { 01369 01370 /* 01371 * When the dc is scrolled, the part that's revealed cannot be 01372 * updated properly. We set up the variables to blt just the part that 01373 * was just uncovered. 01374 */ 01375 if (dx != 0) { 01376 if (dxDone + dxStep > dx) { 01377 dxStep = dx - dxDone; 01378 } 01379 dxDone += dxStep; 01380 01381 xDst = dx - dxDone; 01382 dxBlt = rc.right - xDst; 01383 if (!fNegX) { 01384 xSrc = xDst; 01385 xDst = 0; 01386 } 01387 } 01388 01389 if (dy != 0) { 01390 if (dyDone + dyStep > dy) { 01391 dyStep = dy - dyDone; 01392 } 01393 dyDone += dyStep; 01394 01395 yDst = dy - dyDone; 01396 dyBlt = rc.bottom - yDst; 01397 if (!fNegY) { 01398 ySrc = yDst; 01399 yDst = 0; 01400 } 01401 } 01402 01403 /* 01404 * This is a hack for ReaderMode to be smoothly continuous. We'll make an 01405 * attempt for the scrolling to take as close to dwTime 01406 * as possible. We'll also dispatch MOUSEMOVEs to the ReaderMode window, so it 01407 * can update mouse cursor. 01408 */ 01409 if (MsgWaitForMultipleObjects(0, NULL, FALSE, dwSleep, QS_MOUSEMOVE) == WAIT_OBJECT_0) { 01410 if (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, MAKELONG(PM_NOREMOVE, QS_INPUT))) { 01411 PWND pwndPeek = ValidateHwnd(msg.hwnd); 01412 if (pwndPeek != NULL) { 01413 PCLS pcls = (PCLS)REBASEALWAYS(pwndPeek, pcls); 01414 if (pcls->atomClassName == gatomReaderMode) { 01415 if (PeekMessage(&msg, msg.hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, MAKELONG(PM_REMOVE, QS_INPUT))) { 01416 DispatchMessage(&msg); 01417 } 01418 } 01419 } 01420 } 01421 } 01422 01423 if ((nRet = NtUserScrollWindowEx(hwnd, fNegX ? -dxStep : dxStep, 01424 fNegY ? -dyStep : dyStep, prcScroll, prcClip, 01425 hrgnScroll, &rcT, dwFlags)) == ERROR) 01426 goto Cleanup; 01427 01428 UnionRect(&rcUpdate, &rcUpdate, &rcT); 01429 01430 /* 01431 * Blt the uncovered part. 01432 */ 01433 BitBlt(hdc, xDst, yDst, dxBlt, dyBlt, hdcMem, xSrc, ySrc, SRCCOPY | NOMIRRORBITMAP); 01434 01435 SetRectRgn(hrgnErase, xDst, yDst, xDst + dxBlt, yDst + dyBlt); 01436 CombineRgn(hrgnErase, hrgnScroll, hrgnErase, RGN_DIFF); 01437 RedrawWindow(hwnd, NULL, hrgnErase, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW); 01438 01439 } while (dxDone < dx || dyDone < dy); 01440 01441 if (prcUpdate != NULL) { 01442 *prcUpdate = rcUpdate; 01443 } 01444 if (hrgnUpdate != NULL) { 01445 SetRectRgn(hrgnUpdate, rcUpdate.left, rcUpdate.top, 01446 rcUpdate.right, rcUpdate.bottom); 01447 } 01448 01449 Cleanup: 01450 if (hdcMem != NULL) { 01451 DeleteDC(hdcMem); 01452 } 01453 if (hbmMem != NULL) { 01454 DeleteObject(hbmMem); 01455 } 01456 if (hdc != NULL) { 01457 ReleaseDC(hwnd, hdc); 01458 } 01459 if (hrgnErase != NULL) { 01460 DeleteObject(hrgnErase); 01461 } 01462 if (hrgnScroll != NULL) { 01463 DeleteObject(hrgnScroll); 01464 } 01465 return nRet; 01466 } 01467 01468 /***************************************************************************\ 01469 * ScrollWindowEx (API) 01470 * 01471 \***************************************************************************/ 01472 01473 int ScrollWindowEx(HWND hwnd, int dx, int dy, CONST RECT *prcScroll, 01474 CONST RECT *prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, 01475 UINT dwFlags) 01476 { 01477 if (dwFlags & SW_SMOOTHSCROLL) { 01478 return SmoothScrollWindowEx(hwnd, dx, dy, prcScroll, prcClip, 01479 hrgnUpdate, prcUpdate, LOWORD(dwFlags), HIWORD(dwFlags)); 01480 } else { 01481 return NtUserScrollWindowEx(hwnd, dx, dy, prcScroll, prcClip, 01482 hrgnUpdate, prcUpdate, dwFlags); 01483 } 01484 }

Generated on Sat May 15 19:42:25 2004 for test by doxygen 1.3.7