Source code of Windows XP (NT5)
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.

382 lines
12 KiB

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: User.cpp
  4. // Created: Feb 1996
  5. // By: Martin Holladay (a-martih) and Ryan D. Marshall (a-ryanm)
  6. //
  7. // Project: MultiDesk - The NT Desktop Switcher
  8. //
  9. //
  10. //
  11. // Revision History:
  12. //
  13. // March 1997 - Add external icon capability
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////
  16. #include <windows.h>
  17. #include <assert.h>
  18. #include <shellapi.h>
  19. #include <prsht.h>
  20. #include <commctrl.h>
  21. #include "Resource.h"
  22. #include "DeskSpc.h"
  23. #include "Desktop.h"
  24. #include "User.h"
  25. #include "Menu.h"
  26. #include "CmdHand.h"
  27. extern APPVARS AppMember;
  28. /*------------------------------------------------------------------------------*/
  29. /* */
  30. /* Create the rectangular window that makes up the main user-interface. */
  31. /* */
  32. /*------------------------------------------------------------------------------*/
  33. BOOL CreateMainWindow()
  34. {
  35. HWND hWnd, hWndListView;
  36. DWORD ThreadId;
  37. HIMAGELIST hImgListSmall;
  38. UINT ii;
  39. RECT rect;
  40. //
  41. // We had better have an instance of the app
  42. //
  43. assert(AppMember.hInstance != NULL);
  44. //
  45. // Create a main window for this application instance.
  46. //
  47. hWnd = CreateWindowEx(
  48. WS_EX_TOPMOST | WS_EX_DLGMODALFRAME | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW,
  49. AppMember.szAppName,
  50. AppMember.szAppTitle,
  51. WS_POPUPWINDOW | WS_DLGFRAME,
  52. AppMember.nX,
  53. AppMember.nY,
  54. AppMember.nWidth,
  55. AppMember.nHeight,
  56. NULL,
  57. NULL,
  58. AppMember.hInstance,
  59. NULL);
  60. //
  61. // If window could not be created, return FALSE
  62. //
  63. if (!hWnd)
  64. {
  65. return FALSE;
  66. }
  67. //
  68. // Save the hWnd of the Window
  69. //
  70. ThreadId = GetCurrentThreadId();
  71. AppMember.pDesktopControl->SetThreadWindow(ThreadId, hWnd);
  72. //
  73. // Hide until we're supposed to be seen window
  74. //
  75. ShowWindow(hWnd, SW_HIDE);
  76. //
  77. // Create the child listview window to contain all of the icons.
  78. //
  79. GetClientRect(hWnd, &rect);
  80. AppMember.nWidth = rect.right;
  81. AppMember.nHeight = rect.bottom;
  82. hWndListView = CreateWindow(WC_LISTVIEW, NULL,
  83. WS_VISIBLE | WS_CHILDWINDOW | LVS_LIST | LVS_SINGLESEL |
  84. LVS_SHOWSELALWAYS | LVS_OWNERDATA,
  85. 0, 0, AppMember.nWidth, AppMember.nHeight,
  86. hWnd, (HMENU) IDC_DESKTOPICONLIST, AppMember.hInstance, NULL);
  87. ListView_SetExtendedListViewStyle(hWndListView,
  88. LVS_EX_ONECLICKACTIVATE | LVS_EX_UNDERLINEHOT);
  89. //
  90. // Create an image list containing small icons and assign it.
  91. //
  92. hImgListSmall = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, NUM_BUILTIN_ICONS, 0);
  93. if (hImgListSmall != NULL)
  94. {
  95. for (ii = 0; ii < NUM_BUILTIN_ICONS; ii++)
  96. ImageList_AddIcon(hImgListSmall,
  97. AppMember.pDesktopControl->GetBuiltinIcon(ii));
  98. ListView_SetImageList(hWndListView, hImgListSmall, LVSIL_SMALL);
  99. }
  100. UpdateCurrentUI(hWnd);
  101. return TRUE;
  102. }
  103. /*------------------------------------------------------------------------------*/
  104. /* */
  105. /* Make a cute little transparent layered window that displays some text */
  106. /* */
  107. /*------------------------------------------------------------------------------*/
  108. BOOL CreateTransparentLabelWindow()
  109. {
  110. HWND hWnd;
  111. DWORD ThreadId;
  112. UINT DesktopID;
  113. TCHAR szLabelText[MAX_NAME_LENGTH];
  114. // Get the saifer name
  115. ThreadId = GetCurrentThreadId();
  116. DesktopID = AppMember.pDesktopControl->GetThreadDesktopID(ThreadId);
  117. if (!AppMember.pDesktopControl->GetDesktopName(DesktopID, szLabelText, MAX_NAME_LENGTH) ||
  118. !lstrlen(szLabelText))
  119. lstrcpy(szLabelText, TEXT("Unknown desktop"));
  120. // Create the transparent window.
  121. hWnd = CreateWindowEx(
  122. WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,
  123. TRANSPARENT_CLASSNAME,
  124. szLabelText,
  125. WS_DISABLED | WS_VISIBLE | WS_POPUP,
  126. TRANSPARENT_POSITIONS,
  127. NULL,
  128. NULL,
  129. AppMember.hInstance,
  130. (LPVOID) NULL);
  131. if (hWnd != NULL)
  132. {
  133. SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
  134. SWP_NOSIZE | SWP_NOREPOSITION | SWP_NOMOVE);
  135. SetLayeredWindowAttributes(hWnd, TRANSPARENT_BACKCOLOR,
  136. TRANSPARENT_ALPHA, LWA_COLORKEY | LWA_ALPHA);
  137. ShowWindow(hWnd, SW_SHOW);
  138. return TRUE;
  139. }
  140. return FALSE;
  141. }
  142. /*------------------------------------------------------------------------------*/
  143. /* */
  144. /* Add our little icon to the Task Bar Notification Area ("the Tray") */
  145. /* */
  146. /*------------------------------------------------------------------------------*/
  147. BOOL PlaceOnTaskbar(HWND hWnd)
  148. {
  149. NOTIFYICONDATA NotifyIconData;
  150. //
  151. // Create the Icon on the Taskbar
  152. //
  153. ZeroMemory(&NotifyIconData, sizeof(NOTIFYICONDATA));
  154. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  155. NotifyIconData.hWnd = hWnd;
  156. NotifyIconData.uID = IDI_TASKBAR_ICON;
  157. NotifyIconData.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
  158. NotifyIconData.uCallbackMessage = WM_TASKBAR;
  159. NotifyIconData.hIcon = AppMember.hTaskbarIcon;
  160. LoadString(AppMember.hInstance, IDS_TASKBAR_TIP, NotifyIconData.szTip, 64);
  161. if (!Shell_NotifyIcon(NIM_ADD, &NotifyIconData))
  162. {
  163. return FALSE;
  164. }
  165. AppMember.bTrayed = TRUE;
  166. return TRUE;
  167. }
  168. /*------------------------------------------------------------------------------*/
  169. /* */
  170. /* Remove the little icon from the Task Bar Notification Area ("the Tray") */
  171. /* */
  172. /*------------------------------------------------------------------------------*/
  173. BOOL RemoveFromTaskbar(HWND hWnd)
  174. {
  175. NOTIFYICONDATA NotifyIconData;
  176. //
  177. // Remove the Icon from the Taskbar
  178. //
  179. ZeroMemory(&NotifyIconData, sizeof(NOTIFYICONDATA));
  180. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  181. NotifyIconData.hWnd = hWnd;
  182. NotifyIconData.uID = IDI_TASKBAR_ICON;
  183. if (!Shell_NotifyIcon(NIM_DELETE, &NotifyIconData))
  184. {
  185. return FALSE;
  186. }
  187. AppMember.bTrayed = FALSE;
  188. return TRUE;
  189. }
  190. /*------------------------------------------------------------------------------*/
  191. /* */
  192. /* Decided if the app should shut down */
  193. /* */
  194. /*------------------------------------------------------------------------------*/
  195. BOOL CloseRequestHandler(HWND hWnd)
  196. {
  197. BOOL Shutdown = FALSE;
  198. TCHAR szCaption[MAX_TITLELEN + 1];
  199. TCHAR szText[MAX_MESSAGE];
  200. HWND hMainWnd;
  201. UINT rValue;
  202. //
  203. // Verify that user wishes to close the app. We don't ask
  204. // the user for confirmation if there is only one desktop open.
  205. //
  206. if (AppMember.pDesktopControl->GetNumDesktops() > 1)
  207. {
  208. LoadString(AppMember.hInstance, IDS_CLOSE_CAPTION, szCaption, MAX_TITLELEN);
  209. LoadString(AppMember.hInstance, IDS_CLOSE_VERIFY, szText, MAX_MESSAGE);
  210. rValue = MessageBox(hWnd, szText, szCaption, MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL);
  211. if ((rValue == 0) || (rValue == IDCANCEL))
  212. Shutdown = FALSE;
  213. else
  214. Shutdown = TRUE;
  215. }
  216. else
  217. Shutdown = TRUE;
  218. //
  219. // Get the window handle and send the Shutdown Message
  220. //
  221. if (Shutdown)
  222. {
  223. // Save any scheme changes made to the current desktop
  224. AppMember.pDesktopControl->SaveCurrentDesktopScheme();
  225. hMainWnd = AppMember.pDesktopControl->GetWindowDesktop(0);
  226. PostMessage(hMainWnd, WM_ENDSESSION, 0, 0);
  227. }
  228. return Shutdown;
  229. }
  230. /*------------------------------------------------------------------------------*/
  231. /* */
  232. /* Update UI for the current desktop (usually Add/Deletes cause change) */
  233. /* */
  234. /*------------------------------------------------------------------------------*/
  235. void UpdateCurrentUI(HWND hWnd)
  236. {
  237. HWND hWndList = GetDlgItem(hWnd, IDC_DESKTOPICONLIST);
  238. if (hWndList != NULL)
  239. {
  240. ListView_SetItemCountEx(hWndList,
  241. AppMember.pDesktopControl->GetNumDesktops(), 0);
  242. for (UINT ii = 0; ii < AppMember.pDesktopControl->GetNumDesktops(); ii++)
  243. {
  244. if (ii == AppMember.pDesktopControl->GetActiveDesktop()) {
  245. ListView_SetItemState(hWndList, ii,
  246. LVIS_FOCUSED | LVIS_SELECTED,
  247. LVIS_FOCUSED | LVIS_SELECTED);
  248. } else {
  249. ListView_SetItemState(hWndList, ii,
  250. LVIS_FOCUSED | LVIS_SELECTED, 0);
  251. }
  252. }
  253. ListView_RedrawItems(hWndList, 0,
  254. AppMember.pDesktopControl->GetNumDesktops() - 1);
  255. }
  256. InvalidateRect(hWnd, NULL, TRUE);
  257. }
  258. /*------------------------------------------------------------------------------*/
  259. /* */
  260. /* Hide or show the UI for the current desktop */
  261. /* */
  262. /*------------------------------------------------------------------------------*/
  263. void HideOrRevealUI(HWND hWnd, BOOL bHide)
  264. {
  265. if (bHide)
  266. {
  267. #ifndef NOANIMATEDWINDOWS
  268. AnimateWindow(hWnd, 100, AW_HIDE | AW_HOR_POSITIVE | AW_VER_POSITIVE);
  269. #else
  270. ShowWindow(hWnd, SW_HIDE);
  271. #endif
  272. }
  273. else
  274. {
  275. #ifndef NOANIMATEDWINDOWS
  276. AnimateWindow(hWnd, 100, AW_HOR_NEGATIVE | AW_VER_NEGATIVE);
  277. #else
  278. ShowWindow(hWnd, SW_SHOW);
  279. #endif
  280. }
  281. }
  282. /*------------------------------------------------------------------------------*/
  283. /* */
  284. /* Sets up and starts the RenameDialog within a Property Sheet */
  285. /* The RenameDialog's messages are handled by CallBack in CmdHandlers.cpp */
  286. /* */
  287. /*------------------------------------------------------------------------------*/
  288. void RenameDialog(HWND hWnd, UINT nBtnIndex) // zero based
  289. {
  290. PROPSHEETHEADER psh;
  291. PROPSHEETPAGE pspRename;
  292. RENAMEINFO sRenameInfo;
  293. TCHAR szText[MAX_TITLELEN+1];
  294. TCHAR szCaptionText[MAX_TITLELEN+1];
  295. TCHAR szErrMsg[MAX_TITLELEN+1];
  296. assert(nBtnIndex >= 0 && nBtnIndex < AppMember.pDesktopControl->GetNumDesktops());
  297. sRenameInfo.nBtnIndex = nBtnIndex;
  298. //
  299. // Setup the Rename dialog page
  300. //
  301. pspRename.dwSize = sizeof(PROPSHEETPAGE);
  302. pspRename.dwFlags = PSP_USETITLE;
  303. pspRename.hInstance = AppMember.hInstance;
  304. pspRename.pszTemplate = MAKEINTRESOURCE(IDD_PROPERTIES);
  305. pspRename.pfnDlgProc = (DLGPROC) RenameDialogProc;
  306. pspRename.lParam = (LPARAM) &sRenameInfo;
  307. pspRename.pszTitle = MAKEINTRESOURCE(IDS_GENERAL);
  308. //
  309. // Setup the property sheet
  310. //
  311. psh.dwSize = sizeof(PROPSHEETHEADER);
  312. psh.dwFlags = PSH_PROPSHEETPAGE;
  313. psh.hwndParent = hWnd;
  314. psh.hInstance = AppMember.hInstance;
  315. LoadString(AppMember.hInstance, IDS_PROPS, szCaptionText, MAX_TITLELEN);
  316. psh.pszCaption = szCaptionText;
  317. psh.nPages = 1;
  318. psh.ppsp = (LPCPROPSHEETPAGE) &pspRename;
  319. //
  320. // Run the property sheet
  321. //
  322. if (PropertySheet(&psh) < 0)
  323. {
  324. LoadString(AppMember.hInstance, IDS_RENDLG_ERR, szErrMsg, MAX_TITLELEN);
  325. Message(szErrMsg);
  326. }
  327. }