From: Oliver Regenfelder on
Hello,

Lets first state the problem I need to solve:

Our application has a protocol debug view, which graphically displays
the last round of some UHF reader commands done in a device attached
via a serial port (some UHF reader). This display consists of several
rows (one per time slot) and each row has severl columns (for the
various actions done in this time slot). Depending on what happened
the column fields in each row get different colors and text.

Originally this was done by placine a lot of static labels on the dialod
and just changing their text and foreground/background color. So to have
a cell painted green you would set background to green and write a lot
of spaces into it... obviously no good idea.

I changed this to do all the painting in the OnPaint handler taking the
grid dimensions from some constants defined in the class. And I get the
protocol information in some abstract format which is parsed by the
painting code to decide for each cell of the grid how to paint it.

This works nicely. But now I have to integrate scrolling as sometimes
the output has more rows than can be displayed in the dialog (dialog
based app), and it is impossible to change the dialogs dimensions.


So, as far as I understand it I would have to solve it as follows:

1) Develop my own control which displays protocol information. This
would be derived from CWnd and handle scroll bar messages from an
attached scrollbar - I think I know how to do this and there is a
lot of information on that.

2) Place a custom control in the dialog editor and attach it to my
own developed control class.

An I correct, or are there better ways?


Seccond question: Right now the painting is done in a CDialog derived
class and I use MapDialogRect to map the grid dimensions in dialog box
units into the pixels to paint. I do this to thave the protocol display
change accordingly if the dialogs base font is changed.

But for a control it would be more natural to derive it from CWnd, I
thought. So, how can I access the dialog box units of the dialog the
CWnd is embedded in, to do this conversions nicely?


Best regards,

Oliver
From: David Lowndes on
>So, as far as I understand it I would have to solve it as follows:
>
>1) Develop my own control which displays protocol information. This
>would be derived from CWnd and handle scroll bar messages from an
>attached scrollbar - I think I know how to do this and there is a
>lot of information on that.
>
>2) Place a custom control in the dialog editor and attach it to my
>own developed control class.

From what you've said, I'd say that you'd do best to use a grid
control. I believe there are a few decent free one's available online.

>Seccond question: Right now the painting is done in a CDialog derived
>class and I use MapDialogRect to map the grid dimensions in dialog box
>units into the pixels to paint. I do this to thave the protocol display
>change accordingly if the dialogs base font is changed.
>
>But for a control it would be more natural to derive it from CWnd, I
>thought. So, how can I access the dialog box units of the dialog the
>CWnd is embedded in, to do this conversions nicely?

Presumably you'd only need to map the bounding rectangle of the window
from dialog units to pixels, once you're dealing with things inside
your own window, everything would be pixels (assuming you're using the
default mapping mode).

Dave
From: Joseph M. Newcomer on
See below...
On Wed, 12 May 2010 13:33:17 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Hello,
>
>Lets first state the problem I need to solve:
>
>Our application has a protocol debug view, which graphically displays
>the last round of some UHF reader commands done in a device attached
>via a serial port (some UHF reader). This display consists of several
>rows (one per time slot) and each row has severl columns (for the
>various actions done in this time slot). Depending on what happened
>the column fields in each row get different colors and text.
>
>Originally this was done by placine a lot of static labels on the dialod
>and just changing their text and foreground/background color. So to have
>a cell painted green you would set background to green and write a lot
>of spaces into it... obviously no good idea.
>
>I changed this to do all the painting in the OnPaint handler taking the
>grid dimensions from some constants defined in the class. And I get the
>protocol information in some abstract format which is parsed by the
>painting code to decide for each cell of the grid how to paint it.
****
Sounds like a good idea
****
>
>This works nicely. But now I have to integrate scrolling as sometimes
>the output has more rows than can be displayed in the dialog (dialog
>based app), and it is impossible to change the dialogs dimensions.
****
Not an uncommon problem.
****
>
>
>So, as far as I understand it I would have to solve it as follows:
>
>1) Develop my own control which displays protocol information. This
>would be derived from CWnd and handle scroll bar messages from an
>attached scrollbar - I think I know how to do this and there is a
>lot of information on that.
****
Note that what you might mean by "attached scrollbar" is what we would mean by "a
scrollbar created by the WS_HSCROLL or WS_VSCROLL styles", and which is part of the
window.
****
>
>2) Place a custom control in the dialog editor and attach it to my
>own developed control class.
***
There are a couple approaches here. Putting the custom control in the dialog is a real
pain because of the weakness of the dialog editor, so I tend to avoid doing this. My
alternative is to create a CStatic with the control ID I want, and execute the following
code in my OnInitDialog handler, where c_MyStatic is bound to the static control that
tells me where to put my custom control, e.g., in the .h file I have:
CStatic c_MyStatic;
CMyCustomControl c_MyCustomControl;

