00001 /***************************************************************************\ 00002 * 00003 * DLGEND.C - 00004 * 00005 * Copyright (c) 1985 - 1999, Microsoft Corporation 00006 * 00007 * Dialog Destruction Routines 00008 * 00009 * ??-???-???? mikeke Ported from Win 3.0 sources 00010 * 12-Feb-1991 mikeke Added Revalidation code 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 00017 /***************************************************************************\ 00018 * EndDialog 00019 * 00020 * History: 00021 * 11-Dec-1990 mikeke ported from win30 00022 \***************************************************************************/ 00023 00024 BOOL EndDialog( 00025 HWND hwnd, 00026 INT_PTR result) 00027 { 00028 PWND pwnd; 00029 PWND pwndOwner; 00030 HWND hwndOwner; 00031 BOOL fWasActive = FALSE; 00032 #ifdef SYSMODALWINDOWS 00033 HWND hwndOldSysModal; 00034 #endif 00035 00036 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 00037 return (0L); 00038 } 00039 00040 CheckLock(pwnd); 00041 00042 /* 00043 * Must do special validation here to make sure pwnd is a dialog window. 00044 */ 00045 if (!ValidateDialogPwnd(pwnd)) 00046 return 0; 00047 00048 if (SAMEWOWHANDLE(hwnd, GetActiveWindow())) { 00049 fWasActive = TRUE; 00050 } 00051 00052 /* 00053 * GetWindowCreator returns either a kernel address or NULL. 00054 */ 00055 pwndOwner = GetWindowCreator(pwnd); 00056 00057 if (pwndOwner != NULL) { 00058 00059 /* 00060 * Hide the window. 00061 */ 00062 pwndOwner = REBASEPTR(pwnd, pwndOwner); 00063 hwndOwner = HWq(pwndOwner); 00064 if (!PDLG(pwnd)->fDisabled) { 00065 NtUserEnableWindow(hwndOwner, TRUE); 00066 } 00067 } else { 00068 hwndOwner = NULL; 00069 } 00070 00071 /* 00072 * Terminate Mode Loop. 00073 */ 00074 PDLG(pwnd)->fEnd = TRUE; 00075 PDLG(pwnd)->result = result; 00076 00077 if (fWasActive && IsChild(hwnd, GetFocus())) { 00078 00079 /* 00080 * Set focus to the dialog box so that any control which has the focus 00081 * can do an kill focus processing. Most useful for combo boxes so that 00082 * they can popup their dropdowns before destroying/hiding the dialog 00083 * box window. Note that we only do this if the focus is currently at a 00084 * child of this dialog box. We also need to make sure we are the active 00085 * window because this may be happening while we are in a funny state. 00086 * ie. the activation is in the middle of changing but the focus hasn't 00087 * changed yet. This happens with TaskMan (or maybe with other apps that 00088 * change the focus/activation at funny times). 00089 */ 00090 NtUserSetFocus(hwnd); 00091 } 00092 00093 NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0, 00094 SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | 00095 SWP_NOSIZE | SWP_NOZORDER); 00096 00097 #ifdef SYSMODALWINDOWS 00098 00099 /* 00100 * If this guy was sysmodal, set the sysmodal flag to previous guy so we 00101 * won't have a hidden sysmodal window that will screw things 00102 * up royally... 00103 */ 00104 if (pwnd == gspwndSysModal) { 00105 hwndOldSysModal = PDLG(pwnd)->hwndSysModalSave; 00106 if (hwndOldSysModal && !IsWindow(hwndOldSysModal)) 00107 hwndOldSysModal = NULL; 00108 00109 SetSysModalWindow(hwndOldSysModal); 00110 00111 // If there was a previous system modal window, we want to 00112 // activate it instead of this window's owner. 00113 // 00114 if (hwndOldSysModal) 00115 hwndOwner = hwndOldSysModal; 00116 } 00117 #endif 00118 00119 /* 00120 * Don't do any activation unless we were previously active. 00121 */ 00122 if (fWasActive && hwndOwner) { 00123 NtUserSetActiveWindow(hwndOwner); 00124 } else { 00125 00126 /* 00127 * If at this point we are still the active window it means that 00128 * we have fallen into the black hole of being the only visible 00129 * window in the system when we hid ourselves. This is a bug and 00130 * needs to be fixed better later on. For now, though, just 00131 * set the active and focus window to NULL. 00132 */ 00133 if (SAMEWOWHANDLE(hwnd, GetActiveWindow())) { 00134 // The next two lines are *not* the equivalent of the two Unlock 00135 // statements that were in Daytona server-side dlgend.c. So, we 00136 // need to go over to server/kernel and do it right. This fixes 00137 // a problem in Visual Slick, which had the MDI window lose focus 00138 // when a message box was dismissed. FritzS 00139 // SetActiveWindow(NULL); 00140 // SetFocus(NULL); 00141 NtUserCallNoParam(SFI_ZAPACTIVEANDFOCUS); 00142 } 00143 } 00144 00145 #ifdef SYSMODALWINDOWS 00146 00147 /* 00148 * If this guy was sysmodal, set the sysmodal flag to previous guy so we 00149 * won't have a hidden sysmodal window that will screw things 00150 * up royally... 00151 * See comments for Bug #134; SANKAR -- 08-25-89 --; 00152 */ 00153 if (pwnd == gspwndSysModal) { 00154 00155 /* 00156 * Check if the previous Sysmodal guy is still valid? 00157 */ 00158 hwndOldSysModal = PDLG(pwnd)->hwndSysModalSave; 00159 if (hwndOldSysModal && !IsWindow(hwndOldSysModal)) 00160 hwndOldSysModal = NULL; 00161 SetSysModalWindow(hwndOldSysModal); 00162 } 00163 #endif 00164 00165 /* 00166 * Make sure the dialog loop will wake and destroy the window. 00167 * The dialog loop is waiting on posted events (WaitMessage). If 00168 * EndDialog is called due to a sent message from another thread the 00169 * dialog loop will keep waiting for posted events and not destroy 00170 * the window. This happens when the dialog is obscured. 00171 * This is a problem with winfile and its copy/move dialog. 00172 */ 00173 PostMessage(hwnd, WM_NULL, 0, 0); 00174 00175 return TRUE; 00176 }