VS_VERSION_INFO static ctrl

  • Follow


I'm trying to figure the best way to set and track my MFC app version.
The issue is I see that the AppWizard upon project creation puts
version 1.0 in a static text in the class CAboutDlg : public CDialog.
I can manually edit this but it would seem there would be either
a way to access the value from code in MyDoc Class, or at least set
this value from code so that I don't have to manually edit said static text
to match whatever version I am implementing in my code or
schema. Appreciate any input on the best way to do the above or
how you implement your version data.



0
Reply RB 6/12/2010 3:01:16 AM

I consider the Microsoft About box one of the single worst pieces of code generated by the
framework, and it proves once again that software *evolves* (there is no trace of
Intelligent Design anywhere!)

What you have to do is use the version APIs to get the version number of the current
executable (GetModuleFileName), then format it yourself in the OnInitInstance handler of
the About dialog (had there been any trace of Intelligent Design (a) this would have
already been done for you and (b) the About box would be in a separate pair of files
About.cpp and About.h, and we could then write once and replug an intelligently-designed
Abput box in)

The About box is the result of some summer intern being allowed to do design.  No one who
cared about software could possibly have come up with a design as bad as the one we have
now for the About box.

You can download the About box code that Brent Rector wrote if you go to
www.flounder.com/downloads and download the code for our book.  I did some minor
enhancements, but the code is over ten years old and doesn't cover modern CPUs.  I should
rewrite it to use the CPUID instruction instead of the sort-of-kludge it uses.  But
Brent's code will nicely substitute values from the VERSIONINFO resource into the static
controls (you preload the static control with the VERSIONINFO keyword you want to use!)

But Brent is an Intelligent Designer.  Too bad something this simple couldn't have been
produced by the framework.
				joe
 
On Fri, 11 Jun 2010 23:01:16 -0400, "RB" <NoMail@NoSpam> wrote:

>
>I'm trying to figure the best way to set and track my MFC app version.
>The issue is I see that the AppWizard upon project creation puts
>version 1.0 in a static text in the class CAboutDlg : public CDialog.
>I can manually edit this but it would seem there would be either
>a way to access the value from code in MyDoc Class, or at least set
>this value from code so that I don't have to manually edit said static text
>to match whatever version I am implementing in my code or
>schema. Appreciate any input on the best way to do the above or
>how you implement your version data.
>
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/12/2010 3:27:55 AM



"RB" <NoMail@NoSpam> wrote in message 
news:#dg$MudCLHA.4604@TK2MSFTNGP05.phx.gbl...

> I'm trying to figure the best way to set and track my MFC app version.
> The issue is I see that the AppWizard upon project creation puts
> version 1.0 in a static text in the class CAboutDlg : public CDialog.
> I can manually edit this but it would seem there would be either
> a way to access the value from code in MyDoc Class, or at least set
> this value from code so that I don't have to manually edit said static 
> text
> to match whatever version I am implementing in my code or
> schema. Appreciate any input on the best way to do the above or
> how you implement your version data.

 Let me suggest an alternative to extracting the version number with the 
Version APIs as Joe suggests.

I have a couple of EXE's and a few DLL's, and when I build them, I want them 
all to get matching version numbers.

So I put the versioninfo in the .rc2 file (to stop appstudio from buggering 
it about) and use #defined constants (VERMAJ, VERMIN, VERFIX, BUILDNUMBER) 
from an included header file (see below).

This means that I can change the version number of all my modules very 
easily, and I can also get the version number by including the header file 
in .cpp files.

Dave
-- 
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm

//==================================

VS_VERSION_INFO VERSIONINFO
 FILEVERSION VERMAJ,VERMIN,VERFIX,BUILDNUMBER
 PRODUCTVERSION VERMAJ,VERMIN,VERFIX,BUILDNUMBER
.....
            VALUE "FileVersion",		VERSIONSTRING
            VALUE "ProductVersion",	PRODUCTSTRING
.....


//==================================
The included header file contains:

// Stringisation.
// (Two steps needed).

#define _STR(x)  #x
#define  STR(x)  _STR(x)

// The following are used as defined quantities
// in the versioninfo resource:

#define VERMAJ               1
#define VERMIN               0
#define VERFIX	       0
#define BUILDNUMBER     0

#define VERMAJSTR	   STR( VERMAJ )
#define VERMINSTR	   STR( VERMIN )
#define VERFIXSTR	  STR( VERFIX )
#define BUILDSTR        STR( BUILDNUMBER )#define VERSIONSTRING	VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR
#define PRODUCTSTRING	VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR


//==================================

 

0
Reply David 6/12/2010 7:48:17 AM

David Webber wrote:
> Let me suggest an alternative to extracting the version number with the
> Version APIs as Joe suggests.
>
> I have a couple of EXE's and a few DLL's, and when I build them, I want
> them all to get matching version numbers.
>
> So I put the versioninfo in the .rc2 file (to stop appstudio from
> buggering it about) and use #defined constants (VERMAJ, VERMIN, VERFIX,
> BUILDNUMBER) from an included header file (see below).

Clever. Why didn't I think of this?

-- 
David Wilkinson
Visual C++ MVP
0
Reply David 6/12/2010 9:47:55 AM

Thanks Joe. 


0
Reply RB 6/12/2010 11:47:56 AM

Thanks David I will try this. 


0
Reply RB 6/12/2010 11:49:50 AM

> So I put the versioninfo in the .rc2 file (to stop appstudio from buggering  it about)

Hi again David, I kinda dumb on rc files. I understand what you are
doing in the header file, but I need a little help on the rc context.
First off do I delete the data that is in my original (ResourceView) rc file?

And then I am confused as to what I actually put in the rc2 file ?

>VS_VERSION_INFO VERSIONINFO
> FILEVERSION VERMAJ,VERMIN,VERFIX,BUILDNUMBER
> PRODUCTVERSION VERMAJ,VERMIN,VERFIX,BUILDNUMBER
>....
>            VALUE "FileVersion",  VERSIONSTRING
>            VALUE "ProductVersion", PRODUCTSTRING
>....


0
Reply RB 6/12/2010 1:17:03 PM

Ok been reading and experimenting and I am beginning to see some of
what you meant.  I have the below done. First I cut this out of my old
rc file (by opening it up in Notepad) and then pasted it into the rc2 file

/////////in my rc2 file///////////////////////////////////
// Add manually edited resources here...
#include "AppVer.h"

#ifndef _MAC
VS_VERSION_INFO VERSIONINFO
//----- used to be FILEVERSION   1,0,0,1 -----//
 FILEVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER  // edited
 PRODUCTVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L

#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "CompanyName", "\0"
            VALUE "FileDescription", "FileHandling MFC Application\0"
            VALUE "FileVersion", VERSIONSTRING"\0"   // edited
            VALUE "InternalName", "FileHandling\0"
            VALUE "LegalCopyright", "Copyright (C) 2010\0"
            VALUE "LegalTrademarks", "\0"
            VALUE "OriginalFilename", "FileHandling.EXE\0"
            VALUE "ProductName", "FileHandling Application\0"
            VALUE "ProductVersion", VERSIONSTRING"\0"   // edited
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END
#endif    // !_MAC
//////////==== then I put this in my AppVer.h file =============//

#define _STR(x)  #x
#define  STR(x)  _STR(x)

#define VERMAJ      1
#define VERMIN      0
#define VERFIX       0
#define BUILDNUMBER   1

#define VERMAJSTR   STR( VERMAJ )
#define VERMINSTR   STR( VERMIN )
#define VERFIXSTR   STR( VERFIX )
#define BUILDSTR    STR( BUILDNUMBER )
#define VERSIONSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR
#define PRODUCTSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR
// =====However I guess now I have to set the window text in the Static
// control to get all of this to show up 


0
Reply RB 6/12/2010 5:07:26 PM

From: "RB" <NoMail@NoSpam>

> Ok been reading and experimenting and I am beginning to see some of
> what you meant.  I have the below done. First I cut this out of my old
> rc file (by opening it up in Notepad) and then pasted it into the rc2 file

That's the idea: but you can also do it in Visual Studio by right clicking 
in the rc2 file in the "solution view" and choosing "Open with ..." to open 
the file in a normal editing window.

(But be careful editing standard .rc files like that as it is possible to do 
things APPSTUDIO doesn't like.)

> /////////in my rc2 file///////////////////////////////////
>....

That's the general idea.

 // =====However I guess now I have to set the window text in the Static
> // control to get all of this to show up

Exactly.   Something like:

CString s;
s.Format(  _T("This is my program version %d.%d.%d.%d"), VERMAJ, VERMIN, 
VERFIX, BUILDNUMBER );
m_wnd.SetWindowText( s );

Dave
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm 

0
Reply David 6/12/2010 10:22:36 PM

Yea, I was using another format function but having problems with an
assertion, so I tried your CString method. But I am still getting the
assertion, I must not be calling it correctly.  I first tried it in the
dialog constructor, and got the assertion.
  So then I tried it in the handler that calls the dialog, but got
the same assertion. I am foo barring somewhere.
Code below.

//// CAboutDlg dialog used for App About
//
class CAboutDlg : public CDialog
{
public:
 CAboutDlg();
// Dialog Data
 //{{AFX_DATA(CAboutDlg)
 enum { IDD = IDD_ABOUTBOX };
 CStatic m_CtrlStaticCr;
 CStatic m_CtrlStaticVer;
 //}}AFX_DATA
//............
}

//// DDX Stuff
//
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CAboutDlg)
   DDX_Control(pDX, IDC_STATICcr, m_CtrlStaticCr);
   DDX_Control(pDX, IDC_STATICver, m_CtrlStaticVer);
   //}}AFX_DATA_MAP
}

//// handler that runs the dialog
//
void CFileHandlingApp::OnAppAbout()
{
  CAboutDlg aboutDlg;
  CString s;
  s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
  aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion Failed
  aboutDlg.DoModal();
}


0
Reply RB 6/13/2010 1:47:05 PM

On 13/06/2010 15:47, RB wrote:

