Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
9.3 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // wnd.c - window functions
  24. ////
  25. #include "winlocal.h"
  26. #include "wnd.h"
  27. #include "trace.h"
  28. #include "sys.h"
  29. ////
  30. // private definitions
  31. ////
  32. // data passed from WndEnableTaskWindows to EnableTaskWndProc
  33. //
  34. typedef struct ENABLETASKWINDOW
  35. {
  36. BOOL fEnable;
  37. HWND hwndExcept;
  38. int iNestLevel;
  39. } ENABLETASKWINDOW, FAR *LPENABLETASKWINDOW;
  40. // helper functions
  41. //
  42. BOOL DLLEXPORT CALLBACK EnableTaskWndProc(HWND hwnd, LPARAM lParam);
  43. ////
  44. // public functions
  45. ////
  46. // WndCenterWindow - center one window on top of another
  47. // <hwnd1> (i) window to be centered
  48. // <hwnd2> (i) window to be centered upon
  49. // NULL center on parent or owner
  50. // <xOffCenter> (i) offset from horizontal center
  51. // 0 center window exactly
  52. // <yOffCenter> (i) offset from vertical center
  53. // 0 center window exactly
  54. // return 0 if success
  55. //
  56. int DLLEXPORT WINAPI WndCenterWindow(HWND hwnd1, HWND hwnd2, int xOffCenter, int yOffCenter)
  57. {
  58. BOOL fSuccess = TRUE;
  59. POINT pt;
  60. RECT rc1;
  61. RECT rc2;
  62. int nWidth;
  63. int nHeight;
  64. if (hwnd1 == NULL)
  65. fSuccess = TraceFALSE(NULL);
  66. else
  67. {
  68. // use parent or owner window if no other specified
  69. //
  70. if (hwnd2 == NULL)
  71. hwnd2 = GetParent(hwnd1);
  72. // use desktop window if no parent or owner
  73. // or if parent or owner is iconic or invisible
  74. //
  75. if (hwnd2 == NULL || IsIconic(hwnd2) || !IsWindowVisible(hwnd2))
  76. hwnd2 = GetDesktopWindow();
  77. // get the rectangles for both windows
  78. //
  79. GetWindowRect(hwnd1, &rc1);
  80. GetClientRect(hwnd2, &rc2);
  81. // calculate the height and width for MoveWindow
  82. //
  83. nWidth = rc1.right - rc1.left;
  84. nHeight = rc1.bottom - rc1.top;
  85. // find the center point and convert to screen coordinates
  86. //
  87. pt.x = (rc2.right - rc2.left) / 2;
  88. pt.y = (rc2.bottom - rc2.top) / 2;
  89. ClientToScreen(hwnd2, &pt);
  90. // calculate the new x, y starting point
  91. //
  92. pt.x -= (nWidth / 2);
  93. pt.y -= (nHeight / 2);
  94. // adjust the window position off center, if necessary
  95. //
  96. pt.x = max(0, pt.x + xOffCenter);
  97. pt.y = max(0, pt.y + yOffCenter);
  98. // center the window
  99. //
  100. if (!MoveWindow(hwnd1, pt.x, pt.y, nWidth, nHeight, FALSE))
  101. fSuccess = TraceFALSE(NULL);
  102. }
  103. return fSuccess ? 0 : -1;
  104. }
  105. // WndMessageBox - display message box, but first disable task windows
  106. // see MessageBox() documentation for behavior
  107. //
  108. int DLLEXPORT WINAPI WndMessageBox(HWND hwndParent, LPCTSTR lpszText, LPCTSTR lpszTitle, UINT fuStyle)
  109. {
  110. int iRet;
  111. HWND hwndActive = GetActiveWindow();
  112. HTASK hTask = NULL;
  113. if (hwndParent != NULL)
  114. hTask = GetWindowTask(hwndParent);
  115. WndEnableTaskWindows(hTask, FALSE, hwndActive);
  116. iRet = MessageBox(hwndActive, lpszText, lpszTitle, fuStyle | MB_TASKMODAL);
  117. WndEnableTaskWindows(hTask, TRUE, NULL);
  118. return iRet;
  119. }
  120. // WndEnableTaskWindows - enable or disable top-level windows of a task
  121. // <hTask> (i) specified task
  122. // NULL current task
  123. // <fEnable> (i) FALSE to disable, TRUE to enable
  124. // <hwndExcept> (i) disable/enable all windows except this one
  125. // NULL no exceptions
  126. // return 0 if success
  127. //
  128. // This function enables or disables top-level windows
  129. // which are owned by the specified task.
  130. //
  131. // Disabling task windows is useful when an a modal
  132. // dialog box or task modal notify box is displayed,
  133. // because this ensures that all task windows are
  134. // disabled, not just the modal box's parent.
  135. //
  136. // Task windows need to be enabled when the modal dialog
  137. // box or task modal notify box is about to be destroyed.
  138. // It is important to call this function in nested pairs,
  139. // such as:
  140. //
  141. // WndEnableTaskWindows(..., FALSE, ...);
  142. // ...
  143. // WndEnableTaskWindows(..., FALSE, ...);
  144. // ...
  145. // WndEnableTaskWindows(..., TRUE, ...);
  146. // ...
  147. // WndEnableTaskWindows(..., TRUE, ...);
  148. //
  149. int DLLEXPORT WINAPI WndEnableTaskWindows(HTASK hTask, BOOL fEnable, HWND hwndExcept)
  150. {
  151. static int iNestLevel = 0;
  152. BOOL fSuccess = TRUE;
  153. ENABLETASKWINDOW etw;
  154. WNDENUMPROC fpEnableTaskWndProc = NULL;
  155. #if 0 // MakeProcInstance not required for WIN32 or DLLs
  156. HINSTANCE hInst;
  157. #endif
  158. // data to be sent to EnableTaskWndProc
  159. //
  160. etw.fEnable = fEnable;
  161. etw.hwndExcept = hwndExcept;
  162. etw.iNestLevel = fEnable ? iNestLevel : iNestLevel + 1;
  163. // assume current task if none specified
  164. //
  165. if (hTask == NULL && (hTask = GetCurrentTask()) == NULL)
  166. fSuccess = TraceFALSE(NULL);
  167. #if 1 // MakeProcInstance not required for WIN32 or DLLs
  168. else if ((fpEnableTaskWndProc = (WNDENUMPROC) EnableTaskWndProc) == NULL)
  169. fSuccess = TraceFALSE(NULL);
  170. #else
  171. // get instance handle of specified task
  172. //
  173. else if ((hInst = SysGetTaskInstance(hTask)) == NULL)
  174. fSuccess = TraceFALSE(NULL);
  175. else if ((fpEnableTaskWndProc = (WNDENUMPROC)
  176. MakeProcInstance((FARPROC) EnableTaskWndProc, hInst)) == NULL)
  177. fSuccess = TraceFALSE(NULL);
  178. #endif
  179. // call EnableTaskWndProc once for each task window
  180. //
  181. else if (EnumTaskWindows(hTask, fpEnableTaskWndProc,
  182. (LPARAM) (LPENABLETASKWINDOW) &etw) == 0)
  183. fSuccess = TraceFALSE(NULL);
  184. #if 0 // MakeProcInstance not required for WIN32 or DLLs
  185. if (fpEnableTaskWndProc != NULL)
  186. {
  187. FreeProcInstance((FARPROC) fpEnableTaskWndProc);
  188. fpEnableTaskWndProc = NULL;
  189. }
  190. #endif
  191. if (fSuccess)
  192. {
  193. // if we just finished disabling, increment nest level
  194. //
  195. if (!fEnable)
  196. ++iNestLevel;
  197. // if we just finished enabling, decrement nest level
  198. //
  199. if (fEnable)
  200. --iNestLevel;
  201. }
  202. return fSuccess ? 0 : -1;
  203. }
  204. ////
  205. // helper functions
  206. ////
  207. // EnableTaskWndProc - called once for each task window
  208. // <hwnd> (i) task window handle
  209. // <lParam> (i) pointer to ENABLETASKWINDOW struct
  210. // return TRUE to continue enumeration of task windows
  211. //
  212. BOOL DLLEXPORT CALLBACK EnableTaskWndProc(HWND hwnd, LPARAM lParam)
  213. {
  214. static LPTSTR lpszProp = TEXT("TaskWindowDisabled");
  215. LPENABLETASKWINDOW lpetw = (LPENABLETASKWINDOW) lParam;
  216. BOOL fEnable = lpetw->fEnable;
  217. int iNestLevel = lpetw->iNestLevel;
  218. HWND hwndExcept = lpetw->hwndExcept;
  219. //
  220. //
  221. HANDLE hProp = NULL;
  222. if (TraceGetLevel(NULL) >= 6)
  223. {
  224. TCHAR szClassName[64];
  225. TCHAR szWindowText[128];
  226. *szClassName = '\0';
  227. GetClassName(hwnd, szClassName, SIZEOFARRAY(szClassName));
  228. *szWindowText = '\0';
  229. GetWindowText(hwnd, szWindowText, SIZEOFARRAY(szWindowText));
  230. TracePrintf_7(NULL, 6, TEXT("TaskWindow: (%p, \"%s\", \"%s\" \"%c%c%c\", %d)\n"),
  231. hwnd,
  232. (LPTSTR) szClassName,
  233. (LPTSTR) szWindowText,
  234. (TCHAR) (IsIconic(hwnd) ? 'I' : ' '),
  235. (TCHAR) (IsWindowVisible(hwnd) ? 'V' : ' '),
  236. (TCHAR) (IsWindowEnabled(hwnd) ? 'E' : ' '),
  237. (int) iNestLevel);
  238. }
  239. // the exception window should not be affected
  240. //
  241. if (hwndExcept != NULL && hwndExcept == hwnd)
  242. {
  243. TraceOutput(NULL, 6, TEXT("->hwndExcept\n"));
  244. return TRUE;
  245. }
  246. // NOTE: we only disable/enable task windows which are visible.
  247. // This is convenient because:
  248. // 1) it prevents unnecessary disabling/enabling
  249. // of invisible windows, which can't receive
  250. // mouse or keyboard input anyway.
  251. // 2) it allows us to call this function from
  252. // a dialog box's WM_INITDIALOG handler without
  253. // affecting the dialog box itself (the dialog box is
  254. // a top-level task window, but is not yet visible)
  255. // 3) it prevents the listbox of a drop-down ComboBox
  256. // from being disabled, which is somehow considered
  257. // a top-level task window
  258. if (!fEnable)
  259. {
  260. // only disable windows which are visible and enabled
  261. //
  262. if (!IsIconic(hwnd) && IsWindowVisible(hwnd) && IsWindowEnabled(hwnd))
  263. {
  264. // give the window a property reminding us we disabled it
  265. //
  266. if (SetProp(hwnd, lpszProp, (HANDLE) (WORD) iNestLevel))
  267. {
  268. TraceOutput(NULL, 6, TEXT("->EnableWindow(FALSE)\n"));
  269. EnableWindow(hwnd, FALSE);
  270. }
  271. }
  272. }
  273. else if (fEnable)
  274. {
  275. // only enable windows which we disabled at this nest level
  276. //
  277. if (GetProp(hwnd, lpszProp) == (HANDLE) (WORD) iNestLevel)
  278. {
  279. TraceOutput(NULL, 6, TEXT("->EnableWindow(TRUE)\n"));
  280. EnableWindow(hwnd, TRUE);
  281. //
  282. // We should delete the handler
  283. //
  284. hProp = RemoveProp(hwnd, lpszProp);
  285. if( hProp )
  286. {
  287. GlobalUnlock( hProp );
  288. GlobalFree( hProp );
  289. }
  290. }
  291. }
  292. // keep calling this function until no more task windows
  293. //
  294. return TRUE;
  295. }