From: mfc on
Hi,

is it much better to create all the buttons from a view in the
OnInitialUpdate() method instead of placing the buttons with the
resource editor....

Version1: create button in resource-editor and add some additional
properties in the OnInitialUpdate() method of the specific view

m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
m_btnMenu1Ok.SetButtonText("OK");
m_btnMenu1Ok.SetFont("Arial",16);
m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
255, 255));
m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
150, 150));
m_btnMenu1Ok.SubclassDlgItem(IDC_MENU1_BTN_BACK_OK, this);

I`ve read in the www that SubclassDlgItem() is not a safe method - is
this statement true? Maybe someone of you could give me some more
information about this statement to improve me knowledge...

Version2: create the whole button in the OnInitialUpdate() method

m_btnMenu1Ok.Create("OK", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
CRect(10, 10, 30, 30), this, 1);
m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
m_btnMenu1Ok.SetFont("Arial",16);
m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
255, 255));
m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
150, 150));


best regards
Hans
From: Joseph M. Newcomer on
See below...
On Mon, 21 Jun 2010 11:13:22 -0700 (PDT), mfc <mfcprog(a)googlemail.com> wrote:

>Hi,
>
>is it much better to create all the buttons from a view in the
>OnInitialUpdate() method instead of placing the buttons with the
>resource editor....
****
No. In fact, the simplest categorization is that is always and forever a MISTAKE to try to
do this. The truth is more complex than that, but this simple guideline will serve you
well.
*****
>
>Version1: create button in resource-editor and add some additional
>properties in the OnInitialUpdate() method of the specific view
>
>m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
>m_btnMenu1Ok.SetButtonText("OK");
****
What is an English-language string doing in a source program? What is an 8-bit string
doing in a source program? In fact, why is the text not set in the dialog editor? Three
serious design errors in a single line has to be a new record!
*****
>m_btnMenu1Ok.SetFont("Arial",16);
****
There is nothing right about the above line. Why 16? What makes you think this could
*possibly* make sense? The default font is established as part of the user's profile
selections, and you either must obey them or not do anything this dumb. Don't do it.
****
>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
>255, 255));
****
Why do you think white makes sense here? Why did you not use
::GetSysColor(COLOR_WINDOW)
for the color? Either follow the user's color scheme, or don't do ANYTHING!
****
>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
>150, 150));
****
What could 150, 150, 150 POSSIBLY mean? Did you not mean
::GetSysColor(COLOR_BTNFACE)
?

FOLLOW THE USER'S COLOR SCHEME!
****
>m_btnMenu1Ok.SubclassDlgItem(IDC_MENU1_BTN_BACK_OK, this);
****
You are in such deep trouble here. Why in the world would you SubclassDlgItem? If you
are calling this, you are not using MFC correctly! Even if you create buttons
dynamically, you would not need to do this!
*****
>
>I`ve read in the www that SubclassDlgItem() is not a safe method - is
>this statement true? Maybe someone of you could give me some more
>information about this statement to improve me knowledge...
*****
It is an indication that you have no idea how to use MFC correctly. So if you need to do
it, re-examine what you are doing! When I was clueless about MFC, I once wrote it (some
time in my first or second MFC program) and was given similar advice.

There is no need to use it. So don't.
*****
>
>Version2: create the whole button in the OnInitialUpdate() method
>
>m_btnMenu1Ok.Create("OK", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
>CRect(10, 10, 30, 30), this, 1);
****
First the CRect is a colossal blunder. Where in the world did you get the idea that
10,10,30,30 could possibly make sense? Sure, on YOUR machine, with YOUR display, YOUR
graphics card, YOUR current version of the display driver, YOUR current resolution, and
YOUR default font size, but unless the program is now and forever going to run on YOUR
machine and you will never, ever change any one of these settings or components, it cannot
possibly run correctly anywhere else. So don't do it.


In situations where I have to create buttons dynamically (because the number of buttons is
based on some only-known-at-run-time set of parameters) I will always create an
*invisible* button on the dialog, and use it to get the necessary parameters, e.g.,

CRect r;
c_ButtonPrototype.GetWindowRect(&r);
ScreenToClient(&r);

This will give me the width and height I need; for positioning, I usually place some
control on the dialog I can use as a reference point (sometimes an invisible CStatic) and
use it to determine the top and left of an array of buttons. I usually separate them by
some platform-independent computation, like 3 * ::GetSystemMetrics(SM_CXEDGE) or 3 *
::GetSystemMetrics(SM_CYEDGE) or some similar computation that will work on every screen,
every resolution, etc..

Assume that ANY hardwired integer you use for computing position, unless it is a simple
multiplier or divisor of a runtime-determined value, is erroneous.

