|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis is just another OLE Document / Structured Document Viewer. Just to add a little to it, I have added deletion and insertion facilities in it. I developed it coz it was needed for our internal office use. We were working a lot on Structured Storage files and needed a utility to not only view all the details of Storages and Streams within a file but also to be able to edit the file. So, this is the end-product. BackgroundYou must be familiar with structured storage to have a complete grasp over this article. Just to introduce it to those who doesn't know about it, structured storage files are normally said to have a File System within a file. As with a normal file system in which we have folders and files, in a structured storage file, we have Storages and Streams. A storage can have streams as well as storages inside it, but a stream is like a simple binary file. This is a small standalone exe. Now, some people would ask that Microsoft is itself providing an OLE Doc Viewer so what is the need for this. I think I have answered this before. I have added editing facilities which we needed for our office project and that was the only reason to develop it. Plus, I thought that it is something which should be shared. So, accept my apologies if somebody gets annoyed for repetition of work which I think isn't the case. The CodeSince it is always considered best to represent a file system in a tree, so is done here. I have used a tree to show the full file system (so-called) within a storage file. By double-clicking or by selecting "Show Contents" from the right-click menu, you can see the value of the selected stream in the right side pane. Well, coming to the code. I have stored all the Storages within a file in a linked list. There is a structure named Now, using a linked list for a tree caused me some problems especially while deleting, because logically a tree should be stored in a tree but that was again difficult to handle. So, I opted for the first difficult option because I thought I was good at that :-). I know self-praise leads to isolation but sometimes .... Anyway, here are some of the important code snippets: First of all, the structure which is used for the linked list: typedef struct StgPointers { IStorage * pointer; IStorage * parent; CString stgName; StgPointers * next; StgPointers * prev; HTREEITEM hTree; } Pointers; This is the API used for opening a Storage file on the disk. HRESULT hRes = StgOpenStorage(wcFName, NULL, m_dwMode, NULL, 0, &m_pRootStg);
Now, this is the recursive function which is used to populate the tree. bool COLEDOCViewerDlg::PopulateTree(IStorage * pCurrentStorage, HTREEITEM htreeItem) { HTREEITEM hNewItem; if(!m_bRootInserted) { htreeItem = m_treeData.InsertItem(m_strFileName, 3 , 2);m_first->hTree = htreeItem; m_cur = m_prev = m_first; m_bRootInserted = true; } USES_CONVERSION; IEnumSTATSTG * ppenum = NULL; HRESULT hRes = pCurrentStorage->EnumElements(0,NULL, 0, &ppenum); CString addtoList; STATSTG arr[1]; while(hRes != S_FALSE) { hRes = ppenum->Next(1, arr, NULL); addtoList = W2A(arr[0].pwcsName); if(arr[0].type == 1) { hNewItem = m_treeData.InsertItem(addtoList, 3, 2, htreeItem, NULL); WCHAR * stgName = A2W(addtoList); IStorage * pNewStorage = NULL; hRes = pCurrentStorage->OpenStorage(stgName, NULL, m_dwMode, NULL, 0, &pNewStorage); //Adding in Linked List m_prev = m_cur; m_cur = new Pointers;m_cur->prev = m_prev;m_cur->parent = pCurrentStorage;m_cur->pointer = pNewStorage;m_cur->stgName = addtoList;m_cur->hTree = hNewItem;m_cur->next = NULL;m_prev->next = m_cur; //Added PopulateTree(pNewStorage, hNewItem); } if(arr[0].type == 2) { addtoList += " <STREAM>"; m_treeData.InsertItem(addtoList, htreeItem); } } ppenum->Release(); return true; } The contents of a Stream are gotten like this. Here, pStream->Read(readData, noofbytes, NULL);
The logic of One important thing is the mode in which all the objects are opened. These are handled by one variable m_dwMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT
Remaining is quite simple. My ThanksI used a function
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||