> void CFileHandlingApp::OnAppAbout()
> {
>    CAboutDlg aboutDlg;
>    CString s;
>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion Failed
>    aboutDlg.DoModal();

You may want to add a method to your CAboutDlg class like 
SetVersionString(LPCTSTR pszVersion) and a data member of type CString 
(e.g. CString m_strVersion).
This new method should set the version string, storing it into the 
proper data member.

Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText() 
it in the proper static control.

e.g.:

class CAboutDlg
{
    ...
public:
    void SetVersionString(LPCTSTR pszVersion)
    {
        m_strVersion = pszVersion;
    }

....

private:
    CString m_strVersion;
};

In CAboudDlg::OnInitDialog() do:

   m_CtrlStaticVer.SetWindowText(m_strVersion);


Giovanni
0
Reply Giovanni 6/13/2010 5:48:26 PM


"RB" <NoMail@NoSpam> wrote in message 
news:u1Z9q7vCLHA.4388@TK2MSFTNGP04.phx.gbl...

> Yea, I was using another format function but having problems with an
> assertion, so I tried your CString method. But I am still getting the
> assertion, I must not be calling it correctly.  I first tried it in the
> dialog constructor, and got the assertion.
>  So then I tried it in the handler that calls the dialog, but got
> the same assertion. I am foo barring somewhere.

In MFC there are two concepts: the Window with its HWND (looked after by 
Windows), and the class (derived from CWnd, in this case CDialog) which 
wraps the Window (looked after by MFC).

When you construct your class, it is not attached to a Window, so it doesn't 
know about the controls, which are yet to become Windows.   So you can't 
touch them.

When you invoke DoModal() the window is attached to the class, and it gives 
you a chance to initialise anything you need when it calls OnInitDialog(). 
That is where you can set the text in static controls.

Looked at from outside from an object oriented programming point of view, 
this structure is a complete mess.   But when MFC was invented I don't think 
anyone at Microsoft had heard of object oriented programming.  (Otherwise 
why do you have to create the view of the document before you create the 
document?)    From the point of view of creating a thin wrapper round the 
Windows API, it makes more sense.  And in those days people who knew the 
Windows API could learn MFC quite quickly, just because it was a thin 
wrapper.   But nowadays who writes programs in C using the Windows API?

[I suppose .NET was a bid to escape the historical quirks of MFC, but those 
of us with lots of legacy MFC code we're still developing have grown to know 
and, well not exactly love but coexist with, the vagaries of MFC's 
structure.]

Dave

-- 
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm

 

0
Reply David 6/13/2010 6:22:36 PM

Thanks Giovanni, worked like a charm, though I changed the
SetVersionString function to no args.  I have a couple of
questions if you would be so kind. See code and comments
below. Questions are at very bottom in the OnInitDialog.

#include .....others.....
#include "AppVer.h"  // has version string data thanks
                                // to David Webber

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
 {
   private:
    CString m_strVersion;
   public:
    void SetVersionString( );
    CAboutDlg( );

// Dialog Data
//{{AFX_DATA(CAboutDlg)
  enum { IDD = IDD_ABOUTBOX };
  CStatic m_CtrlStaticCr;
  CStatic m_CtrlStaticVer;
 //}}AFX_DATA

 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CAboutDlg)
  protected:
  virtual void DoDataExchange(CDataExchange* pDX);
 //}}AFX_VIRTUAL

// Implementation
 protected:     /// ** used the class wizard to add suggested
                                             //  OnInitDialog handler ** //
 //{{AFX_MSG(CAboutDlg)
  virtual BOOL OnInitDialog( );
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP( )
};
      /// ** suggested SetVersion function, but no args ** //
void CAboutDlg::SetVersionString( )
 {
   m_strVersion.Format(  _T(" version %d.%d.%d.%d"),
     VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
 }

----constructor, nothing happening here

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CAboutDlg)
 DDX_Control(pDX, IDC_STATICcr, m_CtrlStaticCr);
 DDX_Control(pDX, IDC_STATICver, m_CtrlStaticVer);
 //}}AFX_DATA_MAP
}

...........message map stuff ..........
.............

//// handler that runs the dialog
//
void CFileHandlingApp::OnAppAbout( )
 {
   CAboutDlg aboutDlg;
   aboutDlg.DoModal( );
 }

/////////////////////////////////////////////////////////////////////////////
// CFileHandlingApp message handlers

BOOL CAboutDlg::OnInitDialog( )
 {    //** Class Wizard added  base call ** //
   CDialog::OnInitDialog( );

//** being added code //
   SetVersionString( );   // format the CString
   HWND hDlg = m_CtrlStaticVer.GetSafeHwnd( );

//** Question 1.
//** here I used the API SetWindowText to get a return, the
//     MFC SetWindowText was a void return, Is this a big deal ?

   BOOL bResult = ::SetWindowText(hDlg, m_strVersion);

//**Question 2
//** Class Wizard put below return in ? when I had planned to return the
//** the result of the SetWindow,  Can you explain what this is all about ?

   return TRUE;  // return TRUE unless you set the focus to a control
               // EXCEPTION: OCX Property Pages should return FALSE
}


0
Reply RB 6/13/2010 7:34:48 PM

>When you invoke DoModal( ) the window is attached to the class, and it gives you a chance to initialise anything you need when it 
>calls OnInitDialog(). That is where you can set the text in static controls.

  You know I had a gut feeling that it was the window was not yet
created or something like that, but I am just too inexperienced to
know what to do about it. Giovanni also suggested to me the
OnInitDialog and a SetString function that worked out great.
It would seem to me that MFC would have generated an empty
OnInitDialog handler from the start to give a hint to clueless newbs
like me, but I guess that might be asking too much. However I do
see other functions created just as said with //TODO: comments//
in the Doc/View structure.
   In any case THANKS to you for all of this, it has solved my
version dilemma in a functional way that I am very pleased with.
RB



0
Reply RB 6/13/2010 7:58:28 PM

Serious error: see below...
On Sun, 13 Jun 2010 09:47:05 -0400, "RB" <NoMail@NoSpam> wrote:

>
>Yea, I was using another format function but having problems with an
>assertion, so I tried your CString method. But I am still getting the
>assertion, I must not be calling it correctly.  I first tried it in the
>dialog constructor, and got the assertion.
>  So then I tried it in the handler that calls the dialog, but got
>the same assertion. I am foo barring somewhere.
>Code below.
>
>//// CAboutDlg dialog used for App About
>//
>class CAboutDlg : public CDialog
>{
>public:
> CAboutDlg();
>// Dialog Data
> //{{AFX_DATA(CAboutDlg)
> enum { IDD = IDD_ABOUTBOX };
> CStatic m_CtrlStaticCr;
> CStatic m_CtrlStaticVer;
> //}}AFX_DATA
>//............
>}
>
>//// DDX Stuff
>//
>void CAboutDlg::DoDataExchange(CDataExchange* pDX)
>{
>   CDialog::DoDataExchange(pDX);
>   //{{AFX_DATA_MAP(CAboutDlg)
>   DDX_Control(pDX, IDC_STATICcr, m_CtrlStaticCr);
>   DDX_Control(pDX, IDC_STATICver, m_CtrlStaticVer);
>   //}}AFX_DATA_MAP
>}
>
>//// handler that runs the dialog
>//
>void CFileHandlingApp::OnAppAbout()
>{
>  CAboutDlg aboutDlg;
>  CString s;
>  s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
>  aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion Failed
****
This is incorrect code.  You must put this in the OnInitDialog handler of the dialog.  

The assertion failure, if you looked at it, said the window does not exist.  Big surprise.
The window does not exist!  In fact, the window does not exist until the OnInitDialog
handler is invoked in the context of the dialog.

As a general rule, you should NEVER touch a control variable of a dialog from outside the
dialog.  In fact, it is a serious design error in the MFC framework that defaults control
variables to public and declares handlers as public methods.  This design error was
induced by the incredibly bad ClassWizard of VS<=6, which couldn't parse the header files
because it had an /ad hoc/ parser.  When VS.NET delivered an intelligent parsers, they
forgot to change the behavior to make sense.  It *never* makes sense to declare a control
variable or handler as public, and the default should be 'protected'.

You violate that rule here by attempting to manipulate a control variable from outside the
dialog.  The control variable is not bound to a control until INSIDE the OnInitDialog
handler (in fact, it is bound when the CDialog::OnInitDialog call invokes the
DoDataExchange method of the dialog class).  Since the code you show here takes place long
before OnInitDialog, there is no possible way the variable could be bound to a control. In
fact, the control doesn't even exist at the point you are trying to manipulate it.
					joe

>  aboutDlg.DoModal();
>}
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/14/2010 2:26:24 AM

On 13/06/2010 21:34, RB wrote:

> Thanks Giovanni, worked like a charm, though I changed the
> SetVersionString function to no args.  I have a couple of
> questions if you would be so kind. See code and comments
> below. Questions are at very bottom in the OnInitDialog.

> class CAboutDlg : public CDialog
>   {
>     private:
>      CString m_strVersion;
>     public:
>      void SetVersionString( );

If the SetVersionString method is not designed to be called from the 
outside of the class, you could make it 'private' (so it can be 
accessible only inside CAboutDlg class), or 'protected' (so it can be 
accessible inside CAboutDlg class and classes derived from it).


> BOOL CAboutDlg::OnInitDialog( )
>   {    //** Class Wizard added  base call ** //
>     CDialog::OnInitDialog( );
>
> //** being added code //
>     SetVersionString( );   // format the CString
>     HWND hDlg = m_CtrlStaticVer.GetSafeHwnd( );
>
> //** Question 1.
> //** here I used the API SetWindowText to get a return, the
> //     MFC SetWindowText was a void return, Is this a big deal ?
>
>     BOOL bResult = ::SetWindowText(hDlg, m_strVersion);

Frankly speaking, in MFC code I've always used CWnd::SetWindowText 
method (not the global raw Win32 API ::SetWindowText).

e.g. considering the m_CtrlStaticVer control class, I would just write:

   m_CtrlStaticVer.SetWindowText( someString );

However, you are right that the return value of ::SetWindowText is lost 
in this case.

In VC10 (VS2010), the implementation of CWnd::SetWindowText is like this:

<code>

void CWnd::SetWindowText(LPCTSTR lpszString)
{
	ENSURE(this);
	ENSURE(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));

	if (m_pCtrlSite == NULL)
		::SetWindowText(m_hWnd, lpszString);
	else
		m_pCtrlSite->SetWindowText(lpszString);
}

</code>

So, the return value of ::SetWindowText is just discarded.
I would have preferred a method returning BOOL, to better wrap the raw 
Win32 ::SetWindowText.

Note that ATL's CWindow::SetWindowText() correctly returns a BOOL, so it 
is a better wrapper to ::SetWindowText:

   http://msdn.microsoft.com/en-us/library/wfaxc8w5(VS.80).aspx

>
> //**Question 2
> //** Class Wizard put below return in ? when I had planned to return the
> //** the result of the SetWindow,  Can you explain what this is all about ?
>
>     return TRUE;  // return TRUE unless you set the focus to a control
>                 // EXCEPTION: OCX Property Pages should return FALSE
> }

When you use a framework like MFC, it is better to follow the rules of 
this framework, as indicated by the comments introduced by the MFC Wizard.

Note also that OnInitDialog method wraps the WM_INITDIALOG Win32 
message, and in the "Return Value" paragraph you can read:

http://msdn.microsoft.com/en-us/library/ms645428(VS.85).aspx

<quote>

The dialog box procedure should return TRUE to direct the system to set 
the keyboard focus to the control specified by wParam. Otherwise, it 
should return FALSE to prevent the system from setting the default 
keyboard focus.

</quote>


Giovanni
0
Reply Giovanni 6/14/2010 10:03:33 AM

