|
|
 Prize winner in Competition
"MFC/C++ Sep 2003"
Comments and Discussions
|
|
 |

|
It's awesome~
Easy to use ^^
Thank you
|
|
|
|

|
Hi I tried your code its great.
Im trying to use latest Visual Studio 2008 + MFC Feature Pack.
This allow to make Office 2007 like ribbon tool bar control or Outlook like side bars.
Meet problem with integration of your banner in wizard generated code.
Effect controls partly overdrawn by banner, not shifted to side.
In some cases like BOTTOM banner havent appeared.
Will check more tomorrow more.
|
|
|
|

|
Following Alexander Bischofberger's remark, if one of the characters is outside the range 0 to 255 (and "à" is) - most asian characters would be as well - there is a problem... Hence, I have slightly updated your code so it would cope with real "Unicode" characters.
void CKCSideBannerWnd::DrawTextFields(CDC* pDC, CRect rect)
{
CPoint pt, pt2;
if ( m_hIcon )
DrawBannerIcon(pDC, rect);
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
{
m_lfTitle.lfEscapement = m_lfTitle.lfOrientation =
m_lfCaption.lfEscapement = m_lfCaption.lfOrientation = 900;
pt.x = rect.left + m_szEdgeOffset.cx;
pt.y = rect.bottom - m_szEdgeOffset.cy;
pt2.x = pt.x - m_lfTitle.lfHeight + m_szCaptionOffset.cx;
pt2.y = pt.y - m_szCaptionOffset.cy;
}
else if ( m_uPosFlag & KCSB_ATTACH_RIGHT )
{
m_lfTitle.lfEscapement = m_lfTitle.lfOrientation =
m_lfCaption.lfEscapement = m_lfCaption.lfOrientation = -900;
pt.x = rect.right - m_szEdgeOffset.cx;
pt.y = rect.top + m_szEdgeOffset.cy;
pt2.x = pt.x + m_lfTitle.lfHeight - m_szCaptionOffset.cx;
pt2.y = pt.y + m_szCaptionOffset.cy;
}
else if ( ( m_uPosFlag & KCSB_ATTACH_TOP ) || ( m_uPosFlag & KCSB_ATTACH_BOTTOM ) )
{
m_lfTitle.lfEscapement = m_lfTitle.lfOrientation =
m_lfCaption.lfEscapement = m_lfCaption.lfOrientation = 0;
pt.x = rect.left + m_szEdgeOffset.cx;
pt.y = rect.top + m_szEdgeOffset.cy;
pt2.x = pt.x + m_szCaptionOffset.cx;
pt2.y = pt.y - m_lfTitle.lfHeight + m_szCaptionOffset.cy;
}
int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
CFont nFont, *pOldFont = NULL;
COLORREF oldTxtCol = pDC->SetTextColor(m_colTxtTitle);
nFont.CreateFontIndirect(&m_lfTitle);
pOldFont = pDC->SelectObject(&nFont);
pDC->TextOut(pt.x, pt.y, m_strTitle);
pDC->SelectObject(pOldFont);
nFont.DeleteObject();
pDC->SetTextColor(m_colTxtCaption);
nFont.CreateFontIndirect(&m_lfCaption);
pOldFont = pDC->SelectObject(&nFont);
int nCount = m_strCaption.GetLength(), i, nHeight = 0;
CPoint ptDraw = pt2;
TCHAR ch;
for ( i = 0; i < nCount; i++ )
{
ch = m_strCaption.GetAt(i);
if ( ch == '\r' )
continue;
if ( ch == '\n' )
{
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
{
ptDraw = pt2;
ptDraw.x -= m_lfCaption.lfHeight * (++nHeight);
}
else if ( (m_uPosFlag & KCSB_ATTACH_TOP) || (m_uPosFlag & KCSB_ATTACH_BOTTOM) )
{
ptDraw = pt2;
ptDraw.y -= m_lfCaption.lfHeight * (++nHeight);
}
else if ( (m_uPosFlag & KCSB_ATTACH_RIGHT) )
{
ptDraw = pt2;
ptDraw.x += m_lfCaption.lfHeight * (++nHeight);
}
continue;
}
CString strString = CString((TCHAR) ch);
pDC->TextOut( ptDraw.x, ptDraw.y, strString );
int nThisCharWidth = pDC->GetTextExtent(strString).cx;
int nNextCharWidth=0;
if ( i < nCount-1 )
nNextCharWidth = pDC->GetTextExtent(CString(m_strCaption.GetAt(i+1))).cx;
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
{
ptDraw.y -= nThisCharWidth;
if ( ptDraw.y - nNextCharWidth < rect.top )
{
ptDraw = pt2;
ptDraw.x -= m_lfCaption.lfHeight * (++nHeight);
}
}
else if ( (m_uPosFlag & KCSB_ATTACH_TOP) || (m_uPosFlag & KCSB_ATTACH_BOTTOM) )
{
ptDraw.x += nThisCharWidth;
if ( ptDraw.x + nNextCharWidth > rect.right )
{
ptDraw = pt2;
ptDraw.y -= m_lfCaption.lfHeight * (++nHeight);
}
}
else if ( (m_uPosFlag & KCSB_ATTACH_RIGHT) )
{
ptDraw.y += nThisCharWidth;
if ( ptDraw.y + nNextCharWidth > rect.bottom )
{
ptDraw = pt2;
ptDraw.x += m_lfCaption.lfHeight * (++nHeight);
}
}
}
pDC->SelectObject(pOldFont);
nFont.DeleteObject();
pDC->SetBkMode(nOldBkMode);
pDC->SetTextColor(oldTxtCol);
}
I had already voted 5 to your article long ago... it's a beautiful control! thanks for sharing!
|
|
|
|

