CSplitterWnd flip between horizontal and vertical splitter? - mfc

Suppose I have a splitter with 2 rows.
--------
| |
--------
| |
--------
How do I make it to this
---------
| | |
| | |
| | |
---------
switch from horizontal split to vertical split
without having to re-create the whole splitter?
Code is:
if (!m_wndSplitter.CreateStatic(this, 1, 2, WS_CHILD|WS_VISIBLE))
{
TRACE0("Failed to create splitter window\n");
return FALSE;
}
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CWnd), CSize(200, 100), NULL))
{
TRACE0("Failed to create CView1\n");
return FALSE;
}
if (!m_wndSplitter.CreateView(0, 2, RUNTIME_CLASS(CWnd), CSize(500, 100), NULL))
{
TRACE0("Failed to create CView2\n");
return FALSE;
}

Don't use CreateStatic, just use Create on the splitter. Then you have a so called dynamic splitter, see more here.
When converting the splitter from horz to vert, you have to remove the views from the splitter and attach them again afterwards. You have to do this in your document-class. I can post a method to do this if needed.
Ok, here is a method to switch views in a pane:
CView* CGMBefundDoc::SwitchToView(CView* pNewView,int row,int col)
{
CMainFrame* pMainWnd = (CMainFrame*)AfxGetMainWnd();
CSplitterWnd* pSplitter = &pMainWnd->m_wndSplitter;
CView* pOldActiveView = reinterpret_cast<CView*>(pSplitter->GetPane(row,col));
ASSERT(pOldActiveView != pNewView);
// set flag so that document will not be deleted when view is destroyed
m_bAutoDelete = FALSE;
// Dettach existing view
RemoveView(pOldActiveView);
// set flag back to default
m_bAutoDelete = TRUE;
// Set the child window ID of the active view to the ID of the corresponding
// pane. Set the child ID of the previously active view to some other ID.
::SetWindowLong(pOldActiveView->m_hWnd, GWL_ID, 0);
::SetWindowLong(pNewView->m_hWnd,GWL_ID,pSplitter->IdFromRowCol(row,col));
// Show the newly active view and hide the inactive view.
pNewView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
// Attach new view
AddView(pNewView);
// Set active
pSplitter->GetParentFrame()->SetActiveView(pNewView);
pSplitter->RecalcLayout();
return pOldActiveView;
}
I hope you get the idea, otherwise just ask.

-----------|----------|
| | |
| | |
| |----------|
| | |
| | |
-----------|----------|
2 column splitter with right side having 2 rows, one Up and one Down and another one with left side to the Up and Down ?

Related

MFC How to change link text color of CLinkCtrl?

From this post, I have set up the code by putting in the OnInitDialog event:
LITEM* pItem = new LITEM;
pItem->iLink = 0; // Url index is 0
//LIF_ITEMINDEX is required for iLink, LIF_STATE is required for modifing state
pItem->mask = LIF_ITEMINDEX | LIF_STATE;
//using LIS_DEFAULTCOLORS state
pItem->state = LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS;
pItem->stateMask = LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS;
// Send the LM_SETITEM MESSAGE with pItem
HWND m_hWnd=nil; GetDlgItem(IDC_lbstackoverflow, &m_hWnd);
And from OnCtrlColor event:
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkColor(normal);
pDC->SetDCBrushColor(RGB(255, 255, 255));
return (HBRUSH)GetStockObject(DC_BRUSH);
After the code runs, my result is:
If I click on it, now it works:
But, how I can change text color?
You may not be setting the control state correctly.
Please try the MFC way (it works for me). Add to your dialog class:
CLinkCtrl syslink;
Connect it to the resource ID of your link:
void CMFCApplication4Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SYSLINK1, syslink);
}
and in OnInitDialog add this:
syslink.SetItemState(0, LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS,
LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS);
I see red link with your code in OnCtlColor.

Getting notifications about sizeHint changes from internal widgets