> void CWnd::SetWindowText(LPCTSTR lpszString)
> {
> ENSURE(this);
>............

Oh I see, I was also later stepping thru it and began to have
a hunch this was the case. So the importance of the return
is dimished quite a bit being that a failure is handled within.

> Note that ATL's CWindow::SetWindowText() correctly returns a BOOL, so it is a better wrapper to ::SetWindowText:

I will check out the link, I had wondered about CWindow class,
was curious why MFC would seemingly have two classes to do
much of the same stuff, but never really investigated it enough to
even know what was the story. Thanks for the info.

> When you use a framework like MFC, it is better to follow the rules of this framework, as indicated by the comments introduced by 
> the MFC Wizard.
> Note also that OnInitDialog method wraps the WM_INITDIALOG Win32 message, and in the "Return Value" paragraph you can read:
> The dialog box procedure should return TRUE to direct the system to set the keyboard focus to the control specified by wParam. 
> Otherwise, it should return FALSE to prevent the system from setting the default keyboard focus.

Well yes I should have thought of that being that it is a class handler it
has it's own adjenda rather than me implementing mine on it's return.
I should have thought to wrap the call to SetWindowText and then
deal with my return accordingly before letting OnInitDialog deal with
it's own adjenda. That was stupid on my part but none the less always
glad to hear words of wisdom from experience.
This could be the last correspondence I will experience on this group
(only time will tell ) but I appreciate all you guys have helped me on,
and hopefully I can get my NNTP set up so the forums won't be so
cryptic. RB 


0
Reply RB 6/14/2010 1:38:50 PM

Thanks Joe, another novice stupid move on my part. One
thing about me, I am not afraid to screw up in order to move
forward.
   But in reference to the dangerous code that you so informatively
detailed, I have rectified it (with the help of Giovanni ) and it is
now working great and I have learned another facet of programming
that hopefully will stick with me enough not to do it again. In
retrospect I had a hunch previously that much of what you said was
the case from remembering long ago when I tried writing small simple
API apps that had child windows.
   This has taught me that I am leaning too much on what is visually
available in the Class Wizard rather than having the foresight to
have looked in the docs for CDialog class I would have found
in the OnInitDialog class member text, clearly showing that it
was the function I was needing. Even though I have my VS2005
now, I still do my experimentations in VC6 since I am so used to
it. But this is yet another reason to move on even in that facet.
If I don't see you on this group again, thanks ever so much for all
your help. RB 


0
Reply RB 6/14/2010 1:59:33 PM

On 14/06/2010 15:38, RB wrote:

>> Note that ATL's CWindow::SetWindowText() correctly returns a BOOL, so it is a better wrapper to ::SetWindowText:
>
> I will check out the link, I had wondered about CWindow class,
> was curious why MFC would seemingly have two classes to do
> much of the same stuff, but never really investigated it enough to
> even know what was the story. Thanks for the info.

Actually, CWindow is an ATL class, completely different from CWnd.
CWindow is an inexpensive class to create: it's just a wrapper around an 
HWND data member (instead, MFC maintains maps between HWND's and CWnd's...).
Moreover, when an instance of CWindow goes out of scope, the associated 
window is *not* destroyed.

The spirit of ATL is different from the spirit of MFC: ATL is a more 
thin wrapper around Win32 APIs, heavily uses templates, is leaner than 
MFC, supports COM programming very well, etc.

There is a project called WTL which started internally in Microsoft and 
then went open-source, that is built upon ATL, and offers several C++ 
wrapper classes to several Windows controls.


 > That was stupid on my part

When you try to learn something there is nothing stupid about it :)


> This could be the last correspondence I will experience on this group
> (only time will tell ) but I appreciate all you guys have helped me on,
> and hopefully I can get my NNTP set up so the forums won't be so
> cryptic. RB

This newsgroup seems still active :)


Giovanni

0
Reply Giovanni 6/14/2010 2:35:12 PM

See below...
On Mon, 14 Jun 2010 09:38:50 -0400, "RB" <NoMail@NoSpam> wrote:

