|
YES! You are the greatest. Thank you so much for all of your help!
|
|
|
|
|
Grr, I keep hitting speed bumps! How would I be able to do file stream from within the app to write the batch file to a directory within the program files? It's saying that access was denied on Vista, it works perfectly fine in XP. I can force the program to run as administrator, but it still doesn't work when trying to do file stream to write to a file.
|
|
|
|
|
Hi,
My current project is to make wrapper classes of legacy mfc codes. I could easily marshal the String^ to CString like this:
bool LoadFile(String^ strPath)
{
// from managed to unmanaged using C++ Interop marshaling
pin_ptr<const wchar_t> pstrPath = PtrToStringChars(strPath);
// unmanaged declaration: bool LoadFile(CString path);
return m_pLegacyClass->LoadFile(pstrPath);
}
But string array is not a simple case. I marshaled all array members then copied the members to unmanaged memory. Here is the code.
bool LoadFiles(array<String^>^ arrayAviFilePath, int nAviFile)
{
// Array to marshal String^
array<IntPtr>^ arrayMarshalString = gcnew array<IntPtr>(nAviFile);
// Initialize unmanaged array
IntPtr arrayUnmanagedString = Marshal::AllocHGlobal(IntPtr::Size * nAviFile);
for (int i = 0; i < nAviFile; i++)
{
// Marshaling String^ to IntPtr
arrayMarshalString[i] = Marshal::StringToHGlobalUni(arrayAviFilePath[i]);
// Write to unmanaged memory
Marshal::WriteIntPtr(arrayUnmanagedString, i * IntPtr::Size, arrayMarshalString[i]);
}
// Use unmanaged array here
CString *pArrayAvi = static_cast<CString *>(arrayUnmanagedString.ToPointer());
bool bReturn = m_pLegacyClass->LoadFiles(pArrayAvi, nAviFile);
// Free unmanaged memory now
for (int i = 0; i < nAviFile; i++)
Marshal::FreeHGlobal(arrayMarshalString[i]);
Marshal::FreeHGlobal(arrayUnmanagedString);
return bReturn;
}
// legacy declaration
bool LoadFiles(CString arrayAviFilePath[], int nAviFile);
It works well anyway but is this best way?
|
|
|
|
|
Oldboy2 wrote: It works well
I don't see how, unless you're just getting lucky.
For example, casting arrayUnmanagedString.ToPointer() to a CString* is not valid.
It seems overly complex to me. Why not just create an array of CStrings and marshal
each System::String to a CString in the array like in your first simple example
(using PtrToStringChars)? There's no need to do all the managed allocation of native
memory - just use the native heap.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: I don't see how, unless you're just getting lucky.
Didn't you get the memo? That's how it's done[^]!
|
|
|
|
|
Thank you for reply. I got a simplest example from googling. I did not even know CString has a constructor that takes a String. That's so simple!
bool LoadFiles(array<String^>^ arrayAviFilePath, int nAviFile)
{
CString *pArrayAvi = new CString[nAviFile];
for (int i = 0; i < nAviFile; i++)
{
pArrayAvi[i] = CString(arrayAviFilePath[i]);
}
bool bReturn = m_pLegacyClass->LoadFiles(pArrayAvi, nAviFile);
delete [] pArrayAvi;
return bReturn;
}
|
|
|
|
|
Oldboy2 wrote: I did not even know CString has a constructor that takes a String.
How could you know when they hide that information in the documentation[^]
|
|
|
|
|
Hey guys, thanks for looking at my questions!
First off, I am making a program that changes words into pig-latin form, here is an explanation of that: If a words starts with a vowel (including y), simply add -way to the end of the word (ex. "alphabet" would be alphabet-way). If a word starts with a consonant, move the section of the word up till the first vowel and put it at the end with "ay" attatched to it (ex. "lame" would be "ame-lay" and glucose would be "ucose-glay")
On to the questions:
I'm having some trouble figuring out how to determine the length of a word to a vowel. An example would be that the length of the word "Chair" up to the first vowel is 2.
Also, I am having trouble using the String::Compare method to determine if a word even starts with a vowel (see code block at the bottom). I believe the syntax is String::Compare(string1, subscript1, string2, subscript2, count) and it returns a value of 0 if string1 is equivalent to string2, please correct me if I am wrong. I used an array containing all of the vowels and used it as string2 and had the word to compare it it to as string1 with the subscripts and count set up accordingly but it does not seem to return a value as I expected.
Ok, I realize this probably made no sense without any code, so here is what I have so far (problem areas bolded):
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
String ^transformy = "";
String ^transformed = "";
String ^beginning = "";
String ^end = "";
array<String ^>^vowels = {"a", "e", "i", "o", "u", "y"};
int VowelOrNot = 0;
int toVowel = 0;
int toEnd = 0;
transformy = Convert::ToString(uIn->Text);
VowelOrNot = String::Compare(transformy, 0, Convert::ToString(vowels), 0, 1);;
if (VowelOrNot == 0)
{
transformed = String::Concat(transformy, "-way");
pOut->Text = Convert::ToString(transformed);
}
else
{
toVowel = Something goes here;
toEnd = Something also goes here;
beginning = transformy->Substring(toVowel, toEnd);
end = String::Concat(transformy->(0, toVowel), "ay");
transformed = String::Concat(String::Concat(begining, "-"), end);
pOut->Text = Convert::ToString(transformed);
}
}
Thank you very much for your time, and any help you can offer!
|
|
|
|
|
TabascoSauce wrote: //Determine if the first letter is a vowel by comaring the first letter
bool startsWithVowel = (Array::IndexOf(vowels, transformy->Substring(0,1), 0) == -1) ? false : true;
if(startsWithVowel)
{
.....
}
TabascoSauce wrote: //Determine how long a word is up to first vowel
transformy->IndexOfAny(vowels); You need to make vowels as array<Char>^
modified on Tuesday, April 21, 2009 5:37 AM
|
|
|
|
|
Thanks N a v a n e e t h!
**Edit
Ok, I got it now! Thanks very much!
modified on Tuesday, April 21, 2009 10:06 PM
|
|
|
|
|
I have a project that I'm working on that generates batch files when a button is clicked. I added a close button that then cleans the subdirectory the batch files are generated in. The only problem I'm experiencing now is that when the user closes the application using the builtin x button in the upper right hand corner, it doesn't execute the code since it calls it's own destructor. Is there any way to have that close feature also clean the subdirectory by removing all the *.bat files?
|
|
|
|
|
Hi,
you might put your exit code in the mainform's FormClosed event handler.
|
|
|
|
|
I created this app using Visual C++, sorry to sound really stupid, but where exactly would I find that? I'm more of a console programmer but recently decided to try and tackle GUIs.
|
|
|
|
|
You know how to add a Button.Click handler? or a TextBox.TextChanged handler?
It is exactly the same for Form.FormClosed: in Visual Designer select the Control, right click for Properties, use Lightning icon to switch to events, double-click the event you want, that adds and opens the handler's method.
|
|
|
|
|
Awesome! That was very helpful! Thank you so much!
|
|
|
|
|
You're welcome.
|
|
|
|
|
I would like to copy the data content of pDataByte to QByte using Microsoft Visual C++ 2008 .NET
Debug Info
Name Value Type
pDataByte {System.Array} System::Object^
[0x0] 0x41 ‘A’ unsigned char
[0x1] 0x42 ‘B’ unsigned char
[0x2] 0x43 ‘C’ unsigned char
[0x3] 0x44 ‘D’ unsigned char
QByte {Length=0x4} unsigned char[]
[0x0] 0x00 ‘’ unsigned char
[0x1] 0x00 ‘’ unsigned char
[0x2] 0x00 ‘’ unsigned char
[0x3] 0x00 ‘’ unsigned char
I have tried several approaches, for example:
<br />
System::Object ^pDataByte;<br />
unsigned char QByte[4];<br />
<br />
ReadOutput(pDataByte);<br />
<br />
<br />
QByte[0] = (unsigned char)System::Convert::ToChar(pDataByte); <br />
Error Code (at runtime at line: QByte[0] = (unsigned char)System...)
An unhandled exception of type 'System.InvalidCastException' occurred in mscorlib.dll
Additional information: Unable to cast object of type 'System.Byte[]' to type 'System.IConvertible'.
Please help, I have tried very hard to get this to work, I am used to plane C++ (not .NET Framework)
|
|
|
|
|
What is the type of the content in pDataByte ? Is that a byte array?
|
|
|
|
|
Yes, unsigned char (8-bit, byte) system array to be more specific, see "Debug Info".
Debug Info
Name Value Type
pDataByte {System.Array} System::Object^
[0x0] 0x41 ‘A’ unsigned char
[0x1] 0x42 ‘B’ unsigned char
[0x2] 0x43 ‘C’ unsigned char
[0x3] 0x44 ‘D’ unsigned char
QByte {Length=0x4} unsigned char[]
[0x0] 0x00 ‘’ unsigned char
[0x1] 0x00 ‘’ unsigned char
[0x2] 0x00 ‘’ unsigned char
[0x3] 0x00 ‘’ unsigned char
|
|
|
|
|
QByte[0] = (unsigned char)System::Convert::ToChar(pDataByte); First you need to get a unsigned char array from the object. Loop through each element and assign it to QByte . Sample code follows,
array<unsigned char>^ uChars = static_cast<array<unsigned char>^>(pDataByte);
for(int i=0; i < uChars->Length; i++)
{
QByte[i] = uChars[i];
} Hope that helps
|
|
|
|
|
Thanks a lot, that´s not enough, thank you, thank you, thank you!
I used your solution together with the solution from Mark Salsbery
array<unsigned char>^ uChars = static_cast<array<unsigned char>^>(pDataByte);
System::Runtime::InteropServices::Marshal::Copy(uChars, 0, System::IntPtr(QByte), 4);
Thank you both extremely much
modified on Monday, April 20, 2009 5:44 AM
|
|
|
|
|
Happy to see it worked
|
|
|
|
|
Of course it worked, three people working as a team should be sufficient to move 4 bytes
|
|
|
|
|
Luc Pattyn wrote: three people working as a team should be sufficient to move 4 bytes
Great! Worth for a new sig.
|
|
|
|
|
Obviously, four people would have been the most efficient team size for this project - one person per byte
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|