Usage of CScrollView in MFC application - c++

I am using CSCrollView window for our Application in which i have table drawn in View.
I have derived the CMYclass from CSCrollView, But whenevr i am scrolling the window up and down whatever i have drwan is getting erased. How i can acheive it this... i need to perform same actvity like a Word Pad is doing with images and Text. I want to keep scroll the View Vertically. Till the page ends.
Here is the code snippet:-
void CMyView::OnInitialUpdate()
{
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = 450;
sizeTotal.cy = 700;
SetScrollSizes(MM_TEXT, sizeTotal);
}
void CMyView::OnDraw(CDC* pDC)
{
for(int i = 1;i<50;++i)
{
AddRow(pDC);
TopPos = Height+TopPos;// ![Outpu Window Image][1]
nCountRow++;
}
}
it is only drawing 18 rows, but when iam scrolling down above drawn content is no more and also there is nothing coming up in scrolled area.
Is there anything more need to add?
Thanking for help
Regards,
Mukesh

Long time I have used CScrollView. Here is my hint: Try mapping modes other than MM_TEXT. Also look up other functions in CScrollView. I suggest to draw simple stuff first than some complicated rows.

Related

How to stop the bottom scrollbar from a CListCtrl from displaying?

I have a CListCtrl which is dynamically resized with the dialogue. I used a WM_SIZE message handler in the derived CListCtrl to resize the columns such that the total is the width of the control - 4, where the - 4 is to indicate the width of the border.
When I make the dialogue bigger, the control resizes correctly and I don't get the bottom scrollbar. However when I shrink the control, I sometimes get the horizontal scrollbar showing up.
void CMyListCtrl::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
ResizeLastColumn();
}
void CMyListCtrl::ResizeLastColumn()
{
LVCOLUMN column;
column.mask = LVCF_WIDTH;
LONG maxWidth = 0;
for (int i = 0; i < lastColumnIndex; ++i)
{
GetColumn(i, &column);
maxWidth += column.cx;
}
CRect wndRect;
GetWindowRect(&wndRect);
SetColumnWidth(lastColumnIndex, wndRect.Width() - maxWidth - 4);
}
It is like the WM_SIZE message is getting to the control before the control is finally resized.
This is related to How to determine if a scrollbar for a CListCtrl is displaying?. However, this question is not dealing with the right scrollbar, and is assuming that it is not being displayed.
Resizing the window generates a message to test for horizontal scroll. SetColumnWidth will also generate the same message. It depends how ListView handles this internally, but a vertical scroll could also come in and go, this will change the client area, so the code may have to make recursive calls to figure out if the scroll should be visible or not. You can see this can easily run in to problems.
Try resizing the columns in WM_WINDOWPOSCHANGED, before calling the default procedure. Use SetRedraw to stop redundant paint messages.
ON_WM_WINDOWPOSCHANGED()
...
void CMyListCtrl::OnWindowPosChanged(WINDOWPOS *wpos)
{
SetRedraw(FALSE);
ResizeLastColumn();
SetRedraw(TRUE);
CListCtrl::OnWindowPosChanged(wpos);
}
You can use GetClientRect for the client area, then you don't need to subtract the border thickness (which is not always 4).
void ResizeLastColumn()
{
int maxwidth = 0;
int index = GetHeaderCtrl()->GetItemCount() - 1;
for(int i = 0; i < index; ++i)
maxwidth += GetColumnWidth(i);
CRect rc;
GetClientRect(&rc);
SetColumnWidth(index, rc.Width() - maxwidth);
}
Also GetHeaderCtrl()->GetItemCount() returns the number of columns.
I'm facing the exact same issue, with the exact same Use Case.
To disable the horizontal scroll bar altogether, you add a message handler for WM_NCCALCSIZE
Using the Class Wizard this adds the following to your message map:
ON_WM_NCCALCSIZE()
In the implementation of this handler, you modify the style to disable the horizontal scroll bar.
void CMyListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
ModifyStyle(WS_HSCROLL, 0); // disable the horizontal scroll bar
__super::OnNcCalcSize(bCalcValidRects, lpncsp);
}
In my own implementation of ResizeLastColumn(), which is similar to yours, I subtract ::GetSystemMetrics(SM_CXVSCROLL) from the width to account for the vertical scroll bar.
I realise this reply is rather late, but hopefully it will help someone.
(Edited to remove mentions of some problems I am having because a) they are off-topic and b) because I think they stem from me not using the Doc-View architecture and things not being wired up correctly as a result. I'm going to re-think my approach.)

