// MainDlg.cpp : implementation file // #include "stdafx.h" #include "MainApp.h" #include "MainDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // LUserDicomDir Class LUserDicomDir::LUserDicomDir(L_CHAR* pszDICOMDIRDstFolder, L_CHAR* pszPath) : LDicomDir(pszDICOMDIRDstFolder, pszPath) { m_bDicomDirExists = FALSE; m_uAddedDicomFilesCount = 0; m_pWndStatus = NULL; } L_VOID LUserDicomDir::Reset() { m_bDicomDirExists = FALSE; m_uAddedDicomFilesCount = 0; } L_VOID LUserDicomDir::SetWndStatus(CWnd* pWndStatus) { m_pWndStatus = pWndStatus; } L_UINT LUserDicomDir::GetAddedDicomFilesCount() const { return m_uAddedDicomFilesCount; } L_BOOL LUserDicomDir::DoesDicomDirExist() const { return m_bDicomDirExists; } L_UINT16 LUserDicomDir::OnInsertDicomFile(const L_CHAR* pszFileName, LDicomDS* pDataSet, L_UINT16 uStatusCode) { if (uStatusCode == DICOMDIR_INSERTDICOMFILE_PREADD) // About to add the DICOM file? { L_UINT32 uIOD; pDataSet->GetInfoDS(&uIOD, NULL); if (uIOD == CLASS_BASIC_DIRECTORY) // Is it a DICOMDIR file? { m_bDicomDirExists = TRUE; return DICOM_ERROR_FORMAT; } else if (m_pWndStatus) { CString sStatus = "Status: Adding the file \""; sStatus += pszFileName; sStatus += "\""; m_pWndStatus->SetWindowText(sStatus); } } else if (uStatusCode == DICOM_SUCCESS) // The DICOM file has been added successfully? { m_uAddedDicomFilesCount++; } return DICOM_SUCCESS; } ///////////////////////////////////////////////////////////////////////////// // CMainDlg dialog CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/) : CDialog(CMainDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMainDlg) m_bInsertIconImgSeq = FALSE; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMainDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMainDlg) DDX_Control(pDX, IDC_TREE, m_Tree); DDX_Control(pDX, IDC_LIST, m_List); DDX_Check(pDX, IDC_CHECK_INSERTICONIMGSEQ, m_bInsertIconImgSeq); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMainDlg, CDialog) //{{AFX_MSG_MAP(CMainDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse) ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelChangedTree) ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE, OnItemExpandingTree) ON_NOTIFY(NM_DBLCLK, IDC_TREE, OnDblClkTree) ON_WM_CLOSE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMainDlg message handlers UINT CMainDlg::m_BitmapList[] = { IDB_STORAGE_EXPANDED, IDB_STORAGE_COLLAPSED, IDB_STREAM }; BOOL CMainDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here LBase::LoadLibraries(LT_KRN | LT_DIS); CBitmap Bitmap; int iSize = sizeof(m_BitmapList) / sizeof(m_BitmapList[0]); m_ImageList.Create(16, 16, ILC_MASK, 0, iSize); for (int i = 0; i < iSize; i++) { Bitmap.LoadBitmap(m_BitmapList[i]); m_ImageList.Add(&Bitmap, (COLORREF) 0xFFFFFF); Bitmap.DeleteObject(); } m_Tree.SetImageList(&m_ImageList, TVSIL_NORMAL); return TRUE; // return TRUE unless you set the focus to a control } void CMainDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMainDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMainDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } /*************************************************************************************/ /* This function contains all the code you need in order to create a DICOM Directory */ /* for all the DICOM files in a folder. */ /*************************************************************************************/ L_UINT16 CMainDlg::DoCreateDicomDir() { // Reset the DICOM Directory and set the destination folder where the DICOMDIR // File will be saved m_DicomDir.ResetDicomDir((const L_CHAR*) m_sDicomFilesFolder); // If it is desired to change the values of the Implementation Class // UID (0002,0012) and the Implementation Version Name (0002,0013)... pDICOMELEMENT pElement; pElement = m_DicomDir.FindFirstElement(NULL, TAG_IMPLEMENTATION_CLASS_UID, FALSE); if (pElement) { m_DicomDir.SetStringValue(pElement, "1.2.840.114257.0.1", 1); // Must be a UID } pElement = m_DicomDir.FindFirstElement(NULL, TAG_IMPLEMENTATION_VERSION_NAME, FALSE); if (pElement) { m_DicomDir.SetStringValue(pElement, "LEADTOOLS 13", 1); // Up to 16 characters } DICOMDIROPTIONS Options; m_DicomDir.GetOptions(&Options, sizeof(DICOMDIROPTIONS)); // Ensure that subfolders are to be included Options.bIncludeSubfolders = TRUE; // Do we need to insert icon image sequences? UpdateData(TRUE); if (m_bInsertIconImgSeq) { Options.uFlags = Options.uFlags | DICOMDIR_INSERT_ICON_IMAGE_SEQUENCE; } else { Options.uFlags = Options.uFlags & ~DICOMDIR_INSERT_ICON_IMAGE_SEQUENCE; } m_DicomDir.SetOptions(&Options); m_DicomDir.Reset(); m_DicomDir.SetWndStatus(GetDlgItem(IDC_STATUS)); // Add the DICOM files to the DICOM Directory. // This is the function that does it all! // You can always give the user feedback about the progress inside this function by // overriding the function LDicomDir::OnInsertDicomFile. return m_DicomDir.InsertDicomFile(NULL); } void CMainDlg::OnButtonBrowse() { // Let the user choose a folder if (!GetFolder("Choose a Folder:", m_hWnd)) return; CWaitCursor Wait; m_BitmapWindow.SetHandle(NULL); m_BitmapWindow.SetWndHandle(NULL); m_Tree.DeleteAllItems(); m_List.DeleteAllItems(); m_List.RedrawWindow(); SetDlgItemText(IDC_SELECTED_DIR, m_sDicomFilesFolder); // Create a DICOM Directory for all the files in the folder m_sDicomFilesFolder and // all subfolders if (DoCreateDicomDir() != DICOM_SUCCESS) { SetDlgItemText(IDC_STATUS, "Status: Failed to create the DICOM Directory!"); return; } if (m_DicomDir.GetAddedDicomFilesCount() == 0) { SetDlgItemText(IDC_STATUS, "Status: Search is complete. No DICOM files were added to the DICOM Directory."); return; } FillTree(TVI_ROOT, NULL); CString sStatus; if (m_DicomDir.DoesDicomDirExist()) { int iRet = AfxMessageBox("A DICOMDIR file already exists. Do you want to overwrite it?", MB_YESNO | MB_ICONQUESTION); if (iRet == IDNO) { sStatus.Format("Status: Search is complete. %u file(s) were added to the DICOM " \ "Directory.", m_DicomDir.GetAddedDicomFilesCount()); SetDlgItemText(IDC_STATUS, sStatus); return; } } // Save the DICOMDIR file L_UINT16 uRet = m_DicomDir.SaveDicomDir(); if (uRet == DICOM_SUCCESS) { sStatus.Format("Status: Search is complete. %u file(s) were added to the DICOM " \ "Directory. The DICOMDIR file was saved into \"%s\".", m_DicomDir.GetAddedDicomFilesCount(), m_sDicomFilesFolder + "\\DICOMDIR"); SetDlgItemText(IDC_STATUS, sStatus); } else { sStatus.Format("Status: Search is complete. %u file(s) were added to the DICOM " \ "Directory. Failed to save the DICOMDIR file (Error code: %u).", m_DicomDir.GetAddedDicomFilesCount(), uRet); SetDlgItemText(IDC_STATUS, sStatus); } } BOOL CMainDlg::GetFolder(LPCTSTR pszTitle, HWND hWndOwner) { BROWSEINFOA bi; bi.hwndOwner = hWndOwner; bi.pidlRoot = NULL; bi.pszDisplayName = NULL; bi.lpszTitle = pszTitle; bi.ulFlags = BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; bi.lParam = 0; bi.iImage = 0; LPITEMIDLIST pIDL = SHBrowseForFolder(&bi); if (pIDL == NULL) return FALSE; L_CHAR pszDisplayName[MAX_PATH]; if (SHGetPathFromIDList(pIDL, pszDisplayName)) { m_sDicomFilesFolder = pszDisplayName; return TRUE; } return FALSE; } L_VOID CMainDlg::FillTree(HTREEITEM hParentTreeItem, pDICOMELEMENT pParentElement) { pDICOMELEMENT pElement; HTREEITEM hItem; if (pParentElement == NULL) { pElement = m_DicomDir.GetFirstKey(NULL, TRUE); } else { pElement = m_DicomDir.GetChildKey(pParentElement); } while (pElement != NULL) { hItem = m_Tree.InsertItem(m_DicomDir.GetValueKey(pElement), GetTreeItemImage(IDB_STORAGE_COLLAPSED), GetTreeItemImage(IDB_STORAGE_COLLAPSED), hParentTreeItem, TVI_SORT); FillSubTree(hItem, pElement); if (pElement->nLength == ELEMENT_LENGTH_MAX && m_DicomDir.GetChildKey(pElement) != NULL) FillTree(hItem, pElement); pElement = m_DicomDir.GetNextKey(pElement, TRUE); } } L_VOID CMainDlg::FillSubTree(HTREEITEM hParentTreeItem, pDICOMELEMENT pParentElement) { pDICOMTAG pTag; HTREEITEM hItem; CString sElement; pDICOMELEMENT pElement = m_DicomDir.GetChildElement(pParentElement, TRUE); while (pElement != NULL) { pTag = LDicomTag::Find(pElement->nTag); sElement.Format("%04X:%04X - %s", GETGROUP(pElement->nTag), GETELEMENT(pElement->nTag), (pTag != NULL) ? pTag->pszName : "Unknown"); hItem = m_Tree.InsertItem(sElement, GetTreeItemImage(IDB_STREAM), GetTreeItemImage(IDB_STREAM), hParentTreeItem, TVI_SORT); if (hItem) m_Tree.SetItemData(hItem, (DWORD) pElement); pElement = m_DicomDir.GetNextElement(pElement, TRUE, TRUE); } } L_INT CMainDlg::GetTreeItemImage(L_UINT uBitmap) { L_INT iSize = sizeof(m_BitmapList) / sizeof(m_BitmapList[0]); for (L_INT iImageIndex = 0; iImageIndex < iSize; iImageIndex++) if (m_BitmapList[iImageIndex] == uBitmap) break; return iImageIndex; } void CMainDlg::OnSelChangedTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*) pNMHDR; if (pNMTreeView->itemNew.hItem != pNMTreeView->itemOld.hItem) { m_BitmapWindow.SetHandle(NULL); m_BitmapWindow.SetWndHandle(NULL); DisplayElementValue(pNMTreeView->itemNew.hItem); } *pResult = 0; } L_VOID CMainDlg::DisplayElementValue(HTREEITEM hItem) { m_List.DeleteAllItems(); m_List.RedrawWindow(); if (hItem == NULL) return; pDICOMELEMENT pElement = (pDICOMELEMENT) m_Tree.GetItemData(hItem); if (pElement == NULL) return; if (m_DicomDir.ExistsElement(pElement) == FALSE) return; L_UINT32 uValuesCount = m_DicomDir.GetCountValue(pElement); if (uValuesCount == 0) return; L_UINT32 uLength = m_DicomDir.GetConvertValue(pElement, NULL); if (uLength == 0) return; L_CHAR* pszValue = new L_CHAR[uLength]; if (!pszValue) { m_DicomDir.FreeValue(pElement); return; } m_DicomDir.GetConvertValue(pElement, pszValue); m_DicomDir.FreeValue(pElement); L_UINT32 i; L_CHAR* p; L_CHAR* q; for (i = 0, p = pszValue; i < uValuesCount; i++) { if (uValuesCount > 1) { q = strchr(p, '\\'); if (q != NULL) *q = 0; } m_List.InsertItem(p); p += strlen(p) + 1; } delete [] pszValue; m_List.RedrawWindow(); m_List.SelectItem(m_List.GetFirstVisibleItem()); } void CMainDlg::OnItemExpandingTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*) pNMHDR; UINT uBitmap; if ((pNMTreeView->itemNew.state & TVIS_EXPANDED) != TVIS_EXPANDED) { uBitmap = IDB_STORAGE_EXPANDED; } else { uBitmap = IDB_STORAGE_COLLAPSED; } m_Tree.SetItemImage(pNMTreeView->itemNew.hItem, GetTreeItemImage(uBitmap), GetTreeItemImage(uBitmap)); *pResult = 0; } void CMainDlg::OnDblClkTree(NMHDR* pNMHDR, LRESULT* pResult) { CPoint Point; ::GetCursorPos(&Point); m_Tree.ScreenToClient(&Point); L_UINT nIndent = m_Tree.GetIndent(); if (Point.x < (long) nIndent) return; HTREEITEM hItem = m_Tree.HitTest(Point); DisplayImage(hItem); *pResult = 0; } L_VOID CMainDlg::DisplayImage(HTREEITEM hItem) { if (hItem == NULL) return; pDICOMELEMENT pElement = (pDICOMELEMENT) m_Tree.GetItemData(hItem); if (pElement == NULL) return; if (m_DicomDir.ExistsElement(pElement) == FALSE) return; if (pElement->nTag != TAG_REFERENCED_FILE_ID) return; m_List.DeleteAllItems(); m_List.RedrawWindow(); pDICOMELEMENT pKey = m_DicomDir.GetParentElement(pElement); CString sType = m_DicomDir.GetValueKey(pKey); if (sType == "IMAGE") { CString sFile = m_sDicomFilesFolder + "\\"; L_UINT32 uLength = pElement->nLength; if (uLength != 0) { L_CHAR* pszFileID = new L_CHAR[uLength + 1]; if (pszFileID) { if (m_DicomDir.GetBinaryValue(pElement, pszFileID, uLength)) { pszFileID[uLength] = '\0'; sFile += pszFileID; } m_DicomDir.FreeValue(pElement); delete [] pszFileID; } } // Load the Data Set in the file LDicomDS DataSet; if (DataSet.LoadDS((L_CHAR*)(LPCSTR) sFile, DS_LOAD_CLOSE) != DICOM_SUCCESS) { SetDlgItemText(IDC_STATUS, "Status: Failed to load the Data Set."); return; } pElement = DataSet.FindFirstElement(NULL, TAG_PIXEL_DATA, FALSE); if (pElement == NULL) return; BITMAPHANDLE Bitmap; if (DataSet.GetImage(pElement, &Bitmap, sizeof(BITMAPHANDLE), 0, 0, ORDER_RGB, DICOM_GETIMAGE_AUTO_APPLY_MODALITY_LUT | DICOM_GETIMAGE_AUTO_APPLY_VOI_LUT | DICOM_GETIMAGE_ALLOW_RANGE_EXPANSION, NULL, NULL) == DICOM_SUCCESS) { m_BitmapWindow.SetWndHandle(m_List.m_hWnd); m_BitmapWindow.SetPatternBackColor(RGB(0, 0, 0)); m_BitmapWindow.SetHandle(&Bitmap); m_BitmapWindow.SetZoomMode(ZOOM_FIT); } } } // This is a trick, so that when the user presses the "Esc" button, our dialog doesn't get // closed. We do nothing inside OnCancel() and we call CDialog::OnCancel() inside OnClose(). void CMainDlg::OnCancel() { } void CMainDlg::OnClose() { CDialog::OnCancel(); } void CMainDlg::OnOK() { }