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

dlgmgr.c

Go to the documentation of this file.
00001 /***************************************************************************\ 00002 * 00003 * DLGMGR.C - 00004 * 00005 * Dialog Box Manager Routines 00006 * 00007 * ??-???-???? mikeke Ported from Win 3.0 sources 00008 * 12-Feb-1991 mikeke Added Revalidation code 00009 * 19-Feb-1991 JimA Added access checks 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 #define UNICODE_MINUS_SIGN 0x2212 00016 00017 // FA 00018 LRESULT ResizeDlgMessage( LPVOID pObject, 00019 HWND hwnd, 00020 UINT message, 00021 WPARAM wParam, 00022 LPARAM lParam 00023 ); 00024 00025 00026 LOOKASIDE DialogLookaside; 00027 00028 BOOL ValidateCallback(HANDLE h); 00029 00030 #define IsInForegroundQueue(hwnd) \ 00031 (NtUserQueryWindow(hwnd, WindowIsForegroundThread) != NULL) 00032 #define IsCurrentThreadForeground() \ 00033 ((BOOL)NtUserGetThreadState(UserThreadStateIsForeground)) 00034 00035 /***************************************************************************\ 00036 * 00037 * GetParentDialog() 00038 * 00039 * Gets top level window, not a control parent. If not a dialog, then use 00040 * "highest" control parent guy. 00041 * 00042 * BOGUS 00043 * Need a way to mark a window as a dialog. If it ever comes into 00044 * DefDlgProc(), set an internal flag. Will be used by thunking and 00045 * CallDlgProc() optimizations also! 00046 * 00047 \***************************************************************************/ 00048 00049 PWND GetParentDialog(PWND pwndDialog) 00050 { 00051 PWND pwndParent; 00052 00053 pwndParent = pwndDialog; 00054 00055 // 00056 // Walk up the parent chain. We're looking for the top-most dialog 00057 // window. Most cases, the window is a top level one. But in case of 00058 // backup app, the window will be a child of some other window. 00059 // 00060 for (; pwndDialog; pwndDialog = REBASEPWND(pwndDialog, spwndParent)) 00061 { 00062 if (TestWF(pwndDialog, WFDIALOGWINDOW)) 00063 { 00064 // 00065 // For old guys: If not DS_RECURSE, then stop here. 00066 // that way old apps which try to do the nested dialog 00067 // stuff in their old limited way don't die. 00068 // 00069 if (TestWF(pwndDialog, WEFCONTROLPARENT)) 00070 pwndParent = pwndDialog; 00071 else if (!TestWF(pwndDialog, DFCONTROL)) 00072 break; 00073 } 00074 00075 if (!TestWF(pwndDialog, WFCHILD)) 00076 break; 00077 } 00078 00079 return(pwndParent); 00080 } 00081 00082 /***************************************************************************\ 00083 * xxxSaveDlgFocus 00084 * 00085 * History: 00086 * 02-18-92 JimA Ported from Win31 sources 00087 \***************************************************************************/ 00088 00089 BOOL xxxSaveDlgFocus( 00090 PWND pwnd) 00091 { 00092 HWND hwndFocus = GetFocus(); 00093 00094 CheckLock(pwnd); 00095 00096 if (hwndFocus != NULL && IsChild(HWq(pwnd), hwndFocus) && 00097 PDLG(pwnd)->hwndFocusSave == NULL) { 00098 PDLG(pwnd)->hwndFocusSave = hwndFocus; 00099 xxxRemoveDefaultButton(pwnd, ValidateHwnd(hwndFocus)); 00100 return TRUE; 00101 } 00102 return FALSE; 00103 } 00104 00105 /***************************************************************************\ 00106 * xxxRestoreDlgFocus 00107 * 00108 * History: 00109 * 02-18-92 JimA Ported from Win31 sources 00110 \***************************************************************************/ 00111 00112 // LATER 00113 // 21-Mar-1992 mikeke 00114 // does pwndFocusSave need to be unlocked when the dialog is destroyed? 00115 00116 BOOL xxxRestoreDlgFocus( 00117 PWND pwnd) 00118 { 00119 HWND hwndFocus; 00120 HWND hwndFocusSave; 00121 BOOL fRestored = FALSE; 00122 00123 CheckLock(pwnd); 00124 00125 if (PDLG(pwnd)->hwndFocusSave && !TestWF(pwnd, WFMINIMIZED)) { 00126 00127 hwndFocus = GetFocus(); 00128 hwndFocusSave = PDLG(pwnd)->hwndFocusSave; 00129 00130 if (IsWindow(hwndFocusSave)) { 00131 xxxCheckDefPushButton(pwnd, hwndFocus, hwndFocusSave); 00132 fRestored = (NtUserSetFocus(hwndFocusSave) != NULL); 00133 #ifdef FE_IME 00134 // 00135 // after calling SetFocus(), we need to re-validate 00136 // the window. PDLG(pwnd) might be NULL. This can 00137 // be happened in FE environment where IME window 00138 // exist. (kkntbug #12613) 00139 // 00140 if (IS_IME_ENABLED() && !ValidateDialogPwnd(pwnd)) { 00141 return fRestored; 00142 } 00143 #endif 00144 } 00145 PDLG(pwnd)->hwndFocusSave = NULL; 00146 } 00147 00148 return fRestored; 00149 } 00150 00151 00152 /***************************************************************************\ 00153 * DlgSetFocus 00154 * 00155 * History: 00156 \***************************************************************************/ 00157 00158 void DlgSetFocus( 00159 HWND hwnd) 00160 { 00161 if (((UINT)SendMessage(hwnd, WM_GETDLGCODE, 0, 0)) & DLGC_HASSETSEL) { 00162 SendMessage(hwnd, EM_SETSEL, 0, MAXLONG); 00163 } 00164 00165 NtUserSetFocus(hwnd); 00166 } 00167 00168 00169 int GetDlgCtrlID( 00170 HWND hwnd) 00171 { 00172 PWND pwnd; 00173 00174 pwnd = ValidateHwnd(hwnd); 00175 if (pwnd == NULL) 00176 return 0; 00177 00178 return PtrToLong(pwnd->spmenu); 00179 } 00180 00181 00182 00183 /***************************************************************************\ 00184 * ValidateDialogPwnd 00185 * 00186 * Under Win3, DLGWINDOWEXTRA is 30 bytes. We cannot change that for 16 bit 00187 * compatibility reasons. Problem is there is no way to tell if a given 00188 * 16 bit window depends on byte count. If there was, this would be easy. 00189 * The only way to tell is when a window is about to be used as a dialog 00190 * window. This window may be of the class DIALOGCLASS, but again it may 00191 * not!! So we keep dialog window words at 30 bytes, and allocate another 00192 * structure for the real dialog structure fields. Problem is that this 00193 * structure has to be created lazily! And that's what we're doing here. 00194 * 00195 * 05-21-91 ScottLu Created. 00196 \***************************************************************************/ 00197 00198 BOOL ValidateDialogPwnd( 00199 PWND pwnd) 00200 { 00201 static BOOL sfInit = TRUE; 00202 PDLG pdlg; 00203 00204 /* 00205 * This bit is set if we've already run through this initialization and 00206 * have identified this window as a dialog window (able to withstand 00207 * peeks into window words at random moments in time). 00208 */ 00209 if (TestWF(pwnd, WFDIALOGWINDOW)) 00210 return TRUE; 00211 00212 if (pwnd->cbwndExtra < DLGWINDOWEXTRA) { 00213 RIPERR0(ERROR_WINDOW_NOT_DIALOG, RIP_VERBOSE, ""); 00214 return FALSE; 00215 } 00216 00217 /* 00218 * See if the pdlg was destroyed and this is a rogue message to be ignored 00219 */ 00220 if (pwnd->fnid & FNID_STATUS_BITS) { 00221 return FALSE; 00222 } 00223 00224 /* 00225 * If the lookaside buffer has not been initialized, do it now. 00226 */ 00227 if (sfInit) { 00228 if (!NT_SUCCESS(InitLookaside(&DialogLookaside, sizeof(DLG), 2))) { 00229 return FALSE; 00230 } 00231 sfInit = FALSE; 00232 } 00233 00234 if ((pdlg = (PDLG)AllocLookasideEntry(&DialogLookaside)) == NULL) { 00235 return FALSE; 00236 } 00237 00238 NtUserCallHwndParam(HWq(pwnd), (ULONG_PTR)pdlg, SFI_SETDIALOGPOINTER); 00239 00240 return TRUE; 00241 } 00242 00243 00244 /***************************************************************************\ 00245 * CvtDec 00246 * 00247 * LATER!!! convert to itoa? 00248 * 00249 * History: 00250 \***************************************************************************/ 00251 00252 void CvtDec( 00253 int u, 00254 LPWSTR *lplpch) 00255 { 00256 if (u >= 10) { 00257 CvtDec(u / 10, lplpch); 00258 u %= 10; 00259 } 00260 00261 *(*lplpch)++ = (WCHAR)(u + '0'); 00262 } 00263 00264 00265 /***************************************************************************\ 00266 * SetDlgItemInt 00267 * 00268 * History: 00269 \***************************************************************************/ 00270 00271 BOOL SetDlgItemInt( 00272 HWND hwnd, 00273 int item, 00274 UINT u, 00275 BOOL fSigned) 00276 { 00277 LPWSTR lpch; 00278 WCHAR rgch[16]; 00279 00280 lpch = rgch; 00281 if (fSigned) { 00282 if ((int)u < 0) { 00283 *lpch++ = TEXT('-'); 00284 u = (UINT)(-(int)u); 00285 } 00286 } else { 00287 if (u & 0x80000000) { 00288 CvtDec(u / 10, (LPWSTR FAR *)&lpch); 00289 u = u % 10; 00290 } 00291 } 00292 00293 CvtDec(u, (LPWSTR FAR *)&lpch); 00294 *lpch = 0; 00295 00296 return SetDlgItemTextW(hwnd, item, rgch); 00297 } 00298 00299 00300 /***************************************************************************\ 00301 * CheckDlgButton 00302 * 00303 * History: 00304 \***************************************************************************/ 00305 00306 BOOL CheckDlgButton( 00307 HWND hwnd, 00308 int id, 00309 UINT cmdCheck) 00310 { 00311 if ((hwnd = GetDlgItem(hwnd, id)) == NULL) { 00312 return FALSE; 00313 } 00314 00315 SendMessage(hwnd, BM_SETCHECK, cmdCheck, 0); 00316 00317 return TRUE; 00318 } 00319 00320 00321 /***************************************************************************\ 00322 * GetDlgItemInt 00323 * 00324 * History: 00325 \***************************************************************************/ 00326 00327 UINT GetDlgItemInt( 00328 HWND hwnd, 00329 int item, 00330 BOOL FAR *lpfValOK, 00331 BOOL fSigned) 00332 { 00333 int i, digit, ch; 00334 BOOL fOk, fNeg; 00335 LPWSTR lpch; 00336 WCHAR rgch[48]; 00337 WCHAR rgchDigits[48]; 00338 00339 fOk = FALSE; 00340 if (lpfValOK != NULL) 00341 *lpfValOK = FALSE; 00342 00343 if (!GetDlgItemTextW(hwnd, item, rgch, sizeof(rgch)/sizeof(WCHAR) - 1)) 00344 return 0; 00345 00346 lpch = rgch; 00347 00348 /* 00349 * Skip leading white space. 00350 */ 00351 while (*lpch == TEXT(' ')) 00352 lpch++; 00353 00354 fNeg = FALSE; 00355 while (fSigned && ((*lpch == L'-') || (*lpch == UNICODE_MINUS_SIGN))) { 00356 lpch++; 00357 fNeg ^= TRUE; 00358 } 00359 00360 /* 00361 * Convert all decimal digits to ASCII Unicode digits 0x0030 - 0x0039 00362 */ 00363 FoldStringW(MAP_FOLDDIGITS, lpch, -1, rgchDigits, 00364 sizeof(rgchDigits)/sizeof(rgchDigits[0])); 00365 lpch = rgchDigits; 00366 00367 i = 0; 00368 while (ch = *lpch++) { 00369 digit = ch - TEXT('0'); 00370 if (digit < 0 || digit > 9) { 00371 break; 00372 } 00373 if (fSigned) { 00374 if (i > (INT_MAX - digit) / 10) { 00375 return(0); 00376 } 00377 } else { 00378 if ((UINT)i > (UINT)((UINT_MAX - digit) / 10)) { 00379 return(0); 00380 } 00381 } 00382 00383 fOk = TRUE; 00384 i = ((UINT)i * 10) + digit; 00385 } 00386 00387 if (fNeg) 00388 i = -i; 00389 00390 if (lpfValOK != NULL) 00391 *lpfValOK = ((ch == 0) && fOk); 00392 00393 return (UINT)i; 00394 } 00395 00396 /***************************************************************************\ 00397 * CheckRadioButton 00398 * 00399 * History: 00400 \***************************************************************************/ 00401 00402 BOOL CheckRadioButton( 00403 HWND hwnd, 00404 int idFirst, 00405 int idLast, 00406 int id) 00407 { 00408 PWND pwnd, pwndDialog; 00409 BOOL fCheckOn; 00410 00411 pwndDialog = ValidateHwnd(hwnd); 00412 if (pwndDialog == NULL) 00413 return 0; 00414 00415 for (pwnd = REBASE(pwndDialog, spwndChild); pwnd; pwnd = REBASE(pwnd, spwndNext)) { 00416 00417 if ((PtrToLong(pwnd->spmenu) >= idFirst) && 00418 (PtrToLong(pwnd->spmenu) <= idLast)) { 00419 00420 fCheckOn = (PtrToLong(pwnd->spmenu) == id); 00421 SendMessage(PtoHq(pwnd), BM_SETCHECK, fCheckOn, 0L); 00422 } 00423 } 00424 00425 return TRUE; 00426 } 00427 00428 00429 /***************************************************************************\ 00430 * IsDlgButtonChecked 00431 * 00432 * History: 00433 \***************************************************************************/ 00434 00435 UINT IsDlgButtonChecked( 00436 HWND hwnd, 00437 int id) 00438 { 00439 if ((hwnd = GetDlgItem(hwnd, id)) != NULL) { 00440 return (UINT)SendMessage(hwnd, BM_GETCHECK, 0, 0); 00441 } 00442 00443 return FALSE; 00444 } 00445 00446 00447 /***************************************************************************\ 00448 * DefDlgProc 00449 * 00450 * History: 00451 \***************************************************************************/ 00452 00453 LRESULT DefDlgProcWorker( 00454 PWND pwnd, 00455 UINT message, 00456 WPARAM wParam, 00457 LPARAM lParam, 00458 DWORD fAnsi) 00459 { 00460 HWND hwnd = HWq(pwnd); 00461 TL tlpwndT1, tlpwndT2, tlpwndT3, tlpwndTop; 00462 PWND pwndT; 00463 PWND pwndT1, pwndT2, pwndT3, pwndTop; 00464 HWND hwndT1; 00465 LRESULT result; 00466 BOOL fSetBit; 00467 DLGPROC pfn; 00468 00469 CheckLock(pwnd); 00470 00471 /* 00472 * use the Win 3.1 documented size 00473 */ 00474 VALIDATECLASSANDSIZE(pwnd, FNID_DIALOG); 00475 00476 /* 00477 * Must do special validation here to make sure pwnd is a dialog window. 00478 */ 00479 if (!ValidateDialogPwnd(pwnd)) 00480 return 0; 00481 00482 if (((PDIALOG)pwnd)->resultWP != 0) 00483 NtUserSetWindowLongPtr(hwnd, DWLP_MSGRESULT, 0, FALSE); 00484 result = 0; // no dialog proc 00485 00486 if (message == WM_FINALDESTROY) { 00487 goto DoCleanup; 00488 } 00489 00490 if ((pfn = PDLG(pwnd)->lpfnDlg) != NULL) { 00491 if (IsWOWProc(pfn)) { 00492 result = (*pfnWowDlgProcEx)(hwnd, message, wParam, lParam, (ULONG_PTR)pfn, &(pwnd->state)); 00493 } else { 00494 result = (pfn)(hwnd, message, wParam, lParam); 00495 } 00496 00497 /* 00498 * Get out if the window was destroyed in the dialog proc. 00499 */ 00500 if ((RevalidateHwnd(hwnd)==NULL) || (pwnd->fnid & FNID_STATUS_BITS)) 00501 return result; 00502 } 00503 00504 /* 00505 * SPECIAL CASED ... and DOCUMENTED that way !!! 00506 * These 6, and ONLY these 6, should be hacked in this fashion. 00507 * Anybody who needs the REAL return value to a message should 00508 * use SetDlgMsgResult in WINDOWSX.H 00509 */ 00510 00511 switch (message) 00512 { 00513 case WM_INITDIALOG: 00514 // 00515 // FA 00516 // 00517 if( PDLG(pwnd)->pDlgResize != NULL ) 00518 ResizeDlgMessage( PDLG(pwnd)->pDlgResize, hwnd, message, wParam, lParam ); 00519 // fall through 00520 case WM_COMPAREITEM: 00521 case WM_VKEYTOITEM: 00522 case WM_CHARTOITEM: 00523 case WM_QUERYDRAGICON: 00524 return ((LRESULT)(DWORD)result); 00525 00526 case WM_CTLCOLOR: 00527 case WM_CTLCOLORMSGBOX: 00528 case WM_CTLCOLOREDIT: 00529 case WM_CTLCOLORLISTBOX: 00530 case WM_CTLCOLORBTN: 00531 case WM_CTLCOLORDLG: 00532 case WM_CTLCOLORSCROLLBAR: 00533 case WM_CTLCOLORSTATIC: 00534 // QuarkXPress doesn't like finding the WM_CTLCOLOR result in 00535 // resultWP -- we should never be setting resultWP -- that's meant 00536 // as a pass-thru return value -- so let's go back to doing it the 00537 // old way -- Win95B B#21269 -- 03/13/95 -- tracysh (cr: jeffbog) 00538 if (result) 00539 return ((LRESULT)(DWORD)result); 00540 break; 00541 } 00542 00543 if (!result) { 00544 00545 /* 00546 * Save the result value in case our private memory is freed 00547 * before we return 00548 */ 00549 // result = PDLG(pwnd)->resultWP; 00550 00551 switch (message) { 00552 case WM_CTLCOLOR: 00553 case WM_CTLCOLORMSGBOX: 00554 case WM_CTLCOLOREDIT: 00555 case WM_CTLCOLORLISTBOX: 00556 case WM_CTLCOLORBTN: 00557 case WM_CTLCOLORDLG: 00558 case WM_CTLCOLORSCROLLBAR: 00559 case WM_CTLCOLORSTATIC: 00560 { 00561 // 00562 // HACK OF DEATH: 00563 // To get 3D colors for non 4.0 apps who use 3DLOOK, 00564 // we temporarily add on the 4.0 compat bit, pass this 00565 // down to DWP, and clear it. 00566 // 00567 // Use "result" var for bool saying we have to add/clear 4.0 00568 // compat bit. 00569 00570 fSetBit = (TestWF(pwnd, DF3DLOOK)!= 0) && 00571 (TestWF(pwnd, WFWIN40COMPAT) == 0); 00572 00573 if (fSetBit) 00574 SetWindowState(pwnd, WFWIN40COMPAT); 00575 00576 result = DefWindowProcWorker(pwnd, message, 00577 wParam, lParam, fAnsi); 00578 00579 if (fSetBit) 00580 ClearWindowState(pwnd, WFWIN40COMPAT); 00581 return((LRESULT)(DWORD) result); 00582 } 00583 00584 case WM_ERASEBKGND: 00585 FillWindow(hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG); 00586 00587 // 00588 // FA 00589 if( PDLG(pwnd)->pDlgResize != NULL ) 00590 return ResizeDlgMessage( PDLG(pwnd)->pDlgResize, hwnd, message, wParam, lParam ); 00591 return TRUE; 00592 00593 case WM_SHOWWINDOW: 00594 00595 /* 00596 * If hiding the window, save the focus. If showing the window 00597 * by means of a SW_* command and the fEnd bit is set, do not 00598 * pass to DWP so it won't get shown. 00599 */ 00600 if (GetParentDialog(pwnd) == pwnd) { 00601 if (!wParam) { 00602 xxxSaveDlgFocus(pwnd); 00603 } else { 00604 00605 if (LOWORD(lParam) != 0 && PDLG(pwnd)->fEnd) 00606 break; 00607 00608 /* 00609 * Snap the cursor to the center of the default button. 00610 * Only do this if the current thread is in the foreground. 00611 * The _ShowCursor() code is added to work around a 00612 * problem with hardware cursors. If change is done 00613 * in the same refresh cycle, the display of the cursor 00614 * would not reflect the new position. 00615 */ 00616 if (TEST_PUSIF(PUSIF_SNAPTO) && 00617 IsInForegroundQueue(hwnd)) { 00618 hwndT1 = GetDlgItem(hwnd, PDLG(pwnd)->result); 00619 if (hwndT1) { 00620 RECT rc; 00621 00622 NtUserShowCursor(FALSE); 00623 00624 GetWindowRect(hwndT1, &rc); 00625 NtUserSetCursorPos(rc.left + ((rc.right - rc.left)/2), 00626 rc.top + ((rc.bottom - rc.top)/2)); 00627 00628 NtUserShowCursor(TRUE); 00629 } 00630 } 00631 } 00632 } 00633 goto CallDWP; 00634 00635 case WM_SYSCOMMAND: 00636 if (GetParentDialog(pwnd) == pwnd) { 00637 /* 00638 * If hiding the window, save the focus. If showing the window 00639 * by means of a SW_* command and the fEnd bit is set, do not 00640 * pass to DWP so it won't get shown. 00641 */ 00642 if ((int)wParam == SC_MINIMIZE) 00643 xxxSaveDlgFocus(pwnd); 00644 } 00645 goto CallDWP; 00646 00647 case WM_ACTIVATE: 00648 pwndT1 = GetParentDialog(pwnd); 00649 if ( pwndT1 != pwnd) { 00650 00651 /* 00652 * This random bit is used during key processing - bit 00653 * 08000000 of WM_CHAR messages is set if a dialog is currently 00654 * active. 00655 */ 00656 NtUserSetThreadState(wParam ? QF_DIALOGACTIVE : 0, QF_DIALOGACTIVE); 00657 } 00658 ThreadLock(pwndT1, &tlpwndT1); 00659 if (wParam != 0) 00660 xxxRestoreDlgFocus(pwndT1); 00661 else 00662 xxxSaveDlgFocus(pwndT1); 00663 00664 ThreadUnlock(&tlpwndT1); 00665 break; 00666 00667 case WM_SETFOCUS: 00668 pwndT1 = GetParentDialog(pwnd); 00669 if (!PDLG(pwndT1)->fEnd && !xxxRestoreDlgFocus(pwndT1)) { 00670 00671 pwndT = _GetNextDlgTabItem(pwndT1, NULL, FALSE); 00672 DlgSetFocus(HW(pwndT)); 00673 } 00674 break; 00675 00676 case WM_CLOSE: 00677 /* 00678 * Make sure cancel button is not disabled before sending the 00679 * IDCANCEL. Note that we need to do this as a message instead 00680 * of directly calling the dlg proc so that any dialog box 00681 * filters get this. 00682 */ 00683 pwndT1 = _GetDlgItem(pwnd, IDCANCEL); 00684 if (pwndT1 && TestWF(pwndT1, WFDISABLED)) 00685 NtUserMessageBeep(0); 00686 else 00687 PostMessage(hwnd, WM_COMMAND, MAKELONG(IDCANCEL, BN_CLICKED), 00688 (LPARAM)HW(pwndT1)); 00689 break; 00690 00691 case WM_NCDESTROY: 00692 case WM_FINALDESTROY: 00693 DoCleanup: 00694 NtUserSetThreadState(0, QF_DIALOGACTIVE); 00695 if (!(pwnd->style & DS_LOCALEDIT)) { 00696 if (PDLG(pwnd)->hData) { 00697 ReleaseEditDS(PDLG(pwnd)->hData); 00698 PDLG(pwnd)->hData = NULL; 00699 } 00700 } 00701 00702 /* 00703 * Delete the user defined font if any 00704 */ 00705 if (PDLG(pwnd)->hUserFont) { 00706 DeleteObject(PDLG(pwnd)->hUserFont); 00707 PDLG(pwnd)->hUserFont = NULL; 00708 } 00709 00710 /* 00711 * Free the dialog memory and mark this as a non-dialog window 00712 */ 00713 FreeLookasideEntry(&DialogLookaside, PDLG(pwnd)); 00714 NtUserCallHwndParam(hwnd, 0, SFI_SETDIALOGPOINTER); 00715 break; 00716 00717 case DM_REPOSITION: 00718 { 00719 RECT rc; 00720 PMONITOR pMonitor; 00721 00722 // DAT recorder APP sends it's own private message 0x402 00723 // through and we mistake it to be DM_REPOSITION. To avoid 00724 // this confusion, we do the following check. 00725 // Fix for Bug#25747 -- 9/29/94 -- 00726 if (!TestWF(pwnd, WEFCONTROLPARENT) || 00727 (GETFNID(pwnd) != FNID_DESKTOP && 00728 GETFNID(REBASEPWND(pwnd, spwndParent)) != FNID_DESKTOP)) { 00729 00730 goto CallDWP; 00731 } 00732 00733 CopyRect(&rc, &pwnd->rcWindow); 00734 pMonitor = _MonitorFromRect(&rc, MONITOR_DEFAULTTOPRIMARY); 00735 RepositionRect(pMonitor, &rc, pwnd->style, pwnd->ExStyle); 00736 NtUserSetWindowPos(hwnd, HWND_TOP, rc.left, rc.top, 00737 rc.right-rc.left, rc.bottom-rc.top, 00738 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); 00739 } 00740 break; 00741 00742 case DM_SETDEFID: 00743 pwndT1 = GetParentDialog(pwnd); 00744 ThreadLock(pwndT1, &tlpwndT1); 00745 00746 if (!(PDLG(pwndT1)->fEnd)) { 00747 00748 pwndT2 = NULL; 00749 if (PDLG(pwndT1)->result != 0) 00750 pwndT2 = _FindDlgItem(pwndT1, PDLG(pwndT1)->result); 00751 00752 pwndT3 = NULL; 00753 if (wParam != 0) { 00754 pwndT3 = _GetDlgItem(pwnd, wParam); 00755 } 00756 00757 ThreadLock(pwndT2, &tlpwndT2); 00758 ThreadLock(pwndT3, &tlpwndT3); 00759 00760 xxxCheckDefPushButton(pwndT1, HW(pwndT2), HW(pwndT3)); 00761 00762 ThreadUnlock(&tlpwndT3); 00763 ThreadUnlock(&tlpwndT2); 00764 00765 PDLG(pwndT1)->result = wParam; 00766 // if (PDLG(pwnd)->spwndFocusSave) { 00767 // Lock(&(PDLG(pwnd)->spwndFocusSave), pwndT2); 00768 // } 00769 00770 if (FWINABLE()) { 00771 NotifyWinEvent(EVENT_OBJECT_DEFACTIONCHANGE, HW(pwndT1), OBJID_CLIENT, INDEXID_CONTAINER); 00772 } 00773 } 00774 ThreadUnlock(&tlpwndT1); 00775 return TRUE; 00776 00777 case DM_GETDEFID: 00778 pwndT1 = GetParentDialog(pwnd); 00779 00780 if (!PDLG(pwndT1)->fEnd && PDLG(pwndT1)->result) 00781 return(MAKELONG(PDLG(pwndT1)->result, DC_HASDEFID)); 00782 else 00783 return 0; 00784 break; 00785 00786 /* 00787 * This message was added so that user defined controls that want 00788 * tab keys can pass the tab off to the next/previous control in the 00789 * dialog box. Without this, all they could do was set the focus 00790 * which didn't do the default button stuff. 00791 */ 00792 case WM_NEXTDLGCTL: 00793 pwndTop = GetParentDialog(pwnd); 00794 ThreadLock(pwndTop, &tlpwndTop); 00795 00796 hwndT1 = GetFocus(); 00797 pwndT2 = ValidateHwndNoRip(hwndT1); 00798 if (LOWORD(lParam)) { 00799 if (pwndT2 == NULL) 00800 pwndT2 = pwndTop; 00801 00802 /* 00803 * wParam contains the pwnd of the ctl to set focus to. 00804 */ 00805 if ((pwndT1 = ValidateHwnd((HWND)wParam)) == NULL) { 00806 ThreadUnlock(&tlpwndTop); 00807 return TRUE; 00808 } 00809 } else { 00810 if (pwndT2 == NULL) { 00811 00812 /* 00813 * Set focus to the first tab item. 00814 */ 00815 pwndT1 = _GetNextDlgTabItem(pwndTop, NULL, FALSE); 00816 pwndT2 = pwndTop; 00817 } else { 00818 00819 /* 00820 * If window with focus not a dlg ctl, ignore message. 00821 */ 00822 if (!_IsChild(pwndTop, pwndT2)) { 00823 ThreadUnlock(&tlpwndTop); 00824 return TRUE; 00825 } 00826 /* 00827 * wParam = TRUE for previous, FALSE for next 00828 */ 00829 pwndT1 = _GetNextDlgTabItem(pwndTop, pwndT2, wParam); 00830 00831 /* 00832 * If there is no next item, ignore the message. 00833 */ 00834 if (pwndT1 == NULL) { 00835 ThreadUnlock(&tlpwndTop); 00836 return TRUE; 00837 } 00838 } 00839 } 00840 00841 ThreadLock(pwndT1, &tlpwndT1); 00842 ThreadLock(pwndT2, &tlpwndT2); 00843 00844 DlgSetFocus(HW(pwndT1)); 00845 xxxCheckDefPushButton(pwndTop, HW(pwndT2), HW(pwndT1)); 00846 00847 ThreadUnlock(&tlpwndT2); 00848 ThreadUnlock(&tlpwndT1); 00849 ThreadUnlock(&tlpwndTop); 00850 00851 return TRUE; 00852 00853 case WM_ENTERMENULOOP: 00854 00855 /* 00856 * We need to pop up the combo box window if the user brings 00857 * down a menu. 00858 * 00859 * ... FALL THROUGH... 00860 */ 00861 00862 case WM_LBUTTONDOWN: 00863 case WM_NCLBUTTONDOWN: 00864 hwndT1 = GetFocus(); 00865 if (hwndT1 != NULL) { 00866 pwndT1 = ValidateHwndNoRip(hwndT1); 00867 00868 if (GETFNID(pwndT1) == FNID_COMBOBOX) { 00869 00870 /* 00871 * If user clicks anywhere in dialog box and a combo box (or 00872 * the editcontrol of a combo box) has the focus, then hide 00873 * it's listbox. 00874 */ 00875 ThreadLockAlways(pwndT1, &tlpwndT1); 00876 SendMessage(HWq(pwndT1), CB_SHOWDROPDOWN, FALSE, 0); 00877 ThreadUnlock(&tlpwndT1); 00878 00879 } else { 00880 PWND pwndParent; 00881 00882 /* 00883 * It's a subclassed combo box. See if the listbox and edit 00884 * boxes exist (this is a very cheezy evaluation - what if 00885 * these controls are subclassed too? NOTE: Not checking 00886 * for EditWndProc: it's a client proc address. 00887 */ 00888 pwndParent = REBASEPWND(pwndT1, spwndParent); 00889 if (GETFNID(pwndParent) == FNID_COMBOBOX) { 00890 pwndT1 = pwndParent; 00891 ThreadLock(pwndT1, &tlpwndT1); 00892 SendMessage(HWq(pwndT1), CB_SHOWDROPDOWN, FALSE, 0); 00893 ThreadUnlock(&tlpwndT1); 00894 } 00895 } 00896 } 00897 00898 /* 00899 * Always send the message off to DefWndProc 00900 */ 00901 goto CallDWP; 00902 00903 case WM_GETFONT: 00904 return (LRESULT)PDLG(pwnd)->hUserFont; 00905 00906 case WM_VKEYTOITEM: 00907 case WM_COMPAREITEM: 00908 case WM_CHARTOITEM: 00909 case WM_INITDIALOG: 00910 00911 /* 00912 * We need to return the 0 the app may have returned for these 00913 * items instead of calling defwindow proc. 00914 */ 00915 return result; 00916 00917 // FA 00918 // 00919 case WM_NCHITTEST: 00920 if( PDLG(pwnd)->pDlgResize != NULL ) 00921 { 00922 LRESULT lres=ResizeDlgMessage( PDLG(pwnd)->pDlgResize, hwnd, message, wParam, lParam ); 00923 if( lres ) // && (((PDIALOG)pwnd)->resultWP != 0) ) 00924 return ((PDIALOG)pwnd)->resultWP; 00925 goto CallDWP; 00926 } 00927 00928 case WM_SIZE: 00929 case WM_WINDOWPOSCHANGING: 00930 if( PDLG(pwnd)->pDlgResize != NULL ) 00931 return ResizeDlgMessage( PDLG(pwnd)->pDlgResize, hwnd, message, wParam, lParam ); 00932 goto CallDWP; 00933 break; 00934 // 00935 // FA 00936 00937 case WM_NOTIFYFORMAT: 00938 if (lParam == NF_QUERY) 00939 return((PDLG(pwnd)->flags & DLGF_ANSI ) ? NFR_ANSI : NFR_UNICODE); 00940 return result; 00941 00942 default: 00943 CallDWP: 00944 return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 00945 } 00946 } else if ((message == WM_SHOWWINDOW) && result) { 00947 00948 /* 00949 * For a visible-case we want to snap the cursor regardless of 00950 * what was returned from the dialog-handler on the client. If 00951 * we're going visible, snap the cursor to the dialog-button. 00952 */ 00953 if (GetParentDialog(pwnd) == pwnd) { 00954 00955 if (wParam && ((LOWORD(lParam) == 0) || !PDLG(pwnd)->fEnd)) { 00956 00957 /* 00958 * Snap the cursor to the center of the default button. 00959 * Only do this if the current thread is in the foreground. 00960 * The _ShowCursor() code is added to work around a 00961 * problem with hardware cursors. If change is done 00962 * in the same refresh cycle, the display of the cursor 00963 * would not reflect the new position. 00964 */ 00965 if (TEST_PUSIF(PUSIF_SNAPTO) && 00966 IsInForegroundQueue(hwnd)) { 00967 hwndT1 = GetDlgItem(hwnd, PDLG(pwnd)->result); 00968 if (hwndT1) { 00969 RECT rc; 00970 00971 NtUserShowCursor(FALSE); 00972 00973 GetWindowRect(hwndT1, &rc); 00974 NtUserSetCursorPos(rc.left + ((rc.right - rc.left)/2), 00975 rc.top + ((rc.bottom - rc.top)/2)); 00976 00977 NtUserShowCursor(TRUE); 00978 } 00979 } 00980 } 00981 } 00982 } 00983 00984 00985 /* 00986 * If this is still marked as a dialog window then return the real 00987 * result. Otherwise, we've already processed the WM_NCDESTROY message 00988 * and freed our private memory so return the stored value. 00989 */ 00990 if (TestWF(pwnd, WFDIALOGWINDOW)) 00991 return ((PDIALOG)pwnd)->resultWP; 00992 else 00993 return result; 00994 } 00995 00996 00997 /***************************************************************************\ 00998 * DefDlgProc 00999 * 01000 * Translates the message, calls DefDlgProc on server side. DefDlgProc 01001 * is the default WindowProc for dialogs (NOT the dialog's dialog proc) 01002 * 01003 * 04-11-91 ScottLu Created. 01004 \***************************************************************************/ 01005 01006 LRESULT WINAPI DefDlgProcW( 01007 HWND hwnd, 01008 UINT message, 01009 WPARAM wParam, 01010 LPARAM lParam) 01011 { 01012 PWND pwnd; 01013 01014 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 01015 return (0L); 01016 } 01017 01018 return DefDlgProcWorker(pwnd, message, wParam, lParam, FALSE); 01019 } 01020 01021 LRESULT WINAPI DefDlgProcA( 01022 HWND hwnd, 01023 UINT message, 01024 WPARAM wParam, 01025 LPARAM lParam) 01026 { 01027 PWND pwnd; 01028 01029 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 01030 return (0L); 01031 } 01032 01033 return DefDlgProcWorker(pwnd, message, wParam, lParam, TRUE); 01034 } 01035 01036 01037 /***************************************************************************\ 01038 * DialogBox2 01039 * 01040 * History: 01041 \***************************************************************************/ 01042 01043 int PASCAL DialogBox2( 01044 HWND hwnd, 01045 HWND hwndOwner, 01046 BOOL fDisabled, 01047 BOOL fOwnerIsActiveWindow) 01048 { 01049 MSG msg; 01050 int result; 01051 BOOL fShown; 01052 BOOL fWantIdleMsgs; 01053 BOOL fSentIdleMessage = FALSE; 01054 HWND hwndCapture; 01055 PWND pwnd; 01056 01057 if (hwnd) { 01058 pwnd = ValidateHwnd(hwnd); 01059 } else { 01060 pwnd = NULL; 01061 } 01062 01063 CheckLock(pwnd); 01064 01065 if (pwnd == NULL) { 01066 if ((hwndOwner != NULL) && !fDisabled && IsWindow(hwndOwner)) { 01067 NtUserEnableWindow(hwndOwner, TRUE); 01068 if (fOwnerIsActiveWindow) { 01069 01070 /* 01071 * The dialog box failed but we disabled the owner in 01072 * xxxDialogBoxIndirectParam and if it had the focus, the 01073 * focus was set to NULL. Now, when we enable the window, it 01074 * doesn't get the focus back if it had it previously so we 01075 * need to correct this. 01076 */ 01077 NtUserSetFocus(hwndOwner); 01078 } 01079 } 01080 return -1; 01081 } 01082 01083 hwndCapture = GetCapture(); 01084 if (hwndCapture != NULL) { 01085 SendMessage(hwndCapture, WM_CANCELMODE, 0, 0); 01086 } 01087 01088 /* 01089 * Set the 'parent disabled' flag for EndDialog(). 01090 * convert BOOL to definite bit 0 or 1 01091 */ 01092 PDLG(pwnd)->fDisabled = !!fDisabled; 01093 01094 fShown = TestWF(pwnd, WFVISIBLE); 01095 01096 /* 01097 * Should the WM_ENTERIDLE messages be sent? 01098 */ 01099 fWantIdleMsgs = !(pwnd->style & DS_NOIDLEMSG); 01100 01101 if ((SYSMET(SLOWMACHINE) & 1) && !fShown && !PDLG(pwnd)->fEnd) 01102 goto ShowIt; 01103 01104 while (PDLG(pwnd) && (!PDLG(pwnd)->fEnd)) { 01105 if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 01106 ShowIt: 01107 if (!fShown) { 01108 fShown = TRUE; 01109 01110 #ifdef SYSMODALWINDOWS 01111 if (pwnd == gspwndSysModal) { 01112 /* 01113 * Make this a topmost window 01114 */ 01115 NtUserSetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, 01116 SWP_NOSIZE | SWP_NOMOVE | 01117 SWP_NOREDRAW | SWP_NOACTIVATE); 01118 } 01119 #endif 01120 01121 NtUserShowWindow(hwnd, SHOW_OPENWINDOW); 01122 UpdateWindow(hwnd); 01123 01124 if (FWINABLE()) { 01125 NotifyWinEvent(EVENT_SYSTEM_DIALOGSTART, hwnd, OBJID_WINDOW, INDEXID_CONTAINER); 01126 } 01127 } else { 01128 /* 01129 * Make sure window still exists 01130 */ 01131 if (hwndOwner && !IsWindow(hwndOwner)) 01132 hwndOwner = NULL; 01133 01134 if (hwndOwner && fWantIdleMsgs && !fSentIdleMessage) { 01135 fSentIdleMessage = TRUE; 01136 01137 SendMessage(hwndOwner, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd); 01138 } else { 01139 if ((RevalidateHwnd(hwnd)==NULL) || (pwnd->fnid & FNID_STATUS_BITS)) 01140 break; 01141 01142 NtUserWaitMessage(); 01143 } 01144 } 01145 01146 } else { 01147 /* 01148 * We got a real message. Reset fSentIdleMessage so that we send 01149 * one next time things are calm. 01150 */ 01151 fSentIdleMessage = FALSE; 01152 01153 if (msg.message == WM_QUIT) { 01154 PostQuitMessage(msg.wParam); 01155 break; 01156 } 01157 01158 /* 01159 * If pwnd is a message box, allow Ctrl-C and Ctrl-Ins 01160 * to copy its content to the clipboard. 01161 * Fall through in case hooking apps look for these keys. 01162 */ 01163 if (TestWF(pwnd, WFMSGBOX)) { 01164 if ( (msg.message == WM_CHAR && LOBYTE(msg.wParam) == 3) || 01165 (msg.message == WM_KEYDOWN && LOBYTE(msg.wParam) == VK_INSERT && GetKeyState(VK_CONTROL) < 0)) { 01166 /* 01167 * Send the WM_COPY message and let the original message fall through 01168 * as some apps might want it 01169 */ 01170 SendMessage(hwnd, WM_COPY, 0, 0); 01171 } 01172 } 01173 01174 /* 01175 * Moved the msg filter hook call to IsDialogMessage to allow 01176 * messages to be hooked for both modal and modeless dialog 01177 * boxes. 01178 */ 01179 if (!IsDialogMessage(hwnd, &msg)) { 01180 TranslateMessage(&msg); 01181 DispatchMessage(&msg); 01182 } 01183 01184 /* 01185 * If we get a timer message, go ahead and show the window. 01186 * We may continuously get timer msgs if there are zillions of 01187 * apps running. 01188 * 01189 * If we get a syskeydown message, show the dialog box because 01190 * the user may be bringing down a menu and we want the dialog 01191 * box to become visible. 01192 */ 01193 if (!fShown && (msg.message == WM_TIMER || 01194 msg.message == WM_SYSTIMER || msg.message == WM_SYSKEYDOWN)) 01195 goto ShowIt; 01196 } 01197 01198 #if DBG 01199 if (!RevalidateHwnd(hwnd)) { 01200 /* 01201 * Bogus case - we've already been destroyed somehow (by app, 01202 * GP, etc.) 01203 */ 01204 RIPMSG0(RIP_WARNING, 01205 "Dialog should be dismissed with EndDialog, not DestroyWindow"); 01206 } 01207 #endif 01208 } 01209 01210 if (FWINABLE()) { 01211 NotifyWinEvent(EVENT_SYSTEM_DIALOGEND, hwnd, OBJID_WINDOW, INDEXID_CONTAINER); 01212 } 01213 01214 /* 01215 * Make sure the window still exists 01216 */ 01217 if (!RevalidateHwnd(hwnd)) { 01218 return 0; 01219 } 01220 01221 if (PDLG(pwnd)) 01222 result = PDLG(pwnd)->result; 01223 else 01224 result = 0; 01225 01226 NtUserDestroyWindow(hwnd); 01227 01228 /* 01229 * If the owner window belongs to another thread, the reactivation 01230 * of the owner may have failed within DestroyWindow(). Therefore, 01231 * if the current thread is in the foreground and the owner is not 01232 * in the foreground we can safely set the foreground back 01233 * to the owner. 01234 */ 01235 if (hwndOwner != NULL) { 01236 if (IsCurrentThreadForeground() && 01237 !IsInForegroundQueue(hwndOwner)) { 01238 NtUserSetForegroundWindow(hwndOwner); 01239 } 01240 } 01241 01242 return result; 01243 } 01244 01245 01246 /***************************************************************************\ 01247 * InternalDialogBox 01248 * 01249 * Server portion of DialogBoxIndirectParam. 01250 * 01251 * 04-05-91 ScottLu Created. 01252 \***************************************************************************/ 01253 01254 extern HCURSOR hCurCursor; 01255 01256 int InternalDialogBox( 01257 HANDLE hModule, 01258 LPDLGTEMPLATE lpdt, 01259 HWND hwndOwner, 01260 DLGPROC pfnDialog, 01261 LPARAM lParam, 01262 UINT fSCDLGFlags) 01263 { 01264 int i; 01265 BOOL fDisabled; 01266 HWND hwnd; 01267 PWND pwndOwner; 01268 BOOL fOwnerIsActiveWindow = FALSE; 01269 TL tlpwndOwner; 01270 BOOL fUnlockOwner; 01271 01272 UserAssert(!(fSCDLGFlags & ~(SCDLG_CLIENT|SCDLG_ANSI|SCDLG_16BIT))); // These are the only valid flags 01273 01274 /* 01275 * If hwndOwner == HWNDESKTOP, change it to NULL. This way the desktop 01276 * (and all its children) won't be disabled if the dialog is modal. 01277 */ 01278 if (hwndOwner && SAMEWOWHANDLE(hwndOwner, GetDesktopWindow())) 01279 hwndOwner = NULL; 01280 01281 /* 01282 * We return 0 if the ValidateHwnd fails in order to match Win 3.1 01283 * validation layer which always returns 0 for invalid hwnds even 01284 * if the function is spec'ed to return -1. Autocad setup bug #3615 01285 */ 01286 if (hwndOwner) { 01287 if ((pwndOwner = ValidateHwnd(hwndOwner)) == NULL) { 01288 return (0L); 01289 } 01290 } else { 01291 pwndOwner = NULL; 01292 } 01293 01294 CheckLock(pwndOwner); 01295 01296 fUnlockOwner = FALSE; 01297 if (pwndOwner != NULL) { 01298 01299 /* The following fixes an AV in Corel Photo-Paint 6.0. It passes a 01300 * 16-bit HWND in, and croaks at some point when it gets 16-bit hwnds 01301 * back in send messages. FritzS -- fixing bug 12531 01302 */ 01303 hwndOwner = PtoHq(pwndOwner); 01304 01305 /* 01306 * Make sure the owner is a top level window. 01307 */ 01308 if (TestwndChild(pwndOwner)) { 01309 pwndOwner = GetTopLevelWindow(pwndOwner); 01310 hwndOwner = HWq(pwndOwner); 01311 ThreadLock(pwndOwner, &tlpwndOwner); 01312 fUnlockOwner = TRUE; 01313 } 01314 01315 /* 01316 * Remember if window was originally disabled (so we can set 01317 * the correct state when the dialog goes away. 01318 */ 01319 fDisabled = TestWF(pwndOwner, WFDISABLED); 01320 fOwnerIsActiveWindow = (SAMEWOWHANDLE(hwndOwner, GetActiveWindow())); 01321 01322 /* 01323 * Disable the window. 01324 */ 01325 NtUserEnableWindow(hwndOwner, FALSE); 01326 } 01327 01328 /* 01329 * Don't show cursors on a mouseless system. Put up an hour glass while 01330 * the dialog comes up. 01331 */ 01332 if (SYSMET(MOUSEPRESENT)) { 01333 NtUserSetCursor(LoadCursor(NULL, IDC_WAIT)); 01334 } 01335 01336 /* 01337 * Creates the dialog. Frees the menu if this routine fails. 01338 */ 01339 hwnd = InternalCreateDialog(hModule, lpdt, 0, hwndOwner, 01340 pfnDialog, lParam, fSCDLGFlags); 01341 01342 if (hwnd == NULL) { 01343 01344 /* 01345 * The dialog creation failed. Re-enable the window, destroy the 01346 * menu, ie., fail gracefully. 01347 */ 01348 if (!fDisabled && hwndOwner != NULL) 01349 NtUserEnableWindow(hwndOwner, TRUE); 01350 01351 if (fUnlockOwner) 01352 ThreadUnlock(&tlpwndOwner); 01353 return -1; 01354 } 01355 01356 i = DialogBox2(hwnd, hwndOwner, fDisabled, fOwnerIsActiveWindow); 01357 01358 if (fUnlockOwner) 01359 ThreadUnlock(&tlpwndOwner); 01360 return i; 01361 } 01362 01363 /***************************************************************************\ 01364 ** 01365 ** RepositionRect() 01366 ** 01367 ** Used to ensure that toplevel dialogs are still visible within the 01368 ** desktop area after they've resized. 01369 ** 01370 \***************************************************************************/ 01371 01372 void 01373 RepositionRect( 01374 PMONITOR pMonitor, 01375 LPRECT lprc, 01376 DWORD dwStyle, 01377 DWORD dwExStyle) 01378 { 01379 LPRECT lprcClip; 01380 int y; 01381 01382 UserAssert(lprc); 01383 UserAssert(pMonitor); 01384 01385 if (dwStyle & WS_CHILD) { 01386 if (dwExStyle & WS_EX_CONTROLPARENT) 01387 return; 01388 01389 /* 01390 * Old style 3.1 child dialogs--do this nonsense anyway. Keeps 01391 * FedEx happy. 01392 */ 01393 pMonitor = GetPrimaryMonitor(); 01394 lprcClip = &pMonitor->rcMonitor; 01395 } else if (dwExStyle & WS_EX_TOOLWINDOW) { 01396 lprcClip = &pMonitor->rcMonitor; 01397 } else { 01398 lprcClip = &pMonitor->rcWork; 01399 } 01400 01401 UserAssert(lprc); 01402 01403 y = lprcClip->bottom - (SYSMET(CYEDGE) * 2 + SYSMET(CYKANJIWINDOW)); 01404 01405 if (lprc->bottom > y) { 01406 OffsetRect(lprc, 0, y - lprc->bottom); 01407 } 01408 01409 if (lprc->top < lprcClip->top) { 01410 OffsetRect(lprc, 0, lprcClip->top - lprc->top); 01411 } 01412 01413 if (lprc->right > lprcClip->right) { 01414 OffsetRect(lprc, lprcClip->right - lprc->right, 0); 01415 } 01416 01417 if (lprc->left < lprcClip->left) { 01418 OffsetRect(lprc, lprcClip->left - lprc->left, 0); 01419 } 01420 } 01421 01422 /***************************************************************************\ 01423 * MapDialogRect 01424 * 01425 * History: 01426 \***************************************************************************/ 01427 01428 BOOL MapDialogRect( 01429 HWND hwnd, 01430 LPRECT lprc) 01431 { 01432 PWND pwnd; 01433 01434 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 01435 return FALSE; 01436 } 01437 01438 /* 01439 * Must do special validation here to make sure pwnd is a dialog window. 01440 */ 01441 if (!ValidateDialogPwnd(pwnd)) 01442 return FALSE; 01443 01444 lprc->left = XPixFromXDU(lprc->left, PDLG(pwnd)->cxChar); 01445 lprc->right = XPixFromXDU(lprc->right, PDLG(pwnd)->cxChar); 01446 lprc->top = YPixFromYDU(lprc->top, PDLG(pwnd)->cyChar); 01447 lprc->bottom = YPixFromYDU(lprc->bottom, PDLG(pwnd)->cyChar); 01448 01449 return TRUE; 01450 }

Generated on Sat May 15 19:39:45 2004 for test by doxygen 1.3.7