|
Sorry forgot to add, I'm using your 22nd Nov code. Is there a release newer than this?
Hari
|
|
|
|
|
Hariharan Mahadevan wrote:
Sorry forgot to add, I'm using your 22nd Nov code. Is there a release newer than this?
I hopefully within the month will be updating the site with new code.
-Daniel
|
|
|
|
|
Hariharan Mahadevan wrote:
Just a quick bug report. Tried to compile the code using VS.NET 2003 and line 2765 of customtabctrl.h gives an error. The code is shown below.
int FindItem(TItem* pFindItem, TItem::FieldFlags eFlags, int nStart = -1) const
VC reports this as syntax error C2061:identifier 'FieldFlags'.
Thanks.
Until I can post an update (and get to a couple backlogged requests), here's how you can update the code to work with VS.NET 2003:
CustomTabCtrl.h
- Just after the declaration of
class ATL_NO_VTABLE CCustomTabCtrl ... replace the line
typedef TItem TItem; with the line
typedef typename TItem TItem; - Replace
int FindItem(TItem* pFindItem, TItem::FieldFlags eFlags, int nStart = -1) const with
int FindItem(TItem* pFindItem, typename TItem::FieldFlags eFlags, int nStart = -1) const
TabbedMDI.h
- Just after the declaration of
class ATL_NO_VTABLE CTabbedMDIFrameWindowImpl ... replace the lines
typedef TClient TClient;
typedef TClient::TTabCtrl TTabCtrl;
with the lines
typedef typename TClient TClient;
typedef typename TClient::TTabCtrl TTabCtrl;
- Just after the declaration of
class CMDITabOwner ... replace the lines
typedef TTabCtrl TTabCtrl;
with the lines
typedef typename TTabCtrl TTabCtrl;
- Just after the declaration of
class CTabbedMDIClient ... replace the lines
typedef TTabCtrl TTabCtrl;
typedef TTabOwner TTabOwner;
with the lines
typedef typename TTabCtrl TTabCtrl;
typedef typename TTabOwner TTabOwner;
-Daniel
|
|
|
|
|
Tks very much. Just when I thought your code was great, your support seems to be even better!!
Best regards
Hari
|
|
|
|
|
I try to use the CPaneTreeView as in the TabbedSDISplitter example, but having trouble with notifications. The CLeftPaneTreeView's parent is splitter ( m_paneTree.Create(m_splitter, _T("Tree")) - does it mean that all notifications go there? How do I get the TVN_SELCHANGED - there is no message map for the splitter. It seems to me that in the example there is some attempt to get it - commented statement NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnSelChanged); However, if I uncomment it, nothing happens and TVN_SELCHANGED still don't come.
Please help.
|
|
|
|
|
Sorry for not responding earlier, I hadn't gotten an e-mail notifying about your post.
Vladimir G. Ivanov wrote:
I try to use the CPaneTreeView as in the TabbedSDISplitter example, but having trouble with notifications. The CLeftPaneTreeView's parent is splitter ( m_paneTree.Create(m_splitter, _T("Tree")) - does it mean that all notifications go there?
Yes, notifications of a tree view (SysTreeView32) go to the parent window. In the TabbedSDISplitter sample, the direct parent of the tree view window is a CPaneContainer window. The parent window of the pane container is a CSplitterWindow window. The parent of the splitter is the main frame. If you look in the message map of both CPaneContainer and CSplitterWindow (the message maps are in their base classes), you'll see that they have FORWARD_NOTIFICATIONS() . This means that the tree view notifications will go to the pane container, get forwarded to the splitter, and the splitter will forward them to the main frame.
You're right in that in the sample, it doesn't work if you uncomment the REFLECTED_NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnSelChanged) in CLeftPaneTreeView as it currently is. To make it work, you need the parent, or someone else receiving the forwarded notifications to reflect the notifications back to the source window.
There are multiple ways to accomplish this, but here are two:
- Add
REFLECT_NOTIFICATIONS() at the end of the main frame's message map. This might be risky because you'll be reflecting notifications for more than just the tree view, and a window might not be prepared to receive reflected notifications (DEFAULT_REFLECTION_HANDLER ). - If you are using ATL 7 or higher, have
CLeftPaneTreeView inherit from CWindowWithReflectorImpl instead of CWindowImpl . You can look at the code and make your own CWindowWithReflectorImpl if you can't use ATL 7. Essentially, there will be a new intermediate window that will be the direct parent of the tree view, and will reflect notifications back. The intermediate window will be the direct child of the pane.
HTH,
-Daniel
|
|
|
|
|
Hi Daniel !
I'm very new in WTL programming and can't find what is wrong with my app. Pleeeeeeeease help !!!
In Your Docking demo example I put CListViewCtrl enstead of CPlainTextView and trying to get notify messages such as NM_RCLICK in the MainFrame message map. The messages seems not coming thru. If I try to catch them in class derivied from CListViewCtrl, I get the same result. So please please can U help me? If there a way to catch them in main frame it will be perfect...
Thanx
|
|
|
|
|
Notifications go to the window parent (from a windows hierarchy point of view). The main frame isn't your direct parent.
If you want the list view as an MDI child, then try creating an out of the box WTL MDI app, and choose the list view as the view type. You'll get a "frame" class, and the view itself. The frame class will be the direct parent of the list view in that case. You can then handle the notifications in the frame using NOTIFY_CODE_HANDLER and the like. Or have the frame reflect the notifications back to the list view (REFLECT_NOTIFICATIONS), and use REFLECTED_NOTIFY_CODE_HANDLER to handle the notifications, and also have DEFAULT_REFLECTION_HANDLER at the end of the list view's message map.
If you want the list view as a docked window, then you need to use the option to tell the pane window "frame" to reflect notifications (see the SetPaneView call), then handle things like above with REFLECTED_NOTIFY_CODE_HANDLER and DEFAULT_REFLECTION_HANDLER.
-Daniel
|
|
|
|
|
Thank you Daniel for the answer, but I didn't make it to work.
So if I understand it right in DockingDemo the member m_OutputFrame in MainFrame is a parent to CPlainTextView (CListViewCtrl in my case) members:
m_TaskListView.Create(m_OutputFrame, rcDefault, NULL, ...);
m_OutputFrame must reflect notifications and we must call something like
m_OutputFrame.SetReflectNotifications(true); somewhere after creation of m_OutputFrame. Right?
The CListViewCtrl class is derivied from CWindow, not CWindowImplRoot where DefaultReflectionHandler is. So DEFAULT_REFLECTION_HANDLER() will fail to compile if we put it in CListViewCtrl. Do I have to create a new one in my class?
If I compile without DEFAULT_REFLECTION_HANDLER(), like this:
BEGIN_MSG_MAP(MyListView)
char b[100];
sprintf(b, "%d", uMsg);
::MessageBox(0,b,"",0);
END_MSG_MAP()
...still no messages or notifications
If you want the list view as a docked window, then you need to use the option to tell the pane window "frame" to reflect notifications (see the SetPaneView call), then handle things like above with REFLECTED_NOTIFY_CODE_HANDLER and DEFAULT_REFLECTION_HANDLER.
I couldn't find SetPaneView functions anywhere (maybe it doesn't metter, because I just want it work like I described above).
|
|
|
|
|
It's working now !!!
My problem was in derivieding of CListViewCtrl, I had the following:
class MyListView : public CListViewCtrl // derivied from CWindow
{ ... }
after I derivied from CWindowImpl instead, it gets work:
class MyListView : public CWindowImpl<MyListView, CListViewCtrl>
Thank you Daniel, without You my app maybe never would see the light
|
|
|
|
|
How do MFC Porject(MDI or SDI) link ?
|
|
|
|
|
I noticed the other day that in Visual Studio.NET I can move the tab order around simply by dragging tabs along the bar. This is cool - and now I've noticed it I feel like I have to have it in my own app (along with the moon on a stick!) Have you ever implemented this, and if not what would be your estimate as to how complex it would be to do?
Also, while I'm here, I'm wondering if you could provide any insight on this problem: Having been working in VS.NET for a while I got used to the (seemingly really clever) tab-order management:
Select window 4.
Select window 2.
Ctrl-tab takes you to window 4. Release Ctrl.
Ctrl-tab takes you to window 2. Release Ctrl.
Ctrl-tab takes you to window 4.... and so on.
They basically seem to store a history of your last visited tabs and work through them in that order - instead of the seemingly barking mad order that the basic MDI framework provides you with.
Have you seen any neat code to solve this problem - perhaps a nice generic way or even better a method fitted into a lovely tab control MDI child manager <cheeky-grin>?
thanks in advance,
--
Simon Steele
Programmers Notepad - http://www.pnotepad.org/
|
|
|
|
|
Simon Steele wrote:
I noticed the other day that in Visual Studio.NET I can move the tab order around simply by dragging tabs along the bar. This is cool - and now I've noticed it I feel like I have to have it in my own app (along with the moon on a stick!) Have you ever implemented this, and if not what would be your estimate as to how complex it would be to do?
This has always been on my TODO list. You've probably already seen it, but Sergey Klimov has a general docking window approach that now supports grouping docked windows with tabs and dragging tabs around (just for docked windows though, not for MDI tabs) - http://www.codeproject.com/wtl/wtldockingwindows.asp. He even uses my tab stuff (that I helped him integrate)
I have an example of using his docking windows and my tab stuff in the "DockingDemo" that comes with the samples to this article. If you run the EXE I provided, you should see the functionality of dragging tabs around of docked windows, and docking them elsewhere even. You'll have some problems compiling the code with Sergey's current public release though, because in my samples, I didn't provide the version of his code with my suggestions and bug-fixes that I sent him a while back that "DockingDemo" depends on (that he hasn't officially released yet).
One thing that is still on my TODO list however is dragging MDI tabs around. This functionality doesn't really come with (or belong in) the docking window stuff. Dragging MDI tabs around might not make it into my next update, but I'll try to get it in there if I can.
Note that I also have several other minor updates to the tab stuff that will be in an upcoming update. I can't really say when exactly I'll have my next update of the tab stuff ready, because of some other looming deadlines, but I hope to within a month or two at the latest.
Simon Steele wrote:
Having been working in VS.NET for a while I got used to the (seemingly really clever) tab-order management .... They basically seem to store a history of your last visited tabs and work through them in that order - instead of the seemingly barking mad order that the basic MDI framework provides you with.
Yes, I've always liked how Ctrl-Tab works with MDI children in Visual Studio. I think you might be suprised that there's really only one small difference between the default MDIClient behavior and the MDI behavior in Visual Studio (as far as I can tell).
It's all about Z-Order. The default MDIClient handles Ctrl-Tab by cycling through the MDI children in Z-Order. Ctrl-Shift-Tab cycles in reverse. The other default accelerators with MDI children are Ctrl-F6 and Ctrl-Shift-F6, that in the default implementation seem to work just like Ctrl-Tab and Ctrl-Shift-Tab. With the default implementation, the newly activated MDI child goes to the top of the Z-Order, and the last active MDI child goes to the bottom of the Z-Order. The effect is if you let up on the Ctrl key, the default behavior just picks up cycling where you left off.
With Visual Studio, Ctrl-Tab, Ctrl-Shift-Tab, Ctrl-F6, Ctrl-Shift-F6 also cycle forwards and backwards through MDI children according to Z-Order. However, there is one important difference from the default MDIClient implementation. When you cycle through windows (using Ctrl-Tab, etc.), the Z-order of the newly activated MDI child still gets moved to the top of the Z-Order, but the MDI child losing focus doesn't get sent to the bottom of the Z-Order (which really makes more sense if you ask me). The effect is that you hit Ctrl-Tab once, and it takes you to the last active MDI child, which let's you quickly toggle back and forth between two MDI children. In the default implementation, to toggle back and forth like this, you'd have to use Ctrl-Tab and then Ctrl-Shift-Tab.
My TabbedMDI classes seem like a good place to provide the option of having things work the Visual Studio way. I'll try to get this into my next update as well
-Daniel
|
|
|
|
|
Hi Dan,
Great control, especially the MDI version which I'm using in a current project.
Thanks a bunch
|
|
|
|
|
rdheadrick wrote:
Hi Dan,
Great control, especially the MDI version which I'm using in a current project.
Thanks a bunch
You're welcome. Thanks for the kind words I'm using the code in a real project as well, so I'm always interested in bug reports and missing functionality (that might be general enough to work into the base classes)
-Daniel
|
|
|
|
|
When using the CDotNetButtonTabCtrl like in the TabDemo project (but with a RichEdit control as a replacement for the PlainTextView) I cannot get shortcut keys (Ctrl-C, Ctrl-V etc.) to work in the RichEdit control.
If I skip the CDotNetButtonTabCtrl and use the RichEdit control like in the SimpleTabbedMDIDemo, everything is working fine.
I suspect it's something in the PreTranslateMessage of the MainFrame, but it's only a wild n00b guess.
|
|
|
|
|
Tester Joe wrote:
When using the CDotNetButtonTabCtrl like in the TabDemo project (but with a RichEdit control as a replacement for the PlainTextView) I cannot get shortcut keys (Ctrl-C, Ctrl-V etc.) to work in the RichEdit control.
If I skip the CDotNetButtonTabCtrl and use the RichEdit control like in the SimpleTabbedMDIDemo, everything is working fine.
I suspect it's something in the PreTranslateMessage of the MainFrame, but it's only a wild n00b guess.
Yes, PreTranslateMessage does have something to do with it.
The "proper" way to handle Ctrl-C, Ctrl-V, etc. is to have them be "accelerators". This essentially turns key strokes into WM_COMMAND messages (with an ID like ID_EDIT_COPY, etc.). You then have your window handle these WM_COMMAND message (COMMAND_ID_HANDLER in the message map) and call (or SendMessage) the appropriate thing.
Where PreTranslateMessage gets involved is in recognizing the keystrokes as accelerators before the key messages are processed as usual. Take for example an out-of-the-box MDI application using the WTL wizard. One of the things you get is a CChildFrame class that inherits from CMDIChildWindowImpl. The DECLARE_FRAME_WND_CLASS macro is used to say what resource ID is used for the MDI child. There can be an icon with this resource ID, a menu, an accelerator table, and so on. When you create the window, WTL will try to do a LoadAccelerators with that ID to load the accelerator table (which gets used later as you'll see). Then you have the main frame registering itself so that it gets PreTranslateMessage calls. In the default implementation, it calls the base class CMDIFrameWindowImpl<cmainframe>::PreTranslateMessage(pMsg), and then does a SendMessage WM_FORWARDMSG to the active MDI child (if there is one). WM_FORWARDMSG is essentially a message-only way to call PreTranslateMessage (when you don't have C++ knowledge of the window, but know its HWND). The default handler for the MDI child's WM_FORWARDMSG calls CMDIChildWindowImpl's PreTranslateMessage, which calls TranslateAccelerator to see if the message triggers an accelerator. So in your MDI child, this is how you get WM_COMMAND with ID_EDIT_COPY when you hit Ctrl-C.
The problem that I bet your having is getting Ctrl-C, etc. to work for a window that is docked. My guess is that it doesn't even work with a normal edit box. In order for it to work:
- You'll need an accelerator table for the docked window
- You'll need to make sure that the main frame PreTranslateMessage is modified to give your docked window a chance (depending on focus for example)
- Your docked window needs to handle that PreTranslateMessage/WM_FORWARDMSG to call TranslateAccelerator. You also need to make sure that someone else doesn't steal the message before you get it (i.e., the main frame).
I'll update the TabDemo and DockingDemo for a future release to show how to do this, but for the meantime, change your CMainFrame::PreTranslateAccelerator in TabDemo to be something like:
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
if(pMsg == NULL)
{
return FALSE;
}
if(pMsg->hwnd == m_hWnd || pMsg->hwnd == m_hWndMDIClient)
{
if(baseClass::PreTranslateMessage(pMsg))
return TRUE;
}
HWND hWndFocus = ::GetFocus();
HWND hWndMDIActive = this->MDIGetActive();
if((hWndMDIActive == hWndFocus) || (::IsChild(hWndMDIActive, hWndFocus)))
{
if(baseClass::PreTranslateMessage(pMsg))
return TRUE;
if(hWndMDIActive != NULL)
{
return (BOOL)::SendMessage(hWndMDIActive, WM_FORWARDMSG, 0, (LPARAM)pMsg);
}
}
else if(m_OutputFrame.IsWindow() && m_OutputFrame.IsChild(hWndFocus))
{
if(m_OutputFrame.PreTranslateMessage(pMsg))
{
return TRUE;
}
}
return FALSE;
}
Notice how I depend on the focus here as to who gets a crack at doing their own PreTranslateMessage calls.
You'll also need to update the docked window, like the edit window (or other window that wants to deal with accelerators). Here's how you might change "PlainTextView.h" to explicitly create an accelerator table manually and use it (there's other ways to do this too - like having the accelerator table in a resource and doing LoadAccelerators):
class CPlainTextView:
public CWindowImpl<CPlainTextView, CEdit, CPlainTextViewWinTraits>,
public CEditCommands<CPlainTextView>
{
protected:
typedef CPlainTextView thisClass;
typedef CWindowImpl<CPlainTextView, CEdit, CPlainTextViewWinTraits> baseClass;
protected:
HACCEL m_hAccel;
WTL::CFont m_font;
public:
CPlainTextView() :
m_hAccel(NULL)
{
}
public:
DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())
BOOL PreTranslateMessage(MSG* pMsg)
{
if(pMsg)
{
if((pMsg->hwnd == m_hWnd) || ::IsChild(m_hWnd, pMsg->hwnd))
{
if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
{
return TRUE;
}
}
}
return FALSE;
}
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
if(uMsg == WM_FORWARDMSG)
if(PreTranslateMessage((LPMSG)lParam)) return TRUE;
CHAIN_MSG_MAP_ALT(CEditCommands<CPlainTextView>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
bHandled = TRUE;
this->InitializeFont();
this->CreateAccelerators();
return lRet;
}
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
this->DestroyAccelerators();
bHandled = FALSE;
return 0;
}
protected:
void InitializeFont(void)
{
CClientDC dc(m_hWnd);
LOGFONT lf = {0};
::ZeroMemory(&lf, sizeof(LOGFONT));
const int PointSize = 8;
lf.lfHeight = -MulDiv(PointSize, GetDeviceCaps(dc, LOGPIXELSY), 72);
::lstrcpy(lf.lfFaceName, _T("Courier New"));
m_font.Attach( ::CreateFontIndirect(&lf) );
this->SetFont(m_font);
CFontHandle hOldFont = dc.SelectFont(m_font);
TEXTMETRIC tm = {0};
dc.GetTextMetrics(&tm);
dc.SelectFont(hOldFont);
int nDialogUnitsX = 4*(tm.tmAveCharWidth / LOWORD(GetDialogBaseUnits()));
int nTabStops = 4*nDialogUnitsX;
this->SetTabStops(nTabStops);
}
void CreateAccelerators(void)
{
const int cAccel = 12;
ACCEL AccelTable[cAccel] = {
{FVIRTKEY | FCONTROL | FNOINVERT, 'A', ID_EDIT_SELECT_ALL},
{FVIRTKEY | FCONTROL | FNOINVERT, 'X', ID_EDIT_CUT},
{FVIRTKEY | FCONTROL | FNOINVERT, 'C', ID_EDIT_COPY},
{FVIRTKEY | FCONTROL | FNOINVERT, 'V', ID_EDIT_PASTE},
{FVIRTKEY | FCONTROL | FNOINVERT, 'F', ID_EDIT_FIND},
{FVIRTKEY | FNOINVERT, VK_F3, ID_EDIT_REPEAT},
{FVIRTKEY | FCONTROL | FNOINVERT, 'H', ID_EDIT_REPLACE},
{FVIRTKEY | FCONTROL | FNOINVERT, 'Z', ID_EDIT_UNDO},
{FVIRTKEY | FCONTROL | FNOINVERT, 'Y', ID_EDIT_REDO},
{FVIRTKEY | FSHIFT | FNOINVERT, VK_DELETE, ID_EDIT_CUT},
{FVIRTKEY | FCONTROL | FNOINVERT, VK_INSERT, ID_EDIT_COPY},
{FVIRTKEY | FSHIFT | FNOINVERT, VK_INSERT, ID_EDIT_PASTE}
};
m_hAccel = ::CreateAcceleratorTable(AccelTable, cAccel);
}
void DestroyAccelerators(void)
{
if(m_hAccel)
{
::DestroyAcceleratorTable(m_hAccel);
m_hAccel = NULL;
}
}
};
HTH,
-Daniel
|
|
|
|
|
Daniel's reply is good and comprehensive and I've noted it for my own purposes, but you can also apply a simple workaround for this particular problem (one that I use):
Create handlers for WM_COPY, WM_CUT, WM_PASTE etc. in your main frame, and then use simple code in each like this:
::SendMessage(::GetFocus(), WM_?, wParam, lParam);
and this will forward on the relevant message to the active window.
hope that helps,
--
Simon Steele
Programmers Notepad - http://www.pnotepad.org/
|
|
|
|
|
On XP this project works perfectly. On W2K I’ve got a problem.
Under XP, the text in the tabs are perfectly readable. On W2K, the text of the tab that is active is perfectly readable but the text in tabs that are not active are nearly impossible to read.
Is there a workaround?
Daniel, this is absolutely terrific code. I wish I had the money to hire you.
Maybe someday I will.
Ralph Shnelvar
Managing Partner
Information LLC
|
|
|
|
|
Ralph Shnelvar wrote:
Daniel, this is absolutely terrific code. I wish I had the money to hire you.
Maybe someday I will.
Ralph Shnelvar wrote:
On XP this project works perfectly. On W2K I’ve got a problem.
Under XP, the text in the tabs are perfectly readable. On W2K, the text of the tab that is active is perfectly readable but the text in tabs that are not active are nearly impossible to read.
Is there a workaround?
Interesting. I assume you're talking about CDotNetTabCtrl. With CDotNetTabCtrl I tried to match how the pane tabs and MDI tabs in Visual Studio .Net look. When you run Visual Studio .Net on the XP and the W2K machine, do my tabs look different than theirs? If they look different, please send me some screen shots. If they look the same, but you don't like the look, here's a couple of options:
- FYI, The tab colors (active, inactive, background, etc.) in CDotNetTabCtrl (and the tabs in VS.Net) depend on the following system settings:
- SPI_GETICONTITLELOGFONT - SystemParametersInfo (The "Icon" font)
- COLOR_BTNFACE - GetSysColor (3D Objects)
- COLOR_BTNTEXT - GetSysColor (3D Objects)
- COLOR_BTNSHADOW - GetSysColor (3D Objects)
- COLOR_GRAYTEXT - GetSysColor (3D Objects)
- COLOR_BTNHIGHLIGHT - GetSysColor (Selected Items)
- COLOR_HOTLIGHT - GetSysColor (Selected Items)
- COLOR_APPWORKSPACE - GetSysColor (Application Background)
- The color bits per pixel (it does something different if there is less than 8bpp)
- Try adjusting "Appearance" settings (Control Panel -> Display -> Appearance). Under W2K, you'll see "Scheme" and also "Item". Under XP you'll see "Windows and buttons" (to choose either XP themes or "classic" style), "Color Scheme", "Font Size", and under advanced, you'll see the "Item" things you can individually change.
- CDotNetTabCtrl supports doing "Custom Draw" just like you do it with list views and tree views (CCustomTabCtrl supports custom draw in general, but the specific tab controls have to as well in order for it to change the appearance). If you have control of the parent window, you could respond to the NM_CUSTOMDRAW notification and choose different colors for things (see the article for a brief explanation).
HTH,
-Daniel
|
|
|
|
|
> Daniel wrote: Interesting. I assume you're talking about CDotNetTabCtrl. With CDotNetTabCtrl I tried to match how the pane tabs and MDI tabs in Visual Studio .Net look. When you run Visual Studio .Net on the XP and the W2K machine, do my tabs look different than theirs?
Daniel, yes, I'm talking about CDotNetTabCtrl. Sorry, should have been clearer.
Let me say that I am something of a novice when it comes to GUI programming (although I am a strong C++ programmer as well as something of a systems-level programmer). Thus some of what you wrote is not clear to me.
I have W2K and XP installed on the same machine on different partitions.
I have VC++6 installed on W2K and .Net on XP. I don't use .Net much because I lose Brief emulation as the text editor.
What can I do to satisfy your query about different looking tabs? Sorry, I’m not sure I understand what you want me to do.
I found that the source of my “trouble” is roughly at line 238 in DotNetTabCtrl where you issue
m_hbrBackground = CDCHandle::GetHalftoneBrush();
m_clrInactiveTab = ::GetSysColor(COLOR_GRAYTEXT);
Violating all good rules of OOP programming, I went in and replaced your code with
extern unsigned int _winmajor;
if(_winmajor == 6)
{
// if XP
m_hbrBackground = CDCHandle::GetHalftoneBrush();
m_clrInactiveTab = ::GetSysColor(COLOR_GRAYTEXT);
}
else
{
m_hbrBackground.CreateSolidBrush(m_clrBackground);
m_clrInactiveTab = ::GetSysColor(COLOR_BTNFACE);
}
which then cleared my problem.
Would you please point me at a WTL example of owner draw so that I do things “right.”?
Ralph Shnelvar
Managing Partner
Information LLC
|
|
|
|
|
Ralph Shnelvar wrote:
Sorry, I’m not sure I understand what you want me to do.
Sorry if I wasn't very clear
Ralph Shnelvar wrote:
I found that the source of my “trouble” is roughly at line 238 in DotNetTabCtrl where you issue
m_hbrBackground = CDCHandle::GetHalftoneBrush();
m_clrInactiveTab = ::GetSysColor(COLOR_GRAYTEXT);
That's a good clue. That little bit of code only gets called if your screen resolution is set so that the color depth isn't greater than 256 colors (8bpp). What do you have as your settings - i.e., 1600x1200, True Color (32 bit)? What does the line
int nBitsPerPixel = dcWindow.GetDeviceCaps(BITSPIXEL);
before the line you mentioned return for nBitsPerPixel?
Windows XP doesn't let you choose less than 16bpp (although it is possible if you know how), but Windows 2000 lets you choose down to 8bpp (256 colors).
...
OK, I just tried the code on Windows 2000 with the color depth set to "256 colors". You're right - it looks terrible I never personally run with less than 16bpp unless I'm testing something out, so I've missed this problem. I thought I had tested this out, but from the looks of it I probably missed it I ran Visual Studio .Net under 256 colors, and the tabs looks much better than what I have (the text for inactive tabs is white on a gray background).
I'll work on getting the drawing to look decent when your color depth is 256 colors or less for my next update. I had done quite a bit of testing with Visual Studio to try to figure out how to match their colors for various system settings. I'll have to do some of those tests again running with 256 colors.
Ralph Shnelvar wrote:
Would you please point me at a WTL example of owner draw so that I do things “right.”?
There's a bit to learn with owner draw and custom draw if you've never done it before. For now, go ahead and fix your copy of the code so that things look better
If you'd like to know more about Custom Draw, most of the samples are either in MFC or SDK style, so you have to convert to WTL. There are some that are WTL as well. Take a look at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/custdraw/custdraw.asp (SDK style)
http://www.codeproject.com/listctrl/lvcustomdraw.asp (MFC style)
http://www.codeproject.com/wtl/customdrawlist_wtl.asp (WTL style)
And thanks for the bug report!
-Daniel
|
|
|
|
|
Dear Daniel:
I apologize for taking so long to get back to you. It’s not been a quiet week in Lake Wobegon.
First, I want to say thank you for your kindness and patience. Second, part of the reason that it took me so long to get back to you is that I was waiting for an email in my inbox saying that you had responded. I never got that email.
Let me impose on you a bit more.
Could I ask you to please email me. Depending on finances and distance I may want to contract with you for some telephone support. No guarantees …
I also would like to learn how to post to this list with all the fancy markups that you use.
Is it nothing more than HTML text (that I might be able to produce with Word 2000)? Or is it something else since “everyone” seems to use the same kind of style.
I’m thinking about writing a little monograph about my experiences with ATL. Do you think people would be interested and where would the best place to pos it be?
Ralph Shnelvar
Managing partner
Information LLC
|
|
|
|
|
Ralph Shnelvar wrote:
First, I want to say thank you for your kindness and patience. Second, part of the reason that it took me so long to get back to you is that I was waiting for an email in my inbox saying that you had responded. I never got that email.
You're welcome.
I've noticed that I haven't gotten e-mail notifications on some things as well (must be a problem with CodeProject's notification stuff). There's a couple that did eventually come, but took a long time. There's others that never came at all.
Ralph Shnelvar wrote:
Could I ask you to please email me
Sure. When you see a codeproject message, if there's an "E-mail" link, you can click on it, and it will use codeproject to send an e-mail to the direct e-mail of the person, with your own e-mail as the reply-to address (if you're logged in).
Ralph Shnelvar wrote:
I also would like to learn how to post to this list with all the fancy markups that you use.
There's a bit of info about doing this on the pages that talk about submitting codeproject articles: http://www.codeproject.com/info/submit.asp. You can also get to that page by going to the home page, and under "Join CodeProject!" follow the link for "Adding and updating articles". Essentially, you can use HTML markup, and content in <pre> / <code> tags get syntax colorized.
Ralph Shnelvar wrote:
I’m thinking about writing a little monograph about my experiences with ATL. Do you think people would be interested and where would the best place to pos it be?
On CodeProject, you could start by posting a message to the ATL forum (click on "Message Boards" on the top right of the home page - the ATL/WTL/STL forum is http://www.codeproject.com/script/comments/forums.asp?forumid=4486). You could also post a message to the ATL mailing list (http://discuss.develop.com/atl.html) or the WTL mailing list (http://groups.yahoo.com/group/wtl/). You could also try writing up an article for codeproject.
-Daniel
|
|
|
|
|
When I cascade the child windows, I would like to hide the "main" tabbed toolbar (the one with the mdi child titles). Is there an easy way to do this?
Thanks,
Gordon.
|
|
|
|
|