>> void CWnd::SetWindowText(LPCTSTR lpszString)
>> {
>> ENSURE(this);
>>............
>
>Oh I see, I was also later stepping thru it and began to have
>a hunch this was the case. So the importance of the return
>is dimished quite a bit being that a failure is handled within.
>
>> Note that ATL's CWindow::SetWindowText() correctly returns a BOOL, so it is a better wrapper to ::SetWindowText:
>
>I will check out the link, I had wondered about CWindow class,
>was curious why MFC would seemingly have two classes to do
>much of the same stuff, but never really investigated it enough to
>even know what was the story. Thanks for the info.
****
CWnd is the MFC class

CWindow is the ATL class

CWindow is a stripped-down lightweight class for use in ActiveX controls (primarily in
ActiveVIrus controls, those controls whose purpose in life is to be blocked by
intelligently-configured browsers)

You would not use CWindow in an MFC app.
****
>
>> When you use a framework like MFC, it is better to follow the rules of this framework, as indicated by the comments introduced by 
>> the MFC Wizard.
>> Note also that OnInitDialog method wraps the WM_INITDIALOG Win32 message, and in the "Return Value" paragraph you can read:
>> The dialog box procedure should return TRUE to direct the system to set the keyboard focus to the control specified by wParam. 
>> Otherwise, it should return FALSE to prevent the system from setting the default keyboard focus.
>
>Well yes I should have thought of that being that it is a class handler it
>has it's own adjenda rather than me implementing mine on it's return.
****
All methods designed by the framework are designed with the frameworks's "agenda" in mind.
Note that this also means that in a raw Win32 app (using windows but no MFC), that the
return value from the WM_INITDIALOG message is what the Windows framework defines it to
be, and has nothing to do with your wishes.  In fact, the resturn value (or lack thereof)
for EVERY WM_, EM_, CB_, etc. message is predefined by the Windows framework!

The CDialog::OnInitDialog virtual method you override is just a reflection of the deep
functionality of the WM_INITDIALOG message, and corresponds to its requirements.  It
doesn't care at all about yours, since you will never see the return value from
OnInitDialog (only the dialog box framework, an integral part of Windows, sees it)
****
>I should have thought to wrap the call to SetWindowText and then
>deal with my return accordingly before letting OnInitDialog deal with
>it's own adjenda.
****
You are clearly confused about "agendas" here.  The "agenda" on WM_INITDIALOG is to allow
YOU to do what YOU want with the controls in the dialog.  As such, it is not issued until
all the controls are created.  The CDialog::OnInitDialog virtual method reflects this
functionality.  Note that the root CDiallog::OnInitDialog calls the virtual method
DoDataExchange, and your virtual DoDataExchange method calls the parent class's
DoDataExchange, and so on up the line (this allows one dialog to derive from another!).
DoDataExchange, knowing that the controls now exist (a guarantee), will bind the controls
to the variables.

So I'm not sure what "agenda" is going on here.  It *specifically* exists to allow you to
implment "your agenda".
				joe
****
> That was stupid on my part but none the less always
>glad to hear words of wisdom from experience.
>This could be the last correspondence I will experience on this group
>(only time will tell ) but I appreciate all you guys have helped me on,
>and hopefully I can get my NNTP set up so the forums won't be so
>cryptic. RB 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/14/2010 3:43:16 PM

As I pointed out, VS2005 erroneously maintains the "public" nature of control variables
(although you *can* change it, most people don't know they *should*) and of handlers (you
are not given a option to change their visibility, a fudnamental design error, given they
are erroneously marked 'public').  I always hand-edit my .h files to lump the handlers
together (in a 'protected' area), lump the variables together (in a 'protected' area,
often in alphabetical order), and so on, instead of taking the horrible misorganization
the new tools seem to think would be acceptable.
				joe

On Mon, 14 Jun 2010 09:59:33 -0400, "RB" <NoMail@NoSpam> wrote:

>Thanks Joe, another novice stupid move on my part. One
>thing about me, I am not afraid to screw up in order to move
>forward.
>   But in reference to the dangerous code that you so informatively
>detailed, I have rectified it (with the help of Giovanni ) and it is
>now working great and I have learned another facet of programming
>that hopefully will stick with me enough not to do it again. In
>retrospect I had a hunch previously that much of what you said was
>the case from remembering long ago when I tried writing small simple
>API apps that had child windows.
>   This has taught me that I am leaning too much on what is visually
>available in the Class Wizard rather than having the foresight to
>have looked in the docs for CDialog class I would have found
>in the OnInitDialog class member text, clearly showing that it
>was the function I was needing. Even though I have my VS2005
>now, I still do my experimentations in VC6 since I am so used to
>it. But this is yet another reason to move on even in that facet.
>If I don't see you on this group again, thanks ever so much for all
>your help. RB 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/14/2010 3:46:20 PM

> ****
> CWnd is the MFC class
> CWindow is the ATL class
> CWindow is a stripped-down lightweight class for use in ActiveX controls
> (primarily in ActiveVIrus controls, those controls whose purpose in life is to 
> be blocked by intelligently-configured browsers)
> You would not use CWindow in an MFC app.
> ****

Thank you, I will note that.

> You are clearly confused about "agendas" here.  The "agenda" on 
> WM_INITDIALOG is to allow YOU to do what YOU want with the controls 
>  in the dialog.  As such, it is not issued until all the controls are created.  The 
> CDialog::OnInitDialog virtual method reflects this functionality.  Note that the 
> root CDiallog::OnInitDialog calls the virtual method DoDataExchange, and your 
> ..................................
> So I'm not sure what "agenda" is going on here.  It *specifically* exists to allow 
> you to implment "your agenda".
> joe
> ****

Thanks again for the elaboration. I was attempting to describe my confused state
on using the return of OnInitDialog for my return value. Apologize for ambiguity
on my part in doing so. I do understand that I had the whole return idea wrong.
RB
0
Reply RB 6/14/2010 9:39:33 PM

I think I'm missing something but I'm interested in this topic.
If you have your version defined in a header file, then you can display it 
in the dialog, however, if you did a "property" on the exe file, has it 
really changed?  If so, then I got lost somewhere in this thread.

Also;
I was under the impression that you can set something in VS that allowed the 
version to change each time you do a build.  I don't remember how to do this 
but I always thought this was possible.  Now it may only change the Build 
number and not anything else, however, this is a good feature.  Is this 
still possible, if so ....  how do you do it?

Thanks


"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in message 
news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
> On 13/06/2010 15:47, RB wrote:
>
>> void CFileHandlingApp::OnAppAbout()
>> {
>>    CAboutDlg aboutDlg;
>>    CString s;
>>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, 
>> BUILDNUMBER );
>>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion 
>> Failed
>>    aboutDlg.DoModal();
>
> You may want to add a method to your CAboutDlg class like 
> SetVersionString(LPCTSTR pszVersion) and a data member of type CString 
> (e.g. CString m_strVersion).
> This new method should set the version string, storing it into the proper 
> data member.
>
> Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText() 
> it in the proper static control.
>
> e.g.:
>
> class CAboutDlg
> {
>    ...
> public:
>    void SetVersionString(LPCTSTR pszVersion)
>    {
>        m_strVersion = pszVersion;
>    }
>
> ...
>
> private:
>    CString m_strVersion;
> };
>
> In CAboudDlg::OnInitDialog() do:
>
>   m_CtrlStaticVer.SetWindowText(m_strVersion);
>
>
> Giovanni 

0
Reply JCO 6/14/2010 11:54:46 PM

"JCO" wrote
>I think I'm missing something but I'm interested in this topic.
> If you have your version defined in a header file, then you can display it 
> in the dialog, however, if you did a "property" on the exe file, has it 
> really changed?  If so, then I got lost somewhere in this thread.

Well I think I can show you that part since it does work on my
App. See code at bottom. 

> Also;
> I was under the impression that you can set something in VS that allowed the 
> version to change each time you do a build.  I don't remember how to do this 
> but I always thought this was possible.  Now it may only change the Build 
> number and not anything else, however, this is a good feature.  Is this 
> still possible, if so ....  how do you do it?

I will let Giovanni respond to that since I am used to using an old version
of VS that does not (that I am aware of ) do this. 

----pasted pertinant code to version going to Exe (and any DLLs) on build
I put the below into my AppVer.h file. This is the one source for version data.
Include this file in each file that needs access to version data
 
// Stringisation.
// (Two steps needed).

#define _STR(x)  #x
#define  STR(x)  _STR(x)

// The following are used as defined quantities
// in the versioninfo resource:

#define VERMAJ        1
#define VERMIN        0
#define VERFIX       0
#define BUILDNUMBER   0

#define VERMAJSTR   STR( VERMAJ )
#define VERMINSTR   STR( VERMIN )
#define VERFIXSTR   STR( VERFIX )
#define BUILDSTR    STR( BUILDNUMBER )
#define VERSIONSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR
#define PRODUCTSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR 

#define CORP_NAME "RBC"   // used in file serialize data
#define CPY_RIGHT_YR  "Copyright (C) 2010"  // used in CAbout dialog
                                                                // along with VERSIONSTRING

----Now as to the Exe properties part, what I did was look in my AppWizard
generated rc file, and cut out the CAbout dialog defined section, and then paste
it into rc2 file,  i.e.

/////////in my rc2 file///////////////////////////////////
// Add manually edited resources here...

#include "AppVer.h"  // this is the one version source

// From here down was cut out of Project rc file and then pasted here
// and then edited to receive the defines from the AppVer.h file
// See edits below

#ifndef _MAC

VS_VERSION_INFO VERSIONINFO
//--in the original rc file section this used to be 
// FILEVERSION 1,0,0,1 --//  
 FILEVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER
 PRODUCTVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L

#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "CompanyName", CORP_NAME "\0" //*EDITED
            VALUE "FileDescription", "FileHandling MFC Application\0"
            VALUE "FileVersion", VERSIONSTRING "\0" //*EDITED
            VALUE "InternalName", "FileHandling\0"
            VALUE "LegalCopyright", CPY_RIGHT_YR "\0" //*EDITED
            VALUE "LegalTrademarks", "\0"
            VALUE "OriginalFilename", "FileHandling.EXE\0"
            VALUE "ProductName", "FileHandling Application\0"
            VALUE "ProductVersion", PRODUCTSTRING "\0" //*EDITED
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END
#endif    // !_MAC

---The above will show in the properties when you right click on exe.
Note I had to leave a space between the DEFINE and the NULL
i.e.  VERSIONSTRING "\0" and not VERSIONSTRING"\0" 
or I got a " in the output.    I choose to keep the "\0" separate from the
#defines since I used some of them later for sting literal initalizers.
Otherwise I guess you could include it in the define.

0
Reply RB 6/15/2010 2:09:09 AM

On 15/06/2010 01:54, JCO wrote:

> I was under the impression that you can set something in VS that allowed
> the version to change each time you do a build. I don't remember how to
> do this but I always thought this was possible. Now it may only change
> the Build number and not anything else, however, this is a good feature.
> Is this still possible, if so .... how do you do it?

Are you thinking of something like this?

http://www.codeproject.com/KB/dotnet/build_versioning.aspx

Giovanni

0
Reply Giovanni 6/15/2010 9:15:00 AM

On 14/06/2010 17:43, Joseph M. Newcomer wrote:

> CWindow is the ATL class
>
> CWindow is a stripped-down lightweight class for use in ActiveX controls (primarily in
> ActiveVIrus controls, those controls whose purpose in life is to be blocked by
> intelligently-configured browsers)

You can use CWindow to wrap any HWND's.
ATL was originally designed to build lightweight (quickly downloadable 
from the web, and not requiring MFC DLL's) ActiveX controls, but then it 
evolved in a small and fast template-based library for Win32 and COM 
programming.

Giovanni

0
Reply Giovanni 6/15/2010 9:20:29 AM

Corrective update, although the paste I gave you does in fact work
in my App currently. You may want to reexamine my use of the
results of 
#define _STR(x)  #x
#define  STR(x)  _STR(x)
since I am still learning this area, and some reading I did last night
proves to me that I did not fully understand what this macro was
expanding to when I implemented some of the pasted code.

I really should not be replying to questions since I am not at that
level of competence yet. I only supplied it since I "appeared at the
time" to have a working example of what you asked for, which
the whole idea was given to me ( if you followed the thread )
by David Webber, but the implementation (and any foo bars )
are my doing, not Davids.
So use what you will but be aware.
RB
0
Reply RB 6/15/2010 12:42:54 PM

The idea is that the header file is used to create both the string in the About box and
the values in the .rc file that describes the VERSIONINFO.
				joe

On Mon, 14 Jun 2010 18:54:46 -0500, "JCO" <someone@somewhere.com> wrote:

>I think I'm missing something but I'm interested in this topic.
>If you have your version defined in a header file, then you can display it 
>in the dialog, however, if you did a "property" on the exe file, has it 
>really changed?  If so, then I got lost somewhere in this thread.
>
>Also;
>I was under the impression that you can set something in VS that allowed the 
>version to change each time you do a build.  I don't remember how to do this 
>but I always thought this was possible.  Now it may only change the Build 
>number and not anything else, however, this is a good feature.  Is this 
>still possible, if so ....  how do you do it?
>
>Thanks
>
>
>"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in message 
>news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
>> On 13/06/2010 15:47, RB wrote:
>>
>>> void CFileHandlingApp::OnAppAbout()
>>> {
>>>    CAboutDlg aboutDlg;
>>>    CString s;
>>>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, 
>>> BUILDNUMBER );
>>>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion 
>>> Failed
>>>    aboutDlg.DoModal();
>>
>> You may want to add a method to your CAboutDlg class like 
>> SetVersionString(LPCTSTR pszVersion) and a data member of type CString 
>> (e.g. CString m_strVersion).
>> This new method should set the version string, storing it into the proper 
>> data member.
>>
>> Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText() 
>> it in the proper static control.
>>
>> e.g.:
>>
>> class CAboutDlg
>> {
>>    ...
>> public:
>>    void SetVersionString(LPCTSTR pszVersion)
>>    {
>>        m_strVersion = pszVersion;
>>    }
>>
>> ...
>>
>> private:
>>    CString m_strVersion;
>> };
>>
>> In CAboudDlg::OnInitDialog() do:
>>
>>   m_CtrlStaticVer.SetWindowText(m_strVersion);
>>
>>
>> Giovanni 
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/15/2010 1:52:44 PM

See below...
On Mon, 14 Jun 2010 22:09:09 -0400, "RB" <NoMail@NoSpam> wrote:

>
>"JCO" wrote
>>I think I'm missing something but I'm interested in this topic.
>> If you have your version defined in a header file, then you can display it 
>> in the dialog, however, if you did a "property" on the exe file, has it 
>> really changed?  If so, then I got lost somewhere in this thread.
>
>Well I think I can show you that part since it does work on my
>App. See code at bottom. 
>
>> Also;
>> I was under the impression that you can set something in VS that allowed the 
>> version to change each time you do a build.  I don't remember how to do this 
>> but I always thought this was possible.  Now it may only change the Build 
>> number and not anything else, however, this is a good feature.  Is this 
>> still possible, if so ....  how do you do it?
****
This has been a gross oversight which I first complained about in the early 1990s, and
Microsoft has done NOTHING to provide a build-number incrementer (although it would be
easy enough to do as an integrated component of VS).  I wrote my own build number
incrementer some years ago and you can find it on my MVP Tips site.  We still don't have
it in VS2010, which means it has been something they have been aware of for over 15 years
and have still done NOTHING to fix, in spite of the demand of users.
				joe
****
>
>I will let Giovanni respond to that since I am used to using an old version
>of VS that does not (that I am aware of ) do this. 
>
>----pasted pertinant code to version going to Exe (and any DLLs) on build
>I put the below into my AppVer.h file. This is the one source for version data.
>Include this file in each file that needs access to version data
> 
>// Stringisation.
>// (Two steps needed).
>
>#define _STR(x)  #x
>#define  STR(x)  _STR(x)
>
>// The following are used as defined quantities
>// in the versioninfo resource:
>
>#define VERMAJ        1
>#define VERMIN        0
>#define VERFIX       0
>#define BUILDNUMBER   0
>
>#define VERMAJSTR   STR( VERMAJ )
>#define VERMINSTR   STR( VERMIN )
>#define VERFIXSTR   STR( VERFIX )
>#define BUILDSTR    STR( BUILDNUMBER )
>#define VERSIONSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR
>#define PRODUCTSTRING VERMAJSTR "." VERMINSTR "." VERFIXSTR "." BUILDSTR 
>
>#define CORP_NAME "RBC"   // used in file serialize data
>#define CPY_RIGHT_YR  "Copyright (C) 2010"  // used in CAbout dialog
>                                                                // along with VERSIONSTRING
>
>----Now as to the Exe properties part, what I did was look in my AppWizard
>generated rc file, and cut out the CAbout dialog defined section, and then paste
>it into rc2 file,  i.e.
>
>/////////in my rc2 file///////////////////////////////////
>// Add manually edited resources here...
>
>#include "AppVer.h"  // this is the one version source
>
>// From here down was cut out of Project rc file and then pasted here
>// and then edited to receive the defines from the AppVer.h file
>// See edits below
>
>#ifndef _MAC
>
>VS_VERSION_INFO VERSIONINFO
>//--in the original rc file section this used to be 
>// FILEVERSION 1,0,0,1 --//  
> FILEVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER
> PRODUCTVERSION VERMAJ,VERMIN,VERFIX, BUILDNUMBER
> FILEFLAGSMASK 0x3fL
>#ifdef _DEBUG
> FILEFLAGS 0x1L
>#else
> FILEFLAGS 0x0L
>
>#endif
> FILEOS 0x4L
> FILETYPE 0x1L
> FILESUBTYPE 0x0L
>BEGIN
>    BLOCK "StringFileInfo"
>    BEGIN
>        BLOCK "040904B0"
>        BEGIN
>            VALUE "CompanyName", CORP_NAME "\0" //*EDITED
>            VALUE "FileDescription", "FileHandling MFC Application\0"
>            VALUE "FileVersion", VERSIONSTRING "\0" //*EDITED
>            VALUE "InternalName", "FileHandling\0"
>            VALUE "LegalCopyright", CPY_RIGHT_YR "\0" //*EDITED
>            VALUE "LegalTrademarks", "\0"
>            VALUE "OriginalFilename", "FileHandling.EXE\0"
>            VALUE "ProductName", "FileHandling Application\0"
>            VALUE "ProductVersion", PRODUCTSTRING "\0" //*EDITED
>        END
>    END
>    BLOCK "VarFileInfo"
>    BEGIN
>        VALUE "Translation", 0x409, 1200
>    END
>END
>#endif    // !_MAC
>
>---The above will show in the properties when you right click on exe.
>Note I had to leave a space between the DEFINE and the NULL
>i.e.  VERSIONSTRING "\0" and not VERSIONSTRING"\0" 
>or I got a " in the output.    I choose to keep the "\0" separate from the
>#defines since I used some of them later for sting literal initalizers.
>Otherwise I guess you could include it in the define.
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/15/2010 1:56:28 PM

When I add this information to the RC2 file, I get these two errors:
1  CVT1100: duplicate resource,  Type:VERSION, name:1, language:0x0409
2  LNK1123: failure during conversion to COFF: file invalid or corrupt

"RB" <NoMail@NoSpam> wrote in message 
news:umG$MhIDLHA.4400@TK2MSFTNGP05.phx.gbl...
> Corrective update, although the paste I gave you does in fact work
> in my App currently. You may want to reexamine my use of the
> results of #define _STR(x)  #x
> #define  STR(x)  _STR(x)
> since I am still learning this area, and some reading I did last night
> proves to me that I did not fully understand what this macro was
> expanding to when I implemented some of the pasted code.
>
> I really should not be replying to questions since I am not at that
> level of competence yet. I only supplied it since I "appeared at the
> time" to have a working example of what you asked for, which
> the whole idea was given to me ( if you followed the thread )
> by David Webber, but the implementation (and any foo bars )
> are my doing, not Davids.
> So use what you will but be aware.
> RB 

0
Reply JCO 6/15/2010 5:24:05 PM

> "JCO" wrote in message 
> When I add this information to the RC2 file, I get these two errors:
> 1  CVT1100: duplicate resource,  Type:VERSION, name:1, language:0x0409
> 2  LNK1123: failure during conversion to COFF: file invalid or corrupt

Well again, I am only a novice speculating, but when you say you added
this information, 
Did you cut out the About Dialog segment of your rc file (so that it is 
gone from that file) and then paste that exact cut into your rc2 file ?
Then try to compile, if all goes well then include your AppVer.h
file into the rc2 file, and hand edit the items in rc2 file you desire
to reflect from the header file. If you do them one at a time you should 
be able to see what is causing the problem.
  Also I did this using VC6 your version may have a different format
or order of items in the rc file, but none the less if you paste the
exact cut into the rc2 file and work from there you should be able
to decipher what you need. I remember David Webber said in his
version there was another way to get at the rc file text, in mine I had
to open it in notepad, which he said sometimes can cause problems 
but my VC later just says it has been changed do I want to reload it, 
I choose yes.  I don't know of any other way to edit my version.
Good luck with it. It works great for me, I really like the setup
RB

0
Reply RB 6/15/2010 6:36:55 PM

I understand the items that are added to the .rc2 file, however, are you 
suppose to also edit the .rc file by commenting out everything listed under 
"Version"?


"RB" <NoMail@NoSpam> wrote in message 
news:umG$MhIDLHA.4400@TK2MSFTNGP05.phx.gbl...
> Corrective update, although the paste I gave you does in fact work
> in my App currently. You may want to reexamine my use of the
> results of #define _STR(x)  #x
> #define  STR(x)  _STR(x)
> since I am still learning this area, and some reading I did last night
> proves to me that I did not fully understand what this macro was
> expanding to when I implemented some of the pasted code.
>
> I really should not be replying to questions since I am not at that
> level of competence yet. I only supplied it since I "appeared at the
> time" to have a working example of what you asked for, which
> the whole idea was given to me ( if you followed the thread )
> by David Webber, but the implementation (and any foo bars )
> are my doing, not Davids.
> So use what you will but be aware.
> RB 

0
Reply JCO 6/15/2010 6:44:23 PM

> I understand the items that are added to the .rc2 file, however, 
> are you suppose to also edit the .rc file by commenting out 
> everything listed under "Version"?

Yes, and sorry I said CAbout Dialog segment earlier. Actually
at first I cut and pasted the Dialog segement also and it worked
but I lost my ability to see and edit it's other aspects in the 
resource editor so I pasted it back and it held next time 
VS rewrote it.
But anyhow yes the version segment, but in my VS  I cannot 
comment out rc file segments since the VS writes (and rewrites ) 
the entire file.  So I cut the version segment out totally and pasted it 
into the rc2 file.  See other reply (but ignore dialog segment and
use version)
If your VS allows you to comment in the rc file then yea you could 
do that, but unless things changed with the newer VS that file belongs 
to the VS so I would think that anything you were allowed to comment
would be gone next time VS rewrote it
RB


0
Reply RB 6/15/2010 7:05:22 PM

When I delete the VERSION in the .rc, I get the following link errors:

Error	1	error LNK2019: unresolved external symbol _GetFileVersionInfoW@16 
referenced in function "public: void __thiscall 
CAppVersionDynamicDlg::OnBnClickedButton1(void)" 
(?OnBnClickedButton1@CAppVersionDynamicDlg@@QAEXXZ)	AppVersionDynamicDlg.objAppVersionDynamicError	2	fatal error LNK1120: 1 unresolved externals	E:\My 
C++\AppVersionDynamic\AppVersionDynamic\Debug\AppVersionDynamic.exeAppVersionDynamicIf I don't remove anything from the .rc file, I get the other two errors I 
posted earlier.
Sorry this isn't working for me.   I'm not that experienced in this stuff 
either.
Thanks

"RB" <NoMail@NoSpam> wrote in message 
news:eI1w22LDLHA.1888@TK2MSFTNGP05.phx.gbl...
>> I understand the items that are added to the .rc2 file, however, are you 
>> suppose to also edit the .rc file by commenting out everything listed 
>> under "Version"?
>
> Yes, and sorry I said CAbout Dialog segment earlier. Actually
> at first I cut and pasted the Dialog segement also and it worked
> but I lost my ability to see and edit it's other aspects in the resource 
> editor so I pasted it back and it held next time VS rewrote it.
> But anyhow yes the version segment, but in my VS  I cannot comment out rc 
> file segments since the VS writes (and rewrites ) the entire file.  So I 
> cut the version segment out totally and pasted it into the rc2 file.  See 
> other reply (but ignore dialog segment and
> use version)
> If your VS allows you to comment in the rc file then yea you could do 
> that, but unless things changed with the newer VS that file belongs to the 
> VS so I would think that anything you were allowed to comment
> would be gone next time VS rewrote it
> RB
>
> 
0
Reply JCO 6/15/2010 9:15:28 PM


"JCO" <someone@somewhere.com> wrote in message 
news:Oigi3zBDLHA.2012@TK2MSFTNGP02.phx.gbl...

> I think I'm missing something but I'm interested in this topic.
> If you have your version defined in a header file, then you can display it 
> in the dialog, however, if you did a "property" on the exe file, has it 
> really changed?  If so, then I got lost somewhere in this thread.

#define VERMAX 3

causes VERMAX to be replaced by 3 before compilation of the exe, so of 
course it is the same in the "property" dialoge.

> I was under the impression that you can set something in VS that allowed 
> the version to change each time you do a build.  I don't remember how to 
> do this but I always thought this was possible.  Now it may only change 
> the Build number and not anything else, however, this is a good feature. 
> Is this still possible, if so ....  how do you do it?

Haven't tried it.  I only update my build number when making it available to 
3rd parties, and I do that manually.  It's good enough for my purposes.

Dave

-- 
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm 

0
Reply David 6/15/2010 9:26:33 PM


"JCO" <someone@somewhere.com> wrote in message 
news:#cDkO#KDLHA.2012@TK2MSFTNGP02.phx.gbl...

> When I add this information to the RC2 file, I get these two errors:
> 1  CVT1100: duplicate resource,  Type:VERSION, name:1, language:0x0409
> 2  LNK1123: failure during conversion to COFF: file invalid or corrupt

If you left the VERSIONINFO in the rc file AND pasted in the rc2 file, then 
you have it twice.  That might be what error 1 is telling you.

Dave

-- 
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm 

0
Reply David 6/15/2010 9:29:15 PM

Yes I got it to work.  I had some code in the cpp file that was causing the 
link error.
I will review what I have done now.. but everything seems okay and works.

"RB" <NoMail@NoSpam> wrote in message 
news:eI1w22LDLHA.1888@TK2MSFTNGP05.phx.gbl...
>> I understand the items that are added to the .rc2 file, however, are you 
>> suppose to also edit the .rc file by commenting out everything listed 
>> under "Version"?
>
> Yes, and sorry I said CAbout Dialog segment earlier. Actually
> at first I cut and pasted the Dialog segement also and it worked
> but I lost my ability to see and edit it's other aspects in the resource 
> editor so I pasted it back and it held next time VS rewrote it.
> But anyhow yes the version segment, but in my VS  I cannot comment out rc 
> file segments since the VS writes (and rewrites ) the entire file.  So I 
> cut the version segment out totally and pasted it into the rc2 file.  See 
> other reply (but ignore dialog segment and
> use version)
> If your VS allows you to comment in the rc file then yea you could do 
> that, but unless things changed with the newer VS that file belongs to the 
> VS so I would think that anything you were allowed to comment
> would be gone next time VS rewrote it
> RB
>
> 
0
Reply JCO 6/15/2010 9:32:42 PM

Agreed!

"David Webber" <dave@musical-dot-demon-dot-co.uk> wrote in message 
news:O#VF20NDLHA.4400@TK2MSFTNGP05.phx.gbl...
>
>
> "JCO" <someone@somewhere.com> wrote in message 
> news:Oigi3zBDLHA.2012@TK2MSFTNGP02.phx.gbl...
>
>> I think I'm missing something but I'm interested in this topic.
>> If you have your version defined in a header file, then you can display 
>> it in the dialog, however, if you did a "property" on the exe file, has 
>> it really changed?  If so, then I got lost somewhere in this thread.
>
> #define VERMAX 3
>
> causes VERMAX to be replaced by 3 before compilation of the exe, so of 
> course it is the same in the "property" dialoge.
>
>> I was under the impression that you can set something in VS that allowed 
>> the version to change each time you do a build.  I don't remember how to 
>> do this but I always thought this was possible.  Now it may only change 
>> the Build number and not anything else, however, this is a good feature. 
>> Is this still possible, if so ....  how do you do it?
>
> Haven't tried it.  I only update my build number when making it available 
> to 3rd parties, and I do that manually.  It's good enough for my purposes.
>
> Dave
>
> -- 
> David Webber
> Mozart Music Software
> http://www.mozart.co.uk
> For discussion and support see
> http://www.mozart.co.uk/mozartists/mailinglist.htm 

0
Reply JCO 6/15/2010 11:03:34 PM

This is another issue that fits in this thread.
I've been messing with the GetFileVersionInfo() but when it's in my cpp, I 
get link errors.  I can't seem to find a header file that might be missing 
so I don't understand it.  The code snip is shown below.  I have some extra 
code because I'm experimenting a bit but the issue is the 
GetFileVersionInfo() linker Issue.
*********************************************************
	//get filename, add .exe, then get handle to this filename
	CString strFileName( _T("") );
	strFileName = AfxGetApp()->m_pszExeName;
	strFileName.Append( _T(".exe") );
	HMODULE hmod = GetModuleHandle( strFileName );

	//use GetModuleFileName() to obtain full path of file
	CString strFullPath( _T("") );
	LPTSTR pstr	= strFullPath.GetBufferSetLength(MAX_PATH+1);
	DWORD pathLen	= ::GetModuleFileName( hmod, pstr, MAX_PATH);

	strFullPath.ReleaseBuffer( pathLen );	   //Note: ReleaseBuffer doesn't need 
a +1 for the null byte

	//Use GetFileVersionInfo() to get file information
	TCHAR szExePath[MAX_PATH];
	::GetModuleFileName( NULL, szExePath, MAX_PATH );

	DWORD dwDummy;
	DWORD dwFVISize = GetFileVersionInfoSize( szExePath, &dwDummy );

	LPBYTE lpVersionInfo = new BYTE[dwFVISize];
	GetFileVersionInfo( szExePath , 0 , dwFVISize , lpVersionInfo );

	if( lpVersionInfo )
		delete lpVersionInfo;

	VS_FIXEDFILEINFO *lpFfi;
	DWORD dwFileVersionMS	= lpFfi->dwFileVersionMS;
	DWORD dwFileVersionLS	= lpFfi->dwFileVersionLS;
	DWORD dwLeftMost	= HIWORD(dwFileVersionMS);
	DWORD dwSecondLeft	= LOWORD(dwFileVersionMS);
	DWORD dwSecondRight	= HIWORD(dwFileVersionLS);
	DWORD dwRightMost	= LOWORD(dwFileVersionLS);

	CString sMsg;
	sMsg.Format( _T("Version: %d.%d.%d.%d") , dwLeftMost, 
dwSecondLeft,dwSecondRight, dwRightMost );
	MessageBox( sMsg );

********************************************************

These are the liker Errors:
Error	1	error LNK2019: unresolved external symbol _GetFileVersionInfoW@16 
referenced in function "public: void __thiscall 
CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)" 
(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj	AppVersionDynamicError	2	error LNK2019: unresolved external symbol _GetFileVersionInfoSizeW@8 
referenced in function "public: void __thiscall 
CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)" 
(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj	AppVersionDynamic"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message 
news:cc1f16hsn3lejfmtp2b5n0a20093vii1bf@4ax.com...
> The idea is that the header file is used to create both the string in the 
> About box and
> the values in the .rc file that describes the VERSIONINFO.
> joe
>
> On Mon, 14 Jun 2010 18:54:46 -0500, "JCO" <someone@somewhere.com> wrote:
>
>>I think I'm missing something but I'm interested in this topic.
>>If you have your version defined in a header file, then you can display it
>>in the dialog, however, if you did a "property" on the exe file, has it
>>really changed?  If so, then I got lost somewhere in this thread.
>>
>>Also;
>>I was under the impression that you can set something in VS that allowed 
>>the
>>version to change each time you do a build.  I don't remember how to do 
>>this
>>but I always thought this was possible.  Now it may only change the Build
>>number and not anything else, however, this is a good feature.  Is this
>>still possible, if so ....  how do you do it?
>>
>>Thanks
>>
>>
>>"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in message
>>news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
>>> On 13/06/2010 15:47, RB wrote:
>>>
>>>> void CFileHandlingApp::OnAppAbout()
>>>> {
>>>>    CAboutDlg aboutDlg;
>>>>    CString s;
>>>>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX,
>>>> BUILDNUMBER );
>>>>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion
>>>> Failed
>>>>    aboutDlg.DoModal();
>>>
>>> You may want to add a method to your CAboutDlg class like
>>> SetVersionString(LPCTSTR pszVersion) and a data member of type CString
>>> (e.g. CString m_strVersion).
>>> This new method should set the version string, storing it into the 
>>> proper
>>> data member.
>>>
>>> Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText()
>>> it in the proper static control.
>>>
>>> e.g.:
>>>
>>> class CAboutDlg
>>> {
>>>    ...
>>> public:
>>>    void SetVersionString(LPCTSTR pszVersion)
>>>    {
>>>        m_strVersion = pszVersion;
>>>    }
>>>
>>> ...
>>>
>>> private:
>>>    CString m_strVersion;
>>> };
>>>
>>> In CAboudDlg::OnInitDialog() do:
>>>
>>>   m_CtrlStaticVer.SetWindowText(m_strVersion);
>>>
>>>
>>> Giovanni
> Joseph M. Newcomer [MVP]
> email: newcomer@flounder.com
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm 

0
Reply JCO 6/15/2010 11:14:48 PM

> "JCO" wrote 
> Yes I got it to work.  I had some code in the cpp file that was causing the 
> link error. I will review what I have done now.. but everything seems 
> okay and works.

Good I think you will find it convenient.  If you work it right you
only have to edit the header file when anything changes and then
the rest updates itself on compile.
Remember to always keep spaces between items and the quotation
marks or you will end up seeing quotations in the output.
See comment below,
===========================================
//--in your version header file
#define _STR(x)  #x
#define  STR(x)  _STR(x)


#define  VERMAJ     1
#define  VERMIN     0
#define  VERFIX      0
#define  BUILDNUM    0
#define  YR    2010

#define V_MA_STR_LIT   STR( VERMAJ )
#define V_MI_STR_LIT    STR( VERMIN )
#define V_FX_STR_LIT    STR( VERFIX )
#define B_N_STR_LIT      STR( BUILDNUM )
#define YR_STR_LIT  STR( YR )

// must leave space between items and the quotation marks or you will end up seeing quotations in the output.
#define VERSTR      V_MA_STR_LIT  "."  V_MI_STR_LIT  "."  V_FX_STR_LIT  "."  B_N_STR_LIT  "\0"
#define  CPY_RT_YR_STR_LITERAL  "Copyright (C) "  YR_STR_LIT

===============================================
//----and reflected in your rc2 file------//
#include "YourVersion.h"

VS_VERSION_INFO VERSIONINFO
 FILEVERSION  VERMAJ, VERMIN, VERFIX,  BUILDNUM
 PRODUCTVERSION  VERMAJ, VERMIN, VERFIX,  BUILDNUM
............
     ..................
     VALUE "FileVersion", VERSTR
      ................

===============================================
//----and in your About Dialog------//
#include "YourVersion.h"

class CAboutDlg : public CDialog
 {
   ........
   private:
   void SetVerStr( );
  CString m_strVersion,  m_strCpyRightYr ;
  ........
}

void CAboutDlg::SetVerStr( )
 {
   m_strVersion.Format(  _T(" Version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUM );
   m_strCpyRightYr = _T(CPY_RT_YR_STR_LITERAL);
 }

BOOL CAboutDlg::OnInitDialog( ) 
{
  CDialog::OnInitDialog( );
  SetVerStr(); 
  m_CtrlStaticVer.SetWindowText( m_strVersion );
  m_CtrlStaticCr.SetWindowText( m_strCpyRightYr );
  return TRUE;  
}

=====================================
//-----and in your DocClass constructor--//
#include "YourVersion.h"

CFileHandlingDoc::CFileHandlingDoc( ) 
{ // These are CStrings in a Version Struct
   VerData.Ver.Format(  _T("Version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUM );
   VerData.CpyRt = _T(CPY_RT_YR_STR_LITERAL);
}  

//----and in your DocClass serialize function----//

void CFileHandlingDoc::Serialize(CArchive& ar)
{ 
 if (ar.IsStoring( ))       
   { 
     ............
     ar << VerData.Ver << VerData.CpyRt;
     ............
   }                                         
 else               
   { 
     ............
     ar >> VerData.Ver >> VerData.CpyRt;
     ............
   }       
}
0
Reply RB 6/15/2010 11:21:05 PM

The version library is not included by default in the link.  If you get any kind of linker
error, it is ESSENTIAL that you RTFM, which tells you which library needs to be linked in.
Link in that library.
				joe
****
On Tue, 15 Jun 2010 18:14:48 -0500, "JCO" <someone@somewhere.com> wrote:

>
>This is another issue that fits in this thread.
>I've been messing with the GetFileVersionInfo() but when it's in my cpp, I 
>get link errors.  I can't seem to find a header file that might be missing 
>so I don't understand it.  The code snip is shown below.  I have some extra 
>code because I'm experimenting a bit but the issue is the 
>GetFileVersionInfo() linker Issue.
>*********************************************************
>	//get filename, add .exe, then get handle to this filename
****
Start throwing code away here
****
>	CString strFileName( _T("") );
>	strFileName = AfxGetApp()->m_pszExeName;
>	strFileName.Append( _T(".exe") );
>	HMODULE hmod = GetModuleHandle( strFileName );
>
>	//use GetModuleFileName() to obtain full path of file
>	CString strFullPath( _T("") );
>	LPTSTR pstr	= strFullPath.GetBufferSetLength(MAX_PATH+1);
>	DWORD pathLen	= ::GetModuleFileName( hmod, pstr, MAX_PATH);
>
>	strFullPath.ReleaseBuffer( pathLen );	   //Note: ReleaseBuffer doesn't need 
>a +1 for the null byte
****
Throw away all the above code.  As far as I can tell, it does nothing that can't be done
in the four simple lines below.

	CString filename;
	LPTSTR p = fliename.GetBuffer(MAX_PATH);
	GetModuleFileName(NULL, p, MAX_PATH);
	filename.ReleaseBuffer();

It is not at all clear why you have to use GetModuleHandle here at all.  The module handle
is not needed for anything.  RTFM; using NULL as the module handle gives you the filename
of the running executable!
****
>
>	//Use GetFileVersionInfo() to get file information
>	TCHAR szExePath[MAX_PATH];
****
This variable is not needed; eliminate it entirely!
*****
>	::GetModuleFileName( NULL, szExePath, MAX_PATH );
****
Why are you repeating the GetModuleFileName, which was already done?  Get rid of this
line; it serves no useful purpose because you already have the module filename!
****
>
>	DWORD dwDummy;
>	DWORD dwFVISize = GetFileVersionInfoSize( szExePath, &dwDummy );
****
Given I used the variable "filename" above, this would simply be
	DWORD dwFVISize = ::GetFileVersionInfoSize(filename, &dwDummy);
****
>
>	LPBYTE lpVersionInfo = new BYTE[dwFVISize];
****
You would be better served by
	CBytArray VersionInfo;
	VersionInfo.SetSize(dwFVISize];
*****
>	GetFileVersionInfo( szExePath , 0 , dwFVISize , lpVersionInfo );
****
And then coding the above as
	::GetFileVersionInfo(filename, 0, dwFVISize, VersionInfo.GetData());
****
>
>	if( lpVersionInfo )
>		delete lpVersionInfo;
****
Note there is no need to do the delete if you have used the CByteArray.

Note also that you must not delete this data until *after* you have used it!

And why is it that if the value is NULL, you try to call ::GetFileVersionInfo anyway?  If
you were testing for an allocation error, you would test BEFORE you tried to use the
pointer.   And there is no need to condition delete if it is NULL.   And if the call
failed, why are you blindly going on and tryhing to *use* the illegal values?
>
>	VS_FIXEDFILEINFO *lpFfi;
****
And where do I see this pointer being initialized?  You have an uninitialized pointer and
you blindly use it to access values below!

It should be initialized as
	VS_FIXEDFILEINFO * Ffi =(VS_FIXEDFILEINFO *)VersionInfo.GetData();
****
>	DWORD dwFileVersionMS	= lpFfi->dwFileVersionMS;
>	DWORD dwFileVersionLS	= lpFfi->dwFileVersionLS;
>	DWORD dwLeftMost	= HIWORD(dwFileVersionMS);
>	DWORD dwSecondLeft	= LOWORD(dwFileVersionMS);
>	DWORD dwSecondRight	= HIWORD(dwFileVersionLS);
>	DWORD dwRightMost	= LOWORD(dwFileVersionLS);
>
>	CString sMsg;
>	sMsg.Format( _T("Version: %d.%d.%d.%d") , dwLeftMost, 
>dwSecondLeft,dwSecondRight, dwRightMost );
>	MessageBox( sMsg );
>
>********************************************************
>
>These are the liker Errors:
>Error	1	error LNK2019: unresolved external symbol _GetFileVersionInfoW@16 
>referenced in function "public: void __thiscall 
>CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)" 
>(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj	AppVersionDynamicError	2	error LNK2019: unresolved external symbol _GetFileVersionInfoSizeW@8 
>referenced in function "public: void __thiscall 
>CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)" 
>(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj	AppVersionDynamic"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message 
>news:cc1f16hsn3lejfmtp2b5n0a20093vii1bf@4ax.com...
****
RTFM.  The documentation CLEARLY states that the API call is found in version.lib, so it
is screamingly obvious that this library is not included in the link.  So add it to the
linker list of libraries to search!
				joe
****
>> The idea is that the header file is used to create both the string in the 
>> About box and
>> the values in the .rc file that describes the VERSIONINFO.
>> joe
>>
>> On Mon, 14 Jun 2010 18:54:46 -0500, "JCO" <someone@somewhere.com> wrote:
>>
>>>I think I'm missing something but I'm interested in this topic.
>>>If you have your version defined in a header file, then you can display it
>>>in the dialog, however, if you did a "property" on the exe file, has it
>>>really changed?  If so, then I got lost somewhere in this thread.
>>>
>>>Also;
>>>I was under the impression that you can set something in VS that allowed 
>>>the
>>>version to change each time you do a build.  I don't remember how to do 
>>>this
>>>but I always thought this was possible.  Now it may only change the Build
>>>number and not anything else, however, this is a good feature.  Is this
>>>still possible, if so ....  how do you do it?
>>>
>>>Thanks
>>>
>>>
>>>"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in message
>>>news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
>>>> On 13/06/2010 15:47, RB wrote:
>>>>
>>>>> void CFileHandlingApp::OnAppAbout()
>>>>> {
>>>>>    CAboutDlg aboutDlg;
>>>>>    CString s;
>>>>>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX,
>>>>> BUILDNUMBER );
>>>>>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug Assertion
>>>>> Failed
>>>>>    aboutDlg.DoModal();
>>>>
>>>> You may want to add a method to your CAboutDlg class like
>>>> SetVersionString(LPCTSTR pszVersion) and a data member of type CString
>>>> (e.g. CString m_strVersion).
>>>> This new method should set the version string, storing it into the 
>>>> proper
>>>> data member.
>>>>
>>>> Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText()
>>>> it in the proper static control.
>>>>
>>>> e.g.:
>>>>
>>>> class CAboutDlg
>>>> {
>>>>    ...
>>>> public:
>>>>    void SetVersionString(LPCTSTR pszVersion)
>>>>    {
>>>>        m_strVersion = pszVersion;
>>>>    }
>>>>
>>>> ...
>>>>
>>>> private:
>>>>    CString m_strVersion;
>>>> };
>>>>
>>>> In CAboudDlg::OnInitDialog() do:
>>>>
>>>>   m_CtrlStaticVer.SetWindowText(m_strVersion);
>>>>
>>>>
>>>> Giovanni
>> Joseph M. Newcomer [MVP]
>> email: newcomer@flounder.com
>> Web: http://www.flounder.com
>> MVP Tips: http://www.flounder.com/mvp_tips.htm 
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/16/2010 3:57:28 AM

If you add a VERSIONINFO to the RC2 file, you must DELETE the EXISTING ONE from the .rc
file!  Otherwise, guess what, you have a duplicate resource of type VERSION, whose name is
1, and whose language is 0x0409. 

Error 1 leads directly to error 2.
				joe

On Tue, 15 Jun 2010 12:24:05 -0500, "JCO" <someone@somewhere.com> wrote:

>When I add this information to the RC2 file, I get these two errors:
>1  CVT1100: duplicate resource,  Type:VERSION, name:1, language:0x0409
>2  LNK1123: failure during conversion to COFF: file invalid or corrupt
>
>"RB" <NoMail@NoSpam> wrote in message 
>news:umG$MhIDLHA.4400@TK2MSFTNGP05.phx.gbl...
>> Corrective update, although the paste I gave you does in fact work
>> in my App currently. You may want to reexamine my use of the
>> results of #define _STR(x)  #x
>> #define  STR(x)  _STR(x)
>> since I am still learning this area, and some reading I did last night
>> proves to me that I did not fully understand what this macro was
>> expanding to when I implemented some of the pasted code.
>>
>> I really should not be replying to questions since I am not at that
>> level of competence yet. I only supplied it since I "appeared at the
>> time" to have a working example of what you asked for, which
>> the whole idea was given to me ( if you followed the thread )
>> by David Webber, but the implementation (and any foo bars )
>> are my doing, not Davids.
>> So use what you will but be aware.
>> RB 
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/16/2010 4:04:05 AM

See below...
On Tue, 15 Jun 2010 13:44:23 -0500, "JCO" <someone@somewhere.com> wrote:

>
>I understand the items that are added to the .rc2 file, however, are you 
>suppose to also edit the .rc file by commenting out everything listed under 
>"Version"?
****
I have no idea what you mean by "commenting out everything listed under "Version".  What
you need to do is DELETE the version resource from the .rc file.  Highlight it in the tree
describing the resources and use the "delete" key, just like you would do in deleting any
other kind of resource.

Commenting something out is not a relevant concept here.  Deleting it is what you want to
do!
			joe

>
>
>"RB" <NoMail@NoSpam> wrote in message 
>news:umG$MhIDLHA.4400@TK2MSFTNGP05.phx.gbl...
>> Corrective update, although the paste I gave you does in fact work
>> in my App currently. You may want to reexamine my use of the
>> results of #define _STR(x)  #x
>> #define  STR(x)  _STR(x)
>> since I am still learning this area, and some reading I did last night
>> proves to me that I did not fully understand what this macro was
>> expanding to when I implemented some of the pasted code.
>>
>> I really should not be replying to questions since I am not at that
>> level of competence yet. I only supplied it since I "appeared at the
>> time" to have a working example of what you asked for, which
>> the whole idea was given to me ( if you followed the thread )
>> by David Webber, but the implementation (and any foo bars )
>> are my doing, not Davids.
>> So use what you will but be aware.
>> RB 
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
Reply Joseph 6/16/2010 4:05:43 AM

On 16/06/2010 05:57, Joseph M. Newcomer wrote:

>> 	LPBYTE lpVersionInfo = new BYTE[dwFVISize];
> ****
> You would be better served by
> 	CBytArray VersionInfo;
> 	VersionInfo.SetSize(dwFVISize];

or STL's vector:

     vector<BYTE> VersionInfo(dwFVISize);

>>
>> 	if( lpVersionInfo )
>> 		delete lpVersionInfo;
> ****
> Note there is no need to do the delete if you have used the CByteArray.
>
> Note also that you must not delete this data until *after* you have used it!

Note also that if the memory was allocated using new BYTE[...], it 
should be deleted using delete[] (note the square brackets).

I agree that with RAII classes like std::vector you just don't need to 
spend brain cycles :) to track these kind of memory leaks.

Giovanni
0
Reply Giovanni 6/16/2010 9:38:26 AM

Actually I have been experimenting with the
#define _STR(x)  #x
#define  STR(x)  _STR(x)
 
And I found that instead stringizing every individual numerical
define as in
#define VERMAJ  1
#define V_MA_STR_LIT   STR( VERMAJ )
........ etc

which ended up doing all of this
#define VERSTR_LITERAL  V_MA_STR_LIT "." V_MI_STR_LIT "." V_FX_STR_LIT "." B_N_STR_LIT

I could use the numericals right of and just do this
#define VERSTR_LITERAL  STR( VERMAJ.VERMIN.VERFIX.BUILDNUM)
// which can be used anywhere you would manually type in a string literal of "x.x.x.x"
// or in the first version case "1.0.0.0"
0
Reply RB 6/16/2010 12:24:59 PM

Yes this is all working now except for the implementation in the actual 
About Box.  I'm getting the Assertion Error.
For the AboutBox implementation I have the following:
prototypes
void SetVersionString (LPTCSTR sVer);
LPTCSTR GetVersionString (void);

//m_CtrlStaticVer is the control variable for the CStatic that is to be set 
with the proper value in the dialog
BOOL CAboutDlg::OnInitDialog(void)
{
	CString s;
	s.Format(  _T("AppVersionDynamic, Version %d.%d.%d.%d"), VERMAJ,
                                                        VERMIN, VERFIX, 
BUILDNUMBER );
	SetVersionString( s );

	m_CtrlStaticVer.SetWindowText( GetVersionString() );
	return TRUE;
}

I get 2 Assertion Errors.  One deals with the control variable setting the 
value.  If commented out, I get still get an assertion on the dialog when 
you close it out.

Thanks

"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message 
news:i7jg165ugb9uba3nei7p3tqleka51cvm7v@4ax.com...
> If you add a VERSIONINFO to the RC2 file, you must DELETE the EXISTING ONE 
> from the .rc
> file!  Otherwise, guess what, you have a duplicate resource of type 
> VERSION, whose name is
> 1, and whose language is 0x0409.
>
> Error 1 leads directly to error 2.
> joe
>
> On Tue, 15 Jun 2010 12:24:05 -0500, "JCO" <someone@somewhere.com> wrote:
>
>>When I add this information to the RC2 file, I get these two errors:
>>1  CVT1100: duplicate resource,  Type:VERSION, name:1, language:0x0409
>>2  LNK1123: failure during conversion to COFF: file invalid or corrupt
>>
>>"RB" <NoMail@NoSpam> wrote in message
>>news:umG$MhIDLHA.4400@TK2MSFTNGP05.phx.gbl...
>>> Corrective update, although the paste I gave you does in fact work
>>> in my App currently. You may want to reexamine my use of the
>>> results of #define _STR(x)  #x
>>> #define  STR(x)  _STR(x)
>>> since I am still learning this area, and some reading I did last night
>>> proves to me that I did not fully understand what this macro was
>>> expanding to when I implemented some of the pasted code.
>>>
>>> I really should not be replying to questions since I am not at that
>>> level of competence yet. I only supplied it since I "appeared at the
>>> time" to have a working example of what you asked for, which
>>> the whole idea was given to me ( if you followed the thread )
>>> by David Webber, but the implementation (and any foo bars )
>>> are my doing, not Davids.
>>> So use what you will but be aware.
>>> RB
> Joseph M. Newcomer [MVP]
> email: newcomer@flounder.com
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm 

0
Reply JCO 6/16/2010 2:21:25 PM

Sorry, I'm not familiar with RTFM.
I'm not sure how to figure out what library is missing and how to include 
it?

I made the change using CByteArray.  That's a big help and your rigth... the 
code looks cleaner.  Plus I was able to delete the "delete[]"

Thanks so far.

"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message 
news:crhg1652u574iem3g5iu09amqun7o9n7on@4ax.com...
> The version library is not included by default in the link.  If you get 
> any kind of linker
> error, it is ESSENTIAL that you RTFM, which tells you which library needs 
> to be linked in.
> Link in that library.
> joe
> ****
> On Tue, 15 Jun 2010 18:14:48 -0500, "JCO" <someone@somewhere.com> wrote:
>
>>
>>This is another issue that fits in this thread.
>>I've been messing with the GetFileVersionInfo() but when it's in my cpp, I
>>get link errors.  I can't seem to find a header file that might be missing
>>so I don't understand it.  The code snip is shown below.  I have some 
>>extra
>>code because I'm experimenting a bit but the issue is the
>>GetFileVersionInfo() linker Issue.
>>*********************************************************
>> //get filename, add .exe, then get handle to this filename
> ****
> Start throwing code away here
> ****
>> CString strFileName( _T("") );
>> strFileName = AfxGetApp()->m_pszExeName;
>> strFileName.Append( _T(".exe") );
>> HMODULE hmod = GetModuleHandle( strFileName );
>>
>> //use GetModuleFileName() to obtain full path of file
>> CString strFullPath( _T("") );
>> LPTSTR pstr = strFullPath.GetBufferSetLength(MAX_PATH+1);
>> DWORD pathLen = ::GetModuleFileName( hmod, pstr, MAX_PATH);
>>
>> strFullPath.ReleaseBuffer( pathLen );    //Note: ReleaseBuffer doesn't 
>> need
>>a +1 for the null byte
> ****
> Throw away all the above code.  As far as I can tell, it does nothing that 
> can't be done
> in the four simple lines below.
>
> CString filename;
> LPTSTR p = fliename.GetBuffer(MAX_PATH);
> GetModuleFileName(NULL, p, MAX_PATH);
> filename.ReleaseBuffer();
>
> It is not at all clear why you have to use GetModuleHandle here at all. 
> The module handle
> is not needed for anything.  RTFM; using NULL as the module handle gives 
> you the filename
> of the running executable!
> ****
>>
>> //Use GetFileVersionInfo() to get file information
>> TCHAR szExePath[MAX_PATH];
> ****
> This variable is not needed; eliminate it entirely!
> *****
>> ::GetModuleFileName( NULL, szExePath, MAX_PATH );
> ****
> Why are you repeating the GetModuleFileName, which was already done?  Get 
> rid of this
> line; it serves no useful purpose because you already have the module 
> filename!
> ****
>>
>> DWORD dwDummy;
>> DWORD dwFVISize = GetFileVersionInfoSize( szExePath, &dwDummy );
> ****
> Given I used the variable "filename" above, this would simply be
> DWORD dwFVISize = ::GetFileVersionInfoSize(filename, &dwDummy);
> ****
>>
>> LPBYTE lpVersionInfo = new BYTE[dwFVISize];
> ****
> You would be better served by
> CBytArray VersionInfo;
> VersionInfo.SetSize(dwFVISize];
> *****
>> GetFileVersionInfo( szExePath , 0 , dwFVISize , lpVersionInfo );
> ****
> And then coding the above as
> ::GetFileVersionInfo(filename, 0, dwFVISize, VersionInfo.GetData());
> ****
>>
>> if( lpVersionInfo )
>> delete lpVersionInfo;
> ****
> Note there is no need to do the delete if you have used the CByteArray.
>
> Note also that you must not delete this data until *after* you have used 
> it!
>
> And why is it that if the value is NULL, you try to call 
> ::GetFileVersionInfo anyway?  If
> you were testing for an allocation error, you would test BEFORE you tried 
> to use the
> pointer.   And there is no need to condition delete if it is NULL.   And 
> if the call
> failed, why are you blindly going on and tryhing to *use* the illegal 
> values?
>>
>> VS_FIXEDFILEINFO *lpFfi;
> ****
> And where do I see this pointer being initialized?  You have an 
> uninitialized pointer and
> you blindly use it to access values below!
>
> It should be initialized as
> VS_FIXEDFILEINFO * Ffi =(VS_FIXEDFILEINFO *)VersionInfo.GetData();
> ****
>> DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
>> DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
>> DWORD dwLeftMost = HIWORD(dwFileVersionMS);
>> DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
>> DWORD dwSecondRight = HIWORD(dwFileVersionLS);
>> DWORD dwRightMost = LOWORD(dwFileVersionLS);
>>
>> CString sMsg;
>> sMsg.Format( _T("Version: %d.%d.%d.%d") , dwLeftMost,
>>dwSecondLeft,dwSecondRight, dwRightMost );
>> MessageBox( sMsg );
>>
>>********************************************************
>>
>>These are the liker Errors:
>>Error 1 error LNK2019: unresolved external symbol _GetFileVersionInfoW@16
>>referenced in function "public: void __thiscall
>>CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)"
>>(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj 
>>AppVersionDynamicError 2 error LNK2019: unresolved external symbol 
>>_GetFileVersionInfoSizeW@8
>>referenced in function "public: void __thiscall
>>CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)"
>>(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj 
>>AppVersionDynamic"Joseph M. Newcomer" <newcomer@flounder.com> wrote in 
>>message
>>news:cc1f16hsn3lejfmtp2b5n0a20093vii1bf@4ax.com...
> ****
> RTFM.  The documentation CLEARLY states that the API call is found in 
> version.lib, so it
> is screamingly obvious that this library is not included in the link.  So 
> add it to the
> linker list of libraries to search!
> joe
> ****
>>> The idea is that the header file is used to create both the string in 
>>> the
>>> About box and
>>> the values in the .rc file that describes the VERSIONINFO.
>>> joe
>>>
>>> On Mon, 14 Jun 2010 18:54:46 -0500, "JCO" <someone@somewhere.com> wrote:
>>>
>>>>I think I'm missing something but I'm interested in this topic.
>>>>If you have your version defined in a header file, then you can display 
>>>>it
>>>>in the dialog, however, if you did a "property" on the exe file, has it
>>>>really changed?  If so, then I got lost somewhere in this thread.
>>>>
>>>>Also;
>>>>I was under the impression that you can set something in VS that allowed
>>>>the
>>>>version to change each time you do a build.  I don't remember how to do
>>>>this
>>>>but I always thought this was possible.  Now it may only change the 
>>>>Build
>>>>number and not anything else, however, this is a good feature.  Is this
>>>>still possible, if so ....  how do you do it?
>>>>
>>>>Thanks
>>>>
>>>>
>>>>"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in 
>>>>message
>>>>news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
>>>>> On 13/06/2010 15:47, RB wrote:
>>>>>
>>>>>> void CFileHandlingApp::OnAppAbout()
>>>>>> {
>>>>>>    CAboutDlg aboutDlg;
>>>>>>    CString s;
>>>>>>    s.Format(  _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX,
>>>>>> BUILDNUMBER );
>>>>>>    aboutDlg.m_CtrlStaticVer.SetWindowText(s);  //gets a Debug 
>>>>>> Assertion
>>>>>> Failed
>>>>>>    aboutDlg.DoModal();
>>>>>
>>>>> You may want to add a method to your CAboutDlg class like
>>>>> SetVersionString(LPCTSTR pszVersion) and a data member of type CString
>>>>> (e.g. CString m_strVersion).
>>>>> This new method should set the version string, storing it into the
>>>>> proper
>>>>> data member.
>>>>>
>>>>> Then, CAboutDlg::OnInitDialog would get this string and 
>>>>> .SetWindowText()
>>>>> it in the proper static control.
>>>>>
>>>>> e.g.:
>>>>>
>>>>> class CAboutDlg
>>>>> {
>>>>>    ...
>>>>> public:
>>>>>    void SetVersionString(LPCTSTR pszVersion)
>>>>>    {
>>>>>        m_strVersion = pszVersion;
>>>>>    }
>>>>>
>>>>> ...
>>>>>
>>>>> private:
>>>>>    CString m_strVersion;
>>>>> };
>>>>>
>>>>> In CAboudDlg::OnInitDialog() do:
>>>>>
>>>>>   m_CtrlStaticVer.SetWindowText(m_strVersion);
>>>>>
>>>>>
>>>>> Giovanni
>>> Joseph M. Newcomer [MVP]
>>> email: newcomer@flounder.com
>>> Web: http://www.flounder.com
>>> MVP Tips: http://www.flounder.com/mvp_tips.htm
> Joseph M. Newcomer [MVP]
> email: newcomer@flounder.com
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm 

0
Reply JCO 6/16/2010 2:57:02 PM

Never mind!  I went to the project property and added version.lib in the
area Linker->Dependency.
I never understood how to figure out that version.lib is what I needed
(other than Joseph's post)?

Of course this brings up all sorts of other errors further down in the code. 
None of the code below works.  It throws exceptions:

	DWORD dwFileVersionMS	= lpFfi->dwFileVersionMS;
	DWORD dwFileVersionLS	= lpFfi->dwFileVersionLS;
	DWORD dwLeftMost	= HIWORD(dwFileVersionMS);
	DWORD dwSecondLeft	= LOWORD(dwFileVersionMS);
	DWORD dwSecondRight	= HIWORD(dwFileVersionLS);
	DWORD dwRightMost	= LOWORD(dwFileVersionLS);


"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in message
news:#TsHxeTDLHA.1368@TK2MSFTNGP06.phx.gbl...
> On 16/06/2010 05:57, Joseph M. Newcomer wrote:
>
>>> LPBYTE lpVersionInfo = new BYTE[dwFVISize];
>> ****
>> You would be better served by
>> CBytArray VersionInfo;
>> VersionInfo.SetSize(dwFVISize];
>
> or STL's vector:
>
>     vector<BYTE> VersionInfo(dwFVISize);
>
>>>
>>> if( lpVersionInfo )
>>> delete lpVersionInfo;
>> ****
>> Note there is no need to do the delete if you have used the CByteArray.
>>
>> Note also that you must not delete this data until *after* you have used
>> it!
>
> Note also that if the memory was allocated using new BYTE[...], it should
> be deleted using delete[] (note the square brackets).
>
> I agree that with RAII classes like std::vector you just don't need to
> spend brain cycles :) to track these kind of memory leaks.
>
> Giovanni 

0
Reply JCO 6/16/2010 3:27:44 PM

On 16/06/2010 17:27, JCO wrote:

> Of course this brings up all sorts of other errors further down in the
> code. None of the code below works. It throws exceptions:
>
> DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
> DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
> DWORD dwLeftMost = HIWORD(dwFileVersionMS);
> DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
> DWORD dwSecondRight = HIWORD(dwFileVersionLS);
> DWORD dwRightMost = LOWORD(dwFileVersionLS);

What kind of exceptions?

Giovanni
0
Reply Giovanni 6/16/2010 3:34:03 PM

48 Replies
619 Views

(page loaded in 2.36 seconds)

Similiar Articles:



















7/19/2012 6:52:54 PM


Reply: