loginboxTosReminder.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "./loginbox.h"
  2. #include "./loginpage.h"
  3. #include "../resource.h"
  4. #include "../api.h"
  5. #include <windows.h>
  6. typedef struct __TOSREMINDERCREATEPARAM
  7. {
  8. HANDLE hModal;
  9. BOOL fAnimate;
  10. INT_PTR *pResult;
  11. } TOSREMINDERCREATEPARAM;
  12. typedef struct __TOSREMINDER
  13. {
  14. HANDLE hModal;
  15. BOOL fAnimate;
  16. SIZE idealSize;
  17. INT_PTR *pResult;
  18. } TOSREMINDER;
  19. #define TOSREMINDER_PROP L"LoginboxTosReminderProp"
  20. #define GetTosReminder(__hwnd) ((TOSREMINDER*)GetProp(__hwnd, TOSREMINDER_PROP))
  21. static INT_PTR CALLBACK TosReminder_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  22. static INT_PTR TosReminder_EnterModalLoop(HANDLE hExit);
  23. HWND TosReminder_CreateWindow(HWND hParent)
  24. {
  25. if (NULL == hParent)
  26. return NULL;
  27. return WASABI_API_CREATEDIALOGPARAMW(IDD_TOSREMINDER, hParent, TosReminder_DialogProc, 0L);
  28. }
  29. INT_PTR TosReminder_Show(HWND hParent, INT controlId, BOOL fAnimate)
  30. {
  31. if (NULL == hParent)
  32. return -1;
  33. INT_PTR result;
  34. TOSREMINDERCREATEPARAM param;
  35. param.fAnimate = fAnimate;
  36. param.pResult = &result;
  37. param.hModal = CreateEvent(NULL, FALSE, FALSE, NULL);
  38. if (NULL == param.hModal) return -1;
  39. HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_TOSREMINDER,
  40. hParent, TosReminder_DialogProc, (LPARAM)&param);
  41. if (NULL == hwnd) return -1;
  42. SetWindowLongPtr(hwnd, GWLP_ID, controlId);
  43. SetWindowPos(hParent, NULL, 0, 0, 0, 0,
  44. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
  45. if (FALSE == fAnimate ||
  46. 0 == AnimateWindow(hwnd, 150, AW_ACTIVATE | AW_VER_POSITIVE | AW_SLIDE))
  47. {
  48. ShowWindow(hwnd, SW_SHOWNORMAL);
  49. }
  50. TosReminder_EnterModalLoop(param.hModal);
  51. return result;
  52. }
  53. static void TosReminder_EndDialog(HWND hwnd, INT_PTR code)
  54. {
  55. TOSREMINDER *reminder = GetTosReminder(hwnd);
  56. if (NULL != reminder)
  57. {
  58. if (NULL != reminder->pResult)
  59. {
  60. (*reminder->pResult) = code;
  61. reminder->pResult = NULL;
  62. }
  63. if (NULL != reminder->hModal)
  64. {
  65. SetEvent(reminder->hModal);
  66. reminder->hModal = NULL;
  67. }
  68. if (FALSE == reminder->fAnimate ||
  69. 0 == AnimateWindow(hwnd, 150, AW_HIDE | AW_VER_NEGATIVE | AW_SLIDE))
  70. {
  71. ShowWindow(hwnd, SW_HIDE);
  72. }
  73. }
  74. DestroyWindow(hwnd);
  75. }
  76. static void TosReminder_UpdateLayout(HWND hwnd, BOOL fRedraw)
  77. {
  78. RECT clientRect;
  79. if (FALSE == GetClientRect(hwnd, &clientRect)) return;
  80. LONG centerX = clientRect.left + (clientRect.right - clientRect.left)/2;
  81. LONG buttonTop = clientRect.bottom;
  82. const INT szControls[] = {IDOK, IDCANCEL, IDC_TEXT, };
  83. RECT controlRect;
  84. UINT sharedFlags = SWP_NOZORDER | SWP_NOACTIVATE;
  85. if (FALSE == fRedraw) sharedFlags |= SWP_NOREDRAW;
  86. HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
  87. if (NULL == hdwp) return;
  88. UINT controlFlags;
  89. LONG x, y, cx, cy;
  90. for (INT i = 0; i < ARRAYSIZE(szControls); i++)
  91. {
  92. HWND hControl = GetDlgItem(hwnd, szControls[i]);
  93. if (NULL == hControl || FALSE == GetWindowRect(hControl, &controlRect))
  94. continue;
  95. controlFlags = sharedFlags;
  96. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&controlRect, 2);
  97. x = controlRect.left;
  98. y = controlRect.top;
  99. cx = controlRect.right - controlRect.left;
  100. cy = controlRect.bottom - controlRect.top;
  101. switch(szControls[i])
  102. {
  103. case IDOK:
  104. x = centerX - cx - 8;
  105. if (x < clientRect.left) x = clientRect.left;
  106. y = (clientRect.bottom - 8) - cy;
  107. if (y < clientRect.top) y = clientRect.top;
  108. if (y < buttonTop) buttonTop = y;
  109. break;
  110. case IDCANCEL:
  111. x = centerX + 8;
  112. if ((x + cx) > clientRect.right) x = clientRect.right - cx;
  113. y = (clientRect.bottom - 8) - cy;
  114. if (y < clientRect.top) y = clientRect.top;
  115. if (y < buttonTop) buttonTop = y;
  116. break;
  117. case IDC_TEXT:
  118. cx = (clientRect.right - clientRect.left) - 2*x;
  119. cy = (buttonTop - y) - 16;
  120. break;
  121. }
  122. hdwp = DeferWindowPos(hdwp, hControl, NULL, x, y, cx, cy, controlFlags);
  123. if (NULL == hdwp) return;
  124. }
  125. EndDeferWindowPos(hdwp);
  126. if (FALSE != fRedraw)
  127. {
  128. HWND hControl = GetDlgItem(hwnd, IDC_TEXT);
  129. if (NULL != hControl) InvalidateRect(hControl, NULL, FALSE);
  130. }
  131. }
  132. static INT_PTR TosReminder_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM param)
  133. {
  134. TOSREMINDER *reminder = (TOSREMINDER*)malloc(sizeof(TOSREMINDER));
  135. if (NULL == reminder)
  136. {
  137. DestroyWindow(hwnd);
  138. return 0;
  139. }
  140. ZeroMemory(reminder, sizeof(TOSREMINDER));
  141. SetProp(hwnd, TOSREMINDER_PROP, reminder);
  142. TOSREMINDERCREATEPARAM *createParam = (TOSREMINDERCREATEPARAM*)param;
  143. if (NULL != createParam)
  144. {
  145. reminder->fAnimate = createParam->fAnimate;
  146. reminder->hModal = createParam->hModal;
  147. reminder->pResult = createParam->pResult;
  148. }
  149. RECT windowRect;
  150. if (FALSE != GetWindowRect(hwnd, &windowRect))
  151. {
  152. reminder->idealSize.cx = windowRect.right - windowRect.left;
  153. reminder->idealSize.cy = windowRect.bottom - windowRect.top;
  154. }
  155. PostMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0L);
  156. return 0;
  157. }
  158. static void TosReminder_OnDestroy(HWND hwnd)
  159. {
  160. TOSREMINDER *reminder = GetTosReminder(hwnd);
  161. RemoveProp(hwnd, TOSREMINDER_PROP);
  162. if (NULL == reminder)
  163. return;
  164. if (NULL != reminder->pResult)
  165. {
  166. (*reminder->pResult) = -1;
  167. }
  168. if (NULL != reminder->hModal)
  169. {
  170. SetEvent(reminder->hModal);
  171. reminder->hModal = NULL;
  172. }
  173. free(reminder);
  174. }
  175. static void TosReminder_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp)
  176. {
  177. if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
  178. {
  179. TosReminder_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags));
  180. }
  181. }
  182. static void TosReminder_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND hControl)
  183. {
  184. switch(commandId)
  185. {
  186. case IDOK:
  187. TosReminder_EndDialog(hwnd, commandId);
  188. break;
  189. case IDCANCEL:
  190. TosReminder_EndDialog(hwnd, commandId);
  191. break;
  192. }
  193. }
  194. static BOOL TosReminder_OnGetIdealSize(HWND hwnd, SIZE *pSize)
  195. {
  196. TOSREMINDER *reminder = GetTosReminder(hwnd);
  197. if (NULL == reminder || NULL == pSize) return FALSE;
  198. CopyMemory(pSize, &reminder->idealSize, sizeof(SIZE));
  199. return TRUE;
  200. }
  201. static BOOL TosReminder_OnClose(HWND hwnd, BOOL *pfAbort)
  202. {
  203. TOSREMINDER *reminder = GetTosReminder(hwnd);
  204. if (NULL != reminder) reminder->fAnimate = FALSE;
  205. TosReminder_EndDialog(hwnd, IDCANCEL);
  206. return TRUE;
  207. }
  208. static INT_PTR CALLBACK TosReminder_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  209. {
  210. switch(uMsg)
  211. {
  212. case WM_INITDIALOG: return TosReminder_OnInitDialog(hwnd, (HWND)wParam, lParam);
  213. case WM_DESTROY: TosReminder_OnDestroy(hwnd); return 0;
  214. case WM_WINDOWPOSCHANGED: TosReminder_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return TRUE;
  215. case WM_COMMAND: TosReminder_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
  216. case NLPM_GETIDEALSIZE: MSGRESULT(hwnd, TosReminder_OnGetIdealSize(hwnd, (SIZE*)lParam));
  217. case NLPM_CLOSE: MSGRESULT(hwnd, TosReminder_OnClose(hwnd, (BOOL*)lParam));
  218. }
  219. return 0;
  220. }
  221. static BOOL TosReminder_PumpMessages()
  222. {
  223. MSG msg;
  224. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  225. {
  226. if (WM_QUIT == msg.message)
  227. {
  228. PostQuitMessage((int)msg.wParam);
  229. return TRUE;
  230. }
  231. if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
  232. {
  233. TranslateMessage(&msg);
  234. DispatchMessage(&msg);
  235. }
  236. }
  237. return FALSE;
  238. }
  239. static INT_PTR TosReminder_EnterModalLoop(HANDLE hExit)
  240. {
  241. if (NULL == hExit)
  242. return FALSE;
  243. for(;;)
  244. {
  245. DWORD code = MsgWaitForMultipleObjectsEx(1, &hExit, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
  246. switch(code)
  247. {
  248. case WAIT_FAILED:
  249. return FALSE;
  250. case WAIT_OBJECT_0:
  251. return TRUE;
  252. case (WAIT_OBJECT_0 + 1):
  253. if (FALSE != TosReminder_PumpMessages())
  254. return TRUE;
  255. break;
  256. }
  257. }
  258. return TRUE;
  259. }