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.

431 lines
13 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: MBOXEX.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 7/13/2000
  12. *
  13. * DESCRIPTION: Super duper message box
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <simcrack.h>
  19. #include <movewnd.h>
  20. #include <dlgunits.h>
  21. #include <simrect.h>
  22. #include <shlwapi.h>
  23. #include "mboxex.rh"
  24. #include "mboxex.h"
  25. extern HINSTANCE g_hInstance;
  26. CMessageBoxEx::CMessageBoxEx( HWND hWnd )
  27. : m_hWnd(hWnd),
  28. m_pData(NULL)
  29. {
  30. }
  31. LRESULT CMessageBoxEx::OnInitDialog( WPARAM, LPARAM lParam )
  32. {
  33. WIA_PUSHFUNCTION(TEXT("CMessageBoxEx::OnInitDialog"));
  34. //
  35. // Actual button ids
  36. //
  37. const UINT nButtonIds[MaxButtons] = { IDC_MESSAGEBOX_BUTTON_1, IDC_MESSAGEBOX_BUTTON_2, IDC_MESSAGEBOX_BUTTON_3, IDC_MESSAGEBOX_BUTTON_4 };
  38. //
  39. // Get the data, and return and error if it is invalid
  40. //
  41. m_pData = reinterpret_cast<CData*>(lParam);
  42. if (!m_pData)
  43. {
  44. EndDialog( m_hWnd, -1 );
  45. return 0;
  46. }
  47. //
  48. // Set the button text for the used buttons
  49. //
  50. for (UINT i=0,nStart=MaxButtons-m_pData->m_nButtonCount;i<m_pData->m_nButtonCount;i++)
  51. {
  52. SetWindowLongPtr( GetDlgItem( m_hWnd, nButtonIds[nStart+i] ), GWLP_USERDATA, nButtonIds[nStart+i] );
  53. }
  54. //
  55. // Set the default for the "Hide future messages" button
  56. //
  57. if (m_pData->m_bHideMessageInFuture)
  58. {
  59. SendDlgItemMessage( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE, BM_SETCHECK, BST_CHECKED, 0 );
  60. }
  61. int nDeltaY = 0;
  62. HDC hDC = GetDC( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_MESSAGE ) );
  63. if (hDC)
  64. {
  65. //
  66. // Get the window rect of the message control
  67. //
  68. CSimpleRect rcMessage( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_MESSAGE ), CSimpleRect::WindowRect );
  69. rcMessage.ScreenToClient(m_hWnd);
  70. //
  71. // Get the correct font
  72. //
  73. HFONT hFont = reinterpret_cast<HFONT>(SendDlgItemMessage( m_hWnd, IDC_MESSAGEBOX_MESSAGE, WM_GETFONT, 0, 0 ));
  74. if (!hFont)
  75. {
  76. hFont = reinterpret_cast<HFONT>(GetStockObject(SYSTEM_FONT));
  77. }
  78. if (hFont)
  79. {
  80. //
  81. // Calculate the height of the text
  82. //
  83. CSimpleRect rcText = rcMessage;
  84. HFONT hOldFont = reinterpret_cast<HFONT>(SelectObject( hDC, hFont ));
  85. int nHeight = DrawText( hDC, m_pData->m_strMessage, m_pData->m_strMessage.Length(), &rcText, DT_CALCRECT|DT_EXPANDTABS|DT_NOPREFIX|DT_WORDBREAK );
  86. //
  87. // Only resize the control if it needs to be larger. Don't do it if the control needs to be smaller.
  88. //
  89. if (nHeight > rcMessage.Height())
  90. {
  91. nDeltaY += (rcMessage.Height() - nHeight);
  92. CMoveWindow().Size( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_MESSAGE ), 0, nHeight, CMoveWindow::NO_SIZEX );
  93. }
  94. SelectObject( hDC, hOldFont );
  95. }
  96. ReleaseDC( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_MESSAGE ), hDC );
  97. }
  98. //
  99. // If we are not supposed to show the "Hide future messages" button, hide it
  100. // and move all of the controls up by its height and vertical margin.
  101. //
  102. if ((m_pData->m_nFlags & MBEX_HIDEFUTUREMESSAGES) == 0)
  103. {
  104. EnableWindow( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE ), FALSE );
  105. ShowWindow( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE ), SW_HIDE );
  106. //
  107. // Figure out how much to move the controls up
  108. //
  109. nDeltaY += CSimpleRect( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE ), CSimpleRect::WindowRect ).Height() + CDialogUnits(m_hWnd).Y(7);
  110. }
  111. if (nDeltaY)
  112. {
  113. CMoveWindow mw;
  114. //
  115. // Move the "Hide future messages" button
  116. //
  117. mw.Move( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE ), 0, CSimpleRect( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - nDeltaY, CMoveWindow::NO_MOVEX );
  118. //
  119. // Figure out what the top row is
  120. //
  121. int nButtonTopRow = CSimpleRect( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_BUTTON_4 ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - nDeltaY;
  122. //
  123. // Move all of the buttons
  124. //
  125. mw.Move( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_BUTTON_1 ), 0, nButtonTopRow, CMoveWindow::NO_MOVEX );
  126. mw.Move( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_BUTTON_2 ), 0, nButtonTopRow, CMoveWindow::NO_MOVEX );
  127. mw.Move( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_BUTTON_3 ), 0, nButtonTopRow, CMoveWindow::NO_MOVEX );
  128. mw.Move( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_BUTTON_4 ), 0, nButtonTopRow, CMoveWindow::NO_MOVEX );
  129. mw.Apply();
  130. //
  131. // Resize the dialog
  132. //
  133. CSimpleRect rcDialog( m_hWnd, CSimpleRect::WindowRect );
  134. SetWindowPos( m_hWnd, NULL, 0, 0, rcDialog.Width(), rcDialog.Height()-nDeltaY, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
  135. }
  136. //
  137. // Hide and disable the unused buttons
  138. //
  139. for (i=0;i<MaxButtons-m_pData->m_nButtonCount;i++)
  140. {
  141. EnableWindow( GetDlgItem( m_hWnd, nButtonIds[i] ), FALSE );
  142. ShowWindow( GetDlgItem( m_hWnd, nButtonIds[i] ), SW_HIDE );
  143. }
  144. //
  145. // Set the button IDs. Do this last, so we can use constants until then
  146. //
  147. for (UINT i=0,nStart=MaxButtons-m_pData->m_nButtonCount;i<m_pData->m_nButtonCount;i++)
  148. {
  149. WIA_TRACE((TEXT("SetWindowLongPtr( GetDlgItem( m_hWnd, %d ), GWLP_ID, %d );"), nButtonIds[nStart+i], m_pData->m_Buttons[i] ));
  150. SetWindowLongPtr( GetDlgItem( m_hWnd, nButtonIds[nStart+i] ), GWLP_ID, m_pData->m_Buttons[i] );
  151. }
  152. //
  153. // Set the focus and default button
  154. //
  155. if (m_pData->m_nDefault)
  156. {
  157. SetFocus( GetDlgItem( m_hWnd, m_pData->m_nDefault) );
  158. SendDlgItemMessage( GetParent(m_hWnd), m_pData->m_nDefault, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE,0) );
  159. SendMessage( m_hWnd, DM_SETDEFID, m_pData->m_nDefault, 0 );
  160. }
  161. //
  162. // Set the icon
  163. //
  164. SendDlgItemMessage( m_hWnd, IDC_MESSAGEBOX_ICON, STM_SETICON, reinterpret_cast<WPARAM>(m_pData->m_hIcon), 0 );
  165. //
  166. // Set the message text
  167. //
  168. m_pData->m_strMessage.SetWindowText( GetDlgItem( m_hWnd, IDC_MESSAGEBOX_MESSAGE ) );
  169. //
  170. // Set the window text
  171. //
  172. m_pData->m_strTitle.SetWindowText( m_hWnd );
  173. SetForegroundWindow( m_hWnd );
  174. return TRUE;
  175. }
  176. LRESULT CMessageBoxEx::OnCommand( WPARAM wParam, LPARAM lParam )
  177. {
  178. //
  179. // First, check to see if this message pertains to one of our buttons
  180. //
  181. for (UINT i=0;i<m_pData->m_nButtonCount;i++)
  182. {
  183. if ((LOWORD(wParam) == m_pData->m_Buttons[i]) == (HIWORD(wParam) == BN_CLICKED))
  184. {
  185. //
  186. // Store the "Hide this message in the future" value
  187. //
  188. m_pData->m_bHideMessageInFuture = (BST_CHECKED == SendDlgItemMessage( m_hWnd, IDC_MESSAGEBOX_HIDEINFUTURE, BM_GETCHECK, 0, 0 ));
  189. //
  190. // Close the dialog
  191. //
  192. EndDialog( m_hWnd, LOWORD(wParam) );
  193. return 0;
  194. }
  195. }
  196. if (LOWORD(wParam) == IDCANCEL)
  197. {
  198. EndDialog( m_hWnd, IDCANCEL );
  199. return 0;
  200. }
  201. SC_BEGIN_COMMAND_HANDLERS()
  202. {
  203. }
  204. SC_END_COMMAND_HANDLERS();
  205. }
  206. INT_PTR CALLBACK CMessageBoxEx::DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  207. {
  208. SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CMessageBoxEx)
  209. {
  210. SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog );
  211. SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand );
  212. }
  213. SC_END_DIALOG_MESSAGE_HANDLERS();
  214. }
  215. UINT CMessageBoxEx::MessageBox( HWND hWndParent, LPCTSTR pszMessage, LPCTSTR pszTitle, UINT nFlags, bool *pbHideFutureMessages )
  216. {
  217. CData Data;
  218. Data.m_nFlags = nFlags;
  219. Data.m_strMessage = pszMessage;
  220. Data.m_strTitle = pszTitle;
  221. //
  222. // Figure out which set of buttons to use
  223. //
  224. int nDialogResource = 0;
  225. if (nFlags & MBEX_OKCANCEL)
  226. {
  227. nDialogResource = IDD_MESSAGEBOX_OKCANCEL;
  228. Data.m_Buttons[0] = IDMBEX_OK;
  229. Data.m_Buttons[1] = IDMBEX_CANCEL;
  230. Data.m_nButtonCount = 2;
  231. }
  232. else if (nFlags & MBEX_YESNO)
  233. {
  234. nDialogResource = IDD_MESSAGEBOX_YESNO;
  235. Data.m_Buttons[0] = IDMBEX_YES;
  236. Data.m_Buttons[1] = IDMBEX_NO;
  237. Data.m_nButtonCount = 2;
  238. }
  239. else if (nFlags & MBEX_CANCELRETRYSKIPSKIPALL)
  240. {
  241. nDialogResource = IDD_MESSAGEBOX_CANCELRETRYSKIPSKIPALL;
  242. Data.m_Buttons[0] = IDMBEX_CANCEL;
  243. Data.m_Buttons[1] = IDMBEX_RETRY;
  244. Data.m_Buttons[2] = IDMBEX_SKIP;
  245. Data.m_Buttons[3] = IDMBEX_SKIPALL;
  246. Data.m_nButtonCount = 4;
  247. }
  248. else if (nFlags & MBEX_CANCELRETRY)
  249. {
  250. nDialogResource = IDD_MESSAGEBOX_CANCELRETRY;
  251. Data.m_Buttons[0] = IDMBEX_CANCEL;
  252. Data.m_Buttons[1] = IDMBEX_RETRY;
  253. Data.m_nButtonCount = 2;
  254. }
  255. else if (nFlags & MBEX_YESYESTOALLNONOTOALL)
  256. {
  257. nDialogResource = IDD_MESSAGEBOX_YESYESTOALLNONOTOALL;
  258. Data.m_Buttons[0] = IDMBEX_YES;
  259. Data.m_Buttons[1] = IDMBEX_YESTOALL;
  260. Data.m_Buttons[2] = IDMBEX_NO;
  261. Data.m_Buttons[3] = IDMBEX_NOTOALL;
  262. Data.m_nButtonCount = 4;
  263. }
  264. else
  265. {
  266. nDialogResource = IDD_MESSAGEBOX_OK;
  267. Data.m_Buttons[0] = IDMBEX_OK;
  268. Data.m_nButtonCount = 1;
  269. }
  270. //
  271. // Figure out which icon to use
  272. //
  273. if (nFlags & MBEX_ICONWARNING)
  274. {
  275. Data.m_hIcon = LoadIcon( NULL, IDI_WARNING );
  276. MessageBeep( MB_ICONWARNING );
  277. }
  278. else if (nFlags & MBEX_ICONERROR)
  279. {
  280. Data.m_hIcon = LoadIcon( NULL, IDI_ERROR );
  281. MessageBeep( MB_ICONERROR );
  282. }
  283. else if (nFlags & MBEX_ICONQUESTION)
  284. {
  285. Data.m_hIcon = LoadIcon( NULL, IDI_QUESTION );
  286. MessageBeep( MB_ICONQUESTION );
  287. }
  288. else
  289. {
  290. Data.m_hIcon = LoadIcon( NULL, IDI_INFORMATION );
  291. MessageBeep( MB_ICONINFORMATION );
  292. }
  293. //
  294. // Figure out which button should be the default
  295. //
  296. if (nFlags & MBEX_DEFBUTTON2)
  297. {
  298. Data.m_nDefault = Data.m_Buttons[1];
  299. }
  300. else if (nFlags & MBEX_DEFBUTTON3)
  301. {
  302. Data.m_nDefault = Data.m_Buttons[2];
  303. }
  304. else if (nFlags & MBEX_DEFBUTTON4)
  305. {
  306. Data.m_nDefault = Data.m_Buttons[3];
  307. }
  308. else
  309. {
  310. Data.m_nDefault = Data.m_Buttons[0];
  311. }
  312. if (pbHideFutureMessages)
  313. {
  314. Data.m_bHideMessageInFuture = *pbHideFutureMessages;
  315. }
  316. INT_PTR nResult = DialogBoxParam( g_hInstance, MAKEINTRESOURCE(nDialogResource), hWndParent, DialogProc, reinterpret_cast<LPARAM>(&Data) );
  317. if (pbHideFutureMessages)
  318. {
  319. *pbHideFutureMessages = Data.m_bHideMessageInFuture;
  320. }
  321. return static_cast<UINT>(nResult);
  322. }
  323. UINT CMessageBoxEx::MessageBox( HWND hWndParent, LPCTSTR pszMessage, LPCTSTR pszTitle, UINT nFlags, bool &bHideFutureMessages )
  324. {
  325. return MessageBox( hWndParent, pszMessage, pszTitle, nFlags|MBEX_HIDEFUTUREMESSAGES, &bHideFutureMessages );
  326. }
  327. UINT CMessageBoxEx::MessageBox( HWND hWndParent, LPCTSTR pszMessage, LPCTSTR pszTitle, UINT nFlags )
  328. {
  329. return MessageBox( hWndParent, pszMessage, pszTitle, nFlags, NULL );
  330. }
  331. UINT CMessageBoxEx::MessageBox( LPCTSTR pszMessage, LPCTSTR pszTitle, UINT nFlags )
  332. {
  333. return MessageBox( NULL, pszMessage, pszTitle, nFlags, NULL );
  334. }
  335. UINT CMessageBoxEx::MessageBox( HWND hWndParent, HINSTANCE hInstance, UINT nMessageId, UINT nTitleId, UINT nFlags, bool &bHideFutureMessages )
  336. {
  337. return MessageBox( hWndParent, CSimpleString(nMessageId,hInstance), CSimpleString(nTitleId,hInstance), nFlags|MBEX_HIDEFUTUREMESSAGES, &bHideFutureMessages );
  338. }
  339. UINT CMessageBoxEx::MessageBox( HWND hWndParent, LPCTSTR pszTitle, UINT nFlags, LPCTSTR pszFormat, ... )
  340. {
  341. TCHAR szMessage[1024] = {0};
  342. va_list arglist;
  343. va_start( arglist, pszFormat );
  344. wvnsprintf( szMessage, ARRAYSIZE(szMessage), pszFormat, arglist );
  345. va_end( arglist );
  346. return MessageBox( hWndParent, szMessage, pszTitle, nFlags, NULL );
  347. }
  348. UINT CMessageBoxEx::MessageBox( HWND hWndParent, LPCTSTR pszTitle, UINT nFlags, bool &bHideFutureMessages, LPCTSTR pszFormat, ... )
  349. {
  350. TCHAR szMessage[1024] = {0};
  351. va_list arglist;
  352. va_start( arglist, pszFormat );
  353. wvnsprintf( szMessage, ARRAYSIZE(szMessage), pszFormat, arglist );
  354. va_end( arglist );
  355. return MessageBox( hWndParent, szMessage, pszTitle, nFlags, &bHideFutureMessages );
  356. }
  357. UINT CMessageBoxEx::MessageBox( HWND hWndParent, HINSTANCE hInstance, UINT nTitleId, UINT nFlags, UINT nFormatId, ... )
  358. {
  359. TCHAR szMessage[1024] = {0};
  360. va_list arglist;
  361. va_start( arglist, nFormatId );
  362. wvnsprintf( szMessage, ARRAYSIZE(szMessage), CSimpleString(nFormatId,hInstance), arglist );
  363. va_end( arglist );
  364. return MessageBox( hWndParent, szMessage, CSimpleString(nTitleId,hInstance), nFlags, NULL );
  365. }