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.

186 lines
5.0 KiB

  1. ////////////////////////////////////////////////////////////////
  2. // MSDN -- August 2000
  3. // If this code works, it was written by Paul DiLascia.
  4. // If not, I don't know who wrote it.
  5. // Largely based on original implementation by Michael Lemley.
  6. // Compiles with Visual C++ 6.0, runs on Windows 98 and probably NT too.
  7. //
  8. // CFileDialogEx implements a CFileDialog that uses the new Windows
  9. // 2000 style open/save dialog. Use companion class CDocManagerEx in an
  10. // MFC framework app.
  11. //
  12. #include "stdafx.h"
  13. #include <afxpriv.h>
  14. #include "FileDialogEx.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. static BOOL IsWin2000();
  21. IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)
  22. CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt,
  23. LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
  24. CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName,
  25. dwFlags, lpszFilter, pParentWnd)
  26. {
  27. }
  28. BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog)
  29. //{{AFX_MSG_MAP(CFileDialogEx)
  30. //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32. BOOL IsWin2000()
  33. {
  34. OSVERSIONINFOEX osvi;
  35. BOOL bOsVersionInfoEx;
  36. // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
  37. // which is supported on Windows 2000.
  38. //
  39. // If that fails, try using the OSVERSIONINFO structure.
  40. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  41. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  42. if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
  43. {
  44. // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  45. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  46. if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
  47. return FALSE;
  48. }
  49. switch (osvi.dwPlatformId)
  50. {
  51. case VER_PLATFORM_WIN32_NT:
  52. if ( osvi.dwMajorVersion >= 5 )
  53. return TRUE;
  54. break;
  55. }
  56. return FALSE;
  57. }
  58. //////////////////
  59. // DoModal override copied mostly from MFC, with modification to use
  60. // m_ofnEx instead of m_ofn.
  61. //
  62. INT_PTR CFileDialogEx::DoModal()
  63. {
  64. ASSERT_VALID(this);
  65. ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
  66. ASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
  67. // zero out the file buffer for consistent parsing later
  68. ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
  69. DWORD nOffset = lstrlen(m_ofn.lpstrFile)+1;
  70. ASSERT(nOffset <= m_ofn.nMaxFile);
  71. memset(m_ofn.lpstrFile+nOffset, 0, (m_ofn.nMaxFile-nOffset)*sizeof(TCHAR));
  72. // WINBUG: This is a special case for the file open/save dialog,
  73. // which sometimes pumps while it is coming up but before it has
  74. // disabled the main window.
  75. HWND hWndFocus = ::GetFocus();
  76. BOOL bEnableParent = FALSE;
  77. m_ofn.hwndOwner = PreModal();
  78. AfxUnhookWindowCreate();
  79. if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
  80. {
  81. bEnableParent = TRUE;
  82. ::EnableWindow(m_ofn.hwndOwner, FALSE);
  83. }
  84. _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  85. ASSERT(pThreadState->m_pAlternateWndInit == NULL);
  86. if (m_ofn.Flags & OFN_EXPLORER)
  87. pThreadState->m_pAlternateWndInit = this;
  88. else
  89. AfxHookWindowCreate(this);
  90. memset(&m_ofnEx, 0, sizeof(m_ofnEx));
  91. memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn));
  92. if (IsWin2000())
  93. m_ofnEx.lStructSize = sizeof(m_ofnEx);
  94. INT_PTR nResult;
  95. if (m_bOpenFileDialog)
  96. nResult = ::GetOpenFileName((OPENFILENAME*)&m_ofnEx);
  97. else
  98. nResult = ::GetSaveFileName((OPENFILENAME*)&m_ofnEx);
  99. memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
  100. m_ofn.lStructSize = sizeof(m_ofn);
  101. if (nResult)
  102. ASSERT(pThreadState->m_pAlternateWndInit == NULL);
  103. pThreadState->m_pAlternateWndInit = NULL;
  104. // WINBUG: Second part of special case for file open/save dialog.
  105. if (bEnableParent)
  106. ::EnableWindow(m_ofnEx.hwndOwner, TRUE);
  107. if (::IsWindow(hWndFocus))
  108. ::SetFocus(hWndFocus);
  109. PostModal();
  110. return nResult ? nResult : IDCANCEL;
  111. }
  112. //////////////////
  113. // When the open dialog sends a notification, copy m_ofnEx to m_ofn in
  114. // case handler function is expecting updated information in the
  115. // OPENFILENAME struct.
  116. //
  117. BOOL CFileDialogEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  118. {
  119. memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
  120. m_ofn.lStructSize = sizeof(m_ofn);
  121. return CFileDialog::OnNotify( wParam, lParam, pResult);
  122. }
  123. ////////////////////////////////////////////////////////////////
  124. // The following functions are provided for testing purposes, to
  125. // demonstrate that they in fact called; ie, that MFC's internal dialog
  126. // proc is hooked up properly. Delete them if you like.
  127. //
  128. BOOL CFileDialogEx::OnFileNameOK()
  129. {
  130. TRACE(_T("CFileDialogEx::OnFileNameOK\n"));
  131. return CFileDialog::OnFileNameOK();
  132. }
  133. void CFileDialogEx::OnInitDone()
  134. {
  135. TRACE(_T("CFileDialogEx::OnInitDone\n"));
  136. CFileDialog::OnInitDone();
  137. }
  138. void CFileDialogEx::OnFileNameChange()
  139. {
  140. TRACE(_T("CFileDialogEx::OnFileNameChange\n"));
  141. CFileDialog::OnFileNameChange();
  142. }
  143. void CFileDialogEx::OnFolderChange()
  144. {
  145. TRACE(_T("CFileDialogEx::OnFolderChange\n"));
  146. CFileDialog::OnFolderChange();
  147. }
  148. void CFileDialogEx::OnTypeChange()
  149. {
  150. TRACE(_T("OnTypeChange(), index = %d\n"), m_ofn.nFilterIndex);
  151. CFileDialog::OnTypeChange();
  152. }