For example, to center a button, I will use
CRect r;
GetClientRect(&r);
CRect b;
c_OK.GetWindowRect(&b);
ScreenToClient(&b);
c_OK.SetWindowPos(NULL, r.Width() / 2 - b.Width() / 2,
r.Height() / 2 - b.Height() / 2,
0, 0,
SWP_NOZORDER | SWP_NOSIZE);

and this will put the button dead center in the dialog. But if you EVER choose an
absolute coordinate or size, you are DEAD WRONG. This includes font sizes.

What is "1" for a control ID? Did you not mean IDOK? And what is English-language text,
and 8-bit text at that, doing in a source program?

OK, a new record. There are FOUR things wrong with the above line, not the least of which
is its very existence!
*****
>m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
>m_btnMenu1Ok.SetFont("Arial",16);
****
You should not be deciding either the font or its size! Why do you think Arial 16 could
possibly make sense? Because it sort-of-looks-like what you are seeing? In exactly which
version of Windows? (Did you know that Microsoft has changed the default dialog font
appearance in every recent version of Windows? You should not presume your dialog is
going to run on the same version of the operating system, including service pack, that you
are using!)

When you create a dialog control explicitly, the best way to set the font is
CFont * f = GetFont();
ctl.SetFont(f);
which uses the same font as the dialog, and this font will track OS versions and user
preferences. It will look like all the other dialogs the user has, and its size will
track properly.
*****
>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
>255, 255));
>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
>150, 150));
****
As already pointed out, you must not be using hardwired colors.

Essentially, EVERY line you wrote except the one to set the image has no reason to exist,
and they should all be deleted. In either version.
joe
*****
>
>
>best regards
>Hans
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Mihai N. on

> m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
> m_btnMenu1Ok.SetButtonText("OK");
> m_btnMenu1Ok.SetFont("Arial",16);
> m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
> 255, 255));
> m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
> 150, 150));
> m_btnMenu1Ok.SubclassDlgItem(IDC_MENU1_BTN_BACK_OK, this);


There is absolutely no reason to do that in native Windows development.
You should use the resource editor, create a dialog using WYSIWYG, and
at run time load it at start usnig with with one function call, DialogBox.
(or family, DialogBoxIndirect, DialogBoxIndirectParam, DialogBoxParam)


--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

From: mfc on

first of all, thank you very much for your support. It is also my
first programm in MFC and with C++.

> >is it much better to create all the buttons from a view in the
> >OnInitialUpdate() method instead of placing the buttons with the
> >resource editor....
>
> ****
> No. In fact, the simplest categorization is that is always and forever a MISTAKE to try to
> do this.  The truth is more complex than that, but this simple guideline will serve you
> well.
> *****

Ok, I hope I got you right: You should install all button items and so
on in the resource-editor (dialog-box) and add all specific code (like
images for the buttons) in the OnInitialUpdate() and OnUpdate()
method. That means if I use more than one language I will use the
function LoadString() in the OnUpdate() method in each view to load
the correct text string to each specific item in the current dialog
box.

But how will I get the specific ID (of each item from the dialogbox)
in the view-class to add additional things like images, textstrings?
>>>m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
>>>m_btnMenu1Ok.SubclassDlgItem(IDC_MENU1_BTN_BACK_OK, this);

With this line, the Cbutton object m_btnMenu1Ok will be connected to
the cbutton, drawn in the dialog with this id
(IDC_MENU1_BTN_BACK_OK)....


Ok I think I found the correct function for that: if it is also
working in a sdi app.

void CApplicationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, lblExample, m_lblExample);
}

After that: add a string from the string-table:
m_lblExample.SetWindowText(m_pLanguage-
>GetString(IDS_EXAMPLE).c_str());



> ****
> Why do you think white makes sense here?  Why did you not use
>         ::GetSysColor(COLOR_WINDOW)
> for the color?  Either follow the user's color scheme, or don't do ANYTHING!
> ****>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
> >150, 150));
>
> ****
> What could 150, 150, 150 POSSIBLY mean?  Did you not mean
>         ::GetSysColor(COLOR_BTNFACE)
> ?
>
> FOLLOW THE USER'S COLOR SCHEME!
> ****>m_btnMenu1Ok.SubclassDlgItem(IDC_MENU1_BTN_BACK_OK, this);
>
> ****
> You are in such deep trouble here.  Why in the world would you SubclassDlgItem?  If you
> are calling this, you are not using MFC correctly!  Even if you create buttons
> dynamically, you would not need to do this!
> *****
>
> >I`ve read in the www that SubclassDlgItem() is not a safe method - is
> >this statement true? Maybe someone of you could give me some more
> >information about this statement to improve me knowledge...
>
> *****
> It is an indication that you have no idea how to use MFC correctly.  So if you need to do
> it, re-examine what you are doing!  When I was clueless about MFC, I once wrote it (some
> time in my first or second MFC program) and was given similar advice.
>
> There is no need to use it.  So don't.
> *****

As you pointed it out - I`m very new to c++ and to mfc: But I`ll learn
this language - and therefore it would be great if you could point it
out why this function (SubclassDlgItem()) is useless? Is it a unsafe
method? Or is it a global function?



> >Version2: create the whole button in the OnInitialUpdate() method
>
> >m_btnMenu1Ok.Create("OK", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
> >CRect(10, 10, 30, 30), this, 1);
>
> ****
> First the CRect is a colossal blunder.  Where in the world did you get the idea that
> 10,10,30,30 could possibly make sense?  Sure, on YOUR machine, with YOUR display, YOUR
> graphics card, YOUR current version of the display driver, YOUR current resolution, and
> YOUR default font size, but unless the program is now and forever going to run on YOUR
> machine and you will never, ever change any one of these settings or components, it cannot
> possibly run correctly anywhere else.  So don't do it.

Thanks for the hint - I didn`t recoginze it.... And 10,10,30,30 was
only a example....