Small picture to depict what the problem is:
external_widget
+--------------------------------------------------+
| |
| |
| layout_widget |
| +-------------------------------+ |
| | | |
| | [internal_layout] | |
| | | |
| | | |
| | [Some Another Widget] | |
| +-------------------------------+ |
| |
+--------------------------------------------------+
layout_widget - just QWidget with vertical layout. It contains another internal_layout and another widgets.
internal_layout - layout where the widgets will be added and deleted in future.
external_widget - just QWidget with no layout, I control the position and size of layout widget and other widgets manually.
When I add some widgets in internal_layout - it sends LayoutRequest event (as far as I know, I saw this in Qt source codes). This event is catched by parent widget and parent widget tells his layout that something is changed which forces layout to recalculate layout_widget sizeHint() etc.
Do I understand this process right?
The problem is that sizeHint() is changed, but my external_widget doesn't know anything about that. I want to get notification about layout_widget sizeHint() changes. Is it possible?
I even tried to do this:
external widget ctor:
{
layout_widget->installEventFilter(this);
}
and tried to catch them:
void ...eventFilter(QObject* obj, QEvent* event )
{
if (obj == layout_widget && event == QEvent::LayoutRequest)
{
// TODO;
}
}
and I never got into "TODO" block.
Do layout_widget send some events or notifications that something was changed inside him and it should be resized, i.e. his sizeHint() has been changed?

Alignment of qtgraphics items in qt graphics scene

I have a graphics view which contains a scene with some graphics items. How can I make those graphics items appear on the left side of the scene and not in the center ?
I have looked through many ideas but no luck.
The easiest way is to add an invisible QGraphicsRectItem as the first item.
Then add other items as children of that first item.
The center of the first item is the center of the coordination.
QGraphicsScene *scene = new QGraphicsScene(widget.graphicsView);
// ....
QGraphicsRectItem *frame = scene->addRect(-100,-100,100,100);
frame->setPen(Qt::NoPen);
// ....
// Add new items as children of frame
// Align them relative to their parent
^
|
|
-100,100 | 100,100
+-----------------------------+
| | |
| | |
| | |
| | |
| | |
| | |
| | |
---------------------------+------------------------>
| | |
| | |
| | |
| | |
| | |
| | |
| | |
+-----------------------------+
-100,100 | 100,-100
|
To make it aware to window size, override these methods:
class MainForm : public QMainWindow
{
//...
QGraphicsScene *scene; // Move it here
QGraphicsRectItem *frame; // Move it here
protected:
virtual void resizeEvent(QResizeEvent * event);
virtual bool event(QEvent * event);
virtual void resizeAction();
//...
};
void MainForm::resizeAction()
{
QRectF rect(field->rect());
widget.graphicsView->setSceneRect(rect);
widget.graphicsView->fitInView(rect, Qt::KeepAspectRatio);
}
void MainForm::resizeEvent(QResizeEvent * event)
{
resizeAction();
QMainWindow::resizeEvent(event);
}
bool MainForm::event(QEvent * event)
{
if (event->type() == QEvent::Show)
resizeAction();
return QMainWindow::event(event);
}
Scene_item.setSceneRect(x0,y0,x1,y1);

mfc remove default toolbar

I've making simple desktop game in mfc for school project, I've managed to make my app be full screen and to remove menu bar but I can't find out how to remove default built in toolbar from my app or status bar. I tried everything that came across my mind...is there some kind of get function to call from your CWnd object to retrieve toolbar and status bar?
The creation of ToolBar and StatusBar is inside the CMainFrame class. You can easily remove them if you do not need them as follows:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// *** creation of ToolBar starts, just remark/delete the whole block if you dont't want it
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
// *** creation of ToolBar ends -------------------------------------------------------
// *** creation of StatusBar starts, just remark/delete the whole block if you dont't want it
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// *** creation of StatusBar ends -------------------------------------------------------
// *** you have to remark/delete these lines too, if you removed the ToolBar above
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
// *** ToolBar extra ends -------------------------------------------------------
return 0;
}
m_pMainWnd->SetMenu(NULL); right before m_pMainWnd->ShowWindow(SW_SHOW); is called in the APPLICATION_NAME.cpp file.
Go to your resource file, double click on it , locate the toolbar, right click on it and choose delete :)

MFC toolbar on top row with right align

By default, MFC toolbar are docked on top row left align. Could anyone please tell me how to dock the MFC toolbar on top row with right align (meaning that all toolbar buttons are align to right on the top row)?
If u just want the tool bar at the right top corner, u can use the below code in CMainFrame
if (!m_wndRSToolBar.CreateEx(this, TTBSTYLE_FLAT, WS_OVERLAPPED | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMI,Rect(700,0,0,0),IDR_MAINFRAME) || !m_wndRSToolBar.LoadToolBar(IDR_MAINFRAME1))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}