How to launch a window as a function of the size of the screen?

I am trying to find a solution to launch a window as a function of the size of the screen. I know there is the method resize() of the Gtk::Window but it is only pixels and not percent that's the problem.
Thank you !
You can get the screen width and height in pixels in a quick and dirty way like this:
#include <Windows.h> // Need this to get the screen resolution.
// Get the horizontal and vertical screen sizes in pixels:
static void GetDesktopResolution(int& horizontal, int& vertical) {
SetProcessDPIAware();
horizontal = GetSystemMetrics(SM_CXVIRTUALSCREEN);
vertical = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
For more advanced functionality, like dealing with multiple monitors, check out the link from the first comment on your question. The answers there are not just for OpenGL.

Qt - Adding a drawing to a Layout

I'm trying to make an application where the user can input some drawings (gestures) that will then be saved and displayed in a gallery on the top of the screen:
When the user presses "Validate", the drawing is supposed to be displayed on the scroll area on the top. However, for some reason, my code is not working the way I intended it to. It saves the drawing with no problem, but when I tell it to add it to the top, nothing happens.
Code here:
void MainWindow::galleryUpdate()
{
for (int i = 0; i < gestureTemplates.size(); i++)
{
QPolygonF scaledGesture = gestureTemplates[i].scaleToSquare(gestureTemplates[i]);
StrokeDrawer * strD = new StrokeDrawer();
QPalette Pal(palette());
Pal.setColor(QPalette::Background, Qt::white);
strD->setMinimumSize(50, 50);
strD->setAutoFillBackground(true);
strD->setPalette(Pal);
galleryList.append(strD);
topZone->addWidget(strD);
strD->setStroke(scaledGesture);
}
}
gestureTemplates is a vector of GestureTemplate (a custom class inheriting from QPolygonF) containing all the drawings. The first line inside the for simply scales the drawing to fit in a square, and returns a QPolygonF.
StrokeDrawer is the class used to display the drawing (code below). I then try to fill it with a white background, save it to galleryList which is a list of StrokeDrawer for each drawing, and then add it to the top, by using topZone->addWidget(strD), where topZone is a HBoxLayout.
I also use the setStroke method to set the drawing to the StrokeDrawer (this method also calls the update() function in the class, which calls its paintEvent, which should take care of actually drawing the QPolygonF).
Initially, I tried to do addWidget by directly using the QPolygonF but that didn't work. That's why I'm using this StrokeDrawer class (which just displays the drawing, it doesn't even allow making changes to it).
By debugging the code on QtCreator, everything works fine until the addWidget line, where nothing happens. I mean, even if the drawing is not being correctly displayed, it should at least show a small, white, 50x50 square, or am I missing something here?
Some code for StrokeDrawer:
void StrokeDrawer::setStroke(QPolygonF g)
{
gesture = g;
update();
}
void StrokeDrawer::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter pait(this);
if (!gesture.empty())
pait.drawPolyline(gesture);
}

Horizontal scroll not coming for listbox?