>
> In situations where I have to create buttons dynamically (because the number of buttons is
> based on some only-known-at-run-time set of parameters) I will always create an
> *invisible* button on the dialog, and use it to get the necessary parameters, e.g.,
>
>         CRect r;
>         c_ButtonPrototype.GetWindowRect(&r);
>         ScreenToClient(&r);
>
> This will give me the width and height I need; for positioning, I usually place some
> control on the dialog I can use as a reference point (sometimes an invisible CStatic) and
> use it to determine the top and left of an array of buttons.  I usually separate them by
> some platform-independent computation, like 3 * ::GetSystemMetrics(SM_CXEDGE) or 3 *
> ::GetSystemMetrics(SM_CYEDGE) or some similar computation that will work on every screen,
> every resolution, etc..
>
> Assume that ANY hardwired integer you use for computing position, unless it is a simple
> multiplier or divisor of a runtime-determined value, is erroneous.
>
> For example, to center a button, I will use
>         CRect r;
>         GetClientRect(&r);
>         CRect b;
>         c_OK.GetWindowRect(&b);
>         ScreenToClient(&b);
>         c_OK.SetWindowPos(NULL,  r.Width() / 2 - b.Width() / 2,
>                                     r..Height() / 2 - b.Height() / 2,
>                                     0, 0,
>                                     SWP_NOZORDER | SWP_NOSIZE);
>
> and this will put the button dead center in the dialog.  But if you EVER choose an
> absolute coordinate or size, you are DEAD WRONG.  This includes font sizes.
>
> What is "1" for a control ID?  Did you not mean IDOK?  And what is English-language text,
> and 8-bit text at that, doing in a source program?
>
> OK, a new record.  There are FOUR things wrong with the above line, not the least of which
> is its very existence!
> *****>m_btnMenu1Ok.SetButtonImg(IDB_BTN_IMG_OK, IDB_BTN_IMG_OK_PRESSED);
> >m_btnMenu1Ok.SetFont("Arial",16);
>
> ****
> You should not be deciding either the font or its size!  Why do you think Arial 16 could
> possibly make sense?  Because it sort-of-looks-like what you are seeing?  In exactly which
> version of Windows?  (Did you know that Microsoft has changed the default dialog font
> appearance in every recent version of Windows?  You should not presume your dialog is
> going to run on the same version of the operating system, including service pack, that you
> are using!)
>
> When you create a dialog control explicitly, the best way to set the font is
>         CFont * f = GetFont();
>         ctl.SetFont(f);
> which uses the same font as the dialog, and this font will track OS versions and user
> preferences.  It will look like all the other dialogs the user has, and its size will
> track properly.
> *****>m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_IN, RGB(255,
> >255, 255));
> >m_btnMenu1Ok.SetColor(CImageTextButton::BTNST_COLOR_FG_OUT, RGB(150,
> >150, 150));
>


best regards
Hans
From: Scott McPhillips [MVP] on
"mfc" <mfcprog(a)googlemail.com> wrote in message
news:c7e93683-39b7-4475-9d7d-ba3b215ff228(a)x27g2000yqb.googlegroups.com...
>As you pointed it out - I`m very new to c++ and to mfc: But I`ll learn
>this language - and therefore it would be great if you could point it
>out why this function (SubclassDlgItem()) is useless? Is it a unsafe
>method? Or is it a global function?

SubclassDlgItem() is used by the DDX_Control call to associate the CButton
control member with the button ID. You should use the DDX_Control call
because it is added for you by the wizard when you create a control member
variable. Calling SubclassDlgItem() yourself is redundant, and probably
would cause asserts because the button is already subclassed.

--
Scott McPhillips [VC++ MVP]