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

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