|
My application calls for multiple document views and I would like to use similar approach as CMDITabs. I would like to have CMDITabs class " inside " tab document class, however, CMDITab cannot do that per this message board.
I was thinking making a doc tab and than an array of view tabs.
How does one gets the menu to have submenu e.a document with pop-up of views?
My views are not same for each document.
I am looking for any suggestions how to do this.
|
|
|
|
|
YES ,it is flick ,I don't know how to resolve it , Would you like to help me ?
thank you
|
|
|
|
|
It's flick because of when you switch a to a tab, the tab that is to be hiden is first restored and the new tab is maximized.
To prevent this, you could set the tab wich is to be hiden to his max size before the bringtotop,
That is what i do (i(ve remove the onselchange) :
void CMDITabs::OnLButtonDown(UINT nFlags, CPoint point)
{
CTabCtrl::OnLButtonDown(nFlags, point);
TCHITTESTINFO tcHit;
tcHit.pt = point;
int selected = HitTest(&tcHit);
int current = GetCurSel();
if (selected!=current)
{
TCITEM item;
item.mask = TCIF_PARAM;
GetItem(GetCurSel(), &item);
HWND hWnd = HWND(item.lParam);
if (::IsZoomed(hWnd)!=0)
{
CRect rect;
::GetClientRect(hWnd,&rect);
GetItem(current, &item);
::MoveWindow(HWND(item.lParam)
,rect.left-GetSystemMetrics(SM_CXFRAME)-GetSystemMetrics(SM_CXEDGE)
,rect.top-GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYFRAME)-GetSystemMetrics(SM_CYEDGE)
,rect.Width()+GetSystemMetrics(SM_CXFRAME)+2*GetSystemMetrics(SM_CXEDGE)
,rect.Height()+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)+2*GetSystemMetrics(SM_CYEDGE)
,FALSE);
GetItem(selected, &item);
::MoveWindow(HWND(item.lParam)
,rect.left-GetSystemMetrics(SM_CXFRAME)-GetSystemMetrics(SM_CXEDGE)
,rect.top-GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYFRAME)-GetSystemMetrics(SM_CYEDGE)
,rect.Width()+GetSystemMetrics(SM_CXFRAME)+2*GetSystemMetrics(SM_CXEDGE)
,rect.Height()+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)+2*GetSystemMetrics(SM_CYEDGE)
,FALSE);
}
GetItem(selected, &item);
hWnd = HWND(item.lParam);
// Invalidate window avant de l'afficher
CView * pView = (CView*) FromHandle(hWnd);
pView->Invalidate(TRUE);
::BringWindowToTop(HWND(item.lParam));
SetCurSel(selected);
}
}
In this case, tou must do the job yourself for restoring the windows pos, like a MDICascade() when the user chose to restore the windows...
|
|
|
|
|
|
Hi,
The TCS_BUTTON style is working but there is just a little problem : the OnSelChange is called only when the left mouse button is released.
When no button style is used, OnSelChange is call immediately after the left mouse boutton is pressed.. It's because of how the button notify his state, i think (like all other buttons) but i'd like that the focus change immediatly
Do you have an idea to correct that ?
Thanks you
|
|
|
|
|
Ok I use this code and it works :
void CMDITabs::OnLButtonDown(UINT nFlags, CPoint point)
{
CTabCtrl::OnLButtonDown(nFlags, point);
TCHITTESTINFO tcHit;
RECT rect;
tcHit.pt = point;
int selected = HitTest(&tcHit);
if (selected!=GetCurSel())
{
SetCurSel(selected);
TCITEM item;
item.mask = TCIF_PARAM;
GetItem(GetCurSel(), &item);
::BringWindowToTop(HWND(item.lParam));
}
}
|
|
|
|
|
when the tab select change, I want to transfer the function of view. but I can't transfer it,help me!!!
when the tab select change, I want to update the button of
toolbar,how to dao?
|
|
|
|
|
I was wondering if it is possible to have the window text be the same as the tab text. Currently it only seems to display the document name. The reason I ask is because each of my windows will have a different name. I am able to change the wondow text properly because I can see them being displayed at the top of the screen as well as in the Window list however the tabs stay as the document name. If you have any suggestions that would be great.
Thanks!
Amy
|
|
|
|
|
I am trying to implement the Serialize function so that I can save and reload my document (with multiple views). This would include creating a new view manually versus using the Window->New button. So for I have tried this and have not had any luck. Any suggestions?
void CScriptBuilderDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
//for each view
numViews = 0;
pos = GetFirstViewPosition();
while (pos != NULL)
{
cview = (CScriptBuilderView *)GetNextView(pos);
numViews++;
}
ar << numViews;
//Plus storing other info related to my views
}
else
{
ar >> numViews;
for (int i = 0; i < numViews; i++)
{
cview = new CScriptBuilderView();
cview->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), AfxGetMainWnd(), AFX_IDW_PANE_FIRST + 1, NULL);
AddView(cview);
//Plus retrieve other info related to my view
}
}
UpdateAllViews(NULL);
}
Thanks in Advance
Amy
|
|
|
|
|
I have derived my CMainFrame class from CPIFrame (see this plugin archietecture article), which is derived from CMDIFrameWnd. Now the problem is VC says there is no CMDIFrameWnd::OnUpdateFrameTitle(BOOL). What could be the problem?
|
|
|
|
|
The problem is:
All my app has three tabs and they should present all the time the application works, but by pressing Ctrl+F4 it's possible to close any tab. Is there any way to avoid this situation?
|
|
|
|
|
I tried your demo project, but it seems it has serious flicking when switching tabs. It seems a form is showed up at first, then it is enlarged to the tab view.
I'm using VS.net.
|
|
|
|
|
내가 이거 알아낸다고 열라 고생했습니다. 아래 코드가 모든 경우에 다 제대로 동작하리라고
보장하지는 못하지만 테스트 결과 잘 되는것 같아서 함 올려보네요.
이것을 근거로 해서 더 완벽한 소스가 공개 되기를 기대해 봅니다. 클래스명은 우리나라영화
"공동경비구역"을 따서 지었음..ㅋㅋ
class CJointSecurityArea : public CMDIChildWnd
{
...
...
};
CRect g_rcJointSecurityAreaRect;
HWND g_wndDeactive=0;
void CJointSecurityArea::OnSize(UINT nType, int cx, int cy)
{
if(g_wndDeactive && g_wndDeactive == m_hWnd)
{
g_wndDeactive = 0;
MoveWindow(&g_rcJointSecurityAreaRect, FALSE);
return ;
}
CMDIChildWnd::OnSize(nType, cx, cy);
}
void CJointSecurityArea::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
{
CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
if(bActivate==FALSE && pDeactivateWnd)
{
g_wndDeactive = pDeactivateWnd->m_hWnd;
pDeactivateWnd->GetWindowRect(&g_rcJointSecurityAreaRect);
}
}
|
|
|
|
|
If I don't misunderstand your meaning, I was troubled with the same problem. You may have a try to remove the WS_OVERLAPPED style of your CMDIChildFrame derived class by adding the following code in the function PreCreateWindow() :
<br />
cs.style = WS_CHILD | WS_VISIBLE
| FWS_ADDTOTITLE| WS_MINIMIZEBOX | WS_MAXIMIZEBOX |WS_MAXIMIZE;<br />
|
|
|
|
|
Neat code, thanks!
However, there appears to be a small syncronisation problem with the MDI tab title compared with the document title
The OnUpdateFrameTitle(BOOL bAddToTitle) implementation is very neat however it can be tripped up.
If the document title is changed after the view is created the update routine is called correctly. However the text returned by GetWindowText() within the routine is the old title, rather than the new one.
You can demonstrate this in your demo app by simply saving one of the document views. You will see the window and app title change to the filename correctly, however the MDI tab is not updated (correctly) until a subsequent refresh of the tab of occurs (open another document / minimise the view / etc)
Alternatively you can create the fault by calling CDocument::SetTitle() any time after the document has been displayed.
Can anyone offer a solution? I've traced the code through and everything seems to be being called in the correct order
--
The Obliterator
|
|
|
|
|
One way to fix it is to overload CDocument::SetTitle() to update the tab control. It's not pretty, but it seems to work.
- Nate
|
|
|
|
|
Yes I considered this, thanks, but like you say its not very pretty!
Actually simply overriding CDocument::SetTitle() to call CDocument::SetTitle() twice in succession resolves the problem. Its slightly neater, but does cause a few unnecessary messages and refreshes. Not to mention you'd need to remember to do this in every document class you create
I'd prefer a more robust self-contained soltion within the MDITabs::Update() function if possible.
--
The Obliterator
|
|
|
|
|
I've encountered the same and has fixed it in MDITabs.cpp..
Search for the following function and look for my additions
void CMDITabs::Update()
{
SetRedraw(false);
HWND active = ::GetTopWindow(m_mdiClient);
typedef std::vector<HWND> TWndVec;
typedef TWndVec::iterator TWndIter;
TWndVec vChild;
for (HWND child = active; child; child = ::GetNextWindow(child, GW_HWNDNEXT))
{
vChild.push_back(child);
}
TCITEM item;
char text[256];
item.pszText = text;
for (int i = GetItemCount(); i--; )
{
item.mask = TCIF_PARAM;
GetItem(i, &item);
TWndIter it = std::find(vChild.begin(), vChild.end(), HWND(item.lParam));
if (it == vChild.end())
{
DeleteItem(i);
if (m_bImages) RemoveImage(i);
}
else
{
item.mask = TCIF_TEXT;
::GetWindowText(*it, text, 256);
CMDIChildWnd *pCF;
pCF = static_cast<CMDIChildWnd*>(FromHandlePermanent(*it));
if (pCF != NULL) {
CDocument *pDoc = pCF->GetActiveDocument();
if (pDoc != NULL) {
strncpy(text, pDoc->GetTitle(), sizeof(text));
}
}
if (m_bImages) m_images.Replace(i, (HICON)::GetClassLong(*it, GCL_HICONSM));
SetItem(i, &item);
if (*it == active) SetCurSel(i);
vChild.erase(it);
}
}
i = GetItemCount();
for (TWndIter it = vChild.begin(), end = vChild.end(); it != end; ++it)
{
item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE;
::GetWindowText(*it, text, 256);
CMDIChildWnd *pCF;
pCF = static_cast<CMDIChildWnd*>(FromHandlePermanent(*it));
if (pCF != NULL) {
CDocument *pDoc = pCF->GetActiveDocument();
if (pDoc != NULL) {
strncpy(text, pDoc->GetTitle(), sizeof(text));
}
}
if (m_bImages) m_images.Add((HICON)::GetClassLong(*it, GCL_HICONSM));
item.iImage = i;
item.lParam = LPARAM(*it);
InsertItem(i, &item);
if (*it == active) SetCurSel(i);
++i;
}
bool bShow = GetItemCount() >= m_minViews;
if ((!bShow && IsWindowVisible()) || (bShow && !IsWindowVisible()))
{
static_cast<CMDIFrameWnd*>(FromHandlePermanent(::GetParent(m_mdiClient)))->RecalcLayout();
}
RedrawWindow(NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_ERASE);
SetRedraw(true);
}
I think this solves it all
Some other genius may add the classtype checking
Greetings,
Albert 'The Mad Butcher!' van Peppen
PS. Happy birthday to me
EDIT: Some annoying things in the code snippet
EDIT2: Fixed some HTML coding problems
|
|
|
|
|
Thanks for the fix - works perfectly.
Tell me though what is the advantage of static_cast() over the normal:
CMDIChildWnd *pCF;
pCF = (CMDIChildWnd *)(FromHandlePermanent(*it));
if (pCF != NULL && pCF->IsKindOf(RUNTIME_CLASS(CMDIChildWnd))
{...}
--
The Obliterator
|
|
|
|
|
Nothing special with the static_cast()..
I'm running devstudio .NET 7.1 and it is promoted to use static_cast() or dynamic_cast()..
That's why.
Albert
|
|
|
|
|
Ok cheers.
Happy birthday BTW (now wheres that emoticon of the cake with the candles?!)
--
The Obliterator
|
|
|
|
|
BTW-
the static_cast operators parameter was obliterated by html tag chaos in the fix snippet.
Change the line:
pCF = static_cast(FromHandlePermanent(*it));
to:
pCF = static_cast<CCMDIChildWnd*>(FromHandlePermanent(*it));
(or at least this is what i assumed the author intended
Cheers,
EE
|
|
|
|
|
Indeed,
It should read like:
....
CMDIChildWnd *pCF;
pCF = static_cast<CMDIChildWnd*>(FromHandlePermanent(*it));
if (pCF != NULL) {
.....
TMB!
I've fixed it in my original posting..
|
|
|
|
|
I've been experimenting and trying to get a shorter-type tab control. Let me explain what I mean:
Say I have a view, it's fairly crowded and I need to display tabs. But I only need to display three or four tabs at a time. Now, I want these tabs on the top left of my page, and I have space there for them. Now, on the top right of the page I have some eidt lines and whatnot. So, I'm wondering how I can draw a tab control that's only a couple hundred pixels wide and then still have all that other stuff in the same position (rather than having the tab control push it down a level). The tab control goes all the way across the app, and I don't want that. I want to be able to display stuff on the same horizontal level as the tabs. I kind of want it to just overlay on the view. I've tried a bunch of stuff to get it to work, but things just don't seem to all come together. Any help would be appreciated.
btw, great work on the class. Good implementation.
|
|
|
|
|
How to deal with ampersand in file names?
I tried implementing owner draw, so I can use DT_NOPREFIX in DrawText, but the control is calculating the size of the tab without accounting for DT_NOPREFIX, and the tab size ends up too small.
I see no TCS_NOPREFIX style for tab controls, so is there another solution, other than inserting an extra '&' in the filename?
|
|
|
|
|