CRect r;
c_MyStatic;GetWindowRect(&r);
ScreenToClient(&r);
c_MyCustomControl.Create(r, c_MyStatic.GetDlgCtrlId());
c_MyCustomControl.SetWindowPos(&c_MyStatic, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
c_MyStatic.DestroyWindow();

My Create method creates a window and has the prototype
int CMyCustomControl::Create(const CRect & r, UINT id)

and creates the window.

Note I have not illustrated appropriate error tests and recovery to simplify the code
example. These are left as an Exercise For The Reader.
****
>
>An I correct, or are there better ways?
>
>
>Seccond question: Right now the painting is done in a CDialog derived
>class and I use MapDialogRect to map the grid dimensions in dialog box
>units into the pixels to paint. I do this to thave the protocol display
>change accordingly if the dialogs base font is changed.
****
I have been programming Windows since 1990. One thing I learned in the first two years:
NEVER use DBUs in real code. There is no need for MapDialogRect or anything else even
vaguely resembling it. Work entirely in pixels. Because the dialog box size changes, the
CStatic I used in my example changes, and your custom window if you used the custom window
capabilities of the dialog editor changes, so the sizes are always adjusted, and at
runtime you simply have a dimension in pixels, Work with what you have. There is no
reason to ever think in DBUs.
****
>
>But for a control it would be more natural to derive it from CWnd, I
>thought. So, how can I access the dialog box units of the dialog the
>CWnd is embedded in, to do this conversions nicely?
****
I do not understand why DBUs are important at all here. You have dimensions in pixels;
your font has dimensions in pixels; no DBUs are required.

Why do you think you need DBUs or MapDialogRect at all?
joe
****
>
>
>Best regards,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Oliver Regenfelder on
Hello,

Joseph M. Newcomer wrote:
> Note that what you might mean by "attached scrollbar" is what we would mean by "a
> scrollbar created by the WS_HSCROLL or WS_VSCROLL styles", and which is part of the
> window.

Yes that is what I meant - and did.

>> 2) Place a custom control in the dialog editor and attach it to my
>> own developed control class.
> ***
> There are a couple approaches here. Putting the custom control in the dialog is a real
> pain because of the weakness of the dialog editor, so I tend to avoid doing this. My
> alternative is to create a CStatic with the control ID I want, and execute the following
> code in my OnInitDialog handler, where c_MyStatic is bound to the static control that
> tells me where to put my custom control, e.g., in the .h file I have:
> CStatic c_MyStatic;
> CMyCustomControl c_MyCustomControl;
>
> CRect r;
> c_MyStatic;GetWindowRect(&r);
> ScreenToClient(&r);
> c_MyCustomControl.Create(r, c_MyStatic.GetDlgCtrlId());
> c_MyCustomControl.SetWindowPos(&c_MyStatic, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
> c_MyStatic.DestroyWindow();
>
> My Create method creates a window and has the prototype
> int CMyCustomControl::Create(const CRect & r, UINT id)
>
> and creates the window.

That looks like a good idea. Right now I just created the new control in
the OnInitDialog an placed it by some values (defined in the class). But
this way the control doesn't show up in the resource file and resource
editor. Your way seems to make it easier to adapt its position later.

> I have been programming Windows since 1990. One thing I learned in the first two years:
> NEVER use DBUs in real code. There is no need for MapDialogRect or anything else even
> vaguely resembling it. Work entirely in pixels. Because the dialog box size changes, the
> CStatic I used in my example changes, and your custom window if you used the custom window
> capabilities of the dialog editor changes, so the sizes are always adjusted, and at
> runtime you simply have a dimension in pixels, Work with what you have. There is no
> reason to ever think in DBUs.

With your approach I can get rid of the DBUs for placing the window.
They are then only used in the .rc file. I thought I needed the DBUs to
scale the grid according to the selected dialog font. So in case this
gets ever changed the control still works.

> I do not understand why DBUs are important at all here. You have dimensions in pixels;
> your font has dimensions in pixels; no DBUs are required.

Ok. I will have a look.

> Why do you think you need DBUs or MapDialogRect at all?

Well I just read the vista user interface guidelines and that might
have me influenced into thinking all DBUs. The Idea was to specify
the grid in terms of DBUs and then calculate grid sizes based on
the current font. Another reason for that was that the original grid
used a bunch of CStatic labels and was therefore defined in terms of
DBUs. But I do not need to stick with the old way when I am redoing
it. So I might not need DBUs but what I would like to have is, that
the display scales with the Font of the Dialog.

Best regards,

Oliver
From: Joseph M. Newcomer on
See below..
On Thu, 13 May 2010 18:19:33 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Hello,
>
>Joseph M. Newcomer wrote:
>> Note that what you might mean by "attached scrollbar" is what we would mean by "a
>> scrollbar created by the WS_HSCROLL or WS_VSCROLL styles", and which is part of the
>> window.
>
>Yes that is what I meant - and did.
***
That's what I thought, but there was always the possibility that you had created a
separate CScrollBar control (some people do!) so I had to make sure we were talking about
the same thing.
****
>
>>> 2) Place a custom control in the dialog editor and attach it to my
>>> own developed control class.
>> ***
>> There are a couple approaches here. Putting the custom control in the dialog is a real
>> pain because of the weakness of the dialog editor, so I tend to avoid doing this. My
>> alternative is to create a CStatic with the control ID I want, and execute the following
>> code in my OnInitDialog handler, where c_MyStatic is bound to the static control that
>> tells me where to put my custom control, e.g., in the .h file I have:
>> CStatic c_MyStatic;
>> CMyCustomControl c_MyCustomControl;
>>
>> CRect r;
>> c_MyStatic;GetWindowRect(&r);
>> ScreenToClient(&r);
>> c_MyCustomControl.Create(r, c_MyStatic.GetDlgCtrlId());
>> c_MyCustomControl.SetWindowPos(&c_MyStatic, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
>> c_MyStatic.DestroyWindow();
>>
>> My Create method creates a window and has the prototype
>> int CMyCustomControl::Create(const CRect & r, UINT id)
>>
>> and creates the window.
>
>That looks like a good idea. Right now I just created the new control in
>the OnInitDialog an placed it by some values (defined in the class). But
>this way the control doesn't show up in the resource file and resource
>editor. Your way seems to make it easier to adapt its position later.
>
>> I have been programming Windows since 1990. One thing I learned in the first two years:
>> NEVER use DBUs in real code. There is no need for MapDialogRect or anything else even
>> vaguely resembling it. Work entirely in pixels. Because the dialog box size changes, the
>> CStatic I used in my example changes, and your custom window if you used the custom window
>> capabilities of the dialog editor changes, so the sizes are always adjusted, and at
>> runtime you simply have a dimension in pixels, Work with what you have. There is no
>> reason to ever think in DBUs.
>
>With your approach I can get rid of the DBUs for placing the window.
>They are then only used in the .rc file. I thought I needed the DBUs to
>scale the grid according to the selected dialog font. So in case this
>gets ever changed the control still works.
****
Some years ago, I realized that the secret of being a succe3ssful programmer is one of
those things we are always told is a Bad Thing: pure laziness! When I tried to use DBUs,
I had to *work*, and the results weren't always what were expected. Once I relized I
could getbetter effects with less work, I went that direction. In generaly, I try to find
the "lazy" solution to a problem, because it is usually simpler.

So I let the dialog system resize my static frame in accordance with its built-in rules,
so I don't have to simulate them, then I just use the results. In general, I try to reuse
existing mechanisms instead of trying to simulate them. Laziness will buy you a lot of
leverage.
****
>
>> I do not understand why DBUs are important at all here. You have dimensions in pixels;
>> your font has dimensions in pixels; no DBUs are required.
>
>Ok. I will have a look.
***
GetClientRect will be important; it already compensates for the scroll bars you might
have.
****
>
>> Why do you think you need DBUs or MapDialogRect at all?
>
>Well I just read the vista user interface guidelines and that might
>have me influenced into thinking all DBUs. The Idea was to specify
>the grid in terms of DBUs and then calculate grid sizes based on
>the current font. Another reason for that was that the original grid
>used a bunch of CStatic labels and was therefore defined in terms of
>DBUs. But I do not need to stick with the old way when I am redoing
>it. So I might not need DBUs but what I would like to have is, that
>the display scales with the Font of the Dialog.

****
As I said, my "lazy" approach means I let someone else worry about DBUs, and just use
their result. The more you can rely on just pixels, the less work you have to use complex
conversions.

Note the use of the SetWindowPos to get the Z-order correct, so the control has the right
tab position. That was one of the fine points of the trick.
joe
****
>
>Best regards,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm