#1
  1. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0

    Help with first MFC program


    Hello all;

    I would like help with creating my first MFC. Many of you have helped me within the last few months and I appreciate all of the time and knowledge that have been given so freely. Let me give you a small insight to my background and then to the subject at hand.

    I am a Computer Science Major, but unfortunately I have only been employed for Visual Basic, Cold Fusion, and such but not C++. During college our C++ was centered on Linux and the DEC Alpha, never Microsoft. I have recently been interested in getting closer to the VC++ that resides in all of us "Computer Nerds". Now when I move to a new place and I want to learn my way around, I get in my car and get lost and then find my way back home. Just call me crazy but that's what I do. Programming is no different for me. When I would like to learn a new language, I figure out a task to solve and then create the product to solve it. During my off time this is what I'm working on now and what many of you have been helping me out with for some time. I have recently finished the first stage and it exceeds my expectations... Thank you all.

    I'm now at the second stage of this project, and here is the global scope. I need to create a program with threads, which I have only done in Java and that was years ago, that will read data in from a text document. This text would give directories strings and attributes of files to watch. This program will take this information and watch these directories for any files to be accessed, I think that hooks would be the best way to do this. Now, as soon as this is triggered the program will just annotate the directory and name of the file that was viewed in another text document which the third stage will handle. That is pretty much all that this program must do. But I also want the program to run from the time that Windows starts until Windows shuts down just as a service runs, and the client must never know that the program is running. I have asked people about this and they informed me that this program might need to be a VC++ MFC program. I have seen code for MFC programs but have never really played with any.

    So I now ask you all to take me to school. Please help me program my first MFC, if this is what I really need for this problem, so that I my be as knowledgeable as you-all are.

    Thanks;
    Eric
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    Sounds like you want to investigate the ReadDirectoryChangesW() function. Check out the documentation for it on MSDN here. Also, there's a sample application showing how to use that function in here. The app watches directories and displays the changes. It appears that this is exactly what you want to do too. Happy hacking! :D
  4. #3
  5. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    As always, thanks man. I'll get back as soon as I hit a wall.

    Eric :)
  6. #4
  7. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    Ok, I'll call Uncle.

    I have tried and tried but cannot get rid of this error:

    error C2065: 'ReadDirectoryChangesW' : undeclared identifier

    Here is what I have done:
    I downloaded the SDK unzipped it and loaded the files into my development directory. Then I started VC++ 6.0 and ran the program. You were right, it really looks exactly like what I was thinking about and it's so small. Well tried to change the .c file but when I ran it, it would not pick up the changes. I then created a new project and copied the .c file to the new .cpp file in this project. I have tried several things but cannot get the program to compile. I thought it was because it needed protocols for the functions but it still came back with the same error. Could it be that I need to include another .h file? I have included the .cpp that I copied and slightly changed to see if I could get to work.

    Any ideas would be appreciated.

    Eric
  8. #5
  9. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    The answer is pretty simple actually. It's in the bottom of the first MSDN link I posted above (the one that documents this function). Quoting directly from the page:

    "To compile an application that uses this function, define the _WIN32_WINNT macro as 0x0400 or later."

    So all you have to do is declare something like :

    #define _WIN32_WINNT 0x0400

    (or 0x0500 if you like, for Windows 2000) somewhere near the top of the file and that should be all that you need to get it to compile! Happy hacking :D
  10. #6
  11. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    :D As always you blow me away, it works fine now. I totally skimmed right over that line in the SDK. Sorry to waist your time.

    I do have one more question. It's nothing really big, just something that I don't quite understand.
    Why do I see these capital L's in the code from Microsoft? Is this some type of casting?

    wprintf( L"Directory %s created\n", p );
    ...
    lstrcat( FilePath, L"\\" );
    ...
    GetPrivateProfileString( L"Files", ... , ... , ...);


    Thanks...

    Eric
  12. #7
  13. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    >> I totally skimmed right over that line in the SDK. Sorry to waist your time.
    You aren't wasting my time at all. Matter of fact, I learned something new as well :D

    >> Why do I see these capital L's in the code from Microsoft? Is this some type of casting?
    Yep, that's to indicate to the compiler that the string constant is composed of unicode characters, instead of single byte characters.

    Hope this helps! :D
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Seattle WA
    Posts
    863
    Rep Power
    14
    Yeah, the L is a macro function. Also look up the _T macro function, which is useful if you're going to be porting your code across ASCII/unicode systems. It assigns the proper type of characters depending on what system the code is being compiled on.
  16. #9
  17. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    So, I noticed that Microsoft uses the L before any directory string. Would this indicate a problem with the compiler interpreting the directory string across the array of Microsoft platforms from 95 to XP?

    Scorpions4ever, you know what I have been working on for the last few months. All I have been dealing with is directory strings. In your professional opinion would it behoove me to incorporate this L into that program also? And if so, would that entail the definition:

    #define _WIN32_WINNT 0x0400

    to be called?

    For anyone else reading, you can read about my previous program problems here.

    Eric
  18. #10
  19. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    Also, do you think that there is a way to watch all the files a directory, and it's sub-directories, or possibly all text files in a directory.

    For example lets take this directory:

    C:\Documents and Settings\Eric\My Documents

    Now I would like to be notified if any file in this directory - or one of it's sub directories is changed.

    Or I might just like to know if only Text files or Doc files are changed.
  20. #11
  21. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    Actually the L is not a macro at all. It's also not specific to Visual C++ either, it's part of the official C++ standard. It's a type specifier to force the string constant type to widechar. For example, if you do this:
    Code:
    wchar_t str1[] = "This is a test";
    wchar_t str2[] = L"This is a test";
    char str3[] = L"This is a test";
    char str4[] = "This is a test";
    When you try compiling the above, you'll get warnings for str1 and str3 because you're initializing them with the wrong types. The L forces the string constant to be a widechar.

    So, this probably brings up the question, what if you're working on an OS that doesn't normally support widechar functions completely (such as Windows 95 or 98). If you use the L to prefix the string, then the code may become unportable to these OSs, when you try to call a function that expects a char string instead of a wchar_t string. To resolve this problem, Microsoft supplies the _T macros. See http://msdn.microsoft.com/library/de...with__MBCS.asp and http://msdn.microsoft.com/library/de...t_Mappings.asp for details. Basically what you can do is something like this:

    _TCHAR str1[] = _T("This is a test");

    Now, if UNICODE is defined, then _TCHAR is replaced by wchar_t and the _T is replaced by an L, so the compiler will see your code as if you typed:
    wchar_t str1[] = L"This is a test";
    which is correct.

    Now, if UNICODE is not defined, then _TCHAR is replaced by char and _T is replaced by nothing, so the compiler will see your code as if you typed:
    char str1[] = "This is a test";
    which is also correct.

    Thus, if you use the _T macros, your code can be portably compiled with or without unicode support.

    As for the API functions themselves, if you have an API function that takes string arguments, say it's called foo(). There are actually two versions of the API function implemented, fooW() and fooA(), which take widechar and char arguments respectively. Depending on whether UNICODE is defined or not, the compiler will pick one of these two versions wherever you call foo() in your code and call the correct version (fooW() or fooA()).

    In general, it's not a good idea to define UNICODE if you intend to use the compiled EXE in a Windows 95/98/Me environment. These OSs have the unicode versions of the functions only implemented as stub functions that return an error when called. See http://msdn.microsoft.com/library/de...limit_5alv.asp for more notes. For any function that accepts string arguments, NT class OSs have both versions implemented correctly, so the code will work correctly whether you have UNICODE defined or not.

    The #define _WIN32_WINNT 0x0400 is only so that the compiler will see the declaration of ReadDirectoryChangesW in the header file. Incidentally the W in the end indicates that this function uses wchar_t type string arguments. There is NO corresponding ReadDirectoryChangesA function implemented and thus this function only works on NT class systems.

    Hope this helps!
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Seattle WA
    Posts
    863
    Rep Power
    14
    You're right of course...I almost went and edited my post when I noticed how the L was used...but...I...got lazy.

    Myself, I got less than a year experience under my belt, and I've only used Visual C++. I never use L, I've trained myself to always use _T() for literals.

    Thanks, that clears it up a bit!
  24. #13
  25. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    Wow, thanks for the breakdown. That explained allot.

    Thanks
    Eric
    :cool:
  26. #14
  27. Some day I will be a Lambda!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    NJ
    Posts
    18
    Rep Power
    0
    :rolleyes: I think this will be a real easy one for someone to answer. Below is a struct from the fwatch demo by Microsoft. I realize that DirInfo is an array of size MAX_DIRS of type DIRECTORY_INFO. But why did MS also place pointers on the struct: *PDIRECTORY_INFO, *LPDIRECTORY_INFO?

    typedef struct _DIRECTORY_INFO {
    HANDLE hDir;
    TCHAR lpszDirName[MAX_PATH];
    CHAR lpBuffer[MAX_BUFFER];
    DWORD dwBufLength;
    OVERLAPPED Overlapped;
    }DIRECTORY_INFO, *PDIRECTORY_INFO, *LPDIRECTORY_INFO;

    TCHAR lpszDirName[MAX_PATH][MAX_BUFFER];
    DIRECTORY_INFO DirInfo[MAX_DIRS];
    TCHAR FileList[MAX_FILES*MAX_PATH];
    DWORD numDirs;

    Thanks... again...

    Eric

    I'm including a zip which contains only fwatch.cpp in case anyone needs to see more code.
  28. #15
  29. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    Microsoft does that for a lot of other structures too. Basically, I think it has something to do with their coding standards. For example, if a function takes a pointer to a DIRECTORY_INFO structure as a param, instead of declaring it like this:
    void foo(DIRECTORY_INFO *lpParam);
    they usually declare it like this:
    void foo(LPDIRECTORY_INFO lpParam);

    Personally, I think they're allergic to using * in their function prototypes, so they use typedefs like LPDIRECTORY_INFO for pointers to structures. But, that's their standard and as long as they stick to it.....

    That's the nice thing about standards, there are so many to choose from :D.

IMN logo majestic logo threadwatch logo seochat tools logo