|
If you use the CTabbedMDICommandBarCtrl a bug occurs when compiling with _WIN32_IE >= 0x0500 - the rebars are restored offset to the left, and each time you restart the application, they shift over some more
Edit "tabbedmdi.h", goto line 1316 and remove the "RBBIM_IDEALSIZE" flag.
e.g.
...
for(int i = 0; i < nCount; i++)
{
#if (_WIN32_IE >= 0x0500)
REBARBANDINFO rbi = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE };
//REBARBANDINFO rbi = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE };
::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
...
Hope this helps, and thanks for creating such a nice looking control!
I'm using it in my application, HydraIRC, grab it from - www.Hydras-World.com
|
|
|
|
|
Interesting. Thanks for the tip! That part of CTabbedMDICommandBarCtrl is a direct copy and paste from CMDICommandBarCtrlImpl::OnAllHookMessages. So, I take it that the default CMDICommandBarCtrl does the same thing to you in a plain vanilla WTL MDI app?
-Daniel
|
|
|
|
|
Well i know that my app does it, and someone else spotted a similar thing in the wtl docking windows stuff and posted a message there too..
It's weird, because for me, it was fine for ages, then all of a sudden starting doing it, then for another user, it did it straight away...
|
|
|
|
|
When you create a new MDI Child window it's always maximized. It should create the window in the same state as the current MDI window.
e.g.
if the current window is restored, new window created as restored.
if current window is maximized, create new window as maximized.
The default should be to always maximize MDI windows, but there should be a way to override this behaviour as it's most annoying for my app..
|
|
|
|
|
Hydra wrote:
When you create a new MDI Child window it's always maximized. It should create the window in the same state as the current MDI window.
You must be referring to the "DockingDemo" sample. If you run the 2 other MDI samples, you'll see that it does indeed do exactly what you would like. In fact, I go to extra lengths that an out-of-the-box WTL app doesn't go through to match the maximization of that last previously active MDI child.
You can see another codeproject article I wrote about this very topic:
http://www.codeproject.com/wtl/wtlmdichildmax.asp
In the "DockingDemo" sample, I am demonstrating how (via my CTabbedMDIChildWindowImpl) you can easily have your app always create MDI children as maximized - by simply including the "WS_MAXIMIZE" style for the child frame. To see the demo without this behavior, simply go to the DockingDemo's version of "HtmlFrame.h", and remove "WS_MAXIMIZE" from CHtmlFrameWinTraits
-Daniel
|
|
|
|
|
ahh, i missed that.. ok thanks! just what i wanted then
|
|
|
|
|
I'm using Windows XP, WTL 7.0, and Visual Studio .NET, when I try any of the demos, or when i use the TabbedMDI control in my app the application does not exit properly if an MDI window is still open.
Instead executing code after the line..:
int nRet = theLoop.Run();
.. it just goes "ding" and then drops back to the dev environment. No assertions, no nothing. I stepped through the code after it processes my CMainFrame::OnClose() and it exits while processing this bit of code from user32.dll
77D458A1 call dword ptr [eax+14h]
77D458A4 push 0
77D458A6 push 0Ch
77D458A8 pop edx
77D458A9 lea ecx,[ebp-0Ch]
77D458AC mov dword ptr [ebp-0Ch],eax
77D458AF call 77D444A7 <<< Exits here!
The callstack from my app is:
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::DefWindowProcA(unsigned int uMsg=0x00000010, unsigned int wParam=0x00000000, long lParam=0x00000000) Line 1270 + 0x22 C++
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::MDIFrameWindowProc(HWND__ * hWnd=0x010c7100, unsigned int uMsg=0x00000010, unsigned int wParam=0x00000000, long lParam=0x00000000) Line 1224 + 0x14 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::DefWindowProcA(unsigned int uMsg=0x00000010, unsigned int wParam=0x00000000, long lParam=0x00000000) Line 3779 + 0x21 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::WindowProc(HWND__ * hWnd=0x010c7340, unsigned int uMsg=0x00000010, unsigned int wParam=0x00000000, long lParam=0x00000000) Line 3822 + 0x14 C++
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::DefWindowProcA(unsigned int uMsg=0x00000112, unsigned int wParam=0x0000f060, long lParam=0x006d03c6) Line 1270 + 0x22 C++
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::MDIFrameWindowProc(HWND__ * hWnd=0x010c7100, unsigned int uMsg=0x00000112, unsigned int wParam=0x0000f060, long lParam=0x006d03c6) Line 1224 + 0x14 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::DefWindowProcA(unsigned int uMsg=0x00000112, unsigned int wParam=0x0000f060, long lParam=0x006d03c6) Line 3779 + 0x21 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::WindowProc(HWND__ * hWnd=0x010c7340, unsigned int uMsg=0x00000112, unsigned int wParam=0x0000f060, long lParam=0x006d03c6) Line 3822 + 0x14 C++
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::DefWindowProcA(unsigned int uMsg=0x000000a1, unsigned int wParam=0x00000014, long lParam=0x006d03c6) Line 1270 + 0x22 C++
HydraIRC.exe!WTL::CMDIFrameWindowImpl<cmainframe,wtl::cmdiwindow,dockwins::cdockingframetraitst<csimplesplitterbar<5>,114229248,262400> >::MDIFrameWindowProc(HWND__ * hWnd=0x010c7100, unsigned int uMsg=0x000000a1, unsigned int wParam=0x00000014, long lParam=0x006d03c6) Line 1224 + 0x14 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::DefWindowProcA(unsigned int uMsg=0x000000a1, unsigned int wParam=0x00000014, long lParam=0x006d03c6) Line 3779 + 0x21 C++
HydraIRC.exe!ATL::CContainedWindowT<atl::cwindow,atl::cwintraits<1442840576,0> >::WindowProc(HWND__ * hWnd=0x010c7340, unsigned int uMsg=0x000000a1, unsigned int wParam=0x00000014, long lParam=0x006d03c6) Line 3822 + 0x14 C++
HydraIRC.exe!Run(char * __formal=0x00151f18, int nCmdShow=0x00000001) Line 533 + 0x8 C++
HydraIRC.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * __formal=0x00000000, char * lpstrCmdLine=0x00151f18, int nCmdShow=0x00000001) Line 603 + 0xd C++
HydraIRC.exe!WinMainCRTStartup() Line 251 + 0x32 C
kernel32.dll!77e7eb69()
Hope you can fix it!
|
|
|
|
|
Hydra wrote:
when I try any of the demos, or when i use the TabbedMDI control in my app the application does not exit properly if an MDI window is still open
Thanks for reporting this! I'm still looking into this, and I'll reply back to this message when I figure out what the problem is or how to fix it (hopefully both ).
Thanks,
-Daniel
|
|
|
|
|
sure thing, and if you need any more info from me, don't hesitate to ask.
|
|
|
|
|
Ok, so I thought, bugger the MDI tabs, don't really need them anyway because I have a taskbar on a rebar toolbar that controls the windows and reorders itself according to which windows you used last:
m_MyToolBar.Movebutton(currentbuttonindex, 0) //move to first button
I wish the .net ones did that, actually, add that to your TODO list too..
anyway, I digress..
So, I #ifdef'd out the MDI tabbed stuff, and implemented two docking windows, each with two tabbed views, and again, the exit problem occurs when there are MDI windows open ?!?.
So maybe the bug is not in the TabbedMDI..Impl, but instead the bug might be in the actual custom Tab Controls or maybe not, but I thought this might be useful for you to know anyway.
|
|
|
|
|
ahh, i might have narrowed it down a bit for you..
i accidentally declared my view in my base class as well as my derived class (oops!) and initilised the ones in the derived class and added them to the tabs and that's what caused exit problem in the above example.
After i removed the declaration in the derived class it all worked normally and exited without a error, even with multiple MDI windows open.
So, maybe the problem *IS* with just the MDI tabs, as I originally thought, but maybe the solution has something to do with something similar...
here's what i had:
class TextQueueManager
{
public:
CSimpleArray<textqueueitem *=""> m_TextQueue;
int m_QueueType;
CTextQueueView *m_pTextQueueView; // <-- the tabbed view...
TextQueueManager( void );
~TextQueueManager( void );
void AddItem(char *From, char *Message, char *ServerName);
void RemoveOldItems( void );
private:
void RemoveItem( TextQueueItem *pTQI );
};
class PrivMsgQueueManager :
public TextQueueManager
{
public:
//CTextQueueView *m_pTextQueueView; // <-- oops! had it here too..
PrivMsgQueueManager( void )
{
m_QueueType = CWQUEUE_PRIVMSG;
m_pTextQueueView = new CTextQueueView(this);
}
~PrivMsgQueueManager( void )
{
delete m_pTextQueueView;
}
};
|
|
|
|
|
Hydra wrote:
when I try any of the demos, or when i use the TabbedMDI control in my app the application does not exit properly if an MDI window is still open
Sorry for taking so long to get back about this.
The fix turns out to be very simple. In DotNetTabCtrl.h, replace line 719:
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_Close, &m_rcCloseButton);
with
if(m_tooltip.IsWindow())
{
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_Close, &m_rcCloseButton);
}
and line 773 and 774:
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_ScrollRight, &m_rcScrollRight);
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_ScrollLeft, &m_rcScrollLeft);
with
if(m_tooltip.IsWindow())
{
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_ScrollRight, &m_rcScrollRight);
m_tooltip.SetToolRect(m_hWnd, ectcToolTip_ScrollLeft, &m_rcScrollLeft);
}
These changes will be in my next updates.
The problem was that when all the items are deleted in DeleteAllItems (called while handling WM_DESTROY) DeleteItem is called, which calls UpdateLayout, which, when CTCS_CLOSEBUTTON and/or CTCS_SCROLL are set, tries to update their respective tooltips, but the tooltips have already been destroyed.
I'm also going to make a change to DeleteAllItems that you can make now if you like. Replace CustomTabCtrl.h line 2338:
while( GetItemCount()>0 ) DeleteItem(0U, false, true);
with
this->SendMessage(WM_SETREDRAW, FALSE, 0);
while( GetItemCount()>0 ) DeleteItem(0U, false, true);
this->SendMessage(WM_SETREDRAW, TRUE, 0);
-Daniel
|
|
|
|
|
I can't find the file "altapp.h".
|
|
|
|
|
atlapp.h is part of WTL. You can get WTL from
http://msdn.microsoft.com/downloads/?url=/downloads/sample.asp?url=/msdn-files/027/001/586/msdncompositedoc.xml&frame=true
or go to msdn.microsoft.com, go to developer downloads ->
Visual Studio, Tools and Languages -> Visual C++ -> Windows Template Library
After installing it, be sure to put WTL's include directory in your Tools->Options->Directories->Include files list.
-Daniel
|
|
|
|
|
I noticed if I change CreateTabWindow(m_hWnd, rcDefault, (CTCS_BOTTOM | CTCS_TOOLTIPS)); to CreateTabWindow(m_hWnd, rcDefault, (CTCS_BOTTOM | CTCS_TOOLTIPS | CTCS_SCROLL | CTCS_CLOSEBUTTON)); I get the associate controls but when I close the application a whole pile of memory and resource leaks show up in BoundsChecker. I noticed that these same leaks appear in the other samples where the scroll and closebutton are used. Therefore I can only assume that it is do to these features.
Just a heads up.
Cheers,
Clint
|
|
|
|
|
I forgot to mention that I am adding the new styles to the TabbedFrame class in the TabbedFrame.h file.
|
|
|
|
|
clintsinger wrote:
I get the associate controls but when I close the application a whole pile of memory and resource leaks show up in BoundsChecker.
From some initial testing, it seems that these "leaks" are being reported by BoundsChecker because of the exit problem that Hydra reported seeing. For example, with the MDI demos, if you close all the MDI children, then exit, you don't get all the "leaks" reported by BoundsChecker. I'm still looking into this.
What version of OS, IE, VS, and WTL are you using (along with any service packs)?
-Daniel
|
|
|
|
|
I am using Windows 2000 SP2, IE 5.5, VS 6.0 SP5, WTL 7.0, BoundsChecker 6.01
Hope those help you a bit. It is possible that these are false positives, unfortunately I am not exactly sure how to hunt them down. Would you like me to send the BCE file?
|
|
|
|
|
clintsinger wrote:
Would you like me to send the BCE file?
Sure.
-Daniel
|
|
|
|
|
I was just looking through your Splitter example and I noticed that the tab bar doesn't have the regular Left/Right/Close buttons. Do they only work with MDI forms and if so do the same techniques to get the SDI up and running with a splitter pane work for MDI?
Otherwise, is there away to get those controls showing with your SDISplitter example? I would like to be able to dynamically create a view like you have but also be able to kill it.
Thanks again,
Clint
|
|
|
|
|
clintsinger wrote:
I was just looking through your Splitter example and I noticed that the tab bar doesn't have the regular Left/Right/Close buttons.
There are a couple of ways to do this. For example, in the "TabbedSDISplitter" sample, after the " m_tabbedChildWindow.Create(m_splitter, rcDefault);" call in the main frame's OnCreate, you could add the line:
m_tabbedChildWindow.GetTabCtrl().ModifyStyle(0, (CTCS_SCROLL | CTCS_CLOSEBUTTON));
Or if you wanted it on top with just the scroll buttons:
m_tabbedChildWindow.GetTabCtrl().ModifyStyle(CTCS_BOTTOM, CTCS_SCROLL);
etc.
However, you're going to have to hook-up the close button to actually do something (you just have to handle the CTCN_CLOSE notification in the parent). I don't know the full needs of your app, but you'd also have to worry about what to do when there are no child views left, as well as other things that an MDIClient typically handles for you (and which my TabbedMDI stuff deals with).
-Daniel
|
|
|
|
|
Hi,
I ran the TabDemo and on closing the tabbed output window via its close box an assertion violation window pops up. This does not happen when I disable the output window via the View | Output Window toggle. Any hints?
Cheers
|
|
|
|
|
Yes, I didn't demonstrate very well the right way to do a toggling popup frame
First, if all you want to do is get rid of the assertion, change the TabDemo's mainfrm.h line 48 from
else if(m_OutputFrame.IsChild(hWndFocus))
to
else if(m_OutputFrame.IsWindow() && m_OutputFrame.IsChild(hWndFocus))
This doesn't make it work right though. To make it work right, you need to handle when the popup window gets the WM_SYSCOMMAND message with wParam set to SC_CLOSE . Then instead of letting the frame do its default handling, you instead simulate the user selecting the corresponding menu item that toggles the visibility of the popup window (you send a WM_COMMAND with the right id).
In future releases, I'll have an updated version of CTabbedPopupFrame that let's you indicate that you want a command message sent instead of a real close to happen. (I had originally meant CTabbedPopupFrame more as a simple example of using CTabbedFrameImpl ).
If you want the updates before then, you could do something like:
CTabbedPopupFrame:
- Add a member variable
WORD m_nCloseCommand - Initialize m_nCloseCommand in the constructor to 0
- Provide accessor methods "GetCloseCommand" and "SetCloseCommand"
- In the message map, before chaining to the base class, add the lines:
if(m_nCloseCommand != 0)
{
if(uMsg == WM_SYSCOMMAND && wParam == SC_CLOSE)
{
bHandled = TRUE;
lResult = ::SendMessage(this->GetParent(), WM_COMMAND, MAKEWPARAM(m_nCloseCommand, 0), 0);
return TRUE;
}
}
Main Frame:
-Daniel
|
|
|
|
|
Thank you very much for that excellent piece of code!
Laurent Kempé
Tech Head
---
Old programmers never die, they just branch to a new address.
|
|
|
|
|
do you keep doing cool stuff in WTL.
|
|
|
|
|