|
I've tested your class into a CPropertySheet/CPropertyPage, but I've found some trouble.
I've used IsKindOf() to test for CPropertyPage and in this case I've resized the parent (CPropertySheet), but the internal painted area remain the same and the problem is also (in case of _TOP) to move button (easy) and the bottom line (I've found no solution). Probably also the object into CPropertySheet must be enumerated and moved.
Does anyone has a solution ?
TIA
|
|
|
|

|
Hello
The Caption and Title both disapear if I specify #pragma pack (1)!
I thought id let you know.
Thanks for a great control
Andy
|
|
|
|

|
:(Did you try to use it with CMainFrame? I've tried to use it and it did not look good. What should I do in order to have support of you great class in CFrameWnd-derived classes like CMainFrame?
|
|
|
|

|
Hello peter,
Firstly, congratulation for your award !
About the "points of interest" in your article, I fall down the same problem in one of my software. I had write a CDialog derived class that "center" or "adjust" all the control in the runtime size of the dialog. The idea is to compute the size of the dialog box in proportion of the screen size, and to center all the control from their orignal position, or to adjust them (change their size in proportion of the original dialog size and the runtime screen size).
I found the same problem for combo, and the same solution (perhaps I will take more time to read and write the MFC forums...) !
The center function work well, but the adjust not, because of the size of the combo doesn't change. As you have work on a similar problem, have you encountered something like that, and found a solution ?
Regards
D. TRECHE
|
|
|
|
|

|
I'm modied the "DrawTextFields" member like this .
....
pDC->SetTextColor(m_colTxtCaption);
nFont.CreateFontIndirect(&m_lfCaption);
pOldFont = pDC->SelectObject(&nFont);
// int arrWidths[256];
// pDC->GetCharWidth(0, 255, arrWidths);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
LONG lWidth = tm.tmAveCharWidth;
int nCount = m_strCaption.GetLength(), i, nHeight = 0;
CPoint ptDraw = pt2;
TCHAR ch;
TCHAR temp[3];
int add =1;
for ( i = 0; i < nCount; i+=add )
{
ch = m_strCaption.GetAt(i);
if ( ch == '\r' )
continue;
if ( ch == '\n' )
{
if ( m_uPosFlag & TDBE_ATTACH_LEFT )
{
ptDraw = pt2;
ptDraw.x -= m_lfCaption.lfHeight * (++nHeight);
}
else if ( (m_uPosFlag & TDBE_ATTACH_TOP) || (m_uPosFlag & TDBE_ATTACH_BOTTOM) )
{
ptDraw = pt2;
ptDraw.y -= m_lfCaption.lfHeight * (++nHeight);
}
else if ( (m_uPosFlag & TDBE_ATTACH_RIGHT) )
{
ptDraw = pt2;
ptDraw.x += m_lfCaption.lfHeight * (++nHeight);
}
continue;
}
if (ch & 0x80)
{
temp[0] = ch;
temp[1] = m_strCaption.GetAt(i+1);
temp[2] ='\0';
::TextOut(pDC->GetSafeHdc(),ptDraw.x,ptDraw.y,temp,2);
add =2;
}
else
{
temp[0] = ch;
temp[1] ='\0';
::TextOut(pDC->GetSafeHdc(),ptDraw.x,ptDraw.y,temp,1);
add =1;
}
//pDC->TextOut( ptDraw.x, ptDraw.y, m_strCaption );
if ( m_uPosFlag & TDBE_ATTACH_LEFT )
{
ptDraw.y -= lWidth*add;// arrWidths[ch];
if ( (i < nCount-1) &&
// ptDraw.y - arrWidths[m_strCaption.GetAt(i+1)] < rect.top )
ptDraw.y - lWidth*add < rect.top )
{
ptDraw = pt2;
ptDraw.x -= m_lfCaption.lfHeight * (++nHeight);
}
}
else if ( (m_uPosFlag & TDBE_ATTACH_TOP) || (m_uPosFlag & TDBE_ATTACH_BOTTOM) )
{
ptDraw.x +=lWidth*add;// arrWidths[ch];
if ( (i < nCount-1) &&
//ptDraw.x + arrWidths[m_strCaption.GetAt(i+1)] > rect.right )
ptDraw.x + lWidth*add > rect.right )
{
ptDraw = pt2;
ptDraw.y -= m_lfCaption.lfHeight * (++nHeight);
}
}
else if ( (m_uPosFlag & TDBE_ATTACH_RIGHT) )
{
ptDraw.y += lWidth*add;// arrWidths[ch];
if ( (i < nCount-1) &&
//ptDraw.y + arrWidths[m_strCaption.GetAt(i+1)] > rect.bottom )
ptDraw.y + lWidth*add > rect.bottom )
{
ptDraw = pt2;
ptDraw.x += m_lfCaption.lfHeight * (++nHeight);
}
}
}
pDC->SelectObject(pOldFont);
nFont.DeleteObject();
pDC->SetBkMode(nOldBkMode);
pDC->SetTextColor(oldTxtCol);
|
|
|
|
|

|
Using the control in dialogs requires a lot of initialisation e.g. setting texts and icon. To reduce the code needed for each dialog I wrote the following function to set up the control - perhaps it helps you using this great control:
void SetupSidebannerWnd(CWnd* pWnd, CKCSideBannerWnd* pWndBanner, UINT uiDlgID)
{
ASSERT(pWnd);
ASSERT(pWndBanner);
if (!pWnd) return;
if (!pWndBanner) return;
pWndBanner->Attach(pWnd, KCSB_ATTACH_TOP);
HICON hIcon = AfxGetApp()->LoadIcon(uiDlgID);
if (hIcon)
pWndBanner->SetIcon(hIcon);
pWndBanner->SetIconPos(KCSB_ICON_LEFT|KCSB_ICON_VCENTER);
CString strTitle(MAKEINTRESOURCE(uiDlgID));
CString strTop;
CString strSub;
AfxExtractSubString(strTop, strTitle, 0, '|');
AfxExtractSubString(strSub, strTitle, 1, '|');
pWndBanner->SetTitle(strTop);
pWndBanner->SetCaption(strSub);
}
To use it in your dialog simply add the following call to your OnInitDialog():
SetupSidebannerWnd(this, &m_wndBanner, IDD);
(assuming that m_wndBanner is the banner window).
Now add a string "Title|Caption" to your resource with the same ID as the dialog and an icon also using this ID. That's it!
Ciao,
Alex
|
|
|
|

|
Thanks for this nice control!
I just wanted to put it to my project (which has also a German UI) and figured out some problems with the German characters ÄÖÜäöüß and even € (EUR). It seems that CDC::GetCharWidth() return bad values for these characters. My only solution is to replace the arrWidths[] entries for äö... with the corresponding values of ao...
Do you have any better solution?
Ciao,
Alex
|
|
|
|

|
do you need a hwnd at all? if i was to make such a banner i would make a class that attaches to a certain hwnd (a dialog or whatever) and then subclasses it. next i would intercept WM_NCCALCSIZE, remember currently calculated rect (after caption and borders) and modify it to make some room for the banner. another interesting message would be WM_NCPAINT where i can use the rect from WM_NCCALCSIZE and the attached hwnd to get a window dc and paint directly. benefits: no hacks with moving controls around -- suppose the developer actually does move some controls at fixed locations. in your case he/she will need to fix the positioning code. in the proposed case only the hwnd client size will be affect and control positions on the hwnd basicly remain the same (although space is still somewhat reduced). just my $.02 worth before downloading the code ) cheers, </wqw>
|
|
|
|

|
Hi everyone,
I've added the UNICODE fix that was mentioned in the thread below this one. Sorry about that! Atleast its done now. This will probably be the last update unless someone (or I) have a great idea of how to improve this control some more...
www.kinkycode.com
[Glossary Manager] [AfterThought Backup Lite]
99 little bugs in the code, 99 little bugs,
Fix 1 bug, recompile....
101 little bugs in the code...
|
|
|
|

|
I really hate to tell you this, especially since you just updated the article.... but.....
The call in the CKCSideBannerWnd constructor, to load the msimg32.dll needs to be wrapped in the _T("") macro.
// try and load the MSIMG32.LIB
if ( (m_hGradMod = LoadLibrary(_T("MSIMG32.DLL"))) )
m_pGradFill = (PFNGRADFILL) GetProcAddress(m_hGradMod, "GradientFill" );
At least *I* had to, to get my unicode build to quit whining.....
Artificial intelligence is no match for natural
stupidity.
|
|
|
|
|

|
hi,
I tried to compile the demo projet and I have execution error "can't find MSGIM32.dll".
I scanned my disk, I found MSGIM32.lib.
I use VC++ 6.0 and NT 4.0.
I'd like to link statically the MSGIM32.
Can you help me ?
|
|
|
|

|
Hi everyone,
I've updated the control to include most of the suggestions and tips that have been so kindly communicated to me. I must admit, my favourite change is the ability to texture the control
Take care and hope you enjoy it!
www.kinkycode.com
[Glossary Manager] [AfterThought Backup Lite]
99 little bugs in the code, 99 little bugs,
Fix 1 bug, recompile....
101 little bugs in the code...
|
|
|
|

|
Nice job !
A few minor changes are necessary to make your control UNICODE compatible:
1) enclose the rest of the string literals with _T("") including the definition of KCSB_CLASSNAME
2) change the paramters to the SetTitle and SetCaption functions from const char* to LPCTSTR
3) change the variable on line 541 of the cpp file from BYTE ch; to TCHAR ch;
|
|
|
|

