|
Perfect! Exactly what I was trying to find.
Thank you very much.
|
|
|
|
|
Hi, In my program (VC++, MFC, MDI ap), I need a function to delete a directory and all it's contained files and sub-directories. I'm currently using "system" to call the DOS program Deltree.exe. However, I'm sure that there should be a pure Windows method to do the same thing that would be much cleaner. Has anyone any suggestions ?
Doug
|
|
|
|
|
Try this:
BOOL DelTree(CString cstrPath)
{
BOOL bRetVal = FALSE;
CString cstrTemp = cstrPath;
CString cstrOldDir;
char buffer[MAX_PATH];
CFileFind cFind;
CString cstrFileName, cstrTempFile;
cstrFileName.Format("%s%s",cstrPath,"\\*.*");
if (cFind.FindFile(cstrFileName))
{
BOOL bFound = TRUE;
while (bFound)
{
bFound = cFind.FindNextFile();
if (cFind.IsDots())
continue;
else
{
cstrTempFile = cFind.GetFilePath();
bRetVal = DeleteFile(cstrTempFile);
if (!bRetVal) break;
}
}
}
cFind.Close();
if (bRetVal)
bRetVal = ::RemoveDirectory(cstrPath);
else
return bRetVal;
}
Jason Henderson start page ; articles
henderson is coming
henderson is an opponent's worst nightmare
* googlism *
|
|
|
|
|
Jason,
Your solution appears correct. However, I'd like to point out a small detail which caught my eye. Your function's signature is BOOL DelTree(CString cstrPath) . Your parameter is a CString value, rather than a constant CString reference, which would be more appropriate: BOOL DelTree(const CString& cstrPath) .
I just wanted to point this out to you and hope that you understand why it's usually much better to pass objects by const reference rather than by value. I realize that the CString class has a copy-on-write scheme which makes passing by value a lot less expensive than it otherwise be. But, passing by const reference is still the most efficient way to pass most objects requiring "by-value" semantics.
Regards,
Alvaro
Well done is better than well said. -- Benjamin Franklin
(I actually prefer medium-well.)
|
|
|
|
|
Thanks.
Actually, I took this code from a COM dll and modified it rather quickly. I really didn't look it over all that well.
Jason Henderson start page ; articles
henderson is coming
henderson is an opponent's worst nightmare
* googlism *
|
|
|
|
|
The only problem I see is that it is not recursive, so it will not work like deltree, deleting all sub-directories and their contents too.
|
|
|
|
|
Hey you're right. Good catch.
It would be easy to modify though.
Jason Henderson start page ; articles
henderson is coming
henderson is an opponent's worst nightmare
* googlism *
|
|
|
|
|
Jason gave you the clean solution. However, here's another one similar to your "system" one, except that it doesn't show the DOS window:
::WinExec("deltree blah", SW_HIDE);
Regards,
Alvaro
Well done is better than well said. -- Benjamin Franklin
(I actually prefer medium-well.)
|
|
|
|
|
But this way (and also the "system" call) relies on "deltree.exe" being present on the system. On my w2k I don't have "deltree.exe" so the app won't work. I think it's better to use Jasons way.
--
karl
|
|
|
|
|
Hi all you guys !!! Many thanks for all your input - I've taken all the points that you've raised, and, as my ap is only for private "consumption" can live with the WinExec solution - I just "hated" droping into a DOS window in the middle of a Windows program but now that I can hide it,I'm happy !!!
Doug
|
|
|
|
|
Hello,
I'm trying to use the API FindFirstFile in a non-MFC DLL using VC++ 6 and I get the following error on compile:
error C2664: 'FindFirstFileW' : cannot convert parameter 1 from 'const char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style
cast or function-style cast
On this line:
HANDLE Finding = FindFirstFile("C:\\*.*", &FindFileData);
Now I can be stupid, but I don't think that a pattern, which is described as an LPCSTR in the MSDN, would ask for an unsigned short*...
Can anybody tell me what I'm doing wrong here?
Thanks,
- Fahr
|
|
|
|
|
any chance you're doing a Unicode build?
-c
I'm not the droid you're looking for.
|
|
|
|
|
That why also my guess.
Have you tried
HANDLE Finding = FindFirstFile(_T("C:\\*.*"), &FindFileData); ?
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Well, that seems to work (could you maybe also explain WHY it works?)
Now I get an error on this:
FString temp = ANSI_TO_TCHAR(FindFileData.cFileName);
it seems to be related, too, the error reads;
error C2664: 'winGetSizeUNICODE' : cannot convert parameter 1 from 'unsigned short [260]' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
a _T() or L() doesn't work here tho :S
- Fahr
|
|
|
|
|
That's fixed, apparently the ANSI_TO_TCHAR was not needed cuz it's already unicode. My bad...
Tho I still don't get why it works like this or not...
- Fahr
|
|
|
|
|
That could very well be, how would I check that? I DID tweak a lot of the compler and linker settings...
How is that related anyways?
- Fahr
|
|
|
|
|
FindFirstFileW is the wide-char version of FindFirstFile. somehow, you've made the compiler think it needs be using this version instead of FindFirstFileA (the single-byte version).
I'm not the droid you're looking for.
|
|
|
|
|
I have a CComboBox in a dialog in my app and have a question about setting the cursor in it. I want it to have the same behavior as the search combo box in the toolbar in VC++. When the user clicks the box to set focus, it should highlight the current word and if they click again, the cursor is positioned at the end of the word. Right now, no matter how many times or where I click the whole word is always highlighted. Thanks!
|
|
|
|
|
The Lady of Shallots wrote:
When the user clicks the box to set focus, it should highlight the current word and if they click again, the cursor is positioned at the end of the word.
Um, isn't this the default action of a CComboBox? I made a quick MFC app and added one and this is how mine acted.
Nick Parker
You see the Standards change. - Fellow co-worker
|
|
|
|
|
Hmmm... maybe it is and I'm messing it up some how because I am overriding some windows messages and setting focus myself in some places, I will look into that. Thanks!
|
|
|
|
|
I want to perform some post-build commands, but I have no idea what the commands are! Is there a listing and explanation of all the commands? Also, how do I get it to execute a batch file, and put the output of it in the Build window (not opening a separate command prompt window)?
Thanks!
|
|
|
|
|
there is no list of commands. you can execute any command, exactly as if you were doing it from the command line. there is a list of symbols you can use in the commands, look in the MSDN for "Macros for Custom Build Commands".
-c
I'm not the droid you're looking for.
|
|
|
|
|
Ok, I've got it to run a batch file. Unfortunately, it runs it in a new command prompt window, and doesn't close the window when it's done. How can I have it close the window, or, better yet, not even open a window?
|
|
|
|
|
Hello world...
I've writed a function
double FindValue(double X, int& prescaler, int& clk_freq) where X is INPUT argument.
prescaler and clk_freq are OUTPUT arguments.
Here is the code:
double FindValue(double X, int& prescaler, int& clk_freq)
{
const MAX_CLOCK = 16;
const double Clock[MAX_CLOCK] = {26., 27., 28., 29., 30., 31., 32., 34., 36., 38., 40., 42., 44., 46., 48., 50. };
double Min[4] = {0}, freq = 0;
int i = 0, j = 0;
for(i = 0; i < 4; i++, j = 0) {
freq = X * pow(2, i);
while( (j+1 < MAX_CLOCK) && (fabs(freq - Clock[j]) >= fabs(freq - Clock[++j])) ) {};
if(j+1 == MAX_CLOCK) {
Min[i] = min( fabs(freq - Clock[j-1]), fabs(freq - Clock[j]) );
} else {
Min[i] = fabs(freq - Clock[j-1]);
}
}
for(j = 1, i = 0; j < 4; j++) {
i = (Min[i] < Min[j]) ? i : j;
}
prescaler = (int)pow(2, i);
j = 0;
freq = X * (double)prescaler;
while( (j+1 < MAX_CLOCK) && (fabs(freq - Clock[j]) >= fabs(freq - Clock[++j])) ) {};
if(j+1 == MAX_CLOCK) {
clk_freq = fabs(freq - Clock[j-1]) < fabs(freq - Clock[j]) ? (int)Clock[j-1] : (int)Clock[j];
} else {
clk_freq = (int)Clock[j-1];
}
return (clk_freq / prescaler);
}
The goal is to find the prescaler (=P) and the frequency (=F) where F/P = X (X is the INPUT wanted).
Values of P are limited to {1, 2, 4, 8} => pow(2, i) with i[0,3]
Values of F are limited to {26, 27, 28, 29, 30, 31, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50}
EXAMPLE:
if I want X = 20 then F must be 40 and P must be 2 because F/P = X
This function work fine with DEBUG mode but the result is different with RELEASE mode???!!!??? very strange...
In RELEASE mode I've found (for X = 20) F = 48 and P = 2... that's wrong
In DEBUG mode I've found (for X = 20) F = 40 and P = 2... that's OK
Thanks in advance for your assistances...
Hello World!!!
from Raphaël
|
|
|
|
|
I didn't trace the exact source of your error, you can do so
by stepping through in the debugger (yes it will work in release
it might behave a little whacky though.)
However, two obvious sources of problems are the two identical lines:
while( (j+1 < MAX_CLOCK) && (fabs(freq - Clock[j]) >= fabs(freq - Clock[++j])) )
This could very well be the source of your problem. You preincrement
j in a line that uses j in other places. C/C++ does not offer any
guarantees as to the order the sub expressions in an expression
are evaluated, and quite often the optimizer reogranizes the evaluation
order for various speed improvements. if "Clock[j]" is evaluated before
"Clock[++j]" you will get a different result than if they are evaluated
in the other order.
The basic style rule is this: never use ++ or -- applied to an lval when
you use the same lval elsewhere in the same expression. A more strict
rule which I personally apply is: never use ++ or -- except as stand alone
statements or in special idiomatic statements (such as *p++ = *q++)
HTH.
|
|
|
|
|