How to Print the particular contents in the entire document using DHTML - visual-c++

In these example, I want to print the contents in the ID tab_form_1.While trying these
sample to print the tab_form_1 contents,lpOleCommandTarget become NULL while query interface using CComptr .
How to solve this issue?
SAMMPLE
IHTMLDocument2 *pDoc;
GetDHtmlDocument(&pDoc);
CComPtr<IHTMLElement2> spControl;
if(GetElementInterface(_T("tab_form_1") ,&spControl) != S_OK)
return;
//ole command target
LPOLECOMMANDTARGET lpOleCommandTarget = NULL;
spControl->QueryInterface(IID_IOleCommandTarget,(void**)&lpOleCommandTarget);ASSERT(lpOleCommandTarget);
//lpDispatch->Release();
if(lpOleCommandTarget == NULL) return;
//prepare header
CString header = _T("Project Path: &w");
VARIANT header_variant;
VariantInit(&header_variant);
V_VT(&header_variant) = VT_BSTR;
V_BSTR(&header_variant) = CString(header).AllocSysString();
//prepare footer
CString footer = _T("&d &t&b Page&p of &P");
VARIANT footer_variant;
VariantInit(&footer_variant);
V_VT(&footer_variant) = VT_BSTR;
V_BSTR(&footer_variant) = CString(footer).AllocSysString();
//prepare header footer safe arrray
SAFEARRAYBOUND parameter_array_bound[1];
SAFEARRAY *parameter_array = NULL;
parameter_array_bound[0].cElements = 2;
parameter_array_bound[0].lLbound = 0;
parameter_array = SafeArrayCreate(VT_VARIANT,1,parameter_array_bound);
//HRESULT hr;
long index;
index = 0;
HRESULT hr = SafeArrayPutElement(parameter_array,&index,&header_variant);
index = 1;
hr = SafeArrayPutElement(parameter_array,&index,&footer_variant);
VARIANT parameter;
VariantInit(&parameter);
V_VT(&parameter) = VT_ARRAY | VT_BYREF;
V_ARRAY(&parameter) = parameter_array;
// print contents of web browser control
lpOleCommandTarget->Exec(NULL, OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, &parameter,NULL);
//clear all variants
VariantClear(&header_variant);
VariantClear(&footer_variant);
if (parameter_array != NULL) {
SafeArrayDestroy(parameter_array);
}
lpOleCommandTarget->Release();

Try this sample.This will eradicate your problem.This code will print the particular contents into the newly created document.
// create DHtmlDocument for Newly Created Dialog
HRESULT hDispatch = printdlg->m_pBrowserApp->get_Document((IDispatch**)&pDisp);
if(hDispatch != S_OK) return;
HRESULT hResult = pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pNewDoc);
if(hResult != S_OK) return;
//GetDHtmlDocument for new document
GetDHtmlDocument(&pDoc);
BSTR strSummaryText = GetElementHtml(L"tab_form_1");
// Creates a new one-dimensional array
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (psaStrings == NULL) {
return;
}
VARIANT *param;
HRESULT hresult = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
param->vt = VT_BSTR;
param->bstrVal = strSummaryText;
hresult = SafeArrayUnaccessData(psaStrings);
//it will write the div part of tab_form_1 into new document to pass the summary contents alone to the printer
hresult = pNewDoc->write(psaStrings);
// SafeArrayDestroy calls SysFreeString for each strtemp
if (psaStrings != NULL) {
SafeArrayDestroy(psaStrings);
}

Related

NAudio Mp3 decoding click and pops

I followed this NAudio Demo modified to play ShoutCast.
In my full code I have to resample the incoming audio and stream it again over the network to a network player. Since I get many "clicks and pops", I came back to the demo code and I found that these artifacts are originated after the decoding block.
If I save the incoming stream in mp3 format, it is pretty clear.
When I save the raw decoded data (without other processing than the decoder) I get many audio artifacts.
I wonder whether I am doing some error, even if my code is almost equal to the NAudio demo.
Here the function from the example as modified by me to save the raw data. It is called as a new Thread.
private void StreamMP3(object state)
{
//Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//SettingsSection section = (SettingsSection)config.GetSection("system.net/settings");
this.fullyDownloaded = false;
string url = "http://icestreaming.rai.it/5.mp3";//(string)state;
webRequest = (HttpWebRequest)WebRequest.Create(url);
int metaInt = 0; // blocksize of mp3 data
int framesize = 0;
webRequest.Headers.Clear();
webRequest.Headers.Add("GET", "/ HTTP/1.0");
// needed to receive metadata informations
webRequest.Headers.Add("Icy-MetaData", "1");
webRequest.UserAgent = "WinampMPEG/5.09";
HttpWebResponse resp = null;
try
{
resp = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException e)
{
if (e.Status != WebExceptionStatus.RequestCanceled)
{
ShowError(e.Message);
}
return;
}
byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame
try
{
// read blocksize to find metadata block
metaInt = Convert.ToInt32(resp.GetResponseHeader("icy-metaint"));
}
catch
{
}
IMp3FrameDecompressor decompressor = null;
byteOut = createNewFile(destPath, "salva", "raw");
try
{
using (var responseStream = resp.GetResponseStream())
{
var readFullyStream = new ReadFullyStream(responseStream);
readFullyStream.metaInt = metaInt;
do
{
if (mybufferedWaveProvider != null && mybufferedWaveProvider.BufferLength - mybufferedWaveProvider.BufferedBytes < mybufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4)
{
Debug.WriteLine("Buffer getting full, taking a break");
Thread.Sleep(500);
}
else
{
Mp3Frame frame = null;
try
{
frame = Mp3Frame.LoadFromStream(readFullyStream, true);
if (metaInt > 0)
UpdateSongName(readFullyStream.SongName);
else
UpdateSongName("No Song Info in Stream...");
}
catch (EndOfStreamException)
{
this.fullyDownloaded = true;
// reached the end of the MP3 file / stream
break;
}
catch (WebException)
{
// probably we have aborted download from the GUI thread
break;
}
if (decompressor == null)
{
// don't think these details matter too much - just help ACM select the right codec
// however, the buffered provider doesn't know what sample rate it is working at
// until we have a frame
WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
decompressor = new AcmMp3FrameDecompressor(waveFormat);
this.mybufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);
this.mybufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(200); // allow us to get well ahead of ourselves
framesize = (decompressor.OutputFormat.Channels * decompressor.OutputFormat.SampleRate * (decompressor.OutputFormat.BitsPerSample / 8) * 20) / 1000;
//this.bufferedWaveProvider.BufferedDuration = 250;
}
int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
//Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed));
mybufferedWaveProvider.AddSamples(buffer, 0, decompressed);
while (mybufferedWaveProvider.BufferedDuration.Milliseconds >= 20)
{
byte[] read = new byte[framesize];
mybufferedWaveProvider.Read(read, 0, framesize);
byteOut.Write(read, 0, framesize);
}
}
} while (playbackState != StreamingPlaybackState.Stopped);
Debug.WriteLine("Exiting");
// was doing this in a finally block, but for some reason
// we are hanging on response stream .Dispose so never get there
decompressor.Dispose();
}
}
finally
{
if (decompressor != null)
{
decompressor.Dispose();
}
}
}
OK i found the problem. I included the shoutcast metadata to the MP3Frame.
See the comment "HERE I COLLECT THE BYTES OF THE MP3 FRAME" to locate the correct point to get the MP3 frame with no streaming metadata.
The following code runs without audio artifacts:
private void SHOUTcastReceiverThread()
{
//-*- String server = "http://216.235.80.18:8285/stream";
//String serverPath = "/";
//String destPath = "C:\\temp\\"; // destination path for saved songs
HttpWebRequest request = null; // web request
HttpWebResponse response = null; // web response
int metaInt = 0; // blocksize of mp3 data
int count = 0; // byte counter
int metadataLength = 0; // length of metadata header
string metadataHeader = ""; // metadata header that contains the actual songtitle
string oldMetadataHeader = null; // previous metadata header, to compare with new header and find next song
//CircularQueueStream framestream = new CircularQueueStream(2048);
QueueStream framestream = new QueueStream();
framestream.Position = 0;
bool bNewSong = false;
byte[] buffer = new byte[512]; // receive buffer
byte[] dec_buffer = new byte[decSIZE];
Mp3Frame frame;
IMp3FrameDecompressor decompressor = null;
Stream socketStream = null; // input stream on the web request
// create web request
request = (HttpWebRequest)WebRequest.Create(server);
// clear old request header and build own header to receive ICY-metadata
request.Headers.Clear();
request.Headers.Add("GET", serverPath + " HTTP/1.0");
request.Headers.Add("Icy-MetaData", "1"); // needed to receive metadata informations
request.UserAgent = "WinampMPEG/5.09";
// execute request
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
// read blocksize to find metadata header
metaInt = Convert.ToInt32(response.GetResponseHeader("icy-metaint"));
try
{
// open stream on response
socketStream = response.GetResponseStream();
var readFullyStream = new ReadFullyStream(socketStream);
frame = null;
// rip stream in an endless loop
do
{
if (IsBufferNearlyFull)
{
Debug.WriteLine("Buffer getting full, taking a break");
Thread.Sleep(500);
frame = null;
}
else
{
int bufLen = readFullyStream.Read(buffer, 0, buffer.Length);
try
{
if (framestream.CanRead && framestream.Length > 512)
frame = Mp3Frame.LoadFromStream(framestream);
else
frame = null;
}
catch (Exception ex)
{
frame = null;
}
if (bufLen < 0)
{
Debug.WriteLine("Buffer error 1: exit.");
return;
}
// processing RAW data
for (int i = 0; i < bufLen; i++)
{
// if there is a header, the 'headerLength' would be set to a value != 0. Then we save the header to a string
if (metadataLength != 0)
{
metadataHeader += Convert.ToChar(buffer[i]);
metadataLength--;
if (metadataLength == 0) // all metadata informations were written to the 'metadataHeader' string
{
string fileName = "";
string fileNameRaw = "";
// if songtitle changes, create a new file
if (!metadataHeader.Equals(oldMetadataHeader))
{
// flush and close old byteOut stream
if (byteOut != null)
{
byteOut.Flush();
byteOut.Close();
byteOut = null;
}
if (byteOutRaw != null)
{
byteOutRaw.Flush();
byteOutRaw.Close();
byteOutRaw = null;
}
timeStart = timeEnd;
// extract songtitle from metadata header. Trim was needed, because some stations don't trim the songtitle
//fileName = Regex.Match(metadataHeader, "(StreamTitle=')(.*)(';StreamUrl)").Groups[2].Value.Trim();
fileName = Regex.Match(metadataHeader, "(StreamTitle=')(.*)(';)").Groups[2].Value.Trim();
// write new songtitle to console for information
if (fileName.Length == 0)
fileName = "shoutcast_test";
fileNameRaw = fileName + "_raw";
framestream.reSetPosition();
SongChanged(this, metadataHeader);
bNewSong = true;
// create new file with the songtitle from header and set a stream on this file
timeEnd = DateTime.Now;
if (bWrite_to_file)
{
byteOut = createNewFile(destPath, fileName, "mp3");
byteOutRaw = createNewFile(destPath, fileNameRaw, "raw");
}
timediff = timeEnd - timeStart;
// save new header to 'oldMetadataHeader' string, to compare if there's a new song starting
oldMetadataHeader = metadataHeader;
}
metadataHeader = "";
}
}
else // write mp3 data to file or extract metadata headerlength
{
if (count++ < metaInt) // write bytes to filestream
{
//HERE I COLLECT THE BYTES OF THE MP3 FRAME
framestream.Write(buffer, i, 1);
}
else // get headerlength from lengthbyte and multiply by 16 to get correct headerlength
{
metadataLength = Convert.ToInt32(buffer[i]) * 16;
count = 0;
}
}
}//for
if (bNewSong)
{
decompressor = createDecompressor(frame);
bNewSong = false;
}
if (frame != null && decompressor != null)
{
framedec(decompressor, frame);
}
// fine Processing dati RAW
}//Buffer is not full
SHOUTcastStatusProcess();
} while (playbackState != StreamingPlaybackState.Stopped);
} //try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (byteOut != null)
byteOut.Close();
if (socketStream != null)
socketStream.Close();
if (decompressor != null)
{
decompressor.Dispose();
decompressor = null;
}
if (null != request)
request.Abort();
if (null != framestream)
framestream.Dispose();
if (null != bufferedWaveProvider)
bufferedWaveProvider.ClearBuffer();
//if (null != bufferedWaveProviderOut)
// bufferedWaveProviderOut.ClearBuffer();
if (null != mono16bitFsinStream)
{
mono16bitFsinStream.Close();
mono16bitFsinStream.Dispose();
}
if (null != middleStream2)
{
middleStream2.Close();
middleStream2.Dispose();
}
if (null != resampler)
resampler.Dispose();
}
}
public class QueueStream : MemoryStream
{
long ReadPosition = 0;
long WritePosition = 0;
public QueueStream() : base() { }
public override int Read(byte[] buffer, int offset, int count)
{
Position = ReadPosition;
var temp = base.Read(buffer, offset, count);
ReadPosition = Position;
return temp;
}
public override void Write(byte[] buffer, int offset, int count)
{
Position = WritePosition;
base.Write(buffer, offset, count);
WritePosition = Position;
}
public void reSetPosition()
{
WritePosition = 0;
ReadPosition = 0;
Position = 0;
}
}
private void framedec(IMp3FrameDecompressor decompressor, Mp3Frame frame)
{
int Ndecoded_samples = 0;
byte[] dec_buffer = new byte[decSIZE];
Ndecoded_samples = decompressor.DecompressFrame(frame, dec_buffer, 0);
bufferedWaveProvider.AddSamples(dec_buffer, 0, Ndecoded_samples);
NBufferedSamples += Ndecoded_samples;
brcnt_in.incSamples(Ndecoded_samples);
if (Ndecoded_samples > decSIZE)
{
Debug.WriteLine(String.Format("Too many samples {0}", Ndecoded_samples));
}
if (byteOut != null)
byteOut.Write(frame.RawData, 0, frame.RawData.Length);
if (byteOutRaw != null) // as long as we don't have a songtitle, we don't open a new file and don't write any bytes
byteOutRaw.Write(dec_buffer, 0, Ndecoded_samples);
frame = null;
}
private IMp3FrameDecompressor createDecompressor(Mp3Frame frame)
{
IMp3FrameDecompressor dec = null;
if (frame != null)
{
// don't think these details matter too much - just help ACM select the right codec
// however, the buffered provider doesn't know what sample rate it is working at
// until we have a frame
WaveFormat srcwaveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
dec = new AcmMp3FrameDecompressor(srcwaveFormat);
bufferedWaveProvider = new BufferedWaveProvider(dec.OutputFormat);// decompressor.OutputFormat
bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(400); // allow us to get well ahead of ourselves
// ------------------------------------------------
//Create an intermediate format with same sampling rate, 16 bit, mono
middlewavformat = new WaveFormat(dec.OutputFormat.SampleRate, 16, 1);
outwavFormat = new WaveFormat(Fs_out, 16, 1);
// wave16ToFloat = new Wave16ToFloatProvider(provider); // I have tried with and without this converter.
wpws = new WaveProviderToWaveStream(bufferedWaveProvider);
//Check middlewavformat.Encoding == WaveFormatEncoding.Pcm;
mono16bitFsinStream = new WaveFormatConversionStream(middlewavformat, wpws);
middleStream2 = new BlockAlignReductionStream(mono16bitFsinStream);
resampler = new MediaFoundationResampler(middleStream2, outwavFormat);
}
return dec;
}

MVC Linq throws intermittent null reference exception during export to Excel

I'm using the same code in 6 Areas, each a separate database. Been working fine for a long time, now fails in 3 of the 6 with a null reference exception. Classes all the same, all database tables hold data. First method is the view which displays the data, second called by a link in the view to export the data to Excel. 3 cases display and export correctly. In 2 out of the other 3 cases the data is displayed correctly in the view, and the null exception is thrown at the point the data should be being retrieved in the export method. In the last case the null exception is thrown when trying to return the view. Simply can't understand how it works in some instances but not in others.
public ActionResult PVS(string studySite, string currentFilter, int? page)
{
ViewBag.SelectedID = studySite;
if (studySite != null)
page = 1;
else
studySite = currentFilter;
ViewBag.CurrentFilter = studySite;
IQueryable<PVS> schedule = db.PVS.OrderBy(v => v.SiteNumber).ThenBy(v => v.Participant);
if (studySite != null)
{
string selectedID = studySite;
images = schedule.Where(v => v.SiteNumber == selectedID);
}
int pageSize = 10;
int pageNumber = (page ?? 1);
return View(schedule.ToPagedList(pageNumber, pageSize));
}
public void ExportPVSToExcel()
{
var grid = new System.Web.UI.WebControls.GridView();
var pvs = db.PVS.OrderBy(p => p.SiteNumber).ThenBy(p => p.Participant).ToList();
grid.DataSource = pvs;
grid.DataBind();
// create an Excel worksheet for the data export
ExcelPackage excel = new ExcelPackage();
var workSheet = excel.Workbook.Worksheets.Add("PVS");
var totalCols = grid.Rows[0].Cells.Count;
var totalRows = grid.Rows.Count;
var headerRow = grid.HeaderRow;
for (var i = 1; i <= totalCols; i++)
{
workSheet.Cells[1, i].Value = headerRow.Cells[i - 1].Text;
}
for (var j = 1; j <= totalRows; j++)
{
for (var i = 1; i <= totalCols; i++)
{
var data = pvs.ElementAt(j - 1);
workSheet.Cells[j + 1, i].Value = data.GetType().GetProperty(headerRow.Cells[i - 1].Text).GetValue(data, null);
}
}
using (var memoryStream = new MemoryStream())
{
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=PVS.xlsx");
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}

Retrieving doc templates in MFC

I am using MFC MDI application and i am adding two doc templates as shown in code below:
BOOL CEmuDiagnosticsClientApp::InitInstance()
{
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
//Added new code
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_STRING_FILTERWINDOW,
RUNTIME_CLASS(CEmuDiagnosticsClientDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CFilterWindow));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
AddDocTemplate(new CMultiDocTemplate(IDR_STRING_SIGNALWINDOW,
RUNTIME_CLASS(CEmuDiagnosticsClientDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CSignalWindow)));
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
{
delete pMainFrame;
return FALSE;
}
m_pMainWnd = pMainFrame;
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The main window has been initialized, so show and update it
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
I am using this code to iterate over documents and get view classes's reference in my CMainFrame class.
CFilterWindow* p = NULL;
CSignalWindow* p1 = NULL;
for( POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition(); pos != NULL; )
{
CDocTemplate* pTempl = AfxGetApp()->GetNextDocTemplate( pos );
for( POSITION pos1 = pTempl->GetFirstDocPosition(); pos!= NULL; )
{
CDocument* pDoc = pTempl->GetNextDoc( pos1 );
for( POSITION pos2 = pDoc->GetFirstViewPosition(); pos2 != NULL; )
{
CView* pView = pDoc->GetNextView( pos2 );
if( pView->IsKindOf( RUNTIME_CLASS(CFilterWindow) ) )
{
p = (CFilterWindow*)pView;
p->UpdateUI();
// Do what you need with the view...
}
else
{
p1 = (CSignalWindow*)pView;
p1->UpdateUI();
}
}
}
}
Problem is with loop for( POSITION pos2 = pDoc->GetFirstViewPosition(); pos2 != NULL; )
as pDoc->GetFirstViewPosition(); always returning NULL.
It is puzzling me why it is returning NULL.
Can anybody suggest where I am wrong?

how to differentiate a Folder Type(Windows/FTP) in MFC(VC++)?

how to differentiate a Folder Type(Windows/FTP) in MFC(VC++)?
In my case I have a MFC Treeview in which i am adding list of folders coming from server , that folders are Windows and CIFS .Now i want to differentiate internally what type of folder are they because i select some folder and say connect then it brings up login page where i need to login credentials details , but before that i need to differentiate what type of folder is that ?
Any treeview property like setting and geeting key or any other approach.
Thanks in Advance.
I get folder list from server in this format volume1/Folder1,volume2/Folder2||Folder3,Folder4 in this below method i am removing "||" and maintaining them in two differnt variables: strDataFolder contains - FTP Folders and
strNASfolders conatins CIFS folder , then one more method i am using UpdateFolder. If it is FTP then directly Add but if it CIFS check for duplication if that folder is already there dont add it again to treeview.
Now iam not able to get it how to differentiate what type of folder are they ?
void CNDSClientDlg::UpdateSharedFolder(CString strNASfolders,HTREEITEM hChildItem)
{
CString strDataFolder = "";
CString strData = "";
int iPos = 0;
int fPosition = 0;
fPosition = strNASfolders.Find("||");
if(fPosition != -1)
{
strDataFolder = strNASfolders.Mid(0,fPosition);
strNASfolders = strNASfolders.Right(strNASfolders.GetLength()-(fPosition+2));
}
else
{
strDataFolder = strNASfolders;
}
if (strDataFolder != "" )
{
UpdateFolders(strDataFolder,hChildItem,false);
}
if (strNASfolders != "" ) //don't add if already exist
{
UpdateFolders(strNASfolders,hChildItem,true);
}
}
void CNDSClientDlg::UpdateFolders(CString strFolderType,HTREEITEM hChildItem,bool bCheck)
{
int iPos = 0 ;
CString strData = "";
CString strCurrFolder ="";
HTREEITEM HShareFolder = NULL;
bool bFound = false ;
while (iPos != -1)
{
iPos = strFolderType.Find(",");
if (iPos != -1)
{
strData = strFolderType.Mid(0,iPos);//get the folder details
}
else
{
strData = strFolderType;//get the last folder details
}
strFolderType = strFolderType.Right(strFolderType.GetLength()-(iPos+1)); //get remaining data
int fPos = strData.ReverseFind('/');
if (fPos != -1)
{
strCurrFolder = strData.Mid(fPos+1,strData.GetLength()); // get required data
}
else
{
strCurrFolder = strData; //else assign all the data
}
if(bCheck == true)
{
bFound = false ;
HTREEITEM hTempItem = NULL;
CString strItemText = "" ;
hTempItem = m_pTreeview->GetChildItem(hChildItem);
strItemText = m_pTreeview->GetItemText(hTempItem);
while(hTempItem != NULL)
{
if(strItemText != strCurrFolder)
{
strItemText = m_pTreeview->GetItemText(hTempItem);
hTempItem = m_pTreeview->GetNextSiblingItem(hTempItem);
}
else
{
bFound = true;
break;
}
}
}
if(bCheck == false || bFound == false)
{
HShareFolder = m_pTreeview->InsertItem(strCurrFolder,hChildItem);
m_pTreeview->SetItemImage(HShareFolder,2,2);
TTipItemData* pToolTipData ;
pToolTipData = new TTipItemData;
pToolTipData->strTool = strData ;
m_pTreeview->SetItemData(HShareFolder,DWORD(pToolTipData));
}
m_pTreeview->Expand(hParentItem,TVE_EXPAND);
m_pTreeview->EnsureVisible(hParentItem);
}
}
Items in treeviews can have arbitrary data associated with them. Check out:
http://msdn.microsoft.com/en-us/library/ettyybhw(VS.80).aspx
The InsertItem method shown here has an LPARAM parameter. This is for your use, and you can set this to some value that is meaningful to your application.
(EDIT: Alternatively, use one of the least convoluted overloads to insert your item and use CTreeCtrl::SetItemData on the handle that is returned afterwards).
To find out what value is associated with your item, use CTreeCtrl::GetItemData.
Minor Example:
HTREEITEM hItem = m_ctrlTree.InsertItem("My Item", TVI_ROOT);
HTREEITEM hOther = m_ctrlTree.InsertItem("Child Item", hItem);
m_ctrlTree.SetItemData(hItem, static_cast<DWORD_PTR>(10)); // set LPARAM to 10
// note, you can also store pointers! This assumes pObj is some kind of instance
// of a class.
m_ctrlTree.SetItemData(hOther, static_cast<DWORD_PTR>(pObj));
// at a later point:
int myVal = static_cast<int>(m_ctrlTree.GetItemData(hItem));
MyObject* pObj = static_cast<MyObject*>(m_ctrlTree.GetItemData(hOther));

Problem with SafeArray access using CComVariant

I have following block of code
/////////////////////////////////////
CComVariant newVal;
//pass the CComVariant and get the strings array!!!
GetStrList(newVal);
USES_CONVERSION;
if (((newVal.vt & VT_ARRAY) == VT_ARRAY) && ((newVal.vt & VT_BSTR) == VT_BSTR))
{
SAFEARRAY* paArray = newVal.parray;
BSTR * str = NULL;
SafeArrayAccessData(paArray, (void**)&str);
SafeArrayUnaccessData(paArray);
long lLBound = 0;
long lUBound = 0;
long nCount = 0;
if (FAILED(SafeArrayGetLBound(paArray, 1, &lLBound)) ||
FAILED(SafeArrayGetUBound(paArray, 1, &lUBound)))
{
ASSERT(false);
return FALSE;
}
nCount = ( lUBound - lLBound + 1 );
for (int i = 0 ; i < nCount ; i++)
{
m_cstrList.AddString(W2T(str[i]));
}
//SafeArrayDestroy(paArray); ---> is it required here???
}
/////////////////////////////////////
method returing the safe arrays
HRESULT GetStrList(VARIANT *pVal)
{
USES_CONVERSION;
if (!pVal)
return E_FAIL;
SAFEARRAYBOUND bound[1]; //single dimension array
bound[0].lLbound = 0;
bound[0].cElements = 10;
SAFEARRAY * A = SafeArrayCreate(VT_BSTR, 1, bound);
BSTR * str = NULL;
SafeArrayAccessData(A, (void**)&str);
//user wants the NT view OPC drivers list.
for (int i=0;i<10;i++)
{
str[i] = SysAllocString(T2W(mystrings[i]));
}
VariantInit(pVal);
pVal->vt = VT_ARRAY | VT_BSTR;
pVal->parray = A;
SafeArrayUnaccessData(A);
A = NULL;
return S_OK;
}
My doubt is, above first block of code has any memory leaks?
Does the CComVariant itself handle every thing about the cleaning?
or do i also manually do SafeArrayDestroy(paArray);
Thanks in Advance!
CComVariant destructor calls VariantClear() which frees whatever the variant was incapsulating, arrays included.
One caveat: the array should not be locked at the time when VariantClear() is called. This means that if an exception is thrown after SafeArrayAccessData() but before SafeArrayUnaccessData() the latter will not be called and VariantClear() will not free resources.
Therefore you better write a bracket class for pairing SafeArrayAccessData() and SafeArrayUnaccessData() calls.

Resources