|
Thank you very much, I really need it in my projects!
Got my 5!
Because I was trying different icon sizes, I made 2 small modifications for my use that I'll like to share:
1. to load the icon directly from the resource ID I have added the member:
bool CKCSideBannerWnd::SetIcon(UINT uIcon, UINT uiIconPos)
{
HICON hIcon = (HICON)::LoadImage(
AfxGetInstanceHandle(), // app instance
MAKEINTRESOURCE(uIcon), // resource ID
IMAGE_ICON, // type of image
0,0, // desired size (0 = current)
LR_DEFAULTCOLOR); // load flags
// call the original method
return SetIcon(hIcon, uiIconPos);
}
2. to ensure the correct icon drawn size, I made a small replacement at the end of the DrawIncon call:
... DrawIcon(...)
{
...
}
pDC->DrawState(
pt,
CSize(m_bmpInfo.bmWidth, m_bmpInfo.bmHeight),
m_hIcon,
DSS_NORMAL, (HBRUSH)NULL);
}
|
|
|
|

|
Nice article there goes my 5.
A little issue though, can we change color of title and caption texts (without modifying your source code)? Texts became unreadable when I tried to use a dark backgroud. Also, since we are at it, will you consider bitmap backgroud?
And out of curious, why don't you just integrate WndUtil.h into KCSideBannerWnd.h so we only need to maintain 2 files instead of 3? Of course, if you are reusing WndUtil.h in multiple applications then forget about it.
Thanks.
|
|
|
|

|
From your article:
Personally, I have never written a control that "makes space" for itself, and the concept has grasped my imagination somewhat. I have been contemplating the idea of developing a background app/service that monitors all HWND creations and attaches a banner to all windows of say, type DIALOG. This would merely be for purposes of fun and educational value... but still a cool idea I think.
Well ... not shure about how and if it can be useful, however, an idea can be to hook the WH_CALLWNDPROC and trap the WM_INITDIALOG message.
This article can give some ideas. It is not necessary to use exactly that code. But the principle could be right.
Of course, in that article I was thinking to applications, not to "services" that do the trick to ll the windows every other would have created. But the idea is essentially the same.
Let me know. By now, get my 5 !
-E-
|
|
|
|

|
Russian text output in caption in bad order. Then you get char fron string
ch = m_strCaption.GetAt(i);
if char code > 127 it appears as negative number
in void CKCSideBannerWnd::DrawTextFields(CDC* pDC, CRect rect)
replace
int ch;
with
BYTE ch;
|
|
|
|

|
The edit control is actually a child of the combobox (ID = 1001). The reason it is returned in your ChildEnumProc is that EnumChildWindows will enumerate all the child windows of the given window, and all the children of the child windows, for as many generations as it takes to enumerate them all. The reason it does not find the list portion of the combobox is because the list box is actually a child of the desktop.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|

|
Nice Work! it does add a nice professional look!!!
1) Add:
#pragma comment(lib, "MSIMG32.LIB")
to the file that needs it (for the Gradient Fill)
so the library gets linked, but the project settings don't have to be changed.
You could also add an optional DEFINE that would exclude
this functionality, in case people don't want to link to this library ???
2)Change the download:
a) Add example .exe file to the download
b) Delete large files that aren't needed to re-build the project (eg. the .ncb file)
to save CP bandwidth.
Warren
|
|
|
|

|
Great class.
Ive been looking for something similar which could be placed above a view (similar to Windows Explorer).
|
|
|
|

|
Excellent idea!
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|

|
...to say why not use static control with a image set, but then I show some of the functions which make it a viable option over a static control.
Good!
|
|
|
|

|
One of possible usages could be displaying of some help/quick tip on dialog usage. Good color filling would be COLOR_INFOBK. This brings possible improvement - good looking button in the banner to hide it
Igor Green
Compare It! - file compare and merge tool with syntax highlighting.
|
|
|
|

|
Hi there,
Nice control, though vertical text isn't very readable. Maybe implementing the control horizontally like in many installers and apps (noticeably in Eclipse platform) should give that nifty "professional looking feel" to most windows and also providing useful information to the user.
Cheers,
Rui
is this a sig?
|
|
|
|

|
After reading the article, I've found myself mentally going through all my software to think where I
can implement it.
Iain: "OOOO. New shiny thing. Must implement."
Now if it worked with Property sheet wizards...!
Go on, you know you want to. As sheer bribery, I'll reserve my voting until after you pander to me.
Congrats,
Iain.
|
|
|
|

|
Very cool.
Maybe it's not useful to have it in larger applications (can't imagine you want this in all of your windows), but it could be nice to have in small, dialog-based, applications.
Great, that's a 5 from me.
Enjoy life, this is not a rehearsal !!!
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
A CWnd-derived control that can attach itself to any window, without the programmer making provisions for it
| Type | Article |
| Licence | CPOL |
| First Posted | 21 Oct 2003 |
| Views | 191,143 |
| Downloads | 1,870 |
| Bookmarked | 130 times |
|
|