I am having a listbox where I set both the properties i.e, vertical and horizontal scroll to true.I am able to get vertical scroll bar but not able to get horizontal scroll bar when added a lengthy string.
Can anyone please let me know how get horizontal scroll bar for a listbox.
Adding this piece of code in OnInitDialog resolved my issue.
BOOL OnInitDialog()
{
CString str;
CSize sz;
int dx = 0;
CDC* pDC = m_listbox.GetDC();
for(int i=0; i < m_listbox.GetCount();i++)
{
m_listbox.GetText(i,str);
sz = pDC->GetTextExtent(str);
if(sz.cx > dx)
dx = sz.cx;
}
m_listbox.ReleaseDC(pDC);
if(m_listbox.GetHorizontalExtent() < dx )
{
m_listbox.SetHorizontalExtent(dx);
ASSERT(m_listbox.GetHorizontalExtent() == dx);
}
return TRUE;
}
You have to specify the horizontal scroll extent (max width in pixels). Do that by calling CListBox::SetHorizontalExtent.
In MFC, I had a listbox that was too big and extended past the right border of the window containing it. Once I made the listbox x dimension fit inside the window, the scrollbar started working properly again.
For some reason if the listbox is too big, Windows did not handle the scrollbar visibility properly as a side-effect of the sizing.

Draw a circle on top of Renderer2D

I created a renderer2D so the user can click and pick the centre of a lesion. I want to show the user where he clicked. Currently my idea is to freeze the renderer (so the slice will be the same and the zoom too) and then use the canvas to draw a circle.
Here is my code:
centerpick2D = new X.renderer2D();
centerpick2D.container = 'pick_center_segment';
centerpick2D.orientation = 'Z';
centerpick2D.init();
centerpick2D.add(volumeT1DCM);
centerpick2D.render();
centerpick2D.interactor.onMouseDown = function(){
tumorCenter=centerpick2D.xy2ijk(centerpick2D.interactor.mousePosition[0],centerpick2D.interactor.mousePosition[1]);
centerpick2D.interactor.config.MOUSEWHEEL_ENABLED = false;
centerpick2D.interactor.config.MOUSECLICKS_ENABLED = false;
$('canvas').attr('id', 'xtkCanvas');
var myCanvas = document.getElementById("xtkCanvas");
var ctx=myCanvas.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.beginPath();
ctx.arc(centerpick2D.interactor.mousePosition[0],centerpick2D.interactor.mousePosition[1],20,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
};
I have two problems:
The MOUSEWHEEL_ENABLED=false and MOUSECLICKS_ENABLED = false do not work. I tried adding a centerpick2D.init() which works but add a second canvas on top of the previous one.
My circle does not appear anywhere.
Any help would be greatly appreciated. :-D
Sorry took me a while to get this uploaded. Here's a quick overview of how I am copying the XTK canvas' contents into my own canvas and then do my own custom drawing on top of it. The actual code for my project is all over the place, so am just pasting formatted snippets here. Again there's a definite drawback in terms of performance here (due to the copying of pixels), so I think it would be better to introduce all this into the XTK Code in the first place and do all the drawing in one Canvas element.
// initialise animation loop with requestAnimationFrame
startDraw:function(){
var _this = this;
var time = new Date().getTime();
function draw() {
//update time
var now = new Date().getTime();
//only draw the frame if 25 milliseconds have passed!
if(now > (time + 25)){
// call drawing function here
drawFrame();
time = now;
}
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
};
//...
// actual drawing function, for each frame copy the pixel contents from a XTK canvas
// into custom canvas and do custom drawing on top of it, so drawing is actually at each
// frame
drawFrame:function(){
//...
// this.ctx is the context of my own custom canvas element
// I use drawImage() function to copy the pixels from this.srcCanvasA
// this.srcCanvasA is a predefined XTKCanvas
this.ctx.drawImage(this.srcCanvas, 1, 1)
// custom func to draw on top of this same canvas (ie. this.ctx) with standard
// HTML Canvas functionality, so this is where you could draw your own circle based
// on the user mouse coords
this.drawAnnotation();
//...
}
Let me know if you have any more questions. The full code is available here:
https://github.com/davidbasalla/IndividualProject